diff -Nru seabios-1.7.1/coreboot-config seabios-1.7.4/coreboot-config --- seabios-1.7.1/coreboot-config 2012-08-31 16:15:57.000000000 +0000 +++ seabios-1.7.4/coreboot-config 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -# -# Automatically generated make config: don't edit -# SeaBIOS Configuration -# Tue Aug 14 21:01:57 2012 -# - -# -# General Features -# -CONFIG_COREBOOT=y -CONFIG_THREADS=y -CONFIG_THREAD_OPTIONROMS=y -CONFIG_RELOCATE_INIT=y -CONFIG_BOOTMENU=y -CONFIG_BOOTSPLASH=y -CONFIG_BOOTORDER=y -CONFIG_COREBOOT_FLASH=y -CONFIG_LZMA=y -CONFIG_FLASH_FLOPPY=y - -# -# Hardware support -# -CONFIG_ATA=y -CONFIG_ATA_DMA=y -# CONFIG_ATA_PIO32 is not set -CONFIG_AHCI=y -CONFIG_FLOPPY=y -CONFIG_PS2PORT=y -CONFIG_USB=y -CONFIG_USB_UHCI=y -CONFIG_USB_OHCI=y -CONFIG_USB_EHCI=y -CONFIG_USB_MSC=y -CONFIG_USB_UAS=y -CONFIG_USB_HUB=y -CONFIG_USB_KEYBOARD=y -CONFIG_USB_MOUSE=y -CONFIG_SERIAL=y -CONFIG_LPT=y - -# -# BIOS interfaces -# -CONFIG_DRIVES=y -CONFIG_CDROM_BOOT=y -CONFIG_CDROM_EMU=y -CONFIG_PCIBIOS=y -CONFIG_APMBIOS=y -CONFIG_PNPBIOS=y -CONFIG_OPTIONROMS=y -# CONFIG_OPTIONROMS_DEPLOYED is not set -CONFIG_PMM=y -CONFIG_BOOT=y -CONFIG_KEYBOARD=y -CONFIG_KBD_CALL_INT15_4F=y -CONFIG_MOUSE=y -CONFIG_S3_RESUME=y -CONFIG_VGAHOOKS=y -# CONFIG_DISABLE_A20 is not set - -# -# VGA ROM -# -CONFIG_NO_VGABIOS=y -# CONFIG_VGA_GEODEGX2 is not set -# CONFIG_VGA_GEODELX is not set -# CONFIG_BUILD_VGABIOS is not set - -# -# Debugging -# -CONFIG_DEBUG_LEVEL=1 -CONFIG_DEBUG_SERIAL=y -CONFIG_DEBUG_SERIAL_PORT=0x3f8 diff -Nru seabios-1.7.1/debian/changelog seabios-1.7.4/debian/changelog --- seabios-1.7.1/debian/changelog 2013-01-13 03:29:08.000000000 +0000 +++ seabios-1.7.4/debian/changelog 2015-08-26 21:28:53.000000000 +0000 @@ -1,8 +1,103 @@ -seabios (1.7.1-1~metacloud1~precise) precise; urgency=low +seabios (1.7.4-4ubuntu1) trusty-proposed; urgency=medium - * Rebuilt for Precise. + * Turn off VGA_ALLOCATE_EXTRA_STACK (LP: #1404396) - -- Rafi Khardalian Sun, 13 Jan 2013 03:28:22 +0000 + -- Serge Hallyn Wed, 26 Aug 2015 15:25:11 -0500 + +seabios (1.7.4-4) unstable; urgency=low + + * apply vgabios-attempt-to-detect-old-x86emu-and-force-a-fault.diff: + a patch from upstream to work around apparently broken x86 emulation + in some software. (Closes: #737142) + + -- Michael Tokarev Mon, 17 Feb 2014 21:35:59 +0400 + +seabios (1.7.4-3) unstable; urgency=low + + * allow seabios to be built using more recent iasl, finally, + and enable acpica-tools build-depend alternative. This has + actually been fixed long ago (the patch is in 1.7.1), even + before the version against which #707454 has been reported, + but the fix required a new iasl option which were available + only in next iasl release. But no one actually noticed this. + (Gladly Closes: #707454) + * update standards-version to 3.9.5 (no changes needed) + * replace $(PWD) with $(CURDIR) in d/rules (fixes build failure) + + -- Michael Tokarev Fri, 07 Feb 2014 00:38:29 +0400 + +seabios (1.7.4-2) unstable; urgency=low + + * actually update optionrom/multiboot.S from the commit indicated + in optionrom/README file. (Closes: #736902) + * build all variants in build/*, refresh debian/rules + * added bios-256k.bin variant for qemu > 1.7, and reduce regular + ("small) bios (for qemu <= 1.7) to be 128Kb in size again + * vgabios-Make-sure-exported-structs-use-PACKED.diff: patch from + upstream to fix interface between vgabios and real world + + -- Michael Tokarev Thu, 06 Feb 2014 23:31:04 +0400 + +seabios (1.7.4-1) unstable; urgency=low + + * new upstream release (1.7.4) + * remove all patches (upstreamed) + * acpi tables are now in $out/src/fw/ not in $out/ + + -- Michael Tokarev Thu, 16 Jan 2014 15:50:54 +0400 + +seabios (1.7.3-3) unstable; urgency=low + + * applied HDTV video modes patch from upstream + + -- Michael Tokarev Fri, 06 Dec 2013 02:50:15 +0400 + +seabios (1.7.3-2) unstable; urgency=low + + [ Michael Tokarev ] + * update to upstream 1.7.3.2 bugfix release + * Multi-Arch: foreign (vs allowed) (Closes: #728475) + * move optionrom/*.bin to the main directory (with compat symlinks) + * update optionrom files to ones from qemu-1.7 + * simplify debian/optionrom/Makefile + + -- Michael Tokarev Sun, 24 Nov 2013 00:40:53 +0400 + +seabios (1.7.3-1) unstable; urgency=low + + * new upstream release (1.7.3) + * Multi-Arch: allowed + + -- Michael Tokarev Mon, 08 Jul 2013 21:34:44 +0400 + +seabios (1.7.2-3) unstable; urgency=low + + * update to the next upstream pointpoint-release (1.7.2.2) + + -- Michael Tokarev Tue, 28 May 2013 10:54:39 +0400 + +seabios (1.7.2-2) unstable; urgency=low + + * bump Standards-Version to 3.9.4 (no changes needed) + * add a versioned dependency on iasl (<< 20130214), see #707454 + * add upstream 1.7.2.1 (as a patch since upstream didn't release source) + (Closes: #707645) + + -- Michael Tokarev Mon, 13 May 2013 19:45:38 +0400 + +seabios (1.7.2-1) unstable; urgency=low + + * new upstream release: + - Support for ICH9 host chipset ("q35") on emulators + - Support for booting from LSI MegaRAID SAS controllers + - Support for using the ACPI PM timer on emulators + - Improved Geode VGA BIOS support. + - Several bug fixes + * build main bios after all vgabioses + * ship acpi-dsdt.aml and q35-acpi-dsdt.aml (*dsdt.aml) too + (needed by new qemu) + + -- Michael Tokarev Sat, 19 Jan 2013 14:48:28 +0400 seabios (1.7.1-1) unstable; urgency=low diff -Nru seabios-1.7.1/debian/control seabios-1.7.4/debian/control --- seabios-1.7.1/debian/control 2012-12-29 15:46:40.000000000 +0000 +++ seabios-1.7.4/debian/control 2015-08-26 20:25:59.000000000 +0000 @@ -1,17 +1,21 @@ Source: seabios Section: misc Priority: extra -Maintainer: Debian QEMU Team -Uploaders: Aurelien Jarno , Riku Voipio , Vagrant Cascadian , +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian QEMU Team +Uploaders: Aurelien Jarno , + Riku Voipio , + Vagrant Cascadian , Michael Tokarev -Build-Depends: debhelper (>= 7), python, iasl -Standards-Version: 3.9.3 +Build-Depends: debhelper (>= 7), python, acpica-tools | iasl +Standards-Version: 3.9.5 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-qemu/seabios.git Vcs-Git: git://anonscm.debian.org/pkg-qemu/seabios.git Homepage: http://www.seabios.org Package: seabios Architecture: all +Multi-Arch: foreign Depends: ${misc:Depends} Breaks: qemu-system (<< 0.14.0), qemu-kvm (<< 0.14.0) Description: Legacy BIOS implementation diff -Nru seabios-1.7.1/debian/install seabios-1.7.4/debian/install --- seabios-1.7.1/debian/install 2012-09-11 13:09:04.000000000 +0000 +++ seabios-1.7.4/debian/install 2014-02-06 19:33:23.000000000 +0000 @@ -1,3 +1,3 @@ -bios.bin usr/share/seabios -vgabios-*.bin usr/share/seabios -debian/optionrom/*.bin usr/share/seabios/optionrom +build/*.bin usr/share/seabios +build/bios/src/fw/*dsdt.aml usr/share/seabios +debian/optionrom/*.bin usr/share/seabios diff -Nru seabios-1.7.1/debian/links seabios-1.7.4/debian/links --- seabios-1.7.1/debian/links 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/debian/links 2014-02-04 12:38:52.000000000 +0000 @@ -0,0 +1,6 @@ +# compatibility symlinks +usr/share/seabios/extboot.bin usr/share/seabios/optionrom/extboot.bin +usr/share/seabios/kvmvapic.bin usr/share/seabios/optionrom/kvmvapic.bin +usr/share/seabios/linuxboot.bin usr/share/seabios/optionrom/linuxboot.bin +usr/share/seabios/multiboot.bin usr/share/seabios/optionrom/multiboot.bin +usr/share/seabios/vapic.bin usr/share/seabios/optionrom/vapic.bin diff -Nru seabios-1.7.1/debian/optionrom/fw_cfg.h seabios-1.7.4/debian/optionrom/fw_cfg.h --- seabios-1.7.1/debian/optionrom/fw_cfg.h 2012-12-29 15:46:16.000000000 +0000 +++ seabios-1.7.4/debian/optionrom/fw_cfg.h 2014-02-04 12:38:52.000000000 +0000 @@ -38,12 +38,14 @@ #define FW_CFG_INVALID 0xffff +#define FW_CFG_MAX_FILE_PATH 56 + #ifndef NO_QEMU_PROTOS typedef struct FWCfgFile { uint32_t size; /* file size */ uint16_t select; /* write this to 0x510 to read it */ uint16_t reserved; - char name[56]; + char name[FW_CFG_MAX_FILE_PATH]; } FWCfgFile; typedef struct FWCfgFiles { @@ -52,19 +54,25 @@ } FWCfgFiles; typedef void (*FWCfgCallback)(void *opaque, uint8_t *data); +typedef void (*FWCfgReadCallback)(void *opaque, uint32_t offset); -typedef struct FWCfgState FWCfgState; -int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len); -int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value); -int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value); -int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value); -int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback, - void *callback_opaque, uint8_t *data, size_t len); -int fw_cfg_add_file(FWCfgState *s, const char *filename, uint8_t *data, - uint32_t len); +void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len); +void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value); +void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value); +void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value); +void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value); +void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback, + void *callback_opaque, void *data, size_t len); +void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, + size_t len); +void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, + FWCfgReadCallback callback, void *callback_opaque, + void *data, size_t len); FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, hwaddr crl_addr, hwaddr data_addr); +FWCfgState *fw_cfg_find(void); + #endif /* NO_QEMU_PROTOS */ #endif diff -Nru seabios-1.7.1/debian/optionrom/Makefile seabios-1.7.4/debian/optionrom/Makefile --- seabios-1.7.1/debian/optionrom/Makefile 2012-09-11 13:09:04.000000000 +0000 +++ seabios-1.7.4/debian/optionrom/Makefile 2014-02-04 12:38:52.000000000 +0000 @@ -1,11 +1,11 @@ -all: build-all +LD = ld +OBJCOPY = objcopy +CC = cc -CFLAGS := -Wall -Wstrict-prototypes -Werror -fomit-frame-pointer -fno-builtin -fno-stack-protector -CFLAGS += -I$(SRC_PATH) -LD=ld -OBJCOPY=objcopy +all: $(subst .S,.bin,$(wildcard *.S)) -build-all: $(subst .S,.bin,$(wildcard *.S)) +%.o: %.S + $(CC) -c -o $@ $< %.img: %.o $(LD) -Ttext 0 -e _start -s -o $@ $< @@ -19,4 +19,4 @@ clean: rm -f *.o *.d *.raw *.img *.bin *~ -.PHONY : all clean build-all +.PHONY: all clean diff -Nru seabios-1.7.1/debian/optionrom/multiboot.S seabios-1.7.4/debian/optionrom/multiboot.S --- seabios-1.7.1/debian/optionrom/multiboot.S 2012-12-29 15:46:16.000000000 +0000 +++ seabios-1.7.4/debian/optionrom/multiboot.S 2014-02-06 19:33:23.000000000 +0000 @@ -89,17 +89,14 @@ /* Initialize multiboot mmap structs using int 0x15(e820) */ xor %ebx, %ebx - /* mmap start after first size */ - movl $4, %edi + /* Start storing mmap data at %es:0 */ + xor %edi, %edi mmap_loop: + /* The multiboot entry size has offset -4, so leave some space */ + add $4, %di /* entry size (mmap struct) & max buffer size (int15) */ movl $20, %ecx - /* store entry size */ - /* old as(1) doesn't like this insn so emit the bytes instead: - movl %ecx, %es:-4(%edi) - */ - .dc.b 0x26,0x67,0x66,0x89,0x4f,0xfc /* e820 */ movl $0x0000e820, %eax /* 'SMAP' magic */ @@ -107,23 +104,65 @@ int $0x15 mmap_check_entry: - /* last entry? then we're done */ + /* Error or last entry already done? */ jb mmap_done - and %bx, %bx - jz mmap_done - /* valid entry, so let's loop on */ mmap_store_entry: - /* %ax = entry_number * 24 */ - mov $24, %ax - mul %bx - mov %ax, %di + /* store entry size */ + /* old as(1) doesn't like this insn so emit the bytes instead: + movl %ecx, %es:-4(%edi) + */ + .dc.b 0x26,0x67,0x66,0x89,0x4f,0xfc + + /* %edi += entry_size, store as mbs_mmap_length */ + add %ecx, %edi movw %di, %fs:0x2c - /* %di = 4 + (entry_number * 24) */ - add $4, %di - jmp mmap_loop + + /* Continuation value 0 means last entry */ + test %ebx, %ebx + jnz mmap_loop mmap_done: + /* Calculate upper_mem field: The amount of memory between 1 MB and + the first upper memory hole. Get it from the mmap. */ + xor %di, %di + mov $0x100000, %edx +upper_mem_entry: + cmp %fs:0x2c, %di + je upper_mem_done + add $4, %di + + /* Skip if type != 1 */ + cmpl $1, %es:16(%di) + jne upper_mem_next + + /* Skip if > 4 GB */ + movl %es:4(%di), %eax + test %eax, %eax + jnz upper_mem_next + + /* Check for contiguous extension (base <= %edx < base + length) */ + movl %es:(%di), %eax + cmp %eax, %edx + jb upper_mem_next + addl %es:8(%di), %eax + cmp %eax, %edx + jae upper_mem_next + + /* If so, update %edx, and restart the search (mmap isn't ordered) */ + mov %eax, %edx + xor %di, %di + jmp upper_mem_entry + +upper_mem_next: + addl %es:-4(%di), %edi + jmp upper_mem_entry + +upper_mem_done: + sub $0x100000, %edx + shr $10, %edx + mov %edx, %fs:0x8 + real_to_prot: /* Load the GDT before going into protected mode */ lgdt: diff -Nru seabios-1.7.1/debian/optionrom/README seabios-1.7.4/debian/optionrom/README --- seabios-1.7.1/debian/optionrom/README 2012-12-29 15:46:16.000000000 +0000 +++ seabios-1.7.4/debian/optionrom/README 2014-02-04 12:38:52.000000000 +0000 @@ -12,14 +12,14 @@ The files taken from qemu: -hw/fw_cfg.h a8170e5e97ad17ca169c64ba87ae2f53850dab4c Tue Oct 23 12:30:10 2012 +0200 +include/hw/nvram/fw_cfg.h 35c12e60c840bc4840cbbe3f6ca514a53b2e36bc Wed Jul 24 18:56:05 2013 +0300 pc-bios/optionrom/optionrom.h 209ca750b9e1854fa8f63fae16aef15becb1cdea Feb 17 18:31:21 2012 +0100 (this one inludes a trivial change for #include'ing fw_cfg.h) scripts/signrom.py 0d6b9cc7420dd2d531b48508f0d4083d1c6a632a Jan 27 19:44:53 2012 +0100 pc-bios/optionrom/extboot.S 211721f31c62cc889369da79d75c38f7297b6465 Feb 18 17:13:30 2010 +0100 (removed upstream) pc-bios/optionrom/linuxboot.S 75b9f69057b166876a0c33d5fd86aa59ccfd3812 Jan 31 15:11:01 2011 +0200 -pc-bios/optionrom/multiboot.S c6e052f0809b56a657b2afcd728e07ffddb28f06 Thu Nov 29 18:11:50 2012 +0100 +pc-bios/optionrom/multiboot.S 26a8ec07616df8eeb7ae5e76a4eade6809c426e3 Sun Jun 23 22:07:45 2013 +0200 pc-bios/optionrom/kvmvapic.S 501981126d0aaaa72f720edeee892b830cbe3e55 Feb 17 18:31:22 2012 +0100 and Makefile to build it all. diff -Nru seabios-1.7.1/debian/patches/series seabios-1.7.4/debian/patches/series --- seabios-1.7.1/debian/patches/series 2012-12-29 15:40:28.000000000 +0000 +++ seabios-1.7.4/debian/patches/series 2015-08-26 20:26:48.000000000 +0000 @@ -1 +1,3 @@ -# nothing is in there +vgabios-Make-sure-exported-structs-use-PACKED.diff +vgabios-attempt-to-detect-old-x86emu-and-force-a-fault.diff +turn-vga-allocate-extra-stack-off diff -Nru seabios-1.7.1/debian/patches/turn-vga-allocate-extra-stack-off seabios-1.7.4/debian/patches/turn-vga-allocate-extra-stack-off --- seabios-1.7.1/debian/patches/turn-vga-allocate-extra-stack-off 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/debian/patches/turn-vga-allocate-extra-stack-off 2015-08-26 20:27:48.000000000 +0000 @@ -0,0 +1,13 @@ +Index: seabios-1.7.4/vgasrc/Kconfig +=================================================================== +--- seabios-1.7.4.orig/vgasrc/Kconfig ++++ seabios-1.7.4/vgasrc/Kconfig +@@ -71,7 +71,7 @@ menu "VGA ROM" + config VGA_ALLOCATE_EXTRA_STACK + depends on BUILD_VGABIOS + bool "Allocate an internal stack for 16bit interrupt entry point" +- default y ++ default n + help + Attempt to allocate (via BIOS PMM call) an internal stack + for the legacy 16bit 0x10 interrupt entry point. This diff -Nru seabios-1.7.1/debian/patches/vgabios-attempt-to-detect-old-x86emu-and-force-a-fault.diff seabios-1.7.4/debian/patches/vgabios-attempt-to-detect-old-x86emu-and-force-a-fault.diff --- seabios-1.7.1/debian/patches/vgabios-attempt-to-detect-old-x86emu-and-force-a-fault.diff 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/debian/patches/vgabios-attempt-to-detect-old-x86emu-and-force-a-fault.diff 2014-02-17 17:28:48.000000000 +0000 @@ -0,0 +1,66 @@ +From: Kevin O'Connor +Date: Wed Feb 5 22:47:29 2014 -0500 +Subject: vgabios: Attempt to detect old x86emu and force a fault. +Upstream-Commit: 8032b8a0fec550de5cb2f7d37aa031cebc2200c3 +Bug-Debian: http://bugs.debian.org/737142 + +Check for cases where the leal instruction does not work. This +instruction is known to not be emulated properly on old versions of +x86emu. If a broken version of x86emu is found, force a fault that +x86emu will easily detect. This should help prevent soft failures +when running old software. + +Signed-off-by: Kevin O'Connor + +diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S +index 9854448..6e31c4e 100644 +--- a/vgasrc/vgaentry.S ++++ b/vgasrc/vgaentry.S +@@ -45,9 +45,26 @@ _rom_header_signature: + * Entry points + ****************************************************************/ + +- // This macro is the same as ENTRY_ARG except the "calll" +- // instruction is avoided to work around known issues in the +- // emulation of some versions of x86emu. ++ // Force a fault if found to be running on broken x86emu versions. ++ DECLFUNC x86emu_fault ++x86emu_fault: ++1: hlt ++ jmp 1b ++ ++ // This macro implements a call while avoiding instructions ++ // that old versions of x86emu have problems with. ++ .macro VGA_CALLL cfunc ++ // Make sure leal instruction works. ++ movl $0x8000, %ecx ++ leal (%ecx, %ecx, 1), %ecx ++ cmpl $0x10000, %ecx ++ jne x86emu_fault ++ // Use callw instead of calll ++ push %ax ++ callw \cfunc ++ .endm ++ ++ // This macro is the same as ENTRY_ARG except VGA_CALLL is used. + .macro ENTRY_ARG_VGA cfunc + cli + cld +@@ -57,7 +74,7 @@ _rom_header_signature: + movl %esp, %ebx // Backup %esp, then zero high bits + movzwl %sp, %esp + movl %esp, %eax // First arg is pointer to struct bregs +- pushw %ax ; callw \cfunc ++ VGA_CALLL \cfunc + movl %ebx, %esp // Restore %esp (including high bits) + POPBREGS + .endm +@@ -103,7 +120,7 @@ entry_10_extrastack: + movw %ds, %dx // Setup %ss/%esp and call function + movw %dx, %ss + movl %eax, %esp +- pushw %ax ; callw handle_10 ++ VGA_CALLL handle_10 + + movl %esp, %eax // Restore registers and return + movw BREGS_size+4(%eax), %ss diff -Nru seabios-1.7.1/debian/patches/vgabios-Make-sure-exported-structs-use-PACKED.diff seabios-1.7.4/debian/patches/vgabios-Make-sure-exported-structs-use-PACKED.diff --- seabios-1.7.1/debian/patches/vgabios-Make-sure-exported-structs-use-PACKED.diff 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/debian/patches/vgabios-Make-sure-exported-structs-use-PACKED.diff 2014-02-06 19:33:23.000000000 +0000 @@ -0,0 +1,66 @@ +Date: Wed, 5 Feb 2014 18:59:20 -0500 +From: Kevin O'Connor +To: seabios@seabios.org +Message-ID: <0e216572159ad2649be6d3d68352c4524ec70c6c.1391644710.git.kevin@koconnor.net> +Subject: [SeaBIOS] [PATCH] vgabios: Make sure exported structs use PACKED. + +Commit ca668640 introduced structs for data returned from the +handle_101b and handle_101c calls. However, the structs were not +declared as packed and that caused incorrect behavior for +handle_101b. This was seen to break some old DOS programs (Win3 setup +and DISPLAY.SYS). This patch adds in the necessary PACKED declaration +to the structs. + +The 'struct saveBDAstate' remains un-packed, as it does not appear +that its contents are documented. (And, its format already differs +from what was in the previous "lgpl vgabios".) + +Signed-off-by: Kevin O'Connor +--- + vgasrc/stdvga.c | 4 ++-- + vgasrc/vgabios.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c +index e0661f1..c94ec06 100644 +--- a/vgasrc/stdvga.c ++++ b/vgasrc/stdvga.c +@@ -338,7 +338,7 @@ struct saveVideoHardware { + u8 grdc_regs[9]; + u16 crtc_addr; + u8 plane_latch[4]; +-}; ++} PACKED; + + static void + stdvga_save_hw_state(u16 seg, struct saveVideoHardware *info) +@@ -412,7 +412,7 @@ struct saveDACcolors { + u8 pelmask; + u8 dac[768]; + u8 color_select; +-}; ++} PACKED; + + static void + stdvga_save_dac_state(u16 seg, struct saveDACcolors *info) +diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c +index 57f1c1f..f70b2b6 100644 +--- a/vgasrc/vgabios.c ++++ b/vgasrc/vgabios.c +@@ -1114,7 +1114,7 @@ struct funcInfo { + u8 save_flags; + u8 disp_info; + u8 reserved_34[12]; +-}; ++} PACKED; + + static void + handle_101b(struct bregs *regs) +-- +1.8.5.3 + + +_______________________________________________ +SeaBIOS mailing list +SeaBIOS@seabios.org +http://www.seabios.org/mailman/listinfo/seabios diff -Nru seabios-1.7.1/debian/rules seabios-1.7.4/debian/rules --- seabios-1.7.1/debian/rules 2012-12-29 15:40:28.000000000 +0000 +++ seabios-1.7.4/debian/rules 2014-02-17 17:26:22.000000000 +0000 @@ -11,54 +11,70 @@ DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) VGABIOSES = cirrus stdvga vmware qxl isavga -VGABIOS_TARGETS = $(addprefix vgabios-, $(addsuffix .bin, $(VGABIOSES))) -BUILD_TARGETS = bios.bin $(VGABIOS_TARGETS) build-optionrom-stamp +VGABIOS_TARGETS = $(addprefix build/vgabios-, $(addsuffix .bin, $(VGABIOSES))) +BUILD_TARGETS = build/bios.bin build/bios-256k.bin \ + $(VGABIOS_TARGETS) build/optionrom-stamp build build-arch build-indep: $(BUILD_TARGETS) -bios.bin: - dh_testdir - $(MAKE) out/bios.bin - mv out/bios.bin bios.bin +# common rule to build any bios. +# $1: build target: bios or vgabios, builds $(OUT)/$1 +# $2: config options to put into .config without CONFIG_ prefix +# $@: where to put output; build dir will be $(basename $@) +define build-bios +set -e; d=$(basename $@); \ +if [ ! -e $$d/.config.old ]; then \ + rm -rf $$d; mkdir -p $$d; \ + for x in $2; do \ + case $$x in \ + (*=n) echo "# CONFIG_$${x%=*} is not set";; \ + (*) echo CONFIG_$$x;; \ + esac; \ + done > $$d/.config; \ + $(MAKE) KCONFIG_CONFIG=$(CURDIR)/$$d/.config OUT=$$d/ oldnoconfig; \ +fi; \ +$(MAKE) KCONFIG_CONFIG=$(CURDIR)/$$d/.config OUT=$$d/ $$d/$1.bin; \ +rm -f $@; ln $$d/$1.bin $@ +endef + +build/bios.bin: +# A (somewhat) stripped-down version of bios, to fit in 128Kb +# If the bios is larger, we have issues with guest migration, and older xen +# (before 4.3.1) does not work as it only supports bios of size 128Kb. +# Upstream qemu builds smaller bios without XCHI (usb3) and XEN, +# but we need XEN support so we disable usb3 (implenented since 1.7.4) +# and another recent but rather small feature, pvscsi. We're very close +# to the available size, and the size also depends on compiler and options. +# Qemu past 1.7 version will load bios-256k.bin by default (for new machine +# types), but the size is still a concern when specifying older machine +# types (1.7 and before). + $(call build-bios,bios,QEMU=y ROM_SIZE=128 USB_XHCI=n PVSCSI=n) +build/bios-256k.bin: + $(call build-bios,bios,QEMU=y ROM_SIZE=256) + +build/vgabios-cirrus.bin: + $(call build-bios,vgabios,BUILD_VGABIOS=y VGA_CIRRUS=y VGA_PCI=y) +build/vgabios-stdvga.bin: + $(call build-bios,vgabios,BUILD_VGABIOS=y VGA_BOCHS=y VGA_PCI=y) +build/vgabios-vmware.bin: + $(call build-bios,vgabios,BUILD_VGABIOS=y VGA_BOCHS=y VGA_PCI=y \ + OVERRIDE_PCI_ID=y VGA_VID=0x15ad VGA_DID=0x0405) +build/vgabios-qxl.bin: + $(call build-bios,vgabios,BUILD_VGABIOS=y VGA_BOCHS=y VGA_PCI=y \ + OVERRIDE_PCI_ID=y VGA_VID=0x1b36 VGA_DID=0x0100) +build/vgabios-isavga.bin: + $(call build-bios,vgabios,BUILD_VGABIOS=y VGA_BOCHS=y VGA_PCI=n) -build-optionrom-stamp: +build/optionrom-stamp: $(MAKE) -C debian/optionrom/ chmod -x debian/optionrom/*.bin ln -s kvmvapic.bin debian/optionrom/vapic.bin - touch $@ - -define build-vgabios -rm -rf out/ -rm -f .config -for x in BUILD_VGABIOS=y $1; do echo CONFIG_$$x; done > .config -$(MAKE) oldnoconfig -$(MAKE) out/vgabios.bin -mv out/vgabios.bin $@ -endef - -# Since we use the same .config (and make oldconfig), -# we can't make all vgabios-*.bin in parallel with each other. -# Ensure they're made one after another by specifying -# that next depends on previous, ie, making a dependency chain, -# starting with main bios.bin - -vgabios-cirrus.bin: bios.bin - $(call build-vgabios,VGA_CIRRUS=y VGA_PCI=y) -vgabios-stdvga.bin: vgabios-cirrus.bin - $(call build-vgabios,VGA_BOCHS=y VGA_PCI=y) -vgabios-vmware.bin: vgabios-stdvga.bin - $(call build-vgabios,VGA_BOCHS=y VGA_PCI=y OVERRIDE_PCI_ID=y VGA_VID=0x15ad VGA_DID=0x0405) -vgabios-qxl.bin: vgabios-vmware.bin - $(call build-vgabios,VGA_BOCHS=y VGA_PCI=y OVERRIDE_PCI_ID=y VGA_VID=0x1b36 VGA_DID=0x0100) -vgabios-isavga.bin: vgabios-qxl.bin - $(call build-vgabios,VGA_BOCHS=y VGA_PCI=n) + mkdir -p $(dir $@) && touch $@ clean: dh_testdir - rm -f $(BUILD_TARGETS) - rm -f .config .config.old - rm -rf out/ - rm -f tools/*pyc + rm -rf build/ + rm -f scripts/*pyc $(MAKE) -C debian/optionrom/ clean dh_clean diff -Nru seabios-1.7.1/Makefile seabios-1.7.4/Makefile --- seabios-1.7.1/Makefile 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/Makefile 2013-12-23 15:40:05.000000000 +0000 @@ -7,25 +7,51 @@ # Output directory OUT=out/ +# Common command definitions +export HOSTCC := $(CC) +export CONFIG_SHELL := sh +export KCONFIG_AUTOHEADER := autoconf.h +export KCONFIG_CONFIG := $(CURDIR)/.config +CROSS_PREFIX= +ifneq ($(CROSS_PREFIX),) +CC=$(CROSS_PREFIX)gcc +endif +AS=$(CROSS_PREFIX)as +LD=$(CROSS_PREFIX)ld +OBJCOPY=$(CROSS_PREFIX)objcopy +OBJDUMP=$(CROSS_PREFIX)objdump +STRIP=$(CROSS_PREFIX)strip +PYTHON=python +CPP=cpp +IASL:=iasl + # Source files -SRCBOTH=misc.c stacks.c pmm.c output.c util.c block.c floppy.c ata.c mouse.c \ - kbd.c pci.c serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \ - pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \ - usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \ - virtio-ring.c virtio-pci.c virtio-blk.c virtio-scsi.c apm.c ahci.c \ - usb-uas.c lsi-scsi.c esp-scsi.c +SRCBOTH=misc.c stacks.c output.c string.c x86.c block.c cdrom.c mouse.c kbd.c \ + serial.c clock.c resume.c pnpbios.c vgahooks.c pcibios.c apm.c \ + fw/smp.c \ + hw/pci.c hw/timer.c hw/rtc.c hw/dma.c hw/pic.c hw/ps2port.c hw/serialio.c \ + hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c hw/usb-xhci.c \ + hw/usb-hid.c hw/usb-msc.c hw/usb-uas.c \ + hw/blockcmd.c hw/floppy.c hw/ata.c hw/ramdisk.c \ + hw/virtio-ring.c hw/virtio-pci.c hw/virtio-blk.c hw/virtio-scsi.c \ + hw/lsi-scsi.c hw/esp-scsi.c hw/megasas.c hw/pvscsi.c SRC16=$(SRCBOTH) system.c disk.c font.c -SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \ - acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \ - lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c \ - biostables.c xen.c bmp.c romfile.c -SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c +SRC32FLAT=$(SRCBOTH) post.c memmap.c malloc.c pmm.c romfile.c optionroms.c \ + boot.c bootsplash.c jpeg.c bmp.c \ + hw/ahci.c hw/usb-hub.c \ + fw/coreboot.c fw/lzmadecode.c fw/csm.c fw/biostables.c \ + fw/paravirt.c fw/shadow.c fw/pciinit.c fw/smm.c fw/mtrr.c fw/xen.c \ + fw/acpi.c fw/mptable.c fw/pirtable.c fw/smbios.c fw/romfile_loader.c +SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c +DIRS=src src/hw src/fw vgasrc # Default compiler flags cc-option=$(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`" \ ; then echo "$(2)"; else echo "$(3)"; fi ;) -COMMONCFLAGS = -I$(OUT) -Os -MD -g \ +CPPFLAGS = -P -MD -MT $@ + +COMMONCFLAGS := -I$(OUT) -Isrc -Os -MD -g \ -Wall -Wno-strict-aliasing -Wold-style-definition \ $(call cc-option,$(CC),-Wtype-limits,) \ -m32 -march=i386 -mregparm=3 -mpreferred-stack-boundary=2 \ @@ -36,14 +62,14 @@ COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,) -CFLAGS32FLAT = $(COMMONCFLAGS) -DMODE16=0 -DMODESEGMENT=0 -fomit-frame-pointer -CFLAGSSEG = $(COMMONCFLAGS) -DMODESEGMENT=1 -fno-defer-pop \ +CFLAGS32FLAT := $(COMMONCFLAGS) -DMODE16=0 -DMODESEGMENT=0 -fomit-frame-pointer +CFLAGSSEG := $(COMMONCFLAGS) -DMODESEGMENT=1 -fno-defer-pop \ $(call cc-option,$(CC),-fno-jump-tables,-DMANUAL_NO_JUMP_TABLE) \ $(call cc-option,$(CC),-fno-tree-switch-conversion,) -CFLAGS32SEG = $(CFLAGSSEG) -DMODE16=0 -fomit-frame-pointer -CFLAGS16INC = $(CFLAGSSEG) -DMODE16=1 -Wa,src/code16gcc.s \ +CFLAGS32SEG := $(CFLAGSSEG) -DMODE16=0 -fomit-frame-pointer +CFLAGS16INC := $(CFLAGSSEG) -DMODE16=1 -Wa,src/code16gcc.s \ $(call cc-option,$(CC),--param large-stack-frame=4,-fno-inline) -CFLAGS16 = $(CFLAGS16INC) -fomit-frame-pointer +CFLAGS16 := $(CFLAGS16INC) -fomit-frame-pointer # Run with "make V=1" to see the actual compile commands ifdef V @@ -53,69 +79,41 @@ MAKEFLAGS += --no-print-directory endif -# Common command definitions -export HOSTCC := $(CC) -export CONFIG_SHELL := sh -export KCONFIG_AUTOHEADER := autoconf.h -export KCONFIG_CONFIG := $(CURDIR)/.config -AS=as -OBJCOPY=objcopy -OBJDUMP=objdump -STRIP=strip -PYTHON=python -IASL:=iasl - # Default targets -include $(KCONFIG_CONFIG) -target-y = $(OUT) $(OUT)bios.bin +target-y := +target-$(CONFIG_QEMU) += $(OUT)bios.bin +target-$(CONFIG_CSM) += $(OUT)Csm16.bin +target-$(CONFIG_COREBOOT) += $(OUT)bios.bin.elf target-$(CONFIG_BUILD_VGABIOS) += $(OUT)vgabios.bin all: $(target-y) # Make definitions .PHONY : all clean distclean FORCE - -vpath %.c src vgasrc -vpath %.S src vgasrc +.DELETE_ON_ERROR: ################ Common build rules # Verify the build environment works. -TESTGCC:=$(shell CC="$(CC)" LD="$(LD)" IASL="$(IASL)" tools/test-build.sh) +TESTGCC:=$(shell OUT="$(OUT)" CC="$(CC)" LD="$(LD)" IASL="$(IASL)" scripts/test-build.sh) ifeq "$(TESTGCC)" "-1" $(error "Please upgrade the build environment") endif -ifndef COMPSTRAT -COMPSTRAT=$(TESTGCC) +ifeq "$(TESTGCC)" "0" +# Use -fwhole-program +CFLAGSWHOLE=-fwhole-program -DWHOLE_PROGRAM endif -# Do a whole file compile - three methods are supported. -ifeq "$(COMPSTRAT)" "1" -# First method - use -fwhole-program without -combine. -define whole-compile -@echo " Compiling whole program $3" -$(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c -$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -c $3.tmp.c -o $3 -endef -else -ifeq "$(COMPSTRAT)" "2" -# Second menthod - don't use -fwhole-program at all. -define whole-compile -@echo " Compiling whole program $3" -$(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c -$(Q)$(CC) $1 -c $3.tmp.c -o $3 -endef -else -# Third (and preferred) method - use -fwhole-program with -combine +# Do a whole file compile by textually including all C code. define whole-compile @echo " Compiling whole program $3" -$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -combine -c $2 -o $3 +$(Q)printf '$(foreach i,$2,#include "$(CURDIR)/$i"\n)' > $3.tmp.c +$(Q)$(CC) $1 $(CFLAGSWHOLE) -c $3.tmp.c -o $3 endef -endif -endif %.strip.o: %.o @echo " Stripping $@" @@ -125,41 +123,45 @@ @echo " Compiling to assembler $@" $(Q)$(CC) $(CFLAGS16) -S -c $< -o $@ +$(OUT)%.o: %.c $(OUT)autoconf.h + @echo " Compile checking $@" + $(Q)$(CC) $(CFLAGS32FLAT) -c $< -o $@ + $(OUT)%.lds: %.lds.S @echo " Precompiling $@" - $(Q)$(CPP) -P -D__ASSEMBLY__ $< -o $@ + $(Q)$(CPP) $(CPPFLAGS) -D__ASSEMBLY__ $< -o $@ ################ Main BIOS build rules $(OUT)asm-offsets.s: $(OUT)autoconf.h -$(OUT)asm-offsets.h: $(OUT)asm-offsets.s +$(OUT)asm-offsets.h: $(OUT)src/asm-offsets.s @echo " Generating offset file $@" - $(Q)./tools/gen-offsets.sh $< $@ + $(Q)./scripts/gen-offsets.sh $< $@ -$(OUT)ccode16.o: $(OUT)autoconf.h ; $(call whole-compile, $(CFLAGS16), $(addprefix src/, $(SRC16)),$@) +$(OUT)ccode16.o: $(OUT)autoconf.h $(patsubst %.c, $(OUT)src/%.o,$(SRC16)) ; $(call whole-compile, $(CFLAGS16), $(addprefix src/, $(SRC16)),$@) -$(OUT)code32seg.o: $(OUT)autoconf.h ; $(call whole-compile, $(CFLAGS32SEG), $(addprefix src/, $(SRC32SEG)),$@) +$(OUT)code32seg.o: $(OUT)autoconf.h $(patsubst %.c, $(OUT)src/%.o,$(SRC32SEG)) ; $(call whole-compile, $(CFLAGS32SEG), $(addprefix src/, $(SRC32SEG)),$@) -$(OUT)ccode32flat.o: $(OUT)autoconf.h ; $(call whole-compile, $(CFLAGS32FLAT), $(addprefix src/, $(SRC32FLAT)),$@) +$(OUT)ccode32flat.o: $(OUT)autoconf.h $(patsubst %.c, $(OUT)src/%.o,$(SRC32FLAT)) ; $(call whole-compile, $(CFLAGS32FLAT), $(addprefix src/, $(SRC32FLAT)),$@) -$(OUT)romlayout.o: romlayout.S $(OUT)asm-offsets.h +$(OUT)romlayout.o: src/romlayout.S $(OUT)asm-offsets.h @echo " Compiling (16bit) $@" $(Q)$(CC) $(CFLAGS16) -c -D__ASSEMBLY__ $< -o $@ -$(OUT)romlayout16.lds: $(OUT)ccode32flat.o $(OUT)code32seg.o $(OUT)ccode16.o $(OUT)romlayout.o tools/layoutrom.py +$(OUT)romlayout16.lds: $(OUT)ccode32flat.o $(OUT)code32seg.o $(OUT)ccode16.o $(OUT)romlayout.o scripts/layoutrom.py scripts/buildversion.sh @echo " Building ld scripts" - $(Q)./tools/buildversion.sh $(OUT)version.c + $(Q)./scripts/buildversion.sh $(OUT)version.c $(Q)$(CC) $(CFLAGS32FLAT) -c $(OUT)version.c -o $(OUT)version.o $(Q)$(LD) -melf_i386 -r $(OUT)ccode32flat.o $(OUT)version.o -o $(OUT)code32flat.o $(Q)$(LD) -melf_i386 -r $(OUT)ccode16.o $(OUT)romlayout.o -o $(OUT)code16.o $(Q)$(OBJDUMP) -thr $(OUT)code32flat.o > $(OUT)code32flat.o.objdump $(Q)$(OBJDUMP) -thr $(OUT)code32seg.o > $(OUT)code32seg.o.objdump $(Q)$(OBJDUMP) -thr $(OUT)code16.o > $(OUT)code16.o.objdump - $(Q)$(PYTHON) ./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32seg.o.objdump $(OUT)code32flat.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds + $(Q)$(PYTHON) ./scripts/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32seg.o.objdump $(OUT)code32flat.o.objdump $(OUT)$(KCONFIG_AUTOHEADER) $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds -# These are actually built by tools/layoutrom.py above, but by pulling them +# These are actually built by scripts/layoutrom.py above, but by pulling them # into an extra rule we prevent make -j from spawning layoutrom.py 4 times. $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds $(OUT)code32flat.o $(OUT)code16.o: $(OUT)romlayout16.lds @@ -175,48 +177,62 @@ @echo " Linking $@" $(Q)$(LD) -T $(OUT)romlayout32flat.lds $(OUT)rom16.strip.o $(OUT)rom32seg.strip.o $(OUT)code32flat.o -o $@ -$(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py +$(OUT)bios.bin.prep: $(OUT)rom.o scripts/checkrom.py @echo " Prepping $@" + $(Q)rm -f $(OUT)bios.bin $(OUT)Csm16.bin $(OUT)bios.bin.elf $(Q)$(OBJDUMP) -thr $< > $<.objdump $(Q)$(OBJCOPY) -O binary $< $(OUT)bios.bin.raw - $(Q)$(PYTHON) ./tools/checkrom.py $<.objdump $(OUT)bios.bin.raw $(OUT)bios.bin + $(Q)$(PYTHON) ./scripts/checkrom.py $<.objdump $(CONFIG_ROM_SIZE) \ + $(OUT)bios.bin.raw $(OUT)bios.bin.prep + +$(OUT)bios.bin: $(OUT)bios.bin.prep + @echo " Creating $@" + $(Q)cp $< $@ + +$(OUT)Csm16.bin: $(OUT)bios.bin.prep + @echo " Creating $@" + $(Q)cp $< $@ + +$(OUT)bios.bin.elf: $(OUT)rom.o $(OUT)bios.bin.prep + @echo " Creating $@" $(Q)$(STRIP) -R .comment $< -o $(OUT)bios.bin.elf ################ VGA build rules # VGA src files -SRCVGA=src/output.c src/util.c src/pci.c \ - vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/vgafonts.c vgasrc/vbe.c \ +SRCVGA=src/output.c src/string.c src/hw/pci.c src/hw/serialio.c \ + vgasrc/vgainit.c vgasrc/vgabios.c vgasrc/vgafb.c \ + vgasrc/vgafonts.c vgasrc/vbe.c \ vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \ vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c CFLAGS16VGA = $(CFLAGS16INC) -Isrc -$(OUT)vgaccode16.raw.s: $(OUT)autoconf.h ; $(call whole-compile, $(CFLAGS16VGA) -S, $(SRCVGA),$@) +$(OUT)vgaccode16.raw.s: $(OUT)autoconf.h $(patsubst %.c, $(OUT)%.o,$(SRCVGA)) ; $(call whole-compile, $(CFLAGS16VGA) -S, $(SRCVGA),$@) -$(OUT)vgaccode16.o: $(OUT)vgaccode16.raw.s +$(OUT)vgaccode16.o: $(OUT)vgaccode16.raw.s scripts/vgafixup.py @echo " Fixup VGA rom assembler" - $(Q)$(PYTHON) ./tools/vgafixup.py $< $(OUT)vgaccode16.s + $(Q)$(PYTHON) ./scripts/vgafixup.py $< $(OUT)vgaccode16.s $(Q)$(AS) --32 src/code16gcc.s $(OUT)vgaccode16.s -o $@ -$(OUT)vgaentry.o: vgaentry.S $(OUT)autoconf.h +$(OUT)vgaentry.o: vgasrc/vgaentry.S $(OUT)autoconf.h $(OUT)asm-offsets.h @echo " Compiling (16bit) $@" $(Q)$(CC) $(CFLAGS16VGA) -c -D__ASSEMBLY__ $< -o $@ -$(OUT)vgarom.o: $(OUT)vgaccode16.o $(OUT)vgaentry.o $(OUT)vgalayout.lds +$(OUT)vgarom.o: $(OUT)vgaccode16.o $(OUT)vgaentry.o $(OUT)vgasrc/vgalayout.lds scripts/buildversion.sh @echo " Linking $@" - $(Q)./tools/buildversion.sh $(OUT)vgaversion.c VAR16 + $(Q)./scripts/buildversion.sh $(OUT)vgaversion.c VAR16 $(Q)$(CC) $(CFLAGS16VGA) -c $(OUT)vgaversion.c -o $(OUT)vgaversion.o - $(Q)$(LD) --gc-sections -T $(OUT)vgalayout.lds $(OUT)vgaccode16.o $(OUT)vgaentry.o $(OUT)vgaversion.o -o $@ + $(Q)$(LD) --gc-sections -T $(OUT)vgasrc/vgalayout.lds $(OUT)vgaccode16.o $(OUT)vgaentry.o $(OUT)vgaversion.o -o $@ $(OUT)vgabios.bin.raw: $(OUT)vgarom.o @echo " Extracting binary $@" $(Q)$(OBJCOPY) -O binary $< $@ -$(OUT)vgabios.bin: $(OUT)vgabios.bin.raw tools/buildrom.py +$(OUT)vgabios.bin: $(OUT)vgabios.bin.raw scripts/buildrom.py @echo " Finalizing rom $@" - $(Q)$(PYTHON) ./tools/buildrom.py $< $@ + $(Q)$(PYTHON) ./scripts/buildrom.py $< $@ ################ DSDT build rules @@ -224,26 +240,27 @@ iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ ; then echo "$(2)"; else echo "$(3)"; fi ;) -$(OUT)%.hex: src/%.dsl ./tools/acpi_extract_preprocess.py ./tools/acpi_extract.py +$(OUT)%.hex: %.dsl ./scripts/acpi_extract_preprocess.py ./scripts/acpi_extract.py @echo " Compiling IASL $@" - $(Q)cpp -P $< > $(OUT)$*.dsl.i.orig - $(Q)$(PYTHON) ./tools/acpi_extract_preprocess.py $(OUT)$*.dsl.i.orig > $(OUT)$*.dsl.i + $(Q)$(CPP) $(CPPFLAGS) $< -o $(OUT)$*.dsl.i.orig + $(Q)$(PYTHON) ./scripts/acpi_extract_preprocess.py $(OUT)$*.dsl.i.orig > $(OUT)$*.dsl.i $(Q)$(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $(OUT)$* $(OUT)$*.dsl.i - $(Q)$(PYTHON) ./tools/acpi_extract.py $(OUT)$*.lst > $(OUT)$*.off + $(Q)$(PYTHON) ./scripts/acpi_extract.py $(OUT)$*.lst > $(OUT)$*.off $(Q)cat $(OUT)$*.off > $@ -$(OUT)ccode32flat.o: $(OUT)acpi-dsdt.hex $(OUT)ssdt-proc.hex $(OUT)ssdt-pcihp.hex +$(OUT)src/fw/acpi.o: $(OUT)src/fw/acpi-dsdt.hex $(OUT)src/fw/ssdt-proc.hex $(OUT)src/fw/ssdt-pcihp.hex $(OUT)src/fw/ssdt-misc.hex $(OUT)src/fw/q35-acpi-dsdt.hex ################ Kconfig rules define do-kconfig -$(Q)mkdir -p $(OUT)/tools/kconfig/lxdialog +$(Q)mkdir -p $(OUT)/scripts/kconfig/lxdialog $(Q)mkdir -p $(OUT)/include/config -$(Q)$(MAKE) -C $(OUT) -f $(CURDIR)/tools/kconfig/Makefile srctree=$(CURDIR) src=tools/kconfig obj=tools/kconfig Q=$(Q) Kconfig=$(CURDIR)/src/Kconfig $1 +$(Q)mkdir -p $(addprefix $(OUT), $(DIRS)) +$(Q)$(MAKE) -C $(OUT) -f $(CURDIR)/scripts/kconfig/Makefile srctree=$(CURDIR) src=scripts/kconfig obj=scripts/kconfig Q=$(Q) Kconfig=$(CURDIR)/src/Kconfig $1 endef $(OUT)autoconf.h : $(KCONFIG_CONFIG) ; $(call do-kconfig, silentoldconfig) -$(KCONFIG_CONFIG): ; $(call do-kconfig, defconfig) +$(KCONFIG_CONFIG): src/Kconfig vgasrc/Kconfig ; $(call do-kconfig, defconfig) %onfig: ; $(call do-kconfig, $@) help: ; $(call do-kconfig, $@) @@ -256,7 +273,4 @@ distclean: clean $(Q)rm -f .config .config.old -$(OUT): - $(Q)mkdir $@ - --include $(OUT)*.d +-include $(patsubst %,$(OUT)%/*.d,$(DIRS)) diff -Nru seabios-1.7.1/README seabios-1.7.4/README --- seabios-1.7.1/README 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/README 2013-12-23 15:40:05.000000000 +0000 @@ -1,8 +1,10 @@ This code implements an X86 legacy bios. It is intended to be compiled using standard gnu tools (eg, gas and gcc). -To build, one should be able to run "make" in the main directory. The -resulting file "out/bios.bin" contains the processed bios image. +To build for QEMU, one should be able to run "make" in the main +directory. The resulting file "out/bios.bin" contains the processed +bios image. To build for coreboot, please see the coreboot wiki. To +build for CSM, please see README.CSM. Testing of images: @@ -17,6 +19,7 @@ cp /usr/share/qemu/*.bin mybiosdir/ cp out/bios.bin mybiosdir/ +cp out/*.aml mybiosdir/ Once this is setup, one can instruct qemu to use the newly created directory for rom images. For example: @@ -31,7 +34,12 @@ mode. (The build system will remove code that is not needed for a particular mode.) -The tools/ directory contains helper utilities for manipulating and +The vgasrc/ directory contains code for VGA BIOS implementations. +This code is separate from the main BIOS code in the src/ directory. +It produces a VGA BIOS rom in out/vgabios.bin. The VGA BIOS code is +always compiled in 16bit mode. + +The scripts/ directory contains helper utilities for manipulating and building the final rom. The out/ directory is created by the build process - it contains all @@ -96,21 +104,22 @@ Most BIOS variables are stored in global variables, the "BDA", or "EBDA" memory areas. Because this is common, three sets of helper -macros (GET/SET_GLOBAL, GET/SET_BDA, and GET/SET_EBDA) are available -to simplify these accesses. +macros (GET_GLOBAL, GET/SET_BDA, and GET/SET_EBDA) are available to +simplify these accesses. Also, an area in the 0xc0000-0xf0000 memory +range is made available for internal BIOS run-time variables that are +marked with the VARLOW attribute. These variables can then be +accessed with the GET/SET_LOW macros. Global variables defined in the C code can be read in 16bit mode if -the variable declaration is marked with VAR16, VAR16VISIBLE, -VAR16EXPORT, or VAR16FIXED. The GET_GLOBAL macro will then allow read -access to the variable. Global variables are stored in the 0xf000 -segment, and their values are persistent across soft resets. Because -the f-segment is marked read-only during run-time, the 16bit code is -not permitted to change the value of 16bit variables (use of the -SET_GLOBAL macro from 16bit mode will cause a link error). Code -running in 32bit mode can not access variables with VAR16, but can -access variables marked with VAR16VISIBLE, VAR16EXPORT, VAR16FIXED, or -with no marking at all. The 32bit code can use the GET/SET_GLOBAL -macros, but they are not required. +the variable declaration is marked with VAR16, VARFSEG, or VAR16FIXED. +The GET_GLOBAL macro will then allow read access to the variable. +Global variables are stored in the 0xf000 segment. Because the +f-segment is marked read-only during run-time, the 16bit code is not +permitted to change the value of 16bit variables. Code running in +32bit mode can not access variables with VAR16, but can access +variables marked with VARFSEG, VARLOW, VAR16FIXED, or with no marking +at all. The 32bit code can use the GET_GLOBAL macros, but they are +not required. GCC 16 bit stack limitations: diff -Nru seabios-1.7.1/README.CSM seabios-1.7.4/README.CSM --- seabios-1.7.1/README.CSM 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/README.CSM 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,22 @@ +Enabling CONFIG_CSM allows SeaBIOS to be built as a Compatibility Support +Module for use with the OMVF/EDK-II UEFI firmware. + +It will provide "legacy" BIOS services for booting non-EFI operating +systems and will also allow OVMF to display on otherwise unsupported +video hardware by using the traditional VGA BIOS. + +Windows 2008r2 is known to use INT 10h BIOS calls even when booted via +EFI, and the presence of a CSM makes this work as expected too. + +Having built SeaBIOS with CONFIG_CSM, you should be able to drop the +result (out/Csm16.bin) into your OVMF build tree at +OvmfPkg/Csm/Csm16/Csm16.bin and then build OVMF with 'build -D +CSM_ENABLE'. The SeaBIOS binary will be included as a discrete file +within the 'Flash Volume' which is created, and there are tools which +will extract it and allow it to be replaced; satisfying the +requirements of the LGPL licence. + +A patch to OVMF is required, to prevent it from marking the region from +0xC0000-0xFFFFF as read-only before invoking our Legacy16Boot method. See +http://www.sourceforge.net/mailarchive/forum.php?thread_name=50FD7290.9060003%40redhat.com&forum_name=edk2-devel + diff -Nru seabios-1.7.1/scripts/acpi_extract_preprocess.py seabios-1.7.4/scripts/acpi_extract_preprocess.py --- seabios-1.7.1/scripts/acpi_extract_preprocess.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/acpi_extract_preprocess.py 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,41 @@ +#!/usr/bin/python +# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +# Read a preprocessed ASL listing and put each ACPI_EXTRACT +# directive in a comment, to make iasl skip it. +# We also put each directive on a new line, the machinery +# in tools/acpi_extract.py requires this. + +import re; +import sys; +import fileinput; + +def die(diag): + sys.stderr.write("Error: %s\n" % (diag)) + sys.exit(1) + +# Note: () around pattern make split return matched string as part of list +psplit = re.compile(r''' ( + \b # At word boundary + ACPI_EXTRACT_\w+ # directive + \s+ # some whitespace + \w+ # array name + )''', re.VERBOSE); + +lineno = 0 +for line in fileinput.input(): + # line number and debug string to output in case of errors + lineno = lineno + 1 + debug = "input line %d: %s" % (lineno, line.rstrip()) + + s = psplit.split(line); + # The way split works, each odd item is the matching ACPI_EXTRACT directive. + # Put each in a comment, and on a line by itself. + for i in range(len(s)): + if (i % 2): + sys.stdout.write("\n/* %s */\n" % s[i]) + else: + sys.stdout.write(s[i]) + diff -Nru seabios-1.7.1/scripts/acpi_extract.py seabios-1.7.4/scripts/acpi_extract.py --- seabios-1.7.1/scripts/acpi_extract.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/acpi_extract.py 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,354 @@ +#!/usr/bin/python +# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +# Process mixed ASL/AML listing (.lst file) produced by iasl -l +# Locate and execute ACPI_EXTRACT directives, output offset info +# +# Documentation of ACPI_EXTRACT_* directive tags: +# +# These directive tags output offset information from AML for BIOS runtime +# table generation. +# Each directive is of the form: +# ACPI_EXTRACT_ (...) +# and causes the extractor to create an array +# named with offset, in the generated AML, +# of an object of a given type in the following . +# +# A directive must fit on a single code line. +# +# Object type in AML is verified, a mismatch causes a build failure. +# +# Directives and operators currently supported are: +# ACPI_EXTRACT_NAME_DWORD_CONST - extract a Dword Const object from Name() +# ACPI_EXTRACT_NAME_WORD_CONST - extract a Word Const object from Name() +# ACPI_EXTRACT_NAME_BYTE_CONST - extract a Byte Const object from Name() +# ACPI_EXTRACT_METHOD_STRING - extract a NameString from Method() +# ACPI_EXTRACT_NAME_STRING - extract a NameString from Name() +# ACPI_EXTRACT_PROCESSOR_START - start of Processor() block +# ACPI_EXTRACT_PROCESSOR_STRING - extract a NameString from Processor() +# ACPI_EXTRACT_PROCESSOR_END - offset at last byte of Processor() + 1 +# ACPI_EXTRACT_DEVICE_START - start of Device() block +# ACPI_EXTRACT_DEVICE_STRING - extract a NameString from Device() +# ACPI_EXTRACT_DEVICE_END - offset at last byte of Device() + 1 +# ACPI_EXTRACT_PKG_START - start of Package block +# +# ACPI_EXTRACT_ALL_CODE - create an array storing the generated AML bytecode +# +# ACPI_EXTRACT is not allowed anywhere else in code, except in comments. + +import re; +import sys; +import fileinput; + +aml = [] +asl = [] +output = {} +debug = "" + +class asl_line: + line = None + lineno = None + aml_offset = None + +def die(diag): + sys.stderr.write("Error: %s; %s\n" % (diag, debug)) + sys.exit(1) + +#Store an ASL command, matching AML offset, and input line (for debugging) +def add_asl(lineno, line): + l = asl_line() + l.line = line + l.lineno = lineno + l.aml_offset = len(aml) + asl.append(l) + +#Store an AML byte sequence +#Verify that offset output by iasl matches # of bytes so far +def add_aml(offset, line): + o = int(offset, 16); + # Sanity check: offset must match size of code so far + if (o != len(aml)): + die("Offset 0x%x != 0x%x" % (o, len(aml))) + # Strip any trailing dots and ASCII dump after " + line = re.sub(r'\s*\.*\s*".*$',"", line) + # Strip traling whitespace + line = re.sub(r'\s+$',"", line) + # Strip leading whitespace + line = re.sub(r'^\s+',"", line) + # Split on whitespace + code = re.split(r'\s+', line) + for c in code: + # Require a legal hex number, two digits + if (not(re.search(r'^[0-9A-Fa-f][0-9A-Fa-f]$', c))): + die("Unexpected octet %s" % c); + aml.append(int(c, 16)); + +# Process aml bytecode array, decoding AML +def aml_pkglen_bytes(offset): + # PkgLength can be multibyte. Bits 8-7 give the # of extra bytes. + pkglenbytes = aml[offset] >> 6; + return pkglenbytes + 1 + +def aml_pkglen(offset): + pkgstart = offset + pkglenbytes = aml_pkglen_bytes(offset) + pkglen = aml[offset] & 0x3F + # If multibyte, first nibble only uses bits 0-3 + if ((pkglenbytes > 1) and (pkglen & 0x30)): + die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" % + (pkglen, pkglen)) + offset += 1 + pkglenbytes -= 1 + for i in range(pkglenbytes): + pkglen |= aml[offset + i] << (i * 8 + 4) + if (len(aml) < pkgstart + pkglen): + die("PckgLen 0x%x at offset 0x%x exceeds AML size 0x%x" % + (pkglen, offset, len(aml))) + return pkglen + +# Given method offset, find its NameString offset +def aml_method_string(offset): + #0x14 MethodOp PkgLength NameString MethodFlags TermList + if (aml[offset] != 0x14): + die( "Method offset 0x%x: expected 0x14 actual 0x%x" % + (offset, aml[offset])); + offset += 1; + pkglenbytes = aml_pkglen_bytes(offset) + offset += pkglenbytes; + return offset; + +# Given name offset, find its NameString offset +def aml_name_string(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x08): + die( "Name offset 0x%x: expected 0x08 actual 0x%x" % + (offset, aml[offset])); + offset += 1 + # Block Name Modifier. Skip it. + if (aml[offset] == 0x5c or aml[offset] == 0x5e): + offset += 1 + return offset; + +# Given data offset, find 8 byte buffer offset +def aml_data_buffer8(offset): + #0x08 NameOp NameString DataRef + expect = [0x11, 0x0B, 0x0A, 0x08] + if (aml[offset:offset+4] != expect): + die( "Name offset 0x%x: expected %s actual %s" % + (offset, aml[offset:offset+4], expect)) + return offset + len(expect) + +# Given data offset, find dword const offset +def aml_data_dword_const(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x0C): + die( "Name offset 0x%x: expected 0x0C actual 0x%x" % + (offset, aml[offset])); + return offset + 1; + +# Given data offset, find word const offset +def aml_data_word_const(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x0B): + die( "Name offset 0x%x: expected 0x0B actual 0x%x" % + (offset, aml[offset])); + return offset + 1; + +# Given data offset, find byte const offset +def aml_data_byte_const(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x0A): + die( "Name offset 0x%x: expected 0x0A actual 0x%x" % + (offset, aml[offset])); + return offset + 1; + +# Find name'd buffer8 +def aml_name_buffer8(offset): + return aml_data_buffer8(aml_name_string(offset) + 4) + +# Given name offset, find dword const offset +def aml_name_dword_const(offset): + return aml_data_dword_const(aml_name_string(offset) + 4) + +# Given name offset, find word const offset +def aml_name_word_const(offset): + return aml_data_word_const(aml_name_string(offset) + 4) + +# Given name offset, find byte const offset +def aml_name_byte_const(offset): + return aml_data_byte_const(aml_name_string(offset) + 4) + +def aml_device_start(offset): + #0x5B 0x82 DeviceOp PkgLength NameString + if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x82)): + die( "Name offset 0x%x: expected 0x5B 0x82 actual 0x%x 0x%x" % + (offset, aml[offset], aml[offset + 1])); + return offset + +def aml_device_string(offset): + #0x5B 0x82 DeviceOp PkgLength NameString + start = aml_device_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + offset += pkglenbytes + return offset + +def aml_device_end(offset): + start = aml_device_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + pkglen = aml_pkglen(offset) + return offset + pkglen + +def aml_processor_start(offset): + #0x5B 0x83 ProcessorOp PkgLength NameString ProcID + if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)): + die( "Name offset 0x%x: expected 0x5B 0x83 actual 0x%x 0x%x" % + (offset, aml[offset], aml[offset + 1])); + return offset + +def aml_processor_string(offset): + #0x5B 0x83 ProcessorOp PkgLength NameString ProcID + start = aml_processor_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + offset += pkglenbytes + return offset + +def aml_processor_end(offset): + start = aml_processor_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + pkglen = aml_pkglen(offset) + return offset + pkglen + +def aml_package_start(offset): + offset = aml_name_string(offset) + 4 + # 0x12 PkgLength NumElements PackageElementList + if (aml[offset] != 0x12): + die( "Name offset 0x%x: expected 0x12 actual 0x%x" % + (offset, aml[offset])); + offset += 1 + return offset + aml_pkglen_bytes(offset) + 1 + +lineno = 0 +for line in fileinput.input(): + # Strip trailing newline + line = line.rstrip(); + # line number and debug string to output in case of errors + lineno = lineno + 1 + debug = "input line %d: %s" % (lineno, line) + #ASL listing: space, then line#, then ...., then code + pasl = re.compile('^\s+([0-9]+)(:\s\s|\.\.\.\.)\s*') + m = pasl.search(line) + if (m): + add_asl(lineno, pasl.sub("", line)); + # AML listing: offset in hex, then ...., then code + paml = re.compile('^([0-9A-Fa-f]+)(:\s\s|\.\.\.\.)\s*') + m = paml.search(line) + if (m): + add_aml(m.group(1), paml.sub("", line)) + +# Now go over code +# Track AML offset of a previous non-empty ASL command +prev_aml_offset = -1 +for i in range(len(asl)): + debug = "input line %d: %s" % (asl[i].lineno, asl[i].line) + + l = asl[i].line + + # skip if not an extract directive + a = len(re.findall(r'ACPI_EXTRACT', l)) + if (not a): + # If not empty, store AML offset. Will be used for sanity checks + # IASL seems to put {}. at random places in the listing. + # Ignore any non-words for the purpose of this test. + m = re.search(r'\w+', l) + if (m): + prev_aml_offset = asl[i].aml_offset + continue + + if (a > 1): + die("Expected at most one ACPI_EXTRACT per line, actual %d" % a) + + mext = re.search(r''' + ^\s* # leading whitespace + /\*\s* # start C comment + (ACPI_EXTRACT_\w+) # directive: group(1) + \s+ # whitspace separates directive from array name + (\w+) # array name: group(2) + \s*\*/ # end of C comment + \s*$ # trailing whitespace + ''', l, re.VERBOSE) + if (not mext): + die("Stray ACPI_EXTRACT in input") + + # previous command must have produced some AML, + # otherwise we are in a middle of a block + if (prev_aml_offset == asl[i].aml_offset): + die("ACPI_EXTRACT directive in the middle of a block") + + directive = mext.group(1) + array = mext.group(2) + offset = asl[i].aml_offset + + if (directive == "ACPI_EXTRACT_ALL_CODE"): + if array in output: + die("%s directive used more than once" % directive) + output[array] = aml + continue + if (directive == "ACPI_EXTRACT_NAME_BUFFER8"): + offset = aml_name_buffer8(offset) + elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"): + offset = aml_name_dword_const(offset) + elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"): + offset = aml_name_word_const(offset) + elif (directive == "ACPI_EXTRACT_NAME_BYTE_CONST"): + offset = aml_name_byte_const(offset) + elif (directive == "ACPI_EXTRACT_NAME_STRING"): + offset = aml_name_string(offset) + elif (directive == "ACPI_EXTRACT_METHOD_STRING"): + offset = aml_method_string(offset) + elif (directive == "ACPI_EXTRACT_DEVICE_START"): + offset = aml_device_start(offset) + elif (directive == "ACPI_EXTRACT_DEVICE_STRING"): + offset = aml_device_string(offset) + elif (directive == "ACPI_EXTRACT_DEVICE_END"): + offset = aml_device_end(offset) + elif (directive == "ACPI_EXTRACT_PROCESSOR_START"): + offset = aml_processor_start(offset) + elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"): + offset = aml_processor_string(offset) + elif (directive == "ACPI_EXTRACT_PROCESSOR_END"): + offset = aml_processor_end(offset) + elif (directive == "ACPI_EXTRACT_PKG_START"): + offset = aml_package_start(offset) + else: + die("Unsupported directive %s" % directive) + + if array not in output: + output[array] = [] + output[array].append(offset) + +debug = "at end of file" + +def get_value_type(maxvalue): + #Use type large enough to fit the table + if (maxvalue >= 0x10000): + return "int" + elif (maxvalue >= 0x100): + return "short" + else: + return "char" + +# Pretty print output +for array in output.keys(): + otype = get_value_type(max(output[array])) + odata = [] + for value in output[array]: + odata.append("0x%x" % value) + sys.stdout.write("static unsigned %s %s[] = {\n" % (otype, array)) + sys.stdout.write(",\n".join(odata)) + sys.stdout.write('\n};\n'); diff -Nru seabios-1.7.1/scripts/buildrom.py seabios-1.7.4/scripts/buildrom.py --- seabios-1.7.1/scripts/buildrom.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/buildrom.py 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# Fill in checksum/size of an option rom, and pad it to proper length. +# +# Copyright (C) 2009 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +import sys + +def alignpos(pos, alignbytes): + mask = alignbytes - 1 + return (pos + mask) & ~mask + +def checksum(data): + ords = map(ord, data) + return sum(ords) + +def main(): + inname = sys.argv[1] + outname = sys.argv[2] + + # Read data in + f = open(inname, 'rb') + data = f.read() + f.close() + count = len(data) + + # Pad to a 512 byte boundary + data += "\0" * (alignpos(count, 512) - count) + count = len(data) + + # Check if a pci header is present + pcidata = ord(data[24:25]) + (ord(data[25:26]) << 8) + if pcidata != 0: + data = data[:pcidata + 16] + chr(count/512) + chr(0) + data[pcidata + 18:] + + # Fill in size field; clear checksum field + data = data[:2] + chr(count/512) + data[3:6] + "\0" + data[7:] + + # Checksum rom + newsum = (256 - checksum(data)) & 0xff + data = data[:6] + chr(newsum) + data[7:] + + # Write new rom + f = open(outname, 'wb') + f.write(data) + f.close() + +if __name__ == '__main__': + main() diff -Nru seabios-1.7.1/scripts/buildversion.sh seabios-1.7.4/scripts/buildversion.sh --- seabios-1.7.1/scripts/buildversion.sh 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/buildversion.sh 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,27 @@ +#!/bin/sh +# Script to generate a C file with version information. +OUTFILE="$1" +VAR16MODE="$2" + +# Extract version info +if [ -d .git -o -f .git ]; then + VERSION="`git describe --tags --long --dirty`" +elif [ -f .version ]; then + VERSION="`cat .version`" +else + VERSION="?" +fi +VERSION="${VERSION}-`date +"%Y%m%d_%H%M%S"`-`hostname`" +echo "Version: ${VERSION}" + +# Build header file +if [ "$VAR16MODE" = "VAR16" ]; then + cat > ${OUTFILE} < ${OUTFILE} < +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +import sys +import layoutrom + +def subst(data, offset, new): + return data[:offset] + new + data[offset + len(new):] + +def checksum(data, start, size, csum): + sumbyte = 0 + while size: + sumbyte = sumbyte + ord(data[start + size - 1]) + size = size - 1 + sumbyte = (0x100 - sumbyte) & 0xff + return subst(data, start+csum, chr(sumbyte)) + +def main(): + # Get args + objinfo, finalsize, rawfile, outfile = sys.argv[1:] + + # Read in symbols + objinfofile = open(objinfo, 'rb') + symbols = layoutrom.parseObjDump(objinfofile, 'in')[1] + + # Read in raw file + f = open(rawfile, 'rb') + rawdata = f.read() + f.close() + datasize = len(rawdata) + finalsize = int(finalsize) * 1024 + if finalsize == 0: + finalsize = 64*1024 + if datasize > 64*1024: + finalsize = 128*1024 + if datasize > 128*1024: + finalsize = 256*1024 + if datasize > finalsize: + print "Error! ROM doesn't fit (%d > %d)" % (datasize, finalsize) + print " You have to either increate the size (CONFIG_ROM_SIZE)" + print " or turn off some features (such as hardware support not" + print " needed) to make it fit. Trying a more recent gcc version" + print " might work too." + sys.exit(1) + + # Sanity checks + start = symbols['code32flat_start'].offset + end = symbols['code32flat_end'].offset + expend = layoutrom.BUILD_BIOS_ADDR + layoutrom.BUILD_BIOS_SIZE + if end != expend: + print "Error! Code does not end at 0x%x (got 0x%x)" % ( + expend, end) + sys.exit(1) + if datasize > finalsize: + print "Error! Code is too big (0x%x vs 0x%x)" % ( + datasize, finalsize) + sys.exit(1) + expdatasize = end - start + if datasize != expdatasize: + print "Error! Unknown extra data (0x%x vs 0x%x)" % ( + datasize, expdatasize) + sys.exit(1) + + # Fix up CSM Compatibility16 table + if 'csm_compat_table' in symbols and 'entry_csm' in symbols: + # Field offsets within EFI_COMPATIBILITY16_TABLE + ENTRY_FIELD_OFS = 14 # Compatibility16CallOffset (UINT16) + SIZE_FIELD_OFS = 5 # TableLength (UINT8) + CSUM_FIELD_OFS = 4 # TableChecksum (UINT8) + + tableofs = symbols['csm_compat_table'].offset - symbols['code32flat_start'].offset + entry_addr = symbols['entry_csm'].offset - layoutrom.BUILD_BIOS_ADDR + byte1 = chr(entry_addr & 0xff) + byte2 = chr(entry_addr >> 8) + rawdata = subst(rawdata, tableofs+ENTRY_FIELD_OFS, byte1+byte2) + + tablesize = ord(rawdata[tableofs+SIZE_FIELD_OFS]) + rawdata = checksum(rawdata, tableofs, tablesize, CSUM_FIELD_OFS) + + # Print statistics + runtimesize = end - symbols['code32init_end'].offset + print "Total size: %d Fixed: %d Free: %d (used %.1f%% of %dKiB rom)" % ( + datasize, runtimesize, finalsize - datasize + , (datasize / float(finalsize)) * 100.0 + , finalsize / 1024) + + # Write final file + f = open(outfile, 'wb') + f.write(("\0" * (finalsize - datasize)) + rawdata) + f.close() + +if __name__ == '__main__': + main() diff -Nru seabios-1.7.1/scripts/checkstack.py seabios-1.7.4/scripts/checkstack.py --- seabios-1.7.1/scripts/checkstack.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/checkstack.py 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,225 @@ +#!/usr/bin/env python +# Script that tries to find how much stack space each function in an +# object is using. +# +# Copyright (C) 2008 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +# Usage: +# objdump -m i386 -M i8086 -M suffix -d out/rom16.o | tools/checkstack.py + +import sys +import re + +# Functions that change stacks +STACKHOP = ['stack_hop', 'stack_hop_back'] +# List of functions we can assume are never called. +#IGNORE = ['panic', '__dprintf'] +IGNORE = ['panic'] + +OUTPUTDESC = """ +#funcname1[preamble_stack_usage,max_usage_with_callers]: +# insn_addr:called_function [usage_at_call_point+caller_preamble,total_usage] +# +#funcname2[p,m,max_usage_to_yield_point]: +# insn_addr:called_function [u+c,t,usage_to_yield_point] +""" + +# Find out maximum stack usage for a function +def calcmaxstack(funcs, funcaddr): + info = funcs[funcaddr] + # Find max of all nested calls. + maxusage = info[1] + maxyieldusage = doesyield = 0 + if info[3] is not None: + maxyieldusage = info[3] + doesyield = 1 + info[2] = maxusage + info[4] = info[3] + seenbefore = {} + totcalls = 0 + for insnaddr, calladdr, usage in info[6]: + callinfo = funcs.get(calladdr) + if callinfo is None: + continue + if callinfo[2] is None: + calcmaxstack(funcs, calladdr) + if callinfo[0] not in seenbefore: + seenbefore[callinfo[0]] = 1 + totcalls += 1 + callinfo[5] + funcnameroot = callinfo[0].split('.')[0] + if funcnameroot in IGNORE: + # This called function is ignored - don't contribute it to + # the max stack. + continue + if funcnameroot in STACKHOP: + if usage > maxusage: + maxusage = usage + if callinfo[4] is not None: + doesyield = 1 + if usage > maxyieldusage: + maxyieldusage = usage + continue + totusage = usage + callinfo[2] + if totusage > maxusage: + maxusage = totusage + if callinfo[4] is not None: + doesyield = 1 + totyieldusage = usage + callinfo[4] + if totyieldusage > maxyieldusage: + maxyieldusage = totyieldusage + info[2] = maxusage + if doesyield: + info[4] = maxyieldusage + info[5] = totcalls + +# Try to arrange output so that functions that call each other are +# near each other. +def orderfuncs(funcaddrs, availfuncs): + l = [(availfuncs[funcaddr][5], availfuncs[funcaddr][0], funcaddr) + for funcaddr in funcaddrs if funcaddr in availfuncs] + l.sort() + l.reverse() + out = [] + while l: + count, name, funcaddr = l.pop(0) + if funcaddr not in availfuncs: + continue + calladdrs = [calls[1] for calls in availfuncs[funcaddr][6]] + del availfuncs[funcaddr] + out = out + orderfuncs(calladdrs, availfuncs) + [funcaddr] + return out + +# Update function info with a found "yield" point. +def noteYield(info, stackusage): + prevyield = info[3] + if prevyield is None or prevyield < stackusage: + info[3] = stackusage + +# Update function info with a found "call" point. +def noteCall(info, subfuncs, insnaddr, calladdr, stackusage): + if (calladdr, stackusage) in subfuncs: + # Already noted a nearly identical call - ignore this one. + return + info[6].append((insnaddr, calladdr, stackusage)) + subfuncs[(calladdr, stackusage)] = 1 + +hex_s = r'[0-9a-f]+' +re_func = re.compile(r'^(?P' + hex_s + r') <(?P.*)>:$') +re_asm = re.compile( + r'^[ ]*(?P' + hex_s + + r'):\t.*\t(addr32 )?(?P.+?)[ ]*((?P' + hex_s + + r') <(?P.*)>)?$') +re_usestack = re.compile( + r'^(push[f]?[lw])|(sub.* [$](?P0x' + hex_s + r'),%esp)$') + +def calc(): + # funcs[funcaddr] = [funcname, basicstackusage, maxstackusage + # , yieldusage, maxyieldusage, totalcalls + # , [(insnaddr, calladdr, stackusage), ...]] + funcs = {-1: ['', 0, 0, None, None, 0, []]} + cur = None + atstart = 0 + stackusage = 0 + + # Parse input lines + for line in sys.stdin.readlines(): + m = re_func.match(line) + if m is not None: + # Found function + funcaddr = int(m.group('funcaddr'), 16) + funcs[funcaddr] = cur = [m.group('func'), 0, None, None, None, 0, []] + stackusage = 0 + atstart = 1 + subfuncs = {} + continue + m = re_asm.match(line) + if m is not None: + insn = m.group('insn') + + im = re_usestack.match(insn) + if im is not None: + if insn.startswith('pushl') or insn.startswith('pushfl'): + stackusage += 4 + continue + elif insn.startswith('pushw') or insn.startswith('pushfw'): + stackusage += 2 + continue + stackusage += int(im.group('num'), 16) + + if atstart: + if '%esp' in insn or insn.startswith('leal'): + # Still part of initial header + continue + cur[1] = stackusage + atstart = 0 + + insnaddr = m.group('insnaddr') + calladdr = m.group('calladdr') + if calladdr is None: + if insn.startswith('lcallw'): + noteCall(cur, subfuncs, insnaddr, -1, stackusage + 4) + noteYield(cur, stackusage + 4) + elif insn.startswith('int'): + noteCall(cur, subfuncs, insnaddr, -1, stackusage + 6) + noteYield(cur, stackusage + 6) + elif insn.startswith('sti'): + noteYield(cur, stackusage) + else: + # misc instruction + continue + else: + # Jump or call insn + calladdr = int(calladdr, 16) + ref = m.group('ref') + if '+' in ref: + # Inter-function jump. + pass + elif insn.startswith('j'): + # Tail call + noteCall(cur, subfuncs, insnaddr, calladdr, 0) + elif insn.startswith('calll'): + noteCall(cur, subfuncs, insnaddr, calladdr, stackusage + 4) + else: + print "unknown call", ref + noteCall(cur, subfuncs, insnaddr, calladdr, stackusage) + # Reset stack usage to preamble usage + stackusage = cur[1] + + #print "other", repr(line) + + # Calculate maxstackusage + for funcaddr, info in funcs.items(): + if info[2] is not None: + continue + calcmaxstack(funcs, funcaddr) + + # Sort functions for output + funcaddrs = orderfuncs(funcs.keys(), funcs.copy()) + + # Show all functions + print OUTPUTDESC + for funcaddr in funcaddrs: + name, basicusage, maxusage, yieldusage, maxyieldusage, count, calls = \ + funcs[funcaddr] + if maxusage == 0 and maxyieldusage is None: + continue + yieldstr = "" + if maxyieldusage is not None: + yieldstr = ",%d" % maxyieldusage + print "\n%s[%d,%d%s]:" % (name, basicusage, maxusage, yieldstr) + for insnaddr, calladdr, stackusage in calls: + callinfo = funcs.get(calladdr, ("", 0, 0, 0, None)) + yieldstr = "" + if callinfo[4] is not None: + yieldstr = ",%d" % (stackusage + callinfo[4]) + print " %04s:%-40s [%d+%d,%d%s]" % ( + insnaddr, callinfo[0], stackusage, callinfo[1] + , stackusage+callinfo[2], yieldstr) + +def main(): + calc() + +if __name__ == '__main__': + main() diff -Nru seabios-1.7.1/scripts/checksum.py seabios-1.7.4/scripts/checksum.py --- seabios-1.7.1/scripts/checksum.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/checksum.py 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# Script to report the checksum of a file. +# +# Copyright (C) 2009 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +import sys + +def main(): + data = sys.stdin.read() + ords = map(ord, data) + print "sum=%x\n" % sum(ords) + +if __name__ == '__main__': + main() diff -Nru seabios-1.7.1/scripts/encodeint.py seabios-1.7.4/scripts/encodeint.py --- seabios-1.7.1/scripts/encodeint.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/encodeint.py 2013-12-23 15:40:05.000000000 +0000 @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# Encode an integer in little endian format in a file. +# +# Copyright (C) 2011 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +import sys +import struct + +def main(): + filename = sys.argv[1] + value = int(sys.argv[2]) + + outval = struct.pack(' "$OUTFILE" </{s:->#\(.*\):/* \1 */:; \ + s:^->\([^ ]*\) [\$\#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:->::; p;}" < "$INFILE" >> "$OUTFILE" +cat >> "$OUTFILE" < /dev/null 2>&1 << EOF +#include +int main() +{ + gettext(""); + return 0; +} +EOF +if [ ! "$?" -eq "0" ]; then + echo -DKBUILD_NO_NLS; +fi + diff -Nru seabios-1.7.1/scripts/kconfig/conf.c seabios-1.7.4/scripts/kconfig/conf.c --- seabios-1.7.1/scripts/kconfig/conf.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/conf.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,718 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); +static void xfgets(char *str, int size, FILE *in); + +enum input_mode { + oldaskconfig, + silentoldconfig, + oldconfig, + allnoconfig, + allyesconfig, + allmodconfig, + alldefconfig, + randconfig, + defconfig, + savedefconfig, + listnewconfig, + olddefconfig, +} input_mode = oldaskconfig; + +static int indent = 1; +static int tty_stdio; +static int valid_stdin = 1; +static int sync_kconfig; +static int conf_cnt; +static char line[128]; +static struct menu *rootEntry; + +static void print_help(struct menu *menu) +{ + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + printf("\n%s\n", str_get(&help)); + str_free(&help); +} + +static void strip(char *str) +{ + char *p = str; + int l; + + while ((isspace(*p))) + p++; + l = strlen(p); + if (p != str) + memmove(str, p, l + 1); + if (!l) + return; + p = str + l - 1; + while ((isspace(*p))) + *p-- = 0; +} + +static void check_stdin(void) +{ + if (!valid_stdin) { + printf(_("aborted!\n\n")); + printf(_("Console input/output is redirected. ")); + printf(_("Run 'make oldconfig' to update configuration.\n\n")); + exit(1); + } +} + +static int conf_askvalue(struct symbol *sym, const char *def) +{ + enum symbol_type type = sym_get_type(sym); + + if (!sym_has_value(sym)) + printf(_("(NEW) ")); + + line[0] = '\n'; + line[1] = 0; + + if (!sym_is_changable(sym)) { + printf("%s\n", def); + line[0] = '\n'; + line[1] = 0; + return 0; + } + + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (sym_has_value(sym)) { + printf("%s\n", def); + return 0; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); + if (!tty_stdio) + printf("\n"); + return 1; + default: + break; + } + + switch (type) { + case S_INT: + case S_HEX: + case S_STRING: + printf("%s\n", def); + return 1; + default: + ; + } + printf("%s", line); + return 1; +} + +static int conf_string(struct menu *menu) +{ + struct symbol *sym = menu->sym; + const char *def; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("(%s) ", sym->name); + def = sym_get_string_value(sym); + if (sym_get_string_value(sym)) + printf("[%s] ", def); + if (!conf_askvalue(sym, def)) + return 0; + switch (line[0]) { + case '\n': + break; + case '?': + /* print help */ + if (line[1] == '\n') { + print_help(menu); + def = NULL; + break; + } + /* fall through */ + default: + line[strlen(line)-1] = 0; + def = line; + } + if (def && sym_set_string_value(sym, def)) + return 0; + } +} + +static int conf_sym(struct menu *menu) +{ + struct symbol *sym = menu->sym; + tristate oldval, newval; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + if (sym->name) + printf("(%s) ", sym->name); + putchar('['); + oldval = sym_get_tristate_value(sym); + switch (oldval) { + case no: + putchar('N'); + break; + case mod: + putchar('M'); + break; + case yes: + putchar('Y'); + break; + } + if (oldval != no && sym_tristate_within_range(sym, no)) + printf("/n"); + if (oldval != mod && sym_tristate_within_range(sym, mod)) + printf("/m"); + if (oldval != yes && sym_tristate_within_range(sym, yes)) + printf("/y"); + if (menu_has_help(menu)) + printf("/?"); + printf("] "); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; + strip(line); + + switch (line[0]) { + case 'n': + case 'N': + newval = no; + if (!line[1] || !strcmp(&line[1], "o")) + break; + continue; + case 'm': + case 'M': + newval = mod; + if (!line[1]) + break; + continue; + case 'y': + case 'Y': + newval = yes; + if (!line[1] || !strcmp(&line[1], "es")) + break; + continue; + case 0: + newval = oldval; + break; + case '?': + goto help; + default: + continue; + } + if (sym_set_tristate_value(sym, newval)) + return 0; +help: + print_help(menu); + } +} + +static int conf_choice(struct menu *menu) +{ + struct symbol *sym, *def_sym; + struct menu *child; + bool is_new; + + sym = menu->sym; + is_new = !sym_has_value(sym); + if (sym_is_changable(sym)) { + conf_sym(menu); + sym_calc_value(sym); + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + return 0; + case yes: + break; + } + } else { + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + return 0; + case yes: + break; + } + } + + while (1) { + int cnt, def; + + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + def_sym = sym_get_choice_value(sym); + cnt = def = 0; + line[0] = 0; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (!child->sym) { + printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); + continue; + } + cnt++; + if (child->sym == def_sym) { + def = cnt; + printf("%*c", indent, '>'); + } else + printf("%*c", indent, ' '); + printf(" %d. %s", cnt, _(menu_get_prompt(child))); + if (child->sym->name) + printf(" (%s)", child->sym->name); + if (!sym_has_value(child->sym)) + printf(_(" (NEW)")); + printf("\n"); + } + printf(_("%*schoice"), indent - 1, ""); + if (cnt == 1) { + printf("[1]: 1\n"); + goto conf_childs; + } + printf("[1-%d", cnt); + if (menu_has_help(menu)) + printf("?"); + printf("]: "); + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (!is_new) { + cnt = def; + printf("%d\n", cnt); + break; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); + strip(line); + if (line[0] == '?') { + print_help(menu); + continue; + } + if (!line[0]) + cnt = def; + else if (isdigit(line[0])) + cnt = atoi(line); + else + continue; + break; + default: + break; + } + + conf_childs: + for (child = menu->list; child; child = child->next) { + if (!child->sym || !menu_is_visible(child)) + continue; + if (!--cnt) + break; + } + if (!child) + continue; + if (line[0] && line[strlen(line) - 1] == '?') { + print_help(child); + continue; + } + sym_set_choice_value(sym, child->sym); + for (child = child->list; child; child = child->next) { + indent += 2; + conf(child); + indent -= 2; + } + return 1; + } +} + +static void conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (prop) { + const char *prompt; + + switch (prop->type) { + case P_MENU: + if ((input_mode == silentoldconfig || + input_mode == listnewconfig || + input_mode == olddefconfig) && + rootEntry != menu) { + check_conf(menu); + return; + } + /* fall through */ + case P_COMMENT: + prompt = menu_get_prompt(menu); + if (prompt) + printf("%*c\n%*c %s\n%*c\n", + indent, '*', + indent, '*', _(prompt), + indent, '*'); + default: + ; + } + } + + if (!sym) + goto conf_childs; + + if (sym_is_choice(sym)) { + conf_choice(menu); + if (sym->curr.tri != mod) + return; + goto conf_childs; + } + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + conf_string(menu); + break; + default: + conf_sym(menu); + break; + } + +conf_childs: + if (sym) + indent += 2; + for (child = menu->list; child; child = child->next) + conf(child); + if (sym) + indent -= 2; +} + +static void check_conf(struct menu *menu) +{ + struct symbol *sym; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { + if (input_mode == listnewconfig) { + if (sym->name && !sym_is_choice_value(sym)) { + printf("%s%s\n", CONFIG_, sym->name); + } + } else if (input_mode != olddefconfig) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } + } + } + + for (child = menu->list; child; child = child->next) + check_conf(child); +} + +static struct option long_opts[] = { + {"oldaskconfig", no_argument, NULL, oldaskconfig}, + {"oldconfig", no_argument, NULL, oldconfig}, + {"silentoldconfig", no_argument, NULL, silentoldconfig}, + {"defconfig", optional_argument, NULL, defconfig}, + {"savedefconfig", required_argument, NULL, savedefconfig}, + {"allnoconfig", no_argument, NULL, allnoconfig}, + {"allyesconfig", no_argument, NULL, allyesconfig}, + {"allmodconfig", no_argument, NULL, allmodconfig}, + {"alldefconfig", no_argument, NULL, alldefconfig}, + {"randconfig", no_argument, NULL, randconfig}, + {"listnewconfig", no_argument, NULL, listnewconfig}, + {"olddefconfig", no_argument, NULL, olddefconfig}, + /* + * oldnoconfig is an alias of olddefconfig, because people already + * are dependent on its behavior(sets new symbols to their default + * value but not 'n') with the counter-intuitive name. + */ + {"oldnoconfig", no_argument, NULL, olddefconfig}, + {NULL, 0, NULL, 0} +}; + +static void conf_usage(const char *progname) +{ + + printf("Usage: %s [option] \n", progname); + printf("[option] is _one_ of the following:\n"); + printf(" --listnewconfig List new options\n"); + printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); + printf(" --oldconfig Update a configuration using a provided .config as base\n"); + printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); + printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n"); + printf(" --oldnoconfig An alias of olddefconfig\n"); + printf(" --defconfig New config with default defined in \n"); + printf(" --savedefconfig Save the minimal current configuration to \n"); + printf(" --allnoconfig New config where all options are answered with no\n"); + printf(" --allyesconfig New config where all options are answered with yes\n"); + printf(" --allmodconfig New config where all options are answered with mod\n"); + printf(" --alldefconfig New config with all symbols set to default\n"); + printf(" --randconfig New config with random answer to all options\n"); +} + +int main(int ac, char **av) +{ + const char *progname = av[0]; + int opt; + const char *name, *defconfig_file = NULL /* gcc uninit */; + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + tty_stdio = isatty(0) && isatty(1) && isatty(2); + + while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { + input_mode = (enum input_mode)opt; + switch (opt) { + case silentoldconfig: + sync_kconfig = 1; + break; + case defconfig: + case savedefconfig: + defconfig_file = optarg; + break; + case randconfig: + { + struct timeval now; + unsigned int seed; + char *seed_env; + + /* + * Use microseconds derived seed, + * compensate for systems where it may be zero + */ + gettimeofday(&now, NULL); + seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); + + seed_env = getenv("KCONFIG_SEED"); + if( seed_env && *seed_env ) { + char *endp; + int tmp = (int)strtol(seed_env, &endp, 0); + if (*endp == '\0') { + seed = tmp; + } + } + fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed ); + srand(seed); + break; + } + case oldaskconfig: + case oldconfig: + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case listnewconfig: + case olddefconfig: + break; + case '?': + conf_usage(progname); + exit(1); + break; + } + } + if (ac == optind) { + printf(_("%s: Kconfig file missing\n"), av[0]); + conf_usage(progname); + exit(1); + } + name = av[optind]; + conf_parse(name); + //zconfdump(stdout); + if (sync_kconfig) { + name = conf_get_configname(); + if (stat(name, &tmpstat)) { + fprintf(stderr, _("***\n" + "*** Configuration file \"%s\" not found!\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n"), name); + exit(1); + } + } + + switch (input_mode) { + case defconfig: + if (!defconfig_file) + defconfig_file = conf_get_default_confname(); + if (conf_read(defconfig_file)) { + printf(_("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n"), defconfig_file); + exit(1); + } + break; + case savedefconfig: + case silentoldconfig: + case oldaskconfig: + case oldconfig: + case listnewconfig: + case olddefconfig: + conf_read(NULL); + break; + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case randconfig: + name = getenv("KCONFIG_ALLCONFIG"); + if (!name) + break; + if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { + if (conf_read_simple(name, S_DEF_USER)) { + fprintf(stderr, + _("*** Can't read seed configuration \"%s\"!\n"), + name); + exit(1); + } + break; + } + switch (input_mode) { + case allnoconfig: name = "allno.config"; break; + case allyesconfig: name = "allyes.config"; break; + case allmodconfig: name = "allmod.config"; break; + case alldefconfig: name = "alldef.config"; break; + case randconfig: name = "allrandom.config"; break; + default: break; + } + if (conf_read_simple(name, S_DEF_USER) && + conf_read_simple("all.config", S_DEF_USER)) { + fprintf(stderr, + _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), + name); + exit(1); + } + break; + default: + break; + } + + if (sync_kconfig) { + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** The configuration requires explicit update.\n\n")); + return 1; + } + } + valid_stdin = tty_stdio; + } + + switch (input_mode) { + case allnoconfig: + conf_set_all_new_symbols(def_no); + break; + case allyesconfig: + conf_set_all_new_symbols(def_yes); + break; + case allmodconfig: + conf_set_all_new_symbols(def_mod); + break; + case alldefconfig: + conf_set_all_new_symbols(def_default); + break; + case randconfig: + /* Really nothing to do in this loop */ + while (conf_set_all_new_symbols(def_random)) ; + break; + case defconfig: + conf_set_all_new_symbols(def_default); + break; + case savedefconfig: + break; + case oldaskconfig: + rootEntry = &rootmenu; + conf(&rootmenu); + input_mode = silentoldconfig; + /* fall through */ + case oldconfig: + case listnewconfig: + case olddefconfig: + case silentoldconfig: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt && + (input_mode != listnewconfig && + input_mode != olddefconfig)); + break; + } + + if (sync_kconfig) { + /* silentoldconfig is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); + return 1; + } + } else if (input_mode == savedefconfig) { + if (conf_write_defconfig(defconfig_file)) { + fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), + defconfig_file); + return 1; + } + } else if (input_mode != listnewconfig) { + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + } + return 0; +} + +/* + * Helper function to facilitate fgets() by Jean Sacren. + */ +void xfgets(char *str, int size, FILE *in) +{ + if (fgets(str, size, in) == NULL) + fprintf(stderr, "\nError in reading or end of file.\n"); +} diff -Nru seabios-1.7.1/scripts/kconfig/confdata.c seabios-1.7.4/scripts/kconfig/confdata.c --- seabios-1.7.1/scripts/kconfig/confdata.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/confdata.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1242 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static void conf_message(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_warnings, conf_unsaved; + +const char conf_defname[] = "arch/$ARCH/defconfig"; + +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + +static void conf_default_message_callback(const char *fmt, va_list ap) +{ + printf("#\n# "); + vprintf(fmt, ap); + printf("\n#\n"); +} + +static void (*conf_message_callback) (const char *fmt, va_list ap) = + conf_default_message_callback; +void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) +{ + conf_message_callback = fn; +} + +static void conf_message(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (conf_message_callback) + conf_message_callback(fmt, ap); +} + +const char *conf_get_configname(void) +{ + char *name = getenv("KCONFIG_CONFIG"); + + return name ? name : ".config"; +} + +const char *conf_get_autoconfig_name(void) +{ + char *name = getenv("KCONFIG_AUTOCONFIG"); + + return name ? name : "include/config/auto.conf"; +} + +static char *conf_expand_value(const char *in) +{ + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; +} + +char *conf_get_default_confname(void) +{ + struct stat buf; + static char fullname[PATH_MAX+1]; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; +} + +static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) +{ + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + /* fall through */ + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + /* fall through */ + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + conf_warning("invalid string found"); + return 1; + } + /* fall through */ + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; +} + +#define LINE_GROWTH 16 +static int add_byte(int c, char **lineptr, size_t slen, size_t *n) +{ + char *nline; + size_t new_size = slen + 1; + if (new_size > *n) { + new_size += LINE_GROWTH - 1; + new_size *= 2; + nline = realloc(*lineptr, new_size); + if (!nline) + return -1; + + *lineptr = nline; + *n = new_size; + } + + (*lineptr)[slen] = c; + + return 0; +} + +static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) +{ + char *line = *lineptr; + size_t slen = 0; + + for (;;) { + int c = getc(stream); + + switch (c) { + case '\n': + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + /* fall through */ + case EOF: + if (add_byte('\0', &line, slen, n) < 0) + goto e_out; + *lineptr = line; + if (slen == 0) + return -1; + return slen; + default: + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + } + } + +e_out: + line[slen-1] = '\0'; + *lineptr = line; + return -1; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char *line = NULL; + size_t line_asize = 0; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + goto load; + sym_add_change_count(1); + if (!sym_defconfig_list) { + if (modules_sym) + sym_calc_value(modules_sym); + return 1; + } + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + conf_message(_("using defaults found in %s"), + name); + goto load; + } + } + } + if (!in) + return 1; + +load: + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + /* fall through */ + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (compat_getline(&line, &line_asize, in) != -1) { + conf_lineno++; + sym = NULL; + if (line[0] == '#') { + if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) + continue; + p = strchr(line + 2 + strlen(CONFIG_), ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2 + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { + p = strchr(line + strlen(CONFIG_), '='); + if (!p) + continue; + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; + } else { + if (line[0] != '\r' && line[0] != '\n') + conf_warning("unexpected data"); + continue; + } +setsym: + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) + conf_warning("override: %s changes choice state", sym->name); + cs->def[def].val = sym; + break; + } + cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); + } + } + free(line); + fclose(in); + + if (modules_sym) + sym_calc_value(modules_sym); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym; + int i; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) + return 1; + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + continue; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + continue; + /* fall through */ + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + continue; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + continue; + conf_unsaved++; + /* maybe print value in verbose mode... */ + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + /* Reset values of generates values, so they'll appear + * as new, if they should become visible, but that + * doesn't quite work if the Kconfig and the saved + * configuration disagree. + */ + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + /* Reset a string value if it's out of range */ + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; +} + +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } +} + +static struct conf_printer kconfig_printer_cb = +{ + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: { + const char *suffix = ""; + + switch (*value) { + case 'n': + fprintf(fp, "#define %s%s%s 0\n", + CONFIG_, sym->name, suffix); + break; + case 'm': + suffix = "_MODULE"; + /* fall through */ + default: + fprintf(fp, "#define %s%s%s 1\n", + CONFIG_, sym->name, suffix); + } + break; + } + case S_HEX: { + const char *prefix = ""; + + if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) + prefix = "0x"; + if (!value[0]) + prefix = "0"; + fprintf(fp, "#define %s%s %s%s\n", + CONFIG_, sym->name, prefix, value); + break; + } + case S_STRING: + case S_INT: + fprintf(fp, "#define %s%s %s\n", + CONFIG_, sym->name, value); + break; + default: + break; + } + +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { + case S_OTHER: + case S_UNKNOWN: + break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); + } +} + +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + +/* + * Write out a minimal config. + * All values that has default values are skipped as this is redundant. + */ +int conf_write_defconfig(const char *filename) +{ + struct symbol *sym; + struct menu *menu; + FILE *out; + + out = fopen(filename, "w"); + if (!out) + return 1; + + sym_clear_all_valid(); + + /* Traverse all menus to find all relevant symbols */ + menu = rootmenu.list; + + while (menu != NULL) + { + sym = menu->sym; + if (sym == NULL) { + if (!menu_is_visible(menu)) + goto next_menu; + } else if (!sym_is_choice(sym)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next_menu; + sym->flags &= ~SYMBOL_WRITE; + /* If we cannot change the symbol - skip */ + if (!sym_is_changable(sym)) + goto next_menu; + /* If symbol equals to default value - skip */ + if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) + goto next_menu; + + /* + * If symbol is a choice value and equals to the + * default for a choice - skip. + * But only if value is bool and equal to "y" and + * choice is not "optional". + * (If choice is "optional" then all values can be "n") + */ + if (sym_is_choice_value(sym)) { + struct symbol *cs; + struct symbol *ds; + + cs = prop_get_symbol(sym_get_choice_prop(sym)); + ds = sym_choice_default(cs); + if (!sym_is_optional(cs) && sym == ds) { + if ((sym->type == S_BOOLEAN) && + sym_get_tristate_value(sym) == yes) + goto next_menu; + } + } + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } +next_menu: + if (menu->list != NULL) { + menu = menu->list; + } + else if (menu->next != NULL) { + menu = menu->next; + } else { + while ((menu = menu->parent)) { + if (menu->next != NULL) { + menu = menu->next; + break; + } + } + } + } + fclose(out); + return 0; +} + +int conf_write(const char *name) +{ + FILE *out; + struct symbol *sym; + struct menu *menu; + const char *basename; + const char *str; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; + char *env; + + dirname[0] = 0; + if (name && name[0]) { + struct stat st; + char *slash; + + if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + strcpy(dirname, name); + strcat(dirname, "/"); + basename = conf_get_configname(); + } else if ((slash = strrchr(name, '/'))) { + int size = slash - name + 1; + memcpy(dirname, name, size); + dirname[size] = 0; + if (slash[1]) + basename = slash + 1; + else + basename = conf_get_configname(); + } else + basename = name; + } else + basename = conf_get_configname(); + + sprintf(newname, "%s%s", dirname, basename); + env = getenv("KCONFIG_OVERWRITECONFIG"); + if (!env || !*env) { + sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(tmpname, "w"); + } else { + *tmpname = 0; + out = fopen(newname, "w"); + } + if (!out) + return 1; + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + if (!conf_get_changed()) + sym_clear_all_valid(); + + menu = rootmenu.list; + while (menu) { + sym = menu->sym; + if (!sym) { + if (!menu_is_visible(menu)) + goto next; + str = menu_get_prompt(menu); + fprintf(out, "\n" + "#\n" + "# %s\n" + "#\n", str); + } else if (!(sym->flags & SYMBOL_CHOICE)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next; + sym->flags &= ~SYMBOL_WRITE; + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } + +next: + if (menu->list) { + menu = menu->list; + continue; + } + if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->next) { + menu = menu->next; + break; + } + } + } + fclose(out); + + if (*tmpname) { + strcat(dirname, basename); + strcat(dirname, ".old"); + rename(newname, dirname); + if (rename(tmpname, newname)) + return 1; + } + + conf_message(_("configuration written to %s"), newname); + + sym_set_change_count(0); + + return 0; +} + +static int conf_split_config(void) +{ + const char *name; + char path[PATH_MAX+1]; + char *s, *d, c; + struct symbol *sym; + struct stat sb; + int res, i, fd; + + name = conf_get_autoconfig_name(); + conf_read_simple(name, S_DEF_AUTO); + + if (chdir("include/config")) + return 1; + + res = 0; + for_all_symbols(i, sym) { + sym_calc_value(sym); + if ((sym->flags & SYMBOL_AUTO) || !sym->name) + continue; + if (sym->flags & SYMBOL_WRITE) { + if (sym->flags & SYMBOL_DEF_AUTO) { + /* + * symbol has old and new value, + * so compare them... + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == + sym->def[S_DEF_AUTO].tri) + continue; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (!strcmp(sym_get_string_value(sym), + sym->def[S_DEF_AUTO].val)) + continue; + break; + default: + break; + } + } else { + /* + * If there is no old value, only 'no' (unset) + * is allowed as new value. + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == no) + continue; + break; + default: + break; + } + } + } else if (!(sym->flags & SYMBOL_DEF_AUTO)) + /* There is neither an old nor a new value. */ + continue; + /* else + * There is an old value, but no new value ('no' (unset) + * isn't saved in auto.conf, so the old value is always + * different from 'no'). + */ + + /* Replace all '_' and append ".h" */ + s = sym->name; + d = path; + while ((c = *s++)) { + c = tolower(c); + *d++ = (c == '_') ? '/' : c; + } + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) { + res = 1; + break; + } + /* + * Create directory components, + * unless they exist already. + */ + d = path; + while ((d = strchr(d, '/'))) { + *d = 0; + if (stat(path, &sb) && mkdir(path, 0755)) { + res = 1; + goto out; + } + *d++ = '/'; + } + /* Try it again. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + res = 1; + break; + } + } + close(fd); + } +out: + if (chdir("../..")) + return 1; + + return res; +} + +int conf_write_autoconf(void) +{ + struct symbol *sym; + const char *name; + FILE *out, *tristate, *out_h; + int i; + + sym_clear_all_valid(); + + file_write_dep("include/config/auto.conf.cmd"); + + if (conf_split_config()) + return 1; + + out = fopen(".tmpconfig", "w"); + if (!out) + return 1; + + tristate = fopen(".tmpconfig_tristate", "w"); + if (!tristate) { + fclose(out); + return 1; + } + + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) { + fclose(out); + fclose(tristate); + return 1; + } + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (!sym->name) + continue; + if (!(sym->flags & SYMBOL_WRITE)) { + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); + continue; + } + + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); + + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); + } + fclose(out); + fclose(tristate); + fclose(out_h); + + name = getenv("KCONFIG_AUTOHEADER"); + if (!name) + name = "include/generated/autoconf.h"; + if (rename(".tmpconfig.h", name)) + return 1; + name = getenv("KCONFIG_TRISTATE"); + if (!name) + name = "include/config/tristate.conf"; + if (rename(".tmpconfig_tristate", name)) + return 1; + name = conf_get_autoconfig_name(); + /* + * This must be the last step, kbuild has a dependency on auto.conf + * and this marks the successful completion of the previous steps. + */ + if (rename(".tmpconfig", name)) + return 1; + + return 0; +} + +static int sym_change_count; +static void (*conf_changed_callback)(void); + +void sym_set_change_count(int count) +{ + int _sym_change_count = sym_change_count; + sym_change_count = count; + if (conf_changed_callback && + (bool)_sym_change_count != (bool)count) + conf_changed_callback(); +} + +void sym_add_change_count(int count) +{ + sym_set_change_count(count + sym_change_count); +} + +bool conf_get_changed(void) +{ + return sym_change_count; +} + +void conf_set_changed_callback(void (*fn)(void)) +{ + conf_changed_callback = fn; +} + +static bool randomize_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + int cnt, def; + + /* + * If choice is mod then we may have more items selected + * and if no then no-one. + * In both cases stop. + */ + if (csym->curr.tri != yes) + return false; + + prop = sym_get_choice_prop(csym); + + /* count entries in choice block */ + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) + cnt++; + + /* + * find a random value and set it to yes, + * set the rest to no so we have only one set + */ + def = (rand() % cnt); + + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) { + if (def == cnt++) { + sym->def[S_DEF_USER].tri = yes; + csym->def[S_DEF_USER].val = sym; + } + else { + sym->def[S_DEF_USER].tri = no; + } + sym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + sym->flags &= ~SYMBOL_VALID; + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); + + return true; +} + +void set_all_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + + prop = sym_get_choice_prop(csym); + + /* + * Set all non-assinged choice values to no + */ + expr_list_for_each_sym(prop->expr, e, sym) { + if (!sym_has_value(sym)) + sym->def[S_DEF_USER].tri = no; + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); +} + +bool conf_set_all_new_symbols(enum conf_def_mode mode) +{ + struct symbol *sym, *csym; + int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y + * pty: probability of tristate = y + * ptm: probability of tristate = m + */ + + pby = 50; pty = ptm = 33; /* can't go as the default in switch-case + * below, otherwise gcc whines about + * -Wmaybe-uninitialized */ + if (mode == def_random) { + int n, p[3]; + char *env = getenv("KCONFIG_PROBABILITY"); + n = 0; + while( env && *env ) { + char *endp; + int tmp = strtol( env, &endp, 10 ); + if( tmp >= 0 && tmp <= 100 ) { + p[n++] = tmp; + } else { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + env = (*endp == ':') ? endp+1 : endp; + if( n >=3 ) { + break; + } + } + switch( n ) { + case 1: + pby = p[0]; ptm = pby/2; pty = pby-ptm; + break; + case 2: + pty = p[0]; ptm = p[1]; pby = pty + ptm; + break; + case 3: + pby = p[0]; pty = p[1]; ptm = p[2]; + break; + } + + if( pty+ptm > 100 ) { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + } + bool has_changed = false; + + for_all_symbols(i, sym) { + if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) + continue; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + has_changed = true; + switch (mode) { + case def_yes: + sym->def[S_DEF_USER].tri = yes; + break; + case def_mod: + sym->def[S_DEF_USER].tri = mod; + break; + case def_no: + sym->def[S_DEF_USER].tri = no; + break; + case def_random: + sym->def[S_DEF_USER].tri = no; + cnt = rand() % 100; + if (sym->type == S_TRISTATE) { + if (cnt < pty) + sym->def[S_DEF_USER].tri = yes; + else if (cnt < (pty+ptm)) + sym->def[S_DEF_USER].tri = mod; + } else if (cnt < pby) + sym->def[S_DEF_USER].tri = yes; + break; + default: + continue; + } + if (!(sym_is_choice(sym) && mode == def_random)) + sym->flags |= SYMBOL_DEF_USER; + break; + default: + break; + } + + } + + sym_clear_all_valid(); + + /* + * We have different type of choice blocks. + * If curr.tri equals to mod then we can select several + * choice symbols in one block. + * In this case we do nothing. + * If curr.tri equals yes then only one symbol can be + * selected in a choice block and we set it to yes, + * and the rest to no. + */ + if (mode != def_random) { + for_all_symbols(i, csym) { + if ((sym_is_choice(csym) && !sym_has_value(csym)) || + sym_is_choice_value(csym)) + csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; + } + } + + for_all_symbols(i, csym) { + if (sym_has_value(csym) || !sym_is_choice(csym)) + continue; + + sym_calc_value(csym); + if (mode == def_random) + has_changed = randomize_choice_values(csym); + else { + set_all_choice_values(csym); + has_changed = true; + } + } + + return has_changed; +} diff -Nru seabios-1.7.1/scripts/kconfig/expr.c seabios-1.7.4/scripts/kconfig/expr.c --- seabios-1.7.1/scripts/kconfig/expr.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/expr.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1168 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#include "lkc.h" + +#define DEBUG_EXPR 0 + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = E_SYMBOL; + e->left.sym = sym; + return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = type; + e->left.expr = ce; + return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = type; + e->left.expr = e1; + e->right.expr = e2; + return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = type; + e->left.sym = s1; + e->right.sym = s2; + return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(const struct expr *org) +{ + struct expr *e; + + if (!org) + return NULL; + + e = xmalloc(sizeof(*org)); + memcpy(e, org, sizeof(*org)); + switch (org->type) { + case E_SYMBOL: + e->left = org->left; + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); + break; + case E_EQUAL: + case E_UNEQUAL: + e->left.sym = org->left.sym; + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_LIST: + e->left.expr = expr_copy(org->left.expr); + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); + free(e); + e = NULL; + break; + } + + return e; +} + +void expr_free(struct expr *e) +{ + if (!e) + return; + + switch (e->type) { + case E_SYMBOL: + break; + case E_NOT: + expr_free(e->left.expr); + return; + case E_EQUAL: + case E_UNEQUAL: + break; + case E_OR: + case E_AND: + expr_free(e->left.expr); + expr_free(e->right.expr); + break; + default: + printf("how to free type %d?\n", e->type); + break; + } + free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ + if (e1->type == type) { + __expr_eliminate_eq(type, &e1->left.expr, &e2); + __expr_eliminate_eq(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + __expr_eliminate_eq(type, &e1, &e2->left.expr); + __expr_eliminate_eq(type, &e1, &e2->right.expr); + return; + } + if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym && + (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + return; + if (!expr_eq(e1, e2)) + return; + trans_count++; + expr_free(e1); expr_free(e2); + switch (type) { + case E_OR: + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + break; + case E_AND: + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + break; + default: + ; + } +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ + if (!e1 || !e2) + return; + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } + e1 = expr_eliminate_yn(e1); + e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +int expr_eq(struct expr *e1, struct expr *e2) +{ + int res, old_count; + + if (e1->type != e2->type) + return 0; + switch (e1->type) { + case E_EQUAL: + case E_UNEQUAL: + return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; + case E_SYMBOL: + return e1->left.sym == e2->left.sym; + case E_NOT: + return expr_eq(e1->left.expr, e2->left.expr); + case E_AND: + case E_OR: + e1 = expr_copy(e1); + e2 = expr_copy(e2); + old_count = trans_count; + expr_eliminate_eq(&e1, &e2); + res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym); + expr_free(e1); + expr_free(e2); + trans_count = old_count; + return res; + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + + if (DEBUG_EXPR) { + expr_fprint(e1, stdout); + printf(" = "); + expr_fprint(e2, stdout); + printf(" ?\n"); + } + + return 0; +} + +struct expr *expr_eliminate_yn(struct expr *e) +{ + struct expr *tmp; + + if (e) switch (e->type) { + case E_AND: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } + } + break; + case E_OR: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + break; + default: + ; + } + return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ + if (!e) + return NULL; + switch (e->type) { + case E_AND: + case E_OR: + case E_NOT: + e->left.expr = expr_trans_bool(e->left.expr); + e->right.expr = expr_trans_bool(e->right.expr); + break; + case E_UNEQUAL: + // FOO!=n -> FOO + if (e->left.sym->type == S_TRISTATE) { + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + } + } + break; + default: + ; + } + return e; +} + +/* + * e1 || e2 -> ? + */ +static struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='m') -> (a!='n') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='n') -> (a!='m') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { + // (a='m') || (a='n') -> (a!='y') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); + } + } + if (sym1->type == S_BOOLEAN && sym1 == sym2) { + if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || + (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) + return expr_alloc_symbol(&symbol_yes); + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") || ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + // (a) && (a='y') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + // (a) && (a!='n') -> (a) + return expr_alloc_symbol(sym1); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + // (a) && (a!='m') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='m') -> (a='n') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + // (a!='m') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp; + + if (e1->type == type) { + expr_eliminate_dups1(type, &e1->left.expr, &e2); + expr_eliminate_dups1(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups1(type, &e1, &e2->left.expr); + expr_eliminate_dups1(type, &e1, &e2->right.expr); + return; + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e1->type, &e1, &e1); + default: + ; + } + + switch (type) { + case E_OR: + tmp = expr_join_or(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_no); + e2 = tmp; + trans_count++; + } + break; + case E_AND: + tmp = expr_join_and(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_yes); + e2 = tmp; + trans_count++; + } + break; + default: + ; + } +#undef e1 +#undef e2 +} + +static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp, *tmp1, *tmp2; + + if (e1->type == type) { + expr_eliminate_dups2(type, &e1->left.expr, &e2); + expr_eliminate_dups2(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups2(type, &e1, &e2->left.expr); + expr_eliminate_dups2(type, &e1, &e2->right.expr); + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO || BAR) && (!FOO && !BAR) -> n + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_and(&tmp1, &tmp2); + if (expr_is_yes(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_no); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + case E_AND: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO && BAR) || (!FOO || !BAR) -> y + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_or(&tmp1, &tmp2); + if (expr_is_no(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_yes); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + default: + ; + } +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ + int oldcount; + if (!e) + return e; + + oldcount = trans_count; + while (1) { + trans_count = 0; + switch (e->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e->type, &e, &e); + expr_eliminate_dups2(e->type, &e, &e); + default: + ; + } + if (!trans_count) + break; + e = expr_eliminate_yn(e); + } + trans_count = oldcount; + return e; +} + +struct expr *expr_transform(struct expr *e) +{ + struct expr *tmp; + + if (!e) + return NULL; + switch (e->type) { + case E_EQUAL: + case E_UNEQUAL: + case E_SYMBOL: + case E_LIST: + break; + default: + e->left.expr = expr_transform(e->left.expr); + e->right.expr = expr_transform(e->right.expr); + } + + switch (e->type) { + case E_EQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + break; + case E_UNEQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + break; + case E_NOT: + switch (e->left.expr->type) { + case E_NOT: + // !!a -> a + tmp = e->left.expr->left.expr; + free(e->left.expr); + free(e); + e = tmp; + e = expr_transform(e); + break; + case E_EQUAL: + case E_UNEQUAL: + // !a='x' -> a!='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; + break; + case E_OR: + // !(a || b) -> !a && !b + tmp = e->left.expr; + e->type = E_AND; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_AND: + // !(a && b) -> !a || !b + tmp = e->left.expr; + e->type = E_OR; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_SYMBOL: + if (e->left.expr->left.sym == &symbol_yes) { + // !'y' -> 'n' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + break; + } + if (e->left.expr->left.sym == &symbol_mod) { + // !'m' -> 'm' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_mod; + break; + } + if (e->left.expr->left.sym == &symbol_no) { + // !'n' -> 'y' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + break; + } + break; + default: + ; + } + break; + default: + ; + } + return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return 0; + + switch (dep->type) { + case E_AND: + case E_OR: + return expr_contains_symbol(dep->left.expr, sym) || + expr_contains_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + case E_UNEQUAL: + return dep->left.sym == sym || + dep->right.sym == sym; + case E_NOT: + return expr_contains_symbol(dep->left.expr, sym); + default: + ; + } + return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return false; + + switch (dep->type) { + case E_AND: + return expr_depends_symbol(dep->left.expr, sym) || + expr_depends_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) + return true; + } + break; + case E_UNEQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_no) + return true; + } + break; + default: + ; + } + return false; +} + +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_AND, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_OR, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + if (e1->type == type) { + expr_extract_eq(type, ep, &e1->left.expr, &e2); + expr_extract_eq(type, ep, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_extract_eq(type, ep, ep1, &e2->left.expr); + expr_extract_eq(type, ep, ep1, &e2->right.expr); + return; + } + if (expr_eq(e1, e2)) { + *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; + expr_free(e2); + if (type == E_AND) { + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + } else if (type == E_OR) { + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + } + } +#undef e1 +#undef e2 +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ + struct expr *e1, *e2; + + if (!e) { + e = expr_alloc_symbol(sym); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + } + switch (e->type) { + case E_AND: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_AND, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_OR, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_OR: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_OR, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_AND, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_NOT: + return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); + case E_UNEQUAL: + case E_EQUAL: + if (type == E_EQUAL) { + if (sym == &symbol_yes) + return expr_copy(e); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_no); + if (sym == &symbol_no) + return expr_alloc_one(E_NOT, expr_copy(e)); + } else { + if (sym == &symbol_yes) + return expr_alloc_one(E_NOT, expr_copy(e)); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_yes); + if (sym == &symbol_no) + return expr_copy(e); + } + break; + case E_SYMBOL: + return expr_alloc_comp(type, e->left.sym, sym); + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + return NULL; +} + +tristate expr_calc_value(struct expr *e) +{ + tristate val1, val2; + const char *str1, *str2; + + if (!e) + return yes; + + switch (e->type) { + case E_SYMBOL: + sym_calc_value(e->left.sym); + return e->left.sym->curr.tri; + case E_AND: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_AND(val1, val2); + case E_OR: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_OR(val1, val2); + case E_NOT: + val1 = expr_calc_value(e->left.expr); + return EXPR_NOT(val1); + case E_EQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? yes : no; + case E_UNEQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? no : yes; + default: + printf("expr_calc_value: %d?\n", e->type); + return no; + } +} + +int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ +#if 0 + return 1; +#else + if (t1 == t2) + return 0; + switch (t1) { + case E_EQUAL: + case E_UNEQUAL: + if (t2 == E_NOT) + return 1; + case E_NOT: + if (t2 == E_AND) + return 1; + case E_AND: + if (t2 == E_OR) + return 1; + case E_OR: + if (t2 == E_LIST) + return 1; + case E_LIST: + if (t2 == 0) + return 1; + default: + return -1; + } + printf("[%dgt%d?]", t1, t2); + return 0; +#endif +} + +static inline struct expr * +expr_get_leftmost_symbol(const struct expr *e) +{ + + if (e == NULL) + return NULL; + + while (e->type != E_SYMBOL) + e = e->left.expr; + + return expr_copy(e); +} + +/* + * Given expression `e1' and `e2', returns the leaf of the longest + * sub-expression of `e1' not containing 'e2. + */ +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) +{ + struct expr *ret; + + switch (e1->type) { + case E_OR: + return expr_alloc_and( + expr_simplify_unmet_dep(e1->left.expr, e2), + expr_simplify_unmet_dep(e1->right.expr, e2)); + case E_AND: { + struct expr *e; + e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); + e = expr_eliminate_dups(e); + ret = (!expr_eq(e, e1)) ? e1 : NULL; + expr_free(e); + break; + } + default: + ret = e1; + break; + } + + return expr_get_leftmost_symbol(ret); +} + +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +{ + if (!e) { + fn(data, NULL, "y"); + return; + } + + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, "("); + switch (e->type) { + case E_SYMBOL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + break; + case E_NOT: + fn(data, NULL, "!"); + expr_print(e->left.expr, fn, data, E_NOT); + break; + case E_EQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_UNEQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "!="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_OR: + expr_print(e->left.expr, fn, data, E_OR); + fn(data, NULL, " || "); + expr_print(e->right.expr, fn, data, E_OR); + break; + case E_AND: + expr_print(e->left.expr, fn, data, E_AND); + fn(data, NULL, " && "); + expr_print(e->right.expr, fn, data, E_AND); + break; + case E_LIST: + fn(data, e->right.sym, e->right.sym->name); + if (e->left.expr) { + fn(data, NULL, " ^ "); + expr_print(e->left.expr, fn, data, E_LIST); + } + break; + case E_RANGE: + fn(data, NULL, "["); + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, " "); + fn(data, e->right.sym, e->right.sym->name); + fn(data, NULL, "]"); + break; + default: + { + char buf[32]; + sprintf(buf, "", e->type); + fn(data, NULL, buf); + break; + } + } + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, ")"); +} + +static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +{ + xfwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ + expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +{ + struct gstr *gs = (struct gstr*)data; + const char *sym_str = NULL; + + if (sym) + sym_str = sym_get_string_value(sym); + + if (gs->max_width) { + unsigned extra_length = strlen(str); + const char *last_cr = strrchr(gs->s, '\n'); + unsigned last_line_length; + + if (sym_str) + extra_length += 4 + strlen(sym_str); + + if (!last_cr) + last_cr = gs->s; + + last_line_length = strlen(gs->s) - (last_cr - gs->s); + + if ((last_line_length + extra_length) > gs->max_width) + str_append(gs, "\\\n"); + } + + str_append(gs, str); + if (sym && sym->type != S_UNKNOWN) + str_printf(gs, " [=%s]", sym_str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ + expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff -Nru seabios-1.7.1/scripts/kconfig/expr.h seabios-1.7.4/scripts/kconfig/expr.h --- seabios-1.7.1/scripts/kconfig/expr.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/expr.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "list.h" +#ifndef __cplusplus +#include +#endif + +struct file { + struct file *next; + struct file *parent; + const char *name; + int lineno; +}; + +typedef enum tristate { + no, mod, yes +} tristate; + +enum expr_type { + E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE +}; + +union expr_data { + struct expr *expr; + struct symbol *sym; +}; + +struct expr { + enum expr_type type; + union expr_data left, right; +}; + +#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) +#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) +#define EXPR_NOT(dep) (2-(dep)) + +#define expr_list_for_each_sym(l, e, s) \ + for (e = (l); e && (s = e->right.sym); e = e->left.expr) + +struct expr_value { + struct expr *expr; + tristate tri; +}; + +struct symbol_value { + void *val; + tristate tri; +}; + +enum symbol_type { + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +/* enum values are used as index to symbol.def[] */ +enum { + S_DEF_USER, /* main user value */ + S_DEF_AUTO, /* values read from auto.conf */ + S_DEF_DEF3, /* Reserved for UI usage */ + S_DEF_DEF4, /* Reserved for UI usage */ + S_DEF_COUNT +}; + +struct symbol { + struct symbol *next; + char *name; + enum symbol_type type; + struct symbol_value curr; + struct symbol_value def[S_DEF_COUNT]; + tristate visible; + int flags; + struct property *prop; + struct expr_value dir_dep; + struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_CONST 0x0001 /* symbol is const */ +#define SYMBOL_CHECK 0x0008 /* used during dependency checking */ +#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ +#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ +#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ +#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ +#define SYMBOL_WRITE 0x0200 /* ? */ +#define SYMBOL_CHANGED 0x0400 /* ? */ +#define SYMBOL_AUTO 0x1000 /* value from environment variable */ +#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ +#define SYMBOL_WARNED 0x8000 /* warning has been issued */ + +/* Set when symbol.def[] is used */ +#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ +#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ +#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ +#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ +#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ + +/* choice values need to be set before calculating this symbol value */ +#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000 + +#define SYMBOL_MAXLENGTH 256 +#define SYMBOL_HASHSIZE 9973 + +/* A property represent the config options that can be associated + * with a config "symbol". + * Sample: + * config FOO + * default y + * prompt "foo prompt" + * select BAR + * config BAZ + * int "BAZ Value" + * range 1..255 + */ +enum prop_type { + P_UNKNOWN, + P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ + P_COMMENT, /* text associated with a comment */ + P_MENU, /* prompt associated with a menuconfig option */ + P_DEFAULT, /* default y */ + P_CHOICE, /* choice value */ + P_SELECT, /* select BAR */ + P_RANGE, /* range 7..100 (for a symbol) */ + P_ENV, /* value from environment variable */ + P_SYMBOL, /* where a symbol is defined */ +}; + +struct property { + struct property *next; /* next property - null if last */ + struct symbol *sym; /* the symbol for which the property is associated */ + enum prop_type type; /* type of property */ + const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ + struct expr_value visible; + struct expr *expr; /* the optional conditional part of the property */ + struct menu *menu; /* the menu the property are associated with + * valid for: P_SELECT, P_RANGE, P_CHOICE, + * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ + struct file *file; /* what file was this property defined */ + int lineno; /* what lineno was this property defined */ +}; + +#define for_all_properties(sym, st, tok) \ + for (st = sym->prop; st; st = st->next) \ + if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) + +struct menu { + struct menu *next; + struct menu *parent; + struct menu *list; + struct symbol *sym; + struct property *prompt; + struct expr *visibility; + struct expr *dep; + unsigned int flags; + char *help; + struct file *file; + int lineno; + void *data; +}; + +#define MENU_CHANGED 0x0001 +#define MENU_ROOT 0x0002 + +struct jump_key { + struct list_head entries; + size_t offset; + struct menu *target; + int index; +}; + +#define JUMP_NB 9 + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern struct symbol *sym_defconfig_list; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(const struct expr *org); +void expr_free(struct expr *e); +int expr_eq(struct expr *e1, struct expr *e2); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_eliminate_yn(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ + return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ + return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff -Nru seabios-1.7.1/scripts/kconfig/gconf.c seabios-1.7.4/scripts/kconfig/gconf.c --- seabios-1.7.1/scripts/kconfig/gconf.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/gconf.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1542 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include "lkc.h" +#include "images.c" + +#include +#include +#include +#include + +#include +#include +#include +#include + +//#define DEBUG + +enum { + SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +enum { + OPT_NORMAL, OPT_ALL, OPT_PROMPT +}; + +static gint view_mode = FULL_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean resizeable = FALSE; +static int opt_mode = OPT_NORMAL; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL; // left frame +GtkWidget *tree2_w = NULL; // right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; +GtkWidget *save_btn = NULL; +GtkWidget *save_menu_item = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256]; +static gint indent; + +static struct menu *current; // current node for SINGLE view +static struct menu *browsed; // browsed node for SPLIT view + +enum { + COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, + COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, + COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); +static void conf_changed(void); + +/* Helping/Debugging Functions */ + +const char *dbg_sym_flags(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val & SYMBOL_CONST) + strcat(buf, "const/"); + if (val & SYMBOL_CHECK) + strcat(buf, "check/"); + if (val & SYMBOL_CHOICE) + strcat(buf, "choice/"); + if (val & SYMBOL_CHOICEVAL) + strcat(buf, "choiceval/"); + if (val & SYMBOL_VALID) + strcat(buf, "valid/"); + if (val & SYMBOL_OPTIONAL) + strcat(buf, "optional/"); + if (val & SYMBOL_WRITE) + strcat(buf, "write/"); + if (val & SYMBOL_CHANGED) + strcat(buf, "changed/"); + if (val & SYMBOL_AUTO) + strcat(buf, "auto/"); + + buf[strlen(buf) - 1] = '\0'; + + return buf; +} + +void replace_button_icon(GladeXML * xml, GdkDrawable * window, + GtkStyle * style, gchar * btn_name, gchar ** xpm) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkToolButton *button; + GtkWidget *image; + + pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, + &style->bg[GTK_STATE_NORMAL], + xpm); + + button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); + image = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(image); + gtk_tool_button_set_icon_widget(button, image); +} + +/* Main Window Initialization */ +void init_main_window(const gchar * glade_file) +{ + GladeXML *xml; + GtkWidget *widget; + GtkTextBuffer *txtbuf; + GtkStyle *style; + + xml = glade_xml_new(glade_file, "window1", NULL); + if (!xml) + g_error(_("GUI loading failed !\n")); + glade_xml_signal_autoconnect(xml); + + main_wnd = glade_xml_get_widget(xml, "window1"); + hpaned = glade_xml_get_widget(xml, "hpaned1"); + vpaned = glade_xml_get_widget(xml, "vpaned1"); + tree1_w = glade_xml_get_widget(xml, "treeview1"); + tree2_w = glade_xml_get_widget(xml, "treeview2"); + text_w = glade_xml_get_widget(xml, "textview3"); + + back_btn = glade_xml_get_widget(xml, "button1"); + gtk_widget_set_sensitive(back_btn, FALSE); + + widget = glade_xml_get_widget(xml, "show_name1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_name); + + widget = glade_xml_get_widget(xml, "show_range1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_range); + + widget = glade_xml_get_widget(xml, "show_data1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_value); + + save_btn = glade_xml_get_widget(xml, "button3"); + save_menu_item = glade_xml_get_widget(xml, "save1"); + conf_set_changed_callback(conf_changed); + + style = gtk_widget_get_style(main_wnd); + widget = glade_xml_get_widget(xml, "toolbar1"); + +#if 0 /* Use stock Gtk icons instead */ + replace_button_icon(xml, main_wnd->window, style, + "button1", (gchar **) xpm_back); + replace_button_icon(xml, main_wnd->window, style, + "button2", (gchar **) xpm_load); + replace_button_icon(xml, main_wnd->window, style, + "button3", (gchar **) xpm_save); +#endif + replace_button_icon(xml, main_wnd->window, style, + "button4", (gchar **) xpm_single_view); + replace_button_icon(xml, main_wnd->window, style, + "button5", (gchar **) xpm_split_view); + replace_button_icon(xml, main_wnd->window, style, + "button6", (gchar **) xpm_tree_view); + +#if 0 + switch (view_mode) { + case SINGLE_VIEW: + widget = glade_xml_get_widget(xml, "button4"); + g_signal_emit_by_name(widget, "clicked"); + break; + case SPLIT_VIEW: + widget = glade_xml_get_widget(xml, "button5"); + g_signal_emit_by_name(widget, "clicked"); + break; + case FULL_VIEW: + widget = glade_xml_get_widget(xml, "button6"); + g_signal_emit_by_name(widget, "clicked"); + break; + } +#endif + txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", + "foreground", "red", + "weight", PANGO_WEIGHT_BOLD, + NULL); + tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", + /*"style", PANGO_STYLE_OBLIQUE, */ + NULL); + + gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text); + + gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ + gint i; + + tree = tree2 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model2 = GTK_TREE_MODEL(tree2); + + for (parents[0] = NULL, i = 1; i < 256; i++) + parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + + tree1 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree1_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + + gtk_tree_view_set_model(view, model1); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data); + +void init_right_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree2_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + gint i; + + gtk_tree_view_set_model(view, model2); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "pixbuf", COL_PIXBUF, + "visible", COL_PIXVIS, NULL); + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Name"), renderer, + "text", COL_NAME, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "N", renderer, + "text", COL_NO, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "M", renderer, + "text", COL_MOD, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Y", renderer, + "text", COL_YES, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Value"), renderer, + "text", COL_VALUE, + "editable", + COL_EDIT, + "foreground-gdk", + COL_COLOR, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(renderer_edited), NULL); + + column = gtk_tree_view_get_column(view, COL_NAME); + gtk_tree_view_column_set_visible(column, show_name); + column = gtk_tree_view_get_column(view, COL_NO); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_MOD); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_YES); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_VALUE); + gtk_tree_view_column_set_visible(column, show_value); + + if (resizeable) { + for (i = 0; i < COL_VALUE; i++) { + column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_resizable(column, TRUE); + } + } + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *prompt = _(menu_get_prompt(menu)); + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2, + NULL); + str_free(&help); +} + + +static void text_insert_msg(const char *title, const char *message) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *msg = message; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, + NULL); +} + + +/* Main Windows Callbacks */ + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GtkWidget *dialog, *label; + gint result; + + if (!conf_get_changed()) + return FALSE; + + dialog = gtk_dialog_new_with_buttons(_("Warning !"), + GTK_WINDOW(main_wnd), + (GtkDialogFlags) + (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, + GTK_RESPONSE_YES, + GTK_STOCK_NO, + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), + GTK_RESPONSE_CANCEL); + + label = gtk_label_new(_("\nSave configuration ?\n")); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_widget_show(label); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + switch (result) { + case GTK_RESPONSE_YES: + on_save_activate(NULL, NULL); + return FALSE; + case GTK_RESPONSE_NO: + return FALSE; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + default: + gtk_widget_destroy(dialog); + return TRUE; + } + + return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, + GtkRequisition * requisition, gpointer user_data) +{ + static gint old_h; + gint w, h; + + if (widget->window == NULL) + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + else + gdk_window_get_size(widget->window, &w, &h); + + if (h == old_h) + return; + old_h = h; + + gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_read(fn)) + text_insert_msg(_("Error"), _("Unable to load configuration !")); + else + display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Load file...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(load_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (conf_write(NULL)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_write(fn)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); + + gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Save file as...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(store_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (!on_window1_delete_event(NULL, NULL, NULL)) + gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); + if (col) + gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); + if (col) + gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_NORMAL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_ALL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_PROMPT; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *intro_text = _( + "Welcome to gkc, the GTK+ graphical configuration tool\n" + "For each option, a blank box indicates the feature is disabled, a\n" + "check indicates it is enabled, and a dot indicates that it is to\n" + "be compiled as a module. Clicking on the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you\n" + "believe should be present, try turning on Show All Options\n" + "under the Options menu.\n" + "Although there is no cross reference yet to help you figure out\n" + "what other options must be enabled to support the option you\n" + "are interested in, you can still view the help of a grayed-out\n" + "option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show \n" + "the dependencies, which you can then match by examining other options."); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", intro_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *about_text = + _("gkc is copyright (c) 2002 Romain Lievin .\n" + "Based on the source code from Roman Zippel.\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", about_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *license_text = + _("gkc is released under the terms of the GNU GPL v2.\n" + "For more information, please see the source code or\n" + "visit http://www.fsf.org/licenses/licenses.html\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", license_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_back_clicked(GtkButton * button, gpointer user_data) +{ + enum prop_type ptype; + + current = current->parent; + ptype = current->prompt ? current->prompt->type : P_UNKNOWN; + if (ptype != P_MENU) + current = current->parent; + display_tree_part(); + + if (current == &rootmenu) + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_clicked(GtkButton * button, gpointer user_data) +{ + on_load1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = SINGLE_VIEW; + gtk_widget_hide(tree1_w); + current = &rootmenu; + display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ + gint w, h; + view_mode = SPLIT_VIEW; + gtk_widget_show(tree1_w); + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + gtk_paned_set_position(GTK_PANED(hpaned), w / 2); + if (tree2) + gtk_tree_store_clear(tree2); + display_list(); + + /* Disable back btn, like in full mode. */ + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = FULL_VIEW; + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + const char *old_def, *new_def; + struct menu *menu; + struct symbol *sym; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + sym = menu->sym; + + gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); + new_def = new_text; + + sym_set_string_value(sym, new_def); + + update_tree(&rootmenu, NULL); + + gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ + struct symbol *sym = menu->sym; + tristate newval; + + if (!sym) + return; + + if (col == COL_NO) + newval = no; + else if (col == COL_MOD) + newval = mod; + else if (col == COL_YES) + newval = yes; + else + return; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (!sym_tristate_within_range(sym, newval)) + newval = yes; + sym_set_tristate_value(sym, newval); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll + break; + case S_INT: + case S_HEX: + case S_STRING: + default: + break; + } +} + +static void toggle_sym_value(struct menu *menu) +{ + if (!menu->sym) + return; + + sym_toggle_tristate_value(menu->sym); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll +} + +static gint column2index(GtkTreeViewColumn * column) +{ + gint i; + + for (i = 0; i < COL_NUMBER; i++) { + GtkTreeViewColumn *col; + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); + if (col == column) + return i; + } + + return -1; +} + + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + +#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); +#else + gtk_tree_view_get_cursor(view, &path, &column); +#endif + if (path == NULL) + return FALSE; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return FALSE; + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + col = column2index(column); + if (event->type == GDK_2BUTTON_PRESS) { + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + + if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { + // goes down into menu + current = menu; + display_tree_part(); + gtk_widget_set_sensitive(back_btn, TRUE); + } else if ((col == COL_OPTION)) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } + } else { + if (col == COL_VALUE) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } else if (col == COL_NO || col == COL_MOD + || col == COL_YES) { + change_sym_value(menu, col); + gtk_tree_view_expand_row(view, path, TRUE); + } + } + + return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, + GdkEventKey * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + + gtk_tree_view_get_cursor(view, &path, &column); + if (path == NULL) + return FALSE; + + if (event->keyval == GDK_space) { + if (gtk_tree_view_row_expanded(view, path)) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); + return TRUE; + } + if (event->keyval == GDK_KP_Enter) { + } + if (widget == tree1_w) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + if (!strcasecmp(event->string, "n")) + col = COL_NO; + else if (!strcasecmp(event->string, "m")) + col = COL_MOD; + else if (!strcasecmp(event->string, "y")) + col = COL_YES; + else + col = -1; + change_sym_value(menu, col); + + return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + struct menu *menu; + + selection = gtk_tree_view_get_selection(treeview); + if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + text_insert_help(menu); + } +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model1, &iter, path); + gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + + if (event->type == GDK_2BUTTON_PRESS) { + toggle_sym_value(menu); + current = menu; + display_tree_part(); + } else { + browsed = menu; + display_tree_part(); + } + + gtk_widget_realize(tree2_w); + gtk_tree_view_set_cursor(view, path, NULL, FALSE); + gtk_widget_grab_focus(tree2_w); + + return FALSE; +} + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ + static gchar *row[COL_NUMBER]; + struct symbol *sym = menu->sym; + const char *def; + int stype; + tristate val; + enum prop_type ptype; + int i; + + for (i = COL_OPTION; i <= COL_COLOR; i++) + g_free(row[i]); + bzero(row, sizeof(row)); + + row[COL_OPTION] = + g_strdup_printf("%s %s", _(menu_get_prompt(menu)), + sym && !sym_has_value(sym) ? "(NEW)" : ""); + + if (opt_mode == OPT_ALL && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else if (opt_mode == OPT_PROMPT && + menu_has_prompt(menu) && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else + row[COL_COLOR] = g_strdup("Black"); + + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + row[COL_PIXBUF] = (gchar *) xpm_menu; + if (view_mode == SINGLE_VIEW) + row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + case P_COMMENT: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + default: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + break; + } + + if (!sym) + return row; + row[COL_NAME] = g_strdup(sym->name); + + sym_calc_value(sym); + sym->flags &= ~SYMBOL_CHANGED; + + if (sym_is_choice(sym)) { // parse childs for getting final value + struct menu *child; + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) + && child->sym == def_sym) + def_menu = child; + } + + if (def_menu) + row[COL_VALUE] = + g_strdup(_(menu_get_prompt(def_menu))); + } + if (sym->flags & SYMBOL_CHOICEVAL) + row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + if (sym_is_choice(sym)) + break; + /* fall through */ + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + row[COL_NO] = g_strdup("N"); + row[COL_VALUE] = g_strdup("N"); + row[COL_BTNACT] = GINT_TO_POINTER(FALSE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + case mod: + row[COL_MOD] = g_strdup("M"); + row[COL_VALUE] = g_strdup("M"); + row[COL_BTNINC] = GINT_TO_POINTER(TRUE); + break; + case yes: + row[COL_YES] = g_strdup("Y"); + row[COL_VALUE] = g_strdup("Y"); + row[COL_BTNACT] = GINT_TO_POINTER(TRUE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + } + + if (val != no && sym_tristate_within_range(sym, no)) + row[COL_NO] = g_strdup("_"); + if (val != mod && sym_tristate_within_range(sym, mod)) + row[COL_MOD] = g_strdup("_"); + if (val != yes && sym_tristate_within_range(sym, yes)) + row[COL_YES] = g_strdup("_"); + break; + case S_INT: + case S_HEX: + case S_STRING: + def = sym_get_string_value(sym); + row[COL_VALUE] = g_strdup(def); + row[COL_EDIT] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + } + + return row; +} + + +/* Set the node content with a row of strings */ +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ + GdkColor color; + gboolean success; + GdkPixbuf *pix; + + pix = gdk_pixbuf_new_from_xpm_data((const char **) + row[COL_PIXBUF]); + + gdk_color_parse(row[COL_COLOR], &color); + gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, + FALSE, FALSE, &success); + + gtk_tree_store_set(tree, node, + COL_OPTION, row[COL_OPTION], + COL_NAME, row[COL_NAME], + COL_NO, row[COL_NO], + COL_MOD, row[COL_MOD], + COL_YES, row[COL_YES], + COL_VALUE, row[COL_VALUE], + COL_MENU, (gpointer) menu, + COL_COLOR, &color, + COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), + COL_PIXBUF, pix, + COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), + COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), + COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), + COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), + -1); + + g_object_unref(pix); +} + + +/* Add a node to the tree */ +static void place_node(struct menu *menu, char **row) +{ + GtkTreeIter *parent = parents[indent - 1]; + GtkTreeIter *node = parents[indent]; + + gtk_tree_store_append(tree, node, parent); + set_node(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, + struct menu *tofind) +{ + GtkTreeIter iter; + GtkTreeIter *child = &iter; + gboolean valid; + GtkTreeIter *ret; + + valid = gtk_tree_model_iter_children(model2, child, parent); + while (valid) { + struct menu *menu; + + gtk_tree_model_get(model2, child, 6, &menu, -1); + + if (menu == tofind) { + memcpy(&found, child, sizeof(GtkTreeIter)); + return &found; + } + + ret = gtktree_iter_find_node(child, tofind); + if (ret) + return ret; + + valid = gtk_tree_model_iter_next(model2, child); + } + + return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ + struct menu *child1; + GtkTreeIter iter, tmp; + GtkTreeIter *child2 = &iter; + gboolean valid; + GtkTreeIter *sibling; + struct symbol *sym; + struct menu *menu1, *menu2; + + if (src == &rootmenu) + indent = 1; + + valid = gtk_tree_model_iter_children(model2, child2, dst); + for (child1 = src->list; child1; child1 = child1->next) { + + sym = child1->sym; + + reparse: + menu1 = child1; + if (valid) + gtk_tree_model_get(model2, child2, COL_MENU, + &menu2, -1); + else + menu2 = NULL; // force adding of a first child + +#ifdef DEBUG + printf("%*c%s | %s\n", indent, ' ', + menu1 ? menu_get_prompt(menu1) : "nil", + menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + + if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || + (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) || + (opt_mode == OPT_ALL && !menu_get_prompt(child1))) { + + /* remove node */ + if (gtktree_iter_find_node(dst, menu1) != NULL) { + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; /* next parent */ + else + goto reparse; /* next child */ + } else + continue; + } + + if (menu1 != menu2) { + if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node + if (!valid && !menu2) + sibling = NULL; + else + sibling = child2; + gtk_tree_store_insert_before(tree2, + child2, + dst, sibling); + set_node(child2, menu1, fill_row(menu1)); + if (menu2 == NULL) + valid = TRUE; + } else { // remove node + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } + } else if (sym && (sym->flags & SYMBOL_CHANGED)) { + set_node(child2, menu1, fill_row(menu1)); + } + + indent++; + update_tree(child1, child2); + indent--; + + valid = gtk_tree_model_iter_next(model2, child2); + } +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + enum prop_type ptype; + + if (menu == &rootmenu) { + indent = 1; + current = &rootmenu; + } + + for (child = menu->list; child; child = child->next) { + prop = child->prompt; + sym = child->sym; + ptype = prop ? prop->type : P_UNKNOWN; + + if (sym) + sym->flags &= ~SYMBOL_CHANGED; + + if ((view_mode == SPLIT_VIEW) + && !(child->flags & MENU_ROOT) && (tree == tree1)) + continue; + + if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) + && (tree == tree2)) + continue; + + if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || + (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || + (opt_mode == OPT_ALL && menu_get_prompt(child))) + place_node(child, fill_row(child)); +#ifdef DEBUG + printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); + printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); + printf("%s", prop_get_type_name(ptype)); + printf(" | "); + if (sym) { + printf("%s", sym_type_name(sym->type)); + printf(" | "); + printf("%s", dbg_sym_flags(sym->flags)); + printf("\n"); + } else + printf("\n"); +#endif + if ((view_mode != FULL_VIEW) && (ptype == P_MENU) + && (tree == tree2)) + continue; +/* + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW))*/ + + /* Change paned position if the view is not in 'split mode' */ + if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) { + gtk_paned_set_position(GTK_PANED(hpaned), 0); + } + + if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { + indent++; + display_tree(child); + indent--; + } + } +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ + if (tree2) + gtk_tree_store_clear(tree2); + if (view_mode == SINGLE_VIEW) + display_tree(current); + else if (view_mode == SPLIT_VIEW) + display_tree(browsed); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ + if (tree1) + gtk_tree_store_clear(tree1); + + tree = tree1; + display_tree(&rootmenu); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); + tree = tree2; +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + + +/* Main */ +int main(int ac, char *av[]) +{ + const char *name; + char *env; + gchar *glade_file; + + bindtextdomain(PACKAGE, LOCALEDIR); + bind_textdomain_codeset(PACKAGE, "UTF-8"); + textdomain(PACKAGE); + + /* GTK stuffs */ + gtk_set_locale(); + gtk_init(&ac, &av); + glade_init(); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + + /* Determine GUI path */ + env = getenv(SRCTREE); + if (env) + glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL); + else if (av[0][0] == '/') + glade_file = g_strconcat(av[0], ".glade", NULL); + else + glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); + + /* Conf stuffs */ + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'a': + //showAll = 1; + break; + case 'h': + case '?': + printf("%s \n", av[0]); + exit(0); + } + name = av[2]; + } else + name = av[1]; + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + + /* Load the interface and connect signals */ + init_main_window(glade_file); + init_tree_model(); + init_left_tree(); + init_right_tree(); + + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); + break; + case SPLIT_VIEW: + display_list(); + break; + case FULL_VIEW: + display_tree(&rootmenu); + break; + } + + gtk_main(); + + return 0; +} + +static void conf_changed(void) +{ + bool changed = conf_get_changed(); + gtk_widget_set_sensitive(save_btn, changed); + gtk_widget_set_sensitive(save_menu_item, changed); +} diff -Nru seabios-1.7.1/scripts/kconfig/gconf.glade seabios-1.7.4/scripts/kconfig/gconf.glade --- seabios-1.7.1/scripts/kconfig/gconf.glade 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/gconf.glade 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,661 @@ + + + + + + True + Gtk Kernel Configurator + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 640 + 480 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + Load a config file + _Load + True + + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in .config + _Save + True + + + + + + True + gtk-save + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in a file + Save _as + True + + + + + True + gtk-save-as + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + _Quit + True + + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Options + True + + + + + + + True + Show name + Show _name + True + False + + + + + + + True + Show range (Y/M/N) + Show _range + True + False + + + + + + + True + Show value of the option + Show _data + True + False + + + + + + + True + + + + + + True + Show normal options + Show normal options + True + True + + + + + + + True + Show all options + Show all _options + True + False + set_option_mode1 + + + + + + + True + Show all options with prompts + Show all prompt options + True + False + set_option_mode1 + + + + + + + + + + + + True + _Help + True + + + + + + + True + _Introduction + True + + + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _About + True + + + + + + True + gtk-properties + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _License + True + + + + + True + gtk-justify-fill + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_BOTH + True + True + + + + True + Goes up of one level (single view) + Back + True + gtk-undo + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Load a config file + Load + True + gtk-open + True + True + False + + + + False + True + + + + + + True + Save a config file + Save + True + gtk-save + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Single view + Single + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Split view + Split + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Full view + Full + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Collapse the whole tree in the right frame + Collapse + True + gtk-remove + True + True + False + + + + False + True + + + + + + True + Expand the whole tree in the right frame + Expand + True + gtk-add + True + True + False + + + + False + True + + + + + + + 0 + False + False + + + + + + 1 + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + Sorry, no help available for this option yet. + + + + + True + True + + + + + True + True + + + + + 0 + True + True + + + + + + + diff -Nru seabios-1.7.1/scripts/kconfig/.gitignore seabios-1.7.4/scripts/kconfig/.gitignore --- seabios-1.7.1/scripts/kconfig/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/.gitignore 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,22 @@ +# +# Generated files +# +config* +*.lex.c +*.tab.c +*.tab.h +zconf.hash.c +*.moc +gconf.glade.h +*.pot +*.mo + +# +# configuration programs +# +conf +mconf +nconf +qconf +gconf +kxgettext diff -Nru seabios-1.7.1/scripts/kconfig/images.c seabios-1.7.4/scripts/kconfig/images.c --- seabios-1.7.1/scripts/kconfig/images.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/images.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +static const char *xpm_load[] = { +"22 22 5 1", +". c None", +"# c #000000", +"c c #838100", +"a c #ffff00", +"b c #ffffff", +"......................", +"......................", +"......................", +"............####....#.", +"...........#....##.##.", +"..................###.", +".................####.", +".####...........#####.", +"#abab##########.......", +"#babababababab#.......", +"#ababababababa#.......", +"#babababababab#.......", +"#ababab###############", +"#babab##cccccccccccc##", +"#abab##cccccccccccc##.", +"#bab##cccccccccccc##..", +"#ab##cccccccccccc##...", +"#b##cccccccccccc##....", +"###cccccccccccc##.....", +"##cccccccccccc##......", +"###############.......", +"......................"}; + +static const char *xpm_save[] = { +"22 22 5 1", +". c None", +"# c #000000", +"a c #838100", +"b c #c5c2c5", +"c c #cdb6d5", +"......................", +".####################.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbcbb####.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aaa############aaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaa#############aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +"..##################..", +"......................"}; + +static const char *xpm_back[] = { +"22 22 3 1", +". c None", +"# c #000083", +"a c #838183", +"......................", +"......................", +"......................", +"......................", +"......................", +"...........######a....", +"..#......##########...", +"..##...####......##a..", +"..###.###.........##..", +"..######..........##..", +"..#####...........##..", +"..######..........##..", +"..#######.........##..", +"..########.......##a..", +"...............a###...", +"...............###....", +"......................", +"......................", +"......................", +"......................", +"......................", +"......................"}; + +static const char *xpm_tree_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......................", +"......................"}; + +static const char *xpm_single_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"......................", +"......................"}; + +static const char *xpm_split_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......................", +"......................"}; + +static const char *xpm_symbol_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_mod[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . . ", +" . .. . ", +" . . .. . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_choice_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_choice_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_menu[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_menu_inv[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" .......... ", +" .. ...... ", +" .. .... ", +" .. .. ", +" .. .. ", +" .. .... ", +" .. ...... ", +" .......... ", +" .......... ", +" "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_void[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff -Nru seabios-1.7.1/scripts/kconfig/kxgettext.c seabios-1.7.4/scripts/kconfig/kxgettext.c --- seabios-1.7.1/scripts/kconfig/kxgettext.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/kxgettext.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,235 @@ +/* + * Arnaldo Carvalho de Melo , 2005 + * + * Released under the terms of the GNU GPL v2.0 + */ + +#include +#include + +#include "lkc.h" + +static char *escape(const char* text, char *bf, int len) +{ + char *bfp = bf; + int multiline = strchr(text, '\n') != NULL; + int eol = 0; + int textlen = strlen(text); + + if ((textlen > 0) && (text[textlen-1] == '\n')) + eol = 1; + + *bfp++ = '"'; + --len; + + if (multiline) { + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 3; + } + + while (*text != '\0' && len > 1) { + if (*text == '"') + *bfp++ = '\\'; + else if (*text == '\n') { + *bfp++ = '\\'; + *bfp++ = 'n'; + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 5; + ++text; + goto next; + } + else if (*text == '\\') { + *bfp++ = '\\'; + len--; + } + *bfp++ = *text++; +next: + --len; + } + + if (multiline && eol) + bfp -= 3; + + *bfp++ = '"'; + *bfp = '\0'; + + return bf; +} + +struct file_line { + struct file_line *next; + const char *file; + int lineno; +}; + +static struct file_line *file_line__new(const char *file, int lineno) +{ + struct file_line *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->file = file; + self->lineno = lineno; + self->next = NULL; +out: + return self; +} + +struct message { + const char *msg; + const char *option; + struct message *next; + struct file_line *files; +}; + +static struct message *message__list; + +static struct message *message__new(const char *msg, char *option, + const char *file, int lineno) +{ + struct message *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->files = file_line__new(file, lineno); + if (self->files == NULL) + goto out_fail; + + self->msg = strdup(msg); + if (self->msg == NULL) + goto out_fail_msg; + + self->option = option; + self->next = NULL; +out: + return self; +out_fail_msg: + free(self->files); +out_fail: + free(self); + self = NULL; + goto out; +} + +static struct message *mesage__find(const char *msg) +{ + struct message *m = message__list; + + while (m != NULL) { + if (strcmp(m->msg, msg) == 0) + break; + m = m->next; + } + + return m; +} + +static int message__add_file_line(struct message *self, const char *file, + int lineno) +{ + int rc = -1; + struct file_line *fl = file_line__new(file, lineno); + + if (fl == NULL) + goto out; + + fl->next = self->files; + self->files = fl; + rc = 0; +out: + return rc; +} + +static int message__add(const char *msg, char *option, const char *file, + int lineno) +{ + int rc = 0; + char bf[16384]; + char *escaped = escape(msg, bf, sizeof(bf)); + struct message *m = mesage__find(escaped); + + if (m != NULL) + rc = message__add_file_line(m, file, lineno); + else { + m = message__new(escaped, option, file, lineno); + + if (m != NULL) { + m->next = message__list; + message__list = m; + } else + rc = -1; + } + return rc; +} + +static void menu_build_message_list(struct menu *menu) +{ + struct menu *child; + + message__add(menu_get_prompt(menu), NULL, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + if (menu->sym != NULL && menu_has_help(menu)) + message__add(menu_get_help(menu), menu->sym->name, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + for (child = menu->list; child != NULL; child = child->next) + if (child->prompt != NULL) + menu_build_message_list(child); +} + +static void message__print_file_lineno(struct message *self) +{ + struct file_line *fl = self->files; + + putchar('\n'); + if (self->option != NULL) + printf("# %s:00000\n", self->option); + + printf("#: %s:%d", fl->file, fl->lineno); + fl = fl->next; + + while (fl != NULL) { + printf(", %s:%d", fl->file, fl->lineno); + fl = fl->next; + } + + putchar('\n'); +} + +static void message__print_gettext_msgid_msgstr(struct message *self) +{ + message__print_file_lineno(self); + + printf("msgid %s\n" + "msgstr \"\"\n", self->msg); +} + +static void menu__xgettext(void) +{ + struct message *m = message__list; + + while (m != NULL) { + /* skip empty lines ("") */ + if (strlen(m->msg) > sizeof("\"\"")) + message__print_gettext_msgid_msgstr(m); + m = m->next; + } +} + +int main(int ac, char **av) +{ + conf_parse(av[1]); + + menu_build_message_list(menu_get_root_menu(NULL)); + menu__xgettext(); + return 0; +} diff -Nru seabios-1.7.1/scripts/kconfig/lex.zconf.c seabios-1.7.4/scripts/kconfig/lex.zconf.c --- seabios-1.7.1/scripts/kconfig/lex.zconf.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lex.zconf.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,2430 @@ + +#line 3 "scripts/kconfig/lex.zconf.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer zconf_create_buffer +#define yy_delete_buffer zconf_delete_buffer +#define yy_flex_debug zconf_flex_debug +#define yy_init_buffer zconf_init_buffer +#define yy_flush_buffer zconf_flush_buffer +#define yy_load_buffer_state zconf_load_buffer_state +#define yy_switch_to_buffer zconf_switch_to_buffer +#define yyin zconfin +#define yyleng zconfleng +#define yylex zconflex +#define yylineno zconflineno +#define yyout zconfout +#define yyrestart zconfrestart +#define yytext zconftext +#define yywrap zconfwrap +#define yyalloc zconfalloc +#define yyrealloc zconfrealloc +#define yyfree zconffree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via zconfrestart()), so that the user can continue scanning by + * just pointing zconfin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); +void zconf_delete_buffer (YY_BUFFER_STATE b ); +void zconf_flush_buffer (YY_BUFFER_STATE b ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); + +void *zconfalloc (yy_size_t ); +void *zconfrealloc (void *,yy_size_t ); +void zconffree (void * ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][17] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + }, + + { + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 + }, + + { + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 + }, + + { + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 + }, + + { + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 + + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 + }, + + { + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 + }, + + { + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 + }, + + { + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + + }, + + { + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 + }, + + { + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 + }, + + { + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 + }, + + { + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 + + }, + + { + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 + }, + + { + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 + }, + + { + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 + }, + + { + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 + }, + + { + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 + + }, + + { + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + }, + + { + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 + }, + + { + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 + }, + + { + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 + }, + + { + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 + + }, + + { + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 + }, + + { + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 + }, + + { + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 + }, + + { + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 + }, + + { + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 + + }, + + { + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 + }, + + { + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 + + }, + + { + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + }, + + { + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 + }, + + { + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 + }, + + { + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 + + }, + + { + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 + }, + + { + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 + }, + + { + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 + }, + + { + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 + }, + + { + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + + }, + + { + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 + }, + + { + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 + }, + + { + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 + }, + + { + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 + }, + + { + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 + + }, + + { + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 + }, + + } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + zconfleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[61] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, + 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, + 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; +#define YY_NO_INPUT 1 + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int zconflex_destroy (void ); + +int zconfget_debug (void ); + +void zconfset_debug (int debug_flag ); + +YY_EXTRA_TYPE zconfget_extra (void ); + +void zconfset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *zconfget_in (void ); + +void zconfset_in (FILE * in_str ); + +FILE *zconfget_out (void ); + +void zconfset_out (FILE * out_str ); + +int zconfget_leng (void ); + +char *zconfget_text (void ); + +int zconfget_lineno (void ); + +void zconfset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + errno=0; \ + while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(zconfin); \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + int str = 0; + int ts, i; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! zconfin ) + zconfin = stdin; + + if ( ! zconfout ) + zconfout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of zconftext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + return T_EOL; +} + YY_BREAK +case 3: +YY_RULE_SETUP + + YY_BREAK +case 4: +YY_RULE_SETUP +{ + BEGIN(COMMAND); +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + unput(zconftext[0]); + BEGIN(COMMAND); +} + YY_BREAK + +case 6: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 7: +YY_RULE_SETUP + + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } + YY_BREAK + +case 9: +YY_RULE_SETUP +return T_AND; + YY_BREAK +case 10: +YY_RULE_SETUP +return T_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +return T_OPEN_PAREN; + YY_BREAK +case 12: +YY_RULE_SETUP +return T_CLOSE_PAREN; + YY_BREAK +case 13: +YY_RULE_SETUP +return T_NOT; + YY_BREAK +case 14: +YY_RULE_SETUP +return T_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +return T_UNEQUAL; + YY_BREAK +case 16: +YY_RULE_SETUP +{ + str = zconftext[0]; + new_string(); + BEGIN(STRING); + } + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; + YY_BREAK +case 18: +YY_RULE_SETUP +/* ignore */ + YY_BREAK +case 19: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 20: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +current_file->lineno++; + YY_BREAK +case 22: +YY_RULE_SETUP + + YY_BREAK +case YY_STATE_EOF(PARAM): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 23: +/* rule 23 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 24: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + } + YY_BREAK +case 25: +/* rule 25 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 26: +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + } + YY_BREAK +case 27: +YY_RULE_SETUP +{ + if (str == zconftext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(zconftext, 1); + } + YY_BREAK +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +{ + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + YY_BREAK +case YY_STATE_EOF(STRING): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 29: +YY_RULE_SETUP +{ + ts = 0; + for (i = 0; i < zconfleng; i++) { + if (zconftext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + YY_BREAK +case 30: +/* rule 30 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + append_string("\n", 1); + } + YY_BREAK +case 32: +YY_RULE_SETUP +{ + while (zconfleng) { + if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) + break; + zconfleng--; + } + append_string(zconftext, zconfleng); + if (!first_ts) + first_ts = last_ts; + } + YY_BREAK +case YY_STATE_EOF(HELP): +{ + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(zconfin); + yyterminate(); +} + YY_BREAK +case 33: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed zconfin at a new source and called + * zconflex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( zconfwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * zconftext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + zconfrestart(zconfin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up zconftext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + zconfrestart(zconfin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( zconfwrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve zconftext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void zconfrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); + zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * zconfpop_buffer_state(); + * zconfpush_buffer_state(new_buffer); + */ + zconfensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + zconf_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (zconfwrap()) processing, but the only time this flag + * is looked at is after zconfwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + zconf_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + * + */ + void zconf_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + zconffree((void *) b->yy_ch_buf ); + + zconffree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ + static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + zconf_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then zconf_init_buffer was _probably_ + * called from zconfrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void zconf_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + zconfensure_buffer_stack(); + + /* This block is copied from zconf_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from zconf_switch_to_buffer. */ + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void zconfpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + zconf_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +{ + + return zconf_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) zconfalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = zconf_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + zconftext[zconfleng] = (yy_hold_char); \ + (yy_c_buf_p) = zconftext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + zconfleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int zconfget_lineno (void) +{ + + return zconflineno; +} + +/** Get the input stream. + * + */ +FILE *zconfget_in (void) +{ + return zconfin; +} + +/** Get the output stream. + * + */ +FILE *zconfget_out (void) +{ + return zconfout; +} + +/** Get the length of the current token. + * + */ +int zconfget_leng (void) +{ + return zconfleng; +} + +/** Get the current token. + * + */ + +char *zconfget_text (void) +{ + return zconftext; +} + +/** Set the current line number. + * @param line_number + * + */ +void zconfset_lineno (int line_number ) +{ + + zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE * in_str ) +{ + zconfin = in_str ; +} + +void zconfset_out (FILE * out_str ) +{ + zconfout = out_str ; +} + +int zconfget_debug (void) +{ + return zconf_flex_debug; +} + +void zconfset_debug (int bdebug ) +{ + zconf_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from zconflex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + zconfin = stdin; + zconfout = stdout; +#else + zconfin = (FILE *) 0; + zconfout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * zconflex_init() + */ + return 0; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + zconfpop_buffer_state(); + } + + /* Destroy the stack itself. */ + zconffree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * zconflex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *zconfalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *zconfrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ + free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; + current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + zconfin = zconf_fopen(file->name); + if (!zconfin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + if (file->flags & FILE_BUSY) { + printf("%s:%d: do not source '%s' from itself\n", + zconf_curname(), zconf_lineno(), name); + exit(1); + } + if (file->flags & FILE_SCANNED) { + printf("%s:%d: file '%s' is already sourced from '%s'\n", + zconf_curname(), zconf_lineno(), name, + file->parent->name); + exit(1); + } + file->flags |= FILE_BUSY; + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file->flags |= FILE_SCANNED; + current_file->flags &= ~FILE_BUSY; + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(zconfin); + zconf_delete_buffer(YY_CURRENT_BUFFER); + zconf_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} + diff -Nru seabios-1.7.1/scripts/kconfig/list.h seabios-1.7.4/scripts/kconfig/list.h --- seabios-1.7.1/scripts/kconfig/list.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/list.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,131 @@ +#ifndef LIST_H +#define LIST_H + +/* + * Copied from include/linux/... + */ + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +struct list_head { + struct list_head *next, *prev; +}; + + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *_new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *_new, struct list_head *head) +{ + __list_add(_new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (struct list_head*)LIST_POISON1; + entry->prev = (struct list_head*)LIST_POISON2; +} +#endif diff -Nru seabios-1.7.1/scripts/kconfig/lkc.h seabios-1.7.4/scripts/kconfig/lkc.h --- seabios-1.7.1/scripts/kconfig/lkc.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lkc.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#include "expr.h" + +#ifndef KBUILD_NO_NLS +# include +#else +static inline const char *gettext(const char *txt) { return txt; } +static inline void textdomain(const char *domainname) {} +static inline void bindtextdomain(const char *name, const char *dir) {} +static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define P(name,type,arg) extern type name arg +#include "lkc_proto.h" +#undef P + +#define SRCTREE "srctree" + +#ifndef PACKAGE +#define PACKAGE "linux" +#endif + +#define LOCALEDIR "/usr/share/locale" + +#define _(text) gettext(text) +#define N_(text) (text) + +#ifndef CONFIG_ +#define CONFIG_ "CONFIG_" +#endif +static inline const char *CONFIG_prefix(void) +{ + return getenv( "CONFIG_" ) ?: CONFIG_; +} +#undef CONFIG_ +#define CONFIG_ CONFIG_prefix() + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 +#define TF_OPTION 0x0004 + +enum conf_def_mode { + def_default, + def_yes, + def_mod, + def_no, + def_random +}; + +#define T_OPT_MODULES 1 +#define T_OPT_DEFCONFIG_LIST 2 +#define T_OPT_ENV 3 + +struct kconf_id { + int name; + int token; + unsigned int flags; + enum symbol_type stype; +}; + +extern int zconfdebug; + +int zconfparse(void); +void zconfdump(FILE *out); +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +int zconf_lineno(void); +const char *zconf_curname(void); + +/* confdata.c */ +const char *conf_get_configname(void); +const char *conf_get_autoconfig_name(void); +char *conf_get_default_confname(void); +void sym_set_change_count(int count); +void sym_add_change_count(int count); +bool conf_set_all_new_symbols(enum conf_def_mode mode); +void set_all_choice_values(struct symbol *csym); + +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + +/* confdata.c and expr.c */ +static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) +{ + assert(len != 0); + + if (fwrite(str, len, count, out) != count) + fprintf(stderr, "Error in writing or end of file.\n"); +} + +/* menu.c */ +void _menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +void menu_add_visibility(struct expr *dep); +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option(int token, char *arg); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); +void *xmalloc(size_t size); +void *xcalloc(size_t nmemb, size_t size); + +struct gstr { + size_t len; + char *s; + /* + * when max_width is not zero long lines in string s (if any) get + * wrapped not to exceed the max_width value + */ + int max_width; +}; +struct gstr str_new(void); +struct gstr str_assign(const char *s); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +extern struct expr *sym_env_list; + +void sym_init(void); +void sym_clear_all_valid(void); +void sym_set_all_changed(void); +void sym_set_changed(struct symbol *sym); +struct symbol *sym_choice_default(struct symbol *sym); +const char *sym_get_string_default(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); +struct property *sym_get_env_prop(struct symbol *sym); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ + return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ + return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ + return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ + return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_DEF_USER ? true : false; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff -Nru seabios-1.7.1/scripts/kconfig/lkc_proto.h seabios-1.7.4/scripts/kconfig/lkc_proto.h --- seabios-1.7.1/scripts/kconfig/lkc_proto.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lkc_proto.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,57 @@ +#include + +/* confdata.c */ +P(conf_parse,void,(const char *name)); +P(conf_read,int,(const char *name)); +P(conf_read_simple,int,(const char *name, int)); +P(conf_write_defconfig,int,(const char *name)); +P(conf_write,int,(const char *name)); +P(conf_write_autoconf,int,(void)); +P(conf_get_changed,bool,(void)); +P(conf_set_changed_callback, void,(void (*fn)(void))); +P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); + +/* menu.c */ +P(rootmenu,struct menu,); + +P(menu_is_empty, bool, (struct menu *menu)); +P(menu_is_visible, bool, (struct menu *menu)); +P(menu_has_prompt, bool, (struct menu *menu)); +P(menu_get_prompt,const char *,(struct menu *menu)); +P(menu_get_root_menu,struct menu *,(struct menu *menu)); +P(menu_get_parent_menu,struct menu *,(struct menu *menu)); +P(menu_has_help,bool,(struct menu *menu)); +P(menu_get_help,const char *,(struct menu *menu)); +P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head + *head)); +P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head + *head)); +P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); + +/* symbol.c */ +P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); + +P(sym_lookup,struct symbol *,(const char *name, int flags)); +P(sym_find,struct symbol *,(const char *name)); +P(sym_expand_string_value,const char *,(const char *in)); +P(sym_escape_string_value, const char *,(const char *in)); +P(sym_re_search,struct symbol **,(const char *pattern)); +P(sym_type_name,const char *,(enum symbol_type type)); +P(sym_calc_value,void,(struct symbol *sym)); +P(sym_get_type,enum symbol_type,(struct symbol *sym)); +P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); +P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); +P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); +P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); +P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); +P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); +P(sym_is_changable,bool,(struct symbol *sym)); +P(sym_get_choice_prop,struct property *,(struct symbol *sym)); +P(sym_get_default_prop,struct property *,(struct symbol *sym)); +P(sym_get_string_value,const char *,(struct symbol *sym)); + +P(prop_get_type_name,const char *,(enum prop_type type)); + +/* expr.c */ +P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/BIG.FAT.WARNING seabios-1.7.4/scripts/kconfig/lxdialog/BIG.FAT.WARNING --- seabios-1.7.1/scripts/kconfig/lxdialog/BIG.FAT.WARNING 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/BIG.FAT.WARNING 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,4 @@ +This is NOT the official version of dialog. This version has been +significantly modified from the original. It is for use by the Linux +kernel configuration script. Please do not bother Savio Lam with +questions about this program. diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/checklist.c seabios-1.7.4/scripts/kconfig/lxdialog/checklist.c --- seabios-1.7.1/scripts/kconfig/lxdialog/checklist.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/checklist.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,332 @@ +/* + * checklist.c -- implements the checklist box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; 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. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x; + +/* + * Print list item + */ +static void print_item(WINDOW * win, int choice, int selected) +{ + int i; + char *list_item = malloc(list_width + 1); + + strncpy(list_item, item_str(), list_width - item_x); + list_item[list_width - item_x] = '\0'; + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + + wmove(win, choice, check_x); + wattrset(win, selected ? dlg.check_selected.atr + : dlg.check.atr); + if (!item_is_tag(':')) + wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); + + wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); + mvwaddch(win, choice, item_x, list_item[0]); + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + waddstr(win, list_item + 1); + if (selected) { + wmove(win, choice, check_x + 1); + wrefresh(win); + } + free(list_item); +} + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, + int y, int x, int height) +{ + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + choice < item_no - 1)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } +} + +/* + * Display the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext("Select"), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * in the style of radiolist (only one option turned on at a time). + */ +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height) +{ + int i, x, y, box_x, box_y; + int key = 0, button = 0, choice = 0, scroll = 0, max_choice; + WINDOW *dialog, *list; + + /* which item to highlight */ + item_foreach() { + if (item_is_tag('X')) + choice = item_n(); + if (item_is_selected()) { + choice = item_n(); + break; + } + } + +do_resize: + if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN)) + return -ERRDISPLAYTOOSMALL; + + max_choice = MIN(list_height, item_count()); + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + list_width = width - 6; + box_y = height - list_height - 5; + box_x = (width - list_width) / 2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, + x + box_x + 1); + + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + /* Find length of longest item in order to center checklist */ + check_x = 0; + item_foreach() + check_x = MAX(check_x, strlen(item_str()) + 4); + check_x = MIN(check_x, list_width); + + check_x = (list_width - check_x) / 2; + item_x = check_x + 4; + + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + + /* Print the list */ + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + print_item(list, i, i == choice); + } + + print_arrows(dialog, choice, item_count(), scroll, + box_y, box_x + check_x + 5, list_height); + + print_buttons(dialog, height, width, 0); + + wnoutrefresh(dialog); + wnoutrefresh(list); + doupdate(); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + for (i = 0; i < max_choice; i++) { + item_set(i + scroll); + if (toupper(key) == toupper(item_str()[0])) + break; + } + + if (i < max_choice || key == KEY_UP || key == KEY_DOWN || + key == '+' || key == '-') { + if (key == KEY_UP || key == '-') { + if (!choice) { + if (!scroll) + continue; + /* Scroll list down */ + if (list_height > 1) { + /* De-highlight current first item */ + item_set(scroll); + print_item(list, 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + item_set(scroll); + print_item(list, 0, TRUE); + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice - 1; + } else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll + choice >= item_count() - 1) + continue; + /* Scroll list up */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + item_set(scroll + max_choice - 1); + print_item(list, + max_choice - 1, + FALSE); + scrollok(list, TRUE); + wscrl(list, 1); + scrollok(list, FALSE); + } + scroll++; + item_set(scroll + max_choice - 1); + print_item(list, max_choice - 1, TRUE); + + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice + 1; + } + if (i != choice) { + /* De-highlight current item */ + item_set(scroll + choice); + print_item(list, choice, FALSE); + /* Highlight new item */ + choice = i; + item_set(scroll + choice); + print_item(list, choice, TRUE); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + switch (key) { + case 'H': + case 'h': + case '?': + button = 1; + /* fall-through */ + case 'S': + case 's': + case ' ': + case '\n': + item_foreach() + item_set_selected(0); + item_set(scroll + choice); + item_set_selected(1); + delwin(list); + delwin(dialog); + return button; + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(list); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + + /* Now, update everything... */ + doupdate(); + } + delwin(list); + delwin(dialog); + return key; /* ESC pressed */ +} diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/check-lxdialog.sh seabios-1.7.4/scripts/kconfig/lxdialog/check-lxdialog.sh --- seabios-1.7.1/scripts/kconfig/lxdialog/check-lxdialog.sh 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/check-lxdialog.sh 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,87 @@ +#!/bin/sh +# Check ncurses compatibility + +# What library to link +ldflags() +{ + pkg-config --libs ncursesw 2>/dev/null && exit + pkg-config --libs ncurses 2>/dev/null && exit + for ext in so a dll.a dylib ; do + for lib in ncursesw ncurses curses ; do + $cc -print-file-name=lib${lib}.${ext} | grep -q / + if [ $? -eq 0 ]; then + echo "-l${lib}" + exit + fi + done + done + exit 1 +} + +# Where is ncurses.h? +ccflags() +{ + if [ -f /usr/include/ncursesw/curses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC=""' + echo ' -DNCURSES_WIDECHAR=1' + elif [ -f /usr/include/ncurses/ncurses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses/curses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses.h ]; then + echo '-DCURSES_LOC=""' + else + echo '-DCURSES_LOC=""' + fi +} + +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + +# Check if we can link to ncurses +check() { + $cc -x c - -o $tmp 2>/dev/null <<'EOF' +#include CURSES_LOC +main() {} +EOF + if [ $? != 0 ]; then + echo " *** Unable to find the ncurses libraries or the" 1>&2 + echo " *** required header files." 1>&2 + echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 + echo " *** " 1>&2 + echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 + echo " *** " 1>&2 + exit 1 + fi +} + +usage() { + printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" +} + +if [ $# -eq 0 ]; then + usage + exit 1 +fi + +cc="" +case "$1" in + "-check") + shift + cc="$@" + check + ;; + "-ccflags") + ccflags + ;; + "-ldflags") + shift + cc="$@" + ldflags + ;; + "*") + usage + exit 1 + ;; +esac diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/dialog.h seabios-1.7.4/scripts/kconfig/lxdialog/dialog.h --- seabios-1.7.1/scripts/kconfig/lxdialog/dialog.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/dialog.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,257 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KBUILD_NO_NLS +# include +#else +# define gettext(Msgid) ((const char *) (Msgid)) +#endif + +#ifdef __sun__ +#define CURS_MACROS +#endif +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked. This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses. The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef wbkgdset +#define wbkgdset(w,p) /*nothing */ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define KEY_ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/* error return codes */ +#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) + +/* + * Color definitions + */ +struct dialog_color { + chtype atr; /* Color attribute */ + int fg; /* foreground */ + int bg; /* background */ + int hl; /* highlight this item */ +}; + +struct subtitle_list { + struct subtitle_list *next; + const char *text; +}; + +struct dialog_info { + const char *backtitle; + struct subtitle_list *subtitles; + struct dialog_color screen; + struct dialog_color shadow; + struct dialog_color dialog; + struct dialog_color title; + struct dialog_color border; + struct dialog_color button_active; + struct dialog_color button_inactive; + struct dialog_color button_key_active; + struct dialog_color button_key_inactive; + struct dialog_color button_label_active; + struct dialog_color button_label_inactive; + struct dialog_color inputbox; + struct dialog_color inputbox_border; + struct dialog_color searchbox; + struct dialog_color searchbox_title; + struct dialog_color searchbox_border; + struct dialog_color position_indicator; + struct dialog_color menubox; + struct dialog_color menubox_border; + struct dialog_color item; + struct dialog_color item_selected; + struct dialog_color tag; + struct dialog_color tag_selected; + struct dialog_color tag_key; + struct dialog_color tag_key_selected; + struct dialog_color check; + struct dialog_color check_selected; + struct dialog_color uarrow; + struct dialog_color darrow; +}; + +/* + * Global variables + */ +extern struct dialog_info dlg; +extern char dialog_input_result[]; +extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */ + +/* + * Function prototypes + */ + +/* item list as used by checklist and menubox */ +void item_reset(void); +void item_make(const char *fmt, ...); +void item_add_str(const char *fmt, ...); +void item_set_tag(char tag); +void item_set_data(void *p); +void item_set_selected(int val); +int item_activate_selected(void); +void *item_data(void); +char item_tag(void); + +/* item list manipulation for lxdialog use */ +#define MAXITEMSTR 200 +struct dialog_item { + char str[MAXITEMSTR]; /* promtp displayed */ + char tag; + void *data; /* pointer to menu item - used by menubox+checklist */ + int selected; /* Set to 1 by dialog_*() function if selected. */ +}; + +/* list of lialog_items */ +struct dialog_list { + struct dialog_item node; + struct dialog_list *next; +}; + +extern struct dialog_list *item_cur; +extern struct dialog_list item_nil; +extern struct dialog_list *item_head; + +int item_count(void); +void item_set(int n); +int item_n(void); +const char *item_str(void); +int item_is_selected(void); +int item_is_tag(char tag); +#define item_foreach() \ + for (item_cur = item_head ? item_head: item_cur; \ + item_cur && (item_cur != &item_nil); item_cur = item_cur->next) + +/* generic key handlers */ +int on_key_esc(WINDOW *win); +int on_key_resize(void); + +/* minimum (re)size values */ +#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */ +#define CHECKLIST_WIDTH_MIN 6 +#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */ +#define INPUTBOX_WIDTH_MIN 2 +#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */ +#define MENUBOX_WIDTH_MIN 65 +#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */ +#define TEXTBOX_WIDTH_MIN 8 +#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */ +#define YESNO_WIDTH_MIN 4 +#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */ +#define WINDOW_WIDTH_MIN 80 + +int init_dialog(const char *backtitle); +void set_dialog_backtitle(const char *backtitle); +void set_dialog_subtitles(struct subtitle_list *subtitles); +void end_dialog(int x, int y); +void attr_clear(WINDOW * win, int height, int width, chtype attr); +void dialog_clear(void); +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); +void print_button(WINDOW * win, const char *label, int y, int x, int selected); +void print_title(WINDOW *dialog, const char *title, int width); +void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, + chtype border); +void draw_shadow(WINDOW * win, int y, int x, int height, int width); + +int first_alpha(const char *string, const char *exempt); +int dialog_yesno(const char *title, const char *prompt, int height, int width); +int dialog_msgbox(const char *title, const char *prompt, int height, + int width, int pause); + + +typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void + *_data); +int dialog_textbox(const char *title, char *tbuf, int initial_height, + int initial_width, int *keys, int *_vscroll, int *_hscroll, + update_text_fn update_text, void *data); +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll); +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height); +int dialog_inputbox(const char *title, const char *prompt, int height, + int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + * -- the first 32 are used as numbers, in addition to '0'-'9' + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/.gitignore seabios-1.7.4/scripts/kconfig/lxdialog/.gitignore --- seabios-1.7.1/scripts/kconfig/lxdialog/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/.gitignore 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,4 @@ +# +# Generated files +# +lxdialog diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/inputbox.c seabios-1.7.4/scripts/kconfig/lxdialog/inputbox.c --- seabios-1.7.1/scripts/kconfig/lxdialog/inputbox.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/inputbox.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,301 @@ +/* + * inputbox.c -- implements the input box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; 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. + */ + +#include "dialog.h" + +char dialog_input_result[MAX_LEN + 1]; + +/* + * Print the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext(" Ok "), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int dialog_inputbox(const char *title, const char *prompt, int height, int width, + const char *init) +{ + int i, x, y, box_y, box_x, box_width; + int input_x = 0, key = 0, button = -1; + int show_x, len, pos; + char *instr = dialog_input_result; + WINDOW *dialog; + + if (!init) + instr[0] = '\0'; + else + strcpy(instr, init); + +do_resize: + if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + /* Draw the input field box */ + box_width = width - 6; + getyx(dialog, y, x); + box_y = y + 2; + box_x = (width - box_width) / 2; + draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + dlg.dialog.atr, dlg.border.atr); + + print_buttons(dialog, height, width, 0); + + /* Set up the initial value */ + wmove(dialog, box_y, box_x); + wattrset(dialog, dlg.inputbox.atr); + + len = strlen(instr); + pos = len; + + if (len >= box_width) { + show_x = len - box_width + 1; + input_x = box_width - 1; + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr[show_x + i]); + } else { + show_x = 0; + input_x = len; + waddstr(dialog, instr); + } + + wmove(dialog, box_y, box_x + input_x); + + wrefresh(dialog); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_BACKSPACE: + case 127: + if (pos) { + wattrset(dialog, dlg.inputbox.atr); + if (input_x == 0) { + show_x--; + } else + input_x--; + + if (pos < len) { + for (i = pos - 1; i < len; i++) { + instr[i] = instr[i+1]; + } + } + + pos--; + len--; + instr[len] = '\0'; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + case KEY_LEFT: + if (pos > 0) { + if (input_x > 0) { + wmove(dialog, box_y, --input_x + box_x); + } else if (input_x == 0) { + show_x--; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, box_x); + } + pos--; + } + continue; + case KEY_RIGHT: + if (pos < len) { + if (input_x < box_width - 1) { + wmove(dialog, box_y, ++input_x + box_x); + } else if (input_x == box_width - 1) { + show_x++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, input_x + box_x); + } + pos++; + } + continue; + default: + if (key < 0x100 && isprint(key)) { + if (len < MAX_LEN) { + wattrset(dialog, dlg.inputbox.atr); + if (pos < len) { + for (i = len; i > pos; i--) + instr[i] = instr[i-1]; + instr[pos] = key; + } else { + instr[len] = key; + } + pos++; + len++; + instr[len] = '\0'; + + if (input_x == box_width - 1) { + show_x++; + } else { + input_x++; + } + + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + } + } + } + switch (key) { + case 'O': + case 'o': + delwin(dialog); + return 0; + case 'H': + case 'h': + delwin(dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + switch (button) { + case -1: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + case 0: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + } + break; + case ' ': + case '\n': + delwin(dialog); + return (button == -1 ? 0 : button); + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return KEY_ESC; /* ESC pressed */ +} diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/menubox.c seabios-1.7.4/scripts/kconfig/lxdialog/menubox.c --- seabios-1.7.1/scripts/kconfig/lxdialog/menubox.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/menubox.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,437 @@ +/* + * menubox.c -- implements the menu box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; 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. + */ + +/* + * Changes by Clifford Wolf (god@clifford.at) + * + * [ 1998-06-13 ] + * + * *) A bugfix for the Page-Down problem + * + * *) Formerly when I used Page Down and Page Up, the cursor would be set + * to the first position in the menu box. Now lxdialog is a bit + * smarter and works more like other menu systems (just have a look at + * it). + * + * *) Formerly if I selected something my scrolling would be broken because + * lxdialog is re-invoked by the Menuconfig shell script, can't + * remember the last scrolling position, and just sets it so that the + * cursor is at the bottom of the box. Now it writes the temporary file + * lxdialog.scrltmp which contains this information. The file is + * deleted by lxdialog if the user leaves a submenu or enters a new + * one, but it would be nice if Menuconfig could make another "rm -f" + * just to be sure. Just try it out - you will recognise a difference! + * + * [ 1998-06-14 ] + * + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + * and menus change their size on the fly. + * + * *) If for some reason the last scrolling position is not saved by + * lxdialog, it sets the scrolling so that the selected item is in the + * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void do_print_item(WINDOW * win, const char *item, int line_y, + int selected, int hotkey) +{ + int j; + char *menu_item = malloc(menu_width + 1); + + strncpy(menu_item, item, menu_width - item_x); + menu_item[menu_width - item_x] = '\0'; + j = first_alpha(menu_item, "YyNnMmHh"); + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, line_y, 0); +#if OLD_NCURSES + { + int i; + for (i = 0; i < menu_width; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + mvwaddstr(win, line_y, item_x, menu_item); + if (hotkey) { + wattrset(win, selected ? dlg.tag_key_selected.atr + : dlg.tag_key.atr); + mvwaddch(win, line_y, item_x + j, menu_item[j]); + } + if (selected) { + wmove(win, line_y, item_x + 1); + } + free(menu_item); + wrefresh(win); +} + +#define print_item(index, choice, selected) \ +do { \ + item_set(index); \ + do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ +} while (0) + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, + int height) +{ + int cur_y, cur_x; + + getyx(win, cur_y, cur_x); + + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + wrefresh(win); + + if ((height < item_no) && (scroll + height < item_no)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + wmove(win, cur_y, cur_x); + wrefresh(win); +} + +/* + * Display the termination buttons. + */ +static void print_buttons(WINDOW * win, int height, int width, int selected) +{ + int x = width / 2 - 28; + int y = height - 2; + + print_button(win, gettext("Select"), y, x, selected == 0); + print_button(win, gettext(" Exit "), y, x + 12, selected == 1); + print_button(win, gettext(" Help "), y, x + 24, selected == 2); + print_button(win, gettext(" Save "), y, x + 36, selected == 3); + print_button(win, gettext(" Load "), y, x + 48, selected == 4); + + wmove(win, y, x + 1 + 12 * selected); + wrefresh(win); +} + +/* scroll up n lines (n may be negative) */ +static void do_scroll(WINDOW *win, int *scroll, int n) +{ + /* Scroll menu up */ + scrollok(win, TRUE); + wscrl(win, n); + scrollok(win, FALSE); + *scroll = *scroll + n; + wrefresh(win); +} + +/* + * Display a menu for choosing among a number of options + */ +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll) +{ + int i, j, x, y, box_x, box_y; + int height, width, menu_height; + int key = 0, button = 0, scroll = 0, choice = 0; + int first_item = 0, max_choice; + WINDOW *dialog, *menu; + +do_resize: + height = getmaxy(stdscr); + width = getmaxx(stdscr); + if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN) + return -ERRDISPLAYTOOSMALL; + + height -= 4; + width -= 5; + menu_height = height - 10; + + max_choice = MIN(menu_height, item_count()); + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + menu_width = width - 6; + box_y = height - menu_height - 5; + box_x = (width - menu_width) / 2 - 1; + + /* create new window for the menu */ + menu = subwin(dialog, menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + keypad(menu, TRUE); + + /* draw a box around the menu items */ + draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + if (menu_width >= 80) + item_x = (menu_width - 70) / 2; + else + item_x = 4; + + /* Set choice to default item */ + item_foreach() + if (selected && (selected == item_data())) + choice = item_n(); + /* get the saved scroll info */ + scroll = *s_scroll; + if ((scroll <= choice) && (scroll + max_choice > choice) && + (scroll >= 0) && (scroll + max_choice <= item_count())) { + first_item = scroll; + choice = choice - scroll; + } else { + scroll = 0; + } + if ((choice >= max_choice)) { + if (choice >= item_count() - max_choice / 2) + scroll = first_item = item_count() - max_choice; + else + scroll = first_item = choice - max_choice / 2; + choice = choice - scroll; + } + + /* Print the menu */ + for (i = 0; i < max_choice; i++) { + print_item(first_item + i, i, i == choice); + } + + wnoutrefresh(menu); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + print_buttons(dialog, height, width, 0); + wmove(menu, choice, item_x + 1); + wrefresh(menu); + + while (key != KEY_ESC) { + key = wgetch(menu); + + if (key < 256 && isalpha(key)) + key = tolower(key); + + if (strchr("ynmh", key)) + i = max_choice; + else { + for (i = choice + 1; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + if (i == max_choice) + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + } + + if (item_count() != 0 && + (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE)) { + /* Remove highligt of current item */ + print_item(scroll + choice, choice, FALSE); + + if (key == KEY_UP || key == '-') { + if (choice < 2 && scroll) { + /* Scroll menu down */ + do_scroll(menu, &scroll, -1); + + print_item(scroll, 0, FALSE); + } else + choice = MAX(choice - 1, 0); + + } else if (key == KEY_DOWN || key == '+') { + print_item(scroll+choice, choice, FALSE); + + if ((choice > max_choice - 3) && + (scroll + max_choice < item_count())) { + /* Scroll menu up */ + do_scroll(menu, &scroll, 1); + + print_item(scroll+max_choice - 1, + max_choice - 1, FALSE); + } else + choice = MIN(choice + 1, max_choice - 1); + + } else if (key == KEY_PPAGE) { + scrollok(menu, TRUE); + for (i = 0; (i < max_choice); i++) { + if (scroll > 0) { + do_scroll(menu, &scroll, -1); + print_item(scroll, 0, FALSE); + } else { + if (choice > 0) + choice--; + } + } + + } else if (key == KEY_NPAGE) { + for (i = 0; (i < max_choice); i++) { + if (scroll + max_choice < item_count()) { + do_scroll(menu, &scroll, 1); + print_item(scroll+max_choice-1, + max_choice - 1, FALSE); + } else { + if (choice + 1 < max_choice) + choice++; + } + } + } else + choice = i; + + print_item(scroll + choice, choice, TRUE); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + wnoutrefresh(dialog); + wrefresh(menu); + + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_LEFT: + case TAB: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 4 : (button > 4 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(menu); + break; + case ' ': + case 's': + case 'y': + case 'n': + case 'm': + case '/': + case 'h': + case '?': + case 'z': + case '\n': + /* save scroll info */ + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + switch (key) { + case 'h': + case '?': + return 2; + case 's': + case 'y': + return 5; + case 'n': + return 6; + case 'm': + return 7; + case ' ': + return 8; + case '/': + return 9; + case 'z': + return 10; + case '\n': + return button; + } + return 0; + case 'e': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(menu); + break; + case KEY_RESIZE: + on_key_resize(); + delwin(menu); + delwin(dialog); + goto do_resize; + } + } + delwin(menu); + delwin(dialog); + return key; /* ESC pressed */ +} diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/textbox.c seabios-1.7.4/scripts/kconfig/lxdialog/textbox.c --- seabios-1.7.1/scripts/kconfig/lxdialog/textbox.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/textbox.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,408 @@ +/* + * textbox.c -- implements the text box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; 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. + */ + +#include "dialog.h" + +static void back_lines(int n); +static void print_page(WINDOW *win, int height, int width, update_text_fn + update_text, void *data); +static void print_line(WINDOW *win, int row, int width); +static char *get_line(void); +static void print_position(WINDOW * win); + +static int hscroll; +static int begin_reached, end_reached, page_length; +static char *buf; +static char *page; + +/* + * refresh window content + */ +static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, + int cur_y, int cur_x, update_text_fn update_text, + void *data) +{ + print_page(box, boxh, boxw, update_text, data); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); +} + + +/* + * Display text from a file in a dialog box. + * + * keys is a null-terminated array + * update_text() may not add or remove any '\n' or '\0' in tbuf + */ +int dialog_textbox(const char *title, char *tbuf, int initial_height, + int initial_width, int *keys, int *_vscroll, int *_hscroll, + update_text_fn update_text, void *data) +{ + int i, x, y, cur_x, cur_y, key = 0; + int height, width, boxh, boxw; + WINDOW *dialog, *box; + bool done = false; + + begin_reached = 1; + end_reached = 0; + page_length = 0; + hscroll = 0; + buf = tbuf; + page = buf; /* page is pointer to start of page to be displayed */ + + if (_vscroll && *_vscroll) { + begin_reached = 0; + + for (i = 0; i < *_vscroll; i++) + get_line(); + } + if (_hscroll) + hscroll = *_hscroll; + +do_resize: + getmaxyx(stdscr, height, width); + if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN) + return -ERRDISPLAYTOOSMALL; + if (initial_height != 0) + height = initial_height; + else + if (height > 4) + height -= 4; + else + height = 0; + if (initial_width != 0) + width = initial_width; + else + if (width > 5) + width -= 5; + else + width = 0; + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + /* Create window for box region, used for scrolling text */ + boxh = height - 4; + boxw = width - 2; + box = subwin(dialog, boxh, boxw, y + 1, x + 1); + wattrset(box, dlg.dialog.atr); + wbkgdset(box, dlg.dialog.atr & A_COLOR); + + keypad(box, TRUE); + + /* register the new window, along with its borders */ + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); + wnoutrefresh(dialog); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear(box, boxh, boxw, dlg.dialog.atr); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, + data); + + while (!done) { + key = wgetch(dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + case 'X': + case 'x': + case 'q': + case '\n': + done = true; + break; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + page = buf; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x, update_text, + data); + } + break; + case 'G': /* Last page */ + case KEY_END: + + end_reached = 1; + /* point to last char in buf */ + page = buf + strlen(buf); + back_lines(boxh); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (begin_reached) + break; + + back_lines(page_length + 1); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'B': /* Previous page */ + case 'b': + case 'u': + case KEY_PPAGE: + if (begin_reached) + break; + back_lines(page_length + boxh); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (end_reached) + break; + + back_lines(page_length - 1); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case KEY_NPAGE: /* Next page */ + case ' ': + case 'd': + if (end_reached) + break; + + begin_reached = 0; + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll <= 0) + break; + + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll >= MAX_LEN) + break; + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case KEY_ESC: + if (on_key_esc(dialog) == KEY_ESC) + done = true; + break; + case KEY_RESIZE: + back_lines(height); + delwin(box); + delwin(dialog); + on_key_resize(); + goto do_resize; + default: + for (i = 0; keys[i]; i++) { + if (key == keys[i]) { + done = true; + break; + } + } + } + } + delwin(box); + delwin(dialog); + if (_vscroll) { + const char *s; + + s = buf; + *_vscroll = 0; + back_lines(page_length); + while (s < page && (s = strchr(s, '\n'))) { + (*_vscroll)++; + s++; + } + } + if (_hscroll) + *_hscroll = hscroll; + return key; +} + +/* + * Go back 'n' lines in text. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void back_lines(int n) +{ + int i; + + begin_reached = 0; + /* Go back 'n' lines */ + for (i = 0; i < n; i++) { + if (*page == '\0') { + if (end_reached) { + end_reached = 0; + continue; + } + } + if (page == buf) { + begin_reached = 1; + return; + } + page--; + do { + if (page == buf) { + begin_reached = 1; + return; + } + page--; + } while (*page != '\n'); + page++; + } +} + +/* + * Print a new page of text. + */ +static void print_page(WINDOW *win, int height, int width, update_text_fn + update_text, void *data) +{ + int i, passed_end = 0; + + if (update_text) { + char *end; + + for (i = 0; i < height; i++) + get_line(); + end = page; + back_lines(height); + update_text(buf, page - buf, end - buf, data); + } + + page_length = 0; + for (i = 0; i < height; i++) { + print_line(win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh(win); +} + +/* + * Print a new line of text. + */ +static void print_line(WINDOW * win, int row, int width) +{ + char *line; + + line = get_line(); + line += MIN(strlen(line), hscroll); /* Scroll horizontally */ + wmove(win, row, 0); /* move cursor to correct line */ + waddch(win, ' '); + waddnstr(win, line, MIN(strlen(line), width - 2)); + + /* Clear 'residue' of previous line */ +#if OLD_NCURSES + { + int x = getcurx(win); + int i; + for (i = 0; i < width - x; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char *get_line(void) +{ + int i = 0; + static char line[MAX_LEN + 1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { + end_reached = 1; + break; + } else if (i < MAX_LEN) + line[i++] = *(page++); + else { + /* Truncate lines longer than MAX_LEN characters */ + if (i == MAX_LEN) + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move past '\n' */ + + return line; +} + +/* + * Print current position + */ +static void print_position(WINDOW * win) +{ + int percent; + + wattrset(win, dlg.position_indicator.atr); + wbkgdset(win, dlg.position_indicator.atr & A_COLOR); + percent = (page - buf) * 100 / strlen(buf); + wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); + wprintw(win, "(%3d%%)", percent); +} diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/util.c seabios-1.7.4/scripts/kconfig/lxdialog/util.c --- seabios-1.7.1/scripts/kconfig/lxdialog/util.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/util.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,713 @@ +/* + * util.c + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; 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. + */ + +#include + +#include "dialog.h" + +/* Needed in signal handler in mconf.c */ +int saved_x, saved_y; + +struct dialog_info dlg; + +static void set_mono_theme(void) +{ + dlg.screen.atr = A_NORMAL; + dlg.shadow.atr = A_NORMAL; + dlg.dialog.atr = A_NORMAL; + dlg.title.atr = A_BOLD; + dlg.border.atr = A_NORMAL; + dlg.button_active.atr = A_REVERSE; + dlg.button_inactive.atr = A_DIM; + dlg.button_key_active.atr = A_REVERSE; + dlg.button_key_inactive.atr = A_BOLD; + dlg.button_label_active.atr = A_REVERSE; + dlg.button_label_inactive.atr = A_NORMAL; + dlg.inputbox.atr = A_NORMAL; + dlg.inputbox_border.atr = A_NORMAL; + dlg.searchbox.atr = A_NORMAL; + dlg.searchbox_title.atr = A_BOLD; + dlg.searchbox_border.atr = A_NORMAL; + dlg.position_indicator.atr = A_BOLD; + dlg.menubox.atr = A_NORMAL; + dlg.menubox_border.atr = A_NORMAL; + dlg.item.atr = A_NORMAL; + dlg.item_selected.atr = A_REVERSE; + dlg.tag.atr = A_BOLD; + dlg.tag_selected.atr = A_REVERSE; + dlg.tag_key.atr = A_BOLD; + dlg.tag_key_selected.atr = A_REVERSE; + dlg.check.atr = A_BOLD; + dlg.check_selected.atr = A_REVERSE; + dlg.uarrow.atr = A_BOLD; + dlg.darrow.atr = A_BOLD; +} + +#define DLG_COLOR(dialog, f, b, h) \ +do { \ + dlg.dialog.fg = (f); \ + dlg.dialog.bg = (b); \ + dlg.dialog.hl = (h); \ +} while (0) + +static void set_classic_theme(void) +{ + DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); + DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); + DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); + DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); + DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); +} + +static void set_blackbg_theme(void) +{ + DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); + DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); + DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); + + DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); + DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); + + DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); + + DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); +} + +static void set_bluetitle_theme(void) +{ + set_classic_theme(); + DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); + +} + +/* + * Select color theme + */ +static int set_theme(const char *theme) +{ + int use_color = 1; + if (!theme) + set_bluetitle_theme(); + else if (strcmp(theme, "classic") == 0) + set_classic_theme(); + else if (strcmp(theme, "bluetitle") == 0) + set_bluetitle_theme(); + else if (strcmp(theme, "blackbg") == 0) + set_blackbg_theme(); + else if (strcmp(theme, "mono") == 0) + use_color = 0; + + return use_color; +} + +static void init_one_color(struct dialog_color *color) +{ + static int pair = 0; + + pair++; + init_pair(pair, color->fg, color->bg); + if (color->hl) + color->atr = A_BOLD | COLOR_PAIR(pair); + else + color->atr = COLOR_PAIR(pair); +} + +static void init_dialog_colors(void) +{ + init_one_color(&dlg.screen); + init_one_color(&dlg.shadow); + init_one_color(&dlg.dialog); + init_one_color(&dlg.title); + init_one_color(&dlg.border); + init_one_color(&dlg.button_active); + init_one_color(&dlg.button_inactive); + init_one_color(&dlg.button_key_active); + init_one_color(&dlg.button_key_inactive); + init_one_color(&dlg.button_label_active); + init_one_color(&dlg.button_label_inactive); + init_one_color(&dlg.inputbox); + init_one_color(&dlg.inputbox_border); + init_one_color(&dlg.searchbox); + init_one_color(&dlg.searchbox_title); + init_one_color(&dlg.searchbox_border); + init_one_color(&dlg.position_indicator); + init_one_color(&dlg.menubox); + init_one_color(&dlg.menubox_border); + init_one_color(&dlg.item); + init_one_color(&dlg.item_selected); + init_one_color(&dlg.tag); + init_one_color(&dlg.tag_selected); + init_one_color(&dlg.tag_key); + init_one_color(&dlg.tag_key_selected); + init_one_color(&dlg.check); + init_one_color(&dlg.check_selected); + init_one_color(&dlg.uarrow); + init_one_color(&dlg.darrow); +} + +/* + * Setup for color display + */ +static void color_setup(const char *theme) +{ + int use_color; + + use_color = set_theme(theme); + if (use_color && has_colors()) { + start_color(); + init_dialog_colors(); + } else + set_mono_theme(); +} + +/* + * Set window to attribute 'attr' + */ +void attr_clear(WINDOW * win, int height, int width, chtype attr) +{ + int i, j; + + wattrset(win, attr); + for (i = 0; i < height; i++) { + wmove(win, i, 0); + for (j = 0; j < width; j++) + waddch(win, ' '); + } + touchwin(win); +} + +void dialog_clear(void) +{ + int lines, columns; + + lines = getmaxy(stdscr); + columns = getmaxx(stdscr); + + attr_clear(stdscr, lines, columns, dlg.screen.atr); + /* Display background title if it exists ... - SLH */ + if (dlg.backtitle != NULL) { + int i, len = 0, skip = 0; + struct subtitle_list *pos; + + wattrset(stdscr, dlg.screen.atr); + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + /* 3 is for the arrow and spaces */ + len += strlen(pos->text) + 3; + } + + wmove(stdscr, 1, 1); + if (len > columns - 2) { + const char *ellipsis = "[...] "; + waddstr(stdscr, ellipsis); + skip = len - (columns - 2 - strlen(ellipsis)); + } + + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + if (skip == 0) + waddch(stdscr, ACS_RARROW); + else + skip--; + + if (skip == 0) + waddch(stdscr, ' '); + else + skip--; + + if (skip < strlen(pos->text)) { + waddstr(stdscr, pos->text + skip); + skip = 0; + } else + skip -= strlen(pos->text); + + if (skip == 0) + waddch(stdscr, ' '); + else + skip--; + } + + for (i = len + 1; i < columns - 1; i++) + waddch(stdscr, ACS_HLINE); + } + wnoutrefresh(stdscr); +} + +/* + * Do some initialization for dialog + */ +int init_dialog(const char *backtitle) +{ + int height, width; + + initscr(); /* Init curses */ + + /* Get current cursor position for signal handler in mconf.c */ + getyx(stdscr, saved_y, saved_x); + + getmaxyx(stdscr, height, width); + if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) { + endwin(); + return -ERRDISPLAYTOOSMALL; + } + + dlg.backtitle = backtitle; + color_setup(getenv("MENUCONFIG_COLOR")); + + keypad(stdscr, TRUE); + cbreak(); + noecho(); + dialog_clear(); + + return 0; +} + +void set_dialog_backtitle(const char *backtitle) +{ + dlg.backtitle = backtitle; +} + +void set_dialog_subtitles(struct subtitle_list *subtitles) +{ + dlg.subtitles = subtitles; +} + +/* + * End using dialog functions. + */ +void end_dialog(int x, int y) +{ + /* move cursor back to original position */ + move(y, x); + refresh(); + endwin(); +} + +/* Print the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + **/ +void print_title(WINDOW *dialog, const char *title, int width) +{ + if (title) { + int tlen = MIN(width - 2, strlen(title)); + wattrset(dialog, dlg.title.atr); + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); + waddch(dialog, ' '); + } +} + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are propperly processed. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) +{ + int newl, cur_x, cur_y; + int prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; + + strcpy(tempstr, prompt); + + prompt_len = strlen(tempstr); + + if (prompt_len <= width - x * 2) { /* If prompt is short */ + wmove(win, y, (width - prompt_len) / 2); + waddstr(win, tempstr); + } else { + cur_x = x; + cur_y = y; + newl = 1; + word = tempstr; + while (word && *word) { + sp = strpbrk(word, "\n "); + if (sp && *sp == '\n') + newline_separator = sp; + + if (sp) + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + room = width - cur_x; + wlen = strlen(word); + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strpbrk(sp, "\n ")) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; + cur_x = x; + } + wmove(win, cur_y, cur_x); + waddstr(win, word); + getyx(win, cur_y, cur_x); + + /* Move to the next line if the word separator was a newline */ + if (newline_separator) { + cur_y++; + cur_x = x; + newline_separator = 0; + } else + cur_x++; + + if (sp && *sp == ' ') { + cur_x++; /* double space */ + while (*++sp == ' ') ; + newl = 1; + } else + newl = 0; + word = sp; + } + } +} + +/* + * Print a button + */ +void print_button(WINDOW * win, const char *label, int y, int x, int selected) +{ + int i, temp; + + wmove(win, y, x); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, "<"); + temp = strspn(label, " "); + label += temp; + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + for (i = 0; i < temp; i++) + waddch(win, ' '); + wattrset(win, selected ? dlg.button_key_active.atr + : dlg.button_key_inactive.atr); + waddch(win, label[0]); + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + waddstr(win, (char *)label + 1); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, ">"); + wmove(win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box(WINDOW * win, int y, int x, int height, int width, + chtype box, chtype border) +{ + int i, j; + + wattrset(win, 0); + for (i = 0; i < height; i++) { + wmove(win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch(win, border | ACS_ULCORNER); + else if (i == height - 1 && !j) + waddch(win, border | ACS_LLCORNER); + else if (!i && j == width - 1) + waddch(win, box | ACS_URCORNER); + else if (i == height - 1 && j == width - 1) + waddch(win, box | ACS_LRCORNER); + else if (!i) + waddch(win, border | ACS_HLINE); + else if (i == height - 1) + waddch(win, box | ACS_HLINE); + else if (!j) + waddch(win, border | ACS_VLINE); + else if (j == width - 1) + waddch(win, box | ACS_VLINE); + else + waddch(win, box | ' '); + } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void draw_shadow(WINDOW * win, int y, int x, int height, int width) +{ + int i; + + if (has_colors()) { /* Whether terminal supports color? */ + wattrset(win, dlg.shadow.atr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch(win, winch(win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove(win, i, x + width); + waddch(win, winch(win) & A_CHARTEXT); + waddch(win, winch(win) & A_CHARTEXT); + } + wnoutrefresh(win); + } +} + +/* + * Return the position of the first alphabetic character in a string. + */ +int first_alpha(const char *string, const char *exempt) +{ + int i, in_paren = 0, c; + + for (i = 0; i < strlen(string); i++) { + c = tolower(string[i]); + + if (strchr("<[(", c)) + ++in_paren; + if (strchr(">])", c) && in_paren > 0) + --in_paren; + + if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) + return i; + } + + return 0; +} + +/* + * ncurses uses ESC to detect escaped char sequences. This resutl in + * a small timeout before ESC is actually delivered to the application. + * lxdialog suggest which is correctly translated to two + * times esc. But then we need to ignore the second esc to avoid stepping + * out one menu too much. Filter away all escaped key sequences since + * keypad(FALSE) turn off ncurses support for escape sequences - and thats + * needed to make notimeout() do as expected. + */ +int on_key_esc(WINDOW *win) +{ + int key; + int key2; + int key3; + + nodelay(win, TRUE); + keypad(win, FALSE); + key = wgetch(win); + key2 = wgetch(win); + do { + key3 = wgetch(win); + } while (key3 != ERR); + nodelay(win, FALSE); + keypad(win, TRUE); + if (key == KEY_ESC && key2 == ERR) + return KEY_ESC; + else if (key != ERR && key != KEY_ESC && key2 == ERR) + ungetch(key); + + return -1; +} + +/* redraw screen in new size */ +int on_key_resize(void) +{ + dialog_clear(); + return KEY_RESIZE; +} + +struct dialog_list *item_cur; +struct dialog_list item_nil; +struct dialog_list *item_head; + +void item_reset(void) +{ + struct dialog_list *p, *next; + + for (p = item_head; p; p = next) { + next = p->next; + free(p); + } + item_head = NULL; + item_cur = &item_nil; +} + +void item_make(const char *fmt, ...) +{ + va_list ap; + struct dialog_list *p = malloc(sizeof(*p)); + + if (item_head) + item_cur->next = p; + else + item_head = p; + item_cur = p; + memset(p, 0, sizeof(*p)); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); + va_end(ap); +} + +void item_add_str(const char *fmt, ...) +{ + va_list ap; + size_t avail; + + avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str + strlen(item_cur->node.str), + avail, fmt, ap); + item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; + va_end(ap); +} + +void item_set_tag(char tag) +{ + item_cur->node.tag = tag; +} +void item_set_data(void *ptr) +{ + item_cur->node.data = ptr; +} + +void item_set_selected(int val) +{ + item_cur->node.selected = val; +} + +int item_activate_selected(void) +{ + item_foreach() + if (item_is_selected()) + return 1; + return 0; +} + +void *item_data(void) +{ + return item_cur->node.data; +} + +char item_tag(void) +{ + return item_cur->node.tag; +} + +int item_count(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) + n++; + return n; +} + +void item_set(int n) +{ + int i = 0; + item_foreach() + if (i++ == n) + return; +} + +int item_n(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) { + if (p == item_cur) + return n; + n++; + } + return 0; +} + +const char *item_str(void) +{ + return item_cur->node.str; +} + +int item_is_selected(void) +{ + return (item_cur->node.selected != 0); +} + +int item_is_tag(char tag) +{ + return (item_cur->node.tag == tag); +} diff -Nru seabios-1.7.1/scripts/kconfig/lxdialog/yesno.c seabios-1.7.4/scripts/kconfig/lxdialog/yesno.c --- seabios-1.7.1/scripts/kconfig/lxdialog/yesno.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/lxdialog/yesno.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * yesno.c -- implements the yes/no box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; 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. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 10; + int y = height - 2; + + print_button(dialog, gettext(" Yes "), y, x, selected == 0); + print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + + wmove(dialog, y, x + 1 + 13 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int dialog_yesno(const char *title, const char *prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + +do_resize: + if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + print_buttons(dialog, height, width, 0); + + while (key != KEY_ESC) { + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + return 0; + case 'N': + case 'n': + delwin(dialog); + return 1; + + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + return button; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return key; /* ESC pressed */ +} diff -Nru seabios-1.7.1/scripts/kconfig/Makefile seabios-1.7.4/scripts/kconfig/Makefile --- seabios-1.7.1/scripts/kconfig/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/Makefile 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,331 @@ +# =========================================================================== +# Kernel configuration targets +# These targets are used from top-level makefile + +PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \ + localmodconfig localyesconfig + +ifdef KBUILD_KCONFIG +Kconfig := $(KBUILD_KCONFIG) +else +Kconfig := Kconfig +endif + +# We need this, in case the user has it in its environment +unexport CONFIG_ + +xconfig: $(obj)/qconf + $< $(Kconfig) + +gconfig: $(obj)/gconf + $< $(Kconfig) + +menuconfig: $(obj)/mconf + $< $(Kconfig) + +config: $(obj)/conf + $< --oldaskconfig $(Kconfig) + +nconfig: $(obj)/nconf + $< $(Kconfig) + +oldconfig: $(obj)/conf + $< --$@ $(Kconfig) + +silentoldconfig: $(obj)/conf + @echo " Build Kconfig config file" + $(Q)mkdir -p include/generated + $(Q)$< --$@ $(Kconfig) + +localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf + $(Q)mkdir -p include/generated + $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config + $(Q)if [ -f .config ]; then \ + cmp -s .tmp.config .config || \ + (mv -f .config .config.old.1; \ + mv -f .tmp.config .config; \ + $(obj)/conf --silentoldconfig $(Kconfig); \ + mv -f .config.old.1 .config.old) \ + else \ + mv -f .tmp.config .config; \ + $(obj)/conf --silentoldconfig $(Kconfig); \ + fi + $(Q)rm -f .tmp.config + +# Create new linux.pot file +# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files +update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h + $(Q)echo " GEN config.pot" + $(Q)xgettext --default-domain=linux \ + --add-comments --keyword=_ --keyword=N_ \ + --from-code=UTF-8 \ + --files-from=$(srctree)/scripts/kconfig/POTFILES.in \ + --directory=$(srctree) --directory=$(objtree) \ + --output $(obj)/config.pot + $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot + $(Q)(for i in `ls $(srctree)/arch/*/Kconfig \ + $(srctree)/arch/*/um/Kconfig`; \ + do \ + echo " GEN $$i"; \ + $(obj)/kxgettext $$i \ + >> $(obj)/config.pot; \ + done ) + $(Q)echo " GEN linux.pot" + $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ + --output $(obj)/linux.pot + $(Q)rm -f $(obj)/config.pot + +PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig + +allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf + $< --$@ $(Kconfig) + +PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig + +listnewconfig olddefconfig: $(obj)/conf + $< --$@ $(Kconfig) + +# oldnoconfig is an alias of olddefconfig, because people already are dependent +# on its behavior(sets new symbols to their default value but not 'n') with the +# counter-intuitive name. +oldnoconfig: $(obj)/conf + $< --olddefconfig $(Kconfig) + +savedefconfig: $(obj)/conf + $< --$@=defconfig $(Kconfig) + +defconfig: $(obj)/conf + @echo " Build default config" + $(Q)$< --defconfig=/dev/null $(Kconfig) + +%_defconfig: $(obj)/conf + $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) + +# Help text used by make help +help: + @echo ' config - Update current config utilising a line-oriented program' + @echo ' nconfig - Update current config utilising a ncurses menu based program' + @echo ' menuconfig - Update current config utilising a menu based program' + @echo ' xconfig - Update current config utilising a QT based front-end' + @echo ' gconfig - Update current config utilising a GTK based front-end' + @echo ' oldconfig - Update current config utilising a provided .config as base' + @echo ' localmodconfig - Update current config disabling modules not loaded' + @echo ' localyesconfig - Update current config converting local mods to core' + @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps' + @echo ' defconfig - New config with default from ARCH supplied defconfig' + @echo ' savedefconfig - Save current config as ./defconfig (minimal config)' + @echo ' allnoconfig - New config where all options are answered with no' + @echo ' allyesconfig - New config where all options are accepted with yes' + @echo ' allmodconfig - New config selecting modules when possible' + @echo ' alldefconfig - New config with all symbols set to default' + @echo ' randconfig - New config with random answer to all options' + @echo ' listnewconfig - List new options' + @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value' + +# lxdialog stuff +check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh + +# Use recursively expanded variables so we do not call gcc unless +# we really need to do so. (Do not call gcc as part of make mrproper) +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ + -DLOCALE + +# =========================================================================== +# Shared Makefile for the various kconfig executables: +# conf: Used for defconfig, oldconfig and related targets +# nconf: Used for the nconfig target. +# Utilizes ncurses +# mconf: Used for the menuconfig target +# Utilizes the lxdialog package +# qconf: Used for the xconfig target +# Based on QT which needs to be installed to compile it +# gconf: Used for the gconfig target +# Based on GTK which needs to be installed to compile it +# object files used by all kconfig flavours + +lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o +lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o + +conf-objs := conf.o zconf.tab.o +mconf-objs := mconf.o zconf.tab.o $(lxdialog) +nconf-objs := nconf.o zconf.tab.o nconf.gui.o +kxgettext-objs := kxgettext.o zconf.tab.o +qconf-cxxobjs := qconf.o +qconf-objs := zconf.tab.o +gconf-objs := gconf.o zconf.tab.o + +hostprogs-y := conf + +ifeq ($(MAKECMDGOALS),nconfig) + hostprogs-y += nconf +endif + +ifeq ($(MAKECMDGOALS),menuconfig) + hostprogs-y += mconf +endif + +ifeq ($(MAKECMDGOALS),update-po-config) + hostprogs-y += kxgettext +endif + +ifeq ($(MAKECMDGOALS),xconfig) + qconf-target := 1 +endif +ifeq ($(MAKECMDGOALS),gconfig) + gconf-target := 1 +endif + + +ifeq ($(qconf-target),1) + hostprogs-y += qconf +endif + +ifeq ($(gconf-target),1) + hostprogs-y += gconf +endif + +clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck +clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h +clean-files += mconf qconf gconf nconf +clean-files += config.pot linux.pot + +# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) +PHONY += $(obj)/dochecklxdialog +$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog +$(obj)/dochecklxdialog: + $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf) + +always := dochecklxdialog + +# Add environment specific flags +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) + +# generated files seem to need this to find local include files +HOSTCFLAGS_zconf.lex.o := -I$(src) +HOSTCFLAGS_zconf.tab.o := -I$(src) + +LEX_PREFIX_zconf := zconf +YACC_PREFIX_zconf := zconf + +HOSTLOADLIBES_qconf = $(KC_QT_LIBS) +HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) + +HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` +HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ + -Wno-missing-prototypes + +HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) + +HOSTLOADLIBES_nconf = $(shell \ + pkg-config --libs menu panel ncurses 2>/dev/null \ + || echo "-lmenu -lpanel -lncurses" ) +$(obj)/qconf.o: $(obj)/.tmp_qtcheck + +ifeq ($(qconf-target),1) +$(obj)/.tmp_qtcheck: $(src)/Makefile +-include $(obj)/.tmp_qtcheck + +# QT needs some extra effort... +$(obj)/.tmp_qtcheck: + @set -e; echo " CHECK qt"; dir=""; pkg=""; \ + if ! pkg-config --exists QtCore 2> /dev/null; then \ + echo "* Unable to find the QT4 tool qmake. Trying to use QT3"; \ + pkg-config --exists qt 2> /dev/null && pkg=qt; \ + pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \ + if [ -n "$$pkg" ]; then \ + cflags="\$$(shell pkg-config $$pkg --cflags)"; \ + libs="\$$(shell pkg-config $$pkg --libs)"; \ + moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \ + dir="$$(pkg-config $$pkg --variable=prefix)"; \ + else \ + for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ + if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ + done; \ + if [ -z "$$dir" ]; then \ + echo >&2 "*"; \ + echo >&2 "* Unable to find any QT installation. Please make sure that"; \ + echo >&2 "* the QT4 or QT3 development package is correctly installed and"; \ + echo >&2 "* either qmake can be found or install pkg-config or set"; \ + echo >&2 "* the QTDIR environment variable to the correct location."; \ + echo >&2 "*"; \ + false; \ + fi; \ + libpath=$$dir/lib; lib=qt; osdir=""; \ + $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ + osdir=x$$($(HOSTCXX) -print-multi-os-directory); \ + test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \ + test -f $$libpath/libqt-mt.so && lib=qt-mt; \ + cflags="-I$$dir/include"; \ + libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \ + moc="$$dir/bin/moc"; \ + fi; \ + if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \ + echo "*"; \ + echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \ + echo "*"; \ + moc="/usr/bin/moc"; \ + fi; \ + else \ + cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \ + libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \ + moc="\$$(shell pkg-config QtCore --variable=moc_location)"; \ + [ -n "$$moc" ] || moc="\$$(shell pkg-config QtCore --variable=prefix)/bin/moc"; \ + fi; \ + echo "KC_QT_CFLAGS=$$cflags" > $@; \ + echo "KC_QT_LIBS=$$libs" >> $@; \ + echo "KC_QT_MOC=$$moc" >> $@ +endif + +$(obj)/gconf.o: $(obj)/.tmp_gtkcheck + +ifeq ($(gconf-target),1) +-include $(obj)/.tmp_gtkcheck + +# GTK needs some extra effort, too... +$(obj)/.tmp_gtkcheck: + @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \ + if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ + touch $@; \ + else \ + echo >&2 "*"; \ + echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \ + echo >&2 "*"; \ + false; \ + fi \ + else \ + echo >&2 "*"; \ + echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \ + echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \ + echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo >&2 "*"; \ + false; \ + fi +endif + +$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c + +$(obj)/qconf.o: $(obj)/qconf.moc + +quiet_cmd_moc = MOC $@ + cmd_moc = $(KC_QT_MOC) -i $< -o $@ + +$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck + $(call cmd,moc) + +# Extract gconf menu items for I18N support +$(obj)/gconf.glade.h: $(obj)/gconf.glade + $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \ + $(obj)/gconf.glade + +VPATH := $(srctree) + +$(obj)/%:: $(src)/%_shipped + $(Q)cat $< > $@ + +host-cobjs := $(sort $(foreach m,$(hostprogs-y),$($(m)-objs))) +host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) +hostprogs-y := $(addprefix $(obj)/,$(hostprogs-y)) +$(host-cobjs) : $(obj)/%.o : $(src)/%.c + $(Q)$(HOSTCC) -I$(obj) -I$(srctree)/$(src) $(HOSTCFLAGS) $(HOSTCFLAGS_$(@F)) $(HOST_EXTRACFLAGS) -c -o $@ $< +$(hostprogs-y) : $(obj)/% : $(host-cobjs) + $(Q)$(HOSTCC) $(HOSTLDFLAGS) -o $@ $(addprefix $(obj)/,$($(@F)-objs)) $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) diff -Nru seabios-1.7.1/scripts/kconfig/mconf.c seabios-1.7.4/scripts/kconfig/mconf.c --- seabios-1.7.1/scripts/kconfig/mconf.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/mconf.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1039 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + * + * Introduced single menu mode (show all sub-menus in one large tree). + * 2002-11-06 Petr Baudis + * + * i18n, 2005, Arnaldo Carvalho de Melo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" +#include "lxdialog/dialog.h" + +static const char mconf_readme[] = N_( +"Overview\n" +"--------\n" +"This interface let you select features and parameters for the build.\n" +"Features can either be built-in, modularized, or ignored. Parameters\n" +"must be entered in as decimal or hexadecimal numbers or text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change or submenu wish to select and press .\n" +" Submenus are designated by \"--->\", empty ones by \"----\".\n" +"\n" +" Shortcut: Press the option's highlighted letter (hotkey).\n" +" Pressing a hotkey more than once will sequence\n" +" through all visible items which use that hotkey.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the cursor keys to highlight the button\n" +" and press .\n" +"\n" +" Shortcut: Press or or if there is no hotkey\n" +" using those letters. You may press a single , but\n" +" there is a delayed response which you may find annoying.\n" +"\n" +" Also, the and cursor keys will cycle between and\n" +" \n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, use the or cursor keys to highlight the help option\n" +" and press . You can try as well.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do , , and for \n" +" those who are familiar with less and lynx.\n" +"\n" +"o Press , , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"Menuconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a Menuconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting Menuconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use Menuconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"Menuconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single menu, rather\n" +"than the default multimenu hierarchy, run the menuconfig with\n" +"MENUCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make MENUCONFIG_MODE=single_menu menuconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n" +"Different color themes available\n" +"--------------------------------\n" +"It is possible to select different color themes using the variable\n" +"MENUCONFIG_COLOR. To select a theme use:\n" +"\n" +"make MENUCONFIG_COLOR= menuconfig\n" +"\n" +"Available themes are\n" +" mono => selects colors suitable for monochrome displays\n" +" blackbg => selects a color scheme with black background\n" +" classic => theme with blue background. The classic look\n" +" bluetitle => a LCD friendly version of classic. (default)\n" +"\n"), +menu_instructions[] = N_( + "Arrow keys navigate the menu. " + " selects submenus ---> (or empty submenus ----). " + "Highlighted letters are hotkeys. " + "Pressing includes, excludes, modularizes features. " + "Press to exit, for Help, for Search. " + "Legend: [*] built-in [ ] excluded module < > module capable"), +radiolist_instructions[] = N_( + "Use the arrow keys to navigate this window or " + "press the hotkey of the item you wish to select " + "followed by the . " + "Press for additional information about this option."), +inputbox_instructions_int[] = N_( + "Please enter a decimal value. " + "Fractions will not be accepted. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_hex[] = N_( + "Please enter a hexadecimal value. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_string[] = N_( + "Please enter a string value. " + "Use the key to move from the input field to the buttons below it."), +setmod_text[] = N_( + "This feature depends on another which has been configured as a module.\n" + "As a result, this feature will be built as a module."), +load_config_text[] = N_( + "Enter the name of the configuration file you wish to load. " + "Accept the name shown to restore the configuration you " + "last retrieved. Leave blank to abort."), +load_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep several different\n" + "configurations available on a single machine.\n" + "\n" + "If you have saved a previous configuration in a file other than the\n" + "default one, entering its name here will allow you to modify that\n" + "configuration.\n" + "\n" + "If you are uncertain, then you have probably never used alternate\n" + "configuration files. You should therefore leave this blank to abort.\n"), +save_config_text[] = N_( + "Enter a filename to which this configuration should be saved " + "as an alternate. Leave blank to abort."), +save_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep different configurations\n" + "available on a single machine.\n" + "\n" + "Entering a file name here will allow you to later retrieve, modify\n" + "and use the current configuration as an alternate to whatever\n" + "configuration options you have selected at that time.\n" + "\n" + "If you are uncertain what all this means then you should probably\n" + "leave this blank.\n"), +search_help[] = N_( + "\n" + "Search for symbols and display their relations.\n" + "Regular expressions are allowed.\n" + "Example: search for \"^FOO\"\n" + "Result:\n" + "-----------------------------------------------------------------\n" + "Symbol: FOO [=m]\n" + "Type : tristate\n" + "Prompt: Foo bus is used to drive the bar HW\n" + " Defined at drivers/pci/Kconfig:47\n" + " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + " Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" + " -> PCI support (PCI [=y])\n" + "(1) -> PCI access mode ( [=y])\n" + " Selects: LIBCRC32\n" + " Selected by: BAR\n" + "-----------------------------------------------------------------\n" + "o The line 'Type:' shows the type of the configuration option for\n" + " this symbol (boolean, tristate, string, ...)\n" + "o The line 'Prompt:' shows the text used in the menu structure for\n" + " this symbol\n" + "o The 'Defined at' line tell at what file / line number the symbol\n" + " is defined\n" + "o The 'Depends on:' line tell what symbols needs to be defined for\n" + " this symbol to be visible in the menu (selectable)\n" + "o The 'Location:' lines tell where in the menu structure this symbol\n" + " is located\n" + " A location followed by a [=y] indicates that this is a\n" + " selectable menu item - and the current value is displayed inside\n" + " brackets.\n" + " Press the key in the (#) prefix to jump directly to that\n" + " location. You will be returned to the current search results\n" + " after exiting this new menu.\n" + "o The 'Selects:' line tell what symbol will be automatically\n" + " selected if this symbol is selected (y or m)\n" + "o The 'Selected by' line tell what symbol has selected this symbol\n" + "\n" + "Only relevant lines are shown.\n" + "\n\n" + "Search examples:\n" + "Examples: USB => find all symbols containing USB\n" + " ^USB => find all symbols starting with USB\n" + " USB$ => find all symbols ending with USB\n" + "\n"); + +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +static int show_all_options; +static int save_and_exit; + +static void conf(struct menu *menu, struct menu *active_menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static int show_textbox_ext(const char *title, char *text, int r, int c, + int *keys, int *vscroll, int *hscroll, + update_text_fn update_text, void *data); +static void show_textbox(const char *title, const char *text, int r, int c); +static void show_helptext(const char *title, const char *text); +static void show_help(struct menu *menu); + +static char filename[PATH_MAX+1]; +static void set_config_filename(const char *config_filename) +{ + static char menu_backtitle[PATH_MAX+128]; + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + set_dialog_backtitle(menu_backtitle); + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; +} + +struct subtitle_part { + struct list_head entries; + const char *text; +}; +static LIST_HEAD(trail); + +static struct subtitle_list *subtitles; +static void set_subtitle(void) +{ + struct subtitle_part *sp; + struct subtitle_list *pos, *tmp; + + for (pos = subtitles; pos != NULL; pos = tmp) { + tmp = pos->next; + free(pos); + } + + subtitles = NULL; + list_for_each_entry(sp, &trail, entries) { + if (sp->text) { + if (pos) { + pos->next = xcalloc(sizeof(*pos), 1); + pos = pos->next; + } else { + subtitles = pos = xcalloc(sizeof(*pos), 1); + } + pos->text = sp->text; + } + } + + set_dialog_subtitles(subtitles); +} + +static void reset_subtitle(void) +{ + struct subtitle_list *pos, *tmp; + + for (pos = subtitles; pos != NULL; pos = tmp) { + tmp = pos->next; + free(pos); + } + subtitles = NULL; + set_dialog_subtitles(subtitles); +} + +struct search_data { + struct list_head *head; + struct menu **targets; + int *keys; +}; + +static void update_text(char *buf, size_t start, size_t end, void *_data) +{ + struct search_data *data = _data; + struct jump_key *pos; + int k = 0; + + list_for_each_entry(pos, data->head, entries) { + if (pos->offset >= start && pos->offset < end) { + char header[4]; + + if (k < JUMP_NB) { + int key = '0' + (pos->index % JUMP_NB) + 1; + + sprintf(header, "(%c)", key); + data->keys[k] = key; + data->targets[k] = pos->target; + k++; + } else { + sprintf(header, " "); + } + + memcpy(buf + pos->offset, header, sizeof(header) - 1); + } + } + data->keys[k] = 0; +} + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + struct gstr title; + char *dialog_input; + int dres, vscroll = 0, hscroll = 0; + bool again; + struct gstr sttext; + struct subtitle_part stpart; + + title = str_new(); + str_printf( &title, _("Enter %s (sub)string or regexp to search for " + "(with or without \"%s\")"), CONFIG_, CONFIG_); + +again: + dialog_clear(); + dres = dialog_inputbox(_("Search Configuration Parameter"), + str_get(&title), + 10, 75, ""); + switch (dres) { + case 0: + break; + case 1: + show_helptext(_("Search Configuration"), search_help); + goto again; + default: + str_free(&title); + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sttext = str_new(); + str_printf(&sttext, "Search (%s)", dialog_input_result); + stpart.text = str_get(&sttext); + list_add_tail(&stpart.entries, &trail); + + sym_arr = sym_re_search(dialog_input); + do { + LIST_HEAD(head); + struct menu *targets[JUMP_NB]; + int keys[JUMP_NB + 1], i; + struct search_data data = { + .head = &head, + .targets = targets, + .keys = keys, + }; + struct jump_key *pos, *tmp; + + res = get_relations_str(sym_arr, &head); + set_subtitle(); + dres = show_textbox_ext(_("Search Results"), (char *) + str_get(&res), 0, 0, keys, &vscroll, + &hscroll, &update_text, (void *) + &data); + again = false; + for (i = 0; i < JUMP_NB && keys[i]; i++) + if (dres == keys[i]) { + conf(targets[i]->parent, targets[i]); + again = true; + } + str_free(&res); + list_for_each_entry_safe(pos, tmp, &head, entries) + free(pos); + } while (again); + free(sym_arr); + str_free(&title); + list_del(trail.prev); + str_free(&sttext); +} + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + bool visible; + + /* + * note: menu_is_visible() has side effect that it will + * recalc the value of the symbol. + */ + visible = menu_is_visible(menu); + if (show_all_options && !menu_has_prompt(menu)) + return; + else if (!show_all_options && !visible) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + switch (prop->type) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make("%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(" %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); + item_set_tag('m'); + item_set_data(menu); + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + break; + default: + if (prompt) { + child_count++; + item_make("---%*c%s", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make("[%c]", val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + item_make("<%c>", ch); + break; + } + item_set_tag('t'); + item_set_data(menu); + } else { + item_make(" "); + item_set_tag(def_menu ? 't' : ':'); + item_set_data(menu); + } + + item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_set_tag(':'); + item_set_data(menu); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(" "); + item_set_tag(':'); + item_set_data(menu); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make("[%c]", val == no ? ' ' : '*'); + else + item_make("-%c-", val == no ? ' ' : '*'); + item_set_tag('t'); + item_set_data(menu); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make("{%c}", ch); + else + item_make("<%c>", ch); + } else + item_make("-%c-", ch); + item_set_tag('t'); + item_set_data(menu); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ + item_make("(%s)", sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + item_set_tag('s'); + item_set_data(menu); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt->type == P_MENU) { + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void conf(struct menu *menu, struct menu *active_menu) +{ + struct menu *submenu; + const char *prompt = menu_get_prompt(menu); + struct subtitle_part stpart; + struct symbol *sym; + int res; + int s_scroll = 0; + + if (menu != &rootmenu) + stpart.text = menu_get_prompt(menu); + else + stpart.text = NULL; + list_add_tail(&stpart.entries, &trail); + + while (1) { + item_reset(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + set_subtitle(); + dialog_clear(); + res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + active_menu, &s_scroll); + if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) + break; + if (item_count() != 0) { + if (!item_activate_selected()) + continue; + if (!item_tag()) + continue; + } + submenu = item_data(); + active_menu = item_data(); + if (submenu) + sym = submenu->sym; + else + sym = NULL; + + switch (res) { + case 0: + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = (void *) (long) !submenu->data; + else + conf(submenu, NULL); + break; + case 't': + if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt->type == P_MENU) + conf(submenu, NULL); + break; + case 's': + conf_string(submenu); + break; + } + break; + case 2: + if (sym) + show_help(submenu); + else { + reset_subtitle(); + show_helptext(_("README"), _(mconf_readme)); + } + break; + case 3: + reset_subtitle(); + conf_save(); + break; + case 4: + reset_subtitle(); + conf_load(); + break; + case 5: + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + show_textbox(NULL, setmod_text, 6, 74); + } + break; + case 6: + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 7: + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + case 8: + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu, NULL); + break; + case 9: + search_conf(); + break; + case 10: + show_all_options = !show_all_options; + break; + } + } + + list_del(trail.prev); +} + +static int show_textbox_ext(const char *title, char *text, int r, int c, int + *keys, int *vscroll, int *hscroll, update_text_fn + update_text, void *data) +{ + dialog_clear(); + return dialog_textbox(title, text, r, c, keys, vscroll, hscroll, + update_text, data); +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ + show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL, + NULL, NULL); +} + +static void show_helptext(const char *title, const char *text) +{ + show_textbox(title, text, 0, 0); +} + +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[PATH_MAX+1]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + if (save_and_exit) + printf("%s", buf); + else + show_textbox(NULL, buf, 6, 60); +} + +static void show_help(struct menu *menu) +{ + struct gstr help = str_new(); + + help.max_width = getmaxx(stdscr) - 10; + menu_get_ext_help(menu, &help); + + show_helptext(_(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child; + struct symbol *active; + + active = sym_get_choice_value(menu->sym); + while (1) { + int res; + int selected; + item_reset(); + + current_menu = menu; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (child->sym) + item_make("%s", _(menu_get_prompt(child))); + else { + item_make("*** %s ***", _(menu_get_prompt(child))); + item_set_tag(':'); + } + item_set_data(child); + if (child->sym == active) + item_set_selected(1); + if (child->sym == sym_get_choice_value(menu->sym)) + item_set_tag('X'); + } + dialog_clear(); + res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), + _(radiolist_instructions), + MENUBOX_HEIGTH_MIN, + MENUBOX_WIDTH_MIN, + CHECKLIST_HEIGTH_MIN); + selected = item_activate_selected(); + switch (res) { + case 0: + if (selected) { + child = item_data(); + if (!child->sym) + break; + + sym_set_tristate_value(child->sym, yes); + } + return; + case 1: + if (selected) { + child = item_data(); + show_help(child); + active = child->sym; + } else + show_help(menu); + break; + case KEY_ESC: + return; + case -ERRDISPLAYTOOSMALL: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal mconf error!"); + } + dialog_clear(); + res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), + heading, 10, 75, + sym_get_string_value(menu->sym)); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, dialog_input_result)) + return; + show_textbox(NULL, _("You have made an invalid entry."), 5, 43); + break; + case 1: + show_help(menu); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_load(void) +{ + + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, load_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + show_textbox(NULL, _("File does not exist!"), 5, 38); + break; + case 1: + show_helptext(_("Load Alternate Configuration"), load_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, save_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_write(dialog_input_result)) { + set_config_filename(dialog_input_result); + return; + } + show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); + break; + case 1: + show_helptext(_("Save Alternate Configuration"), save_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static int handle_exit(void) +{ + int res; + + save_and_exit = 1; + reset_subtitle(); + dialog_clear(); + if (conf_get_changed()) + res = dialog_yesno(NULL, + _("Do you wish to save your new configuration?\n" + "(Press to continue kernel configuration.)"), + 6, 60); + else + res = -1; + + end_dialog(saved_x, saved_y); + + switch (res) { + case 0: + if (conf_write(filename)) { + fprintf(stderr, _("\n\n" + "Error while writing of the configuration.\n" + "Your configuration changes were NOT saved." + "\n\n")); + return 1; + } + /* fall through */ + case -1: + printf(_("\n\n" + "*** End of the configuration.\n" + "*** Execute 'make' to start the build or try 'make help'." + "\n\n")); + res = 0; + break; + default: + fprintf(stderr, _("\n\n" + "Your configuration changes were NOT saved." + "\n\n")); + if (res != KEY_ESC) + res = 0; + } + + return res; +} + +static void sig_handler(int signo) +{ + exit(handle_exit()); +} + +int main(int ac, char **av) +{ + char *mode; + int res; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + signal(SIGINT, sig_handler); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("MENUCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + if (init_dialog(NULL)) { + fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); + fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); + return 1; + } + + set_config_filename(conf_get_configname()); + conf_set_message_callback(conf_message_callback); + do { + conf(&rootmenu, NULL); + res = handle_exit(); + } while (res == KEY_ESC); + + return res; +} + diff -Nru seabios-1.7.1/scripts/kconfig/menu.c seabios-1.7.4/scripts/kconfig/menu.c --- seabios-1.7.1/scripts/kconfig/menu.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/menu.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,690 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#include "lkc.h" + +static const char nohelp_text[] = "There is no help available for this option."; + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +void menu_warn(struct menu *menu, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void _menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = xmalloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; + if (sym) + menu_add_symbol(P_SYMBOL, sym, NULL); +} + +void menu_end_entry(void) +{ +} + +struct menu *menu_add_menu(void) +{ + menu_end_entry(); + last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +static struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", + sym->name ? sym->name : "", + sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ + struct property *prop = prop_alloc(type, current_entry->sym); + + prop->menu = current_entry; + prop->expr = expr; + prop->visible.expr = menu_check_dep(dep); + + if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } + if (current_entry->prompt && current_entry != &rootmenu) + prop_warn(prop, "prompt redefined"); + + /* Apply all upper menus' visibilities to actual prompts. */ + if(type == P_PROMPT) { + struct menu *menu = current_entry; + + while ((menu = menu->parent) != NULL) { + struct expr *dup_expr; + + if (!menu->visibility) + continue; + /* + * Do not add a reference to the + * menu's visibility expression but + * use a copy of it. Otherwise the + * expression reduction functions + * will modify expressions that have + * multiple references which can + * cause unwanted side effects. + */ + dup_expr = expr_copy(menu->visibility); + + prop->visible.expr + = expr_alloc_and(prop->visible.expr, + dup_expr); + } + } + + current_entry->prompt = prop; + } + prop->text = prompt; + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ + return menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_visibility(struct expr *expr) +{ + current_entry->visibility = expr_alloc_and(current_entry->visibility, + expr); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ + menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ + menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void menu_add_option(int token, char *arg) +{ + struct property *prop; + + switch (token) { + case T_OPT_MODULES: + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(current_entry->sym); + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + case T_OPT_ENV: + prop_add_env(arg); + break; + } +} + +static int menu_validate_number(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + +static void sym_check_prop(struct symbol *sym) +{ + struct property *prop; + struct symbol *sym2; + for (prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_DEFAULT: + if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && + prop->expr->type != E_SYMBOL) + prop_warn(prop, + "default for config symbol '%s'" + " must be a single symbol", sym->name); + if (prop->expr->type != E_SYMBOL) + break; + sym2 = prop_get_symbol(prop); + if (sym->type == S_HEX || sym->type == S_INT) { + if (!menu_validate_number(sym, sym2)) + prop_warn(prop, + "'%s': number is invalid", + sym->name); + } + break; + case P_SELECT: + sym2 = prop_get_symbol(prop); + if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) + prop_warn(prop, + "config symbol '%s' uses select, but is " + "not boolean or tristate", sym->name); + else if (sym2->type != S_UNKNOWN && + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) + prop_warn(prop, + "'%s' has wrong type. 'select' only " + "accept arguments of boolean and " + "tristate type", sym2->name); + break; + case P_RANGE: + if (sym->type != S_INT && sym->type != S_HEX) + prop_warn(prop, "range is only allowed " + "for int or hex symbols"); + if (!menu_validate_number(sym, prop->expr->left.sym) || + !menu_validate_number(sym, prop->expr->right.sym)) + prop_warn(prop, "range is invalid"); + break; + default: + ; + } + } +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { + menu_set_type(menu->sym->type); + break; + } + } + } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = parent->prompt->visible.expr; + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(prop->visible.expr); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + prop->visible.expr = dep; + if (prop->type == P_SELECT) { + struct symbol *es = prop_get_symbol(prop); + es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, + expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); + } + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym) { + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); + next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + + sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep); + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; + menu->sym->flags |= SYMBOL_CHOICEVAL; + if (!menu->prompt) + menu_warn(menu, "choice value must have a prompt"); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type == P_DEFAULT) + prop_warn(prop, "defaults for choice " + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); + } + /* Non-tristate choice values of tristate choices must + * depend on the choice being set to Y. The choice + * values' dependencies were propagated to their + * properties above, so the change here must be re- + * propagated. + */ + if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { + basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); + menu->dep = expr_alloc_and(basedep, menu->dep); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); + } + } + menu_add_symbol(P_CHOICE, sym, NULL); + prop = sym_get_choice_prop(sym); + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_LIST, NULL); + (*ep)->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } + + if (sym && !(sym->flags & SYMBOL_WARNED)) { + if (sym->type == S_UNKNOWN) + menu_warn(parent, "config symbol defined without type"); + + if (sym_is_choice(sym) && !parent->prompt) + menu_warn(parent, "choice must have a prompt"); + + /* Check properties connected to this symbol */ + sym_check_prop(sym); + sym->flags |= SYMBOL_WARNED; + } + + if (sym && !sym_is_optional(sym) && parent->prompt) { + sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, + expr_alloc_and(parent->prompt->visible.expr, + expr_alloc_symbol(&symbol_mod))); + } +} + +bool menu_has_prompt(struct menu *menu) +{ + if (!menu->prompt) + return false; + return true; +} + +/* + * Determine if a menu is empty. + * A menu is considered empty if it contains no or only + * invisible entries. + */ +bool menu_is_empty(struct menu *menu) +{ + struct menu *child; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) + return(false); + } + return(true); +} + +bool menu_is_visible(struct menu *menu) +{ + struct menu *child; + struct symbol *sym; + tristate visible; + + if (!menu->prompt) + return false; + + if (menu->visibility) { + if (expr_calc_value(menu->visibility) == no) + return no; + } + + sym = menu->sym; + if (sym) { + sym_calc_value(sym); + visible = menu->prompt->visible.tri; + } else + visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + + if (visible != no) + return true; + + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) { + if (sym) + sym->flags |= SYMBOL_DEF_USER; + return true; + } + } + + return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return menu->prompt->text; + else if (menu->sym) + return menu->sym->name; + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + for (; menu != &rootmenu; menu = menu->parent) { + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU) + break; + } + return menu; +} + +bool menu_has_help(struct menu *menu) +{ + return menu->help != NULL; +} + +const char *menu_get_help(struct menu *menu) +{ + if (menu->help) + return menu->help; + else + return ""; +} + +static void get_prompt_str(struct gstr *r, struct property *prop, + struct list_head *head) +{ + int i, j; + struct menu *submenu[8], *menu, *location = NULL; + struct jump_key *jump; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + menu = prop->menu->parent; + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { + bool accessible = menu_is_visible(menu); + + submenu[i++] = menu; + if (location == NULL && accessible) + location = menu; + } + if (head && location) { + jump = xmalloc(sizeof(struct jump_key)); + + if (menu_is_visible(prop->menu)) { + /* + * There is not enough room to put the hint at the + * beginning of the "Prompt" line. Put the hint on the + * last "Location" line even when it would belong on + * the former. + */ + jump->target = prop->menu; + } else + jump->target = location; + + if (list_empty(head)) + jump->index = 0; + else + jump->index = list_entry(head->prev, struct jump_key, + entries)->index + 1; + + list_add_tail(&jump->entries, head); + } + + if (i > 0) { + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; + if (head && location && menu == location) + jump->offset = r->len - 1; + str_printf(r, "%*c-> %s", j, ' ', + _(menu_get_prompt(menu))); + if (menu->sym) { + str_printf(r, " (%s [=%s])", menu->sym->name ? + menu->sym->name : _(""), + sym_get_string_value(menu->sym)); + } + str_append(r, "\n"); + } + } +} + +/* + * get peoperty of type P_SYMBOL + */ +static struct property *get_symbol_prop(struct symbol *sym) +{ + struct property *prop = NULL; + + for_all_properties(sym, prop, P_SYMBOL) + break; + return prop; +} + +/* + * head is optional and may be NULL + */ +void get_symbol_str(struct gstr *r, struct symbol *sym, + struct list_head *head) +{ + bool hit; + struct property *prop; + + if (sym && sym->name) { + str_printf(r, "Symbol: %s [=%s]\n", sym->name, + sym_get_string_value(sym)); + str_printf(r, "Type : %s\n", sym_type_name(sym->type)); + if (sym->type == S_INT || sym->type == S_HEX) { + prop = sym_get_range_prop(sym); + if (prop) { + str_printf(r, "Range : "); + expr_gstr_print(prop->expr, r); + str_append(r, "\n"); + } + } + } + for_all_prompts(sym, prop) + get_prompt_str(r, prop, head); + + prop = get_symbol_prop(sym); + if (prop) { + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + prop->menu->lineno); + if (!expr_is_yes(prop->visible.expr)) { + str_append(r, _(" Depends on: ")); + expr_gstr_print(prop->visible.expr, r); + str_append(r, "\n"); + } + } + + hit = false; + for_all_properties(sym, prop, P_SELECT) { + if (!hit) { + str_append(r, " Selects: "); + hit = true; + } else + str_printf(r, " && "); + expr_gstr_print(prop->expr, r); + } + if (hit) + str_append(r, "\n"); + if (sym->rev_dep.expr) { + str_append(r, _(" Selected by: ")); + expr_gstr_print(sym->rev_dep.expr, r); + str_append(r, "\n"); + } + str_append(r, "\n\n"); +} + +struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head) +{ + struct symbol *sym; + struct gstr res = str_new(); + int i; + + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) + get_symbol_str(&res, sym, head); + if (!i) + str_append(&res, _("No matches found.\n")); + return res; +} + + +void menu_get_ext_help(struct menu *menu, struct gstr *help) +{ + struct symbol *sym = menu->sym; + const char *help_text = nohelp_text; + + if (menu_has_help(menu)) { + if (sym->name) + str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); + help_text = menu_get_help(menu); + } + str_printf(help, "%s\n", _(help_text)); + if (sym) + get_symbol_str(help, sym, NULL); +} diff -Nru seabios-1.7.1/scripts/kconfig/merge_config.sh seabios-1.7.4/scripts/kconfig/merge_config.sh --- seabios-1.7.1/scripts/kconfig/merge_config.sh 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/merge_config.sh 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,150 @@ +#!/bin/sh +# merge_config.sh - Takes a list of config fragment values, and merges +# them one by one. Provides warnings on overridden values, and specified +# values that did not make it to the resulting .config file (due to missed +# dependencies or config symbol removal). +# +# Portions reused from kconf_check and generate_cfg: +# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check +# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg +# +# Copyright (c) 2009-2010 Wind River Systems, Inc. +# Copyright 2011 Linaro +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. + +clean_up() { + rm -f $TMP_FILE + exit +} +trap clean_up HUP INT TERM + +usage() { + echo "Usage: $0 [OPTIONS] [CONFIG [...]]" + echo " -h display this help text" + echo " -m only merge the fragments, do not execute the make command" + echo " -n use allnoconfig instead of alldefconfig" + echo " -r list redundant entries when merging fragments" + echo " -O dir to put generated output files" +} + +MAKE=true +ALLTARGET=alldefconfig +WARNREDUN=false +OUTPUT=. + +while true; do + case $1 in + "-n") + ALLTARGET=allnoconfig + shift + continue + ;; + "-m") + MAKE=false + shift + continue + ;; + "-h") + usage + exit + ;; + "-r") + WARNREDUN=true + shift + continue + ;; + "-O") + if [ -d $2 ];then + OUTPUT=$(echo $2 | sed 's/\/*$//') + else + echo "output directory $2 does not exist" 1>&2 + exit 1 + fi + shift 2 + continue + ;; + *) + break + ;; + esac +done + +INITFILE=$1 +shift; + +MERGE_LIST=$* +SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p" +TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX) + +echo "Using $INITFILE as base" +cat $INITFILE > $TMP_FILE + +# Merge files, printing warnings on overrided values +for MERGE_FILE in $MERGE_LIST ; do + echo "Merging $MERGE_FILE" + CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE) + + for CFG in $CFG_LIST ; do + grep -q -w $CFG $TMP_FILE + if [ $? -eq 0 ] ; then + PREV_VAL=$(grep -w $CFG $TMP_FILE) + NEW_VAL=$(grep -w $CFG $MERGE_FILE) + if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then + echo Value of $CFG is redefined by fragment $MERGE_FILE: + echo Previous value: $PREV_VAL + echo New value: $NEW_VAL + echo + elif [ "$WARNREDUN" = "true" ]; then + echo Value of $CFG is redundant by fragment $MERGE_FILE: + fi + sed -i "/$CFG[ =]/d" $TMP_FILE + fi + done + cat $MERGE_FILE >> $TMP_FILE +done + +if [ "$MAKE" = "false" ]; then + cp $TMP_FILE $OUTPUT/.config + echo "#" + echo "# merged configuration written to $OUTPUT/.config (needs make)" + echo "#" + clean_up + exit +fi + +# If we have an output dir, setup the O= argument, otherwise leave +# it blank, since O=. will create an unnecessary ./source softlink +OUTPUT_ARG="" +if [ "$OUTPUT" != "." ] ; then + OUTPUT_ARG="O=$OUTPUT" +fi + + +# Use the merged file as the starting point for: +# alldefconfig: Fills in any missing symbols with Kconfig default +# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set +make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET + + +# Check all specified config values took (might have missed-dependency issues) +for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do + + REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE) + ACTUAL_VAL=$(grep -w -e "$CFG" $OUTPUT/.config) + if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then + echo "Value requested for $CFG not in final .config" + echo "Requested value: $REQUESTED_VAL" + echo "Actual value: $ACTUAL_VAL" + echo "" + fi +done + +clean_up diff -Nru seabios-1.7.1/scripts/kconfig/nconf.c seabios-1.7.4/scripts/kconfig/nconf.c --- seabios-1.7.1/scripts/kconfig/nconf.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/nconf.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1557 @@ +/* + * Copyright (C) 2008 Nir Tzachar +#include + +#include "lkc.h" +#include "nconf.h" +#include + +static const char nconf_global_help[] = N_( +"Help windows\n" +"------------\n" +"o Global help: Unless in a data entry window, pressing will give \n" +" you the global help window, which you are just reading.\n" +"\n" +"o A short version of the global help is available by pressing .\n" +"\n" +"o Local help: To get help related to the current menu entry, use any\n" +" of , or if in a data entry window then press .\n" +"\n" +"\n" +"Menu entries\n" +"------------\n" +"This interface lets you select features and parameters for the kernel\n" +"build. Kernel features can either be built-in, modularized, or removed.\n" +"Parameters must be entered as text or decimal or hexadecimal numbers.\n" +"\n" +"Menu entries beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized, are selected by another feature\n" +" - - are selected by another feature\n" +" XXX cannot be selected. Symbol Info tells you why.\n" +"*, M or whitespace inside braces means to build in, build as a module\n" +"or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the movement keys\n" +"listed below and press to build it in, to make it a module or\n" +" to remove it. You may press the key to cycle through the\n" +"available options.\n" +"\n" +"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n" +"empty submenu.\n" +"\n" +"Menu navigation keys\n" +"----------------------------------------------------------------------\n" +"Linewise up \n" +"Linewise down \n" +"Pagewise up \n" +"Pagewise down \n" +"First entry \n" +"Last entry \n" +"Enter a submenu \n" +"Go back to parent menu \n" +"Close a help window \n" +"Close entry window, apply \n" +"Close entry window, forget \n" +"Start incremental, case-insensitive search for STRING in menu entries,\n" +" no regex support, STRING is displayed in upper left corner\n" +" STRING\n" +" Remove last character \n" +" Jump to next hit \n" +" Jump to previous hit \n" +"Exit menu search mode \n" +"Search for configuration variables with or without leading CONFIG_\n" +" RegExpr\n" +"Verbose search help \n" +"----------------------------------------------------------------------\n" +"\n" +"Unless in a data entry window, key <1> may be used instead of ,\n" +"<2> instead of , etc.\n" +"\n" +"\n" +"Radiolist (Choice list)\n" +"-----------------------\n" +"Use the movement keys listed above to select the option you wish to set\n" +"and press .\n" +"\n" +"\n" +"Data entry\n" +"----------\n" +"Enter the requested information and press . Hexadecimal values\n" +"may be entered without the \"0x\" prefix.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"----------------------\n" +"Use movement keys as listed in table above.\n" +"\n" +"Press any of to exit.\n" +"\n" +"\n" +"Alternate configuration files\n" +"-----------------------------\n" +"nconfig supports switching between different configurations.\n" +"Press to save your current configuration. Press and enter\n" +"a file name to load a previously saved configuration.\n" +"\n" +"\n" +"Terminal configuration\n" +"----------------------\n" +"If you use nconfig in a xterm window, make sure your TERM environment\n" +"variable specifies a terminal configuration which supports at least\n" +"16 colors. Otherwise nconfig will look rather bad.\n" +"\n" +"If the \"stty size\" command reports the current terminalsize correctly,\n" +"nconfig will adapt to sizes larger than the traditional 80x25 \"standard\"\n" +"and display longer menus properly.\n" +"\n" +"\n" +"Single menu mode\n" +"----------------\n" +"If you prefer to have all of the menu entries listed in a single menu,\n" +"rather than the default multimenu hierarchy, run nconfig with\n" +"NCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make NCONFIG_MODE=single_menu nconfig\n" +"\n" +" will then unfold the appropriate category, or fold it if it\n" +"is already unfolded. Folded menu entries will be designated by a\n" +"leading \"++>\" and unfolded entries by a leading \"-->\".\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive than\n" +"the default mode, especially with a larger number of unfolded submenus.\n" +"\n"), +menu_no_f_instructions[] = N_( +"Legend: [*] built-in [ ] excluded module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with and .\n" +"Enter a submenu with or .\n" +"Exit a submenu to its parent menu with or .\n" +"Pressing includes, excludes, modularizes features.\n" +"Pressing cycles through the available options.\n" +"To search for menu entries press .\n" +" always leaves the current window.\n" +"\n" +"You do not have function keys support.\n" +"Press <1> instead of , <2> instead of , etc.\n" +"For verbose global help use key <1>.\n" +"For help related to the current menu entry press or .\n"), +menu_instructions[] = N_( +"Legend: [*] built-in [ ] excluded module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with or .\n" +"Enter a submenu with or .\n" +"Exit a submenu to its parent menu with or .\n" +"Pressing includes, excludes, modularizes features.\n" +"Pressing cycles through the available options.\n" +"To search for menu entries press .\n" +" always leaves the current window.\n" +"\n" +"Pressing <1> may be used instead of , <2> instead of , etc.\n" +"For verbose global help press .\n" +"For help related to the current menu entry press or .\n"), +radiolist_instructions[] = N_( +"Press , , or to navigate a radiolist, select\n" +"with .\n" +"For help related to the current entry press or .\n" +"For global help press .\n"), +inputbox_instructions_int[] = N_( +"Please enter a decimal value.\n" +"Fractions will not be accepted.\n" +"Press to apply, to cancel."), +inputbox_instructions_hex[] = N_( +"Please enter a hexadecimal value.\n" +"Press to apply, to cancel."), +inputbox_instructions_string[] = N_( +"Please enter a string value.\n" +"Press to apply, to cancel."), +setmod_text[] = N_( +"This feature depends on another feature which has been configured as a\n" +"module. As a result, the current feature will be built as a module too."), +load_config_text[] = N_( +"Enter the name of the configuration file you wish to load.\n" +"Accept the name shown to restore the configuration you last\n" +"retrieved. Leave empty to abort."), +load_config_help[] = N_( +"For various reasons, one may wish to keep several different\n" +"configurations available on a single machine.\n" +"\n" +"If you have saved a previous configuration in a file other than the\n" +"default one, entering its name here will allow you to load and modify\n" +"that configuration.\n" +"\n" +"Leave empty to abort.\n"), +save_config_text[] = N_( +"Enter a filename to which this configuration should be saved\n" +"as an alternate. Leave empty to abort."), +save_config_help[] = N_( +"For various reasons, one may wish to keep several different\n" +"configurations available on a single machine.\n" +"\n" +"Entering a file name here will allow you to later retrieve, modify\n" +"and use the current configuration as an alternate to whatever\n" +"configuration options you have selected at that time.\n" +"\n" +"Leave empty to abort.\n"), +search_help[] = N_( +"Search for symbols (configuration variable names CONFIG_*) and display\n" +"their relations. Regular expressions are supported.\n" +"Example: Search for \"^FOO\".\n" +"Result:\n" +"-----------------------------------------------------------------\n" +"Symbol: FOO [ = m]\n" +"Prompt: Foo bus is used to drive the bar HW\n" +"Defined at drivers/pci/Kconfig:47\n" +"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" +"Location:\n" +" -> Bus options (PCI, PCMCIA, EISA, ISA)\n" +" -> PCI support (PCI [ = y])\n" +" -> PCI access mode ( [ = y])\n" +"Selects: LIBCRC32\n" +"Selected by: BAR\n" +"-----------------------------------------------------------------\n" +"o The line 'Prompt:' shows the text displayed for this symbol in\n" +" the menu hierarchy.\n" +"o The 'Defined at' line tells at what file / line number the symbol is\n" +" defined.\n" +"o The 'Depends on:' line lists symbols that need to be defined for\n" +" this symbol to be visible and selectable in the menu.\n" +"o The 'Location:' lines tell, where in the menu structure this symbol\n" +" is located. A location followed by a [ = y] indicates that this is\n" +" a selectable menu item, and the current value is displayed inside\n" +" brackets.\n" +"o The 'Selects:' line tells, what symbol will be automatically selected\n" +" if this symbol is selected (y or m).\n" +"o The 'Selected by' line tells what symbol has selected this symbol.\n" +"\n" +"Only relevant lines are shown.\n" +"\n\n" +"Search examples:\n" +"USB => find all symbols containing USB\n" +"^USB => find all symbols starting with USB\n" +"USB$ => find all symbols ending with USB\n" +"\n"); + +struct mitem { + char str[256]; + char tag; + void *usrptr; + int is_visible; +}; + +#define MAX_MENU_ITEMS 4096 +static int show_all_items; +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +/* the window in which all information appears */ +static WINDOW *main_window; +/* the largest size of the menu window */ +static int mwin_max_lines; +static int mwin_max_cols; +/* the window in which we show option buttons */ +static MENU *curses_menu; +static ITEM *curses_menu_items[MAX_MENU_ITEMS]; +static struct mitem k_menu_items[MAX_MENU_ITEMS]; +static int items_num; +static int global_exit; +/* the currently selected button */ +const char *current_instructions = menu_instructions; + +static char *dialog_input_result; +static int dialog_input_result_len; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_help(struct menu *menu); +static int do_exit(void); +static void setup_windows(void); +static void search_conf(void); + +typedef void (*function_key_handler_t)(int *key, struct menu *menu); +static void handle_f1(int *key, struct menu *current_item); +static void handle_f2(int *key, struct menu *current_item); +static void handle_f3(int *key, struct menu *current_item); +static void handle_f4(int *key, struct menu *current_item); +static void handle_f5(int *key, struct menu *current_item); +static void handle_f6(int *key, struct menu *current_item); +static void handle_f7(int *key, struct menu *current_item); +static void handle_f8(int *key, struct menu *current_item); +static void handle_f9(int *key, struct menu *current_item); + +struct function_keys { + const char *key_str; + const char *func; + function_key key; + function_key_handler_t handler; +}; + +static const int function_keys_num = 9; +struct function_keys function_keys[] = { + { + .key_str = "F1", + .func = "Help", + .key = F_HELP, + .handler = handle_f1, + }, + { + .key_str = "F2", + .func = "SymInfo", + .key = F_SYMBOL, + .handler = handle_f2, + }, + { + .key_str = "F3", + .func = "Help 2", + .key = F_INSTS, + .handler = handle_f3, + }, + { + .key_str = "F4", + .func = "ShowAll", + .key = F_CONF, + .handler = handle_f4, + }, + { + .key_str = "F5", + .func = "Back", + .key = F_BACK, + .handler = handle_f5, + }, + { + .key_str = "F6", + .func = "Save", + .key = F_SAVE, + .handler = handle_f6, + }, + { + .key_str = "F7", + .func = "Load", + .key = F_LOAD, + .handler = handle_f7, + }, + { + .key_str = "F8", + .func = "SymSearch", + .key = F_SEARCH, + .handler = handle_f8, + }, + { + .key_str = "F9", + .func = "Exit", + .key = F_EXIT, + .handler = handle_f9, + }, +}; + +static void print_function_line(void) +{ + int i; + int offset = 1; + const int skip = 1; + int lines = getmaxy(stdscr); + + for (i = 0; i < function_keys_num; i++) { + (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); + mvwprintw(main_window, lines-3, offset, + "%s", + function_keys[i].key_str); + (void) wattrset(main_window, attributes[FUNCTION_TEXT]); + offset += strlen(function_keys[i].key_str); + mvwprintw(main_window, lines-3, + offset, "%s", + function_keys[i].func); + offset += strlen(function_keys[i].func) + skip; + } + (void) wattrset(main_window, attributes[NORMAL]); +} + +/* help */ +static void handle_f1(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("Global help"), _(nconf_global_help)); + return; +} + +/* symbole help */ +static void handle_f2(int *key, struct menu *current_item) +{ + show_help(current_item); + return; +} + +/* instructions */ +static void handle_f3(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("Short help"), + _(current_instructions)); + return; +} + +/* config */ +static void handle_f4(int *key, struct menu *current_item) +{ + int res = btn_dialog(main_window, + _("Show all symbols?"), + 2, + " ", + ""); + if (res == 0) + show_all_items = 1; + else if (res == 1) + show_all_items = 0; + + return; +} + +/* back */ +static void handle_f5(int *key, struct menu *current_item) +{ + *key = KEY_LEFT; + return; +} + +/* save */ +static void handle_f6(int *key, struct menu *current_item) +{ + conf_save(); + return; +} + +/* load */ +static void handle_f7(int *key, struct menu *current_item) +{ + conf_load(); + return; +} + +/* search */ +static void handle_f8(int *key, struct menu *current_item) +{ + search_conf(); + return; +} + +/* exit */ +static void handle_f9(int *key, struct menu *current_item) +{ + do_exit(); + return; +} + +/* return != 0 to indicate the key was handles */ +static int process_special_keys(int *key, struct menu *menu) +{ + int i; + + if (*key == KEY_RESIZE) { + setup_windows(); + return 1; + } + + for (i = 0; i < function_keys_num; i++) { + if (*key == KEY_F(function_keys[i].key) || + *key == '0' + function_keys[i].key){ + function_keys[i].handler(key, menu); + return 1; + } + } + + return 0; +} + +static void clean_items(void) +{ + int i; + for (i = 0; curses_menu_items[i]; i++) + free_item(curses_menu_items[i]); + bzero(curses_menu_items, sizeof(curses_menu_items)); + bzero(k_menu_items, sizeof(k_menu_items)); + items_num = 0; +} + +typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN, + FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f; + +/* return the index of the matched item, or -1 if no such item exists */ +static int get_mext_match(const char *match_str, match_f flag) +{ + int match_start = item_index(current_item(curses_menu)); + int index; + + if (flag == FIND_NEXT_MATCH_DOWN) + ++match_start; + else if (flag == FIND_NEXT_MATCH_UP) + --match_start; + + index = match_start; + index = (index + items_num) % items_num; + while (true) { + char *str = k_menu_items[index].str; + if (strcasestr(str, match_str) != 0) + return index; + if (flag == FIND_NEXT_MATCH_UP || + flag == MATCH_TINKER_PATTERN_UP) + --index; + else + ++index; + index = (index + items_num) % items_num; + if (index == match_start) + return -1; + } +} + +/* Make a new item. */ +static void item_make(struct menu *menu, char tag, const char *fmt, ...) +{ + va_list ap; + + if (items_num > MAX_MENU_ITEMS-1) + return; + + bzero(&k_menu_items[items_num], sizeof(k_menu_items[0])); + k_menu_items[items_num].tag = tag; + k_menu_items[items_num].usrptr = menu; + if (menu != NULL) + k_menu_items[items_num].is_visible = + menu_is_visible(menu); + else + k_menu_items[items_num].is_visible = 1; + + va_start(ap, fmt); + vsnprintf(k_menu_items[items_num].str, + sizeof(k_menu_items[items_num].str), + fmt, ap); + va_end(ap); + + if (!k_menu_items[items_num].is_visible) + memcpy(k_menu_items[items_num].str, "XXX", 3); + + curses_menu_items[items_num] = new_item( + k_menu_items[items_num].str, + k_menu_items[items_num].str); + set_item_userptr(curses_menu_items[items_num], + &k_menu_items[items_num]); + /* + if (!k_menu_items[items_num].is_visible) + item_opts_off(curses_menu_items[items_num], O_SELECTABLE); + */ + + items_num++; + curses_menu_items[items_num] = NULL; +} + +/* very hackish. adds a string to the last item added */ +static void item_add_str(const char *fmt, ...) +{ + va_list ap; + int index = items_num-1; + char new_str[256]; + char tmp_str[256]; + + if (index < 0) + return; + + va_start(ap, fmt); + vsnprintf(new_str, sizeof(new_str), fmt, ap); + va_end(ap); + snprintf(tmp_str, sizeof(tmp_str), "%s%s", + k_menu_items[index].str, new_str); + strncpy(k_menu_items[index].str, + tmp_str, + sizeof(k_menu_items[index].str)); + + free_item(curses_menu_items[index]); + curses_menu_items[index] = new_item( + k_menu_items[index].str, + k_menu_items[index].str); + set_item_userptr(curses_menu_items[index], + &k_menu_items[index]); +} + +/* get the tag of the currently selected item */ +static char item_tag(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (cur == NULL) + return 0; + mcur = (struct mitem *) item_userptr(cur); + return mcur->tag; +} + +static int curses_item_index(void) +{ + return item_index(current_item(curses_menu)); +} + +static void *item_data(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (!cur) + return NULL; + mcur = (struct mitem *) item_userptr(cur); + return mcur->usrptr; + +} + +static int item_is_tag(char tag) +{ + return item_tag() == tag; +} + +static char filename[PATH_MAX+1]; +static char menu_backtitle[PATH_MAX+128]; +static const char *set_config_filename(const char *config_filename) +{ + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; + return menu_backtitle; +} + +/* return = 0 means we are successful. + * -1 means go on doing what you were doing + */ +static int do_exit(void) +{ + int res; + if (!conf_get_changed()) { + global_exit = 1; + return 0; + } + res = btn_dialog(main_window, + _("Do you wish to save your new configuration?\n" + " to cancel and resume nconfig."), + 2, + " ", + ""); + if (res == KEY_EXIT) { + global_exit = 0; + return -1; + } + + /* if we got here, the user really wants to exit */ + switch (res) { + case 0: + res = conf_write(filename); + if (res) + btn_dialog( + main_window, + _("Error during writing of configuration.\n" + "Your configuration changes were NOT saved."), + 1, + ""); + break; + default: + btn_dialog( + main_window, + _("Your configuration changes were NOT saved."), + 1, + ""); + break; + } + global_exit = 1; + return 0; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + struct gstr title; + char *dialog_input; + int dres; + + title = str_new(); + str_printf( &title, _("Enter %s (sub)string or regexp to search for " + "(with or without \"%s\")"), CONFIG_, CONFIG_); + +again: + dres = dialog_inputbox(main_window, + _("Search Configuration Parameter"), + str_get(&title), + "", &dialog_input_result, &dialog_input_result_len); + switch (dres) { + case 0: + break; + case 1: + show_scroll_win(main_window, + _("Search Configuration"), search_help); + goto again; + default: + str_free(&title); + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr, NULL); + free(sym_arr); + show_scroll_win(main_window, + _("Search Results"), str_get(&res)); + str_free(&res); + str_free(&title); +} + + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + + if (!menu || (!show_all_items && !menu_is_visible(menu))) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make(menu, 'm', + "%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(menu, 'm', + " %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); + + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(menu, ':', + " %*c*** %s ***", + indent + 1, ' ', + _(prompt)); + } + break; + default: + if (prompt) { + child_count++; + item_make(menu, ':', "---%*c%s", + indent + 1, ' ', + _(prompt)); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + item_make(menu, 't', "<%c>", ch); + break; + } + } else { + item_make(menu, def_menu ? 't' : ':', " "); + } + + item_add_str("%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", + _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make(menu, ':', + "---%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(menu, ':', " "); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + else + item_make(menu, 't', "-%c-", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make(menu, + 't', "{%c}", ch); + else + item_make(menu, + 't', "<%c>", ch); + } else + item_make(menu, 't', "-%c-", ch); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); + item_make(menu, 's', " (%s)", + sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || + !sym_is_changable(sym)) ? "" : + _(" (NEW)")); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt && menu->prompt->type == P_MENU) { + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void reset_menu(void) +{ + unpost_menu(curses_menu); + clean_items(); +} + +/* adjust the menu to show this item. + * prefer not to scroll the menu if possible*/ +static void center_item(int selected_index, int *last_top_row) +{ + int toprow; + + set_top_row(curses_menu, *last_top_row); + toprow = top_row(curses_menu); + if (selected_index < toprow || + selected_index >= toprow+mwin_max_lines) { + toprow = max(selected_index-mwin_max_lines/2, 0); + if (toprow >= item_count(curses_menu)-mwin_max_lines) + toprow = item_count(curses_menu)-mwin_max_lines; + set_top_row(curses_menu, toprow); + } + set_current_item(curses_menu, + curses_menu_items[selected_index]); + *last_top_row = toprow; + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +/* this function assumes reset_menu has been called before */ +static void show_menu(const char *prompt, const char *instructions, + int selected_index, int *last_top_row) +{ + int maxx, maxy; + WINDOW *menu_window; + + current_instructions = instructions; + + clear(); + (void) wattrset(main_window, attributes[NORMAL]); + print_in_middle(stdscr, 1, 0, getmaxx(stdscr), + menu_backtitle, + attributes[MAIN_HEADING]); + + (void) wattrset(main_window, attributes[MAIN_MENU_BOX]); + box(main_window, 0, 0); + (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]); + mvwprintw(main_window, 0, 3, " %s ", prompt); + (void) wattrset(main_window, attributes[NORMAL]); + + set_menu_items(curses_menu, curses_menu_items); + + /* position the menu at the middle of the screen */ + scale_menu(curses_menu, &maxy, &maxx); + maxx = min(maxx, mwin_max_cols-2); + maxy = mwin_max_lines; + menu_window = derwin(main_window, + maxy, + maxx, + 2, + (mwin_max_cols-maxx)/2); + keypad(menu_window, TRUE); + set_menu_win(curses_menu, menu_window); + set_menu_sub(curses_menu, menu_window); + + /* must reassert this after changing items, otherwise returns to a + * default of 16 + */ + set_menu_format(curses_menu, maxy, 1); + center_item(selected_index, last_top_row); + set_menu_format(curses_menu, maxy, 1); + + print_function_line(); + + /* Post the menu */ + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +static void adj_match_dir(match_f *match_direction) +{ + if (*match_direction == FIND_NEXT_MATCH_DOWN) + *match_direction = + MATCH_TINKER_PATTERN_DOWN; + else if (*match_direction == FIND_NEXT_MATCH_UP) + *match_direction = + MATCH_TINKER_PATTERN_UP; + /* else, do no change.. */ +} + +struct match_state +{ + int in_search; + match_f match_direction; + char pattern[256]; +}; + +/* Return 0 means I have handled the key. In such a case, ans should hold the + * item to center, or -1 otherwise. + * Else return -1 . + */ +static int do_match(int key, struct match_state *state, int *ans) +{ + char c = (char) key; + int terminate_search = 0; + *ans = -1; + if (key == '/' || (state->in_search && key == 27)) { + move(0, 0); + refresh(); + clrtoeol(); + state->in_search = 1-state->in_search; + bzero(state->pattern, sizeof(state->pattern)); + state->match_direction = MATCH_TINKER_PATTERN_DOWN; + return 0; + } else if (!state->in_search) + return 1; + + if (isalnum(c) || isgraph(c) || c == ' ') { + state->pattern[strlen(state->pattern)] = c; + state->pattern[strlen(state->pattern)] = '\0'; + adj_match_dir(&state->match_direction); + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_DOWN) { + state->match_direction = FIND_NEXT_MATCH_DOWN; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_UP) { + state->match_direction = FIND_NEXT_MATCH_UP; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_BACKSPACE || key == 127) { + state->pattern[strlen(state->pattern)-1] = '\0'; + adj_match_dir(&state->match_direction); + } else + terminate_search = 1; + + if (terminate_search) { + state->in_search = 0; + bzero(state->pattern, sizeof(state->pattern)); + move(0, 0); + refresh(); + clrtoeol(); + return -1; + } + return 0; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu = 0; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + int res; + int current_index = 0; + int last_top_row = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + while (!global_exit) { + reset_menu(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + + show_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + current_index, &last_top_row); + keypad((menu_win(curses_menu)), TRUE); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, + "searching: %s", match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, ¤t_index) == 0) { + if (current_index != -1) + center_item(current_index, + &last_top_row); + continue; + } + if (process_special_keys(&res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || + res == 32 || res == 'n' || res == 'y' || + res == KEY_LEFT || res == KEY_RIGHT || + res == 'm') + break; + refresh_all_windows(main_window); + } + + refresh_all_windows(main_window); + /* if ESC or left*/ + if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) + break; + + /* remember location in the menu */ + last_top_row = top_row(curses_menu); + current_index = curses_item_index(); + + if (!item_tag()) + continue; + + submenu = (struct menu *) item_data(); + if (!submenu || !menu_is_visible(submenu)) + continue; + sym = submenu->sym; + + switch (res) { + case ' ': + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case KEY_RIGHT: + case 10: /* ENTER WAS PRESSED */ + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = + (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && + sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt && + submenu->prompt->type == P_MENU) + conf(submenu); + else if (res == 10) + sym_toggle_tristate_value(sym); + break; + case 's': + conf_string(submenu); + break; + } + break; + case 'y': + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + btn_dialog(main_window, setmod_text, 0); + } + break; + case 'n': + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 'm': + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + } + } +} + +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[1024]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + btn_dialog(main_window, buf, 1, ""); +} + +static void show_help(struct menu *menu) +{ + struct gstr help; + + if (!menu) + return; + + help = str_new(); + menu_get_ext_help(menu, &help); + show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child = 0; + struct symbol *active; + int selected_index = 0; + int last_top_row = 0; + int res, i = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + active = sym_get_choice_value(menu->sym); + /* this is mostly duplicated from the conf() function. */ + while (!global_exit) { + reset_menu(); + + for (i = 0, child = menu->list; child; child = child->next) { + if (!show_all_items && !menu_is_visible(child)) + continue; + + if (child->sym == sym_get_choice_value(menu->sym)) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else if (child->sym) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else + item_make(child, ':', "*** %s ***", + _(menu_get_prompt(child))); + + if (child->sym == active){ + last_top_row = top_row(curses_menu); + selected_index = i; + } + i++; + } + show_menu(prompt ? _(prompt) : _("Choice Menu"), + _(radiolist_instructions), + selected_index, + &last_top_row); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, "searching: %s", + match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, &selected_index) == 0) { + if (selected_index != -1) + center_item(selected_index, + &last_top_row); + continue; + } + if (process_special_keys( + &res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || res == ' ' || + res == KEY_LEFT){ + break; + } + refresh_all_windows(main_window); + } + /* if ESC or left */ + if (res == 27 || res == KEY_LEFT) + break; + + child = item_data(); + if (!child || !menu_is_visible(child) || !child->sym) + continue; + switch (res) { + case ' ': + case 10: + case KEY_RIGHT: + sym_set_tristate_value(child->sym, yes); + return; + case 'h': + case '?': + show_help(child); + active = child->sym; + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal nconf error!"); + } + res = dialog_inputbox(main_window, + prompt ? _(prompt) : _("Main Menu"), + heading, + sym_get_string_value(menu->sym), + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, + dialog_input_result)) + return; + btn_dialog(main_window, + _("You have made an invalid entry."), 0); + break; + case 1: + show_help(menu); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_load(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, load_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + btn_dialog(main_window, _("File does not exist!"), 0); + break; + case 1: + show_scroll_win(main_window, + _("Load Alternate Configuration"), + load_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, save_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + res = conf_write(dialog_input_result); + if (!res) { + set_config_filename(dialog_input_result); + return; + } + btn_dialog(main_window, _("Can't create file! " + "Probably a nonexistent directory."), + 1, ""); + break; + case 1: + show_scroll_win(main_window, + _("Save Alternate Configuration"), + save_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +void setup_windows(void) +{ + int lines, columns; + + getmaxyx(stdscr, lines, columns); + + if (main_window != NULL) + delwin(main_window); + + /* set up the menu and menu window */ + main_window = newwin(lines-2, columns-2, 2, 1); + keypad(main_window, TRUE); + mwin_max_lines = lines-7; + mwin_max_cols = columns-6; + + /* panels order is from bottom to top */ + new_panel(main_window); +} + +int main(int ac, char **av) +{ + int lines, columns; + char *mode; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("NCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + /* Initialize curses */ + initscr(); + /* set color theme */ + set_colors(); + + cbreak(); + noecho(); + keypad(stdscr, TRUE); + curs_set(0); + + getmaxyx(stdscr, lines, columns); + if (columns < 75 || lines < 20) { + endwin(); + printf("Your terminal should have at " + "least 20 lines and 75 columns\n"); + return 1; + } + + notimeout(stdscr, FALSE); +#if NCURSES_REENTRANT + set_escdelay(1); +#else + ESCDELAY = 1; +#endif + + /* set btns menu */ + curses_menu = new_menu(curses_menu_items); + menu_opts_off(curses_menu, O_SHOWDESC); + menu_opts_on(curses_menu, O_SHOWMATCH); + menu_opts_on(curses_menu, O_ONEVALUE); + menu_opts_on(curses_menu, O_NONCYCLIC); + menu_opts_on(curses_menu, O_IGNORECASE); + set_menu_mark(curses_menu, " "); + set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); + set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); + set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]); + + set_config_filename(conf_get_configname()); + setup_windows(); + + /* check for KEY_FUNC(1) */ + if (has_key(KEY_F(1)) == FALSE) { + show_scroll_win(main_window, + _("Instructions"), + _(menu_no_f_instructions)); + } + + conf_set_message_callback(conf_message_callback); + /* do the work */ + while (!global_exit) { + conf(&rootmenu); + if (!global_exit && do_exit() == 0) + break; + } + /* ok, we are done */ + unpost_menu(curses_menu); + free_menu(curses_menu); + delwin(main_window); + clear(); + refresh(); + endwin(); + return 0; +} + diff -Nru seabios-1.7.1/scripts/kconfig/nconf.gui.c seabios-1.7.4/scripts/kconfig/nconf.gui.c --- seabios-1.7.1/scripts/kconfig/nconf.gui.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/nconf.gui.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2008 Nir Tzachar 0) + win_rows = msg_lines+4; + else + win_rows = msg_lines+2; + + win = newwin(win_rows, total_width+4, y, x); + keypad(win, TRUE); + menu_win = derwin(win, 1, btns_width, win_rows-2, + 1+(total_width+2-btns_width)/2); + menu = new_menu(btns); + msg_win = derwin(win, win_rows-2, msg_width, 1, + 1+(total_width+2-msg_width)/2); + + set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); + set_menu_back(menu, attributes[DIALOG_MENU_BACK]); + + (void) wattrset(win, attributes[DIALOG_BOX]); + box(win, 0, 0); + + /* print message */ + (void) wattrset(msg_win, attributes[DIALOG_TEXT]); + fill_window(msg_win, msg); + + set_menu_win(menu, win); + set_menu_sub(menu, menu_win); + set_menu_format(menu, 1, btn_num); + menu_opts_off(menu, O_SHOWDESC); + menu_opts_off(menu, O_SHOWMATCH); + menu_opts_on(menu, O_ONEVALUE); + menu_opts_on(menu, O_NONCYCLIC); + set_menu_mark(menu, ""); + post_menu(menu); + + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(win))) { + switch (res) { + case KEY_LEFT: + menu_driver(menu, REQ_LEFT_ITEM); + break; + case KEY_RIGHT: + menu_driver(menu, REQ_RIGHT_ITEM); + break; + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case ' ': + case KEY_F(F_BACK): + case KEY_F(F_EXIT): + break; + } + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10 || res == ' ') { + res = item_index(current_item(menu)); + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } + } + + unpost_menu(menu); + free_menu(menu); + for (i = 0; i < btn_num; i++) + free_item(btns[i]); + + delwin(win); + return res; +} + +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len) +{ + int prompt_lines = 0; + int prompt_width = 0; + WINDOW *win; + WINDOW *prompt_win; + WINDOW *form_win; + PANEL *panel; + int i, x, y; + int res = -1; + int cursor_position = strlen(init); + int cursor_form_win; + char *result = *resultp; + + if (strlen(init)+1 > *result_len) { + *result_len = strlen(init)+1; + *resultp = result = realloc(result, *result_len); + } + + /* find the widest line of msg: */ + prompt_lines = get_line_no(prompt); + for (i = 0; i < prompt_lines; i++) { + const char *line = get_line(prompt, i); + int len = get_line_length(line); + prompt_width = max(prompt_width, len); + } + + if (title) + prompt_width = max(prompt_width, strlen(title)); + + /* place dialog in middle of screen */ + y = (getmaxy(stdscr)-(prompt_lines+4))/2; + x = (getmaxx(stdscr)-(prompt_width+4))/2; + + strncpy(result, init, *result_len); + + /* create the windows */ + win = newwin(prompt_lines+6, prompt_width+7, y, x); + prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); + form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); + keypad(form_win, TRUE); + + (void) wattrset(form_win, attributes[INPUT_FIELD]); + + (void) wattrset(win, attributes[INPUT_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[INPUT_HEADING]); + if (title) + mvwprintw(win, 0, 3, "%s", title); + + /* print message */ + (void) wattrset(prompt_win, attributes[INPUT_TEXT]); + fill_window(prompt_win, prompt); + + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + cursor_form_win = min(cursor_position, prompt_width-1); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + + /* create panels */ + panel = new_panel(win); + + /* show the cursor */ + curs_set(1); + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(form_win))) { + int len = strlen(result); + switch (res) { + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case KEY_F(F_HELP): + case KEY_F(F_EXIT): + case KEY_F(F_BACK): + break; + case 127: + case KEY_BACKSPACE: + if (cursor_position > 0) { + memmove(&result[cursor_position-1], + &result[cursor_position], + len-cursor_position+1); + cursor_position--; + cursor_form_win--; + len--; + } + break; + case KEY_DC: + if (cursor_position >= 0 && cursor_position < len) { + memmove(&result[cursor_position], + &result[cursor_position+1], + len-cursor_position+1); + len--; + } + break; + case KEY_UP: + case KEY_RIGHT: + if (cursor_position < len) { + cursor_position++; + cursor_form_win++; + } + break; + case KEY_DOWN: + case KEY_LEFT: + if (cursor_position > 0) { + cursor_position--; + cursor_form_win--; + } + break; + case KEY_HOME: + cursor_position = 0; + cursor_form_win = 0; + break; + case KEY_END: + cursor_position = len; + cursor_form_win = min(cursor_position, prompt_width-1); + break; + default: + if ((isgraph(res) || isspace(res))) { + /* one for new char, one for '\0' */ + if (len+2 > *result_len) { + *result_len = len+2; + *resultp = result = realloc(result, + *result_len); + } + /* insert the char at the proper position */ + memmove(&result[cursor_position+1], + &result[cursor_position], + len-cursor_position+1); + result[cursor_position] = res; + cursor_position++; + cursor_form_win++; + len++; + } else { + mvprintw(0, 0, "unknown key: %d\n", res); + } + break; + } + if (cursor_form_win < 0) + cursor_form_win = 0; + else if (cursor_form_win > prompt_width-1) + cursor_form_win = prompt_width-1; + + wmove(form_win, 0, 0); + wclrtoeol(form_win); + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + wmove(form_win, 0, cursor_form_win); + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10) { + res = 0; + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } else if (res == KEY_F(F_HELP)) { + res = 1; + break; + } + } + + /* hide the cursor */ + curs_set(0); + del_panel(panel); + delwin(prompt_win); + delwin(form_win); + delwin(win); + return res; +} + +/* refresh all windows in the correct order */ +void refresh_all_windows(WINDOW *main_window) +{ + update_panels(); + touchwin(main_window); + refresh(); +} + +/* layman's scrollable window... */ +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text) +{ + int res; + int total_lines = get_line_no(text); + int x, y, lines, columns; + int start_x = 0, start_y = 0; + int text_lines = 0, text_cols = 0; + int total_cols = 0; + int win_cols = 0; + int win_lines = 0; + int i = 0; + WINDOW *win; + WINDOW *pad; + PANEL *panel; + + getmaxyx(stdscr, lines, columns); + + /* find the widest line of msg: */ + total_lines = get_line_no(text); + for (i = 0; i < total_lines; i++) { + const char *line = get_line(text, i); + int len = get_line_length(line); + total_cols = max(total_cols, len+2); + } + + /* create the pad */ + pad = newpad(total_lines+10, total_cols+10); + (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); + fill_window(pad, text); + + win_lines = min(total_lines+4, lines-2); + win_cols = min(total_cols+2, columns-2); + text_lines = max(win_lines-4, 0); + text_cols = max(win_cols-2, 0); + + /* place window in middle of screen */ + y = (lines-win_lines)/2; + x = (columns-win_cols)/2; + + win = newwin(win_lines, win_cols, y, x); + keypad(win, TRUE); + /* show the help in the help window, and show the help panel */ + (void) wattrset(win, attributes[SCROLLWIN_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[SCROLLWIN_HEADING]); + mvwprintw(win, 0, 3, " %s ", title); + panel = new_panel(win); + + /* handle scrolling */ + do { + + copywin(pad, win, start_y, start_x, 2, 2, text_lines, + text_cols, 0); + print_in_middle(win, + text_lines+2, + 0, + text_cols, + "", + attributes[DIALOG_MENU_FORE]); + wrefresh(win); + + res = wgetch(win); + switch (res) { + case KEY_NPAGE: + case ' ': + case 'd': + start_y += text_lines-2; + break; + case KEY_PPAGE: + case 'u': + start_y -= text_lines+2; + break; + case KEY_HOME: + start_y = 0; + break; + case KEY_END: + start_y = total_lines-text_lines; + break; + case KEY_DOWN: + case 'j': + start_y++; + break; + case KEY_UP: + case 'k': + start_y--; + break; + case KEY_LEFT: + case 'h': + start_x--; + break; + case KEY_RIGHT: + case 'l': + start_x++; + break; + } + if (res == 10 || res == 27 || res == 'q' || + res == KEY_F(F_HELP) || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) + break; + if (start_y < 0) + start_y = 0; + if (start_y >= total_lines-text_lines) + start_y = total_lines-text_lines; + if (start_x < 0) + start_x = 0; + if (start_x >= total_cols-text_cols) + start_x = total_cols-text_cols; + } while (res); + + del_panel(panel); + delwin(win); + refresh_all_windows(main_window); +} diff -Nru seabios-1.7.1/scripts/kconfig/nconf.h seabios-1.7.4/scripts/kconfig/nconf.h --- seabios-1.7.1/scripts/kconfig/nconf.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/nconf.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008 Nir Tzachar +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ncurses.h" + +#define max(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a > _b ? _a : _b; }) + +#define min(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a < _b ? _a : _b; }) + +typedef enum { + NORMAL = 1, + MAIN_HEADING, + MAIN_MENU_BOX, + MAIN_MENU_FORE, + MAIN_MENU_BACK, + MAIN_MENU_GREY, + MAIN_MENU_HEADING, + SCROLLWIN_TEXT, + SCROLLWIN_HEADING, + SCROLLWIN_BOX, + DIALOG_TEXT, + DIALOG_MENU_FORE, + DIALOG_MENU_BACK, + DIALOG_BOX, + INPUT_BOX, + INPUT_HEADING, + INPUT_TEXT, + INPUT_FIELD, + FUNCTION_TEXT, + FUNCTION_HIGHLIGHT, + ATTR_MAX +} attributes_t; +extern attributes_t attributes[]; + +typedef enum { + F_HELP = 1, + F_SYMBOL = 2, + F_INSTS = 3, + F_CONF = 4, + F_BACK = 5, + F_SAVE = 6, + F_LOAD = 7, + F_SEARCH = 8, + F_EXIT = 9, +} function_key; + +void set_colors(void); + +/* this changes the windows attributes !!! */ +void print_in_middle(WINDOW *win, + int starty, + int startx, + int width, + const char *string, + chtype color); +int get_line_length(const char *line); +int get_line_no(const char *text); +const char *get_line(const char *text, int line_no); +void fill_window(WINDOW *win, const char *text); +int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len); +void refresh_all_windows(WINDOW *main_window); +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text); diff -Nru seabios-1.7.1/scripts/kconfig/POTFILES.in seabios-1.7.4/scripts/kconfig/POTFILES.in --- seabios-1.7.1/scripts/kconfig/POTFILES.in 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/POTFILES.in 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,12 @@ +scripts/kconfig/lxdialog/checklist.c +scripts/kconfig/lxdialog/inputbox.c +scripts/kconfig/lxdialog/menubox.c +scripts/kconfig/lxdialog/textbox.c +scripts/kconfig/lxdialog/util.c +scripts/kconfig/lxdialog/yesno.c +scripts/kconfig/mconf.c +scripts/kconfig/conf.c +scripts/kconfig/confdata.c +scripts/kconfig/gconf.c +scripts/kconfig/gconf.glade.h +scripts/kconfig/qconf.cc diff -Nru seabios-1.7.1/scripts/kconfig/qconf.cc seabios-1.7.4/scripts/kconfig/qconf.cc --- seabios-1.7.1/scripts/kconfig/qconf.cc 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/qconf.cc 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1790 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include + +#if QT_VERSION < 0x040000 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lkc.h" +#include "qconf.h" + +#include "qconf.moc" +#include "images.c" + +#ifdef _ +# undef _ +# define _ qgettext +#endif + +static QApplication *configApp; +static ConfigSettings *configSettings; + +Q3Action *ConfigMainWindow::saveAction; + +static inline QString qgettext(const char* str) +{ + return QString::fromLocal8Bit(gettext(str)); +} + +static inline QString qgettext(const QString& str) +{ + return QString::fromLocal8Bit(gettext(str.latin1())); +} + +/** + * Reads a list of integer values from the application settings. + */ +Q3ValueList ConfigSettings::readSizes(const QString& key, bool *ok) +{ + Q3ValueList result; + QStringList entryList = readListEntry(key, ok); + QStringList::Iterator it; + + for (it = entryList.begin(); it != entryList.end(); ++it) + result.push_back((*it).toInt()); + + return result; +} + +/** + * Writes a list of integer values to the application settings. + */ +bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList& value) +{ + QStringList stringList; + Q3ValueList::ConstIterator it; + + for (it = value.begin(); it != value.end(); ++it) + stringList.push_back(QString::number(*it)); + return writeEntry(key, stringList); +} + + +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ + Parent::okRename(col); + sym_set_string_value(menu->sym, text(dataColIdx).latin1()); + listView()->updateList(this); +} + +/* + * update the displayed of a menu entry + */ +void ConfigItem::updateMenu(void) +{ + ConfigList* list; + struct symbol* sym; + struct property *prop; + QString prompt; + int type; + tristate expr; + + list = listView(); + if (goParent) { + setPixmap(promptColIdx, list->menuBackPix); + prompt = ".."; + goto set_prompt; + } + + sym = menu->sym; + prop = menu->prompt; + prompt = _(menu_get_prompt(menu)); + + if (prop) switch (prop->type) { + case P_MENU: + if (list->mode == singleMode || list->mode == symbolMode) { + /* a menuconfig entry is displayed differently + * depending whether it's at the view root or a child. + */ + if (sym && list->rootEntry == menu) + break; + setPixmap(promptColIdx, list->menuPix); + } else { + if (sym) + break; + setPixmap(promptColIdx, 0); + } + goto set_prompt; + case P_COMMENT: + setPixmap(promptColIdx, 0); + goto set_prompt; + default: + ; + } + if (!sym) + goto set_prompt; + + setText(nameColIdx, QString::fromLocal8Bit(sym->name)); + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + char ch; + + if (!sym_is_changable(sym) && list->optMode == normalOpt) { + setPixmap(promptColIdx, 0); + setText(noColIdx, QString::null); + setText(modColIdx, QString::null); + setText(yesColIdx, QString::null); + break; + } + expr = sym_get_tristate_value(sym); + switch (expr) { + case yes: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceYesPix); + else + setPixmap(promptColIdx, list->symbolYesPix); + setText(yesColIdx, "Y"); + ch = 'Y'; + break; + case mod: + setPixmap(promptColIdx, list->symbolModPix); + setText(modColIdx, "M"); + ch = 'M'; + break; + default: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceNoPix); + else + setPixmap(promptColIdx, list->symbolNoPix); + setText(noColIdx, "N"); + ch = 'N'; + break; + } + if (expr != no) + setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); + if (expr != mod) + setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); + if (expr != yes) + setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); + + setText(dataColIdx, QChar(ch)); + break; + case S_INT: + case S_HEX: + case S_STRING: + const char* data; + + data = sym_get_string_value(sym); + + int i = list->mapIdx(dataColIdx); + if (i >= 0) + setRenameEnabled(i, TRUE); + setText(dataColIdx, data); + if (type == S_STRING) + prompt = QString("%1: %2").arg(prompt).arg(data); + else + prompt = QString("(%2) %1").arg(prompt).arg(data); + break; + } + if (!sym_has_value(sym) && visible) + prompt += _(" (NEW)"); +set_prompt: + setText(promptColIdx, prompt); +} + +void ConfigItem::testUpdateMenu(bool v) +{ + ConfigItem* i; + + visible = v; + if (!menu) + return; + + sym_calc_value(menu->sym); + if (menu->flags & MENU_CHANGED) { + /* the menu entry changed, so update all list items */ + menu->flags &= ~MENU_CHANGED; + for (i = (ConfigItem*)menu->data; i; i = i->nextItem) + i->updateMenu(); + } else if (listView()->updateAll) + updateMenu(); +} + +void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) +{ + ConfigList* list = listView(); + + if (visible) { + if (isSelected() && !list->hasFocus() && list->mode == menuMode) + Parent::paintCell(p, list->inactivedColorGroup, column, width, align); + else + Parent::paintCell(p, cg, column, width, align); + } else + Parent::paintCell(p, list->disabledColorGroup, column, width, align); +} + +/* + * construct a menu entry + */ +void ConfigItem::init(void) +{ + if (menu) { + ConfigList* list = listView(); + nextItem = (ConfigItem*)menu->data; + menu->data = this; + + if (list->mode != fullMode) + setOpen(TRUE); + sym_calc_value(menu->sym); + } + updateMenu(); +} + +/* + * destruct a menu entry + */ +ConfigItem::~ConfigItem(void) +{ + if (menu) { + ConfigItem** ip = (ConfigItem**)&menu->data; + for (; *ip; ip = &(*ip)->nextItem) { + if (*ip == this) { + *ip = nextItem; + break; + } + } + } +} + +ConfigLineEdit::ConfigLineEdit(ConfigView* parent) + : Parent(parent) +{ + connect(this, SIGNAL(lostFocus()), SLOT(hide())); +} + +void ConfigLineEdit::show(ConfigItem* i) +{ + item = i; + if (sym_get_string_value(item->menu->sym)) + setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); + else + setText(QString::null); + Parent::show(); + setFocus(); +} + +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) { + case Qt::Key_Escape: + break; + case Qt::Key_Return: + case Qt::Key_Enter: + sym_set_string_value(item->menu->sym, text().latin1()); + parent()->updateList(item); + break; + default: + Parent::keyPressEvent(e); + return; + } + e->accept(); + parent()->list->setFocus(); + hide(); +} + +ConfigList::ConfigList(ConfigView* p, const char *name) + : Parent(p, name), + updateAll(false), + symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), + choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), + menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), + showName(false), showRange(false), showData(false), optMode(normalOpt), + rootEntry(0), headerPopup(0) +{ + int i; + + setSorting(-1); + setRootIsDecorated(TRUE); + disabledColorGroup = palette().active(); + disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text()); + inactivedColorGroup = palette().active(); + inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight()); + + connect(this, SIGNAL(selectionChanged(void)), + SLOT(updateSelection(void))); + + if (name) { + configSettings->beginGroup(name); + showName = configSettings->readBoolEntry("/showName", false); + showRange = configSettings->readBoolEntry("/showRange", false); + showData = configSettings->readBoolEntry("/showData", false); + optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } + + for (i = 0; i < colNr; i++) + colMap[i] = colRevMap[i] = -1; + addColumn(promptColIdx, _("Option")); + + reinit(); +} + +bool ConfigList::menuSkip(struct menu *menu) +{ + if (optMode == normalOpt && menu_is_visible(menu)) + return false; + if (optMode == promptOpt && menu_has_prompt(menu)) + return false; + if (optMode == allOpt) + return false; + return true; +} + +void ConfigList::reinit(void) +{ + removeColumn(dataColIdx); + removeColumn(yesColIdx); + removeColumn(modColIdx); + removeColumn(noColIdx); + removeColumn(nameColIdx); + + if (showName) + addColumn(nameColIdx, _("Name")); + if (showRange) { + addColumn(noColIdx, "N"); + addColumn(modColIdx, "M"); + addColumn(yesColIdx, "Y"); + } + if (showData) + addColumn(dataColIdx, _("Value")); + + updateListAll(); +} + +void ConfigList::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showName", showName); + configSettings->writeEntry("/showRange", showRange); + configSettings->writeEntry("/showData", showData); + configSettings->writeEntry("/optionMode", (int)optMode); + configSettings->endGroup(); + } +} + +ConfigItem* ConfigList::findConfigItem(struct menu *menu) +{ + ConfigItem* item = (ConfigItem*)menu->data; + + for (; item; item = item->nextItem) { + if (this == item->listView()) + break; + } + + return item; +} + +void ConfigList::updateSelection(void) +{ + struct menu *menu; + enum prop_type type; + + ConfigItem* item = (ConfigItem*)selectedItem(); + if (!item) + return; + + menu = item->menu; + emit menuChanged(menu); + if (!menu) + return; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (mode == menuMode && type == P_MENU) + emit menuSelected(menu); +} + +void ConfigList::updateList(ConfigItem* item) +{ + ConfigItem* last = 0; + + if (!rootEntry) { + if (mode != listMode) + goto update; + Q3ListViewItemIterator it(this); + ConfigItem* item; + + for (; it.current(); ++it) { + item = (ConfigItem*)it.current(); + if (!item->menu) + continue; + item->testUpdateMenu(menu_is_visible(item->menu)); + } + return; + } + + if (rootEntry != &rootmenu && (mode == singleMode || + (mode == symbolMode && rootEntry->parent != &rootmenu))) { + item = firstChild(); + if (!item) + item = new ConfigItem(this, 0, true); + last = item; + } + if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && + rootEntry->sym && rootEntry->prompt) { + item = last ? last->nextSibling() : firstChild(); + if (!item) + item = new ConfigItem(this, last, rootEntry, true); + else + item->testUpdateMenu(true); + + updateMenuList(item, rootEntry); + triggerUpdate(); + return; + } +update: + updateMenuList(this, rootEntry); + triggerUpdate(); +} + +void ConfigList::setValue(ConfigItem* item, tristate val) +{ + struct symbol* sym; + int type; + tristate oldval; + + sym = item->menu ? item->menu->sym : 0; + if (!sym) + return; + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + + if (!sym_set_tristate_value(sym, val)) + return; + if (oldval == no && item->menu->list) + item->setOpen(TRUE); + parent()->updateList(item); + break; + } +} + +void ConfigList::changeValue(ConfigItem* item) +{ + struct symbol* sym; + struct menu* menu; + int type, oldexpr, newexpr; + + menu = item->menu; + if (!menu) + return; + sym = menu->sym; + if (!sym) { + if (item->menu->list) + item->setOpen(!item->isOpen()); + return; + } + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldexpr = sym_get_tristate_value(sym); + newexpr = sym_toggle_tristate_value(sym); + if (item->menu->list) { + if (oldexpr == newexpr) + item->setOpen(!item->isOpen()); + else if (oldexpr == no) + item->setOpen(TRUE); + } + if (oldexpr != newexpr) + parent()->updateList(item); + break; + case S_INT: + case S_HEX: + case S_STRING: + if (colMap[dataColIdx] >= 0) + item->startRename(colMap[dataColIdx]); + else + parent()->lineEdit->show(item); + break; + } +} + +void ConfigList::setRootMenu(struct menu *menu) +{ + enum prop_type type; + + if (rootEntry == menu) + return; + type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type != P_MENU) + return; + updateMenuList(this, 0); + rootEntry = menu; + updateListAll(); + setSelected(currentItem(), hasFocus()); + ensureItemVisible(currentItem()); +} + +void ConfigList::setParentMenu(void) +{ + ConfigItem* item; + struct menu *oldroot; + + oldroot = rootEntry; + if (rootEntry == &rootmenu) + return; + setRootMenu(menu_get_parent_menu(rootEntry->parent)); + + Q3ListViewItemIterator it(this); + for (; (item = (ConfigItem*)it.current()); it++) { + if (item->menu == oldroot) { + setCurrentItem(item); + ensureItemVisible(item); + break; + } + } +} + +/* + * update all the children of a menu entry + * removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +template +void ConfigList::updateMenuList(P* parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + + if (!menu) { + while ((item = parent->firstChild())) + delete item; + return; + } + + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : parent->firstChild(); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (!menuSkip(child)) { + if (!child->sym && !child->list && !child->prompt) + continue; + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = parent->firstChild(); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} + +void ConfigList::keyPressEvent(QKeyEvent* ev) +{ + Q3ListViewItem* i = currentItem(); + ConfigItem* item; + struct menu *menu; + enum prop_type type; + + if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) { + emit parentSelected(); + ev->accept(); + return; + } + + if (!i) { + Parent::keyPressEvent(ev); + return; + } + item = (ConfigItem*)i; + + switch (ev->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + if (item->goParent) { + emit parentSelected(); + break; + } + menu = item->menu; + if (!menu) + break; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) { + emit menuSelected(menu); + break; + } + case Qt::Key_Space: + changeValue(item); + break; + case Qt::Key_N: + setValue(item, no); + break; + case Qt::Key_M: + setValue(item, mod); + break; + case Qt::Key_Y: + setValue(item, yes); + break; + default: + Parent::keyPressEvent(ev); + return; + } + ev->accept(); +} + +void ConfigList::contentsMousePressEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMousePressEvent(e); +} + +void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + const QPixmap* pm; + int idx, x; + + if (!item) + goto skip; + + menu = item->menu; + x = header()->offset() + p.x(); + idx = colRevMap[header()->sectionAt(x)]; + switch (idx) { + case promptColIdx: + pm = item->pixmap(promptColIdx); + if (pm) { + int off = header()->sectionPos(0) + itemMargin() + + treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); + if (x >= off && x < off + pm->width()) { + if (item->goParent) { + emit parentSelected(); + break; + } else if (!menu) + break; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) + emit menuSelected(menu); + else + changeValue(item); + } + } + break; + case noColIdx: + setValue(item, no); + break; + case modColIdx: + setValue(item, mod); + break; + case yesColIdx: + setValue(item, yes); + break; + case dataColIdx: + changeValue(item); + break; + } + +skip: + //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseReleaseEvent(e); +} + +void ConfigList::contentsMouseMoveEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseMoveEvent(e); +} + +void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + + if (!item) + goto skip; + if (item->goParent) { + emit parentSelected(); + goto skip; + } + menu = item->menu; + if (!menu) + goto skip; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) + emit menuSelected(menu); + else if (menu->sym) + changeValue(item); + +skip: + //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseDoubleClickEvent(e); +} + +void ConfigList::focusInEvent(QFocusEvent *e) +{ + struct menu *menu = NULL; + + Parent::focusInEvent(e); + + ConfigItem* item = (ConfigItem *)currentItem(); + if (item) { + setSelected(item, TRUE); + menu = item->menu; + } + emit gotFocus(menu); +} + +void ConfigList::contextMenuEvent(QContextMenuEvent *e) +{ + if (e->y() <= header()->geometry().bottom()) { + if (!headerPopup) { + Q3Action *action; + + headerPopup = new Q3PopupMenu(this); + action = new Q3Action(NULL, _("Show Name"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowName(bool))); + connect(parent(), SIGNAL(showNameChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showName); + action->addTo(headerPopup); + action = new Q3Action(NULL, _("Show Range"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowRange(bool))); + connect(parent(), SIGNAL(showRangeChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showRange); + action->addTo(headerPopup); + action = new Q3Action(NULL, _("Show Data"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowData(bool))); + connect(parent(), SIGNAL(showDataChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showData); + action->addTo(headerPopup); + } + headerPopup->exec(e->globalPos()); + e->accept(); + } else + e->ignore(); +} + +ConfigView*ConfigView::viewList; +QAction *ConfigView::showNormalAction; +QAction *ConfigView::showAllAction; +QAction *ConfigView::showPromptAction; + +ConfigView::ConfigView(QWidget* parent, const char *name) + : Parent(parent, name) +{ + list = new ConfigList(this, name); + lineEdit = new ConfigLineEdit(this); + lineEdit->hide(); + + this->nextView = viewList; + viewList = this; +} + +ConfigView::~ConfigView(void) +{ + ConfigView** vp; + + for (vp = &viewList; *vp; vp = &(*vp)->nextView) { + if (*vp == this) { + *vp = nextView; + break; + } + } +} + +void ConfigView::setOptionMode(QAction *act) +{ + if (act == showNormalAction) + list->optMode = normalOpt; + else if (act == showAllAction) + list->optMode = allOpt; + else + list->optMode = promptOpt; + + list->updateListAll(); +} + +void ConfigView::setShowName(bool b) +{ + if (list->showName != b) { + list->showName = b; + list->reinit(); + emit showNameChanged(b); + } +} + +void ConfigView::setShowRange(bool b) +{ + if (list->showRange != b) { + list->showRange = b; + list->reinit(); + emit showRangeChanged(b); + } +} + +void ConfigView::setShowData(bool b) +{ + if (list->showData != b) { + list->showData = b; + list->reinit(); + emit showDataChanged(b); + } +} + +void ConfigList::setAllOpen(bool open) +{ + Q3ListViewItemIterator it(this); + + for (; it.current(); it++) + it.current()->setOpen(open); +} + +void ConfigView::updateList(ConfigItem* item) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateList(item); +} + +void ConfigView::updateListAll(void) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateListAll(); +} + +ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) + : Parent(parent, name), sym(0), _menu(0) +{ + if (name) { + configSettings->beginGroup(name); + _showDebug = configSettings->readBoolEntry("/showDebug", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigInfoView::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showDebug", showDebug()); + configSettings->endGroup(); + } +} + +void ConfigInfoView::setShowDebug(bool b) +{ + if (_showDebug != b) { + _showDebug = b; + if (_menu) + menuInfo(); + else if (sym) + symbolInfo(); + emit showDebugChanged(b); + } +} + +void ConfigInfoView::setInfo(struct menu *m) +{ + if (_menu == m) + return; + _menu = m; + sym = NULL; + if (!_menu) + clear(); + else + menuInfo(); +} + +void ConfigInfoView::symbolInfo(void) +{ + QString str; + + str += "Symbol: "; + str += print_filter(sym->name); + str += "

value: "; + str += print_filter(sym_get_string_value(sym)); + str += "
visibility: "; + str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; + str += "
"; + str += debug_info(sym); + + setText(str); +} + +void ConfigInfoView::menuInfo(void) +{ + struct symbol* sym; + QString head, debug, help; + + sym = _menu->sym; + if (sym) { + if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += ""; + if (sym->name) { + head += " ("; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ")"; + } + } else if (sym->name) { + head += ""; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ""; + } + head += "

"; + + if (showDebug()) + debug = debug_info(sym); + + struct gstr help_gstr = str_new(); + menu_get_ext_help(_menu, &help_gstr); + help = print_filter(str_get(&help_gstr)); + str_free(&help_gstr); + } else if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += "

"; + if (showDebug()) { + if (_menu->prompt->visible.expr) { + debug += "  dep: "; + expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "

"; + } + } + } + if (showDebug()) + debug += QString().sprintf("defined at %s:%d

", _menu->file->name, _menu->lineno); + + setText(head + debug + help); +} + +QString ConfigInfoView::debug_info(struct symbol *sym) +{ + QString debug; + + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + if (sym_is_choice(sym)) + debug += " (choice)"; + debug += "
"; + if (sym->rev_dep.expr) { + debug += "reverse dep: "; + expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + case P_MENU: + debug += QString().sprintf("prompt: ", prop->menu); + debug += print_filter(_(prop->text)); + debug += "
"; + break; + case P_DEFAULT: + case P_SELECT: + case P_RANGE: + case P_ENV: + debug += prop_get_type_name(prop->type); + debug += ": "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + case P_CHOICE: + if (sym_is_choice(sym)) { + debug += "choice: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "
"; + } + if (prop->visible.expr) { + debug += "    dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + } + debug += "
"; + + return debug; +} + +QString ConfigInfoView::print_filter(const QString &str) +{ + QRegExp re("[<>&\"\\n]"); + QString res = str; + for (int i = 0; (i = res.find(re, i)) >= 0;) { + switch (res[i].latin1()) { + case '<': + res.replace(i, 1, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + i += 6; + break; + case '\n': + res.replace(i, 1, "
"); + i += 4; + break; + } + } + return res; +} + +void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) +{ + QString* text = reinterpret_cast(data); + QString str2 = print_filter(str); + + if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { + *text += QString().sprintf("", sym); + *text += str2; + *text += ""; + } else + *text += str2; +} + +Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) +{ + Q3PopupMenu* popup = Parent::createPopupMenu(pos); + Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); + action->setOn(showDebug()); + popup->insertSeparator(); + action->addTo(popup); + return popup; +} + +void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e) +{ + Parent::contentsContextMenuEvent(e); +} + +ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) + : Parent(parent, name), result(NULL) +{ + setCaption("Search Config"); + + QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); + QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); + layout2->addWidget(new QLabel(_("Find:"), this)); + editField = new QLineEdit(this); + connect(editField, SIGNAL(returnPressed()), SLOT(search())); + layout2->addWidget(editField); + searchButton = new QPushButton(_("Search"), this); + searchButton->setAutoDefault(FALSE); + connect(searchButton, SIGNAL(clicked()), SLOT(search())); + layout2->addWidget(searchButton); + layout1->addLayout(layout2); + + split = new QSplitter(this); + split->setOrientation(Qt::Vertical); + list = new ConfigView(split, name); + list->list->mode = listMode; + info = new ConfigInfoView(split, name); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + info, SLOT(setInfo(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(setMenuLink(struct menu *))); + + layout1->addWidget(split); + + if (name) { + int x, y, width, height; + bool ok; + + configSettings->beginGroup(name); + width = configSettings->readNumEntry("/window width", parent->width() / 2); + height = configSettings->readNumEntry("/window height", parent->height() / 2); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + Q3ValueList sizes = configSettings->readSizes("/split", &ok); + if (ok) + split->setSizes(sizes); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigSearchWindow::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + configSettings->writeSizes("/split", split->sizes()); + configSettings->endGroup(); + } +} + +void ConfigSearchWindow::search(void) +{ + struct symbol **p; + struct property *prop; + ConfigItem *lastItem = NULL; + + free(result); + list->list->clear(); + info->clear(); + + result = sym_re_search(editField->text().latin1()); + if (!result) + return; + for (p = result; *p; p++) { + for_all_prompts((*p), prop) + lastItem = new ConfigItem(list->list, lastItem, prop->menu, + menu_is_visible(prop->menu)); + } +} + +/* + * Construct the complete config widget + */ +ConfigMainWindow::ConfigMainWindow(void) + : searchWindow(0) +{ + QMenuBar* menu; + bool ok; + int x, y, width, height; + char title[256]; + + QDesktopWidget *d = configApp->desktop(); + snprintf(title, sizeof(title), "%s%s", + rootmenu.prompt->text, +#if QT_VERSION < 0x040000 + " (Qt3)" +#else + "" +#endif + ); + setCaption(title); + + width = configSettings->readNumEntry("/window width", d->width() - 64); + height = configSettings->readNumEntry("/window height", d->height() - 64); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + + split1 = new QSplitter(this); + split1->setOrientation(Qt::Horizontal); + setCentralWidget(split1); + + menuView = new ConfigView(split1, "menu"); + menuList = menuView->list; + + split2 = new QSplitter(split1); + split2->setOrientation(Qt::Vertical); + + // create config tree + configView = new ConfigView(split2, "config"); + configList = configView->list; + + helpText = new ConfigInfoView(split2, "help"); + helpText->setTextFormat(Qt::RichText); + + setTabOrder(configList, helpText); + configList->setFocus(); + + menu = menuBar(); + toolBar = new Q3ToolBar("Tools", this); + + backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this); + connect(backAction, SIGNAL(activated()), SLOT(goBack())); + backAction->setEnabled(FALSE); + Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this); + connect(quitAction, SIGNAL(activated()), SLOT(close())); + Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this); + connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); + saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this); + connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); + conf_set_changed_callback(conf_changed); + // Set saveAction's initial state + conf_changed(); + Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this); + connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); + Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this); + connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); + Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this); + connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); + Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this); + connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); + Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this); + connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); + + Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this); + showNameAction->setToggleAction(TRUE); + connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); + connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); + showNameAction->setOn(configView->showName()); + Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this); + showRangeAction->setToggleAction(TRUE); + connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); + showRangeAction->setOn(configList->showRange); + Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this); + showDataAction->setToggleAction(TRUE); + connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); + connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); + showDataAction->setOn(configList->showData); + + QActionGroup *optGroup = new QActionGroup(this); + optGroup->setExclusive(TRUE); + connect(optGroup, SIGNAL(selected(QAction *)), configView, + SLOT(setOptionMode(QAction *))); + connect(optGroup, SIGNAL(selected(QAction *)), menuView, + SLOT(setOptionMode(QAction *))); + +#if QT_VERSION >= 0x040000 + configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup); + configView->showAllAction = new QAction(_("Show All Options"), optGroup); + configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup); +#else + configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup); + configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup); + configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup); +#endif + configView->showNormalAction->setToggleAction(TRUE); + configView->showNormalAction->setOn(configList->optMode == normalOpt); + configView->showAllAction->setToggleAction(TRUE); + configView->showAllAction->setOn(configList->optMode == allOpt); + configView->showPromptAction->setToggleAction(TRUE); + configView->showPromptAction->setOn(configList->optMode == promptOpt); + + Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this); + showDebugAction->setToggleAction(TRUE); + connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); + connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); + showDebugAction->setOn(helpText->showDebug()); + + Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this); + connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); + Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this); + connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); + + // init tool bar + backAction->addTo(toolBar); + toolBar->addSeparator(); + loadAction->addTo(toolBar); + saveAction->addTo(toolBar); + toolBar->addSeparator(); + singleViewAction->addTo(toolBar); + splitViewAction->addTo(toolBar); + fullViewAction->addTo(toolBar); + + // create config menu + Q3PopupMenu* config = new Q3PopupMenu(this); + menu->insertItem(_("&File"), config); + loadAction->addTo(config); + saveAction->addTo(config); + saveAsAction->addTo(config); + config->insertSeparator(); + quitAction->addTo(config); + + // create edit menu + Q3PopupMenu* editMenu = new Q3PopupMenu(this); + menu->insertItem(_("&Edit"), editMenu); + searchAction->addTo(editMenu); + + // create options menu + Q3PopupMenu* optionMenu = new Q3PopupMenu(this); + menu->insertItem(_("&Option"), optionMenu); + showNameAction->addTo(optionMenu); + showRangeAction->addTo(optionMenu); + showDataAction->addTo(optionMenu); + optionMenu->insertSeparator(); + optGroup->addTo(optionMenu); + optionMenu->insertSeparator(); + + // create help menu + Q3PopupMenu* helpMenu = new Q3PopupMenu(this); + menu->insertSeparator(); + menu->insertItem(_("&Help"), helpMenu); + showIntroAction->addTo(helpMenu); + showAboutAction->addTo(helpMenu); + + connect(configList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(configList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + connect(configList, SIGNAL(parentSelected()), + SLOT(goBack())); + connect(menuList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + + connect(configList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + SLOT(listFocusChanged(void))); + connect(helpText, SIGNAL(menuSelected(struct menu *)), + SLOT(setMenuLink(struct menu *))); + + QString listMode = configSettings->readEntry("/listMode", "symbol"); + if (listMode == "single") + showSingleView(); + else if (listMode == "full") + showFullView(); + else /*if (listMode == "split")*/ + showSplitView(); + + // UI setup done, restore splitter positions + Q3ValueList sizes = configSettings->readSizes("/split1", &ok); + if (ok) + split1->setSizes(sizes); + + sizes = configSettings->readSizes("/split2", &ok); + if (ok) + split2->setSizes(sizes); +} + +void ConfigMainWindow::loadConfig(void) +{ + QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this); + if (s.isNull()) + return; + if (conf_read(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to load configuration!")); + ConfigView::updateListAll(); +} + +bool ConfigMainWindow::saveConfig(void) +{ + if (conf_write(NULL)) { + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); + return false; + } + return true; +} + +void ConfigMainWindow::saveConfigAs(void) +{ + QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this); + if (s.isNull()) + return; + saveConfig(); +} + +void ConfigMainWindow::searchConfig(void) +{ + if (!searchWindow) + searchWindow = new ConfigSearchWindow(this, "search"); + searchWindow->show(); +} + +void ConfigMainWindow::changeMenu(struct menu *menu) +{ + configList->setRootMenu(menu); + if (configList->rootEntry->parent == &rootmenu) + backAction->setEnabled(FALSE); + else + backAction->setEnabled(TRUE); +} + +void ConfigMainWindow::setMenuLink(struct menu *menu) +{ + struct menu *parent; + ConfigList* list = NULL; + ConfigItem* item; + + if (configList->menuSkip(menu)) + return; + + switch (configList->mode) { + case singleMode: + list = configList; + parent = menu_get_parent_menu(menu); + if (!parent) + return; + list->setRootMenu(parent); + break; + case symbolMode: + if (menu->flags & MENU_ROOT) { + configList->setRootMenu(menu); + configList->clearSelection(); + list = menuList; + } else { + list = configList; + parent = menu_get_parent_menu(menu->parent); + if (!parent) + return; + item = menuList->findConfigItem(parent); + if (item) { + menuList->setSelected(item, TRUE); + menuList->ensureItemVisible(item); + } + list->setRootMenu(parent); + } + break; + case fullMode: + list = configList; + break; + default: + break; + } + + if (list) { + item = list->findConfigItem(menu); + if (item) { + list->setSelected(item, TRUE); + list->ensureItemVisible(item); + list->setFocus(); + } + } +} + +void ConfigMainWindow::listFocusChanged(void) +{ + if (menuList->mode == menuMode) + configList->clearSelection(); +} + +void ConfigMainWindow::goBack(void) +{ + ConfigItem* item; + + configList->setParentMenu(); + if (configList->rootEntry == &rootmenu) + backAction->setEnabled(FALSE); + item = (ConfigItem*)menuList->selectedItem(); + while (item) { + if (item->menu == configList->rootEntry) { + menuList->setSelected(item, TRUE); + break; + } + item = (ConfigItem*)item->parent(); + } +} + +void ConfigMainWindow::showSingleView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = singleMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configList->setFocus(); +} + +void ConfigMainWindow::showSplitView(void) +{ + configList->mode = symbolMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configApp->processEvents(); + menuList->mode = menuMode; + menuList->setRootMenu(&rootmenu); + menuList->setAllOpen(TRUE); + menuView->show(); + menuList->setFocus(); +} + +void ConfigMainWindow::showFullView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = fullMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(FALSE); + configList->setFocus(); +} + +/* + * ask for saving configuration before quitting + * TODO ask only when something changed + */ +void ConfigMainWindow::closeEvent(QCloseEvent* e) +{ + if (!conf_get_changed()) { + e->accept(); + return; + } + QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); + mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); + mb.setButtonText(QMessageBox::No, _("&Discard Changes")); + mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); + switch (mb.exec()) { + case QMessageBox::Yes: + if (saveConfig()) + e->accept(); + else + e->ignore(); + break; + case QMessageBox::No: + e->accept(); + break; + case QMessageBox::Cancel: + e->ignore(); + break; + } +} + +void ConfigMainWindow::showIntro(void) +{ + static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n" + "For each option, a blank box indicates the feature is disabled, a check\n" + "indicates it is enabled, and a dot indicates that it is to be compiled\n" + "as a module. Clicking on the box will cycle through the three states.\n\n" + "If you do not see an option (e.g., a device driver) that you believe\n" + "should be present, try turning on Show All Options under the Options menu.\n" + "Although there is no cross reference yet to help you figure out what other\n" + "options must be enabled to support the option you are interested in, you can\n" + "still view the help of a grayed-out option.\n\n" + "Toggling Show Debug Info under the Options menu will show the dependencies,\n" + "which you can then match by examining other options.\n\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::showAbout(void) +{ + static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel .\n\n" + "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::saveSettings(void) +{ + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + + QString entry; + switch(configList->mode) { + case singleMode : + entry = "single"; + break; + + case symbolMode : + entry = "split"; + break; + + case fullMode : + entry = "full"; + break; + + default: + break; + } + configSettings->writeEntry("/listMode", entry); + + configSettings->writeSizes("/split1", split1->sizes()); + configSettings->writeSizes("/split2", split2->sizes()); +} + +void ConfigMainWindow::conf_changed(void) +{ + if (saveAction) + saveAction->setEnabled(conf_get_changed()); +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + +static const char *progname; + +static void usage(void) +{ + printf(_("%s \n"), progname); + exit(0); +} + +int main(int ac, char** av) +{ + ConfigMainWindow* v; + const char *name; + + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + progname = av[0]; + configApp = new QApplication(ac, av); + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'h': + case '?': + usage(); + } + name = av[2]; + } else + name = av[1]; + if (!name) + usage(); + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + //zconfdump(stdout); + + configSettings = new ConfigSettings(); + configSettings->beginGroup("/kconfig/qconf"); + v = new ConfigMainWindow(); + + //zconfdump(stdout); + configApp->setMainWidget(v); + configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); + configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); + v->show(); + configApp->exec(); + + configSettings->endGroup(); + delete configSettings; + + return 0; +} diff -Nru seabios-1.7.1/scripts/kconfig/qconf.h seabios-1.7.4/scripts/kconfig/qconf.h --- seabios-1.7.1/scripts/kconfig/qconf.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/qconf.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#if QT_VERSION < 0x040000 +#include +#else +#include +#endif +#include + +#if QT_VERSION < 0x040000 +#define Q3ValueList QValueList +#define Q3PopupMenu QPopupMenu +#define Q3ListView QListView +#define Q3ListViewItem QListViewItem +#define Q3VBox QVBox +#define Q3TextBrowser QTextBrowser +#define Q3MainWindow QMainWindow +#define Q3Action QAction +#define Q3ToolBar QToolBar +#define Q3ListViewItemIterator QListViewItemIterator +#define Q3FileDialog QFileDialog +#endif + +class ConfigView; +class ConfigList; +class ConfigItem; +class ConfigLineEdit; +class ConfigMainWindow; + +class ConfigSettings : public QSettings { +public: + Q3ValueList readSizes(const QString& key, bool *ok); + bool writeSizes(const QString& key, const Q3ValueList& value); +}; + +enum colIdx { + promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr +}; +enum listMode { + singleMode, menuMode, symbolMode, fullMode, listMode +}; +enum optionMode { + normalOpt = 0, allOpt, promptOpt +}; + +class ConfigList : public Q3ListView { + Q_OBJECT + typedef class Q3ListView Parent; +public: + ConfigList(ConfigView* p, const char *name = 0); + void reinit(void); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + ConfigItem* findConfigItem(struct menu *); + +protected: + void keyPressEvent(QKeyEvent *e); + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseReleaseEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + void contentsMouseDoubleClickEvent(QMouseEvent *e); + void focusInEvent(QFocusEvent *e); + void contextMenuEvent(QContextMenuEvent *e); + +public slots: + void setRootMenu(struct menu *menu); + + void updateList(ConfigItem *item); + void setValue(ConfigItem* item, tristate val); + void changeValue(ConfigItem* item); + void updateSelection(void); + void saveSettings(void); +signals: + void menuChanged(struct menu *menu); + void menuSelected(struct menu *menu); + void parentSelected(void); + void gotFocus(struct menu *); + +public: + void updateListAll(void) + { + updateAll = true; + updateList(NULL); + updateAll = false; + } + ConfigList* listView() + { + return this; + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + int mapIdx(colIdx idx) + { + return colMap[idx]; + } + void addColumn(colIdx idx, const QString& label) + { + colMap[idx] = Parent::addColumn(label); + colRevMap[colMap[idx]] = idx; + } + void removeColumn(colIdx idx) + { + int col = colMap[idx]; + if (col >= 0) { + Parent::removeColumn(col); + colRevMap[col] = colMap[idx] = -1; + } + } + void setAllOpen(bool open); + void setParentMenu(void); + + bool menuSkip(struct menu *); + + template + void updateMenuList(P*, struct menu*); + + bool updateAll; + + QPixmap symbolYesPix, symbolModPix, symbolNoPix; + QPixmap choiceYesPix, choiceNoPix; + QPixmap menuPix, menuInvPix, menuBackPix, voidPix; + + bool showName, showRange, showData; + enum listMode mode; + enum optionMode optMode; + struct menu *rootEntry; + QColorGroup disabledColorGroup; + QColorGroup inactivedColorGroup; + Q3PopupMenu* headerPopup; + +private: + int colMap[colNr]; + int colRevMap[colNr]; +}; + +class ConfigItem : public Q3ListViewItem { + typedef class Q3ListViewItem Parent; +public: + ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(Q3ListView *parent, ConfigItem *after, bool v) + : Parent(parent, after), menu(0), visible(v), goParent(true) + { + init(); + } + ~ConfigItem(void); + void init(void); + void okRename(int col); + void updateMenu(void); + void testUpdateMenu(bool v); + ConfigList* listView() const + { + return (ConfigList*)Parent::listView(); + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + ConfigItem* nextSibling() const + { + return (ConfigItem *)Parent::nextSibling(); + } + void setText(colIdx idx, const QString& text) + { + Parent::setText(listView()->mapIdx(idx), text); + } + QString text(colIdx idx) const + { + return Parent::text(listView()->mapIdx(idx)); + } + void setPixmap(colIdx idx, const QPixmap& pm) + { + Parent::setPixmap(listView()->mapIdx(idx), pm); + } + const QPixmap* pixmap(colIdx idx) const + { + return Parent::pixmap(listView()->mapIdx(idx)); + } + void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align); + + ConfigItem* nextItem; + struct menu *menu; + bool visible; + bool goParent; +}; + +class ConfigLineEdit : public QLineEdit { + Q_OBJECT + typedef class QLineEdit Parent; +public: + ConfigLineEdit(ConfigView* parent); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + void show(ConfigItem *i); + void keyPressEvent(QKeyEvent *e); + +public: + ConfigItem *item; +}; + +class ConfigView : public Q3VBox { + Q_OBJECT + typedef class Q3VBox Parent; +public: + ConfigView(QWidget* parent, const char *name = 0); + ~ConfigView(void); + static void updateList(ConfigItem* item); + static void updateListAll(void); + + bool showName(void) const { return list->showName; } + bool showRange(void) const { return list->showRange; } + bool showData(void) const { return list->showData; } +public slots: + void setShowName(bool); + void setShowRange(bool); + void setShowData(bool); + void setOptionMode(QAction *); +signals: + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; + + static QAction *showNormalAction; + static QAction *showAllAction; + static QAction *showPromptAction; +}; + +class ConfigInfoView : public Q3TextBrowser { + Q_OBJECT + typedef class Q3TextBrowser Parent; +public: + ConfigInfoView(QWidget* parent, const char *name = 0); + bool showDebug(void) const { return _showDebug; } + +public slots: + void setInfo(struct menu *menu); + void saveSettings(void); + void setShowDebug(bool); + +signals: + void showDebugChanged(bool); + void menuSelected(struct menu *); + +protected: + void symbolInfo(void); + void menuInfo(void); + QString debug_info(struct symbol *sym); + static QString print_filter(const QString &str); + static void expr_print_help(void *data, struct symbol *sym, const char *str); + Q3PopupMenu* createPopupMenu(const QPoint& pos); + void contentsContextMenuEvent(QContextMenuEvent *e); + + struct symbol *sym; + struct menu *_menu; + bool _showDebug; +}; + +class ConfigSearchWindow : public QDialog { + Q_OBJECT + typedef class QDialog Parent; +public: + ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0); + +public slots: + void saveSettings(void); + void search(void); + +protected: + QLineEdit* editField; + QPushButton* searchButton; + QSplitter* split; + ConfigView* list; + ConfigInfoView* info; + + struct symbol **result; +}; + +class ConfigMainWindow : public Q3MainWindow { + Q_OBJECT + + static Q3Action *saveAction; + static void conf_changed(void); +public: + ConfigMainWindow(void); +public slots: + void changeMenu(struct menu *); + void setMenuLink(struct menu *); + void listFocusChanged(void); + void goBack(void); + void loadConfig(void); + bool saveConfig(void); + void saveConfigAs(void); + void searchConfig(void); + void showSingleView(void); + void showSplitView(void); + void showFullView(void); + void showIntro(void); + void showAbout(void); + void saveSettings(void); + +protected: + void closeEvent(QCloseEvent *e); + + ConfigSearchWindow *searchWindow; + ConfigView *menuView; + ConfigList *menuList; + ConfigView *configView; + ConfigList *configList; + ConfigInfoView *helpText; + Q3ToolBar *toolBar; + Q3Action *backAction; + QSplitter* split1; + QSplitter* split2; +}; diff -Nru seabios-1.7.1/scripts/kconfig/streamline_config.pl seabios-1.7.4/scripts/kconfig/streamline_config.pl --- seabios-1.7.1/scripts/kconfig/streamline_config.pl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/streamline_config.pl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,640 @@ +#!/usr/bin/perl -w +# +# Copyright 2005-2009 - Steven Rostedt +# Licensed under the terms of the GNU GPL License version 2 +# +# It's simple enough to figure out how this works. +# If not, then you can ask me at stripconfig@goodmis.org +# +# What it does? +# +# If you have installed a Linux kernel from a distribution +# that turns on way too many modules than you need, and +# you only want the modules you use, then this program +# is perfect for you. +# +# It gives you the ability to turn off all the modules that are +# not loaded on your system. +# +# Howto: +# +# 1. Boot up the kernel that you want to stream line the config on. +# 2. Change directory to the directory holding the source of the +# kernel that you just booted. +# 3. Copy the configuraton file to this directory as .config +# 4. Have all your devices that you need modules for connected and +# operational (make sure that their corresponding modules are loaded) +# 5. Run this script redirecting the output to some other file +# like config_strip. +# 6. Back up your old config (if you want too). +# 7. copy the config_strip file to .config +# 8. Run "make oldconfig" +# +# Now your kernel is ready to be built with only the modules that +# are loaded. +# +# Here's what I did with my Debian distribution. +# +# cd /usr/src/linux-2.6.10 +# cp /boot/config-2.6.10-1-686-smp .config +# ~/bin/streamline_config > config_strip +# mv .config config_sav +# mv config_strip .config +# make oldconfig +# +use strict; +use Getopt::Long; + +# set the environment variable LOCALMODCONFIG_DEBUG to get +# debug output. +my $debugprint = 0; +$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG})); + +sub dprint { + return if (!$debugprint); + print STDERR @_; +} + +my $config = ".config"; + +my $uname = `uname -r`; +chomp $uname; + +my @searchconfigs = ( + { + "file" => ".config", + "exec" => "cat", + }, + { + "file" => "/proc/config.gz", + "exec" => "zcat", + }, + { + "file" => "/boot/config-$uname", + "exec" => "cat", + }, + { + "file" => "/boot/vmlinuz-$uname", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "vmlinux", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "/lib/modules/$uname/kernel/kernel/configs.ko", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "kernel/configs.ko", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "kernel/configs.o", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, +); + +sub read_config { + foreach my $conf (@searchconfigs) { + my $file = $conf->{"file"}; + + next if ( ! -f "$file"); + + if (defined($conf->{"test"})) { + `$conf->{"test"} $conf->{"file"} 2>/dev/null`; + next if ($?); + } + + my $exec = $conf->{"exec"}; + + print STDERR "using config: '$file'\n"; + + open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file"; + my @x = <$infile>; + close $infile; + return @x; + } + die "No config file found"; +} + +my @config_file = read_config; + +# Parse options +my $localmodconfig = 0; +my $localyesconfig = 0; + +GetOptions("localmodconfig" => \$localmodconfig, + "localyesconfig" => \$localyesconfig); + +# Get the build source and top level Kconfig file (passed in) +my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); +my $kconfig = $ARGV[1]; +my $lsmod_file = $ENV{'LSMOD'}; + +my @makefiles = `find $ksource -name Makefile 2>/dev/null`; +chomp @makefiles; + +my %depends; +my %selects; +my %prompts; +my %objects; +my $var; +my $iflevel = 0; +my @ifdeps; + +# prevent recursion +my %read_kconfigs; + +sub read_kconfig { + my ($kconfig) = @_; + + my $state = "NONE"; + my $config; + + my $cont = 0; + my $line; + + my $source = "$ksource/$kconfig"; + my $last_source = ""; + + # Check for any environment variables used + while ($source =~ /\$(\w+)/ && $last_source ne $source) { + my $env = $1; + $last_source = $source; + $source =~ s/\$$env/$ENV{$env}/; + } + + open(my $kinfile, '<', $source) || die "Can't open $kconfig"; + while (<$kinfile>) { + chomp; + + # Make sure that lines ending with \ continue + if ($cont) { + $_ = $line . " " . $_; + } + + if (s/\\$//) { + $cont = 1; + $line = $_; + next; + } + + $cont = 0; + + # collect any Kconfig sources + if (/^source\s*"(.*)"/) { + my $kconfig = $1; + # prevent reading twice. + if (!defined($read_kconfigs{$kconfig})) { + $read_kconfigs{$kconfig} = 1; + read_kconfig($kconfig); + } + next; + } + + # configs found + if (/^\s*(menu)?config\s+(\S+)\s*$/) { + $state = "NEW"; + $config = $2; + + # Add depends for 'if' nesting + for (my $i = 0; $i < $iflevel; $i++) { + if ($i) { + $depends{$config} .= " " . $ifdeps[$i]; + } else { + $depends{$config} = $ifdeps[$i]; + } + $state = "DEP"; + } + + # collect the depends for the config + } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { + $state = "DEP"; + $depends{$config} = $1; + } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) { + $depends{$config} .= " " . $1; + + # Get the configs that select this config + } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { + my $conf = $1; + if (defined($selects{$conf})) { + $selects{$conf} .= " " . $config; + } else { + $selects{$conf} = $config; + } + + # configs without prompts must be selected + } elsif ($state ne "NONE" && /^\s*tristate\s\S/) { + # note if the config has a prompt + $prompts{$config} = 1; + + # Check for if statements + } elsif (/^if\s+(.*\S)\s*$/) { + my $deps = $1; + # remove beginning and ending non text + $deps =~ s/^[^a-zA-Z0-9_]*//; + $deps =~ s/[^a-zA-Z0-9_]*$//; + + my @deps = split /[^a-zA-Z0-9_]+/, $deps; + + $ifdeps[$iflevel++] = join ':', @deps; + + } elsif (/^endif/) { + + $iflevel-- if ($iflevel); + + # stop on "help" + } elsif (/^\s*help\s*$/) { + $state = "NONE"; + } + } + close($kinfile); +} + +if ($kconfig) { + read_kconfig($kconfig); +} + +# Makefiles can use variables to define their dependencies +sub convert_vars { + my ($line, %vars) = @_; + + my $process = ""; + + while ($line =~ s/^(.*?)(\$\((.*?)\))//) { + my $start = $1; + my $variable = $2; + my $var = $3; + + if (defined($vars{$var})) { + $process .= $start . $vars{$var}; + } else { + $process .= $start . $variable; + } + } + + $process .= $line; + + return $process; +} + +# Read all Makefiles to map the configs to the objects +foreach my $makefile (@makefiles) { + + my $line = ""; + my %make_vars; + + open(my $infile, '<', $makefile) || die "Can't open $makefile"; + while (<$infile>) { + # if this line ends with a backslash, continue + chomp; + if (/^(.*)\\$/) { + $line .= $1; + next; + } + + $line .= $_; + $_ = $line; + $line = ""; + + my $objs; + + # Convert variables in a line (could define configs) + $_ = convert_vars($_, %make_vars); + + # collect objects after obj-$(CONFIG_FOO_BAR) + if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) { + $var = $1; + $objs = $2; + + # check if variables are set + } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) { + $make_vars{$1} = $2; + } + if (defined($objs)) { + foreach my $obj (split /\s+/,$objs) { + $obj =~ s/-/_/g; + if ($obj =~ /(.*)\.o$/) { + # Objects may be enabled by more than one config. + # Store configs in an array. + my @arr; + + if (defined($objects{$1})) { + @arr = @{$objects{$1}}; + } + + $arr[$#arr+1] = $var; + + # The objects have a hash mapping to a reference + # of an array of configs. + $objects{$1} = \@arr; + } + } + } + } + close($infile); +} + +my %modules; +my $linfile; + +if (defined($lsmod_file)) { + if ( ! -f $lsmod_file) { + if ( -f $ENV{'objtree'}."/".$lsmod_file) { + $lsmod_file = $ENV{'objtree'}."/".$lsmod_file; + } else { + die "$lsmod_file not found"; + } + } + + my $otype = ( -x $lsmod_file) ? '-|' : '<'; + open($linfile, $otype, $lsmod_file); + +} else { + + # see what modules are loaded on this system + my $lsmod; + + foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) { + if ( -x "$dir/lsmod" ) { + $lsmod = "$dir/lsmod"; + last; + } +} + if (!defined($lsmod)) { + # try just the path + $lsmod = "lsmod"; + } + + open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod"; +} + +while (<$linfile>) { + next if (/^Module/); # Skip the first line. + if (/^(\S+)/) { + $modules{$1} = 1; + } +} +close ($linfile); + +# add to the configs hash all configs that are needed to enable +# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o +# where we know we need bar.o so we add FOO to the list. +my %configs; +foreach my $module (keys(%modules)) { + if (defined($objects{$module})) { + my @arr = @{$objects{$module}}; + foreach my $conf (@arr) { + $configs{$conf} = $module; + dprint "$conf added by direct ($module)\n"; + if ($debugprint) { + my $c=$conf; + $c =~ s/^CONFIG_//; + if (defined($depends{$c})) { + dprint " deps = $depends{$c}\n"; + } else { + dprint " no deps\n"; + } + } + } + } else { + # Most likely, someone has a custom (binary?) module loaded. + print STDERR "$module config not found!!\n"; + } +} + +# Read the current config, and see what is enabled. We want to +# ignore configs that we would not enable anyway. + +my %orig_configs; +my $valid = "A-Za-z_0-9"; + +foreach my $line (@config_file) { + $_ = $line; + + if (/(CONFIG_[$valid]*)=(m|y)/) { + $orig_configs{$1} = $2; + } +} + +my $repeat = 1; + +my $depconfig; + +# +# Note, we do not care about operands (like: &&, ||, !) we want to add any +# config that is in the depend list of another config. This script does +# not enable configs that are not already enabled. If we come across a +# config A that depends on !B, we can still add B to the list of depends +# to keep on. If A was on in the original config, B would not have been +# and B would not be turned on by this script. +# +sub parse_config_depends +{ + my ($p) = @_; + + while ($p =~ /[$valid]/) { + + if ($p =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $p =~ s/^[^$valid]*[$valid]+//; + + # We only need to process if the depend config is a module + if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") { + next; + } + + if (!defined($configs{$conf})) { + # We must make sure that this config has its + # dependencies met. + $repeat = 1; # do again + dprint "$conf selected by depend $depconfig\n"; + $configs{$conf} = 1; + } + } else { + die "this should never happen"; + } + } +} + +# Select is treated a bit differently than depends. We call this +# when a config has no prompt and requires another config to be +# selected. We use to just select all configs that selected this +# config, but found that that can balloon into enabling hundreds +# of configs that we do not care about. +# +# The idea is we look at all the configs that select it. If one +# is already in our list of configs to enable, then there's nothing +# else to do. If there isn't, we pick the first config that was +# enabled in the orignal config and use that. +sub parse_config_selects +{ + my ($config, $p) = @_; + + my $next_config; + + while ($p =~ /[$valid]/) { + + if ($p =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $p =~ s/^[^$valid]*[$valid]+//; + + # Make sure that this config exists in the current .config file + if (!defined($orig_configs{$conf})) { + dprint "$conf not set for $config select\n"; + next; + } + + # Check if something other than a module selects this config + if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") { + dprint "$conf (non module) selects config, we are good\n"; + # we are good with this + return; + } + if (defined($configs{$conf})) { + dprint "$conf selects $config so we are good\n"; + # A set config selects this config, we are good + return; + } + # Set this config to be selected + if (!defined($next_config)) { + $next_config = $conf; + } + } else { + die "this should never happen"; + } + } + + # If no possible config selected this, then something happened. + if (!defined($next_config)) { + print STDERR "WARNING: $config is required, but nothing in the\n"; + print STDERR " current config selects it.\n"; + return; + } + + # If we are here, then we found no config that is set and + # selects this config. Repeat. + $repeat = 1; + # Make this config need to be selected + $configs{$next_config} = 1; + dprint "$next_config selected by select $config\n"; +} + +my %process_selects; + +# loop through all configs, select their dependencies. +sub loop_depend { + $repeat = 1; + + while ($repeat) { + $repeat = 0; + + forloop: + foreach my $config (keys %configs) { + + # If this config is not a module, we do not need to process it + if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") { + next forloop; + } + + $config =~ s/^CONFIG_//; + $depconfig = $config; + + if (defined($depends{$config})) { + # This config has dependencies. Make sure they are also included + parse_config_depends $depends{$config}; + } + + # If the config has no prompt, then we need to check if a config + # that is enabled selected it. Or if we need to enable one. + if (!defined($prompts{$config}) && defined($selects{$config})) { + $process_selects{$config} = 1; + } + } + } +} + +sub loop_select { + + foreach my $config (keys %process_selects) { + $config =~ s/^CONFIG_//; + + dprint "Process select $config\n"; + + # config has no prompt and must be selected. + parse_config_selects $config, $selects{$config}; + } +} + +while ($repeat) { + # Get the first set of configs and their dependencies. + loop_depend; + + $repeat = 0; + + # Now we need to see if we have to check selects; + loop_select; +} + +my %setconfigs; + +# Finally, read the .config file and turn off any module enabled that +# we could not find a reason to keep enabled. +foreach my $line (@config_file) { + $_ = $line; + + if (/CONFIG_IKCONFIG/) { + if (/# CONFIG_IKCONFIG is not set/) { + # enable IKCONFIG at least as a module + print "CONFIG_IKCONFIG=m\n"; + # don't ask about PROC + print "# CONFIG_IKCONFIG_PROC is not set\n"; + } else { + print; + } + next; + } + + if (/^(CONFIG.*)=(m|y)/) { + if (defined($configs{$1})) { + if ($localyesconfig) { + $setconfigs{$1} = 'y'; + print "$1=y\n"; + next; + } else { + $setconfigs{$1} = $2; + } + } elsif ($2 eq "m") { + print "# $1 is not set\n"; + next; + } + } + print; +} + +# Integrity check, make sure all modules that we want enabled do +# indeed have their configs set. +loop: +foreach my $module (keys(%modules)) { + if (defined($objects{$module})) { + my @arr = @{$objects{$module}}; + foreach my $conf (@arr) { + if (defined($setconfigs{$conf})) { + next loop; + } + } + print STDERR "module $module did not have configs"; + foreach my $conf (@arr) { + print STDERR " " , $conf; + } + print STDERR "\n"; + } +} diff -Nru seabios-1.7.1/scripts/kconfig/symbol.c seabios-1.7.4/scripts/kconfig/symbol.c --- seabios-1.7.1/scripts/kconfig/symbol.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/symbol.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1381 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +struct symbol symbol_yes = { + .name = "y", + .curr = { "y", yes }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_mod = { + .name = "m", + .curr = { "m", mod }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_no = { + .name = "n", + .curr = { "n", no }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_empty = { + .name = "", + .curr = { "", no }, + .flags = SYMBOL_VALID, +}; + +struct symbol *sym_defconfig_list; +struct symbol *modules_sym; +tristate modules_val; + +struct expr *sym_env_list; + +static void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); +} + +void sym_init(void) +{ + struct symbol *sym; + struct utsname uts; + static bool inited = false; + + if (inited) + return; + inited = true; + + uname(&uts); + + sym = sym_lookup("UNAME_RELEASE", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, uts.release); +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ + enum symbol_type type = sym->type; + + if (type == S_TRISTATE) { + if (sym_is_choice_value(sym) && sym->visible == yes) + type = S_BOOLEAN; + else if (modules_val == no) + type = S_BOOLEAN; + } + return type; +} + +const char *sym_type_name(enum symbol_type type) +{ + switch (type) { + case S_BOOLEAN: + return "boolean"; + case S_TRISTATE: + return "tristate"; + case S_INT: + return "integer"; + case S_HEX: + return "hex"; + case S_STRING: + return "string"; + case S_UNKNOWN: + return "unknown"; + case S_OTHER: + break; + } + return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_choices(sym, prop) + return prop; + return NULL; +} + +struct property *sym_get_env_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_ENV) + return prop; + return NULL; +} + +struct property *sym_get_default_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static struct property *sym_get_range_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_RANGE) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static long sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtol(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + long base, val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtol(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%ld", val2); + else + sprintf(str, "0x%lx", val2); + sym->curr.val = strdup(str); +} + +static void sym_calc_visibility(struct symbol *sym) +{ + struct property *prop; + tristate tri; + + /* any prompt visible? */ + tri = no; + for_all_prompts(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + tri = EXPR_OR(tri, prop->visible.tri); + } + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) + tri = yes; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + /* defaulting to "yes" if no explicit "depends on" are given */ + tri = yes; + if (sym->dir_dep.expr) + tri = expr_calc_value(sym->dir_dep.expr); + if (tri == mod) + tri = yes; + if (sym->dir_dep.tri != tri) { + sym->dir_dep.tri = tri; + sym_set_changed(sym); + } + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + tri = yes; + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; + sym_set_changed(sym); + } +} + +/* + * Find the default symbol for a choice. + * First try the default values for the choice symbol + * Next locate the first visible choice value + * Return NULL if none was found + */ +struct symbol *sym_choice_default(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + + /* any of the defaults visible? */ + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri == no) + continue; + def_sym = prop_get_symbol(prop); + if (def_sym->visible != no) + return def_sym; + } + + /* just get the first visible value */ + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) + if (def_sym->visible != no) + return def_sym; + + /* failed to locate any defaults */ + return NULL; +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + int flags; + + /* first calculate all choice values' visibilities */ + flags = sym->flags; + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + flags &= def_sym->flags; + } + + sym->flags &= flags | ~SYMBOL_DEF_USER; + + /* is the user choice visible? */ + def_sym = sym->def[S_DEF_USER].val; + if (def_sym && def_sym->visible != no) + return def_sym; + + def_sym = sym_choice_default(sym); + + if (def_sym == NULL) + /* no choice? reset tristate value */ + sym->curr.tri = no; + + return def_sym; +} + +void sym_calc_value(struct symbol *sym) +{ + struct symbol_value newval, oldval; + struct property *prop; + struct expr *e; + + if (!sym) + return; + + if (sym->flags & SYMBOL_VALID) + return; + + if (sym_is_choice_value(sym) && + sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) { + sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES; + prop = sym_get_choice_prop(sym); + sym_calc_value(prop_get_symbol(prop)); + } + + sym->flags |= SYMBOL_VALID; + + oldval = sym->curr; + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + newval = symbol_empty.curr; + break; + case S_BOOLEAN: + case S_TRISTATE: + newval = symbol_no.curr; + break; + default: + sym->curr.val = sym->name; + sym->curr.tri = no; + return; + } + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; + + sym_calc_visibility(sym); + + /* set default if recursively called */ + sym->curr = newval; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_is_choice_value(sym) && sym->visible == yes) { + prop = sym_get_choice_prop(sym); + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; + } else { + if (sym->visible != no) { + /* if the symbol is visible use the user value + * if available, otherwise try the default value + */ + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, + sym->visible); + goto calc_newval; + } + } + if (sym->rev_dep.tri != no) + sym->flags |= SYMBOL_WRITE; + if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = EXPR_AND(expr_calc_value(prop->expr), + prop->visible.tri); + } + } + calc_newval: + if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { + struct expr *e; + e = expr_simplify_unmet_dep(sym->rev_dep.expr, + sym->dir_dep.expr); + fprintf(stderr, "warning: ("); + expr_fprint(e, stderr); + fprintf(stderr, ") selects %s which has unmet direct dependencies (", + sym->name); + expr_fprint(sym->dir_dep.expr, stderr); + fprintf(stderr, ")\n"); + expr_free(e); + } + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); + } + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) + newval.tri = yes; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } + } + prop = sym_get_default_prop(sym); + if (prop) { + struct symbol *ds = prop_get_symbol(prop); + if (ds) { + sym->flags |= SYMBOL_WRITE; + sym_calc_value(ds); + newval.val = ds->curr.val; + } + } + break; + default: + ; + } + + sym->curr = newval; + if (sym_is_choice(sym) && newval.tri == yes) + sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); + + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + sym_set_changed(sym); + if (modules_sym == sym) { + sym_set_all_changed(); + modules_val = modules_sym->curr.tri; + } + } + + if (sym_is_choice(sym)) { + struct symbol *choice_sym; + + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, choice_sym) { + if ((sym->flags & SYMBOL_WRITE) && + choice_sym->visible != no) + choice_sym->flags |= SYMBOL_WRITE; + if (sym->flags & SYMBOL_CHANGED) + sym_set_changed(choice_sym); + } + } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; + + if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) + set_all_choice_values(sym); +} + +void sym_clear_all_valid(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_VALID; + sym_add_change_count(1); + if (modules_sym) + sym_calc_value(modules_sym); +} + +void sym_set_changed(struct symbol *sym) +{ + struct property *prop; + + sym->flags |= SYMBOL_CHANGED; + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu) + prop->menu->flags |= MENU_CHANGED; + } +} + +void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ + int type = sym_get_type(sym); + + if (sym->visible == no) + return false; + + if (type != S_BOOLEAN && type != S_TRISTATE) + return false; + + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ + tristate oldval = sym_get_tristate_value(sym); + + if (oldval != val && !sym_tristate_within_range(sym, val)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ + if (sym_is_choice_value(sym) && val == yes) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; + + cs->def[S_DEF_USER].val = sym; + cs->flags |= SYMBOL_DEF_USER; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags |= SYMBOL_DEF_USER; + } + } + + sym->def[S_DEF_USER].tri = val; + if (oldval != val) + sym_clear_all_valid(); + + return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ + tristate oldval, newval; + + oldval = newval = sym_get_tristate_value(sym); + do { + switch (newval) { + case no: + newval = mod; + break; + case mod: + newval = yes; + break; + case yes: + newval = no; + break; + } + if (sym_set_tristate_value(sym, newval)) + break; + } while (oldval != newval); + return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ + signed char ch; + + switch (sym->type) { + case S_STRING: + return true; + case S_INT: + ch = *str++; + if (ch == '-') + ch = *str++; + if (!isdigit(ch)) + return false; + if (ch == '0' && *str != 0) + return false; + while ((ch = *str++)) { + if (!isdigit(ch)) + return false; + } + return true; + case S_HEX: + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + ch = *str++; + do { + if (!isxdigit(ch)) + return false; + } while ((ch = *str++)); + return true; + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + case 'm': case 'M': + case 'n': case 'N': + return true; + } + return false; + default: + return false; + } +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ + struct property *prop; + long val; + + switch (sym->type) { + case S_STRING: + return sym_string_valid(sym, str); + case S_INT: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); + case S_HEX: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + return sym_tristate_within_range(sym, yes); + case 'm': case 'M': + return sym_tristate_within_range(sym, mod); + case 'n': case 'N': + return sym_tristate_within_range(sym, no); + } + return false; + default: + return false; + } +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ + const char *oldval; + char *val; + int size; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (newval[0]) { + case 'y': case 'Y': + return sym_set_tristate_value(sym, yes); + case 'm': case 'M': + return sym_set_tristate_value(sym, mod); + case 'n': case 'N': + return sym_set_tristate_value(sym, no); + } + return false; + default: + ; + } + + if (!sym_string_within_range(sym, newval)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + + oldval = sym->def[S_DEF_USER].val; + size = strlen(newval) + 1; + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { + size += 2; + sym->def[S_DEF_USER].val = val = xmalloc(size); + *val++ = '0'; + *val++ = 'x'; + } else if (!oldval || strcmp(oldval, newval)) + sym->def[S_DEF_USER].val = val = xmalloc(size); + else + return true; + + strcpy(val, newval); + free((void *)oldval); + sym_clear_all_valid(); + + return true; +} + +/* + * Find the default value associated to a symbol. + * For tristate symbol handle the modules=n case + * in which case "m" becomes "y". + * If the symbol does not have any default then fallback + * to the fixed default values. + */ +const char *sym_get_string_default(struct symbol *sym) +{ + struct property *prop; + struct symbol *ds; + const char *str; + tristate val; + + sym_calc_visibility(sym); + sym_calc_value(modules_sym); + val = symbol_no.curr.tri; + str = symbol_empty.curr.val; + + /* If symbol has a default value look it up */ + prop = sym_get_default_prop(sym); + if (prop != NULL) { + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + /* The visibility may limit the value from yes => mod */ + val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); + break; + default: + /* + * The following fails to handle the situation + * where a default value is further limited by + * the valid range. + */ + ds = prop_get_symbol(prop); + if (ds != NULL) { + sym_calc_value(ds); + str = (const char *)ds->curr.val; + } + } + } + + /* Handle select statements */ + val = EXPR_OR(val, sym->rev_dep.tri); + + /* transpose mod to yes if modules are not enabled */ + if (val == mod) + if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no) + val = yes; + + /* transpose mod to yes if type is bool */ + if (sym->type == S_BOOLEAN && val == mod) + val = yes; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (val) { + case no: return "n"; + case mod: return "m"; + case yes: return "y"; + } + case S_INT: + case S_HEX: + return str; + case S_STRING: + return str; + case S_OTHER: + case S_UNKNOWN: + break; + } + return ""; +} + +const char *sym_get_string_value(struct symbol *sym) +{ + tristate val; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + return "n"; + case mod: + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; + case yes: + return "y"; + } + break; + default: + ; + } + return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ + return sym->visible > sym->rev_dep.tri; +} + +static unsigned strhash(const char *s) +{ + /* fnv32 hash */ + unsigned hash = 2166136261U; + for (; *s; s++) + hash = (hash ^ *s) * 0x01000193; + return hash; +} + +struct symbol *sym_lookup(const char *name, int flags) +{ + struct symbol *symbol; + char *new_name; + int hash; + + if (name) { + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; + } + new_name = strdup(name); + } else { + new_name = NULL; + hash = 0; + } + + symbol = xmalloc(sizeof(*symbol)); + memset(symbol, 0, sizeof(*symbol)); + symbol->name = new_name; + symbol->type = S_UNKNOWN; + symbol->flags |= flags; + + symbol->next = symbol_hash[hash]; + symbol_hash[hash] = symbol; + + return symbol; +} + +struct symbol *sym_find(const char *name) +{ + struct symbol *symbol = NULL; + int hash = 0; + + if (!name) + return NULL; + + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + !(symbol->flags & SYMBOL_CONST)) + break; + } + + return symbol; +} + +/* + * Expand symbol's names embedded in the string given in argument. Symbols' + * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to + * the empty string. + */ +const char *sym_expand_string_value(const char *in) +{ + const char *src; + char *res; + size_t reslen; + + reslen = strlen(in) + 1; + res = xmalloc(reslen); + res[0] = '\0'; + + while ((src = strchr(in, '$'))) { + char *p, name[SYMBOL_MAXLENGTH]; + const char *symval = ""; + struct symbol *sym; + size_t newlen; + + strncat(res, in, src - in); + src++; + + p = name; + while (isalnum(*src) || *src == '_') + *p++ = *src++; + *p = '\0'; + + sym = sym_find(name); + if (sym != NULL) { + sym_calc_value(sym); + symval = sym_get_string_value(sym); + } + + newlen = strlen(res) + strlen(symval) + strlen(src) + 1; + if (newlen > reslen) { + reslen = newlen; + res = realloc(res, reslen); + } + + strcat(res, symval); + in = src; + } + strcat(res, in); + + return res; +} + +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = xmalloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + +struct sym_match { + struct symbol *sym; + off_t so, eo; +}; + +/* Compare matched symbols as thus: + * - first, symbols that match exactly + * - then, alphabetical sort + */ +static int sym_rel_comp( const void *sym1, const void *sym2 ) +{ + struct sym_match *s1 = *(struct sym_match **)sym1; + struct sym_match *s2 = *(struct sym_match **)sym2; + int l1, l2; + + /* Exact match: + * - if matched length on symbol s1 is the length of that symbol, + * then this symbol should come first; + * - if matched length on symbol s2 is the length of that symbol, + * then this symbol should come first. + * Note: since the search can be a regexp, both symbols may match + * exactly; if this is the case, we can't decide which comes first, + * and we fallback to sorting alphabetically. + */ + l1 = s1->eo - s1->so; + l2 = s2->eo - s2->so; + if (l1 == strlen(s1->sym->name) && l2 != strlen(s2->sym->name)) + return -1; + if (l1 != strlen(s1->sym->name) && l2 == strlen(s2->sym->name)) + return 1; + + /* As a fallback, sort symbols alphabetically */ + return strcmp(s1->sym->name, s2->sym->name); +} + +struct symbol **sym_re_search(const char *pattern) +{ + struct symbol *sym, **sym_arr = NULL; + struct sym_match **sym_match_arr = NULL; + int i, cnt, size; + regex_t re; + regmatch_t match[1]; + + cnt = size = 0; + /* Skip if empty */ + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE)) + return NULL; + + for_all_symbols(i, sym) { + struct sym_match *tmp_sym_match; + if (sym->flags & SYMBOL_CONST || !sym->name) + continue; + if (regexec(&re, sym->name, 1, match, 0)) + continue; + if (cnt + 1 >= size) { + void *tmp; + size += 16; + tmp = realloc(sym_match_arr, size * sizeof(struct sym_match *)); + if (!tmp) { + goto sym_re_search_free; + } + sym_match_arr = tmp; + } + sym_calc_value(sym); + tmp_sym_match = (struct sym_match*)malloc(sizeof(struct sym_match)); + if (!tmp_sym_match) + goto sym_re_search_free; + tmp_sym_match->sym = sym; + /* As regexec return 0, we know we have a match, so + * we can use match[0].rm_[se]o without further checks + */ + tmp_sym_match->so = match[0].rm_so; + tmp_sym_match->eo = match[0].rm_eo; + sym_match_arr[cnt++] = tmp_sym_match; + } + if (sym_match_arr) { + qsort(sym_match_arr, cnt, sizeof(struct sym_match*), sym_rel_comp); + sym_arr = malloc((cnt+1) * sizeof(struct symbol)); + if (!sym_arr) + goto sym_re_search_free; + for (i = 0; i < cnt; i++) + sym_arr[i] = sym_match_arr[i]->sym; + sym_arr[cnt] = NULL; + } +sym_re_search_free: + if (sym_match_arr) { + for (i = 0; i < cnt; i++) + free(sym_match_arr[i]); + free(sym_match_arr); + } + regfree(&re); + + return sym_arr; +} + +/* + * When we check for recursive dependencies we use a stack to save + * current state so we can print out relevant info to user. + * The entries are located on the call stack so no need to free memory. + * Note inser() remove() must always match to properly clear the stack. + */ +static struct dep_stack { + struct dep_stack *prev, *next; + struct symbol *sym; + struct property *prop; + struct expr *expr; +} *check_top; + +static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) +{ + memset(stack, 0, sizeof(*stack)); + if (check_top) + check_top->next = stack; + stack->prev = check_top; + stack->sym = sym; + check_top = stack; +} + +static void dep_stack_remove(void) +{ + check_top = check_top->prev; + if (check_top) + check_top->next = NULL; +} + +/* + * Called when we have detected a recursive dependency. + * check_top point to the top of the stact so we use + * the ->prev pointer to locate the bottom of the stack. + */ +static void sym_check_print_recursive(struct symbol *last_sym) +{ + struct dep_stack *stack; + struct symbol *sym, *next_sym; + struct menu *menu = NULL; + struct property *prop; + struct dep_stack cv_stack; + + if (sym_is_choice_value(last_sym)) { + dep_stack_insert(&cv_stack, last_sym); + last_sym = prop_get_symbol(sym_get_choice_prop(last_sym)); + } + + for (stack = check_top; stack != NULL; stack = stack->prev) + if (stack->sym == last_sym) + break; + if (!stack) { + fprintf(stderr, "unexpected recursive dependency error\n"); + return; + } + + for (; stack; stack = stack->next) { + sym = stack->sym; + next_sym = stack->next ? stack->next->sym : last_sym; + prop = stack->prop; + if (prop == NULL) + prop = stack->sym->prop; + + /* for choice values find the menu entry (used below) */ + if (sym_is_choice(sym) || sym_is_choice_value(sym)) { + for (prop = sym->prop; prop; prop = prop->next) { + menu = prop->menu; + if (prop->menu) + break; + } + } + if (stack->sym == last_sym) + fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", + prop->file->name, prop->lineno); + if (stack->expr) { + fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + prop_get_type_name(prop->type), + next_sym->name ? next_sym->name : ""); + } else if (stack->prop) { + fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice(sym)) { + fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice_value(sym)) { + fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else { + fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } + } + + if (check_top == &cv_stack) + dep_stack_remove(); +} + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ + struct symbol *sym; + + if (!e) + return NULL; + switch (e->type) { + case E_OR: + case E_AND: + sym = sym_check_expr_deps(e->left.expr); + if (sym) + return sym; + return sym_check_expr_deps(e->right.expr); + case E_NOT: + return sym_check_expr_deps(e->left.expr); + case E_EQUAL: + case E_UNEQUAL: + sym = sym_check_deps(e->left.sym); + if (sym) + return sym; + return sym_check_deps(e->right.sym); + case E_SYMBOL: + return sym_check_deps(e->left.sym); + default: + break; + } + printf("Oops! How to check %d?\n", e->type); + return NULL; +} + +/* return NULL when dependencies are OK */ +static struct symbol *sym_check_sym_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + struct dep_stack stack; + + dep_stack_insert(&stack, sym); + + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + goto out; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + stack.prop = prop; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + break; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + stack.expr = prop->expr; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + break; + stack.expr = NULL; + } + +out: + dep_stack_remove(); + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + struct dep_stack stack; + + dep_stack_insert(&stack, choice); + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; + if (sym2) + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) + break; + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + dep_stack_remove(); + + return sym2; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + sym_check_print_recursive(sym); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + if (sym_is_choice_value(sym)) { + struct dep_stack stack; + + /* for choice groups start the check with main choice symbol */ + dep_stack_insert(&stack, sym); + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + dep_stack_remove(); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; + } + + if (sym2 && sym2 == sym) + sym2 = NULL; + + return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = xmalloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ + if (prop->expr && (prop->expr->type == E_SYMBOL || + prop->expr->type == E_LIST)) + return prop->expr->left.sym; + return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ + switch (type) { + case P_PROMPT: + return "prompt"; + case P_ENV: + return "env"; + case P_COMMENT: + return "comment"; + case P_MENU: + return "menu"; + case P_DEFAULT: + return "default"; + case P_CHOICE: + return "choice"; + case P_SELECT: + return "select"; + case P_RANGE: + return "range"; + case P_SYMBOL: + return "symbol"; + case P_UNKNOWN: + break; + } + return "unknown"; +} + +static void prop_add_env(const char *env) +{ + struct symbol *sym, *sym2; + struct property *prop; + char *p; + + sym = current_entry->sym; + sym->flags |= SYMBOL_AUTO; + for_all_properties(sym, prop, P_ENV) { + sym2 = prop_get_symbol(prop); + if (strcmp(sym2->name, env)) + menu_warn(current_entry, "redefining environment symbol from %s", + sym2->name); + return; + } + + prop = prop_alloc(P_ENV, sym); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); + + sym_env_list = expr_alloc_one(E_LIST, sym_env_list); + sym_env_list->right.sym = sym; + + p = getenv(env); + if (p) + sym_add_default(sym, p); + else + menu_warn(current_entry, "environment variable %s undefined", env); +} diff -Nru seabios-1.7.1/scripts/kconfig/util.c seabios-1.7.4/scripts/kconfig/util.c --- seabios-1.7.1/scripts/kconfig/util.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/util.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel + * Copyright (C) 2002-2005 Sam Ravnborg + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ + struct file *file; + const char *file_name = sym_expand_string_value(name); + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) { + free((void *)file_name); + return file; + } + } + + file = xmalloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = file_name; + file->next = file_list; + file_list = file; + return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ + struct symbol *sym, *env_sym; + struct expr *e; + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\n%s: \\\n" + "\t$(deps_config)\n\n", conf_get_autoconfig_name()); + + expr_list_for_each_sym(sym_env_list, e, sym) { + struct property *prop; + const char *value; + + prop = sym_get_env_prop(sym); + env_sym = prop_get_symbol(prop); + if (!env_sym) + continue; + value = getenv(env_sym->name); + if (!value) + value = ""; + fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); + fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); + fprintf(out, "endif\n"); + } + + fprintf(out, "\n$(deps_config): ;\n"); + fclose(out); + rename("..config.tmp", name); + return 0; +} + + +/* Allocate initial growable string */ +struct gstr str_new(void) +{ + struct gstr gs; + gs.s = xmalloc(sizeof(char) * 64); + gs.len = 64; + gs.max_width = 0; + strcpy(gs.s, "\0"); + return gs; +} + +/* Allocate and assign growable string */ +struct gstr str_assign(const char *s) +{ + struct gstr gs; + gs.s = strdup(s); + gs.len = strlen(s) + 1; + gs.max_width = 0; + return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ + if (gs->s) + free(gs->s); + gs->s = NULL; + gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ + size_t l; + if (s) { + l = strlen(gs->s) + strlen(s) + 1; + if (l > gs->len) { + gs->s = realloc(gs->s, l); + gs->len = l; + } + strcat(gs->s, s); + } +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ + va_list ap; + char s[10000]; /* big enough... */ + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + str_append(gs, s); + va_end(ap); +} + +/* Retrieve value of growable string */ +const char *str_get(struct gstr *gs) +{ + return gs->s; +} + +void *xmalloc(size_t size) +{ + void *p = malloc(size); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} + +void *xcalloc(size_t nmemb, size_t size) +{ + void *p = calloc(nmemb, size); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} + + diff -Nru seabios-1.7.1/scripts/kconfig/zconf.gperf seabios-1.7.4/scripts/kconfig/zconf.gperf --- seabios-1.7.1/scripts/kconfig/zconf.gperf 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/zconf.gperf 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,47 @@ +%language=ANSI-C +%define hash-function-name kconf_id_hash +%define lookup-function-name kconf_id_lookup +%define string-pool-name kconf_id_strings +%compare-strncmp +%enum +%pic +%struct-type + +struct kconf_id; + +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); + +%% +mainmenu, T_MAINMENU, TF_COMMAND +menu, T_MENU, TF_COMMAND +endmenu, T_ENDMENU, TF_COMMAND +source, T_SOURCE, TF_COMMAND +choice, T_CHOICE, TF_COMMAND +endchoice, T_ENDCHOICE, TF_COMMAND +comment, T_COMMENT, TF_COMMAND +config, T_CONFIG, TF_COMMAND +menuconfig, T_MENUCONFIG, TF_COMMAND +help, T_HELP, TF_COMMAND +if, T_IF, TF_COMMAND|TF_PARAM +endif, T_ENDIF, TF_COMMAND +depends, T_DEPENDS, TF_COMMAND +optional, T_OPTIONAL, TF_COMMAND +default, T_DEFAULT, TF_COMMAND, S_UNKNOWN +prompt, T_PROMPT, TF_COMMAND +tristate, T_TYPE, TF_COMMAND, S_TRISTATE +def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE +bool, T_TYPE, TF_COMMAND, S_BOOLEAN +boolean, T_TYPE, TF_COMMAND, S_BOOLEAN +def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN +int, T_TYPE, TF_COMMAND, S_INT +hex, T_TYPE, TF_COMMAND, S_HEX +string, T_TYPE, TF_COMMAND, S_STRING +select, T_SELECT, TF_COMMAND +range, T_RANGE, TF_COMMAND +visible, T_VISIBLE, TF_COMMAND +option, T_OPTION, TF_COMMAND +on, T_ON, TF_PARAM +modules, T_OPT_MODULES, TF_OPTION +defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION +env, T_OPT_ENV, TF_OPTION +%% diff -Nru seabios-1.7.1/scripts/kconfig/zconf.hash.c_shipped seabios-1.7.4/scripts/kconfig/zconf.hash.c_shipped --- seabios-1.7.1/scripts/kconfig/zconf.hash.c_shipped 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/zconf.hash.c_shipped 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,286 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 10 "scripts/kconfig/zconf.gperf" +struct kconf_id; + +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); +/* maximum key range = 71, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +kconf_id_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 25, 25, + 0, 0, 0, 5, 0, 0, 73, 73, 5, 0, + 10, 5, 45, 73, 20, 20, 0, 15, 15, 73, + 20, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +struct kconf_id_strings_t + { + char kconf_id_strings_str2[sizeof("if")]; + char kconf_id_strings_str3[sizeof("int")]; + char kconf_id_strings_str5[sizeof("endif")]; + char kconf_id_strings_str7[sizeof("default")]; + char kconf_id_strings_str8[sizeof("tristate")]; + char kconf_id_strings_str9[sizeof("endchoice")]; + char kconf_id_strings_str12[sizeof("def_tristate")]; + char kconf_id_strings_str13[sizeof("def_bool")]; + char kconf_id_strings_str14[sizeof("defconfig_list")]; + char kconf_id_strings_str17[sizeof("on")]; + char kconf_id_strings_str18[sizeof("optional")]; + char kconf_id_strings_str21[sizeof("option")]; + char kconf_id_strings_str22[sizeof("endmenu")]; + char kconf_id_strings_str23[sizeof("mainmenu")]; + char kconf_id_strings_str25[sizeof("menuconfig")]; + char kconf_id_strings_str27[sizeof("modules")]; + char kconf_id_strings_str29[sizeof("menu")]; + char kconf_id_strings_str31[sizeof("select")]; + char kconf_id_strings_str32[sizeof("comment")]; + char kconf_id_strings_str33[sizeof("env")]; + char kconf_id_strings_str35[sizeof("range")]; + char kconf_id_strings_str36[sizeof("choice")]; + char kconf_id_strings_str39[sizeof("bool")]; + char kconf_id_strings_str41[sizeof("source")]; + char kconf_id_strings_str42[sizeof("visible")]; + char kconf_id_strings_str43[sizeof("hex")]; + char kconf_id_strings_str46[sizeof("config")]; + char kconf_id_strings_str47[sizeof("boolean")]; + char kconf_id_strings_str51[sizeof("string")]; + char kconf_id_strings_str54[sizeof("help")]; + char kconf_id_strings_str56[sizeof("prompt")]; + char kconf_id_strings_str72[sizeof("depends")]; + }; +static const struct kconf_id_strings_t kconf_id_strings_contents = + { + "if", + "int", + "endif", + "default", + "tristate", + "endchoice", + "def_tristate", + "def_bool", + "defconfig_list", + "on", + "optional", + "option", + "endmenu", + "mainmenu", + "menuconfig", + "modules", + "menu", + "select", + "comment", + "env", + "range", + "choice", + "bool", + "source", + "visible", + "hex", + "config", + "boolean", + "string", + "help", + "prompt", + "depends" + }; +#define kconf_id_strings ((const char *) &kconf_id_strings_contents) +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct kconf_id * +kconf_id_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 32, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 14, + MIN_HASH_VALUE = 2, + MAX_HASH_VALUE = 72 + }; + + static const struct kconf_id wordlist[] = + { + {-1}, {-1}, +#line 25 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM}, +#line 36 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT}, + {-1}, +#line 26 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, + {-1}, +#line 29 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, +#line 31 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE}, +#line 20 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, + {-1}, {-1}, +#line 32 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE}, +#line 35 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, +#line 45 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION}, + {-1}, {-1}, +#line 43 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM}, +#line 28 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND}, + {-1}, {-1}, +#line 42 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND}, +#line 17 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND}, +#line 15 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_MAINMENU, TF_COMMAND}, + {-1}, +#line 23 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND}, + {-1}, +#line 44 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, + {-1}, +#line 16 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, + {-1}, +#line 39 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND}, +#line 21 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, +#line 46 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION}, + {-1}, +#line 40 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND}, +#line 19 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND}, + {-1}, {-1}, +#line 33 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, +#line 18 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND}, +#line 41 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND}, +#line 37 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX}, + {-1}, {-1}, +#line 22 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND}, +#line 34 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, {-1}, {-1}, +#line 38 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING}, + {-1}, {-1}, +#line 24 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54, T_HELP, TF_COMMAND}, + {-1}, +#line 30 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56, T_PROMPT, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 27 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72, T_DEPENDS, TF_COMMAND} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = kconf_id_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + kconf_id_strings; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &wordlist[key]; + } + } + } + return 0; +} +#line 47 "scripts/kconfig/zconf.gperf" + diff -Nru seabios-1.7.1/scripts/kconfig/zconf.l seabios-1.7.4/scripts/kconfig/zconf.l --- seabios-1.7.1/scripts/kconfig/zconf.l 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/zconf.l 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,364 @@ +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault perf-report perf-report +%option noinput +%x COMMAND HELP STRING PARAM +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = xmalloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = xmalloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} +%} + +ws [ \n\t] +n [A-Za-z0-9_] + +%% + int str = 0; + int ts, i; + +[ \t]*#.*\n | +[ \t]*\n { + current_file->lineno++; + return T_EOL; +} +[ \t]*#.* + + +[ \t]+ { + BEGIN(COMMAND); +} + +. { + unput(yytext[0]); + BEGIN(COMMAND); +} + + +{ + {n}+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + . + \n { + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } +} + +{ + "&&" return T_AND; + "||" return T_OR; + "(" return T_OPEN_PAREN; + ")" return T_CLOSE_PAREN; + "!" return T_NOT; + "=" return T_EQUAL; + "!=" return T_UNEQUAL; + \"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } + \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; + --- /* ignore */ + ({n}|[-/.])+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + #.* /* comment */ + \\\n current_file->lineno++; + . + <> { + BEGIN(INITIAL); + } +} + +{ + [^'"\\\n]+/\n { + append_string(yytext, yyleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + [^'"\\\n]+ { + append_string(yytext, yyleng); + } + \\.?/\n { + append_string(yytext + 1, yyleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + \\.? { + append_string(yytext + 1, yyleng - 1); + } + \'|\" { + if (str == yytext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(yytext, 1); + } + \n { + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + <> { + BEGIN(INITIAL); + } +} + +{ + [ \t]+ { + ts = 0; + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + [ \t]*\n/[^ \t\n] { + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + [ \t]*\n { + current_file->lineno++; + append_string("\n", 1); + } + [^ \t\n].* { + while (yyleng) { + if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) + break; + yyleng--; + } + append_string(yytext, yyleng); + if (!first_ts) + first_ts = last_ts; + } + <> { + zconf_endhelp(); + return T_HELPTEXT; + } +} + +<> { + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(yyin); + yyterminate(); +} + +%% +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + yyin = zconf_fopen(name); + if (!yyin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = xmalloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = xmalloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + yyin = zconf_fopen(file->name); + if (!yyin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } + } + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} diff -Nru seabios-1.7.1/scripts/kconfig/zconf.lex.c_shipped seabios-1.7.4/scripts/kconfig/zconf.lex.c_shipped --- seabios-1.7.1/scripts/kconfig/zconf.lex.c_shipped 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/zconf.lex.c_shipped 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,2420 @@ + +#line 3 "scripts/kconfig/zconf.lex.c_shipped" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer zconf_create_buffer +#define yy_delete_buffer zconf_delete_buffer +#define yy_flex_debug zconf_flex_debug +#define yy_init_buffer zconf_init_buffer +#define yy_flush_buffer zconf_flush_buffer +#define yy_load_buffer_state zconf_load_buffer_state +#define yy_switch_to_buffer zconf_switch_to_buffer +#define yyin zconfin +#define yyleng zconfleng +#define yylex zconflex +#define yylineno zconflineno +#define yyout zconfout +#define yyrestart zconfrestart +#define yytext zconftext +#define yywrap zconfwrap +#define yyalloc zconfalloc +#define yyrealloc zconfrealloc +#define yyfree zconffree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via zconfrestart()), so that the user can continue scanning by + * just pointing zconfin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); +void zconf_delete_buffer (YY_BUFFER_STATE b ); +void zconf_flush_buffer (YY_BUFFER_STATE b ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); + +void *zconfalloc (yy_size_t ); +void *zconfrealloc (void *,yy_size_t ); +void zconffree (void * ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][17] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + }, + + { + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 + }, + + { + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 + }, + + { + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 + }, + + { + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 + + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 + }, + + { + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 + }, + + { + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 + }, + + { + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + + }, + + { + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 + }, + + { + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 + }, + + { + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 + }, + + { + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 + + }, + + { + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 + }, + + { + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 + }, + + { + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 + }, + + { + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 + }, + + { + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 + + }, + + { + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + }, + + { + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 + }, + + { + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 + }, + + { + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 + }, + + { + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 + + }, + + { + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 + }, + + { + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 + }, + + { + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 + }, + + { + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 + }, + + { + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 + + }, + + { + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 + }, + + { + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 + + }, + + { + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + }, + + { + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 + }, + + { + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 + }, + + { + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 + + }, + + { + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 + }, + + { + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 + }, + + { + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 + }, + + { + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 + }, + + { + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + + }, + + { + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 + }, + + { + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 + }, + + { + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 + }, + + { + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 + }, + + { + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 + + }, + + { + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 + }, + + } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + zconfleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[61] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, + 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, + 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; +#define YY_NO_INPUT 1 + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = xmalloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = xmalloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int zconflex_destroy (void ); + +int zconfget_debug (void ); + +void zconfset_debug (int debug_flag ); + +YY_EXTRA_TYPE zconfget_extra (void ); + +void zconfset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *zconfget_in (void ); + +void zconfset_in (FILE * in_str ); + +FILE *zconfget_out (void ); + +void zconfset_out (FILE * out_str ); + +int zconfget_leng (void ); + +char *zconfget_text (void ); + +int zconfget_lineno (void ); + +void zconfset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + errno=0; \ + while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(zconfin); \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + int str = 0; + int ts, i; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! zconfin ) + zconfin = stdin; + + if ( ! zconfout ) + zconfout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of zconftext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + return T_EOL; +} + YY_BREAK +case 3: +YY_RULE_SETUP + + YY_BREAK +case 4: +YY_RULE_SETUP +{ + BEGIN(COMMAND); +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + unput(zconftext[0]); + BEGIN(COMMAND); +} + YY_BREAK + +case 6: +YY_RULE_SETUP +{ + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 7: +YY_RULE_SETUP + + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } + YY_BREAK + +case 9: +YY_RULE_SETUP +return T_AND; + YY_BREAK +case 10: +YY_RULE_SETUP +return T_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +return T_OPEN_PAREN; + YY_BREAK +case 12: +YY_RULE_SETUP +return T_CLOSE_PAREN; + YY_BREAK +case 13: +YY_RULE_SETUP +return T_NOT; + YY_BREAK +case 14: +YY_RULE_SETUP +return T_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +return T_UNEQUAL; + YY_BREAK +case 16: +YY_RULE_SETUP +{ + str = zconftext[0]; + new_string(); + BEGIN(STRING); + } + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; + YY_BREAK +case 18: +YY_RULE_SETUP +/* ignore */ + YY_BREAK +case 19: +YY_RULE_SETUP +{ + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 20: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +current_file->lineno++; + YY_BREAK +case 22: +YY_RULE_SETUP + + YY_BREAK +case YY_STATE_EOF(PARAM): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 23: +/* rule 23 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 24: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + } + YY_BREAK +case 25: +/* rule 25 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 26: +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + } + YY_BREAK +case 27: +YY_RULE_SETUP +{ + if (str == zconftext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(zconftext, 1); + } + YY_BREAK +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +{ + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + YY_BREAK +case YY_STATE_EOF(STRING): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 29: +YY_RULE_SETUP +{ + ts = 0; + for (i = 0; i < zconfleng; i++) { + if (zconftext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + YY_BREAK +case 30: +/* rule 30 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + append_string("\n", 1); + } + YY_BREAK +case 32: +YY_RULE_SETUP +{ + while (zconfleng) { + if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) + break; + zconfleng--; + } + append_string(zconftext, zconfleng); + if (!first_ts) + first_ts = last_ts; + } + YY_BREAK +case YY_STATE_EOF(HELP): +{ + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(zconfin); + yyterminate(); +} + YY_BREAK +case 33: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed zconfin at a new source and called + * zconflex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( zconfwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * zconftext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + zconfrestart(zconfin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up zconftext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + zconfrestart(zconfin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( zconfwrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve zconftext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void zconfrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); + zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * zconfpop_buffer_state(); + * zconfpush_buffer_state(new_buffer); + */ + zconfensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + zconf_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (zconfwrap()) processing, but the only time this flag + * is looked at is after zconfwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + zconf_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + * + */ + void zconf_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + zconffree((void *) b->yy_ch_buf ); + + zconffree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ + static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + zconf_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then zconf_init_buffer was _probably_ + * called from zconfrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void zconf_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + zconfensure_buffer_stack(); + + /* This block is copied from zconf_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from zconf_switch_to_buffer. */ + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void zconfpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + zconf_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +{ + + return zconf_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) zconfalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = zconf_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + zconftext[zconfleng] = (yy_hold_char); \ + (yy_c_buf_p) = zconftext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + zconfleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int zconfget_lineno (void) +{ + + return zconflineno; +} + +/** Get the input stream. + * + */ +FILE *zconfget_in (void) +{ + return zconfin; +} + +/** Get the output stream. + * + */ +FILE *zconfget_out (void) +{ + return zconfout; +} + +/** Get the length of the current token. + * + */ +int zconfget_leng (void) +{ + return zconfleng; +} + +/** Get the current token. + * + */ + +char *zconfget_text (void) +{ + return zconftext; +} + +/** Set the current line number. + * @param line_number + * + */ +void zconfset_lineno (int line_number ) +{ + + zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE * in_str ) +{ + zconfin = in_str ; +} + +void zconfset_out (FILE * out_str ) +{ + zconfout = out_str ; +} + +int zconfget_debug (void) +{ + return zconf_flex_debug; +} + +void zconfset_debug (int bdebug ) +{ + zconf_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from zconflex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + zconfin = stdin; + zconfout = stdout; +#else + zconfin = (FILE *) 0; + zconfout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * zconflex_init() + */ + return 0; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + zconfpop_buffer_state(); + } + + /* Destroy the stack itself. */ + zconffree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * zconflex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *zconfalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *zconfrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ + free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = xmalloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = xmalloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + zconfin = zconf_fopen(file->name); + if (!zconfin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } + } + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(zconfin); + zconf_delete_buffer(YY_CURRENT_BUFFER); + zconf_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} + diff -Nru seabios-1.7.1/scripts/kconfig/zconf.tab.c_shipped seabios-1.7.4/scripts/kconfig/zconf.tab.c_shipped --- seabios-1.7.1/scripts/kconfig/zconf.tab.c_shipped 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/zconf.tab.c_shipped 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,2504 @@ +/* A Bison parser, made by GNU Bison 2.4.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2009, 2010 Free Software Foundation, Inc. + + 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 3 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, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse zconfparse +#define yylex zconflex +#define yyerror zconferror +#define yylval zconflval +#define yychar zconfchar +#define yydebug zconfdebug +#define yynerrs zconfnerrs + + +/* Copy the first part of user declarations. */ + + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_MAINMENU = 258, + T_MENU = 259, + T_ENDMENU = 260, + T_SOURCE = 261, + T_CHOICE = 262, + T_ENDCHOICE = 263, + T_COMMENT = 264, + T_CONFIG = 265, + T_MENUCONFIG = 266, + T_HELP = 267, + T_HELPTEXT = 268, + T_IF = 269, + T_ENDIF = 270, + T_DEPENDS = 271, + T_OPTIONAL = 272, + T_PROMPT = 273, + T_TYPE = 274, + T_DEFAULT = 275, + T_SELECT = 276, + T_RANGE = 277, + T_VISIBLE = 278, + T_OPTION = 279, + T_ON = 280, + T_WORD = 281, + T_WORD_QUOTE = 282, + T_UNEQUAL = 283, + T_CLOSE_PAREN = 284, + T_OPEN_PAREN = 285, + T_EOL = 286, + T_OR = 287, + T_AND = 288, + T_EQUAL = 289, + T_NOT = 290 + }; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + + + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + const struct kconf_id *id; + + + +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Include zconf.hash.c here so it can see the token constants. */ +#include "zconf.hash.c" + + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 11 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 290 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 36 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 50 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 118 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 191 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 290 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 6, 8, 11, 13, 14, 17, 20, + 23, 26, 31, 36, 40, 42, 44, 46, 48, 50, + 52, 54, 56, 58, 60, 62, 64, 66, 68, 72, + 75, 79, 82, 86, 89, 90, 93, 96, 99, 102, + 105, 108, 112, 117, 122, 127, 133, 137, 138, 142, + 143, 146, 150, 153, 155, 159, 160, 163, 166, 169, + 172, 175, 180, 184, 187, 192, 193, 196, 200, 202, + 206, 207, 210, 213, 216, 220, 224, 228, 230, 234, + 235, 238, 241, 244, 248, 252, 255, 258, 261, 262, + 265, 268, 271, 276, 277, 280, 283, 286, 287, 290, + 292, 294, 297, 300, 303, 305, 308, 309, 312, 314, + 318, 322, 326, 329, 333, 337, 339, 341, 342 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 37, 0, -1, 81, 38, -1, 38, -1, 63, 39, + -1, 39, -1, -1, 39, 41, -1, 39, 55, -1, + 39, 67, -1, 39, 80, -1, 39, 26, 1, 31, + -1, 39, 40, 1, 31, -1, 39, 1, 31, -1, + 16, -1, 18, -1, 19, -1, 21, -1, 17, -1, + 22, -1, 20, -1, 23, -1, 31, -1, 61, -1, + 71, -1, 44, -1, 46, -1, 69, -1, 26, 1, + 31, -1, 1, 31, -1, 10, 26, 31, -1, 43, + 47, -1, 11, 26, 31, -1, 45, 47, -1, -1, + 47, 48, -1, 47, 49, -1, 47, 75, -1, 47, + 73, -1, 47, 42, -1, 47, 31, -1, 19, 78, + 31, -1, 18, 79, 82, 31, -1, 20, 83, 82, + 31, -1, 21, 26, 82, 31, -1, 22, 84, 84, + 82, 31, -1, 24, 50, 31, -1, -1, 50, 26, + 51, -1, -1, 34, 79, -1, 7, 85, 31, -1, + 52, 56, -1, 80, -1, 53, 58, 54, -1, -1, + 56, 57, -1, 56, 75, -1, 56, 73, -1, 56, + 31, -1, 56, 42, -1, 18, 79, 82, 31, -1, + 19, 78, 31, -1, 17, 31, -1, 20, 26, 82, + 31, -1, -1, 58, 41, -1, 14, 83, 81, -1, + 80, -1, 59, 62, 60, -1, -1, 62, 41, -1, + 62, 67, -1, 62, 55, -1, 3, 79, 81, -1, + 4, 79, 31, -1, 64, 76, 74, -1, 80, -1, + 65, 68, 66, -1, -1, 68, 41, -1, 68, 67, + -1, 68, 55, -1, 6, 79, 31, -1, 9, 79, + 31, -1, 70, 74, -1, 12, 31, -1, 72, 13, + -1, -1, 74, 75, -1, 74, 31, -1, 74, 42, + -1, 16, 25, 83, 31, -1, -1, 76, 77, -1, + 76, 31, -1, 23, 82, -1, -1, 79, 82, -1, + 26, -1, 27, -1, 5, 31, -1, 8, 31, -1, + 15, 31, -1, 31, -1, 81, 31, -1, -1, 14, + 83, -1, 84, -1, 84, 34, 84, -1, 84, 28, + 84, -1, 30, 83, 29, -1, 35, 83, -1, 83, + 32, 83, -1, 83, 33, 83, -1, 26, -1, 27, + -1, -1, 26, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 104, 104, 104, 106, 106, 108, 110, 111, 112, + 113, 114, 115, 119, 123, 123, 123, 123, 123, 123, + 123, 123, 127, 128, 129, 130, 131, 132, 136, 137, + 143, 151, 157, 165, 175, 177, 178, 179, 180, 181, + 182, 185, 193, 199, 209, 215, 221, 224, 226, 237, + 238, 243, 252, 257, 265, 268, 270, 271, 272, 273, + 274, 277, 283, 294, 300, 310, 312, 317, 325, 333, + 336, 338, 339, 340, 345, 352, 359, 364, 372, 375, + 377, 378, 379, 382, 390, 397, 404, 410, 417, 419, + 420, 421, 424, 432, 434, 435, 438, 445, 447, 452, + 453, 456, 457, 458, 462, 463, 466, 467, 470, 471, + 472, 473, 474, 475, 476, 479, 480, 483, 484 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", + "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "start", "stmt_list", "option_name", + "common_stmt", "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "symbol_option", "symbol_option_list", + "symbol_option_arg", "choice", "choice_entry", "choice_end", + "choice_stmt", "choice_option_list", "choice_option", "choice_block", + "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu", + "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt", + "comment", "comment_stmt", "help_start", "help", "depends_list", + "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt", + "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 36, 37, 37, 38, 38, 39, 39, 39, 39, + 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, + 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, + 43, 44, 45, 46, 47, 47, 47, 47, 47, 47, + 47, 48, 48, 48, 48, 48, 49, 50, 50, 51, + 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, + 56, 57, 57, 57, 57, 58, 58, 59, 60, 61, + 62, 62, 62, 62, 63, 64, 65, 66, 67, 68, + 68, 68, 68, 69, 70, 71, 72, 73, 74, 74, + 74, 74, 75, 76, 76, 76, 77, 78, 78, 79, + 79, 80, 80, 80, 81, 81, 82, 82, 83, 83, + 83, 83, 83, 83, 83, 84, 84, 85, 85 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 2, 1, 2, 1, 0, 2, 2, 2, + 2, 4, 4, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 3, 2, 3, 2, 0, 2, 2, 2, 2, 2, + 2, 3, 4, 4, 4, 5, 3, 0, 3, 0, + 2, 3, 2, 1, 3, 0, 2, 2, 2, 2, + 2, 4, 3, 2, 4, 0, 2, 3, 1, 3, + 0, 2, 2, 2, 3, 3, 3, 1, 3, 0, + 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, + 2, 2, 4, 0, 2, 2, 2, 0, 2, 1, + 1, 2, 2, 2, 1, 2, 0, 2, 1, 3, + 3, 3, 2, 3, 3, 1, 1, 0, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 6, 0, 104, 0, 3, 0, 6, 6, 99, 100, + 0, 1, 0, 0, 0, 0, 117, 0, 0, 0, + 0, 0, 0, 14, 18, 15, 16, 20, 17, 19, + 21, 0, 22, 0, 7, 34, 25, 34, 26, 55, + 65, 8, 70, 23, 93, 79, 9, 27, 88, 24, + 10, 0, 105, 2, 74, 13, 0, 101, 0, 118, + 0, 102, 0, 0, 0, 115, 116, 0, 0, 0, + 108, 103, 0, 0, 0, 0, 0, 0, 0, 88, + 0, 0, 75, 83, 51, 84, 30, 32, 0, 112, + 0, 0, 67, 0, 0, 11, 12, 0, 0, 0, + 0, 97, 0, 0, 0, 47, 0, 40, 39, 35, + 36, 0, 38, 37, 0, 0, 97, 0, 59, 60, + 56, 58, 57, 66, 54, 53, 71, 73, 69, 72, + 68, 106, 95, 0, 94, 80, 82, 78, 81, 77, + 90, 91, 89, 111, 113, 114, 110, 109, 29, 86, + 0, 106, 0, 106, 106, 106, 0, 0, 0, 87, + 63, 106, 0, 106, 0, 96, 0, 0, 41, 98, + 0, 0, 106, 49, 46, 28, 0, 62, 0, 107, + 92, 42, 43, 44, 0, 0, 48, 61, 64, 45, + 50 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 3, 4, 5, 33, 34, 108, 35, 36, 37, + 38, 74, 109, 110, 157, 186, 39, 40, 124, 41, + 76, 120, 77, 42, 128, 43, 78, 6, 44, 45, + 137, 46, 80, 47, 48, 49, 111, 112, 81, 113, + 79, 134, 152, 153, 50, 7, 165, 69, 70, 60 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -90 +static const yytype_int16 yypact[] = +{ + 4, 42, -90, 96, -90, 111, -90, 15, -90, -90, + 75, -90, 82, 42, 104, 42, 110, 107, 42, 115, + 125, -4, 121, -90, -90, -90, -90, -90, -90, -90, + -90, 162, -90, 163, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 139, -90, -90, 138, -90, 142, -90, 143, -90, + 152, -90, 164, 167, 168, -90, -90, -4, -4, 77, + -18, -90, 177, 185, 33, 71, 195, 247, 236, -2, + 236, 171, -90, -90, -90, -90, -90, -90, 41, -90, + -4, -4, 138, 97, 97, -90, -90, 186, 187, 194, + 42, 42, -4, 196, 97, -90, 219, -90, -90, -90, + -90, 210, -90, -90, 204, 42, 42, 199, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 222, -90, 223, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, 215, -90, -90, -90, -90, -90, + -4, 222, 228, 222, -5, 222, 97, 35, 229, -90, + -90, 222, 232, 222, -4, -90, 135, 233, -90, -90, + 234, 235, 222, 240, -90, -90, 237, -90, 239, -13, + -90, -90, -90, -90, 244, 42, -90, -90, -90, -90, + -90 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -90, -90, 269, 271, -90, 23, -70, -90, -90, -90, + -90, 243, -90, -90, -90, -90, -90, -90, -90, -48, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, -20, -90, -90, -90, -90, -90, 206, 205, -68, + -90, -90, 169, -1, 27, -7, 118, -66, -89, -90 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -86 +static const yytype_int16 yytable[] = +{ + 10, 88, 89, 54, 146, 147, 119, 1, 122, 164, + 93, 141, 56, 142, 58, 156, 94, 62, 1, 90, + 91, 131, 65, 66, 144, 145, 67, 90, 91, 132, + 127, 68, 136, -31, 97, 2, 154, -31, -31, -31, + -31, -31, -31, -31, -31, 98, 52, -31, -31, 99, + -31, 100, 101, 102, 103, 104, -31, 105, 129, 106, + 138, 173, 92, 141, 107, 142, 174, 172, 8, 9, + 143, -33, 97, 90, 91, -33, -33, -33, -33, -33, + -33, -33, -33, 98, 166, -33, -33, 99, -33, 100, + 101, 102, 103, 104, -33, 105, 11, 106, 179, 151, + 123, 126, 107, 135, 125, 130, 2, 139, 2, 90, + 91, -5, 12, 55, 161, 13, 14, 15, 16, 17, + 18, 19, 20, 65, 66, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 57, 59, 31, 61, -4, + 12, 63, 32, 13, 14, 15, 16, 17, 18, 19, + 20, 64, 71, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 72, 73, 31, 180, 90, 91, 52, + 32, -85, 97, 82, 83, -85, -85, -85, -85, -85, + -85, -85, -85, 84, 190, -85, -85, 99, -85, -85, + -85, -85, -85, -85, -85, 85, 97, 106, 86, 87, + -52, -52, 140, -52, -52, -52, -52, 98, 95, -52, + -52, 99, 114, 115, 116, 117, 96, 148, 149, 150, + 158, 106, 155, 159, 97, 163, 118, -76, -76, -76, + -76, -76, -76, -76, -76, 160, 164, -76, -76, 99, + 13, 14, 15, 16, 17, 18, 19, 20, 91, 106, + 21, 22, 14, 15, 140, 17, 18, 19, 20, 168, + 175, 21, 22, 177, 181, 182, 183, 32, 187, 167, + 188, 169, 170, 171, 185, 189, 53, 51, 32, 176, + 75, 178, 121, 0, 133, 162, 0, 0, 0, 0, + 184 +}; + +static const yytype_int16 yycheck[] = +{ + 1, 67, 68, 10, 93, 94, 76, 3, 76, 14, + 28, 81, 13, 81, 15, 104, 34, 18, 3, 32, + 33, 23, 26, 27, 90, 91, 30, 32, 33, 31, + 78, 35, 80, 0, 1, 31, 102, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 31, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 78, 26, + 80, 26, 69, 133, 31, 133, 31, 156, 26, 27, + 29, 0, 1, 32, 33, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 150, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 0, 26, 164, 100, + 77, 78, 31, 80, 77, 78, 31, 80, 31, 32, + 33, 0, 1, 31, 115, 4, 5, 6, 7, 8, + 9, 10, 11, 26, 27, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 26, 26, 31, 0, + 1, 26, 31, 4, 5, 6, 7, 8, 9, 10, + 11, 26, 31, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 1, 1, 26, 31, 32, 33, 31, + 31, 0, 1, 31, 31, 4, 5, 6, 7, 8, + 9, 10, 11, 31, 185, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 1, 26, 31, 31, + 5, 6, 31, 8, 9, 10, 11, 12, 31, 14, + 15, 16, 17, 18, 19, 20, 31, 31, 31, 25, + 1, 26, 26, 13, 1, 26, 31, 4, 5, 6, + 7, 8, 9, 10, 11, 31, 14, 14, 15, 16, + 4, 5, 6, 7, 8, 9, 10, 11, 33, 26, + 14, 15, 5, 6, 31, 8, 9, 10, 11, 31, + 31, 14, 15, 31, 31, 31, 31, 31, 31, 151, + 31, 153, 154, 155, 34, 31, 7, 6, 31, 161, + 37, 163, 76, -1, 79, 116, -1, -1, -1, -1, + 172 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 31, 37, 38, 39, 63, 81, 26, 27, + 79, 0, 1, 4, 5, 6, 7, 8, 9, 10, + 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 26, 31, 40, 41, 43, 44, 45, 46, 52, + 53, 55, 59, 61, 64, 65, 67, 69, 70, 71, + 80, 39, 31, 38, 81, 31, 79, 31, 79, 26, + 85, 31, 79, 26, 26, 26, 27, 30, 35, 83, + 84, 31, 1, 1, 47, 47, 56, 58, 62, 76, + 68, 74, 31, 31, 31, 31, 31, 31, 83, 83, + 32, 33, 81, 28, 34, 31, 31, 1, 12, 16, + 18, 19, 20, 21, 22, 24, 26, 31, 42, 48, + 49, 72, 73, 75, 17, 18, 19, 20, 31, 42, + 57, 73, 75, 41, 54, 80, 41, 55, 60, 67, + 80, 23, 31, 74, 77, 41, 55, 66, 67, 80, + 31, 42, 75, 29, 83, 83, 84, 84, 31, 31, + 25, 79, 78, 79, 83, 26, 84, 50, 1, 13, + 31, 79, 78, 26, 14, 82, 83, 82, 31, 82, + 82, 82, 84, 26, 31, 31, 82, 31, 82, 83, + 31, 31, 31, 31, 82, 34, 51, 31, 31, 31, + 79 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ + +#define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 53: /* "choice_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 59: /* "if_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 65: /* "menu_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 10: + + { zconf_error("unexpected end statement"); ;} + break; + + case 11: + + { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;} + break; + + case 12: + + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name); +;} + break; + + case 13: + + { zconf_error("invalid statement"); ;} + break; + + case 28: + + { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;} + break; + + case 29: + + { zconf_error("invalid option"); ;} + break; + + case 30: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 31: + + { + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 32: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 33: + + { + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 41: + + { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); +;} + break; + + case 42: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 43: + + { + menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr)); + if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[(1) - (4)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (4)].id)->stype); +;} + break; + + case 44: + + { + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 45: + + { + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr)); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 48: + + { + const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, (yyvsp[(3) - (3)].string)); + else + zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string)); + free((yyvsp[(2) - (3)].string)); +;} + break; + + case 49: + + { (yyval.string) = NULL; ;} + break; + + case 50: + + { (yyval.string) = (yyvsp[(2) - (2)].string); ;} + break; + + case 51: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 52: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 53: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 61: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 62: + + { + if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); + } else + YYERROR; +;} + break; + + case 63: + + { + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 64: + + { + if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +;} + break; + + case 67: + + { + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep((yyvsp[(2) - (3)].expr)); + (yyval.menu) = menu_add_menu(); +;} + break; + + case 68: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 74: + + { + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); +;} + break; + + case 75: + + { + menu_add_entry(NULL); + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 76: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 77: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 83: + + { + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); + zconf_nextfile((yyvsp[(2) - (3)].string)); +;} + break; + + case 84: + + { + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 85: + + { + menu_end_entry(); +;} + break; + + case 86: + + { + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +;} + break; + + case 87: + + { + current_entry->help = (yyvsp[(2) - (2)].string); +;} + break; + + case 92: + + { + menu_add_dep((yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 96: + + { + menu_add_visibility((yyvsp[(2) - (2)].expr)); +;} + break; + + case 98: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr)); +;} + break; + + case 101: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 102: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 103: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 106: + + { (yyval.expr) = NULL; ;} + break; + + case 107: + + { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} + break; + + case 108: + + { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;} + break; + + case 109: + + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 110: + + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 111: + + { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} + break; + + case 112: + + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;} + break; + + case 113: + + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 114: + + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 115: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 116: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 117: + + { (yyval.string) = NULL; ;} + break; + + + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + _menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); + + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + + rootmenu.prompt->text = _(rootmenu.prompt->text); + rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +static const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; + } + return ""; +} + +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "zconf.lex.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" + diff -Nru seabios-1.7.1/scripts/kconfig/zconf.y seabios-1.7.4/scripts/kconfig/zconf.y --- seabios-1.7.1/scripts/kconfig/zconf.y 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/kconfig/zconf.y 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,740 @@ +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + +%} +%expect 30 + +%union +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + const struct kconf_id *id; +} + +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP +%token T_HELPTEXT +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_OPTIONAL +%token T_PROMPT +%token T_TYPE +%token T_DEFAULT +%token T_SELECT +%token T_RANGE +%token T_VISIBLE +%token T_OPTION +%token T_ON +%token T_WORD +%token T_WORD_QUOTE +%token T_UNEQUAL +%token T_CLOSE_PAREN +%token T_OPEN_PAREN +%token T_EOL + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%nonassoc T_NOT + +%type prompt +%type symbol +%type expr +%type if_expr +%type end +%type option_name +%type if_entry menu_entry choice_entry +%type symbol_option_arg word_opt + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry + +%{ +/* Include zconf.hash.c here so it can see the token constants. */ +#include "zconf.hash.c" +%} + +%% +input: nl start | start; + +start: mainmenu_stmt stmt_list | stmt_list; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list end { zconf_error("unexpected end statement"); } + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list option_name error T_EOL +{ + zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); +} + | stmt_list error T_EOL { zconf_error("invalid statement"); } +; + +option_name: + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE +; + +common_stmt: + T_EOL + | if_stmt + | comment_stmt + | config_stmt + | menuconfig_stmt + | source_stmt +; + +option_error: + T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } + | error T_EOL { zconf_error("invalid option"); } +; + + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +config_stmt: config_entry_start config_option_list +{ + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: + /* empty */ + | config_option_list config_option + | config_option_list symbol_option + | config_option_list depends + | config_option_list help + | config_option_list option_error + | config_option_list T_EOL +; + +config_option: T_TYPE prompt_stmt_opt T_EOL +{ + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEFAULT expr if_expr T_EOL +{ + menu_add_expr(P_DEFAULT, $2, $3); + if ($1->stype != S_UNKNOWN) + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_SELECT T_WORD if_expr T_EOL +{ + menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +symbol_option: T_OPTION symbol_option_list T_EOL +; + +symbol_option_list: + /* empty */ + | symbol_option_list T_WORD symbol_option_arg +{ + const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, $3); + else + zconfprint("warning: ignoring unknown option %s", $2); + free($2); +}; + +symbol_option_arg: + /* empty */ { $$ = NULL; } + | T_EQUAL prompt { $$ = $2; } +; + +/* choice entry */ + +choice: T_CHOICE word_opt T_EOL +{ + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ + $$ = menu_add_menu(); +}; + +choice_end: end +{ + if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +}; + +choice_stmt: choice_entry choice_block choice_end +; + +choice_option_list: + /* empty */ + | choice_option_list choice_option + | choice_option_list depends + | choice_option_list help + | choice_option_list T_EOL + | choice_option_list option_error +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_TYPE prompt_stmt_opt T_EOL +{ + if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); + } else + YYERROR; +}; + +choice_option: T_OPTIONAL T_EOL +{ + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT T_WORD if_expr T_EOL +{ + if ($1->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +}; + +choice_block: + /* empty */ + | choice_block common_stmt +; + +/* if entry */ + +if_entry: T_IF expr nl +{ + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep($2); + $$ = menu_add_menu(); +}; + +if_end: end +{ + if (zconf_endtoken($1, T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +}; + +if_stmt: if_entry if_block if_end +; + +if_block: + /* empty */ + | if_block common_stmt + | if_block menu_stmt + | if_block choice_stmt +; + +/* mainmenu entry */ + +mainmenu_stmt: T_MAINMENU prompt nl +{ + menu_add_prompt(P_MENU, $2, NULL); +}; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_MENU, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu visibility_list depends_list +{ + $$ = menu_add_menu(); +}; + +menu_end: end +{ + if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +}; + +menu_stmt: menu_entry menu_block menu_end +; + +menu_block: + /* empty */ + | menu_block common_stmt + | menu_block menu_stmt + | menu_block choice_stmt +; + +source_stmt: T_SOURCE prompt T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); + zconf_nextfile($2); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment depends_list +{ + menu_end_entry(); +}; + +/* help option */ + +help_start: T_HELP T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +}; + +help: help_start T_HELPTEXT +{ + current_entry->help = $2; +}; + +/* depends option */ + +depends_list: + /* empty */ + | depends_list depends + | depends_list T_EOL + | depends_list option_error +; + +depends: T_DEPENDS T_ON expr T_EOL +{ + menu_add_dep($3); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +}; + +/* visibility option */ + +visibility_list: + /* empty */ + | visibility_list visible + | visibility_list T_EOL +; + +visible: T_VISIBLE if_expr +{ + menu_add_visibility($2); +}; + +/* prompt statement */ + +prompt_stmt_opt: + /* empty */ + | prompt if_expr +{ + menu_add_prompt(P_PROMPT, $1, $2); +}; + +prompt: T_WORD + | T_WORD_QUOTE +; + +end: T_ENDMENU T_EOL { $$ = $1; } + | T_ENDCHOICE T_EOL { $$ = $1; } + | T_ENDIF T_EOL { $$ = $1; } +; + +nl: + T_EOL + | nl T_EOL +; + +if_expr: /* empty */ { $$ = NULL; } + | T_IF expr { $$ = $2; } +; + +expr: symbol { $$ = expr_alloc_symbol($1); } + | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } + | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } + | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } + | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } + | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } + | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } +; + +symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } +; + +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + +%% + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + _menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); + + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + + rootmenu.prompt->text = _(rootmenu.prompt->text); + rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +static const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; + } + return ""; +} + +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "zconf.lex.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" diff -Nru seabios-1.7.1/scripts/layoutrom.py seabios-1.7.4/scripts/layoutrom.py --- seabios-1.7.1/scripts/layoutrom.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/layoutrom.py 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,708 @@ +#!/usr/bin/env python +# Script to analyze code and arrange ld sections. +# +# Copyright (C) 2008-2010 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +import sys + +# LD script headers/trailers +COMMONHEADER = """ +/* DO NOT EDIT! This is an autogenerated file. See tools/layoutrom.py. */ +OUTPUT_FORMAT("elf32-i386") +OUTPUT_ARCH("i386") +SECTIONS +{ +""" +COMMONTRAILER = """ + + /* Discard regular data sections to force a link error if + * code attempts to access data not marked with VAR16 (or other + * appropriate macro) + */ + /DISCARD/ : { + *(.text*) *(.data*) *(.bss*) *(.rodata*) + *(COMMON) *(.discard*) *(.eh_frame) *(.note*) + } +} +""" + + +###################################################################### +# Determine section locations +###################################################################### + +# Align 'pos' to 'alignbytes' offset +def alignpos(pos, alignbytes): + mask = alignbytes - 1 + return (pos + mask) & ~mask + +# Determine the final addresses for a list of sections that end at an +# address. +def setSectionsStart(sections, endaddr, minalign=1, segoffset=0): + totspace = 0 + for section in sections: + if section.align > minalign: + minalign = section.align + totspace = alignpos(totspace, section.align) + section.size + startaddr = (endaddr - totspace) / minalign * minalign + curaddr = startaddr + for section in sections: + curaddr = alignpos(curaddr, section.align) + section.finalloc = curaddr + section.finalsegloc = curaddr - segoffset + curaddr += section.size + return startaddr, minalign + +# The 16bit code can't exceed 64K of space. +BUILD_BIOS_ADDR = 0xf0000 +BUILD_BIOS_SIZE = 0x10000 +BUILD_ROM_START = 0xc0000 +BUILD_LOWRAM_END = 0xa0000 +# Space to reserve in f-segment for dynamic allocations +BUILD_MIN_BIOSTABLE = 2048 + +# Layout the 16bit code. This ensures sections with fixed offset +# requirements are placed in the correct location. It also places the +# 16bit code as high as possible in the f-segment. +def fitSections(sections, fillsections): + # fixedsections = [(addr, section), ...] + fixedsections = [] + for section in sections: + if section.name.startswith('.fixedaddr.'): + addr = int(section.name[11:], 16) + section.finalloc = addr + BUILD_BIOS_ADDR + section.finalsegloc = addr + fixedsections.append((addr, section)) + if section.align != 1: + print "Error: Fixed section %s has non-zero alignment (%d)" % ( + section.name, section.align) + sys.exit(1) + fixedsections.sort() + firstfixed = fixedsections[0][0] + + # Find freespace in fixed address area + # fixedAddr = [(freespace, section), ...] + fixedAddr = [] + for i in range(len(fixedsections)): + fixedsectioninfo = fixedsections[i] + addr, section = fixedsectioninfo + if i == len(fixedsections) - 1: + nextaddr = BUILD_BIOS_SIZE + else: + nextaddr = fixedsections[i+1][0] + avail = nextaddr - addr - section.size + fixedAddr.append((avail, section)) + fixedAddr.sort() + + # Attempt to fit other sections into fixed area + canrelocate = [(section.size, section.align, section.name, section) + for section in fillsections] + canrelocate.sort() + canrelocate = [section for size, align, name, section in canrelocate] + totalused = 0 + for freespace, fixedsection in fixedAddr: + addpos = fixedsection.finalsegloc + fixedsection.size + totalused += fixedsection.size + nextfixedaddr = addpos + freespace +# print "Filling section %x uses %d, next=%x, available=%d" % ( +# fixedsection.finalloc, fixedsection.size, nextfixedaddr, freespace) + while 1: + canfit = None + for fitsection in canrelocate: + if addpos + fitsection.size > nextfixedaddr: + # Can't fit and nothing else will fit. + break + fitnextaddr = alignpos(addpos, fitsection.align) + fitsection.size +# print "Test %s - %x vs %x" % ( +# fitsection.name, fitnextaddr, nextfixedaddr) + if fitnextaddr > nextfixedaddr: + # This item can't fit. + continue + canfit = (fitnextaddr, fitsection) + if canfit is None: + break + # Found a section that can fit. + fitnextaddr, fitsection = canfit + canrelocate.remove(fitsection) + fitsection.finalloc = addpos + BUILD_BIOS_ADDR + fitsection.finalsegloc = addpos + addpos = fitnextaddr + totalused += fitsection.size +# print " Adding %s (size %d align %d) pos=%x avail=%d" % ( +# fitsection[2], fitsection[0], fitsection[1] +# , fitnextaddr, nextfixedaddr - fitnextaddr) + + # Report stats + total = BUILD_BIOS_SIZE-firstfixed + slack = total - totalused + print ("Fixed space: 0x%x-0x%x total: %d slack: %d" + " Percent slack: %.1f%%" % ( + firstfixed, BUILD_BIOS_SIZE, total, slack, + (float(slack) / total) * 100.0)) + + return firstfixed + BUILD_BIOS_ADDR + +# Return the subset of sections with a given category +def getSectionsCategory(sections, category): + return [section for section in sections if section.category == category] + +# Return the subset of sections with a given name prefix +def getSectionsPrefix(sections, prefix): + return [section for section in sections + if section.name.startswith(prefix)] + +# The sections (and associated information) to be placed in output rom +class LayoutInfo: + genreloc = None + sections16 = sec16_start = sec16_align = None + sections32seg = sec32seg_start = sec32seg_align = None + sections32flat = sec32flat_start = sec32flat_align = None + sections32init = sec32init_start = sec32init_align = None + sections32low = sec32low_start = sec32low_align = None + sections32fseg = sec32fseg_start = sec32fseg_align = None + zonefseg_start = zonefseg_end = None + final_readonly_start = None + zonelow_base = final_sec32low_start = None + exportsyms = varlowsyms = None + +# Determine final memory addresses for sections +def doLayout(sections, config, genreloc): + li = LayoutInfo() + li.genreloc = genreloc + # Determine 16bit positions + li.sections16 = getSectionsCategory(sections, '16') + textsections = getSectionsPrefix(li.sections16, '.text.') + rodatasections = ( + getSectionsPrefix(li.sections16, '.rodata.str1.1') + + getSectionsPrefix(li.sections16, '.rodata.__func__.') + + getSectionsPrefix(li.sections16, '.rodata.__PRETTY_FUNCTION__.')) + datasections = getSectionsPrefix(li.sections16, '.data16.') + fixedsections = getSectionsPrefix(li.sections16, '.fixedaddr.') + + firstfixed = fitSections(fixedsections, textsections) + remsections = [s for s in textsections+rodatasections+datasections + if s.finalloc is None] + li.sec16_start, li.sec16_align = setSectionsStart( + remsections, firstfixed, segoffset=BUILD_BIOS_ADDR) + + # Determine 32seg positions + li.sections32seg = getSectionsCategory(sections, '32seg') + textsections = getSectionsPrefix(li.sections32seg, '.text.') + rodatasections = ( + getSectionsPrefix(li.sections32seg, '.rodata.str1.1') + + getSectionsPrefix(li.sections32seg, '.rodata.__func__.') + + getSectionsPrefix(li.sections32seg, '.rodata.__PRETTY_FUNCTION__.')) + datasections = getSectionsPrefix(li.sections32seg, '.data32seg.') + + li.sec32seg_start, li.sec32seg_align = setSectionsStart( + textsections + rodatasections + datasections, li.sec16_start + , segoffset=BUILD_BIOS_ADDR) + + # Determine "fseg memory" data positions + li.sections32fseg = getSectionsCategory(sections, '32fseg') + + li.sec32fseg_start, li.sec32fseg_align = setSectionsStart( + li.sections32fseg, li.sec32seg_start, 16 + , segoffset=BUILD_BIOS_ADDR) + + # Determine 32flat runtime positions + li.sections32flat = getSectionsCategory(sections, '32flat') + textsections = getSectionsPrefix(li.sections32flat, '.text.') + rodatasections = getSectionsPrefix(li.sections32flat, '.rodata') + datasections = getSectionsPrefix(li.sections32flat, '.data.') + bsssections = getSectionsPrefix(li.sections32flat, '.bss.') + + li.sec32flat_start, li.sec32flat_align = setSectionsStart( + textsections + rodatasections + datasections + bsssections + , li.sec32fseg_start, 16) + + # Determine 32flat init positions + li.sections32init = getSectionsCategory(sections, '32init') + init32_textsections = getSectionsPrefix(li.sections32init, '.text.') + init32_rodatasections = getSectionsPrefix(li.sections32init, '.rodata') + init32_datasections = getSectionsPrefix(li.sections32init, '.data.') + init32_bsssections = getSectionsPrefix(li.sections32init, '.bss.') + + li.sec32init_start, li.sec32init_align = setSectionsStart( + init32_textsections + init32_rodatasections + + init32_datasections + init32_bsssections + , li.sec32flat_start, 16) + + # Determine location of ZoneFSeg memory. + li.zonefseg_end = li.sec32flat_start + if not genreloc: + li.zonefseg_end = li.sec32init_start + li.zonefseg_start = BUILD_BIOS_ADDR + if li.zonefseg_start + BUILD_MIN_BIOSTABLE > li.zonefseg_end: + # Not enough ZoneFSeg space - force a minimum space. + li.zonefseg_end = li.sec32fseg_start + li.zonefseg_start = li.zonefseg_end - BUILD_MIN_BIOSTABLE + li.sec32flat_start, li.sec32flat_align = setSectionsStart( + textsections + rodatasections + datasections + bsssections + , li.zonefseg_start, 16) + li.sec32init_start, li.sec32init_align = setSectionsStart( + init32_textsections + init32_rodatasections + + init32_datasections + init32_bsssections + , li.sec32flat_start, 16) + li.final_readonly_start = min(BUILD_BIOS_ADDR, li.sec32flat_start) + if not genreloc: + li.final_readonly_start = min(BUILD_BIOS_ADDR, li.sec32init_start) + + # Determine "low memory" data positions + li.sections32low = getSectionsCategory(sections, '32low') + sec32low_end = li.sec32init_start + if config.get('CONFIG_MALLOC_UPPERMEMORY'): + final_sec32low_end = li.final_readonly_start + zonelow_base = final_sec32low_end - 64*1024 + li.zonelow_base = max(BUILD_ROM_START, alignpos(zonelow_base, 2*1024)) + else: + final_sec32low_end = BUILD_LOWRAM_END + li.zonelow_base = final_sec32low_end - 64*1024 + relocdelta = final_sec32low_end - sec32low_end + li.sec32low_start, li.sec32low_align = setSectionsStart( + li.sections32low, sec32low_end, 16 + , segoffset=li.zonelow_base - relocdelta) + li.final_sec32low_start = li.sec32low_start + relocdelta + + # Print statistics + size16 = BUILD_BIOS_ADDR + BUILD_BIOS_SIZE - li.sec16_start + size32seg = li.sec16_start - li.sec32seg_start + size32fseg = li.sec32seg_start - li.sec32fseg_start + size32flat = li.sec32fseg_start - li.sec32flat_start + size32init = li.sec32flat_start - li.sec32init_start + sizelow = sec32low_end - li.sec32low_start + print "16bit size: %d" % size16 + print "32bit segmented size: %d" % size32seg + print "32bit flat size: %d" % size32flat + print "32bit flat init size: %d" % size32init + print "Lowmem size: %d" % sizelow + print "f-segment var size: %d" % size32fseg + return li + + +###################################################################### +# Linker script output +###################################################################### + +# Write LD script includes for the given cross references +def outXRefs(sections, useseg=0, exportsyms=[], forcedelta=0): + xrefs = dict([(symbol.name, symbol) for symbol in exportsyms]) + out = "" + for section in sections: + for reloc in section.relocs: + symbol = reloc.symbol + if (symbol.section is not None + and (symbol.section.fileid != section.fileid + or symbol.name != reloc.symbolname)): + xrefs[reloc.symbolname] = symbol + for symbolname, symbol in xrefs.items(): + loc = symbol.section.finalloc + if useseg: + loc = symbol.section.finalsegloc + out += "%s = 0x%x ;\n" % (symbolname, loc + forcedelta + symbol.offset) + return out + +# Write LD script includes for the given sections using relative offsets +def outRelSections(sections, startsym, useseg=0): + sections = [(section.finalloc, section) for section in sections + if section.finalloc is not None] + sections.sort() + out = "" + for addr, section in sections: + loc = section.finalloc + if useseg: + loc = section.finalsegloc + out += ". = ( 0x%x - %s ) ;\n" % (loc, startsym) + if section.name == '.rodata.str1.1': + out += "_rodata = . ;\n" + out += "*(%s)\n" % (section.name,) + return out + +# Build linker script output for a list of relocations. +def strRelocs(outname, outrel, relocs): + relocs.sort() + return (" %s_start = ABSOLUTE(.) ;\n" % (outname,) + + "".join(["LONG(0x%x - %s)\n" % (pos, outrel) + for pos in relocs]) + + " %s_end = ABSOLUTE(.) ;\n" % (outname,)) + +# Find all relocations in the given sections with the given attributes +def getRelocs(sections, type=None, category=None, notcategory=None): + out = [] + for section in sections: + for reloc in section.relocs: + if reloc.symbol.section is None: + continue + destcategory = reloc.symbol.section.category + if ((type is None or reloc.type == type) + and (category is None or destcategory == category) + and (notcategory is None or destcategory != notcategory)): + out.append(section.finalloc + reloc.offset) + return out + +# Return the start address and minimum alignment for a set of sections +def getSectionsStart(sections, defaddr=0): + return min([section.finalloc for section in sections + if section.finalloc is not None] or [defaddr]) + +# Output the linker scripts for all required sections. +def writeLinkerScripts(li, out16, out32seg, out32flat): + # Write 16bit linker script + out = outXRefs(li.sections16, useseg=1) + """ + zonelow_base = 0x%x ; + _zonelow_seg = 0x%x ; + + code16_start = 0x%x ; + .text16 code16_start : { +%s + } +""" % (li.zonelow_base, + li.zonelow_base / 16, + li.sec16_start - BUILD_BIOS_ADDR, + outRelSections(li.sections16, 'code16_start', useseg=1)) + outfile = open(out16, 'wb') + outfile.write(COMMONHEADER + out + COMMONTRAILER) + outfile.close() + + # Write 32seg linker script + out = outXRefs(li.sections32seg, useseg=1) + """ + code32seg_start = 0x%x ; + .text32seg code32seg_start : { +%s + } +""" % (li.sec32seg_start - BUILD_BIOS_ADDR, + outRelSections(li.sections32seg, 'code32seg_start', useseg=1)) + outfile = open(out32seg, 'wb') + outfile.write(COMMONHEADER + out + COMMONTRAILER) + outfile.close() + + # Write 32flat linker script + sections32all = (li.sections32flat + li.sections32init + li.sections32fseg) + sec32all_start = li.sec32low_start + relocstr = "" + if li.genreloc: + # Generate relocations + absrelocs = getRelocs( + li.sections32init, type='R_386_32', category='32init') + relrelocs = getRelocs( + li.sections32init, type='R_386_PC32', notcategory='32init') + initrelocs = getRelocs( + li.sections32flat + li.sections32low + li.sections16 + + li.sections32seg + li.sections32fseg, category='32init') + relocstr = (strRelocs("_reloc_abs", "code32init_start", absrelocs) + + strRelocs("_reloc_rel", "code32init_start", relrelocs) + + strRelocs("_reloc_init", "code32flat_start", initrelocs)) + numrelocs = len(absrelocs + relrelocs + initrelocs) + sec32all_start -= numrelocs * 4 + out = outXRefs(li.sections32low, exportsyms=li.varlowsyms + , forcedelta=li.final_sec32low_start-li.sec32low_start) + out += outXRefs(sections32all, exportsyms=li.exportsyms) + """ + _reloc_min_align = 0x%x ; + zonefseg_start = 0x%x ; + zonefseg_end = 0x%x ; + zonelow_base = 0x%x ; + final_varlow_start = 0x%x ; + final_readonly_start = 0x%x ; + + code32flat_start = 0x%x ; + .text code32flat_start : { +%s + varlow_start = ABSOLUTE(.) ; +%s + varlow_end = ABSOLUTE(.) ; + code32init_start = ABSOLUTE(.) ; +%s + code32init_end = ABSOLUTE(.) ; +%s +%s + . = ( 0x%x - code32flat_start ) ; + *(.text32seg) + . = ( 0x%x - code32flat_start ) ; + *(.text16) + code32flat_end = ABSOLUTE(.) ; + } :text +""" % (li.sec32init_align, + li.zonefseg_start, + li.zonefseg_end, + li.zonelow_base, + li.final_sec32low_start, + li.final_readonly_start, + sec32all_start, + relocstr, + outRelSections(li.sections32low, 'code32flat_start'), + outRelSections(li.sections32init, 'code32flat_start'), + outRelSections(li.sections32flat, 'code32flat_start'), + outRelSections(li.sections32fseg, 'code32flat_start'), + li.sec32seg_start, + li.sec16_start) + out = COMMONHEADER + out + COMMONTRAILER + """ +ENTRY(entry_elf) +PHDRS +{ + text PT_LOAD AT ( code32flat_start ) ; +} +""" + outfile = open(out32flat, 'wb') + outfile.write(out) + outfile.close() + + +###################################################################### +# Detection of init code +###################################################################### + +def markRuntime(section, sections, chain=[]): + if (section is None or not section.keep or section.category is not None + or '.init.' in section.name or section.fileid != '32flat'): + return + if '.data.varinit.' in section.name: + print "ERROR: %s is VARVERIFY32INIT but used from %s" % ( + section.name, chain) + sys.exit(1) + section.category = '32flat' + # Recursively mark all sections this section points to + for reloc in section.relocs: + markRuntime(reloc.symbol.section, sections, chain + [section.name]) + +def findInit(sections): + # Recursively find and mark all "runtime" sections. + for section in sections: + if ('.data.varlow.' in section.name or '.data.varfseg.' in section.name + or '.runtime.' in section.name or '.export.' in section.name): + markRuntime(section, sections) + for section in sections: + if section.category is not None: + continue + if section.fileid == '32flat': + section.category = '32init' + else: + section.category = section.fileid + + +###################################################################### +# Section garbage collection +###################################################################### + +CFUNCPREFIX = [('_cfunc16_', 0), ('_cfunc32seg_', 1), ('_cfunc32flat_', 2)] + +# Find and keep the section associated with a symbol (if available). +def keepsymbol(reloc, infos, pos, isxref): + symbolname = reloc.symbolname + mustbecfunc = 0 + for symprefix, needpos in CFUNCPREFIX: + if symbolname.startswith(symprefix): + if needpos != pos: + return -1 + symbolname = symbolname[len(symprefix):] + mustbecfunc = 1 + break + symbol = infos[pos][1].get(symbolname) + if (symbol is None or symbol.section is None + or symbol.section.name.startswith('.discard.')): + return -1 + isdestcfunc = (symbol.section.name.startswith('.text.') + and not symbol.section.name.startswith('.text.asm.')) + if ((mustbecfunc and not isdestcfunc) + or (not mustbecfunc and isdestcfunc and isxref)): + return -1 + + reloc.symbol = symbol + keepsection(symbol.section, infos, pos) + return 0 + +# Note required section, and recursively set all referenced sections +# as required. +def keepsection(section, infos, pos=0): + if section.keep: + # Already kept - nothing to do. + return + section.keep = 1 + # Keep all sections that this section points to + for reloc in section.relocs: + ret = keepsymbol(reloc, infos, pos, 0) + if not ret: + continue + # Not in primary sections - it may be a cross 16/32 reference + ret = keepsymbol(reloc, infos, (pos+1)%3, 1) + if not ret: + continue + ret = keepsymbol(reloc, infos, (pos+2)%3, 1) + if not ret: + continue + +# Determine which sections are actually referenced and need to be +# placed into the output file. +def gc(info16, info32seg, info32flat): + # infos = ((sections16, symbols16), (sect32seg, sym32seg) + # , (sect32flat, sym32flat)) + infos = (info16, info32seg, info32flat) + # Start by keeping sections that are globally visible. + for section in info16[0]: + if section.name.startswith('.fixedaddr.') or '.export.' in section.name: + keepsection(section, infos) + return [section for section in info16[0]+info32seg[0]+info32flat[0] + if section.keep] + + +###################################################################### +# Startup and input parsing +###################################################################### + +class Section: + name = size = alignment = fileid = relocs = None + finalloc = finalsegloc = category = keep = None +class Reloc: + offset = type = symbolname = symbol = None +class Symbol: + name = offset = section = None + +# Read in output from objdump +def parseObjDump(file, fileid): + # sections = [section, ...] + sections = [] + sectionmap = {} + # symbols[symbolname] = symbol + symbols = {} + + state = None + for line in file.readlines(): + line = line.rstrip() + if line == 'Sections:': + state = 'section' + continue + if line == 'SYMBOL TABLE:': + state = 'symbol' + continue + if line.startswith('RELOCATION RECORDS FOR ['): + sectionname = line[24:-2] + if sectionname.startswith('.debug_'): + # Skip debugging sections (to reduce parsing time) + state = None + continue + state = 'reloc' + relocsection = sectionmap[sectionname] + continue + + if state == 'section': + try: + idx, name, size, vma, lma, fileoff, align = line.split() + if align[:3] != '2**': + continue + section = Section() + section.name = name + section.size = int(size, 16) + section.align = 2**int(align[3:]) + section.fileid = fileid + section.relocs = [] + sections.append(section) + sectionmap[name] = section + except ValueError: + pass + continue + if state == 'symbol': + try: + parts = line[17:].split() + if len(parts) == 3: + sectionname, size, name = parts + elif len(parts) == 4 and parts[2] == '.hidden': + sectionname, size, hidden, name = parts + else: + continue + symbol = Symbol() + symbol.size = int(size, 16) + symbol.offset = int(line[:8], 16) + symbol.name = name + symbol.section = sectionmap.get(sectionname) + symbols[name] = symbol + except ValueError: + pass + continue + if state == 'reloc': + try: + off, type, symbolname = line.split() + reloc = Reloc() + reloc.offset = int(off, 16) + reloc.type = type + reloc.symbolname = symbolname + reloc.symbol = symbols.get(symbolname) + if reloc.symbol is None: + # Some binutils (2.20.1) give section name instead + # of a symbol - create a dummy symbol. + reloc.symbol = symbol = Symbol() + symbol.size = 0 + symbol.offset = 0 + symbol.name = symbolname + symbol.section = sectionmap.get(symbolname) + symbols[symbolname] = symbol + relocsection.relocs.append(reloc) + except ValueError: + pass + return sections, symbols + +# Parser for constants in simple C header files. +def scanconfig(file): + f = open(file, 'rb') + opts = {} + for l in f.readlines(): + parts = l.split() + if len(parts) != 3: + continue + if parts[0] != '#define': + continue + value = parts[2] + if value.isdigit() or (value.startswith('0x') and value[2:].isdigit()): + value = int(value, 0) + opts[parts[1]] = value + return opts + +def main(): + # Get output name + in16, in32seg, in32flat, cfgfile, out16, out32seg, out32flat = sys.argv[1:] + + # Read in the objdump information + infile16 = open(in16, 'rb') + infile32seg = open(in32seg, 'rb') + infile32flat = open(in32flat, 'rb') + + # infoX = (sections, symbols) + info16 = parseObjDump(infile16, '16') + info32seg = parseObjDump(infile32seg, '32seg') + info32flat = parseObjDump(infile32flat, '32flat') + + # Read kconfig config file + config = scanconfig(cfgfile) + + # Figure out which sections to keep. + sections = gc(info16, info32seg, info32flat) + + # Separate 32bit flat into runtime and init parts + findInit(sections) + + # Note "low memory" and "fseg memory" parts + for section in getSectionsPrefix(sections, '.data.varlow.'): + section.category = '32low' + for section in getSectionsPrefix(sections, '.data.varfseg.'): + section.category = '32fseg' + + # Determine the final memory locations of each kept section. + genreloc = '_reloc_abs_start' in info32flat[1] + li = doLayout(sections, config, genreloc) + + # Exported symbols + li.exportsyms = [symbol for symbol in info16[1].values() + if (symbol.section is not None + and '.export.' in symbol.section.name + and symbol.name != symbol.section.name)] + li.varlowsyms = [symbol for symbol in info32flat[1].values() + if (symbol.section is not None + and symbol.section.finalloc is not None + and '.data.varlow.' in symbol.section.name + and symbol.name != symbol.section.name)] + + # Write out linker script files. + writeLinkerScripts(li, out16, out32seg, out32flat) + +if __name__ == '__main__': + main() Binary files /tmp/tmpQX5B3r/1ILzN7giy_/seabios-1.7.1/scripts/layoutrom.pyc and /tmp/tmpQX5B3r/EbHQumljnX/seabios-1.7.4/scripts/layoutrom.pyc differ diff -Nru seabios-1.7.1/scripts/readserial.py seabios-1.7.4/scripts/readserial.py --- seabios-1.7.1/scripts/readserial.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/readserial.py 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# Script that can read from a serial device and show timestamps. +# +# Copyright (C) 2009 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +# Usage: +# tools/readserial.py /dev/ttyUSB0 115200 + +import sys +import time +import select +import optparse + +# Reset time counter after this much idle time. +RESTARTINTERVAL = 60 +# Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data +# bits + 1 stop bit. +BITSPERBYTE = 10 + +def calibrateserialwrite(outfile, byteadjust): + # Build 4000 bytes of dummy data. + data = "0123456789" * 4 + "012345678" + "\n" + data = data * 80 + while 1: + st = time.time() + outfile.write(data) + outfile.flush() + et = time.time() + sys.stdout.write( + "Wrote %d - %.1fus per char (theory states %.1fus)\n" % ( + len(data), (et-st) / len(data) * 1000000, byteadjust * 1000000)) + sys.stdout.flush() + time.sleep(3) + +def calibrateserialread(infile, byteadjust): + starttime = lasttime = 0 + totalchars = 0 + while 1: + select.select([infile], [], []) + d = infile.read(4096) + curtime = time.time() + if curtime - lasttime > 1.0: + if starttime and totalchars: + sys.stdout.write( + "Calibrating on %d bytes - %.1fus per char" + " (theory states %.1fus)\n" % ( + totalchars, + float(lasttime - starttime) * 1000000 / totalchars, + byteadjust * 1000000)) + totalchars = 0 + starttime = curtime + else: + totalchars += len(d) + lasttime = curtime + +def readserial(infile, logfile, byteadjust): + lasttime = 0 + while 1: + # Read data + try: + res = select.select([infile, sys.stdin], [], []) + except KeyboardInterrupt: + sys.stdout.write("\n") + break + if sys.stdin in res[0]: + # Got keyboard input - force reset on next serial input + sys.stdin.read(1) + lasttime = 0 + if len(res[0]) == 1: + continue + d = infile.read(4096) + if not d: + break + datatime = time.time() + + datatime -= len(d) * byteadjust + + # Reset start time if no data for some time + if datatime - lasttime > RESTARTINTERVAL: + starttime = datatime + charcount = 0 + isnewline = 1 + msg = "\n\n======= %s (adjust=%.1fus)\n" % ( + time.asctime(time.localtime(datatime)), byteadjust * 1000000) + sys.stdout.write(msg) + logfile.write(msg) + lasttime = datatime + + # Translate unprintable chars; add timestamps + out = "" + for c in d: + if isnewline: + delta = datatime - starttime - (charcount * byteadjust) + out += "%06.3f: " % delta + isnewline = 0 + oc = ord(c) + charcount += 1 + datatime += byteadjust + if oc == 0x0d: + continue + if oc == 0x00: + out += "<00>\n" + isnewline = 1 + continue + if oc == 0x0a: + out += "\n" + isnewline = 1 + continue + if oc < 0x20 or oc >= 0x7f and oc != 0x09: + out += "<%02x>" % oc + continue + out += c + + sys.stdout.write(out) + sys.stdout.flush() + logfile.write(out) + logfile.flush() + +def main(): + usage = "%prog [options] [ []]" + opts = optparse.OptionParser(usage) + opts.add_option("-f", "--file", + action="store_false", dest="serial", default=True, + help="read from file instead of serialdevice") + opts.add_option("-n", "--no-adjust", + action="store_false", dest="adjustbaud", default=True, + help="don't adjust times by serial rate") + opts.add_option("-c", "--calibrate-read", + action="store_true", dest="calibrate_read", default=False, + help="read from serial port to calibrate it") + opts.add_option("-C", "--calibrate-write", + action="store_true", dest="calibrate_write", default=False, + help="write to serial port to calibrate it") + opts.add_option("-t", "--time", + type="float", dest="time", default=None, + help="time to write one byte on serial port (in us)") + options, args = opts.parse_args() + serialport = 0 + baud = 115200 + if len(args) > 2: + opts.error("Too many arguments") + if len(args) > 0: + serialport = args[0] + if len(args) > 1: + baud = int(args[1]) + byteadjust = float(BITSPERBYTE) / baud + if options.time is not None: + byteadjust = options.time / 1000000.0 + if not options.adjustbaud: + byteadjust = 0.0 + + if options.serial: + # Read from serial port + try: + import serial + except ImportError: + print """ +Unable to find pyserial package ( http://pyserial.sourceforge.net/ ). +On Linux machines try: yum install pyserial +Or: apt-get install python-serial +""" + sys.exit(1) + ser = serial.Serial(serialport, baud, timeout=0) + else: + # Read from a file + ser = open(serialport, 'rb') + import fcntl + import os + fcntl.fcntl(ser, fcntl.F_SETFL + , fcntl.fcntl(ser, fcntl.F_GETFL) | os.O_NONBLOCK) + + if options.calibrate_read: + calibrateserialread(ser, byteadjust) + return + if options.calibrate_write: + calibrateserialwrite(ser, byteadjust) + return + + logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log") + f = open(logname, 'wb') + readserial(ser, f, byteadjust) + +if __name__ == '__main__': + main() diff -Nru seabios-1.7.1/scripts/test-build.sh seabios-1.7.4/scripts/test-build.sh --- seabios-1.7.1/scripts/test-build.sh 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/test-build.sh 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,103 @@ +#!/bin/sh +# Script to test if the build works properly. + +# Test IASL is installed. +$IASL -h > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "The SeaBIOS project requires the 'iasl' package be installed." >&2 + echo "Many Linux distributions have this package." >&2 + echo "Try: sudo yum install iasl" >&2 + echo "Or: sudo apt-get install iasl" >&2 + echo "" >&2 + echo "Please install iasl and retry." >&2 + echo -1 + exit 0 +fi + +mkdir -p ${OUT} +TMPFILE1=${OUT}/tmp_testcompile1.c +TMPFILE1o=${OUT}/tmp_testcompile1.o +TMPFILE1_ld=${OUT}/tmp_testcompile1.lds +TMPFILE2=${OUT}/tmp_testcompile2.c +TMPFILE2o=${OUT}/tmp_testcompile2.o +TMPFILE3o=${OUT}/tmp_testcompile3.o + +# Test if ld's alignment handling is correct. This is a known problem +# with the linker that ships with Ubuntu 11.04. +cat - > $TMPFILE1 < $TMPFILE1_ld < /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Unable to execute the C compiler ($CC)." >&2 + echo "" >&2 + echo "Please install a working compiler and retry." >&2 + echo -1 + exit 0 +fi +$LD -T $TMPFILE1_ld $TMPFILE1o -o $TMPFILE2o > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "The version of LD on this system ($LD) does not properly handle" >&2 + echo "alignments. As a result, this project can not be built." >&2 + echo "" >&2 + echo "The problem may be the result of this LD bug report:" >&2 + echo " http://sourceware.org/bugzilla/show_bug.cgi?id=12726" >&2 + echo "" >&2 + echo "Please update to a working version of binutils and retry." >&2 + echo -1 + exit 0 +fi + +# Test for "-fwhole-program". Older versions of gcc (pre v4.1) don't +# support the whole-program optimization - detect that. +$CC -fwhole-program -S -o /dev/null -xc /dev/null > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo " Working around no -fwhole-program" >&2 + echo 2 + exit 0 +fi + +# Test if "visible" variables and functions are marked global. On +# OpenSuse 10.3 "visible" variables declared with "extern" first +# aren't marked as global in the resulting assembler. On Ubuntu 7.10 +# "visible" functions aren't marked as global in the resulting +# assembler. +cat - > $TMPFILE1 < /dev/null 2>&1 +cat - > $TMPFILE2 < /dev/null 2>&1 +$CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo " Working around non-functional -fwhole-program" >&2 + echo 2 + exit 0 +fi + +echo 0 + +# Also, the Ubuntu 8.04 compiler has a bug causing corruption when the +# "ebp" register is clobberred in an "asm" statement. The code has +# been modified to not clobber "ebp" - no test is available yet. + +rm -f $TMPFILE1 $TMPFILE1o $TMPFILE1_ld $TMPFILE2 $TMPFILE2o $TMPFILE3o diff -Nru seabios-1.7.1/scripts/transdump.py seabios-1.7.4/scripts/transdump.py --- seabios-1.7.1/scripts/transdump.py 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/scripts/transdump.py 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,50 @@ +#!/usr/bin/env python + +# This script is useful for taking the output of memdump() and +# converting it back into binary output. This can be useful, for +# example, when one wants to push that data into other tools like +# objdump or hexdump. +# +# (C) Copyright 2010 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +import sys +import struct + +def unhex(str): + return int(str, 16) + +def parseMem(filehdl): + mem = [] + for line in filehdl: + parts = line.split(':') + if len(parts) < 2: + continue + try: + vaddr = unhex(parts[0]) + parts = parts[1].split() + mem.extend([unhex(v) for v in parts]) + except ValueError: + continue + return mem + +def printUsage(): + sys.stderr.write("Usage:\n %s \n" + % (sys.argv[0],)) + sys.exit(1) + +def main(): + if len(sys.argv) != 2: + printUsage() + filename = sys.argv[1] + if filename == '-': + filehdl = sys.stdin + else: + filehdl = open(filename, 'r') + mem = parseMem(filehdl) + for i in mem: + sys.stdout.write(struct.pack(" +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +# The x86emu code widely used in Linux distributions when running Xorg +# in vesamode is known to have issues with "retl", "leavel", "entryl", +# and some variants of "calll". This code modifies those instructions +# (ret and leave) that are known to be generated by gcc to avoid +# triggering the x86emu bugs. + +# It is also known that the Windows vgabios emulator has issues with +# addressing negative offsets to the %esp register. That has been +# worked around by not using the gcc parameter "-fomit-frame-pointer" +# when compiling. + +import sys + +def main(): + infilename, outfilename = sys.argv[1:] + infile = open(infilename, 'rb') + out = [] + for line in infile: + sline = line.strip() + if sline == 'ret': + out.append('retw $2\n') + elif sline == 'leave': + out.append('movl %ebp, %esp ; popl %ebp\n') + elif sline.startswith('call'): + out.append('pushw %ax ; callw' + sline[4:] + '\n') + else: + out.append(line) + infile.close() + outfile = open(outfilename, 'wb') + outfile.write(''.join(out)) + outfile.close() + +if __name__ == '__main__': + main() diff -Nru seabios-1.7.1/src/acpi.c seabios-1.7.4/src/acpi.c --- seabios-1.7.1/src/acpi.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/acpi.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,842 +0,0 @@ -// Support for generating ACPI tables (on emulators) -// -// Copyright (C) 2008-2010 Kevin O'Connor -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "acpi.h" // struct rsdp_descriptor -#include "util.h" // memcpy -#include "pci.h" // pci_find_init_device -#include "pci_ids.h" // PCI_VENDOR_ID_INTEL -#include "pci_regs.h" // PCI_INTERRUPT_LINE -#include "ioport.h" // inl -#include "paravirt.h" - -/****************************************************/ -/* ACPI tables init */ - -/* Table structure from Linux kernel (the ACPI tables are under the - BSD license) */ - -struct acpi_table_header /* ACPI common table header */ -{ - ACPI_TABLE_HEADER_DEF -} PACKED; - -/* - * ACPI 1.0 Root System Description Table (RSDT) - */ -#define RSDT_SIGNATURE 0x54445352 // RSDT -struct rsdt_descriptor_rev1 -{ - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 table_offset_entry[0]; /* Array of pointers to other */ - /* ACPI tables */ -} PACKED; - -/* - * ACPI 1.0 Firmware ACPI Control Structure (FACS) - */ -#define FACS_SIGNATURE 0x53434146 // FACS -struct facs_descriptor_rev1 -{ - u32 signature; /* ACPI Signature */ - u32 length; /* Length of structure, in bytes */ - u32 hardware_signature; /* Hardware configuration signature */ - u32 firmware_waking_vector; /* ACPI OS waking vector */ - u32 global_lock; /* Global Lock */ - u32 S4bios_f : 1; /* Indicates if S4BIOS support is present */ - u32 reserved1 : 31; /* Must be 0 */ - u8 resverved3 [40]; /* Reserved - must be zero */ -} PACKED; - - -/* - * Differentiated System Description Table (DSDT) - */ -#define DSDT_SIGNATURE 0x54445344 // DSDT - -/* - * MADT values and structures - */ - -/* Values for MADT PCATCompat */ - -#define DUAL_PIC 0 -#define MULTIPLE_APIC 1 - - -/* Master MADT */ - -#define APIC_SIGNATURE 0x43495041 // APIC -struct multiple_apic_table -{ - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 local_apic_address; /* Physical address of local APIC */ -#if 0 - u32 PCATcompat : 1; /* A one indicates system also has dual 8259s */ - u32 reserved1 : 31; -#else - u32 flags; -#endif -} PACKED; - - -/* Values for Type in APIC sub-headers */ - -#define APIC_PROCESSOR 0 -#define APIC_IO 1 -#define APIC_XRUPT_OVERRIDE 2 -#define APIC_NMI 3 -#define APIC_LOCAL_NMI 4 -#define APIC_ADDRESS_OVERRIDE 5 -#define APIC_IO_SAPIC 6 -#define APIC_LOCAL_SAPIC 7 -#define APIC_XRUPT_SOURCE 8 -#define APIC_RESERVED 9 /* 9 and greater are reserved */ - -/* - * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) - */ -#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\ - u8 type; \ - u8 length; - -/* Sub-structures for MADT */ - -struct madt_processor_apic -{ - ACPI_SUB_HEADER_DEF - u8 processor_id; /* ACPI processor id */ - u8 local_apic_id; /* Processor's local APIC id */ -#if 0 - u32 processor_enabled: 1; /* Processor is usable if set */ - u32 reserved2 : 31; /* Reserved, must be zero */ -#else - u32 flags; -#endif -} PACKED; - -struct madt_io_apic -{ - ACPI_SUB_HEADER_DEF - u8 io_apic_id; /* I/O APIC ID */ - u8 reserved; /* Reserved - must be zero */ - u32 address; /* APIC physical address */ - u32 interrupt; /* Global system interrupt where INTI - * lines start */ -} PACKED; - -/* IRQs 5,9,10,11 */ -#define PCI_ISA_IRQ_MASK 0x0e20 - -struct madt_intsrcovr { - ACPI_SUB_HEADER_DEF - u8 bus; - u8 source; - u32 gsi; - u16 flags; -} PACKED; - -struct madt_local_nmi { - ACPI_SUB_HEADER_DEF - u8 processor_id; /* ACPI processor id */ - u16 flags; /* MPS INTI flags */ - u8 lint; /* Local APIC LINT# */ -} PACKED; - - -/* - * ACPI 2.0 Generic Address Space definition. - */ -struct acpi_20_generic_address { - u8 address_space_id; - u8 register_bit_width; - u8 register_bit_offset; - u8 reserved; - u64 address; -} PACKED; - -/* - * HPET Description Table - */ -struct acpi_20_hpet { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 timer_block_id; - struct acpi_20_generic_address addr; - u8 hpet_number; - u16 min_tick; - u8 page_protect; -} PACKED; - -#define HPET_ID 0x000 -#define HPET_PERIOD 0x004 - -/* - * SRAT (NUMA topology description) table - */ - -#define SRAT_PROCESSOR 0 -#define SRAT_MEMORY 1 - -struct system_resource_affinity_table -{ - ACPI_TABLE_HEADER_DEF - u32 reserved1; - u32 reserved2[2]; -} PACKED; - -struct srat_processor_affinity -{ - ACPI_SUB_HEADER_DEF - u8 proximity_lo; - u8 local_apic_id; - u32 flags; - u8 local_sapic_eid; - u8 proximity_hi[3]; - u32 reserved; -} PACKED; - -struct srat_memory_affinity -{ - ACPI_SUB_HEADER_DEF - u8 proximity[4]; - u16 reserved1; - u32 base_addr_low,base_addr_high; - u32 length_low,length_high; - u32 reserved2; - u32 flags; - u32 reserved3[2]; -} PACKED; - -#include "acpi-dsdt.hex" - -static void -build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev) -{ - h->signature = sig; - h->length = cpu_to_le32(len); - h->revision = rev; - memcpy(h->oem_id, CONFIG_APPNAME6, 6); - memcpy(h->oem_table_id, CONFIG_APPNAME4, 4); - memcpy(h->oem_table_id + 4, (void*)&sig, 4); - h->oem_revision = cpu_to_le32(1); - memcpy(h->asl_compiler_id, CONFIG_APPNAME4, 4); - h->asl_compiler_revision = cpu_to_le32(1); - h->checksum -= checksum(h, len); -} - -#define PIIX4_ACPI_ENABLE 0xf1 -#define PIIX4_ACPI_DISABLE 0xf0 -#define PIIX4_GPE0_BLK 0xafe0 -#define PIIX4_GPE0_BLK_LEN 4 - -static void piix4_fadt_init(struct pci_device *pci, void *arg) -{ - struct fadt_descriptor_rev1 *fadt = arg; - fadt->acpi_enable = PIIX4_ACPI_ENABLE; - fadt->acpi_disable = PIIX4_ACPI_DISABLE; - fadt->gpe0_blk = cpu_to_le32(PIIX4_GPE0_BLK); - fadt->gpe0_blk_len = PIIX4_GPE0_BLK_LEN; -} - -static const struct pci_device_id fadt_init_tbl[] = { - /* PIIX4 Power Management device (for ACPI) */ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, - piix4_fadt_init), - - PCI_DEVICE_END -}; - -static void fill_dsdt(struct fadt_descriptor_rev1 *fadt, void *dsdt) -{ - if (fadt->dsdt) { - free((void *)le32_to_cpu(fadt->dsdt)); - } - fadt->dsdt = cpu_to_le32((u32)dsdt); - fadt->checksum -= checksum(fadt, sizeof(*fadt)); - dprintf(1, "ACPI DSDT=%p\n", dsdt); -} - -static void * -build_fadt(struct pci_device *pci) -{ - struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt)); - struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs)); - - if (!fadt || !facs) { - warn_noalloc(); - return NULL; - } - - /* FACS */ - memset(facs, 0, sizeof(*facs)); - facs->signature = FACS_SIGNATURE; - facs->length = cpu_to_le32(sizeof(*facs)); - - /* FADT */ - memset(fadt, 0, sizeof(*fadt)); - fadt->firmware_ctrl = cpu_to_le32((u32)facs); - fadt->dsdt = 0; /* dsdt will be filled later in acpi_bios_init() - by fill_dsdt() */ - fadt->model = 1; - fadt->reserved1 = 0; - int pm_sci_int = pci_config_readb(pci->bdf, PCI_INTERRUPT_LINE); - fadt->sci_int = cpu_to_le16(pm_sci_int); - fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD); - fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE); - fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04); - fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08); - fadt->pm1_evt_len = 4; - fadt->pm1_cnt_len = 2; - fadt->pm_tmr_len = 4; - fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported - fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported - pci_init_device(fadt_init_tbl, pci, fadt); - /* WBINVD + PROC_C1 + SLP_BUTTON + RTC_S4 + USE_PLATFORM_CLOCK */ - fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 7) | - (1 << 15)); - - build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1); - - return fadt; -} - -static void* -build_madt(void) -{ - int madt_size = (sizeof(struct multiple_apic_table) - + sizeof(struct madt_processor_apic) * MaxCountCPUs - + sizeof(struct madt_io_apic) - + sizeof(struct madt_intsrcovr) * 16 - + sizeof(struct madt_local_nmi)); - - struct multiple_apic_table *madt = malloc_high(madt_size); - if (!madt) { - warn_noalloc(); - return NULL; - } - memset(madt, 0, madt_size); - madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR); - madt->flags = cpu_to_le32(1); - struct madt_processor_apic *apic = (void*)&madt[1]; - int i; - for (i=0; itype = APIC_PROCESSOR; - apic->length = sizeof(*apic); - apic->processor_id = i; - apic->local_apic_id = i; - if (apic_id_is_present(apic->local_apic_id)) - apic->flags = cpu_to_le32(1); - else - apic->flags = cpu_to_le32(0); - apic++; - } - struct madt_io_apic *io_apic = (void*)apic; - io_apic->type = APIC_IO; - io_apic->length = sizeof(*io_apic); - io_apic->io_apic_id = BUILD_IOAPIC_ID; - io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR); - io_apic->interrupt = cpu_to_le32(0); - - struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1]; - if (qemu_cfg_irq0_override()) { - memset(intsrcovr, 0, sizeof(*intsrcovr)); - intsrcovr->type = APIC_XRUPT_OVERRIDE; - intsrcovr->length = sizeof(*intsrcovr); - intsrcovr->source = 0; - intsrcovr->gsi = 2; - intsrcovr->flags = 0; /* conforms to bus specifications */ - intsrcovr++; - } - for (i = 1; i < 16; i++) { - if (!(PCI_ISA_IRQ_MASK & (1 << i))) - /* No need for a INT source override structure. */ - continue; - memset(intsrcovr, 0, sizeof(*intsrcovr)); - intsrcovr->type = APIC_XRUPT_OVERRIDE; - intsrcovr->length = sizeof(*intsrcovr); - intsrcovr->source = i; - intsrcovr->gsi = i; - intsrcovr->flags = 0xd; /* active high, level triggered */ - intsrcovr++; - } - - struct madt_local_nmi *local_nmi = (void*)intsrcovr; - local_nmi->type = APIC_LOCAL_NMI; - local_nmi->length = sizeof(*local_nmi); - local_nmi->processor_id = 0xff; /* all processors */ - local_nmi->flags = 0; - local_nmi->lint = 1; /* LINT1 */ - local_nmi++; - - build_header((void*)madt, APIC_SIGNATURE, (void*)local_nmi - (void*)madt, 1); - return madt; -} - -// Encode a hex value -static inline char getHex(u32 val) { - val &= 0x0f; - return (val <= 9) ? ('0' + val) : ('A' + val - 10); -} - -// Encode a length in an SSDT. -static u8 * -encodeLen(u8 *ssdt_ptr, int length, int bytes) -{ - switch (bytes) { - default: - case 4: ssdt_ptr[3] = ((length >> 20) & 0xff); - case 3: ssdt_ptr[2] = ((length >> 12) & 0xff); - case 2: ssdt_ptr[1] = ((length >> 4) & 0xff); - ssdt_ptr[0] = (((bytes-1) & 0x3) << 6) | (length & 0x0f); - break; - case 1: ssdt_ptr[0] = length & 0x3f; - } - return ssdt_ptr + bytes; -} - -#include "ssdt-proc.hex" - -/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */ -#define SD_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2) -#define SD_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4) -#define SD_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start) -#define SD_SIZEOF (*ssdt_proc_end - *ssdt_proc_start) -#define SD_PROC (ssdp_proc_aml + *ssdt_proc_start) - -#define SSDT_SIGNATURE 0x54445353 // SSDT - -static void* -build_ssdt(void) -{ - int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs; - // length = ScopeOp + procs + NTYF method + CPON package - int length = ((1+3+4) - + (acpi_cpus * SD_SIZEOF) - + (1+2+5+(12*acpi_cpus)) - + (6+2+1+(1*acpi_cpus)) - + 17); - u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length); - if (! ssdt) { - warn_noalloc(); - return NULL; - } - u8 *ssdt_ptr = ssdt + sizeof(struct acpi_table_header); - - // build Scope(_SB_) header - *(ssdt_ptr++) = 0x10; // ScopeOp - ssdt_ptr = encodeLen(ssdt_ptr, length-1, 3); - *(ssdt_ptr++) = '_'; - *(ssdt_ptr++) = 'S'; - *(ssdt_ptr++) = 'B'; - *(ssdt_ptr++) = '_'; - - // build Processor object for each processor - int i; - for (i=0; i> 4); - ssdt_ptr[SD_OFFSET_CPUHEX+1] = getHex(i); - ssdt_ptr[SD_OFFSET_CPUID1] = i; - ssdt_ptr[SD_OFFSET_CPUID2] = i; - ssdt_ptr += SD_SIZEOF; - } - - // build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}" - // Arg0 = Processor ID = APIC ID - *(ssdt_ptr++) = 0x14; // MethodOp - ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*acpi_cpus), 2); - *(ssdt_ptr++) = 'N'; - *(ssdt_ptr++) = 'T'; - *(ssdt_ptr++) = 'F'; - *(ssdt_ptr++) = 'Y'; - *(ssdt_ptr++) = 0x02; - for (i=0; i> 4); - *(ssdt_ptr++) = getHex(i); - *(ssdt_ptr++) = 0x69; // Arg1Op - } - - // build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" - *(ssdt_ptr++) = 0x08; // NameOp - *(ssdt_ptr++) = 'C'; - *(ssdt_ptr++) = 'P'; - *(ssdt_ptr++) = 'O'; - *(ssdt_ptr++) = 'N'; - *(ssdt_ptr++) = 0x12; // PackageOp - ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2); - *(ssdt_ptr++) = acpi_cpus; - for (i=0; ip0s = pcimem_start; - bfld->p0e = pcimem_end - 1; - bfld->p0l = pcimem_end - pcimem_start; - bfld->p1s = pcimem64_start; - bfld->p1e = pcimem64_end - 1; - bfld->p1l = pcimem64_end - pcimem64_start; - - // build "OperationRegion(BDAT, SystemMemory, 0x12345678, 0x87654321)" - *(ssdt_ptr++) = 0x5B; // ExtOpPrefix - *(ssdt_ptr++) = 0x80; // OpRegionOp - *(ssdt_ptr++) = 'B'; - *(ssdt_ptr++) = 'D'; - *(ssdt_ptr++) = 'A'; - *(ssdt_ptr++) = 'T'; - *(ssdt_ptr++) = 0x00; // SystemMemory - *(ssdt_ptr++) = 0x0C; // DWordPrefix - *(u32*)ssdt_ptr = (u32)bfld; - ssdt_ptr += 4; - *(ssdt_ptr++) = 0x0C; // DWordPrefix - *(u32*)ssdt_ptr = sizeof(struct bfld); - ssdt_ptr += 4; - - build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1); - - //hexdump(ssdt, ssdt_ptr - ssdt); - - return ssdt; -} - -#include "ssdt-pcihp.hex" - -#define PCI_RMV_BASE 0xae0c - -extern void link_time_assertion(void); - -static void* build_pcihp(void) -{ - char *sys_states; - int sys_state_size; - u32 rmvc_pcrm; - int i; - - u8 *ssdt = malloc_high(sizeof ssdp_pcihp_aml); - if (!ssdt) { - warn_noalloc(); - return NULL; - } - memcpy(ssdt, ssdp_pcihp_aml, sizeof ssdp_pcihp_aml); - - /* Runtime patching of EJ0: to disable hotplug for a slot, - * replace the method name: _EJ0 by EJ0_. */ - if (ARRAY_SIZE(aml_ej0_name) != ARRAY_SIZE(aml_adr_dword)) { - link_time_assertion(); - } - - rmvc_pcrm = inl(PCI_RMV_BASE); - for (i = 0; i < ARRAY_SIZE(aml_ej0_name); ++i) { - /* Slot is in byte 2 in _ADR */ - u8 slot = ssdp_pcihp_aml[aml_adr_dword[i] + 2] & 0x1F; - /* Sanity check */ - if (memcmp(ssdp_pcihp_aml + aml_ej0_name[i], "_EJ0", 4)) { - warn_internalerror(); - free(ssdt); - return NULL; - } - if (!(rmvc_pcrm & (0x1 << slot))) { - memcpy(ssdt + aml_ej0_name[i], "EJ0_", 4); - } - } - - sys_states = romfile_loadfile("etc/system-states", &sys_state_size); - if (!sys_states || sys_state_size != 6) - sys_states = (char[]){128, 0, 0, 129, 128, 128}; - - if (!(sys_states[3] & 128)) - ssdt[acpi_s3_name[0]] = 'X'; - if (!(sys_states[4] & 128)) - ssdt[acpi_s4_name[0]] = 'X'; - else - ssdt[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127; - ((struct acpi_table_header*)ssdt)->checksum = 0; - ((struct acpi_table_header*)ssdt)->checksum -= checksum(ssdt, sizeof(ssdp_pcihp_aml)); - - return ssdt; -} - -#define HPET_SIGNATURE 0x54455048 // HPET -static void* -build_hpet(void) -{ - struct acpi_20_hpet *hpet; - const void *hpet_base = (void *)BUILD_HPET_ADDRESS; - u32 hpet_vendor = readl(hpet_base + HPET_ID) >> 16; - u32 hpet_period = readl(hpet_base + HPET_PERIOD); - - if (hpet_vendor == 0 || hpet_vendor == 0xffff || - hpet_period == 0 || hpet_period > 100000000) - return NULL; - - hpet = malloc_high(sizeof(*hpet)); - if (!hpet) { - warn_noalloc(); - return NULL; - } - - memset(hpet, 0, sizeof(*hpet)); - /* Note timer_block_id value must be kept in sync with value advertised by - * emulated hpet - */ - hpet->timer_block_id = cpu_to_le32(0x8086a201); - hpet->addr.address = cpu_to_le32(BUILD_HPET_ADDRESS); - build_header((void*)hpet, HPET_SIGNATURE, sizeof(*hpet), 1); - - return hpet; -} - -static void -acpi_build_srat_memory(struct srat_memory_affinity *numamem, - u64 base, u64 len, int node, int enabled) -{ - numamem->type = SRAT_MEMORY; - numamem->length = sizeof(*numamem); - memset(numamem->proximity, 0 ,4); - numamem->proximity[0] = node; - numamem->flags = cpu_to_le32(!!enabled); - numamem->base_addr_low = base & 0xFFFFFFFF; - numamem->base_addr_high = base >> 32; - numamem->length_low = len & 0xFFFFFFFF; - numamem->length_high = len >> 32; -} - -#define SRAT_SIGNATURE 0x54415253 // SRAT -static void * -build_srat(void) -{ - int nb_numa_nodes = qemu_cfg_get_numa_nodes(); - - if (nb_numa_nodes == 0) - return NULL; - - u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes)); - if (!numadata) { - warn_noalloc(); - return NULL; - } - - qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes); - - struct system_resource_affinity_table *srat; - int srat_size = sizeof(*srat) + - sizeof(struct srat_processor_affinity) * MaxCountCPUs + - sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2); - - srat = malloc_high(srat_size); - if (!srat) { - warn_noalloc(); - free(numadata); - return NULL; - } - - memset(srat, 0, srat_size); - srat->reserved1=1; - struct srat_processor_affinity *core = (void*)(srat + 1); - int i; - u64 curnode; - - for (i = 0; i < MaxCountCPUs; ++i) { - core->type = SRAT_PROCESSOR; - core->length = sizeof(*core); - core->local_apic_id = i; - curnode = *numadata++; - core->proximity_lo = curnode; - memset(core->proximity_hi, 0, 3); - core->local_sapic_eid = 0; - if (apic_id_is_present(i)) - core->flags = cpu_to_le32(1); - else - core->flags = cpu_to_le32(0); - core++; - } - - - /* the memory map is a bit tricky, it contains at least one hole - * from 640k-1M and possibly another one from 3.5G-4G. - */ - struct srat_memory_affinity *numamem = (void*)core; - int slots = 0; - u64 mem_len, mem_base, next_base = 0; - - acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1); - next_base = 1024 * 1024; - numamem++; - slots++; - for (i = 1; i < nb_numa_nodes + 1; ++i) { - mem_base = next_base; - mem_len = *numadata++; - if (i == 1) - mem_len -= 1024 * 1024; - next_base = mem_base + mem_len; - - /* Cut out the PCI hole */ - if (mem_base <= RamSize && next_base > RamSize) { - mem_len -= next_base - RamSize; - if (mem_len > 0) { - acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); - numamem++; - slots++; - } - mem_base = 1ULL << 32; - mem_len = next_base - RamSize; - next_base += (1ULL << 32) - RamSize; - } - acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); - numamem++; - slots++; - } - for (; slots < nb_numa_nodes + 2; slots++) { - acpi_build_srat_memory(numamem, 0, 0, 0, 0); - numamem++; - } - - build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1); - - free(numadata); - return srat; -} - -static const struct pci_device_id acpi_find_tbl[] = { - /* PIIX4 Power Management device. */ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL), - - PCI_DEVICE_END, -}; - -struct rsdp_descriptor *RsdpAddr; - -#define MAX_ACPI_TABLES 20 -void -acpi_bios_init(void) -{ - if (! CONFIG_ACPI) - return; - - dprintf(3, "init ACPI tables\n"); - - // This code is hardcoded for PIIX4 Power Management device. - struct pci_device *pci = pci_find_init_device(acpi_find_tbl, NULL); - if (!pci) - // Device not found - return; - - // Build ACPI tables - u32 tables[MAX_ACPI_TABLES], tbl_idx = 0; - -#define ACPI_INIT_TABLE(X) \ - do { \ - tables[tbl_idx] = (u32)(X); \ - if (tables[tbl_idx]) \ - tbl_idx++; \ - } while(0) - - struct fadt_descriptor_rev1 *fadt = build_fadt(pci); - ACPI_INIT_TABLE(fadt); - ACPI_INIT_TABLE(build_ssdt()); - ACPI_INIT_TABLE(build_madt()); - ACPI_INIT_TABLE(build_hpet()); - ACPI_INIT_TABLE(build_srat()); - ACPI_INIT_TABLE(build_pcihp()); - - u16 i, external_tables = qemu_cfg_acpi_additional_tables(); - - for (i = 0; i < external_tables; i++) { - u16 len = qemu_cfg_next_acpi_table_len(); - void *addr = malloc_high(len); - if (!addr) { - warn_noalloc(); - continue; - } - struct acpi_table_header *header = - qemu_cfg_next_acpi_table_load(addr, len); - if (header->signature == DSDT_SIGNATURE) { - if (fadt) { - fill_dsdt(fadt, addr); - } - } else { - ACPI_INIT_TABLE(header); - } - if (tbl_idx == MAX_ACPI_TABLES) { - warn_noalloc(); - break; - } - } - if (fadt && !fadt->dsdt) { - /* default DSDT */ - void *dsdt = malloc_high(sizeof(AmlCode)); - if (!dsdt) { - warn_noalloc(); - return; - } - memcpy(dsdt, AmlCode, sizeof(AmlCode)); - fill_dsdt(fadt, dsdt); - } - - // Build final rsdt table - struct rsdt_descriptor_rev1 *rsdt; - size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx; - rsdt = malloc_high(rsdt_len); - if (!rsdt) { - warn_noalloc(); - return; - } - memset(rsdt, 0, rsdt_len); - memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx); - build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1); - - // Build rsdp pointer table - struct rsdp_descriptor *rsdp = malloc_fseg(sizeof(*rsdp)); - if (!rsdp) { - warn_noalloc(); - return; - } - memset(rsdp, 0, sizeof(*rsdp)); - rsdp->signature = RSDP_SIGNATURE; - memcpy(rsdp->oem_id, CONFIG_APPNAME6, 6); - rsdp->rsdt_physical_address = cpu_to_le32((u32)rsdt); - rsdp->checksum -= checksum(rsdp, 20); - RsdpAddr = rsdp; - dprintf(1, "ACPI tables: RSDP=%p RSDT=%p\n", rsdp, rsdt); -} - -u32 -find_resume_vector(void) -{ - dprintf(4, "rsdp=%p\n", RsdpAddr); - if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE) - return 0; - struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address; - dprintf(4, "rsdt=%p\n", rsdt); - if (!rsdt || rsdt->signature != RSDT_SIGNATURE) - return 0; - void *end = (void*)rsdt + rsdt->length; - int i; - for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) { - struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i]; - if (!fadt || fadt->signature != FACP_SIGNATURE) - continue; - dprintf(4, "fadt=%p\n", fadt); - struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl; - dprintf(4, "facs=%p\n", facs); - if (! facs || facs->signature != FACS_SIGNATURE) - return 0; - // Found it. - dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector); - return facs->firmware_waking_vector; - } - return 0; -} diff -Nru seabios-1.7.1/src/acpi-dsdt.dsl seabios-1.7.4/src/acpi-dsdt.dsl --- seabios-1.7.1/src/acpi-dsdt.dsl 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/acpi-dsdt.dsl 1970-01-01 00:00:00.000000000 +0000 @@ -1,804 +0,0 @@ -/* - * Bochs/QEMU ACPI DSDT ASL definition - * - * Copyright (c) 2006 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. - * - * 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 - */ - -ACPI_EXTRACT_ALL_CODE AmlCode - -DefinitionBlock ( - "acpi-dsdt.aml", // Output Filename - "DSDT", // Signature - 0x01, // DSDT Compliance Revision - "BXPC", // OEMID - "BXDSDT", // TABLE ID - 0x1 // OEM Revision - ) -{ - - -/**************************************************************** - * Debugging - ****************************************************************/ - - Scope (\) - { - /* Debug Output */ - OperationRegion (DBG, SystemIO, 0x0402, 0x01) - Field (DBG, ByteAcc, NoLock, Preserve) - { - DBGB, 8, - } - - /* Debug method - use this method to send output to the QEMU - * BIOS debug port. This method handles strings, integers, - * and buffers. For example: DBUG("abc") DBUG(0x123) */ - Method(DBUG, 1) { - ToHexString(Arg0, Local0) - ToBuffer(Local0, Local0) - Subtract(SizeOf(Local0), 1, Local1) - Store(Zero, Local2) - While (LLess(Local2, Local1)) { - Store(DerefOf(Index(Local0, Local2)), DBGB) - Increment(Local2) - } - Store(0x0A, DBGB) - } - } - - -/**************************************************************** - * PCI Bus definition - ****************************************************************/ - - Scope(\_SB) { - Device(PCI0) { - Name (_HID, EisaId ("PNP0A03")) - Name (_ADR, 0x00) - Name (_UID, 1) - Name(_PRT, Package() { - /* PCI IRQ routing table, example from ACPI 2.0a specification, - section 6.2.8.1 */ - /* Note: we provide the same info as the PCI routing - table of the Bochs BIOS */ -#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \ - Package() { nr##ffff, 0, lnk0, 0 }, \ - Package() { nr##ffff, 1, lnk1, 0 }, \ - Package() { nr##ffff, 2, lnk2, 0 }, \ - Package() { nr##ffff, 3, lnk3, 0 } - -#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC) -#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD) -#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA) -#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB) - prt_slot0(0x0000), - /* Device 1 is power mgmt device, and can only use irq 9 */ - prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD), - prt_slot2(0x0002), - prt_slot3(0x0003), - prt_slot0(0x0004), - prt_slot1(0x0005), - prt_slot2(0x0006), - prt_slot3(0x0007), - prt_slot0(0x0008), - prt_slot1(0x0009), - prt_slot2(0x000a), - prt_slot3(0x000b), - prt_slot0(0x000c), - prt_slot1(0x000d), - prt_slot2(0x000e), - prt_slot3(0x000f), - prt_slot0(0x0010), - prt_slot1(0x0011), - prt_slot2(0x0012), - prt_slot3(0x0013), - prt_slot0(0x0014), - prt_slot1(0x0015), - prt_slot2(0x0016), - prt_slot3(0x0017), - prt_slot0(0x0018), - prt_slot1(0x0019), - prt_slot2(0x001a), - prt_slot3(0x001b), - prt_slot0(0x001c), - prt_slot1(0x001d), - prt_slot2(0x001e), - prt_slot3(0x001f), - }) - - OperationRegion(PCST, SystemIO, 0xae00, 0x08) - Field (PCST, DWordAcc, NoLock, WriteAsZeros) - { - PCIU, 32, - PCID, 32, - } - - OperationRegion(SEJ, SystemIO, 0xae08, 0x04) - Field (SEJ, DWordAcc, NoLock, WriteAsZeros) - { - B0EJ, 32, - } - - Name (CRES, ResourceTemplate () - { - WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, - 0x0000, // Address Space Granularity - 0x0000, // Address Range Minimum - 0x00FF, // Address Range Maximum - 0x0000, // Address Translation Offset - 0x0100, // Address Length - ,, ) - IO (Decode16, - 0x0CF8, // Address Range Minimum - 0x0CF8, // Address Range Maximum - 0x01, // Address Alignment - 0x08, // Address Length - ) - WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, - 0x0000, // Address Space Granularity - 0x0000, // Address Range Minimum - 0x0CF7, // Address Range Maximum - 0x0000, // Address Translation Offset - 0x0CF8, // Address Length - ,, , TypeStatic) - WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, - 0x0000, // Address Space Granularity - 0x0D00, // Address Range Minimum - 0xFFFF, // Address Range Maximum - 0x0000, // Address Translation Offset - 0xF300, // Address Length - ,, , TypeStatic) - DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, - 0x00000000, // Address Space Granularity - 0x000A0000, // Address Range Minimum - 0x000BFFFF, // Address Range Maximum - 0x00000000, // Address Translation Offset - 0x00020000, // Address Length - ,, , AddressRangeMemory, TypeStatic) - DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, - 0x00000000, // Address Space Granularity - 0xE0000000, // Address Range Minimum - 0xFEBFFFFF, // Address Range Maximum - 0x00000000, // Address Translation Offset - 0x1EC00000, // Address Length - ,, PW32, AddressRangeMemory, TypeStatic) - }) - Name (CR64, ResourceTemplate () - { - QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, - 0x00000000, // Address Space Granularity - 0x8000000000, // Address Range Minimum - 0xFFFFFFFFFF, // Address Range Maximum - 0x00000000, // Address Translation Offset - 0x8000000000, // Address Length - ,, PW64, AddressRangeMemory, TypeStatic) - }) - Method (_CRS, 0) - { - /* see see acpi.h, struct bfld */ - External (BDAT, OpRegionObj) - Field(BDAT, QWordAcc, NoLock, Preserve) { - P0S, 64, - P0E, 64, - P0L, 64, - P1S, 64, - P1E, 64, - P1L, 64, - } - Field(BDAT, DWordAcc, NoLock, Preserve) { - P0SL, 32, - P0SH, 32, - P0EL, 32, - P0EH, 32, - P0LL, 32, - P0LH, 32, - P1SL, 32, - P1SH, 32, - P1EL, 32, - P1EH, 32, - P1LL, 32, - P1LH, 32, - } - - /* fixup 32bit pci io window */ - CreateDWordField (CRES,\_SB.PCI0.PW32._MIN, PS32) - CreateDWordField (CRES,\_SB.PCI0.PW32._MAX, PE32) - CreateDWordField (CRES,\_SB.PCI0.PW32._LEN, PL32) - Store (P0SL, PS32) - Store (P0EL, PE32) - Store (P0LL, PL32) - - If (LAnd(LEqual(P1SL, 0x00), LEqual(P1SH, 0x00))) { - Return (CRES) - } Else { - /* fixup 64bit pci io window */ - CreateQWordField (CR64,\_SB.PCI0.PW64._MIN, PS64) - CreateQWordField (CR64,\_SB.PCI0.PW64._MAX, PE64) - CreateQWordField (CR64,\_SB.PCI0.PW64._LEN, PL64) - Store (P1S, PS64) - Store (P1E, PE64) - Store (P1L, PL64) - /* add window and return result */ - ConcatenateResTemplate (CRES, CR64, Local0) - Return (Local0) - } - } - } - } - - -/**************************************************************** - * HPET - ****************************************************************/ - - Scope(\_SB) { - Device(HPET) { - Name(_HID, EISAID("PNP0103")) - Name(_UID, 0) - OperationRegion(HPTM, SystemMemory , 0xFED00000, 0x400) - Field(HPTM, DWordAcc, Lock, Preserve) { - VEND, 32, - PRD, 32, - } - Method (_STA, 0, NotSerialized) { - Store (VEND, Local0) - Store (PRD, Local1) - ShiftRight(Local0, 16, Local0) - If (LOr (LEqual(Local0, 0), LEqual(Local0, 0xffff))) { - Return (0x0) - } - If (LOr (LEqual(Local1, 0), LGreater(Local1, 100000000))) { - Return (0x0) - } - Return (0x0F) - } - Name(_CRS, ResourceTemplate() { - DWordMemory( - ResourceConsumer, PosDecode, MinFixed, MaxFixed, - NonCacheable, ReadWrite, - 0x00000000, - 0xFED00000, - 0xFED003FF, - 0x00000000, - 0x00000400 /* 1K memory: FED00000 - FED003FF */ - ) - }) - } - } - - -/**************************************************************** - * VGA - ****************************************************************/ - - Scope(\_SB.PCI0) { - Device (VGA) { - Name (_ADR, 0x00020000) - OperationRegion(PCIC, PCI_Config, Zero, 0x4) - Field(PCIC, DWordAcc, NoLock, Preserve) { - VEND, 32 - } - Method (_S1D, 0, NotSerialized) - { - Return (0x00) - } - Method (_S2D, 0, NotSerialized) - { - Return (0x00) - } - Method (_S3D, 0, NotSerialized) - { - If (LEqual(VEND, 0x1001b36)) { - Return (0x03) // QXL - } Else { - Return (0x00) - } - } - } - } - - -/**************************************************************** - * PIIX3 ISA bridge - ****************************************************************/ - - Scope(\_SB.PCI0) { - Device (ISA) { - Name (_ADR, 0x00010000) - - /* PIIX PCI to ISA irq remapping */ - OperationRegion (P40C, PCI_Config, 0x60, 0x04) - } - } - - -/**************************************************************** - * SuperIO devices (kbd, mouse, etc.) - ****************************************************************/ - - Scope(\_SB.PCI0.ISA) { - /* Real-time clock */ - Device (RTC) - { - Name (_HID, EisaId ("PNP0B00")) - Name (_CRS, ResourceTemplate () - { - IO (Decode16, 0x0070, 0x0070, 0x10, 0x02) - IRQNoFlags () {8} - IO (Decode16, 0x0072, 0x0072, 0x02, 0x06) - }) - } - - /* Keyboard seems to be important for WinXP install */ - Device (KBD) - { - Name (_HID, EisaId ("PNP0303")) - Method (_STA, 0, NotSerialized) - { - Return (0x0f) - } - - Method (_CRS, 0, NotSerialized) - { - Name (TMP, ResourceTemplate () - { - IO (Decode16, - 0x0060, // Address Range Minimum - 0x0060, // Address Range Maximum - 0x01, // Address Alignment - 0x01, // Address Length - ) - IO (Decode16, - 0x0064, // Address Range Minimum - 0x0064, // Address Range Maximum - 0x01, // Address Alignment - 0x01, // Address Length - ) - IRQNoFlags () - {1} - }) - Return (TMP) - } - } - - /* PS/2 mouse */ - Device (MOU) - { - Name (_HID, EisaId ("PNP0F13")) - Method (_STA, 0, NotSerialized) - { - Return (0x0f) - } - - Method (_CRS, 0, NotSerialized) - { - Name (TMP, ResourceTemplate () - { - IRQNoFlags () {12} - }) - Return (TMP) - } - } - - /* PS/2 floppy controller */ - Device (FDC0) - { - Name (_HID, EisaId ("PNP0700")) - Method (_STA, 0, NotSerialized) - { - Return (0x0F) - } - Method (_CRS, 0, NotSerialized) - { - Name (BUF0, ResourceTemplate () - { - IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04) - IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01) - IRQNoFlags () {6} - DMA (Compatibility, NotBusMaster, Transfer8) {2} - }) - Return (BUF0) - } - } - - /* Parallel port */ - Device (LPT) - { - Name (_HID, EisaId ("PNP0400")) - Method (_STA, 0, NotSerialized) - { - Store (\_SB.PCI0.PX13.DRSA, Local0) - And (Local0, 0x80000000, Local0) - If (LEqual (Local0, 0)) - { - Return (0x00) - } - Else - { - Return (0x0F) - } - } - Method (_CRS, 0, NotSerialized) - { - Name (BUF0, ResourceTemplate () - { - IO (Decode16, 0x0378, 0x0378, 0x08, 0x08) - IRQNoFlags () {7} - }) - Return (BUF0) - } - } - - /* Serial Ports */ - Device (COM1) - { - Name (_HID, EisaId ("PNP0501")) - Name (_UID, 0x01) - Method (_STA, 0, NotSerialized) - { - Store (\_SB.PCI0.PX13.DRSC, Local0) - And (Local0, 0x08000000, Local0) - If (LEqual (Local0, 0)) - { - Return (0x00) - } - Else - { - Return (0x0F) - } - } - Method (_CRS, 0, NotSerialized) - { - Name (BUF0, ResourceTemplate () - { - IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08) - IRQNoFlags () {4} - }) - Return (BUF0) - } - } - - Device (COM2) - { - Name (_HID, EisaId ("PNP0501")) - Name (_UID, 0x02) - Method (_STA, 0, NotSerialized) - { - Store (\_SB.PCI0.PX13.DRSC, Local0) - And (Local0, 0x80000000, Local0) - If (LEqual (Local0, 0)) - { - Return (0x00) - } - Else - { - Return (0x0F) - } - } - Method (_CRS, 0, NotSerialized) - { - Name (BUF0, ResourceTemplate () - { - IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08) - IRQNoFlags () {3} - }) - Return (BUF0) - } - } - } - - -/**************************************************************** - * PIIX4 PM - ****************************************************************/ - - Scope(\_SB.PCI0) { - Device (PX13) { - Name (_ADR, 0x00010003) - - OperationRegion (P13C, PCI_Config, 0x5c, 0x24) - Field (P13C, DWordAcc, NoLock, Preserve) - { - DRSA, 32, - DRSB, 32, - DRSC, 32, - DRSE, 32, - DRSF, 32, - DRSG, 32, - DRSH, 32, - DRSI, 32, - DRSJ, 32 - } - } - } - - -/**************************************************************** - * PCI hotplug - ****************************************************************/ - - Scope(\_SB.PCI0) { - /* Methods called by bulk generated PCI devices below */ - - /* Methods called by hotplug devices */ - Method (PCEJ, 1, NotSerialized) { - // _EJ0 method - eject callback - Store(ShiftLeft(1, Arg0), B0EJ) - Return (0x0) - } - - /* Hotplug notification method supplied by SSDT */ - External (\_SB.PCI0.PCNT, MethodObj) - - /* PCI hotplug notify method */ - Method(PCNF, 0) { - // Local0 = iterator - Store (Zero, Local0) - While (LLess(Local0, 31)) { - Increment(Local0) - If (And(PCIU, ShiftLeft(1, Local0))) { - PCNT(Local0, 1) - } - If (And(PCID, ShiftLeft(1, Local0))) { - PCNT(Local0, 3) - } - } - Return(One) - } - - } - - -/**************************************************************** - * PCI IRQs - ****************************************************************/ - - Scope(\_SB) { - Field (PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) - { - PRQ0, 8, - PRQ1, 8, - PRQ2, 8, - PRQ3, 8 - } - - Method (IQST, 1, NotSerialized) { - // _STA method - get status - If (And (0x80, Arg0)) { - Return (0x09) - } - Return (0x0B) - } - Method (IQCR, 1, NotSerialized) { - // _CRS method - get current settings - Name (PRR0, ResourceTemplate () - { - Interrupt (, Level, ActiveHigh, Shared) - { 0 } - }) - CreateDWordField (PRR0, 0x05, PRRI) - If (LLess (Arg0, 0x80)) { - Store (Arg0, PRRI) - } - Return (PRR0) - } - // _DIS method - disable interrupt -#define DISIRQ(PRQVAR) \ - Or(PRQVAR, 0x80, PRQVAR) \ - // _SRS method - set interrupt -#define SETIRQ(PRQVAR, IRQINFO) \ - CreateDWordField (IRQINFO, 0x05, PRRI) \ - Store (PRRI, PRQVAR) - - Device(LNKA) { - Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link - Name(_UID, 1) - Name(_PRS, ResourceTemplate(){ - Interrupt (, Level, ActiveHigh, Shared) - { 5, 10, 11 } - }) - Method (_STA, 0, NotSerialized) { Return (IQST(PRQ0)) } - Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ0) } - Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ0)) } - Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ0, Arg0) } - } - Device(LNKB) { - Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link - Name(_UID, 2) - Name(_PRS, ResourceTemplate(){ - Interrupt (, Level, ActiveHigh, Shared) - { 5, 10, 11 } - }) - Method (_STA, 0, NotSerialized) { Return (IQST(PRQ1)) } - Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ1) } - Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ1)) } - Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ1, Arg0) } - } - Device(LNKC) { - Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link - Name(_UID, 3) - Name(_PRS, ResourceTemplate() { - Interrupt (, Level, ActiveHigh, Shared) - { 5, 10, 11 } - }) - Method (_STA, 0, NotSerialized) { Return (IQST(PRQ2)) } - Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ2) } - Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ2)) } - Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ2, Arg0) } - } - Device(LNKD) { - Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link - Name(_UID, 4) - Name(_PRS, ResourceTemplate() { - Interrupt (, Level, ActiveHigh, Shared) - { 5, 10, 11 } - }) - Method (_STA, 0, NotSerialized) { Return (IQST(PRQ3)) } - Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ3) } - Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ3)) } - Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ3, Arg0) } - } - Device(LNKS) { - Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link - Name(_UID, 5) - Name(_PRS, ResourceTemplate() { - Interrupt (, Level, ActiveHigh, Shared) - { 9 } - }) - Method (_STA, 0, NotSerialized) { Return (IQST(PRQ0)) } - Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ0) } - Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ0)) } - } - } - -/**************************************************************** - * CPU hotplug - ****************************************************************/ - - Scope(\_SB) { - /* Objects filled in by run-time generated SSDT */ - External(NTFY, MethodObj) - External(CPON, PkgObj) - - /* Methods called by run-time generated SSDT Processor objects */ - Method (CPMA, 1, NotSerialized) { - // _MAT method - create an madt apic buffer - // Arg0 = Processor ID = Local APIC ID - // Local0 = CPON flag for this cpu - Store(DerefOf(Index(CPON, Arg0)), Local0) - // Local1 = Buffer (in madt apic form) to return - Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1) - // Update the processor id, lapic id, and enable/disable status - Store(Arg0, Index(Local1, 2)) - Store(Arg0, Index(Local1, 3)) - Store(Local0, Index(Local1, 4)) - Return (Local1) - } - Method (CPST, 1, NotSerialized) { - // _STA method - return ON status of cpu - // Arg0 = Processor ID = Local APIC ID - // Local0 = CPON flag for this cpu - Store(DerefOf(Index(CPON, Arg0)), Local0) - If (Local0) { Return(0xF) } Else { Return(0x0) } - } - Method (CPEJ, 2, NotSerialized) { - // _EJ0 method - eject callback - Sleep(200) - } - - /* CPU hotplug notify method */ - OperationRegion(PRST, SystemIO, 0xaf00, 32) - Field (PRST, ByteAcc, NoLock, Preserve) - { - PRS, 256 - } - Method(PRSC, 0) { - // Local5 = active cpu bitmap - Store (PRS, Local5) - // Local2 = last read byte from bitmap - Store (Zero, Local2) - // Local0 = Processor ID / APIC ID iterator - Store (Zero, Local0) - While (LLess(Local0, SizeOf(CPON))) { - // Local1 = CPON flag for this cpu - Store(DerefOf(Index(CPON, Local0)), Local1) - If (And(Local0, 0x07)) { - // Shift down previously read bitmap byte - ShiftRight(Local2, 1, Local2) - } Else { - // Read next byte from cpu bitmap - Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2) - } - // Local3 = active state for this cpu - Store(And(Local2, 1), Local3) - - If (LNotEqual(Local1, Local3)) { - // State change - update CPON with new state - Store(Local3, Index(CPON, Local0)) - // Do CPU notify - If (LEqual(Local3, 1)) { - NTFY(Local0, 1) - } Else { - NTFY(Local0, 3) - } - } - Increment(Local0) - } - Return(One) - } - } - - -/**************************************************************** - * General purpose events - ****************************************************************/ - - Scope (\_GPE) - { - Name(_HID, "ACPI0006") - - Method(_L00) { - Return(0x01) - } - Method(_E01) { - // PCI hotplug event - Return(\_SB.PCI0.PCNF()) - } - Method(_E02) { - // CPU hotplug event - Return(\_SB.PRSC()) - } - Method(_L03) { - Return(0x01) - } - Method(_L04) { - Return(0x01) - } - Method(_L05) { - Return(0x01) - } - Method(_L06) { - Return(0x01) - } - Method(_L07) { - Return(0x01) - } - Method(_L08) { - Return(0x01) - } - Method(_L09) { - Return(0x01) - } - Method(_L0A) { - Return(0x01) - } - Method(_L0B) { - Return(0x01) - } - Method(_L0C) { - Return(0x01) - } - Method(_L0D) { - Return(0x01) - } - Method(_L0E) { - Return(0x01) - } - Method(_L0F) { - Return(0x01) - } - } -} diff -Nru seabios-1.7.1/src/acpi.h seabios-1.7.4/src/acpi.h --- seabios-1.7.1/src/acpi.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/acpi.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -#ifndef __ACPI_H -#define __ACPI_H - -#include "types.h" // u32 - -void acpi_bios_init(void); -u32 find_resume_vector(void); - -#define RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR " - -struct rsdp_descriptor { /* Root System Descriptor Pointer */ - u64 signature; /* ACPI signature, contains "RSD PTR " */ - u8 checksum; /* To make sum of struct == 0 */ - u8 oem_id [6]; /* OEM identification */ - u8 revision; /* Must be 0 for 1.0, 2 for 2.0 */ - u32 rsdt_physical_address; /* 32-bit physical address of RSDT */ - u32 length; /* XSDT Length in bytes including hdr */ - u64 xsdt_physical_address; /* 64-bit physical address of XSDT */ - u8 extended_checksum; /* Checksum of entire table */ - u8 reserved [3]; /* Reserved field must be 0 */ -}; - -extern struct rsdp_descriptor *RsdpAddr; - -/* Table structure from Linux kernel (the ACPI tables are under the - BSD license) */ - -#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ - u32 signature; /* ACPI signature (4 ASCII characters) */ \ - u32 length; /* Length of table, in bytes, including header */ \ - u8 revision; /* ACPI Specification minor version # */ \ - u8 checksum; /* To make sum of entire table == 0 */ \ - u8 oem_id [6]; /* OEM identification */ \ - u8 oem_table_id [8]; /* OEM table identification */ \ - u32 oem_revision; /* OEM revision number */ \ - u8 asl_compiler_id [4]; /* ASL compiler vendor ID */ \ - u32 asl_compiler_revision; /* ASL compiler revision number */ - - -/* - * ACPI 1.0 Fixed ACPI Description Table (FADT) - */ -#define FACP_SIGNATURE 0x50434146 // FACP -struct fadt_descriptor_rev1 -{ - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 firmware_ctrl; /* Physical address of FACS */ - u32 dsdt; /* Physical address of DSDT */ - u8 model; /* System Interrupt Model */ - u8 reserved1; /* Reserved */ - u16 sci_int; /* System vector of SCI interrupt */ - u32 smi_cmd; /* Port address of SMI command port */ - u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ - u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ - u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ - u8 reserved2; /* Reserved - must be zero */ - u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ - u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ - u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ - u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ - u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ - u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ - u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ - u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ - u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ - u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ - u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ - u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ - u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ - u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ - u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ - u8 reserved3; /* Reserved */ - u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ - u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ - u16 flush_size; /* Size of area read to flush caches */ - u16 flush_stride; /* Stride used in flushing caches */ - u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */ - u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */ - u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ - u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ - u8 century; /* Index to century in RTC CMOS RAM */ - u8 reserved4; /* Reserved */ - u8 reserved4a; /* Reserved */ - u8 reserved4b; /* Reserved */ -#if 0 - u32 wb_invd : 1; /* The wbinvd instruction works properly */ - u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */ - u32 proc_c1 : 1; /* All processors support C1 state */ - u32 plvl2_up : 1; /* C2 state works on MP system */ - u32 pwr_button : 1; /* Power button is handled as a generic feature */ - u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ - u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ - u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ - u32 tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */ - u32 reserved5 : 23; /* Reserved - must be zero */ -#else - u32 flags; -#endif -} PACKED; - -struct bfld { - u64 p0s; /* pci window 0 (below 4g) - start */ - u64 p0e; /* pci window 0 (below 4g) - end */ - u64 p0l; /* pci window 0 (below 4g) - length */ - u64 p1s; /* pci window 1 (above 4g) - start */ - u64 p1e; /* pci window 1 (above 4g) - end */ - u64 p1l; /* pci window 1 (above 4g) - length */ -} PACKED; - -#endif // acpi.h diff -Nru seabios-1.7.1/src/ahci.c seabios-1.7.4/src/ahci.c --- seabios-1.7.1/src/ahci.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ahci.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,641 +0,0 @@ -// Low level AHCI disk access -// -// Copyright (C) 2010 Gerd Hoffmann -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "types.h" // u8 -#include "ioport.h" // inb -#include "util.h" // dprintf -#include "biosvar.h" // GET_GLOBAL -#include "pci.h" // foreachpci -#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER -#include "pci_regs.h" // PCI_INTERRUPT_LINE -#include "boot.h" // add_bcv_hd -#include "disk.h" // struct ata_s -#include "ata.h" // ATA_CB_STAT -#include "ahci.h" // CDB_CMD_READ_10 -#include "blockcmd.h" // CDB_CMD_READ_10 - -#define AHCI_REQUEST_TIMEOUT 32000 // 32 seconds max for IDE ops -#define AHCI_RESET_TIMEOUT 500 // 500 miliseconds -#define AHCI_LINK_TIMEOUT 10 // 10 miliseconds - -/**************************************************************** - * these bits must run in both 16bit and 32bit modes - ****************************************************************/ - -// prepare sata command fis -static void sata_prep_simple(struct sata_cmd_fis *fis, u8 command) -{ - memset_fl(fis, 0, sizeof(*fis)); - SET_LOWFLAT(fis->command, command); -} - -static void sata_prep_readwrite(struct sata_cmd_fis *fis, - struct disk_op_s *op, int iswrite) -{ - u64 lba = op->lba; - u8 command; - - memset_fl(fis, 0, sizeof(*fis)); - - if (op->count >= (1<<8) || lba + op->count >= (1<<28)) { - SET_LOWFLAT(fis->sector_count2, op->count >> 8); - SET_LOWFLAT(fis->lba_low2, lba >> 24); - SET_LOWFLAT(fis->lba_mid2, lba >> 32); - SET_LOWFLAT(fis->lba_high2, lba >> 40); - lba &= 0xffffff; - command = (iswrite ? ATA_CMD_WRITE_DMA_EXT - : ATA_CMD_READ_DMA_EXT); - } else { - command = (iswrite ? ATA_CMD_WRITE_DMA - : ATA_CMD_READ_DMA); - } - SET_LOWFLAT(fis->feature, 1); /* dma */ - SET_LOWFLAT(fis->command, command); - SET_LOWFLAT(fis->sector_count, op->count); - SET_LOWFLAT(fis->lba_low, lba); - SET_LOWFLAT(fis->lba_mid, lba >> 8); - SET_LOWFLAT(fis->lba_high, lba >> 16); - SET_LOWFLAT(fis->device, ((lba >> 24) & 0xf) | ATA_CB_DH_LBA); -} - -static void sata_prep_atapi(struct sata_cmd_fis *fis, u16 blocksize) -{ - memset_fl(fis, 0, sizeof(*fis)); - SET_LOWFLAT(fis->command, ATA_CMD_PACKET); - SET_LOWFLAT(fis->feature, 1); /* dma */ - SET_LOWFLAT(fis->lba_mid, blocksize); - SET_LOWFLAT(fis->lba_high, blocksize >> 8); -} - -// ahci register access helpers -static u32 ahci_ctrl_readl(struct ahci_ctrl_s *ctrl, u32 reg) -{ - u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg; - return pci_readl(addr); -} - -static void ahci_ctrl_writel(struct ahci_ctrl_s *ctrl, u32 reg, u32 val) -{ - u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg; - pci_writel(addr, val); -} - -static u32 ahci_port_to_ctrl(u32 pnr, u32 port_reg) -{ - u32 ctrl_reg = 0x100; - ctrl_reg += pnr * 0x80; - ctrl_reg += port_reg; - return ctrl_reg; -} - -static u32 ahci_port_readl(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg) -{ - u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg); - return ahci_ctrl_readl(ctrl, ctrl_reg); -} - -static void ahci_port_writel(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg, u32 val) -{ - u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg); - ahci_ctrl_writel(ctrl, ctrl_reg, val); -} - -// submit ahci command + wait for result -static int ahci_command(struct ahci_port_s *port, int iswrite, int isatapi, - void *buffer, u32 bsize) -{ - u32 val, status, success, flags, intbits, error; - struct ahci_ctrl_s *ctrl = GET_GLOBAL(port->ctrl); - struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd); - struct ahci_fis_s *fis = GET_GLOBAL(port->fis); - struct ahci_list_s *list = GET_GLOBAL(port->list); - u32 pnr = GET_GLOBAL(port->pnr); - u64 end; - - SET_LOWFLAT(cmd->fis.reg, 0x27); - SET_LOWFLAT(cmd->fis.pmp_type, (1 << 7)); /* cmd fis */ - SET_LOWFLAT(cmd->prdt[0].base, ((u32)buffer)); - SET_LOWFLAT(cmd->prdt[0].baseu, 0); - SET_LOWFLAT(cmd->prdt[0].flags, bsize-1); - - flags = ((1 << 16) | /* one prd entry */ - (iswrite ? (1 << 6) : 0) | - (isatapi ? (1 << 5) : 0) | - (5 << 0)); /* fis length (dwords) */ - SET_LOWFLAT(list[0].flags, flags); - SET_LOWFLAT(list[0].bytes, 0); - SET_LOWFLAT(list[0].base, ((u32)(cmd))); - SET_LOWFLAT(list[0].baseu, 0); - - dprintf(8, "AHCI/%d: send cmd ...\n", pnr); - intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); - if (intbits) - ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); - ahci_port_writel(ctrl, pnr, PORT_SCR_ACT, 1); - ahci_port_writel(ctrl, pnr, PORT_CMD_ISSUE, 1); - - end = calc_future_tsc(AHCI_REQUEST_TIMEOUT); - do { - for (;;) { - intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); - if (intbits) { - ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); - if (intbits & 0x02) { - status = GET_LOWFLAT(fis->psfis[2]); - error = GET_LOWFLAT(fis->psfis[3]); - break; - } - if (intbits & 0x01) { - status = GET_LOWFLAT(fis->rfis[2]); - error = GET_LOWFLAT(fis->rfis[3]); - break; - } - } - if (check_tsc(end)) { - warn_timeout(); - return -1; - } - yield(); - } - dprintf(8, "AHCI/%d: ... intbits 0x%x, status 0x%x ...\n", - pnr, intbits, status); - } while (status & ATA_CB_STAT_BSY); - - success = (0x00 == (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | - ATA_CB_STAT_ERR)) && - ATA_CB_STAT_RDY == (status & (ATA_CB_STAT_RDY))); - if (success) { - dprintf(8, "AHCI/%d: ... finished, status 0x%x, OK\n", pnr, - status); - } else { - dprintf(2, "AHCI/%d: ... finished, status 0x%x, ERROR 0x%x\n", pnr, - status, error); - - // non-queued error recovery (AHCI 1.3 section 6.2.2.1) - // Clears PxCMD.ST to 0 to reset the PxCI register - val = ahci_port_readl(ctrl, pnr, PORT_CMD); - ahci_port_writel(ctrl, pnr, PORT_CMD, val & ~PORT_CMD_START); - - // waits for PxCMD.CR to clear to 0 - while (1) { - val = ahci_port_readl(ctrl, pnr, PORT_CMD); - if ((val & PORT_CMD_LIST_ON) == 0) - break; - yield(); - } - - // Clears any error bits in PxSERR to enable capturing new errors - val = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR); - ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, val); - - // Clears status bits in PxIS as appropriate - val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); - ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val); - - // If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to 1, issue - // a COMRESET to the device to put it in an idle state - val = ahci_port_readl(ctrl, pnr, PORT_TFDATA); - if (val & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ)) { - dprintf(2, "AHCI/%d: issue comreset\n", pnr); - val = ahci_port_readl(ctrl, pnr, PORT_SCR_CTL); - // set Device Detection Initialization (DET) to 1 for 1 ms for comreset - ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val | 1); - mdelay (1); - ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val); - } - - // Sets PxCMD.ST to 1 to enable issuing new commands - val = ahci_port_readl(ctrl, pnr, PORT_CMD); - ahci_port_writel(ctrl, pnr, PORT_CMD, val | PORT_CMD_START); - } - return success ? 0 : -1; -} - -#define CDROM_CDB_SIZE 12 - -int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - if (! CONFIG_AHCI) - return 0; - - struct ahci_port_s *port = container_of( - op->drive_g, struct ahci_port_s, drive); - struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd); - u8 *atapi = cdbcmd; - int i, rc; - - sata_prep_atapi(&cmd->fis, blocksize); - for (i = 0; i < CDROM_CDB_SIZE; i++) { - SET_LOWFLAT(cmd->atapi[i], atapi[i]); - } - rc = ahci_command(port, 0, 1, op->buf_fl, - op->count * blocksize); - if (rc < 0) - return DISK_RET_EBADTRACK; - return DISK_RET_SUCCESS; -} - -// read/write count blocks from a harddrive, op->buf_fl must be word aligned -static int -ahci_disk_readwrite_aligned(struct disk_op_s *op, int iswrite) -{ - struct ahci_port_s *port = container_of( - op->drive_g, struct ahci_port_s, drive); - struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd); - int rc; - - sata_prep_readwrite(&cmd->fis, op, iswrite); - rc = ahci_command(port, iswrite, 0, op->buf_fl, - op->count * DISK_SECTOR_SIZE); - dprintf(8, "ahci disk %s, lba %6x, count %3x, buf %p, rc %d\n", - iswrite ? "write" : "read", (u32)op->lba, op->count, op->buf_fl, rc); - if (rc < 0) - return DISK_RET_EBADTRACK; - return DISK_RET_SUCCESS; -} - -// read/write count blocks from a harddrive. -static int -ahci_disk_readwrite(struct disk_op_s *op, int iswrite) -{ - // if caller's buffer is word aligned, use it directly - if (((u32) op->buf_fl & 1) == 0) - return ahci_disk_readwrite_aligned(op, iswrite); - - // Use a word aligned buffer for AHCI I/O - int rc; - struct disk_op_s localop = *op; - u8 *alignedbuf_fl = GET_GLOBAL(bounce_buf_fl); - u8 *position = op->buf_fl; - - localop.buf_fl = alignedbuf_fl; - localop.count = 1; - - if (iswrite) { - u16 block; - for (block = 0; block < op->count; block++) { - memcpy_fl (alignedbuf_fl, position, DISK_SECTOR_SIZE); - rc = ahci_disk_readwrite_aligned (&localop, 1); - if (rc) - return rc; - position += DISK_SECTOR_SIZE; - localop.lba++; - } - } else { // read - u16 block; - for (block = 0; block < op->count; block++) { - rc = ahci_disk_readwrite_aligned (&localop, 0); - if (rc) - return rc; - memcpy_fl (position, alignedbuf_fl, DISK_SECTOR_SIZE); - position += DISK_SECTOR_SIZE; - localop.lba++; - } - } - return DISK_RET_SUCCESS; -} - -// command demuxer -int process_ahci_op(struct disk_op_s *op) -{ - if (!CONFIG_AHCI) - return 0; - switch (op->command) { - case CMD_READ: - return ahci_disk_readwrite(op, 0); - case CMD_WRITE: - return ahci_disk_readwrite(op, 1); - case CMD_FORMAT: - case CMD_RESET: - case CMD_ISREADY: - case CMD_VERIFY: - case CMD_SEEK: - return DISK_RET_SUCCESS; - default: - dprintf(1, "AHCI: unknown disk command %d\n", op->command); - op->count = 0; - return DISK_RET_EPARAM; - } -} - -/**************************************************************** - * everything below is pure 32bit code - ****************************************************************/ - -static void -ahci_port_reset(struct ahci_ctrl_s *ctrl, u32 pnr) -{ - u32 val; - u64 end; - - /* disable FIS + CMD */ - end = calc_future_tsc(AHCI_RESET_TIMEOUT); - for (;;) { - val = ahci_port_readl(ctrl, pnr, PORT_CMD); - if (!(val & (PORT_CMD_FIS_RX | PORT_CMD_START | - PORT_CMD_FIS_ON | PORT_CMD_LIST_ON))) - break; - val &= ~(PORT_CMD_FIS_RX | PORT_CMD_START); - ahci_port_writel(ctrl, pnr, PORT_CMD, val); - if (check_tsc(end)) { - warn_timeout(); - break; - } - yield(); - } - - /* disable + clear IRQs */ - ahci_port_writel(ctrl, pnr, PORT_IRQ_MASK, 0); - val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); - if (val) - ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val); -} - -static struct ahci_port_s* -ahci_port_alloc(struct ahci_ctrl_s *ctrl, u32 pnr) -{ - struct ahci_port_s *port = malloc_tmp(sizeof(*port)); - - if (!port) { - warn_noalloc(); - return NULL; - } - port->pnr = pnr; - port->ctrl = ctrl; - port->list = memalign_tmp(1024, 1024); - port->fis = memalign_tmp(256, 256); - port->cmd = memalign_tmp(256, 256); - if (port->list == NULL || port->fis == NULL || port->cmd == NULL) { - warn_noalloc(); - return NULL; - } - memset(port->list, 0, 1024); - memset(port->fis, 0, 256); - memset(port->cmd, 0, 256); - - ahci_port_writel(ctrl, pnr, PORT_LST_ADDR, (u32)port->list); - ahci_port_writel(ctrl, pnr, PORT_FIS_ADDR, (u32)port->fis); - return port; -} - -static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port) -{ - struct ahci_port_s *tmp; - u32 cmd; - - tmp = malloc_fseg(sizeof(*port)); - *tmp = *port; - free(port); - port = tmp; - - ahci_port_reset(port->ctrl, port->pnr); - - free(port->list); - free(port->fis); - free(port->cmd); - port->list = memalign_low(1024, 1024); - port->fis = memalign_low(256, 256); - port->cmd = memalign_low(256, 256); - - ahci_port_writel(port->ctrl, port->pnr, PORT_LST_ADDR, (u32)port->list); - ahci_port_writel(port->ctrl, port->pnr, PORT_FIS_ADDR, (u32)port->fis); - - cmd = ahci_port_readl(port->ctrl, port->pnr, PORT_CMD); - cmd |= (PORT_CMD_FIS_RX|PORT_CMD_START); - ahci_port_writel(port->ctrl, port->pnr, PORT_CMD, cmd); - - return port; -} - -static void ahci_port_release(struct ahci_port_s *port) -{ - ahci_port_reset(port->ctrl, port->pnr); - free(port->list); - free(port->fis); - free(port->cmd); - free(port); -} - -#define MAXMODEL 40 - -/* See ahci spec chapter 10.1 "Software Initialization of HBA" */ -static int ahci_port_init(struct ahci_port_s *port) -{ - struct ahci_ctrl_s *ctrl = port->ctrl; - u32 pnr = port->pnr; - char model[MAXMODEL+1]; - u16 buffer[256]; - u32 cmd, stat, err, tf; - u64 end; - int rc; - - /* enable FIS recv */ - cmd = ahci_port_readl(ctrl, pnr, PORT_CMD); - cmd |= PORT_CMD_FIS_RX; - ahci_port_writel(ctrl, pnr, PORT_CMD, cmd); - - /* spin up */ - cmd |= PORT_CMD_SPIN_UP; - ahci_port_writel(ctrl, pnr, PORT_CMD, cmd); - end = calc_future_tsc(AHCI_LINK_TIMEOUT); - for (;;) { - stat = ahci_port_readl(ctrl, pnr, PORT_SCR_STAT); - if ((stat & 0x07) == 0x03) { - dprintf(2, "AHCI/%d: link up\n", port->pnr); - break; - } - if (check_tsc(end)) { - dprintf(2, "AHCI/%d: link down\n", port->pnr); - return -1; - } - yield(); - } - - /* clear error status */ - err = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR); - if (err) - ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, err); - - /* wait for device becoming ready */ - end = calc_future_tsc(AHCI_REQUEST_TIMEOUT); - for (;;) { - tf = ahci_port_readl(ctrl, pnr, PORT_TFDATA); - if (!(tf & (ATA_CB_STAT_BSY | - ATA_CB_STAT_DRQ))) - break; - if (check_tsc(end)) { - warn_timeout(); - dprintf(1, "AHCI/%d: device not ready (tf 0x%x)\n", port->pnr, tf); - return -1; - } - yield(); - } - - /* start device */ - cmd |= PORT_CMD_START; - ahci_port_writel(ctrl, pnr, PORT_CMD, cmd); - - sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_PACKET_DEVICE); - rc = ahci_command(port, 0, 0, buffer, sizeof(buffer)); - if (rc == 0) { - port->atapi = 1; - } else { - port->atapi = 0; - sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_DEVICE); - rc = ahci_command(port, 0, 0, buffer, sizeof(buffer)); - if (rc < 0) - return -1; - } - - port->drive.cntl_id = pnr; - port->drive.removable = (buffer[0] & 0x80) ? 1 : 0; - - if (!port->atapi) { - // found disk (ata) - port->drive.type = DTYPE_AHCI; - port->drive.blksize = DISK_SECTOR_SIZE; - port->drive.pchs.cylinders = buffer[1]; - port->drive.pchs.heads = buffer[3]; - port->drive.pchs.spt = buffer[6]; - - u64 sectors; - if (buffer[83] & (1 << 10)) // word 83 - lba48 support - sectors = *(u64*)&buffer[100]; // word 100-103 - else - sectors = *(u32*)&buffer[60]; // word 60 and word 61 - port->drive.sectors = sectors; - u64 adjsize = sectors >> 11; - char adjprefix = 'M'; - if (adjsize >= (1 << 16)) { - adjsize >>= 10; - adjprefix = 'G'; - } - port->desc = znprintf(MAXDESCSIZE - , "AHCI/%d: %s ATA-%d Hard-Disk (%u %ciBytes)" - , port->pnr - , ata_extract_model(model, MAXMODEL, buffer) - , ata_extract_version(buffer) - , (u32)adjsize, adjprefix); - port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0); - } else { - // found cdrom (atapi) - port->drive.type = DTYPE_AHCI_ATAPI; - port->drive.blksize = CDROM_SECTOR_SIZE; - port->drive.sectors = (u64)-1; - u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05; - if (!iscd) { - dprintf(1, "AHCI/%d: atapi device isn't a cdrom\n", port->pnr); - return -1; - } - port->desc = znprintf(MAXDESCSIZE - , "DVD/CD [AHCI/%d: %s ATAPI-%d DVD/CD]" - , port->pnr - , ata_extract_model(model, MAXMODEL, buffer) - , ata_extract_version(buffer)); - port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0); - } - return 0; -} - -// Detect any drives attached to a given controller. -static void -ahci_port_detect(void *data) -{ - struct ahci_port_s *port = data; - int rc; - - dprintf(2, "AHCI/%d: probing\n", port->pnr); - ahci_port_reset(port->ctrl, port->pnr); - rc = ahci_port_init(port); - if (rc < 0) - ahci_port_release(port); - else { - port = ahci_port_realloc(port); - dprintf(1, "AHCI/%d: registering: \"%s\"\n", port->pnr, port->desc); - if (!port->atapi) { - // Register with bcv system. - boot_add_hd(&port->drive, port->desc, port->prio); - } else { - // fill cdidmap - boot_add_cd(&port->drive, port->desc, port->prio); - } - } -} - -// Initialize an ata controller and detect its drives. -static void -ahci_init_controller(struct pci_device *pci) -{ - struct ahci_ctrl_s *ctrl = malloc_fseg(sizeof(*ctrl)); - struct ahci_port_s *port; - u16 bdf = pci->bdf; - u32 val, pnr, max; - - if (!ctrl) { - warn_noalloc(); - return; - } - - if (bounce_buf_init() < 0) { - warn_noalloc(); - free(ctrl); - return; - } - - ctrl->pci_tmp = pci; - ctrl->pci_bdf = bdf; - ctrl->iobase = pci_config_readl(bdf, PCI_BASE_ADDRESS_5); - ctrl->irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); - dprintf(1, "AHCI controller at %02x.%x, iobase %x, irq %d\n", - bdf >> 3, bdf & 7, ctrl->iobase, ctrl->irq); - - pci_config_maskw(bdf, PCI_COMMAND, 0, - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - - val = ahci_ctrl_readl(ctrl, HOST_CTL); - ahci_ctrl_writel(ctrl, HOST_CTL, val | HOST_CTL_AHCI_EN); - - ctrl->caps = ahci_ctrl_readl(ctrl, HOST_CAP); - ctrl->ports = ahci_ctrl_readl(ctrl, HOST_PORTS_IMPL); - dprintf(2, "AHCI: cap 0x%x, ports_impl 0x%x\n", - ctrl->caps, ctrl->ports); - - max = ctrl->caps & 0x1f; - for (pnr = 0; pnr <= max; pnr++) { - if (!(ctrl->ports & (1 << pnr))) - continue; - port = ahci_port_alloc(ctrl, pnr); - if (port == NULL) - continue; - run_thread(ahci_port_detect, port); - } -} - -// Locate and init ahci controllers. -static void -ahci_init(void) -{ - // Scan PCI bus for ATA adapters - struct pci_device *pci; - foreachpci(pci) { - if (pci->class != PCI_CLASS_STORAGE_SATA) - continue; - if (pci->prog_if != 1 /* AHCI rev 1 */) - continue; - ahci_init_controller(pci); - } -} - -void -ahci_setup(void) -{ - ASSERT32FLAT(); - if (!CONFIG_AHCI) - return; - - dprintf(3, "init ahci\n"); - ahci_init(); -} diff -Nru seabios-1.7.1/src/ahci.h seabios-1.7.4/src/ahci.h --- seabios-1.7.1/src/ahci.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ahci.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,199 +0,0 @@ -#ifndef __AHCI_H -#define __AHCI_H - -struct sata_cmd_fis { - u8 reg; - u8 pmp_type; - u8 command; - u8 feature; - - u8 lba_low; - u8 lba_mid; - u8 lba_high; - u8 device; - - u8 lba_low2; - u8 lba_mid2; - u8 lba_high2; - u8 feature2; - - u8 sector_count; - u8 sector_count2; - u8 res_1; - u8 control; - - u8 res_2[64 - 16]; -}; - -struct ahci_ctrl_s { - struct pci_device *pci_tmp; - u16 pci_bdf; - u8 irq; - u32 iobase; - u32 caps; - u32 ports; -}; - -struct ahci_cmd_s { - struct sata_cmd_fis fis; - u8 atapi[0x20]; - u8 res[0x20]; - struct { - u32 base; - u32 baseu; - u32 res; - u32 flags; - } prdt[]; -}; - -/* command list */ -struct ahci_list_s { - u32 flags; - u32 bytes; - u32 base; - u32 baseu; - u32 res[4]; -}; - -struct ahci_fis_s { - u8 dsfis[0x1c]; /* dma setup */ - u8 res_1[0x04]; - u8 psfis[0x14]; /* pio setup */ - u8 res_2[0x0c]; - u8 rfis[0x14]; /* d2h register */ - u8 res_3[0x04]; - u8 sdbfis[0x08]; /* set device bits */ - u8 ufis[0x40]; /* unknown */ - u8 res_4[0x60]; -}; - -struct ahci_port_s { - struct drive_s drive; - struct ahci_ctrl_s *ctrl; - struct ahci_list_s *list; - struct ahci_fis_s *fis; - struct ahci_cmd_s *cmd; - u32 pnr; - u32 atapi; - char *desc; - int prio; -}; - -void ahci_setup(void); -int process_ahci_op(struct disk_op_s *op); -int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); - -#define AHCI_IRQ_ON_SG (1 << 31) -#define AHCI_CMD_ATAPI (1 << 5) -#define AHCI_CMD_WRITE (1 << 6) -#define AHCI_CMD_PREFETCH (1 << 7) -#define AHCI_CMD_RESET (1 << 8) -#define AHCI_CMD_CLR_BUSY (1 << 10) - -#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ -#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ -#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ - -/* global controller registers */ -#define HOST_CAP 0x00 /* host capabilities */ -#define HOST_CTL 0x04 /* global host control */ -#define HOST_IRQ_STAT 0x08 /* interrupt status */ -#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ -#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ - -/* HOST_CTL bits */ -#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ -#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ -#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */ - -/* HOST_CAP bits */ -#define HOST_CAP_SSC (1 << 14) /* Slumber capable */ -#define HOST_CAP_AHCI (1 << 18) /* AHCI only */ -#define HOST_CAP_CLO (1 << 24) /* Command List Override support */ -#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ -#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ -#define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */ - -/* registers for each SATA port */ -#define PORT_LST_ADDR 0x00 /* command list DMA addr */ -#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ -#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ -#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ -#define PORT_IRQ_STAT 0x10 /* interrupt status */ -#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ -#define PORT_CMD 0x18 /* port command */ -#define PORT_TFDATA 0x20 /* taskfile data */ -#define PORT_SIG 0x24 /* device TF signature */ -#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ -#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ -#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ -#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ -#define PORT_CMD_ISSUE 0x38 /* command issue */ -#define PORT_RESERVED 0x3c /* reserved */ - -/* PORT_IRQ_{STAT,MASK} bits */ -#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ -#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ -#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ -#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ -#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ -#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ -#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ -#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ - -#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ -#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ -#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ -#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ -#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ -#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ -#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ -#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ -#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ - -#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \ - PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ - PORT_IRQ_UNK_FIS) -#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \ - PORT_IRQ_HBUS_DATA_ERR) -#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \ - PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ - PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) - -/* PORT_CMD bits */ -#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ -#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ -#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ -#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ -#define PORT_CMD_CLO (1 << 3) /* Command list override */ -#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ -#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ -#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ - -#define PORT_CMD_ICC_MASK (0xf << 28) /* i/f ICC state mask */ -#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ -#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ -#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ - -#define PORT_IRQ_STAT_DHRS (1 << 0) /* Device to Host Register FIS */ -#define PORT_IRQ_STAT_PSS (1 << 1) /* PIO Setup FIS */ -#define PORT_IRQ_STAT_DSS (1 << 2) /* DMA Setup FIS */ -#define PORT_IRQ_STAT_SDBS (1 << 3) /* Set Device Bits */ -#define PORT_IRQ_STAT_UFS (1 << 4) /* Unknown FIS */ -#define PORT_IRQ_STAT_DPS (1 << 5) /* Descriptor Processed */ -#define PORT_IRQ_STAT_PCS (1 << 6) /* Port Connect Change Status */ -#define PORT_IRQ_STAT_DMPS (1 << 7) /* Device Mechanical Presence - Status */ -#define PORT_IRQ_STAT_PRCS (1 << 22) /* File Ready Status */ -#define PORT_IRQ_STAT_IPMS (1 << 23) /* Incorrect Port Multiplier - Status */ -#define PORT_IRQ_STAT_OFS (1 << 24) /* Overflow Status */ -#define PORT_IRQ_STAT_INFS (1 << 26) /* Interface Non-Fatal Error - Status */ -#define PORT_IRQ_STAT_IFS (1 << 27) /* Interface Fatal Error */ -#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */ -#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */ -#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */ -#define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */ - -#endif // ahci.h diff -Nru seabios-1.7.1/src/apm.c seabios-1.7.4/src/apm.c --- seabios-1.7.1/src/apm.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/apm.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,16 +6,19 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. +#include "biosvar.h" // GET_GLOBAL #include "bregs.h" // struct bregs -#include "ioport.h" // outb -#include "util.h" // dprintf #include "config.h" // CONFIG_* -#include "biosvar.h" // GET_GLOBAL +#include "fw/paravirt.h" // runningOnQEMU +#include "output.h" // dprintf +#include "stacks.h" // yield_toirq +#include "util.h" // apm_shutdown +#include "x86.h" // outb static void out_str(const char *str_cs) { - if (CONFIG_COREBOOT) { + if (!runningOnQEMU()) { dprintf(1, "APM request '%s'\n", str_cs); return; } @@ -107,7 +110,11 @@ void apm_shutdown(void) { + u16 pm1a_cnt = GET_GLOBAL(acpi_pm1a_cnt); + irq_disable(); + if (pm1a_cnt) + outw(0x2000, pm1a_cnt); out_str("Shutdown"); for (;;) hlt(); diff -Nru seabios-1.7.1/src/ata.c seabios-1.7.4/src/ata.c --- seabios-1.7.1/src/ata.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ata.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1042 +0,0 @@ -// Low level ATA disk access -// -// Copyright (C) 2008,2009 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "types.h" // u8 -#include "ioport.h" // inb -#include "util.h" // dprintf -#include "cmos.h" // inb_cmos -#include "pic.h" // enable_hwirq -#include "biosvar.h" // GET_GLOBAL -#include "pci.h" // foreachpci -#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER -#include "pci_regs.h" // PCI_INTERRUPT_LINE -#include "boot.h" // boot_add_hd -#include "disk.h" // struct ata_s -#include "ata.h" // ATA_CB_STAT -#include "blockcmd.h" // CDB_CMD_READ_10 - -#define IDE_TIMEOUT 32000 //32 seconds max for IDE ops - - -/**************************************************************** - * Helper functions - ****************************************************************/ - -// Wait for the specified ide state -static inline int -await_ide(u8 mask, u8 flags, u16 base, u16 timeout) -{ - u64 end = calc_future_tsc(timeout); - for (;;) { - u8 status = inb(base+ATA_CB_STAT); - if ((status & mask) == flags) - return status; - if (check_tsc(end)) { - warn_timeout(); - return -1; - } - yield(); - } -} - -// Wait for the device to be not-busy. -static int -await_not_bsy(u16 base) -{ - return await_ide(ATA_CB_STAT_BSY, 0, base, IDE_TIMEOUT); -} - -// Wait for the device to be ready. -static int -await_rdy(u16 base) -{ - return await_ide(ATA_CB_STAT_RDY, ATA_CB_STAT_RDY, base, IDE_TIMEOUT); -} - -// Wait for ide state - pauses for one ata cycle first. -static inline int -pause_await_not_bsy(u16 iobase1, u16 iobase2) -{ - // Wait one PIO transfer cycle. - inb(iobase2 + ATA_CB_ASTAT); - - return await_not_bsy(iobase1); -} - -// Wait for ide state - pause for 400ns first. -static inline int -ndelay_await_not_bsy(u16 iobase1) -{ - ndelay(400); - return await_not_bsy(iobase1); -} - -// Reset a drive -static void -ata_reset(struct atadrive_s *adrive_g) -{ - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u8 slave = GET_GLOBAL(adrive_g->slave); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); - - dprintf(6, "ata_reset drive=%p\n", &adrive_g->drive); - // Pulse SRST - outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC); - udelay(5); - outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC); - msleep(2); - - // wait for device to become not busy. - int status = await_not_bsy(iobase1); - if (status < 0) - goto done; - if (slave) { - // Change device. - u64 end = calc_future_tsc(IDE_TIMEOUT); - for (;;) { - outb(ATA_CB_DH_DEV1, iobase1 + ATA_CB_DH); - status = ndelay_await_not_bsy(iobase1); - if (status < 0) - goto done; - if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1) - break; - // Change drive request failed to take effect - retry. - if (check_tsc(end)) { - warn_timeout(); - goto done; - } - } - } else { - // QEMU doesn't reset dh on reset, so set it explicitly. - outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH); - } - - // On a user-reset request, wait for RDY if it is an ATA device. - u8 type=GET_GLOBAL(adrive_g->drive.type); - if (type == DTYPE_ATA) - status = await_rdy(iobase1); - -done: - // Enable interrupts - outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); - - dprintf(6, "ata_reset exit status=%x\n", status); -} - -// Check for drive RDY for 16bit interface command. -static int -isready(struct atadrive_s *adrive_g) -{ - // Read the status from controller - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u8 status = inb(iobase1 + ATA_CB_STAT); - if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY) - return DISK_RET_SUCCESS; - return DISK_RET_ENOTREADY; -} - - -/**************************************************************** - * ATA send command - ****************************************************************/ - -struct ata_pio_command { - u8 feature; - u8 sector_count; - u8 lba_low; - u8 lba_mid; - u8 lba_high; - u8 device; - u8 command; - - u8 feature2; - u8 sector_count2; - u8 lba_low2; - u8 lba_mid2; - u8 lba_high2; -}; - -// Send an ata command to the drive. -static int -send_cmd(struct atadrive_s *adrive_g, struct ata_pio_command *cmd) -{ - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u8 slave = GET_GLOBAL(adrive_g->slave); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - - // Select device - int status = await_not_bsy(iobase1); - if (status < 0) - return status; - u8 newdh = ((cmd->device & ~ATA_CB_DH_DEV1) - | (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)); - u8 olddh = inb(iobase1 + ATA_CB_DH); - outb(newdh, iobase1 + ATA_CB_DH); - if ((olddh ^ newdh) & (1<<4)) { - // Was a device change - wait for device to become not busy. - status = ndelay_await_not_bsy(iobase1); - if (status < 0) - return status; - } - - // Check for ATA_CMD_(READ|WRITE)_(SECTORS|DMA)_EXT commands. - if ((cmd->command & ~0x11) == ATA_CMD_READ_SECTORS_EXT) { - outb(cmd->feature2, iobase1 + ATA_CB_FR); - outb(cmd->sector_count2, iobase1 + ATA_CB_SC); - outb(cmd->lba_low2, iobase1 + ATA_CB_SN); - outb(cmd->lba_mid2, iobase1 + ATA_CB_CL); - outb(cmd->lba_high2, iobase1 + ATA_CB_CH); - } - outb(cmd->feature, iobase1 + ATA_CB_FR); - outb(cmd->sector_count, iobase1 + ATA_CB_SC); - outb(cmd->lba_low, iobase1 + ATA_CB_SN); - outb(cmd->lba_mid, iobase1 + ATA_CB_CL); - outb(cmd->lba_high, iobase1 + ATA_CB_CH); - outb(cmd->command, iobase1 + ATA_CB_CMD); - - return 0; -} - -// Wait for data after calling 'send_cmd'. -static int -ata_wait_data(u16 iobase1) -{ - int status = ndelay_await_not_bsy(iobase1); - if (status < 0) - return status; - - if (status & ATA_CB_STAT_ERR) { - dprintf(6, "send_cmd : read error (status=%02x err=%02x)\n" - , status, inb(iobase1 + ATA_CB_ERR)); - return -4; - } - if (!(status & ATA_CB_STAT_DRQ)) { - dprintf(6, "send_cmd : DRQ not set (status %02x)\n", status); - return -5; - } - - return 0; -} - -// Send an ata command that does not transfer any further data. -int -ata_cmd_nondata(struct atadrive_s *adrive_g, struct ata_pio_command *cmd) -{ - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); - - // Disable interrupts - outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); - - int ret = send_cmd(adrive_g, cmd); - if (ret) - goto fail; - ret = ndelay_await_not_bsy(iobase1); - if (ret < 0) - goto fail; - - if (ret & ATA_CB_STAT_ERR) { - dprintf(6, "nondata cmd : read error (status=%02x err=%02x)\n" - , ret, inb(iobase1 + ATA_CB_ERR)); - ret = -4; - goto fail; - } - if (ret & ATA_CB_STAT_DRQ) { - dprintf(6, "nondata cmd : DRQ set (status %02x)\n", ret); - ret = -5; - goto fail; - } - -fail: - // Enable interrupts - outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); - - return ret; -} - - -/**************************************************************** - * ATA PIO transfers - ****************************************************************/ - -// Transfer 'op->count' blocks (of 'blocksize' bytes) to/from drive -// 'op->drive_g'. -static int -ata_pio_transfer(struct disk_op_s *op, int iswrite, int blocksize) -{ - dprintf(16, "ata_pio_transfer id=%p write=%d count=%d bs=%d buf=%p\n" - , op->drive_g, iswrite, op->count, blocksize, op->buf_fl); - - struct atadrive_s *adrive_g = container_of( - op->drive_g, struct atadrive_s, drive); - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); - int count = op->count; - void *buf_fl = op->buf_fl; - int status; - for (;;) { - if (iswrite) { - // Write data to controller - dprintf(16, "Write sector id=%p dest=%p\n", op->drive_g, buf_fl); - if (CONFIG_ATA_PIO32) - outsl_fl(iobase1, buf_fl, blocksize / 4); - else - outsw_fl(iobase1, buf_fl, blocksize / 2); - } else { - // Read data from controller - dprintf(16, "Read sector id=%p dest=%p\n", op->drive_g, buf_fl); - if (CONFIG_ATA_PIO32) - insl_fl(iobase1, buf_fl, blocksize / 4); - else - insw_fl(iobase1, buf_fl, blocksize / 2); - } - buf_fl += blocksize; - - status = pause_await_not_bsy(iobase1, iobase2); - if (status < 0) { - // Error - op->count -= count; - return status; - } - - count--; - if (!count) - break; - status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR); - if (status != ATA_CB_STAT_DRQ) { - dprintf(6, "ata_pio_transfer : more sectors left (status %02x)\n" - , status); - op->count -= count; - return -6; - } - } - - status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ - | ATA_CB_STAT_ERR); - if (!iswrite) - status &= ~ATA_CB_STAT_DF; - if (status != 0) { - dprintf(6, "ata_pio_transfer : no sectors left (status %02x)\n", status); - return -7; - } - - return 0; -} - - -/**************************************************************** - * ATA DMA transfers - ****************************************************************/ - -#define BM_CMD 0 -#define BM_CMD_MEMWRITE 0x08 -#define BM_CMD_START 0x01 -#define BM_STATUS 2 -#define BM_STATUS_IRQ 0x04 -#define BM_STATUS_ERROR 0x02 -#define BM_STATUS_ACTIVE 0x01 -#define BM_TABLE 4 - -struct sff_dma_prd { - u32 buf_fl; - u32 count; -}; - -// Check if DMA available and setup transfer if so. -static int -ata_try_dma(struct disk_op_s *op, int iswrite, int blocksize) -{ - ASSERT16(); - if (! CONFIG_ATA_DMA) - return -1; - u32 dest = (u32)op->buf_fl; - if (dest & 1) - // Need minimum alignment of 1. - return -1; - struct atadrive_s *adrive_g = container_of( - op->drive_g, struct atadrive_s, drive); - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster); - if (! iomaster) - return -1; - u32 bytes = op->count * blocksize; - if (! bytes) - return -1; - - // Build PRD dma structure. - struct sff_dma_prd *dma = MAKE_FLATPTR(SEG_LOW, ExtraStack); - struct sff_dma_prd *origdma = dma; - while (bytes) { - if (dma >= &origdma[16]) - // Too many descriptors.. - return -1; - u32 count = bytes; - u32 max = 0x10000 - (dest & 0xffff); - if (count > max) - count = max; - - SET_LOWFLAT(dma->buf_fl, dest); - bytes -= count; - if (!bytes) - // Last descriptor. - count |= 1<<31; - dprintf(16, "dma@%p: %08x %08x\n", dma, dest, count); - dest += count; - SET_LOWFLAT(dma->count, count); - dma++; - } - - // Program bus-master controller. - outl((u32)origdma, iomaster + BM_TABLE); - u8 oldcmd = inb(iomaster + BM_CMD) & ~(BM_CMD_MEMWRITE|BM_CMD_START); - outb(oldcmd | (iswrite ? 0x00 : BM_CMD_MEMWRITE), iomaster + BM_CMD); - outb(BM_STATUS_ERROR|BM_STATUS_IRQ, iomaster + BM_STATUS); - - return 0; -} - -// Transfer data using DMA. -static int -ata_dma_transfer(struct disk_op_s *op) -{ - if (! CONFIG_ATA_DMA) - return -1; - dprintf(16, "ata_dma_transfer id=%p buf=%p\n", op->drive_g, op->buf_fl); - - struct atadrive_s *adrive_g = container_of( - op->drive_g, struct atadrive_s, drive); - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster); - - // Start bus-master controller. - u8 oldcmd = inb(iomaster + BM_CMD); - outb(oldcmd | BM_CMD_START, iomaster + BM_CMD); - - u64 end = calc_future_tsc(IDE_TIMEOUT); - u8 status; - for (;;) { - status = inb(iomaster + BM_STATUS); - if (status & BM_STATUS_IRQ) - break; - // Transfer in progress - if (check_tsc(end)) { - // Timeout. - warn_timeout(); - break; - } - yield(); - } - outb(oldcmd & ~BM_CMD_START, iomaster + BM_CMD); - - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); - int idestatus = pause_await_not_bsy(iobase1, iobase2); - - if ((status & (BM_STATUS_IRQ|BM_STATUS_ACTIVE)) == BM_STATUS_IRQ - && idestatus >= 0x00 - && (idestatus & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ - | ATA_CB_STAT_ERR)) == 0x00) - // Success. - return 0; - - dprintf(6, "IDE DMA error (dma=%x ide=%x/%x/%x)\n", status, idestatus - , inb(iobase2 + ATA_CB_ASTAT), inb(iobase1 + ATA_CB_ERR)); - op->count = 0; - return -1; -} - - -/**************************************************************** - * ATA hard drive functions - ****************************************************************/ - -// Transfer data to harddrive using PIO protocol. -static int -ata_pio_cmd_data(struct disk_op_s *op, int iswrite, struct ata_pio_command *cmd) -{ - struct atadrive_s *adrive_g = container_of( - op->drive_g, struct atadrive_s, drive); - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); - - // Disable interrupts - outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); - - int ret = send_cmd(adrive_g, cmd); - if (ret) - goto fail; - ret = ata_wait_data(iobase1); - if (ret) - goto fail; - ret = ata_pio_transfer(op, iswrite, DISK_SECTOR_SIZE); - -fail: - // Enable interrupts - outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); - return ret; -} - -// Transfer data to harddrive using DMA protocol. -static int -ata_dma_cmd_data(struct disk_op_s *op, struct ata_pio_command *cmd) -{ - if (! CONFIG_ATA_DMA) - return -1; - struct atadrive_s *adrive_g = container_of( - op->drive_g, struct atadrive_s, drive); - int ret = send_cmd(adrive_g, cmd); - if (ret) - return ret; - return ata_dma_transfer(op); -} - -// Read/write count blocks from a harddrive. -static int -ata_readwrite(struct disk_op_s *op, int iswrite) -{ - u64 lba = op->lba; - - int usepio = ata_try_dma(op, iswrite, DISK_SECTOR_SIZE); - - struct ata_pio_command cmd; - memset(&cmd, 0, sizeof(cmd)); - - if (op->count >= (1<<8) || lba + op->count >= (1<<28)) { - cmd.sector_count2 = op->count >> 8; - cmd.lba_low2 = lba >> 24; - cmd.lba_mid2 = lba >> 32; - cmd.lba_high2 = lba >> 40; - lba &= 0xffffff; - - if (usepio) - cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS_EXT - : ATA_CMD_READ_SECTORS_EXT); - else - cmd.command = (iswrite ? ATA_CMD_WRITE_DMA_EXT - : ATA_CMD_READ_DMA_EXT); - } else { - if (usepio) - cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS - : ATA_CMD_READ_SECTORS); - else - cmd.command = (iswrite ? ATA_CMD_WRITE_DMA - : ATA_CMD_READ_DMA); - } - - cmd.sector_count = op->count; - cmd.lba_low = lba; - cmd.lba_mid = lba >> 8; - cmd.lba_high = lba >> 16; - cmd.device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA; - - int ret; - if (usepio) - ret = ata_pio_cmd_data(op, iswrite, &cmd); - else - ret = ata_dma_cmd_data(op, &cmd); - if (ret) - return DISK_RET_EBADTRACK; - return DISK_RET_SUCCESS; -} - -// 16bit command demuxer for ATA harddrives. -int -process_ata_op(struct disk_op_s *op) -{ - if (!CONFIG_ATA) - return 0; - - struct atadrive_s *adrive_g = container_of( - op->drive_g, struct atadrive_s, drive); - switch (op->command) { - case CMD_READ: - return ata_readwrite(op, 0); - case CMD_WRITE: - return ata_readwrite(op, 1); - case CMD_RESET: - ata_reset(adrive_g); - return DISK_RET_SUCCESS; - case CMD_ISREADY: - return isready(adrive_g); - case CMD_FORMAT: - case CMD_VERIFY: - case CMD_SEEK: - return DISK_RET_SUCCESS; - default: - op->count = 0; - return DISK_RET_EPARAM; - } -} - - -/**************************************************************** - * ATAPI functions - ****************************************************************/ - -#define CDROM_CDB_SIZE 12 - -// Low-level atapi command transmit function. -int -atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - if (! CONFIG_ATA) - return 0; - - struct atadrive_s *adrive_g = container_of( - op->drive_g, struct atadrive_s, drive); - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); - - struct ata_pio_command cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.lba_mid = blocksize; - cmd.lba_high = blocksize >> 8; - cmd.command = ATA_CMD_PACKET; - - // Disable interrupts - outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); - - int ret = send_cmd(adrive_g, &cmd); - if (ret) - goto fail; - ret = ata_wait_data(iobase1); - if (ret) - goto fail; - - // Send command to device - outsw_fl(iobase1, MAKE_FLATPTR(GET_SEG(SS), cdbcmd), CDROM_CDB_SIZE / 2); - - int status = pause_await_not_bsy(iobase1, iobase2); - if (status < 0) { - ret = status; - goto fail; - } - - if (status & ATA_CB_STAT_ERR) { - u8 err = inb(iobase1 + ATA_CB_ERR); - // skip "Not Ready" - if (err != 0x20) - dprintf(6, "send_atapi_cmd : read error (status=%02x err=%02x)\n" - , status, err); - ret = -2; - goto fail; - } - if (blocksize) { - if (!(status & ATA_CB_STAT_DRQ)) { - dprintf(6, "send_atapi_cmd : DRQ not set (status %02x)\n", status); - ret = -3; - goto fail; - } - - ret = ata_pio_transfer(op, 0, blocksize); - } - -fail: - // Enable interrupts - outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); - if (ret) - return DISK_RET_EBADTRACK; - return DISK_RET_SUCCESS; -} - - -/**************************************************************** - * ATA detect and init - ****************************************************************/ - -// Send an identify device or identify device packet command. -static int -send_ata_identity(struct atadrive_s *adrive_g, u16 *buffer, int command) -{ - memset(buffer, 0, DISK_SECTOR_SIZE); - - struct disk_op_s dop; - memset(&dop, 0, sizeof(dop)); - dop.drive_g = &adrive_g->drive; - dop.count = 1; - dop.lba = 1; - dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer); - - struct ata_pio_command cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = command; - - return ata_pio_cmd_data(&dop, 0, &cmd); -} - -// Extract the ATA/ATAPI version info. -int -ata_extract_version(u16 *buffer) -{ - // Extract ATA/ATAPI version. - u16 ataversion = buffer[80]; - u8 version; - for (version=15; version>0; version--) - if (ataversion & (1<chan_gf = dummy->chan_gf; - adrive_g->slave = dummy->slave; - adrive_g->drive.cntl_id = adrive_g->chan_gf->chanid * 2 + dummy->slave; - adrive_g->drive.removable = (buffer[0] & 0x80) ? 1 : 0; - return adrive_g; -} - -// Detect if the given drive is an atapi - initialize it if so. -static struct atadrive_s * -init_drive_atapi(struct atadrive_s *dummy, u16 *buffer) -{ - // Send an IDENTIFY_DEVICE_PACKET command to device - int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_PACKET_DEVICE); - if (ret) - return NULL; - - // Success - setup as ATAPI. - struct atadrive_s *adrive_g = init_atadrive(dummy, buffer); - if (!adrive_g) - return NULL; - adrive_g->drive.type = DTYPE_ATA_ATAPI; - adrive_g->drive.blksize = CDROM_SECTOR_SIZE; - adrive_g->drive.sectors = (u64)-1; - u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05; - char model[MAXMODEL+1]; - char *desc = znprintf(MAXDESCSIZE - , "DVD/CD [ata%d-%d: %s ATAPI-%d %s]" - , adrive_g->chan_gf->chanid, adrive_g->slave - , ata_extract_model(model, MAXMODEL, buffer) - , ata_extract_version(buffer) - , (iscd ? "DVD/CD" : "Device")); - dprintf(1, "%s\n", desc); - - // fill cdidmap - if (iscd) { - int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_tmp, - adrive_g->chan_gf->chanid, - adrive_g->slave); - boot_add_cd(&adrive_g->drive, desc, prio); - } - - return adrive_g; -} - -// Detect if the given drive is a regular ata drive - initialize it if so. -static struct atadrive_s * -init_drive_ata(struct atadrive_s *dummy, u16 *buffer) -{ - // Send an IDENTIFY_DEVICE command to device - int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_DEVICE); - if (ret) - return NULL; - - // Success - setup as ATA. - struct atadrive_s *adrive_g = init_atadrive(dummy, buffer); - if (!adrive_g) - return NULL; - adrive_g->drive.type = DTYPE_ATA; - adrive_g->drive.blksize = DISK_SECTOR_SIZE; - - adrive_g->drive.pchs.cylinders = buffer[1]; - adrive_g->drive.pchs.heads = buffer[3]; - adrive_g->drive.pchs.spt = buffer[6]; - - u64 sectors; - if (buffer[83] & (1 << 10)) // word 83 - lba48 support - sectors = *(u64*)&buffer[100]; // word 100-103 - else - sectors = *(u32*)&buffer[60]; // word 60 and word 61 - adrive_g->drive.sectors = sectors; - u64 adjsize = sectors >> 11; - char adjprefix = 'M'; - if (adjsize >= (1 << 16)) { - adjsize >>= 10; - adjprefix = 'G'; - } - char model[MAXMODEL+1]; - char *desc = znprintf(MAXDESCSIZE - , "ata%d-%d: %s ATA-%d Hard-Disk (%u %ciBytes)" - , adrive_g->chan_gf->chanid, adrive_g->slave - , ata_extract_model(model, MAXMODEL, buffer) - , ata_extract_version(buffer) - , (u32)adjsize, adjprefix); - dprintf(1, "%s\n", desc); - - int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_tmp, - adrive_g->chan_gf->chanid, - adrive_g->slave); - // Register with bcv system. - boot_add_hd(&adrive_g->drive, desc, prio); - - return adrive_g; -} - -static u64 SpinupEnd; - -// Wait for non-busy status and check for "floating bus" condition. -static int -powerup_await_non_bsy(u16 base) -{ - u8 orstatus = 0; - u8 status; - for (;;) { - status = inb(base+ATA_CB_STAT); - if (!(status & ATA_CB_STAT_BSY)) - break; - orstatus |= status; - if (orstatus == 0xff) { - dprintf(4, "powerup IDE floating\n"); - return orstatus; - } - if (check_tsc(SpinupEnd)) { - warn_timeout(); - return -1; - } - yield(); - } - dprintf(6, "powerup iobase=%x st=%x\n", base, status); - return status; -} - -// Detect any drives attached to a given controller. -static void -ata_detect(void *data) -{ - struct ata_channel_s *chan_gf = data; - struct atadrive_s dummy; - memset(&dummy, 0, sizeof(dummy)); - dummy.chan_gf = chan_gf; - // Device detection - int didreset = 0; - u8 slave; - for (slave=0; slave<=1; slave++) { - // Wait for not-bsy. - u16 iobase1 = chan_gf->iobase1; - int status = powerup_await_non_bsy(iobase1); - if (status < 0) - continue; - u8 newdh = slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0; - outb(newdh, iobase1+ATA_CB_DH); - ndelay(400); - status = powerup_await_non_bsy(iobase1); - if (status < 0) - continue; - - // Check if ioport registers look valid. - outb(newdh, iobase1+ATA_CB_DH); - u8 dh = inb(iobase1+ATA_CB_DH); - outb(0x55, iobase1+ATA_CB_SC); - outb(0xaa, iobase1+ATA_CB_SN); - u8 sc = inb(iobase1+ATA_CB_SC); - u8 sn = inb(iobase1+ATA_CB_SN); - dprintf(6, "ata_detect ata%d-%d: sc=%x sn=%x dh=%x\n" - , chan_gf->chanid, slave, sc, sn, dh); - if (sc != 0x55 || sn != 0xaa || dh != newdh) - continue; - - // Prepare new drive. - dummy.slave = slave; - - // reset the channel - if (!didreset) { - ata_reset(&dummy); - didreset = 1; - } - - // check for ATAPI - u16 buffer[256]; - struct atadrive_s *adrive_g = init_drive_atapi(&dummy, buffer); - if (!adrive_g) { - // Didn't find an ATAPI drive - look for ATA drive. - u8 st = inb(iobase1+ATA_CB_STAT); - if (!st) - // Status not set - can't be a valid drive. - continue; - - // Wait for RDY. - int ret = await_rdy(iobase1); - if (ret < 0) - continue; - - // check for ATA. - adrive_g = init_drive_ata(&dummy, buffer); - if (!adrive_g) - // No ATA drive found - continue; - } - - u16 resetresult = buffer[93]; - dprintf(6, "ata_detect resetresult=%04x\n", resetresult); - if (!slave && (resetresult & 0xdf61) == 0x4041) - // resetresult looks valid and device 0 is responding to - // device 1 requests - device 1 must not be present - skip - // detection. - break; - } -} - -// Initialize an ata controller and detect its drives. -static void -init_controller(struct pci_device *pci, int irq - , u32 port1, u32 port2, u32 master) -{ - static int chanid = 0; - struct ata_channel_s *chan_gf = malloc_fseg(sizeof(*chan_gf)); - if (!chan_gf) { - warn_noalloc(); - return; - } - chan_gf->chanid = chanid++; - chan_gf->irq = irq; - chan_gf->pci_bdf = pci ? pci->bdf : -1; - chan_gf->pci_tmp = pci; - chan_gf->iobase1 = port1; - chan_gf->iobase2 = port2; - chan_gf->iomaster = master; - dprintf(1, "ATA controller %d at %x/%x/%x (irq %d dev %x)\n" - , chanid, port1, port2, master, irq, chan_gf->pci_bdf); - run_thread(ata_detect, chan_gf); -} - -#define IRQ_ATA1 14 -#define IRQ_ATA2 15 - -// Handle controllers on an ATA PCI device. -static void -init_pciata(struct pci_device *pci, u8 prog_if) -{ - pci->have_driver = 1; - u16 bdf = pci->bdf; - u8 pciirq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); - int master = 0; - if (CONFIG_ATA_DMA && prog_if & 0x80) { - // Check for bus-mastering. - u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_4); - if (bar & PCI_BASE_ADDRESS_SPACE_IO) { - master = bar & PCI_BASE_ADDRESS_IO_MASK; - pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); - } - } - - u32 port1, port2, irq; - if (prog_if & 1) { - port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_0) - & PCI_BASE_ADDRESS_IO_MASK); - port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_1) - & PCI_BASE_ADDRESS_IO_MASK); - irq = pciirq; - } else { - port1 = PORT_ATA1_CMD_BASE; - port2 = PORT_ATA1_CTRL_BASE; - irq = IRQ_ATA1; - } - init_controller(pci, irq, port1, port2, master); - - if (prog_if & 4) { - port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_2) - & PCI_BASE_ADDRESS_IO_MASK); - port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_3) - & PCI_BASE_ADDRESS_IO_MASK); - irq = pciirq; - } else { - port1 = PORT_ATA2_CMD_BASE; - port2 = PORT_ATA2_CTRL_BASE; - irq = IRQ_ATA2; - } - init_controller(pci, irq, port1, port2, master ? master + 8 : 0); -} - -static void -found_genericata(struct pci_device *pci, void *arg) -{ - init_pciata(pci, pci->prog_if); -} - -static void -found_compatibleahci(struct pci_device *pci, void *arg) -{ - if (CONFIG_AHCI) - // Already handled directly via native ahci interface. - return; - init_pciata(pci, 0x8f); -} - -static const struct pci_device_id pci_ata_tbl[] = { - PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE - , found_genericata), - PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4391, found_compatibleahci), - PCI_DEVICE_END, -}; - -// Locate and init ata controllers. -static void -ata_init(void) -{ - if (!CONFIG_COREBOOT && !PCIDevices) { - // No PCI devices found - probably a QEMU "-M isapc" machine. - // Try using ISA ports for ATA controllers. - init_controller(NULL, IRQ_ATA1 - , PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE, 0); - init_controller(NULL, IRQ_ATA2 - , PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE, 0); - return; - } - - // Scan PCI bus for ATA adapters - struct pci_device *pci; - foreachpci(pci) { - pci_init_device(pci_ata_tbl, pci, NULL); - } -} - -void -ata_setup(void) -{ - ASSERT32FLAT(); - if (!CONFIG_ATA) - return; - - dprintf(3, "init hard drives\n"); - - SpinupEnd = calc_future_tsc(IDE_TIMEOUT); - ata_init(); - - SET_BDA(disk_control_byte, 0xc0); - - enable_hwirq(14, FUNC16(entry_76)); -} diff -Nru seabios-1.7.1/src/ata.h seabios-1.7.4/src/ata.h --- seabios-1.7.1/src/ata.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ata.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -#ifndef __ATA_H -#define __ATA_H - -#include "types.h" // u8 -#include "config.h" // CONFIG_MAX_ATA_INTERFACES -#include "disk.h" // struct drive_s - -struct ata_channel_s { - u16 iobase1; - u16 iobase2; - u16 iomaster; - u8 irq; - u8 chanid; - int pci_bdf; - struct pci_device *pci_tmp; -}; - -struct atadrive_s { - struct drive_s drive; - struct ata_channel_s *chan_gf; - u8 slave; -}; - -// ata.c -char *ata_extract_model(char *model, u32 size, u16 *buffer); -int ata_extract_version(u16 *buffer); -int cdrom_read(struct disk_op_s *op); -int atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); -void ata_setup(void); -int process_ata_op(struct disk_op_s *op); - -// Global defines -- ATA register and register bits. -// command block & control block regs -#define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0 -#define ATA_CB_ERR 1 // error in pio_base_addr1+1 -#define ATA_CB_FR 1 // feature reg out pio_base_addr1+1 -#define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2 -#define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3 -#define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4 -#define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5 -#define ATA_CB_DH 6 // device head in/out pio_base_addr1+6 -#define ATA_CB_STAT 7 // primary status in pio_base_addr1+7 -#define ATA_CB_CMD 7 // command out pio_base_addr1+7 - -#define ATA_CB_ASTAT 2 // alternate status in pio_base_addr2+2 -#define ATA_CB_DC 2 // device control out pio_base_addr2+2 -#define ATA_CB_DA 3 // device address in pio_base_addr2+3 - -#define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC -#define ATA_CB_ER_BBK 0x80 // ATA bad block -#define ATA_CB_ER_UNC 0x40 // ATA uncorrected error -#define ATA_CB_ER_MC 0x20 // ATA media change -#define ATA_CB_ER_IDNF 0x10 // ATA id not found -#define ATA_CB_ER_MCR 0x08 // ATA media change request -#define ATA_CB_ER_ABRT 0x04 // ATA command aborted -#define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found -#define ATA_CB_ER_NDAM 0x01 // ATA address mark not found - -#define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask) -#define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request -#define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort -#define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media -#define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication - -// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC) -#define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask) -#define ATA_CB_SC_P_REL 0x04 // ATAPI release -#define ATA_CB_SC_P_IO 0x02 // ATAPI I/O -#define ATA_CB_SC_P_CD 0x01 // ATAPI C/D - -// bits 7-4 of the device/head (CB_DH) reg -#define ATA_CB_DH_DEV0 0xa0 // select device 0 -#define ATA_CB_DH_DEV1 0xb0 // select device 1 -#define ATA_CB_DH_LBA 0x40 // use LBA - -// status reg (CB_STAT and CB_ASTAT) bits -#define ATA_CB_STAT_BSY 0x80 // busy -#define ATA_CB_STAT_RDY 0x40 // ready -#define ATA_CB_STAT_DF 0x20 // device fault -#define ATA_CB_STAT_WFT 0x20 // write fault (old name) -#define ATA_CB_STAT_SKC 0x10 // seek complete -#define ATA_CB_STAT_SERV 0x10 // service -#define ATA_CB_STAT_DRQ 0x08 // data request -#define ATA_CB_STAT_CORR 0x04 // corrected -#define ATA_CB_STAT_IDX 0x02 // index -#define ATA_CB_STAT_ERR 0x01 // error (ATA) -#define ATA_CB_STAT_CHK 0x01 // check (ATAPI) - -// device control reg (CB_DC) bits -#define ATA_CB_DC_HD15 0x08 // bit should always be set to one -#define ATA_CB_DC_SRST 0x04 // soft reset -#define ATA_CB_DC_NIEN 0x02 // disable interrupts - -// Most mandtory and optional ATA commands (from ATA-3), -#define ATA_CMD_NOP 0x00 -#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03 -#define ATA_CMD_DEVICE_RESET 0x08 -#define ATA_CMD_RECALIBRATE 0x10 -#define ATA_CMD_READ_SECTORS 0x20 -#define ATA_CMD_READ_SECTORS_EXT 0x24 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_READ_DMA_QUEUED_EXT 0x26 -#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT 0x27 -#define ATA_CMD_READ_MULTIPLE_EXT 0x29 -#define ATA_CMD_READ_LOG_EXT 0x2F -#define ATA_CMD_WRITE_SECTORS 0x30 -#define ATA_CMD_WRITE_SECTORS_EXT 0x34 -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_WRITE_DMA_QUEUED_EXT 0x36 -#define ATA_CMD_SET_MAX_ADDRESS_EXT 0x37 -#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38 -#define ATA_CMD_WRITE_MULTIPLE_EXT 0x39 -#define ATA_CMD_WRITE_VERIFY 0x3C -#define ATA_CMD_WRITE_LOG_EXT 0x3F -#define ATA_CMD_READ_VERIFY_SECTORS 0x40 -#define ATA_CMD_READ_VERIFY_SECTORS_EXT 0x42 -#define ATA_CMD_FORMAT_TRACK 0x50 -#define ATA_CMD_SEEK 0x70 -#define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87 -#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 -#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 -#define ATA_CMD_STANDBY_IMMEDIATE2 0x94 -#define ATA_CMD_IDLE_IMMEDIATE2 0x95 -#define ATA_CMD_STANDBY2 0x96 -#define ATA_CMD_IDLE2 0x97 -#define ATA_CMD_CHECK_POWER_MODE2 0x98 -#define ATA_CMD_SLEEP2 0x99 -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1 -#define ATA_CMD_CFA_ERASE_SECTORS 0xC0 -#define ATA_CMD_READ_MULTIPLE 0xC4 -#define ATA_CMD_WRITE_MULTIPLE 0xC5 -#define ATA_CMD_SET_MULTIPLE_MODE 0xC6 -#define ATA_CMD_READ_DMA_QUEUED 0xC7 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_QUEUED 0xCC -#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD -#define ATA_CMD_STANDBY_IMMEDIATE 0xE0 -#define ATA_CMD_IDLE_IMMEDIATE 0xE1 -#define ATA_CMD_STANDBY 0xE2 -#define ATA_CMD_IDLE 0xE3 -#define ATA_CMD_READ_BUFFER 0xE4 -#define ATA_CMD_CHECK_POWER_MODE 0xE5 -#define ATA_CMD_SLEEP 0xE6 -#define ATA_CMD_FLUSH_CACHE 0xE7 -#define ATA_CMD_WRITE_BUFFER 0xE8 -#define ATA_CMD_IDENTIFY_DEVICE 0xEC -#define ATA_CMD_SET_FEATURES 0xEF -#define ATA_CMD_READ_NATIVE_MAX_ADDRESS 0xF8 -#define ATA_CMD_SET_MAX 0xF9 - -#endif // ata.h diff -Nru seabios-1.7.1/src/biostables.c seabios-1.7.4/src/biostables.c --- seabios-1.7.1/src/biostables.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/biostables.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -// Coreboot interface support. -// -// Copyright (C) 2008,2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "config.h" // CONFIG_* -#include "util.h" // dprintf -#include "pci.h" // struct pir_header -#include "acpi.h" // struct rsdp_descriptor -#include "mptable.h" // MPTABLE_SIGNATURE -#include "smbios.h" // struct smbios_entry_point - -static void -copy_pir(void *pos) -{ - struct pir_header *p = pos; - if (p->signature != PIR_SIGNATURE) - return; - if (PirAddr) - return; - if (p->size < sizeof(*p)) - return; - if (checksum(pos, p->size) != 0) - return; - void *newpos = malloc_fseg(p->size); - if (!newpos) { - warn_noalloc(); - return; - } - dprintf(1, "Copying PIR from %p to %p\n", pos, newpos); - memcpy(newpos, pos, p->size); - PirAddr = newpos; -} - -static void -copy_mptable(void *pos) -{ - struct mptable_floating_s *p = pos; - if (p->signature != MPTABLE_SIGNATURE) - return; - if (!p->physaddr) - return; - if (checksum(pos, sizeof(*p)) != 0) - return; - u32 length = p->length * 16; - u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length; - struct mptable_floating_s *newpos = malloc_fseg(length + mpclength); - if (!newpos) { - warn_noalloc(); - return; - } - dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos); - memcpy(newpos, pos, length); - newpos->physaddr = (u32)newpos + length; - newpos->checksum -= checksum(newpos, sizeof(*newpos)); - memcpy((void*)newpos + length, (void*)p->physaddr, mpclength); -} - -static void -copy_acpi_rsdp(void *pos) -{ - if (RsdpAddr) - return; - struct rsdp_descriptor *p = pos; - if (p->signature != RSDP_SIGNATURE) - return; - u32 length = 20; - if (checksum(pos, length) != 0) - return; - if (p->revision > 1) { - length = p->length; - if (checksum(pos, length) != 0) - return; - } - void *newpos = malloc_fseg(length); - if (!newpos) { - warn_noalloc(); - return; - } - dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos); - memcpy(newpos, pos, length); - RsdpAddr = newpos; -} - -static void -copy_smbios(void *pos) -{ - if (SMBiosAddr) - return; - struct smbios_entry_point *p = pos; - if (memcmp(p->anchor_string, "_SM_", 4)) - return; - if (checksum(pos, 0x10) != 0) - return; - if (memcmp(p->intermediate_anchor_string, "_DMI_", 5)) - return; - if (checksum(pos+0x10, p->length-0x10) != 0) - return; - struct smbios_entry_point *newpos = malloc_fseg(p->length); - if (!newpos) { - warn_noalloc(); - return; - } - dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos); - memcpy(newpos, pos, p->length); - SMBiosAddr = newpos; -} - -void -copy_table(void *pos) -{ - copy_pir(pos); - copy_mptable(pos); - copy_acpi_rsdp(pos); - copy_smbios(pos); -} diff -Nru seabios-1.7.1/src/biosvar.h seabios-1.7.4/src/biosvar.h --- seabios-1.7.1/src/biosvar.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/biosvar.h 2013-12-23 15:40:06.000000000 +0000 @@ -1,24 +1,20 @@ -// Variable layouts of bios. +// Memory access to BIOS variables. // -// Copyright (C) 2008-2010 Kevin O'Connor +// Copyright (C) 2008-2013 Kevin O'Connor // // This file may be distributed under the terms of the GNU LGPLv3 license. #ifndef __BIOSVAR_H #define __BIOSVAR_H -#include "types.h" // u8 -#include "farptr.h" // GET_FARVAR #include "config.h" // SEG_BDA +#include "farptr.h" // GET_FARVAR +#include "std/bda.h" // struct bios_data_area_s /**************************************************************** * Interupt vector table ****************************************************************/ -struct rmode_IVT { - struct segoff_s ivec[256]; -}; - #define GET_IVT(vector) \ GET_FARVAR(SEG_IVT, ((struct rmode_IVT *)0)->ivec[vector]) #define SET_IVT(vector, segoff) \ @@ -35,103 +31,6 @@ * Bios Data Area (BDA) ****************************************************************/ -struct bios_data_area_s { - // 40:00 - u16 port_com[4]; - u16 port_lpt[3]; - u16 ebda_seg; - // 40:10 - u16 equipment_list_flags; - u8 pad1; - u16 mem_size_kb; - u8 pad2; - u8 ps2_ctrl_flag; - u8 kbd_flag0; - u8 kbd_flag1; - u8 alt_keypad; - u16 kbd_buf_head; - u16 kbd_buf_tail; - // 40:1e - u8 kbd_buf[32]; - u8 floppy_recalibration_status; - u8 floppy_motor_status; - // 40:40 - u8 floppy_motor_counter; - u8 floppy_last_status; - u8 floppy_return_status[7]; - u8 video_mode; - u16 video_cols; - u16 video_pagesize; - u16 video_pagestart; - // 40:50 - u16 cursor_pos[8]; - // 40:60 - u16 cursor_type; - u8 video_page; - u16 crtc_address; - u8 video_msr; - u8 video_pal; - struct segoff_s jump; - u8 other_6b; - u32 timer_counter; - // 40:70 - u8 timer_rollover; - u8 break_flag; - u16 soft_reset_flag; - u8 disk_last_status; - u8 hdcount; - u8 disk_control_byte; - u8 port_disk; - u8 lpt_timeout[4]; - u8 com_timeout[4]; - // 40:80 - u16 kbd_buf_start_offset; - u16 kbd_buf_end_offset; - u8 video_rows; - u16 char_height; - u8 video_ctl; - u8 video_switches; - u8 modeset_ctl; - u8 dcc_index; - u8 floppy_last_data_rate; - u8 disk_status_controller; - u8 disk_error_controller; - u8 disk_interrupt_flag; - u8 floppy_harddisk_info; - // 40:90 - u8 floppy_media_state[4]; - u8 floppy_track[2]; - u8 kbd_flag2; - u8 kbd_led; - struct segoff_s user_wait_complete_flag; - u32 user_wait_timeout; - // 40:A0 - u8 rtc_wait_flag; - u8 other_a1[7]; - struct segoff_s video_savetable; - u8 other_ac[4]; - // 40:B0 - u8 other_b0[9]; - u8 vbe_flag; - u16 vbe_mode; - u8 other_bc[4]; - // 40:C0 - u8 other_c0[4*16]; -} PACKED; - -// BDA floppy_recalibration_status bitdefs -#define FRS_TIMEOUT (1<<7) - -// BDA rtc_wait_flag bitdefs -#define RWS_WAIT_PENDING (1<<0) -#define RWS_WAIT_ELAPSED (1<<7) - -// BDA floppy_media_state bitdefs -#define FMS_DRIVE_STATE_MASK (0x07) -#define FMS_MEDIA_DRIVE_ESTABLISHED (1<<4) -#define FMS_DOUBLE_STEPPING (1<<5) -#define FMS_DATA_RATE_MASK (0xc0) - // Accessor functions #define GET_BDA(var) \ GET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var) @@ -149,40 +48,6 @@ * Extended Bios Data Area (EBDA) ****************************************************************/ -struct fdpt_s { - u16 cylinders; - u8 heads; - u8 a0h_signature; - u8 phys_sectors; - u16 precompensation; - u8 reserved; - u8 drive_control_byte; - u16 phys_cylinders; - u8 phys_heads; - u16 landing_zone; - u8 sectors; - u8 checksum; -} PACKED; - -struct extended_bios_data_area_s { - u8 size; - u8 reserved1[0x21]; - struct segoff_s far_call_pointer; - u8 mouse_flag1; - u8 mouse_flag2; - u8 mouse_data[0x08]; - // 0x30 - u8 other1[0x0d]; - - // 0x3d - struct fdpt_s fdpt[2]; - - // 0x5d - u8 other2[0xC4]; - - // 0x121 - Begin custom storage. -} PACKED; - // The initial size and location of EBDA #define EBDA_SIZE_START \ DIV_ROUND_UP(sizeof(struct extended_bios_data_area_s), 1024) @@ -234,10 +99,6 @@ #define GET_GLOBAL(var) \ GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var) \ + get_global_offset())) -#define SET_GLOBAL(var, val) do { \ - ASSERT32FLAT(); \ - (var) = (val); \ - } while (0) #if MODESEGMENT #define GLOBALFLAT2GLOBAL(var) ((typeof(var))((void*)(var) - BUILD_BIOS_ADDR)) #else @@ -251,13 +112,13 @@ * "Low" memory variables ****************************************************************/ -extern u8 _datalow_seg, datalow_base[]; -#define SEG_LOW ((u32)&_datalow_seg) +extern u8 _zonelow_seg, zonelow_base[]; +#define SEG_LOW ((u32)&_zonelow_seg) #if MODESEGMENT #define GET_LOW(var) GET_FARVAR(SEG_LOW, (var)) #define SET_LOW(var, val) SET_FARVAR(SEG_LOW, (var), (val)) -#define LOWFLAT2LOW(var) ((typeof(var))((void*)(var) - (u32)datalow_base)) +#define LOWFLAT2LOW(var) ((typeof(var))((void*)(var) - (u32)zonelow_base)) #else #define GET_LOW(var) (var) #define SET_LOW(var, val) do { (var) = (val); } while (0) @@ -266,19 +127,4 @@ #define GET_LOWFLAT(var) GET_LOW(*LOWFLAT2LOW(&(var))) #define SET_LOWFLAT(var, val) SET_LOW(*LOWFLAT2LOW(&(var)), (val)) - -/**************************************************************** - * Bios Config Table - ****************************************************************/ - -struct bios_config_table_s { - u16 size; - u8 model; - u8 submodel; - u8 biosrev; - u8 feature1, feature2, feature3, feature4, feature5; -} PACKED; - -extern struct bios_config_table_s BIOS_CONFIG_TABLE __aligned(1); - #endif // __BIOSVAR_H diff -Nru seabios-1.7.1/src/block.c seabios-1.7.4/src/block.c --- seabios-1.7.1/src/block.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/block.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,19 +5,25 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "disk.h" // struct ata_s #include "biosvar.h" // GET_GLOBAL -#include "cmos.h" // inb_cmos -#include "util.h" // dprintf -#include "ata.h" // process_ata_op -#include "ahci.h" // process_ahci_op -#include "virtio-blk.h" // process_virtio_blk_op -#include "blockcmd.h" // cdb_* +#include "block.h" // process_op +#include "bregs.h" // struct bregs +#include "hw/ata.h" // process_ata_op +#include "hw/ahci.h" // process_ahci_op +#include "hw/blockcmd.h" // cdb_* +#include "hw/rtc.h" // rtc_read +#include "hw/virtio-blk.h" // process_virtio_blk_op +#include "malloc.h" // malloc_low +#include "output.h" // dprintf +#include "stacks.h" // stack_hop +#include "std/disk.h" // struct dpte_s +#include "string.h" // checksum +#include "util.h" // process_floppy_op -u8 FloppyCount VAR16VISIBLE; +u8 FloppyCount VARFSEG; u8 CDCount; -struct drive_s *IDMap[3][CONFIG_MAX_EXTDRIVE] VAR16VISIBLE; -u8 *bounce_buf_fl VAR16VISIBLE; +struct drive_s *IDMap[3][BUILD_MAX_EXTDRIVE] VARFSEG; +u8 *bounce_buf_fl VARFSEG; struct dpte_s DefaultDPTE VARLOW; struct drive_s * @@ -25,22 +31,20 @@ { if (extdriveoffset >= ARRAY_SIZE(IDMap[0])) return NULL; - struct drive_s *drive_gf = GET_GLOBAL(IDMap[exttype][extdriveoffset]); - if (!drive_gf) - return NULL; - return GLOBALFLAT2GLOBAL(drive_gf); + return GET_GLOBAL(IDMap[exttype][extdriveoffset]); } -int getDriveId(u8 exttype, struct drive_s *drive_g) +int getDriveId(u8 exttype, struct drive_s *drive) { + ASSERT32FLAT(); int i; for (i = 0; i < ARRAY_SIZE(IDMap[0]); i++) - if (getDrive(exttype, i) == drive_g) + if (getDrive(exttype, i) == drive) return i; return -1; } -int bounce_buf_init(void) +int create_bounce_buf(void) { if (bounce_buf_fl) return 0; @@ -59,24 +63,24 @@ ****************************************************************/ static u8 -get_translation(struct drive_s *drive_g) +get_translation(struct drive_s *drive) { - u8 type = GET_GLOBAL(drive_g->type); - if (! CONFIG_COREBOOT && type == DTYPE_ATA) { + u8 type = drive->type; + if (CONFIG_QEMU && type == DTYPE_ATA) { // Emulators pass in the translation info via nvram. - u8 ataid = GET_GLOBAL(drive_g->cntl_id); + u8 ataid = drive->cntl_id; u8 channel = ataid / 2; - u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2); + u8 translation = rtc_read(CMOS_BIOS_DISKTRANSFLAG + channel/2); translation >>= 2 * (ataid % 4); translation &= 0x03; return translation; } // Otherwise use a heuristic to determine translation type. - u16 heads = GET_GLOBAL(drive_g->pchs.heads); - u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders); - u16 spt = GET_GLOBAL(drive_g->pchs.spt); - u64 sectors = GET_GLOBAL(drive_g->sectors); + u16 heads = drive->pchs.head; + u16 cylinders = drive->pchs.cylinder; + u16 spt = drive->pchs.sector; + u64 sectors = drive->sectors; u64 psectors = (u64)heads * cylinders * spt; if (!heads || !cylinders || !spt || psectors > sectors) // pchs doesn't look valid - use LBA. @@ -90,15 +94,15 @@ } static void -setup_translation(struct drive_s *drive_g) +setup_translation(struct drive_s *drive) { - u8 translation = get_translation(drive_g); - SET_GLOBAL(drive_g->translation, translation); + u8 translation = get_translation(drive); + drive->translation = translation; - u16 heads = GET_GLOBAL(drive_g->pchs.heads); - u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders); - u16 spt = GET_GLOBAL(drive_g->pchs.spt); - u64 sectors = GET_GLOBAL(drive_g->sectors); + u16 heads = drive->pchs.head ; + u16 cylinders = drive->pchs.cylinder; + u16 spt = drive->pchs.sector; + u64 sectors = drive->sectors; const char *desc = NULL; switch (translation) { @@ -155,15 +159,15 @@ if (cylinders > 1024) cylinders = 1024; dprintf(1, "drive %p: PCHS=%u/%d/%d translation=%s LCHS=%d/%d/%d s=%d\n" - , drive_g - , drive_g->pchs.cylinders, drive_g->pchs.heads, drive_g->pchs.spt + , drive + , drive->pchs.cylinder, drive->pchs.head, drive->pchs.sector , desc , cylinders, heads, spt , (u32)sectors); - SET_GLOBAL(drive_g->lchs.heads, heads); - SET_GLOBAL(drive_g->lchs.cylinders, cylinders); - SET_GLOBAL(drive_g->lchs.spt, spt); + drive->lchs.head = heads; + drive->lchs.cylinder = cylinders; + drive->lchs.sector = spt; } @@ -173,18 +177,18 @@ // Fill in Fixed Disk Parameter Table (located in ebda). static void -fill_fdpt(struct drive_s *drive_g, int hdid) +fill_fdpt(struct drive_s *drive, int hdid) { if (hdid > 1) return; - u16 nlc = GET_GLOBAL(drive_g->lchs.cylinders); - u16 nlh = GET_GLOBAL(drive_g->lchs.heads); - u16 nlspt = GET_GLOBAL(drive_g->lchs.spt); - - u16 npc = GET_GLOBAL(drive_g->pchs.cylinders); - u16 nph = GET_GLOBAL(drive_g->pchs.heads); - u16 npspt = GET_GLOBAL(drive_g->pchs.spt); + u16 nlc = drive->lchs.cylinder; + u16 nlh = drive->lchs.head; + u16 nls = drive->lchs.sector; + + u16 npc = drive->pchs.cylinder; + u16 nph = drive->pchs.head; + u16 nps = drive->pchs.sector; struct fdpt_s *fdpt = &get_ebda_ptr()->fdpt[hdid]; fdpt->precompensation = 0xffff; @@ -192,16 +196,16 @@ fdpt->landing_zone = npc; fdpt->cylinders = nlc; fdpt->heads = nlh; - fdpt->sectors = nlspt; + fdpt->sectors = nls; - if (nlc != npc || nlh != nph || nlspt != npspt) { + if (nlc != npc || nlh != nph || nls != nps) { // Logical mapping present - use extended structure. // complies with Phoenix style Translated Fixed Disk Parameter // Table (FDPT) fdpt->phys_cylinders = npc; fdpt->phys_heads = nph; - fdpt->phys_sectors = npspt; + fdpt->phys_sectors = nps; fdpt->a0h_signature = 0xa0; // Checksum structure. @@ -218,47 +222,49 @@ // Find spot to add a drive static void -add_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive_g) +add_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive) { if (*count >= ARRAY_SIZE(IDMap[0])) { warn_noalloc(); return; } - idmap[*count] = drive_g; + idmap[*count] = drive; *count = *count + 1; } // Map a hard drive void -map_hd_drive(struct drive_s *drive_g) +map_hd_drive(struct drive_s *drive) { ASSERT32FLAT(); struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0); int hdid = bda->hdcount; - dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdid); - add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive_g); + dprintf(3, "Mapping hd drive %p to %d\n", drive, hdid); + add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive); // Setup disk geometry translation. - setup_translation(drive_g); + setup_translation(drive); // Fill "fdpt" structure. - fill_fdpt(drive_g, hdid); + fill_fdpt(drive, hdid); } // Map a cd void -map_cd_drive(struct drive_s *drive_g) +map_cd_drive(struct drive_s *drive) { - dprintf(3, "Mapping cd drive %p\n", drive_g); - add_drive(IDMap[EXTTYPE_CD], &CDCount, drive_g); + ASSERT32FLAT(); + dprintf(3, "Mapping cd drive %p\n", drive); + add_drive(IDMap[EXTTYPE_CD], &CDCount, drive); } // Map a floppy void -map_floppy_drive(struct drive_s *drive_g) +map_floppy_drive(struct drive_s *drive) { - dprintf(3, "Mapping floppy drive %p\n", drive_g); - add_drive(IDMap[EXTTYPE_FLOPPY], &FloppyCount, drive_g); + ASSERT32FLAT(); + dprintf(3, "Mapping floppy drive %p\n", drive); + add_drive(IDMap[EXTTYPE_FLOPPY], &FloppyCount, drive); // Update equipment word bits for floppy if (FloppyCount == 1) { @@ -274,6 +280,36 @@ /**************************************************************** + * Return status functions + ****************************************************************/ + +void +__disk_ret(struct bregs *regs, u32 linecode, const char *fname) +{ + u8 code = linecode; + if (regs->dl < EXTSTART_HD) + SET_BDA(floppy_last_status, code); + else + SET_BDA(disk_last_status, code); + if (code) + __set_code_invalid(regs, linecode, fname); + else + set_code_success(regs); +} + +void +__disk_ret_unimplemented(struct bregs *regs, u32 linecode, const char *fname) +{ + u8 code = linecode; + if (regs->dl < EXTSTART_HD) + SET_BDA(floppy_last_status, code); + else + SET_BDA(disk_last_status, code); + __set_code_unimplemented(regs, linecode, fname); +} + + +/**************************************************************** * 16bit calling interface ****************************************************************/ @@ -297,7 +333,7 @@ } } -static int +int VISIBLE32FLAT process_atapi_op(struct disk_op_s *op) { switch (op->command) { @@ -314,7 +350,7 @@ process_op(struct disk_op_s *op) { ASSERT16(); - u8 type = GET_GLOBAL(op->drive_g->type); + u8 type = GET_GLOBALFLAT(op->drive_gf->type); switch (type) { case DTYPE_FLOPPY: return process_floppy_op(op); @@ -326,16 +362,23 @@ return process_cdemu_op(op); case DTYPE_VIRTIO_BLK: return process_virtio_blk_op(op); - case DTYPE_AHCI: - return process_ahci_op(op); + case DTYPE_AHCI: ; + extern void _cfunc32flat_process_ahci_op(void); + return call32(_cfunc32flat_process_ahci_op + , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM); case DTYPE_ATA_ATAPI: - case DTYPE_AHCI_ATAPI: return process_atapi_op(op); + case DTYPE_AHCI_ATAPI: ; + extern void _cfunc32flat_process_atapi_op(void); + return call32(_cfunc32flat_process_atapi_op + , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM); case DTYPE_USB: case DTYPE_UAS: case DTYPE_VIRTIO_SCSI: case DTYPE_LSI_SCSI: case DTYPE_ESP_SCSI: + case DTYPE_MEGASAS: + case DTYPE_PVSCSI: return process_scsi_op(op); default: op->count = 0; @@ -353,7 +396,7 @@ , sizeof(dop)); dprintf(DEBUG_HDL_13, "disk_op d=%p lba=%d buf=%p count=%d cmd=%d\n" - , dop.drive_g, (u32)dop.lba, dop.buf_fl + , dop.drive_gf, (u32)dop.lba, dop.buf_fl , dop.count, dop.command); int status = process_op(&dop); diff -Nru seabios-1.7.1/src/blockcmd.c seabios-1.7.4/src/blockcmd.c --- seabios-1.7.1/src/blockcmd.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/blockcmd.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,274 +0,0 @@ -// Support for several common scsi like command data block requests -// -// Copyright (C) 2010 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "biosvar.h" // GET_GLOBAL -#include "util.h" // htonl -#include "disk.h" // struct disk_op_s -#include "blockcmd.h" // struct cdb_request_sense -#include "ata.h" // atapi_cmd_data -#include "ahci.h" // atapi_cmd_data -#include "usb-msc.h" // usb_cmd_data -#include "usb-uas.h" // usb_cmd_data -#include "virtio-scsi.h" // virtio_scsi_cmd_data -#include "lsi-scsi.h" // lsi_scsi_cmd_data -#include "esp-scsi.h" // esp_scsi_cmd_data -#include "boot.h" // boot_add_hd - -// Route command to low-level handler. -static int -cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - u8 type = GET_GLOBAL(op->drive_g->type); - switch (type) { - case DTYPE_ATA_ATAPI: - return atapi_cmd_data(op, cdbcmd, blocksize); - case DTYPE_USB: - return usb_cmd_data(op, cdbcmd, blocksize); - case DTYPE_UAS: - return uas_cmd_data(op, cdbcmd, blocksize); - case DTYPE_AHCI_ATAPI: - return ahci_cmd_data(op, cdbcmd, blocksize); - case DTYPE_VIRTIO_SCSI: - return virtio_scsi_cmd_data(op, cdbcmd, blocksize); - case DTYPE_LSI_SCSI: - return lsi_scsi_cmd_data(op, cdbcmd, blocksize); - case DTYPE_ESP_SCSI: - return esp_scsi_cmd_data(op, cdbcmd, blocksize); - default: - op->count = 0; - return DISK_RET_EPARAM; - } -} - -// Determine if the command is a request to pull data from the device -int -cdb_is_read(u8 *cdbcmd, u16 blocksize) -{ - return blocksize && cdbcmd[0] != CDB_CMD_WRITE_10; -} - -int -scsi_is_ready(struct disk_op_s *op) -{ - dprintf(6, "scsi_is_ready (drive=%p)\n", op->drive_g); - - /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is - * reported by the device. If the device reports "IN PROGRESS", - * 30 seconds is added. */ - int in_progress = 0; - u64 end = calc_future_tsc(5000); - for (;;) { - if (check_tsc(end)) { - dprintf(1, "test unit ready failed\n"); - return -1; - } - - int ret = cdb_test_unit_ready(op); - if (!ret) - // Success - break; - - struct cdbres_request_sense sense; - ret = cdb_get_sense(op, &sense); - if (ret) - // Error - retry. - continue; - - // Sense succeeded. - if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */ - dprintf(1, "Device reports MEDIUM NOT PRESENT\n"); - return -1; - } - - if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) { - /* IN PROGRESS OF BECOMING READY */ - printf("Waiting for device to detect medium... "); - /* Allow 30 seconds more */ - end = calc_future_tsc(30000); - in_progress = 1; - } - } - return 0; -} - -// Validate drive, find block size / sector count, and register drive. -int -scsi_init_drive(struct drive_s *drive, const char *s, int prio) -{ - struct disk_op_s dop; - memset(&dop, 0, sizeof(dop)); - dop.drive_g = drive; - struct cdbres_inquiry data; - int ret = cdb_get_inquiry(&dop, &data); - if (ret) - return ret; - char vendor[sizeof(data.vendor)+1], product[sizeof(data.product)+1]; - char rev[sizeof(data.rev)+1]; - strtcpy(vendor, data.vendor, sizeof(vendor)); - nullTrailingSpace(vendor); - strtcpy(product, data.product, sizeof(product)); - nullTrailingSpace(product); - strtcpy(rev, data.rev, sizeof(rev)); - nullTrailingSpace(rev); - int pdt = data.pdt & 0x1f; - int removable = !!(data.removable & 0x80); - dprintf(1, "%s vendor='%s' product='%s' rev='%s' type=%d removable=%d\n" - , s, vendor, product, rev, pdt, removable); - drive->removable = removable; - - if (pdt == SCSI_TYPE_CDROM) { - drive->blksize = CDROM_SECTOR_SIZE; - drive->sectors = (u64)-1; - - char *desc = znprintf(MAXDESCSIZE, "DVD/CD [%s Drive %s %s %s]" - , s, vendor, product, rev); - boot_add_cd(drive, desc, prio); - return 0; - } - - ret = scsi_is_ready(&dop); - if (ret) { - dprintf(1, "scsi_is_ready returned %d\n", ret); - return ret; - } - - struct cdbres_read_capacity capdata; - ret = cdb_read_capacity(&dop, &capdata); - if (ret) - return ret; - - // READ CAPACITY returns the address of the last block. - // We do not bother with READ CAPACITY(16) because BIOS does not support - // 64-bit LBA anyway. - drive->blksize = ntohl(capdata.blksize); - if (drive->blksize != DISK_SECTOR_SIZE) { - dprintf(1, "%s: unsupported block size %d\n", s, drive->blksize); - return -1; - } - drive->sectors = (u64)ntohl(capdata.sectors) + 1; - dprintf(1, "%s blksize=%d sectors=%d\n" - , s, drive->blksize, (unsigned)drive->sectors); - - // We do not recover from USB stalls, so try to be safe and avoid - // sending the command if the (obsolete, but still provided by QEMU) - // fixed disk geometry page may not be supported. - // - // We could also send the command only to small disks (e.g. <504MiB) - // but some old USB keys only support a very small subset of SCSI which - // does not even include the MODE SENSE command! - // - if (! CONFIG_COREBOOT && memcmp(vendor, "QEMU", 5) == 0) { - struct cdbres_mode_sense_geom geomdata; - ret = cdb_mode_sense_geom(&dop, &geomdata); - if (ret == 0) { - u32 cylinders; - cylinders = geomdata.cyl[0] << 16; - cylinders |= geomdata.cyl[1] << 8; - cylinders |= geomdata.cyl[2]; - if (cylinders && geomdata.heads && - drive->sectors <= 0xFFFFFFFFULL && - ((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) { - drive->pchs.cylinders = cylinders; - drive->pchs.heads = geomdata.heads; - drive->pchs.spt = (u32)drive->sectors / (geomdata.heads * cylinders); - } - } - } - - char *desc = znprintf(MAXDESCSIZE, "%s Drive %s %s %s" - , s, vendor, product, rev); - boot_add_hd(drive, desc, prio); - return 0; -} - -int -cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data) -{ - struct cdb_request_sense cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = CDB_CMD_INQUIRY; - cmd.length = sizeof(*data); - op->count = 1; - op->buf_fl = data; - return cdb_cmd_data(op, &cmd, sizeof(*data)); -} - -// Request SENSE -int -cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data) -{ - struct cdb_request_sense cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = CDB_CMD_REQUEST_SENSE; - cmd.length = sizeof(*data); - op->count = 1; - op->buf_fl = data; - return cdb_cmd_data(op, &cmd, sizeof(*data)); -} - -// Test unit ready -int -cdb_test_unit_ready(struct disk_op_s *op) -{ - struct cdb_request_sense cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = CDB_CMD_TEST_UNIT_READY; - op->count = 0; - op->buf_fl = NULL; - return cdb_cmd_data(op, &cmd, 0); -} - -// Request capacity -int -cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data) -{ - struct cdb_read_capacity cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = CDB_CMD_READ_CAPACITY; - op->count = 1; - op->buf_fl = data; - return cdb_cmd_data(op, &cmd, sizeof(*data)); -} - -// Mode sense, geometry page. -int -cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data) -{ - struct cdb_mode_sense cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = CDB_CMD_MODE_SENSE; - cmd.flags = 8; /* DBD */ - cmd.page = MODE_PAGE_HD_GEOMETRY; - cmd.count = htons(sizeof(*data)); - op->count = 1; - op->buf_fl = data; - return cdb_cmd_data(op, &cmd, sizeof(*data)); -} - -// Read sectors. -int -cdb_read(struct disk_op_s *op) -{ - struct cdb_rwdata_10 cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = CDB_CMD_READ_10; - cmd.lba = htonl(op->lba); - cmd.count = htons(op->count); - return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize)); -} - -// Write sectors. -int -cdb_write(struct disk_op_s *op) -{ - struct cdb_rwdata_10 cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.command = CDB_CMD_WRITE_10; - cmd.lba = htonl(op->lba); - cmd.count = htons(op->count); - return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize)); -} diff -Nru seabios-1.7.1/src/blockcmd.h seabios-1.7.4/src/blockcmd.h --- seabios-1.7.1/src/blockcmd.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/blockcmd.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -// Definitions for SCSI style command data blocks. -#ifndef __BLOCKCMD_H -#define __BLOCKCMD_H - -#include "types.h" // u8 - -#define CDB_CMD_READ_10 0x28 -#define CDB_CMD_VERIFY_10 0x2f -#define CDB_CMD_WRITE_10 0x2a - -struct cdb_rwdata_10 { - u8 command; - u8 flags; - u32 lba; - u8 resreved_06; - u16 count; - u8 reserved_09; - u8 pad[6]; -} PACKED; - -#define CDB_CMD_READ_CAPACITY 0x25 - -struct cdb_read_capacity { - u8 command; - u8 flags; - u8 resreved_02[8]; - u8 pad[6]; -} PACKED; - -struct cdbres_read_capacity { - u32 sectors; - u32 blksize; -} PACKED; - -#define CDB_CMD_TEST_UNIT_READY 0x00 -#define CDB_CMD_INQUIRY 0x12 -#define CDB_CMD_REQUEST_SENSE 0x03 - -struct cdb_request_sense { - u8 command; - u8 flags; - u16 reserved_02; - u8 length; - u8 reserved_05; - u8 pad[10]; -} PACKED; - -struct cdbres_request_sense { - u8 errcode; - u8 segment; - u8 flags; - u32 info; - u8 additional; - u32 specific; - u8 asc; - u8 ascq; - u32 reserved_0e; -} PACKED; - -#define SCSI_TYPE_DISK 0x00 -#define SCSI_TYPE_CDROM 0x05 - -struct cdbres_inquiry { - u8 pdt; - u8 removable; - u8 reserved_02[2]; - u8 additional; - u8 reserved_05[3]; - char vendor[8]; - char product[16]; - char rev[4]; -} PACKED; - -#define CDB_CMD_MODE_SENSE 0x5A -#define MODE_PAGE_HD_GEOMETRY 0x04 - -struct cdb_mode_sense { - u8 command; - u8 flags; - u8 page; - u32 reserved_03; - u16 count; - u8 reserved_09; - u8 pad[6]; -} PACKED; - -struct cdbres_mode_sense_geom { - u8 unused_00[3]; - u8 read_only; - u32 unused_04; - u8 page; - u8 length; - u8 cyl[3]; - u8 heads; - u8 precomp[3]; - u8 reduced[3]; - u16 step_rate; - u8 landing[3]; - u16 rpm; -} PACKED; - -// blockcmd.c -int cdb_is_read(u8 *cdbcmd, u16 blocksize); -struct disk_op_s; -int cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data); -int cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data); -int cdb_test_unit_ready(struct disk_op_s *op); -int cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data); -int cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data); -int cdb_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data); -int cdb_read(struct disk_op_s *op); -int cdb_write(struct disk_op_s *op); - -int scsi_is_ready(struct disk_op_s *op); -struct drive_s; -int scsi_init_drive(struct drive_s *drive, const char *s, int prio); - -#endif // blockcmd.h diff -Nru seabios-1.7.1/src/block.h seabios-1.7.4/src/block.h --- seabios-1.7.1/src/block.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/block.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,130 @@ +#ifndef __BLOCK_H +#define __BLOCK_H + +#include "types.h" // u32 + + +/**************************************************************** + * Disk command request + ****************************************************************/ + +struct disk_op_s { + u64 lba; + void *buf_fl; + struct drive_s *drive_gf; + u16 count; + u8 command; +}; + +#define CMD_RESET 0x00 +#define CMD_READ 0x02 +#define CMD_WRITE 0x03 +#define CMD_VERIFY 0x04 +#define CMD_FORMAT 0x05 +#define CMD_SEEK 0x07 +#define CMD_ISREADY 0x10 + + +/**************************************************************** + * Global storage + ****************************************************************/ + +struct chs_s { + u16 head; + u16 cylinder; + u16 sector; + u16 pad; +}; + +// ElTorito Device Emulation data +struct cdemu_s { + struct drive_s *emulated_drive_gf; + u32 ilba; + u16 buffer_segment; + u16 load_segment; + u16 sector_count; + u8 active; + u8 media; + u8 emulated_extdrive; + + // Virtual device + struct chs_s lchs; +}; + +struct drive_s { + u8 type; // Driver type (DTYPE_*) + u8 floppy_type; // Type of floppy (only for floppy drives). + struct chs_s lchs; // Logical CHS + u64 sectors; // Total sectors count + u32 cntl_id; // Unique id for a given driver type. + u8 removable; // Is media removable (currently unused) + + // Info for EDD calls + u8 translation; // type of translation + u16 blksize; // block size + struct chs_s pchs; // Physical CHS +}; + +#define DISK_SECTOR_SIZE 512 +#define CDROM_SECTOR_SIZE 2048 + +#define DTYPE_NONE 0x00 +#define DTYPE_FLOPPY 0x01 +#define DTYPE_ATA 0x02 +#define DTYPE_ATA_ATAPI 0x03 +#define DTYPE_RAMDISK 0x04 +#define DTYPE_CDEMU 0x05 +#define DTYPE_AHCI 0x06 +#define DTYPE_AHCI_ATAPI 0x07 +#define DTYPE_VIRTIO_SCSI 0x08 +#define DTYPE_VIRTIO_BLK 0x09 +#define DTYPE_USB 0x0a +#define DTYPE_UAS 0x0b +#define DTYPE_LSI_SCSI 0x0c +#define DTYPE_ESP_SCSI 0x0d +#define DTYPE_MEGASAS 0x0e +#define DTYPE_PVSCSI 0x0f + +#define MAXDESCSIZE 80 + +#define TRANSLATION_NONE 0 +#define TRANSLATION_LBA 1 +#define TRANSLATION_LARGE 2 +#define TRANSLATION_RECHS 3 + +#define EXTTYPE_FLOPPY 0 +#define EXTTYPE_HD 1 +#define EXTTYPE_CD 2 + +#define EXTSTART_HD 0x80 +#define EXTSTART_CD 0xE0 + + +/**************************************************************** + * Function defs + ****************************************************************/ + +// block.c +extern struct dpte_s DefaultDPTE; +extern u8 FloppyCount, CDCount; +extern u8 *bounce_buf_fl; +struct drive_s *getDrive(u8 exttype, u8 extdriveoffset); +int getDriveId(u8 exttype, struct drive_s *drive); +void map_floppy_drive(struct drive_s *drive); +void map_hd_drive(struct drive_s *drive); +void map_cd_drive(struct drive_s *drive); +struct bregs; +void __disk_ret(struct bregs *regs, u32 linecode, const char *fname); +void __disk_ret_unimplemented(struct bregs *regs, u32 linecode + , const char *fname); +int process_op(struct disk_op_s *op); +int send_disk_op(struct disk_op_s *op); +int create_bounce_buf(void); + +// Helper function for setting up a return code. +#define disk_ret(regs, code) \ + __disk_ret((regs), (code) | (__LINE__ << 8), __func__) +#define disk_ret_unimplemented(regs, code) \ + __disk_ret_unimplemented((regs), (code) | (__LINE__ << 8), __func__) + +#endif // block.h diff -Nru seabios-1.7.1/src/bmp.c seabios-1.7.4/src/bmp.c --- seabios-1.7.1/src/bmp.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/bmp.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,8 +6,17 @@ * * This work is licensed under the terms of the GNU LGPLv3. */ -#include "util.h" -#include "bmp.h" +#include "malloc.h" // malloc_tmphigh +#include "string.h" // memcpy +#include "util.h" // struct bmp_decdata + +struct bmp_decdata { + struct tagRGBQUAD *quadp; + unsigned char *datap; + int width; + int height; + int bpp; +}; #define bmp_load4byte(addr) (*(u32 *)(addr)) #define bmp_load2byte(addr) (*(u16 *)(addr)) @@ -58,12 +67,14 @@ } } +/* allocate decdata struct */ struct bmp_decdata *bmp_alloc(void) { struct bmp_decdata *bmp = malloc_tmphigh(sizeof(*bmp)); return bmp; } +/* extract information from bmp file data */ int bmp_decode(struct bmp_decdata *bmp, unsigned char *data, int data_size) { if (data_size < 54) @@ -83,13 +94,14 @@ return 0; } +/* get bmp properties */ void bmp_get_size(struct bmp_decdata *bmp, int *width, int *height) { *width = bmp->width; *height = bmp->height; } - +/* flush flat picture data to *pc */ int bmp_show(struct bmp_decdata *bmp, unsigned char *pic, int width , int height, int depth, int bytes_per_line_dest) { diff -Nru seabios-1.7.1/src/bmp.h seabios-1.7.4/src/bmp.h --- seabios-1.7.1/src/bmp.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/bmp.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -#ifndef BMP_H -#define BMP_H -#include "types.h" - -struct bmp_decdata { - struct tagRGBQUAD *quadp; - unsigned char *datap; - int width; - int height; - int bpp; -}; - -/* allocate decdata struct */ -struct bmp_decdata *bmp_alloc(void); - -/* extract information from bmp file data */ -int bmp_decode(struct bmp_decdata *bmp, unsigned char *data, int data_size); - -/* get bmp properties */ -void bmp_get_size(struct bmp_decdata *bmp, int *width, int *height); - -/* flush flat picture data to *pc */ -int bmp_show(struct bmp_decdata *bmp, unsigned char *pic, int width - , int height, int depth, int bytes_per_line_dest); -#endif diff -Nru seabios-1.7.1/src/boot.c seabios-1.7.4/src/boot.c --- seabios-1.7.1/src/boot.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/boot.c 2013-12-23 15:40:06.000000000 +0000 @@ -1,26 +1,31 @@ // Code to load disk image and start system boot. // -// Copyright (C) 2008-2010 Kevin O'Connor +// Copyright (C) 2008-2013 Kevin O'Connor // Copyright (C) 2002 MandrakeSoft S.A. // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "util.h" // dprintf -#include "config.h" // CONFIG_* -#include "disk.h" // cdrom_boot +#include "block.h" // struct drive_s #include "bregs.h" // struct bregs -#include "boot.h" // func defs -#include "cmos.h" // inb_cmos -#include "paravirt.h" // qemu_cfg_show_boot_menu -#include "pci.h" // pci_bdf_to_* -#include "usb.h" // struct usbdevice_s +#include "config.h" // CONFIG_* +#include "fw/paravirt.h" // qemu_cfg_show_boot_menu +#include "hw/pci.h" // pci_bdf_to_* +#include "hw/rtc.h" // rtc_read +#include "hw/usb.h" // struct usbdevice_s +#include "list.h" // hlist_node +#include "malloc.h" // free +#include "output.h" // dprintf +#include "romfile.h" // romfile_loadint +#include "std/disk.h" // struct mbr_s +#include "string.h" // memset +#include "util.h" // irqtimer_calc /**************************************************************** * Boot priority ordering ****************************************************************/ -static char **Bootorder; +static char **Bootorder VARVERIFY32INIT; static int BootorderCount; static void @@ -48,7 +53,7 @@ return; } - dprintf(3, "boot order:\n"); + dprintf(1, "boot order:\n"); i = 0; do { Bootorder[i] = f; @@ -56,7 +61,7 @@ if (f) *(f++) = '\0'; nullTrailingSpace(Bootorder[i]); - dprintf(3, "%d: %s\n", i+1, Bootorder[i]); + dprintf(1, "%d: %s\n", i+1, Bootorder[i]); i++; } while (f); } @@ -120,6 +125,8 @@ int bootprio_find_pci_device(struct pci_device *pci) { + if (CONFIG_CSM) + return csm_bootprio_pci(pci); if (!CONFIG_BOOTORDER) return -1; // Find pci device - for example: /pci@i0cf8/ethernet@5 @@ -144,6 +151,8 @@ int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave) { + if (CONFIG_CSM) + return csm_bootprio_ata(pci, chanid, slave); if (!CONFIG_BOOTORDER) return -1; if (!pci) @@ -158,6 +167,8 @@ int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid) { + if (CONFIG_CSM) + return csm_bootprio_fdc(pci, port, fdid); if (!CONFIG_BOOTORDER) return -1; if (!pci) @@ -228,6 +239,7 @@ * Boot setup ****************************************************************/ +static int BootRetryTime; static int CheckFloppySig = 1; #define DEFAULT_PRIO 9999 @@ -238,17 +250,17 @@ static int DefaultBEVPrio = 104; void -boot_setup(void) +boot_init(void) { if (! CONFIG_BOOT) return; - if (!CONFIG_COREBOOT) { + if (CONFIG_QEMU) { // On emulators, get boot order from nvram. - if (inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1) + if (rtc_read(CMOS_BIOS_BOOTFLAG1) & 1) CheckFloppySig = 0; - u32 bootorder = (inb_cmos(CMOS_BIOS_BOOTFLAG2) - | ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4)); + u32 bootorder = (rtc_read(CMOS_BIOS_BOOTFLAG2) + | ((rtc_read(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4)); DefaultFloppyPrio = DefaultCDPrio = DefaultHDPrio = DefaultBEVPrio = DEFAULT_PRIO; int i; @@ -264,6 +276,8 @@ } } + BootRetryTime = romfile_loadint("etc/boot-fail-wait", 60*1000); + loadBootOrder(); } @@ -281,9 +295,9 @@ }; int priority; const char *description; - struct bootentry_s *next; + struct hlist_node node; }; -static struct bootentry_s *BootList; +static struct hlist_head BootList VARVERIFY32INIT; #define IPL_TYPE_FLOPPY 0x01 #define IPL_TYPE_HARDDISK 0x02 @@ -291,6 +305,7 @@ #define IPL_TYPE_CBFS 0x20 #define IPL_TYPE_BEV 0x80 #define IPL_TYPE_BCV 0x81 +#define IPL_TYPE_HALT 0xf0 static void bootentry_add(int type, int prio, u32 data, const char *desc) @@ -310,9 +325,9 @@ , be->description, type, prio, data); // Add entry in sorted order. - struct bootentry_s **pprev; - for (pprev = &BootList; *pprev; pprev = &(*pprev)->next) { - struct bootentry_s *pos = *pprev; + struct hlist_node **pprev; + struct bootentry_s *pos; + hlist_for_each_entry_pprev(pos, pprev, &BootList, node) { if (be->priority < pos->priority) break; if (be->priority > pos->priority) @@ -327,8 +342,7 @@ && be->drive->cntl_id < pos->drive->cntl_id))) break; } - be->next = *pprev; - *pprev = be; + hlist_add(&be->node, pprev); } // Return the given priority if it's set - defaultprio otherwise. @@ -385,29 +399,75 @@ /**************************************************************** + * Keyboard calls + ****************************************************************/ + +// See if a keystroke is pending in the keyboard buffer. +static int +check_for_keystroke(void) +{ + struct bregs br; + memset(&br, 0, sizeof(br)); + br.flags = F_IF|F_ZF; + br.ah = 1; + call16_int(0x16, &br); + return !(br.flags & F_ZF); +} + +// Return a keystroke - waiting forever if necessary. +static int +get_raw_keystroke(void) +{ + struct bregs br; + memset(&br, 0, sizeof(br)); + br.flags = F_IF; + call16_int(0x16, &br); + return br.ah; +} + +// Read a keystroke - waiting up to 'msec' milliseconds. +static int +get_keystroke(int msec) +{ + u32 end = irqtimer_calc(msec); + for (;;) { + if (check_for_keystroke()) + return get_raw_keystroke(); + if (irqtimer_check(end)) + return -1; + yield_toirq(); + } +} + + +/**************************************************************** * Boot menu and BCV execution ****************************************************************/ #define DEFAULT_BOOTMENU_WAIT 2500 // Show IPL option menu. -static void +void interactive_bootmenu(void) { - if (! CONFIG_BOOTMENU || ! qemu_cfg_show_boot_menu()) + // XXX - show available drives? + + if (! CONFIG_BOOTMENU || !romfile_loadint("etc/show-boot-menu", 1)) return; while (get_keystroke(0) >= 0) ; - printf("Press F12 for boot menu.\n\n"); + char *bootmsg = romfile_loadfile("etc/boot-menu-message", NULL); + int menukey = romfile_loadint("etc/boot-menu-key", 0x86); + printf("%s", bootmsg ?: "\nPress F12 for boot menu.\n\n"); + free(bootmsg); u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT); enable_bootsplash(); int scan_code = get_keystroke(menutime); disable_bootsplash(); - if (scan_code != 0x86) - /* not F12 */ + if (scan_code != menukey) return; while (get_keystroke(0) >= 0) @@ -417,14 +477,13 @@ wait_threads(); // Show menu items - struct bootentry_s *pos = BootList; int maxmenu = 0; - while (pos) { + struct bootentry_s *pos; + hlist_for_each_entry(pos, &BootList, node) { char desc[60]; maxmenu++; printf("%d. %s\n", maxmenu , strtcpy(desc, pos->description, ARRAY_SIZE(desc))); - pos = pos->next; } // Get key press @@ -440,14 +499,13 @@ // Find entry and make top priority. int choice = scan_code - 1; - struct bootentry_s **pprev = &BootList; - while (--choice) - pprev = &(*pprev)->next; - pos = *pprev; - *pprev = pos->next; - pos->next = BootList; - BootList = pos; + hlist_for_each_entry(pos, &BootList, node) { + if (! --choice) + break; + } + hlist_del(&pos->node); pos->priority = 0; + hlist_add_head(&pos->node, &BootList); } // BEV (Boot Execution Vector) list @@ -475,22 +533,18 @@ // Prepare for boot - show menu and run bcvs. void -boot_prep(void) +bcv_prepboot(void) { - if (! CONFIG_BOOT) { - wait_threads(); + if (! CONFIG_BOOT) return; - } - // XXX - show available drives? - - // Allow user to modify BCV/IPL order. - interactive_bootmenu(); - wait_threads(); + int haltprio = find_prio("HALT"); + if (haltprio >= 0) + bootentry_add(IPL_TYPE_HALT, haltprio, 0, "HALT"); // Map drives and populate BEV list - struct bootentry_s *pos = BootList; - while (pos) { + struct bootentry_s *pos; + hlist_for_each_entry(pos, &BootList, node) { switch (pos->type) { case IPL_TYPE_BCV: call_bcv(pos->vector.seg, pos->vector.offset); @@ -511,7 +565,6 @@ add_bev(pos->type, pos->data); break; } - pos = pos->next; } // If nothing added a floppy/hd boot - add it manually. @@ -603,7 +656,7 @@ static void boot_cbfs(struct cbfs_file *file) { - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) + if (!CONFIG_COREBOOT_FLASH) return; printf("Booting from CBFS...\n"); cbfs_run_payload(file); @@ -623,15 +676,15 @@ static void boot_fail(void) { - u32 retrytime = romfile_loadint("etc/boot-fail-wait", 60*1000); - if (retrytime == (u32)-1) + if (BootRetryTime == (u32)-1) printf("No bootable device.\n"); else - printf("No bootable device. Retrying in %d seconds.\n", retrytime/1000); - // Wait for 'retrytime' milliseconds and then reboot. - u32 end = calc_future_timer(retrytime); + printf("No bootable device. Retrying in %d seconds.\n" + , BootRetryTime/1000); + // Wait for 'BootRetryTime' milliseconds and then reboot. + u32 end = irqtimer_calc(BootRetryTime); for (;;) { - if (retrytime != (u32)-1 && check_timer(end)) + if (BootRetryTime != (u32)-1 && irqtimer_check(end)) break; yield_toirq(); } @@ -672,6 +725,9 @@ case IPL_TYPE_BEV: boot_rom(ie->vector); break; + case IPL_TYPE_HALT: + boot_fail(); + break; } // Boot failed: invoke the boot recovery function @@ -687,7 +743,7 @@ void VISIBLE32FLAT handle_18(void) { - debug_serial_setup(); + debug_preinit(); debug_enter(NULL, DEBUG_HDL_18); int seq = BootSequence + 1; BootSequence = seq; @@ -698,7 +754,7 @@ void VISIBLE32FLAT handle_19(void) { - debug_serial_setup(); + debug_preinit(); debug_enter(NULL, DEBUG_HDL_19); BootSequence = 0; do_boot(0); diff -Nru seabios-1.7.1/src/boot.h seabios-1.7.4/src/boot.h --- seabios-1.7.1/src/boot.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/boot.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -// Storage for boot definitions. -#ifndef __BOOT_H -#define __BOOT_H - -// boot.c -void boot_setup(void); -void boot_add_bev(u16 seg, u16 bev, u16 desc, int prio); -void boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio); -struct drive_s; -void boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio); -void boot_add_hd(struct drive_s *drive_g, const char *desc, int prio); -void boot_add_cd(struct drive_s *drive_g, const char *desc, int prio); -void boot_add_cbfs(void *data, const char *desc, int prio); -void boot_prep(void); -struct pci_device; -int bootprio_find_pci_device(struct pci_device *pci); -int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun); -int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave); -int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid); -int bootprio_find_pci_rom(struct pci_device *pci, int instance); -int bootprio_find_named_rom(const char *name, int instance); -struct usbdevice_s; -int bootprio_find_usb(struct usbdevice_s *usbdev, int lun); - -#endif // __BOOT_H diff -Nru seabios-1.7.1/src/bootsplash.c seabios-1.7.4/src/bootsplash.c --- seabios-1.7.1/src/bootsplash.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/bootsplash.c 2013-12-23 15:40:06.000000000 +0000 @@ -1,4 +1,4 @@ -// Option rom scanning code. +// Initialize the VGA console and possibly show a boot splash image. // // Copyright (C) 2009-2010 coresystems GmbH // Copyright (C) 2010 Kevin O'Connor @@ -6,12 +6,16 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "bregs.h" // struct bregs -#include "farptr.h" // FLATPTR_TO_SEG #include "config.h" // CONFIG_* -#include "util.h" // dprintf -#include "jpeg.h" // splash -#include "vbe.h" // struct vbe_info -#include "bmp.h" +#include "farptr.h" // FLATPTR_TO_SEG +#include "malloc.h" // free +#include "output.h" // dprintf +#include "romfile.h" // romfile_loadfile +#include "stacks.h" // call16_int +#include "std/vbe.h" // struct vbe_info +#include "string.h" // memset +#include "util.h" // enable_bootsplash + /**************************************************************** * Helper functions @@ -44,7 +48,8 @@ call16_int10(&br); // Write to screen. - printf("SeaBIOS (version %s)\n\n", VERSION); + printf("SeaBIOS (version %s)\n", VERSION); + display_uuid(); } static int @@ -63,7 +68,7 @@ struct bregs br; memset(&br, 0, sizeof(br)); br.ax = 0x4f01; - br.cx = (1 << 14) | videomode; + br.cx = videomode; br.di = FLATPTR_TO_OFFSET(mode_info); br.es = FLATPTR_TO_SEG(mode_info); call16_int10(&br); @@ -216,7 +221,7 @@ dprintf(5, "Switching to graphics mode\n"); memset(&br, 0, sizeof(br)); br.ax = 0x4f02; - br.bx = (1 << 14) | videomode; + br.bx = videomode | VBE_MODE_LINEAR_FRAME_BUFFER; call16_int10(&br); if (br.ax != 0x4f) { dprintf(1, "set_mode failed.\n"); diff -Nru seabios-1.7.1/src/bregs.h seabios-1.7.4/src/bregs.h --- seabios-1.7.1/src/bregs.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/bregs.h 2013-12-23 15:40:06.000000000 +0000 @@ -7,29 +7,14 @@ #ifndef __BREGS_H #define __BREGS_H -// CPU flag bitdefs -#define F_CF (1<<0) -#define F_ZF (1<<6) -#define F_IF (1<<9) -#define F_ID (1<<21) - -// CR0 flags -#define CR0_PG (1<<31) // Paging -#define CR0_CD (1<<30) // Cache disable -#define CR0_NW (1<<29) // Not Write-through -#define CR0_PE (1<<0) // Protection enable - - -#ifndef __ASSEMBLY__ +#include "types.h" // u16 +#include "x86.h" // F_CF -#include "farptr.h" // struct segoff_s /**************************************************************** * Registers saved/restored in romlayout.S ****************************************************************/ -#include "types.h" // u16 - #define UREG(ER, R, RH, RL) union { u32 ER; struct { u16 R; u16 R ## _hi; }; struct { u8 RL; u8 RH; u8 R ## _hilo; u8 R ## _hihi; }; } // Layout of registers passed in to irq handlers. Note that this @@ -92,6 +77,4 @@ set_cf(regs, 1); } -#endif // !__ASSEMBLY__ - #endif // bregs.h diff -Nru seabios-1.7.1/src/byteorder.h seabios-1.7.4/src/byteorder.h --- seabios-1.7.1/src/byteorder.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/byteorder.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,71 @@ +#ifndef __BYTEORDER_H +#define __BYTEORDER_H + +#include "types.h" // u32 + +static inline u16 __swab16_constant(u16 val) { + return (val<<8) | (val>>8); +} +static inline u32 __swab32_constant(u32 val) { + return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24); +} +static inline u64 __swab64_constant(u64 val) { + return ((u64)__swab32_constant(val) << 32) | __swab32_constant(val>>32); +} +static inline u32 __swab32(u32 val) { + asm("bswapl %0" : "+r"(val)); + return val; +} +static inline u64 __swab64(u64 val) { + union u64_u32_u i, o; + i.val = val; + o.lo = __swab32(i.hi); + o.hi = __swab32(i.lo); + return o.val; +} + +#define swab16(x) __swab16_constant(x) +#define swab32(x) (__builtin_constant_p((u32)(x)) \ + ? __swab32_constant(x) : __swab32(x)) +#define swab64(x) (__builtin_constant_p((u64)(x)) \ + ? __swab64_constant(x) : __swab64(x)) + +static inline u16 cpu_to_le16(u16 x) { + return x; +} +static inline u32 cpu_to_le32(u32 x) { + return x; +} +static inline u64 cpu_to_le64(u64 x) { + return x; +} +static inline u16 le16_to_cpu(u16 x) { + return x; +} +static inline u32 le32_to_cpu(u32 x) { + return x; +} +static inline u64 le64_to_cpu(u64 x) { + return x; +} + +static inline u16 cpu_to_be16(u16 x) { + return swab16(x); +} +static inline u32 cpu_to_be32(u32 x) { + return swab32(x); +} +static inline u64 cpu_to_be64(u64 x) { + return swab64(x); +} +static inline u16 be16_to_cpu(u16 x) { + return swab16(x); +} +static inline u32 be32_to_cpu(u32 x) { + return swab32(x); +} +static inline u64 be64_to_cpu(u64 x) { + return swab64(x); +} + +#endif // byteorder.h diff -Nru seabios-1.7.1/src/cdrom.c seabios-1.7.4/src/cdrom.c --- seabios-1.7.1/src/cdrom.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/cdrom.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,15 +5,19 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "disk.h" // cdrom_13 -#include "util.h" // memset -#include "bregs.h" // struct bregs #include "biosvar.h" // GET_GLOBAL -#include "ata.h" // ATA_CMD_REQUEST_SENSE -#include "blockcmd.h" // CDB_CMD_REQUEST_SENSE +#include "block.h" // struct drive_s +#include "bregs.h" // struct bregs +#include "hw/ata.h" // ATA_CMD_REQUEST_SENSE +#include "hw/blockcmd.h" // CDB_CMD_REQUEST_SENSE +#include "malloc.h" // free +#include "output.h" // dprintf +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // cdrom_prepboot // Locks for removable devices -u8 CDRom_locks[CONFIG_MAX_EXTDRIVE] VARLOW; +u8 CDRom_locks[BUILD_MAX_EXTDRIVE] VARLOW; /**************************************************************** @@ -21,15 +25,14 @@ ****************************************************************/ struct cdemu_s CDEmu VARLOW; -struct drive_s *cdemu_drive_gf VAR16VISIBLE; +struct drive_s *cdemu_drive_gf VARFSEG; static int cdemu_read(struct disk_op_s *op) { - struct drive_s *drive_g; - drive_g = GLOBALFLAT2GLOBAL(GET_LOW(CDEmu.emulated_drive_gf)); + struct drive_s *drive_gf = GET_LOW(CDEmu.emulated_drive_gf); struct disk_op_s dop; - dop.drive_g = drive_g; + dop.drive_gf = drive_gf; dop.command = op->command; dop.lba = GET_LOW(CDEmu.ilba) + op->lba / 4; @@ -107,43 +110,28 @@ } void -cdemu_setup(void) +cdrom_prepboot(void) { if (!CONFIG_CDROM_EMU) return; if (!CDCount) return; - if (bounce_buf_init() < 0) + if (create_bounce_buf() < 0) return; - struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g)); - if (!drive_g) { + struct drive_s *drive = malloc_fseg(sizeof(*drive)); + if (!drive) { warn_noalloc(); - free(drive_g); + free(drive); return; } - cdemu_drive_gf = drive_g; - memset(drive_g, 0, sizeof(*drive_g)); - drive_g->type = DTYPE_CDEMU; - drive_g->blksize = DISK_SECTOR_SIZE; - drive_g->sectors = (u64)-1; + cdemu_drive_gf = drive; + memset(drive, 0, sizeof(*drive)); + drive->type = DTYPE_CDEMU; + drive->blksize = DISK_SECTOR_SIZE; + drive->sectors = (u64)-1; } -struct eltorito_s { - u8 size; - u8 media; - u8 emulated_drive; - u8 controller_index; - u32 ilba; - u16 device_spec; - u16 buffer_segment; - u16 load_segment; - u16 sector_count; - u8 cylinders; - u8 sectors; - u8 heads; -}; - #define SET_INT13ET(regs,var,val) \ SET_FARVAR((regs)->ds, ((struct eltorito_s*)((regs)->si+0))->var, (val)) @@ -165,9 +153,9 @@ SET_INT13ET(regs, buffer_segment, GET_LOW(CDEmu.buffer_segment)); SET_INT13ET(regs, load_segment, GET_LOW(CDEmu.load_segment)); SET_INT13ET(regs, sector_count, GET_LOW(CDEmu.sector_count)); - SET_INT13ET(regs, cylinders, GET_LOW(CDEmu.lchs.cylinders)); - SET_INT13ET(regs, sectors, GET_LOW(CDEmu.lchs.spt)); - SET_INT13ET(regs, heads, GET_LOW(CDEmu.lchs.heads)); + SET_INT13ET(regs, cylinders, GET_LOW(CDEmu.lchs.cylinder)); + SET_INT13ET(regs, sectors, GET_LOW(CDEmu.lchs.sector)); + SET_INT13ET(regs, heads, GET_LOW(CDEmu.lchs.head)); // If we have to terminate emulation if (regs->al == 0x00) { @@ -186,14 +174,14 @@ ****************************************************************/ int -cdrom_boot(struct drive_s *drive_g) +cdrom_boot(struct drive_s *drive) { ASSERT32FLAT(); struct disk_op_s dop; - int cdid = getDriveId(EXTTYPE_CD, drive_g); + int cdid = getDriveId(EXTTYPE_CD, drive); memset(&dop, 0, sizeof(dop)); - dop.drive_g = drive_g; - if (!dop.drive_g || cdid < 0) + dop.drive_gf = drive; + if (!dop.drive_gf || cdid < 0) return 1; int ret = scsi_is_ready(&dop); @@ -242,7 +230,7 @@ u8 media = buffer[0x21]; CDEmu.media = media; - CDEmu.emulated_drive_gf = dop.drive_g; + CDEmu.emulated_drive_gf = dop.drive_gf; u16 boot_segment = *(u16*)&buffer[0x22]; if (!boot_segment) @@ -284,19 +272,19 @@ switch (media) { case 0x01: // 1.2M floppy - CDEmu.lchs.spt = 15; - CDEmu.lchs.cylinders = 80; - CDEmu.lchs.heads = 2; + CDEmu.lchs.sector = 15; + CDEmu.lchs.cylinder = 80; + CDEmu.lchs.head = 2; break; case 0x02: // 1.44M floppy - CDEmu.lchs.spt = 18; - CDEmu.lchs.cylinders = 80; - CDEmu.lchs.heads = 2; + CDEmu.lchs.sector = 18; + CDEmu.lchs.cylinder = 80; + CDEmu.lchs.head = 2; break; case 0x03: // 2.88M floppy - CDEmu.lchs.spt = 36; - CDEmu.lchs.cylinders = 80; - CDEmu.lchs.heads = 2; + CDEmu.lchs.sector = 36; + CDEmu.lchs.cylinder = 80; + CDEmu.lchs.head = 2; break; } } else { @@ -310,9 +298,9 @@ u8 cyllow = GET_FARVAR(boot_segment, mbr->partitions[0].last.cyllow); u8 heads = GET_FARVAR(boot_segment, mbr->partitions[0].last.heads); - CDEmu.lchs.spt = sptcyl & 0x3f; - CDEmu.lchs.cylinders = ((sptcyl<<2)&0x300) + cyllow + 1; - CDEmu.lchs.heads = heads + 1; + CDEmu.lchs.sector = sptcyl & 0x3f; + CDEmu.lchs.cylinder = ((sptcyl<<2)&0x300) + cyllow + 1; + CDEmu.lchs.head = heads + 1; } // everything is ok, so from now on, the emulation is active diff -Nru seabios-1.7.1/src/clock.c seabios-1.7.4/src/clock.c --- seabios-1.7.1/src/clock.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/clock.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,265 +6,53 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "biosvar.h" // SET_BDA -#include "util.h" // debug_enter -#include "disk.h" // floppy_tick -#include "cmos.h" // inb_cmos -#include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs -#include "biosvar.h" // GET_GLOBAL -#include "usb-hid.h" // usb_check_event - -// RTC register flags -#define RTC_A_UIP 0x80 - -#define RTC_B_SET 0x80 -#define RTC_B_PIE 0x40 -#define RTC_B_AIE 0x20 -#define RTC_B_UIE 0x10 -#define RTC_B_BIN 0x04 -#define RTC_B_24HR 0x02 -#define RTC_B_DSE 0x01 - - -// Bits for PORT_PS2_CTRLB -#define PPCB_T2GATE (1<<0) -#define PPCB_SPKR (1<<1) -#define PPCB_T2OUT (1<<5) - -// Bits for PORT_PIT_MODE -#define PM_SEL_TIMER0 (0<<6) -#define PM_SEL_TIMER1 (1<<6) -#define PM_SEL_TIMER2 (2<<6) -#define PM_SEL_READBACK (3<<6) -#define PM_ACCESS_LATCH (0<<4) -#define PM_ACCESS_LOBYTE (1<<4) -#define PM_ACCESS_HIBYTE (2<<4) -#define PM_ACCESS_WORD (3<<4) -#define PM_MODE0 (0<<1) -#define PM_MODE1 (1<<1) -#define PM_MODE2 (2<<1) -#define PM_MODE3 (3<<1) -#define PM_MODE4 (4<<1) -#define PM_MODE5 (5<<1) -#define PM_CNT_BINARY (0<<0) -#define PM_CNT_BCD (1<<0) -#define PM_READ_COUNTER0 (1<<1) -#define PM_READ_COUNTER1 (1<<2) -#define PM_READ_COUNTER2 (1<<3) -#define PM_READ_STATUSVALUE (0<<4) -#define PM_READ_VALUE (1<<4) -#define PM_READ_STATUS (2<<4) - - -/**************************************************************** - * TSC timer - ****************************************************************/ - -#define CALIBRATE_COUNT 0x800 // Approx 1.7ms - -u32 cpu_khz VAR16VISIBLE; -u8 no_tsc VAR16VISIBLE; - -static void -calibrate_tsc(void) -{ - u32 eax, ebx, ecx, edx, cpuid_features = 0; - cpuid(0, &eax, &ebx, &ecx, &edx); - if (eax > 0) - cpuid(1, &eax, &ebx, &ecx, &cpuid_features); - - if (!(cpuid_features & CPUID_TSC)) { - SET_GLOBAL(no_tsc, 1); - SET_GLOBAL(cpu_khz, PIT_TICK_RATE / 1000); - dprintf(3, "386/486 class CPU. Using TSC emulation\n"); - return; - } - - // Setup "timer2" - u8 orig = inb(PORT_PS2_CTRLB); - outb((orig & ~PPCB_SPKR) | PPCB_T2GATE, PORT_PS2_CTRLB); - /* binary, mode 0, LSB/MSB, Ch 2 */ - outb(PM_SEL_TIMER2|PM_ACCESS_WORD|PM_MODE0|PM_CNT_BINARY, PORT_PIT_MODE); - /* LSB of ticks */ - outb(CALIBRATE_COUNT & 0xFF, PORT_PIT_COUNTER2); - /* MSB of ticks */ - outb(CALIBRATE_COUNT >> 8, PORT_PIT_COUNTER2); - - u64 start = rdtscll(); - while ((inb(PORT_PS2_CTRLB) & PPCB_T2OUT) == 0) - ; - u64 end = rdtscll(); - - // Restore PORT_PS2_CTRLB - outb(orig, PORT_PS2_CTRLB); - - // Store calibrated cpu khz. - u64 diff = end - start; - dprintf(6, "tsc calibrate start=%u end=%u diff=%u\n" - , (u32)start, (u32)end, (u32)diff); - u32 hz = diff * PIT_TICK_RATE / CALIBRATE_COUNT; - SET_GLOBAL(cpu_khz, hz / 1000); - - dprintf(1, "CPU Mhz=%u\n", hz / 1000000); -} - -/* TSC emulation timekeepers */ -u64 TSC_8254 VARLOW; -int Last_TSC_8254 VARLOW; - -static u64 -emulate_tsc(void) -{ - /* read timer 0 current count */ - u64 ret = GET_LOW(TSC_8254); - /* readback mode has slightly shifted registers, works on all - * 8254, readback PIT0 latch */ - outb(PM_SEL_READBACK | PM_READ_VALUE | PM_READ_COUNTER0, PORT_PIT_MODE); - int cnt = (inb(PORT_PIT_COUNTER0) | (inb(PORT_PIT_COUNTER0) << 8)); - int d = GET_LOW(Last_TSC_8254) - cnt; - /* Determine the ticks count from last invocation of this function */ - ret += (d > 0) ? d : (PIT_TICK_INTERVAL + d); - SET_LOW(Last_TSC_8254, cnt); - SET_LOW(TSC_8254, ret); - return ret; -} - -static u64 -get_tsc(void) -{ - if (unlikely(GET_GLOBAL(no_tsc))) - return emulate_tsc(); - return rdtscll(); -} - -int -check_tsc(u64 end) -{ - return (s64)(get_tsc() - end) > 0; -} - -static void -tscdelay(u64 diff) -{ - u64 start = get_tsc(); - u64 end = start + diff; - while (!check_tsc(end)) - cpu_relax(); -} - -static void -tscsleep(u64 diff) -{ - u64 start = get_tsc(); - u64 end = start + diff; - while (!check_tsc(end)) - yield(); -} - -void ndelay(u32 count) { - tscdelay(count * GET_GLOBAL(cpu_khz) / 1000000); -} -void udelay(u32 count) { - tscdelay(count * GET_GLOBAL(cpu_khz) / 1000); -} -void mdelay(u32 count) { - tscdelay(count * GET_GLOBAL(cpu_khz)); -} - -void nsleep(u32 count) { - tscsleep(count * GET_GLOBAL(cpu_khz) / 1000000); -} -void usleep(u32 count) { - tscsleep(count * GET_GLOBAL(cpu_khz) / 1000); -} -void msleep(u32 count) { - tscsleep(count * GET_GLOBAL(cpu_khz)); -} - -// Return the TSC value that is 'msecs' time in the future. -u64 -calc_future_tsc(u32 msecs) -{ - u32 khz = GET_GLOBAL(cpu_khz); - return get_tsc() + ((u64)khz * msecs); -} -u64 -calc_future_tsc_usec(u32 usecs) -{ - u32 khz = GET_GLOBAL(cpu_khz); - return get_tsc() + ((u64)(khz/1000) * usecs); -} +#include "hw/pic.h" // pic_eoi1 +#include "hw/rtc.h" // rtc_read +#include "hw/usb-hid.h" // usb_check_event +#include "output.h" // debug_enter +#include "stacks.h" // yield +#include "string.h" // memset +#include "util.h" // clock_setup /**************************************************************** * Init ****************************************************************/ -static int -rtc_updating(void) -{ - // This function checks to see if the update-in-progress bit - // is set in CMOS Status Register A. If not, it returns 0. - // If it is set, it tries to wait until there is a transition - // to 0, and will return 0 if such a transition occurs. A -1 - // is returned only after timing out. The maximum period - // that this bit should be set is constrained to (1984+244) - // useconds, but we wait for longer just to be sure. - - if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0) - return 0; - u64 end = calc_future_tsc(15); - for (;;) { - if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0) - return 0; - if (check_tsc(end)) - // update-in-progress never transitioned to 0 - return -1; - yield(); - } -} - -static void -pit_setup(void) -{ - // timer0: binary count, 16bit count, mode 2 - outb(PM_SEL_TIMER0|PM_ACCESS_WORD|PM_MODE2|PM_CNT_BINARY, PORT_PIT_MODE); - // maximum count of 0000H = 18.2Hz - outb(0x0, PORT_PIT_COUNTER0); - outb(0x0, PORT_PIT_COUNTER0); -} - -static void -init_rtc(void) -{ - outb_cmos(0x26, CMOS_STATUS_A); // 32,768Khz src, 976.5625us updates - u8 regB = inb_cmos(CMOS_STATUS_B); - outb_cmos((regB & RTC_B_DSE) | RTC_B_24HR, CMOS_STATUS_B); - inb_cmos(CMOS_STATUS_C); - inb_cmos(CMOS_STATUS_D); -} - static u32 bcd2bin(u8 val) { return (val & 0xf) + ((val >> 4) * 10); } +u8 Century VARLOW; + void -timer_setup(void) +clock_setup(void) { dprintf(3, "init timer\n"); - calibrate_tsc(); pit_setup(); - init_rtc(); + rtc_setup(); rtc_updating(); - u32 seconds = bcd2bin(inb_cmos(CMOS_RTC_SECONDS)); - u32 minutes = bcd2bin(inb_cmos(CMOS_RTC_MINUTES)); - u32 hours = bcd2bin(inb_cmos(CMOS_RTC_HOURS)); - u32 ticks = (hours * 60 + minutes) * 60 + seconds; - ticks = ((u64)ticks * PIT_TICK_RATE) / PIT_TICK_INTERVAL; - SET_BDA(timer_counter, ticks); + u32 seconds = bcd2bin(rtc_read(CMOS_RTC_SECONDS)); + u32 minutes = bcd2bin(rtc_read(CMOS_RTC_MINUTES)); + u32 hours = bcd2bin(rtc_read(CMOS_RTC_HOURS)); + u32 ticks = ticks_from_ms(((hours * 60 + minutes) * 60 + seconds) * 1000); + SET_BDA(timer_counter, ticks % TICKS_PER_DAY); + + // Setup Century storage + if (CONFIG_QEMU) { + Century = rtc_read(CMOS_CENTURY); + } else { + // Infer current century from the year. + u8 year = rtc_read(CMOS_RTC_YEAR); + if (year > 0x80) + Century = 0x19; + else + Century = 0x20; + } enable_hwirq(0, FUNC16(entry_08)); enable_hwirq(8, FUNC16(entry_70)); @@ -275,35 +63,6 @@ * Standard clock functions ****************************************************************/ -#define TICKS_PER_DAY (u32)((u64)60*60*24*PIT_TICK_RATE / PIT_TICK_INTERVAL) - -// Calculate the timer value at 'count' number of full timer ticks in -// the future. -u32 -calc_future_timer_ticks(u32 count) -{ - return (GET_BDA(timer_counter) + count + 1) % TICKS_PER_DAY; -} - -// Return the timer value that is 'msecs' time in the future. -u32 -calc_future_timer(u32 msecs) -{ - if (!msecs) - return GET_BDA(timer_counter); - u32 kticks = DIV_ROUND_UP((u64)msecs * PIT_TICK_RATE, PIT_TICK_INTERVAL); - u32 ticks = DIV_ROUND_UP(kticks, 1000); - return calc_future_timer_ticks(ticks); -} - -// Check if the given timer value has passed. -int -check_timer(u32 end) -{ - return (((GET_BDA(timer_counter) + TICKS_PER_DAY - end) % TICKS_PER_DAY) - < (TICKS_PER_DAY/2)); -} - // get current clock count static void handle_1a00(struct bregs *regs) @@ -338,10 +97,10 @@ return; } - regs->dh = inb_cmos(CMOS_RTC_SECONDS); - regs->cl = inb_cmos(CMOS_RTC_MINUTES); - regs->ch = inb_cmos(CMOS_RTC_HOURS); - regs->dl = inb_cmos(CMOS_STATUS_B) & RTC_B_DSE; + regs->dh = rtc_read(CMOS_RTC_SECONDS); + regs->cl = rtc_read(CMOS_RTC_MINUTES); + regs->ch = rtc_read(CMOS_RTC_HOURS); + regs->dl = rtc_read(CMOS_STATUS_B) & RTC_B_DSE; regs->ah = 0; regs->al = regs->ch; set_success(regs); @@ -362,16 +121,16 @@ // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = ((RegB & 01100000b) | 00000010b) if (rtc_updating()) { - init_rtc(); + rtc_setup(); // fall through as if an update were not in progress } - outb_cmos(regs->dh, CMOS_RTC_SECONDS); - outb_cmos(regs->cl, CMOS_RTC_MINUTES); - outb_cmos(regs->ch, CMOS_RTC_HOURS); + rtc_write(CMOS_RTC_SECONDS, regs->dh); + rtc_write(CMOS_RTC_MINUTES, regs->cl); + rtc_write(CMOS_RTC_HOURS, regs->ch); // Set Daylight Savings time enabled bit to requested value - u8 val8 = ((inb_cmos(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE)) + u8 val8 = ((rtc_read(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE)) | RTC_B_24HR | (regs->dl & RTC_B_DSE)); - outb_cmos(val8, CMOS_STATUS_B); + rtc_write(CMOS_STATUS_B, val8); regs->ah = 0; regs->al = val8; // val last written to Reg B set_success(regs); @@ -386,17 +145,10 @@ set_invalid(regs); return; } - regs->cl = inb_cmos(CMOS_RTC_YEAR); - regs->dh = inb_cmos(CMOS_RTC_MONTH); - regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH); - if (CONFIG_COREBOOT) { - if (regs->cl > 0x80) - regs->ch = 0x19; - else - regs->ch = 0x20; - } else { - regs->ch = inb_cmos(CMOS_CENTURY); - } + regs->cl = rtc_read(CMOS_RTC_YEAR); + regs->dh = rtc_read(CMOS_RTC_MONTH); + regs->dl = rtc_read(CMOS_RTC_DAY_MONTH); + regs->ch = GET_LOW(Century); regs->al = regs->ch; set_success(regs); } @@ -416,18 +168,17 @@ // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = (RegB & 01111111b) if (rtc_updating()) { - init_rtc(); + rtc_setup(); set_invalid(regs); return; } - outb_cmos(regs->cl, CMOS_RTC_YEAR); - outb_cmos(regs->dh, CMOS_RTC_MONTH); - outb_cmos(regs->dl, CMOS_RTC_DAY_MONTH); - if (!CONFIG_COREBOOT) - outb_cmos(regs->ch, CMOS_CENTURY); + rtc_write(CMOS_RTC_YEAR, regs->cl); + rtc_write(CMOS_RTC_MONTH, regs->dh); + rtc_write(CMOS_RTC_DAY_MONTH, regs->dl); + SET_LOW(Century, regs->ch); // clear halt-clock bit - u8 val8 = inb_cmos(CMOS_STATUS_B) & ~RTC_B_SET; - outb_cmos(val8, CMOS_STATUS_B); + u8 val8 = rtc_read(CMOS_STATUS_B) & ~RTC_B_SET; + rtc_write(CMOS_STATUS_B, val8); regs->ah = 0; regs->al = val8; // AL = val last written to Reg B set_success(regs); @@ -447,7 +198,7 @@ // // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = ((RegB & 01111111b) | 00100000b) - u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B + u8 val8 = rtc_read(CMOS_STATUS_B); // Get Status Reg B regs->ax = 0; if (val8 & RTC_B_AIE) { // Alarm interrupt enabled already @@ -455,14 +206,14 @@ return; } if (rtc_updating()) { - init_rtc(); + rtc_setup(); // fall through as if an update were not in progress } - outb_cmos(regs->dh, CMOS_RTC_SECONDS_ALARM); - outb_cmos(regs->cl, CMOS_RTC_MINUTES_ALARM); - outb_cmos(regs->ch, CMOS_RTC_HOURS_ALARM); + rtc_write(CMOS_RTC_SECONDS_ALARM, regs->dh); + rtc_write(CMOS_RTC_MINUTES_ALARM, regs->cl); + rtc_write(CMOS_RTC_HOURS_ALARM, regs->ch); // enable Status Reg B alarm bit, clear halt clock bit - outb_cmos((val8 & ~RTC_B_SET) | RTC_B_AIE, CMOS_STATUS_B); + rtc_write(CMOS_STATUS_B, (val8 & ~RTC_B_SET) | RTC_B_AIE); set_success(regs); } @@ -480,9 +231,9 @@ // // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = (RegB & 01010111b) - u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B + u8 val8 = rtc_read(CMOS_STATUS_B); // Get Status Reg B // clear clock-halt bit, disable alarm bit - outb_cmos(val8 & ~(RTC_B_SET|RTC_B_AIE), CMOS_STATUS_B); + rtc_write(CMOS_STATUS_B, val8 & ~(RTC_B_SET|RTC_B_AIE)); regs->ah = 0; regs->al = val8; // val last written to Reg B set_success(regs); @@ -509,7 +260,6 @@ case 0x05: handle_1a05(regs); break; case 0x06: handle_1a06(regs); break; case 0x07: handle_1a07(regs); break; - case 0xb1: handle_1ab1(regs); break; default: handle_1aXX(regs); break; } } @@ -520,8 +270,7 @@ { debug_isr(DEBUG_ISR_08); - floppy_tick(); - + // Update counter u32 counter = GET_BDA(timer_counter); counter++; // compare to one days worth of timer ticks at 18.2 hz @@ -530,9 +279,10 @@ counter = 0; SET_BDA(timer_rollover, GET_BDA(timer_rollover) + 1); } - SET_BDA(timer_counter, counter); + // Check for internal events. + floppy_tick(); usb_check_event(); // chain to user timer tick INT #0x1c @@ -541,40 +291,44 @@ br.flags = F_IF; call16_int(0x1c, &br); - eoi_pic1(); + pic_eoi1(); } /**************************************************************** - * Periodic timer + * IRQ based timer ****************************************************************/ -int RTCusers VARLOW; +// Calculate the timer value at 'count' number of full timer ticks in +// the future. +u32 +irqtimer_calc_ticks(u32 count) +{ + return (GET_BDA(timer_counter) + count + 1) % TICKS_PER_DAY; +} -void -useRTC(void) +// Return the timer value that is 'msecs' time in the future. +u32 +irqtimer_calc(u32 msecs) { - int count = GET_LOW(RTCusers); - SET_LOW(RTCusers, count+1); - if (count) - return; - // Turn on the Periodic Interrupt timer - u8 bRegister = inb_cmos(CMOS_STATUS_B); - outb_cmos(bRegister | RTC_B_PIE, CMOS_STATUS_B); + if (!msecs) + return GET_BDA(timer_counter); + return irqtimer_calc_ticks(ticks_from_ms(msecs)); } -void -releaseRTC(void) +// Check if the given timer value has passed. +int +irqtimer_check(u32 end) { - int count = GET_LOW(RTCusers); - SET_LOW(RTCusers, count-1); - if (count != 1) - return; - // Clear the Periodic Interrupt. - u8 bRegister = inb_cmos(CMOS_STATUS_B); - outb_cmos(bRegister & ~RTC_B_PIE, CMOS_STATUS_B); + return (((GET_BDA(timer_counter) + TICKS_PER_DAY - end) % TICKS_PER_DAY) + < (TICKS_PER_DAY/2)); } + +/**************************************************************** + * Periodic timer + ****************************************************************/ + static int set_usertimer(u32 usecs, u16 seg, u16 offset) { @@ -585,7 +339,7 @@ SET_BDA(rtc_wait_flag, RWS_WAIT_PENDING); // Set status byte. SET_BDA(user_wait_complete_flag, SEGOFF(seg, offset)); SET_BDA(user_wait_timeout, usecs); - useRTC(); + rtc_use(); return 0; } @@ -596,7 +350,7 @@ return; // Turn off status byte. SET_BDA(rtc_wait_flag, 0); - releaseRTC(); + rtc_release(); } #define RET_ECLOCKINUSE 0x83 @@ -664,8 +418,8 @@ debug_isr(DEBUG_ISR_70); // Check which modes are enabled and have occurred. - u8 registerB = inb_cmos(CMOS_STATUS_B); - u8 registerC = inb_cmos(CMOS_STATUS_C); + u8 registerB = rtc_read(CMOS_STATUS_B); + u8 registerC = rtc_read(CMOS_STATUS_C); if (!(registerB & (RTC_B_PIE|RTC_B_AIE))) goto done; @@ -704,5 +458,5 @@ } done: - eoi_pic2(); + pic_eoi2(); } diff -Nru seabios-1.7.1/src/cmos.h seabios-1.7.4/src/cmos.h --- seabios-1.7.1/src/cmos.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/cmos.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -// Definitions for X86 CMOS non-volatile memory access. -// -// Copyright (C) 2008 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. -#ifndef __CMOS_H -#define __CMOS_H - -#define CMOS_RTC_SECONDS 0x00 -#define CMOS_RTC_SECONDS_ALARM 0x01 -#define CMOS_RTC_MINUTES 0x02 -#define CMOS_RTC_MINUTES_ALARM 0x03 -#define CMOS_RTC_HOURS 0x04 -#define CMOS_RTC_HOURS_ALARM 0x05 -#define CMOS_RTC_DAY_WEEK 0x06 -#define CMOS_RTC_DAY_MONTH 0x07 -#define CMOS_RTC_MONTH 0x08 -#define CMOS_RTC_YEAR 0x09 -#define CMOS_STATUS_A 0x0a -#define CMOS_STATUS_B 0x0b -#define CMOS_STATUS_C 0x0c -#define CMOS_STATUS_D 0x0d -#define CMOS_RESET_CODE 0x0f -#define CMOS_FLOPPY_DRIVE_TYPE 0x10 -#define CMOS_DISK_DATA 0x12 -#define CMOS_EQUIPMENT_INFO 0x14 -#define CMOS_DISK_DRIVE1_TYPE 0x19 -#define CMOS_DISK_DRIVE2_TYPE 0x1a -#define CMOS_DISK_DRIVE1_CYL 0x1b -#define CMOS_DISK_DRIVE2_CYL 0x24 -#define CMOS_MEM_EXTMEM_LOW 0x30 -#define CMOS_MEM_EXTMEM_HIGH 0x31 -#define CMOS_CENTURY 0x32 -#define CMOS_MEM_EXTMEM2_LOW 0x34 -#define CMOS_MEM_EXTMEM2_HIGH 0x35 -#define CMOS_BIOS_BOOTFLAG1 0x38 -#define CMOS_BIOS_DISKTRANSFLAG 0x39 -#define CMOS_BIOS_BOOTFLAG2 0x3d -#define CMOS_MEM_HIGHMEM_LOW 0x5b -#define CMOS_MEM_HIGHMEM_MID 0x5c -#define CMOS_MEM_HIGHMEM_HIGH 0x5d -#define CMOS_BIOS_SMP_COUNT 0x5f - -// CMOS_FLOPPY_DRIVE_TYPE bitdefs -#define CFD_NO_DRIVE 0 -#define CFD_360KB 1 -#define CFD_12MB 2 -#define CFD_720KB 3 -#define CFD_144MB 4 -#define CFD_288MB 5 - -#ifndef __ASSEMBLY__ - -#include "ioport.h" // inb, outb - -static inline u8 -inb_cmos(u8 reg) -{ - reg |= NMI_DISABLE_BIT; - outb(reg, PORT_CMOS_INDEX); - return inb(PORT_CMOS_DATA); -} - -static inline void -outb_cmos(u8 val, u8 reg) -{ - reg |= NMI_DISABLE_BIT; - outb(reg, PORT_CMOS_INDEX); - outb(val, PORT_CMOS_DATA); -} - -#endif // !__ASSEMBLY__ - -#endif // cmos.h diff -Nru seabios-1.7.1/src/config.h seabios-1.7.4/src/config.h --- seabios-1.7.1/src/config.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/config.h 2013-12-23 15:40:06.000000000 +0000 @@ -5,29 +5,27 @@ // Configuration definitions. -//#define CONFIG_APPNAME "QEMU" -//#define CONFIG_CPUNAME8 "QEMUCPU " -//#define CONFIG_APPNAME6 "QEMU " -//#define CONFIG_APPNAME4 "QEMU" -#define CONFIG_APPNAME "Bochs" -#define CONFIG_CPUNAME8 "BOCHSCPU" -#define CONFIG_APPNAME6 "BOCHS " -#define CONFIG_APPNAME4 "BXPC" +//#define BUILD_APPNAME "QEMU" +//#define BUILD_CPUNAME8 "QEMUCPU " +//#define BUILD_APPNAME6 "QEMU " +//#define BUILD_APPNAME4 "QEMU" +#define BUILD_APPNAME "Bochs" +#define BUILD_CPUNAME8 "BOCHSCPU" +#define BUILD_APPNAME6 "BOCHS " +#define BUILD_APPNAME4 "BXPC" // Maximum number of map entries in the e820 map -#define CONFIG_MAX_E820 32 -// Space to reserve in f-segment for dynamic allocations -#define CONFIG_MAX_BIOSTABLE 2048 +#define BUILD_MAX_E820 32 // Space to reserve in high-memory for tables -#define CONFIG_MAX_HIGHTABLE (64*1024) +#define BUILD_MAX_HIGHTABLE (64*1024) // Largest supported externaly facing drive id -#define CONFIG_MAX_EXTDRIVE 16 +#define BUILD_MAX_EXTDRIVE 16 // Number of bytes the smbios may be and still live in the f-segment #define BUILD_MAX_SMBIOS_FSEG 600 -#define CONFIG_MODEL_ID 0xFC -#define CONFIG_SUBMODEL_ID 0x00 -#define CONFIG_BIOS_REVISION 0x01 +#define BUILD_MODEL_ID 0xFC +#define BUILD_SUBMODEL_ID 0x00 +#define BUILD_BIOS_REVISION 0x01 // Various memory addresses used by the code. #define BUILD_STACK_ADDR 0x7000 @@ -44,7 +42,6 @@ #define BUILD_SMM_INIT_ADDR 0x38000 #define BUILD_SMM_ADDR 0xa8000 #define BUILD_SMM_SIZE 0x8000 -#define BUILD_MAX_HIGHMEM 0xe0000000 #define BUILD_PCIMEM_START 0xe0000000 #define BUILD_PCIMEM_END 0xfec00000 /* IOAPIC is mapped at */ @@ -56,6 +53,9 @@ #define BUILD_HPET_ADDRESS 0xfed00000 #define BUILD_APIC_ADDR 0xfee00000 +// PCI IRQS +#define BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11)) + // Important real-mode segments #define SEG_IVT 0x0000 #define SEG_BDA 0x0040 @@ -97,7 +97,7 @@ #define DEBUG_ISR_hwpic2 5 #define DEBUG_HDL_pnp 1 #define DEBUG_HDL_pmm 1 -#define DEBUG_HDL_pcibios32 9 +#define DEBUG_HDL_pcibios 9 #define DEBUG_HDL_apm 9 #define DEBUG_unimplemented 2 diff -Nru seabios-1.7.1/src/coreboot.c seabios-1.7.4/src/coreboot.c --- seabios-1.7.1/src/coreboot.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/coreboot.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,457 +0,0 @@ -// Coreboot interface support. -// -// Copyright (C) 2008,2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "memmap.h" // add_e820 -#include "util.h" // dprintf -#include "lzmadecode.h" // LzmaDecode -#include "smbios.h" // smbios_init -#include "boot.h" // boot_add_cbfs -#include "disk.h" // MAXDESCSIZE -#include "config.h" // CONFIG_* - - -/**************************************************************** - * Memory map - ****************************************************************/ - -struct cb_header { - u32 signature; - u32 header_bytes; - u32 header_checksum; - u32 table_bytes; - u32 table_checksum; - u32 table_entries; -}; - -#define CB_SIGNATURE 0x4f49424C // "LBIO" - -struct cb_memory_range { - u64 start; - u64 size; - u32 type; -}; - -#define CB_MEM_TABLE 16 - -struct cb_memory { - u32 tag; - u32 size; - struct cb_memory_range map[0]; -}; - -#define CB_TAG_MEMORY 0x01 - -#define MEM_RANGE_COUNT(_rec) \ - (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0])) - -struct cb_mainboard { - u32 tag; - u32 size; - u8 vendor_idx; - u8 part_idx; - char strings[0]; -}; - -#define CB_TAG_MAINBOARD 0x0003 - -struct cb_forward { - u32 tag; - u32 size; - u64 forward; -}; - -#define CB_TAG_FORWARD 0x11 - -static u16 -ipchksum(char *buf, int count) -{ - u16 *p = (u16*)buf; - u32 sum = 0; - while (count > 1) { - sum += *p++; - count -= 2; - } - if (count) - sum += *(u8*)p; - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - return ~sum; -} - -// Try to locate the coreboot header in a given address range. -static struct cb_header * -find_cb_header(char *addr, int len) -{ - char *end = addr + len; - for (; addr < end; addr += 16) { - struct cb_header *cbh = (struct cb_header *)addr; - if (cbh->signature != CB_SIGNATURE) - continue; - if (! cbh->table_bytes) - continue; - if (ipchksum(addr, sizeof(*cbh)) != 0) - continue; - if (ipchksum(addr + sizeof(*cbh), cbh->table_bytes) - != cbh->table_checksum) - continue; - return cbh; - } - return NULL; -} - -// Try to find the coreboot memory table in the given coreboot table. -static void * -find_cb_subtable(struct cb_header *cbh, u32 tag) -{ - char *tbl = (char *)cbh + sizeof(*cbh); - int i; - for (i=0; itable_entries; i++) { - struct cb_memory *cbm = (struct cb_memory *)tbl; - tbl += cbm->size; - if (cbm->tag == tag) - return cbm; - } - return NULL; -} - -static struct cb_memory *CBMemTable; -const char *CBvendor = "", *CBpart = ""; - -// Populate max ram and e820 map info by scanning for a coreboot table. -void -coreboot_setup(void) -{ - dprintf(3, "Attempting to find coreboot table\n"); - - // Find coreboot table. - struct cb_header *cbh = find_cb_header(0, 0x1000); - if (!cbh) - goto fail; - struct cb_forward *cbf = find_cb_subtable(cbh, CB_TAG_FORWARD); - if (cbf) { - dprintf(3, "Found coreboot table forwarder.\n"); - cbh = find_cb_header((char *)((u32)cbf->forward), 0x100); - if (!cbh) - goto fail; - } - dprintf(3, "Now attempting to find coreboot memory map\n"); - struct cb_memory *cbm = CBMemTable = find_cb_subtable(cbh, CB_TAG_MEMORY); - if (!cbm) - goto fail; - - u64 maxram = 0, maxram_over4G = 0; - int i, count = MEM_RANGE_COUNT(cbm); - for (i=0; imap[i]; - u32 type = m->type; - if (type == CB_MEM_TABLE) { - type = E820_RESERVED; - } else if (type == E820_ACPI || type == E820_RAM) { - u64 end = m->start + m->size; - if (end > 0x100000000ull) { - end -= 0x100000000ull; - if (end > maxram_over4G) - maxram_over4G = end; - } else if (end > maxram) - maxram = end; - } - add_e820(m->start, m->size, type); - } - - RamSize = maxram; - RamSizeOver4G = maxram_over4G; - - // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this - // confuses grub. So, override it. - add_e820(0, 16*1024, E820_RAM); - - struct cb_mainboard *cbmb = find_cb_subtable(cbh, CB_TAG_MAINBOARD); - if (cbmb) { - CBvendor = &cbmb->strings[cbmb->vendor_idx]; - CBpart = &cbmb->strings[cbmb->part_idx]; - dprintf(1, "Found mainboard %s %s\n", CBvendor, CBpart); - } - - return; - -fail: - // No table found.. Use 16Megs as a dummy value. - dprintf(1, "Unable to find coreboot table!\n"); - RamSize = 16*1024*1024; - RamSizeOver4G = 0; - add_e820(0, 16*1024*1024, E820_RAM); - return; -} - - -/**************************************************************** - * BIOS table copying - ****************************************************************/ - -// Attempt to find (and relocate) any standard bios tables found in a -// given address range. -static void -scan_tables(u32 start, u32 size) -{ - void *p = (void*)ALIGN(start, 16); - void *end = (void*)start + size; - for (; pmap[i]; - if (m->type == CB_MEM_TABLE) - scan_tables(m->start, m->size); - } -} - - -/**************************************************************** - * ulzma - ****************************************************************/ - -// Uncompress data in flash to an area of memory. -static int -ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen) -{ - dprintf(3, "Uncompressing data %d@%p to %d@%p\n", srclen, src, maxlen, dst); - CLzmaDecoderState state; - int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); - if (ret != LZMA_RESULT_OK) { - dprintf(1, "LzmaDecodeProperties error - %d\n", ret); - return -1; - } - u8 scratch[15980]; - int need = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); - if (need > sizeof(scratch)) { - dprintf(1, "LzmaDecode need %d have %d\n", need, (unsigned int)sizeof(scratch)); - return -1; - } - state.Probs = (CProb *)scratch; - - u32 dstlen = *(u32*)(src + LZMA_PROPERTIES_SIZE); - if (dstlen > maxlen) { - dprintf(1, "LzmaDecode too large (max %d need %d)\n", maxlen, dstlen); - return -1; - } - u32 inProcessed, outProcessed; - ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, srclen - , &inProcessed, dst, dstlen, &outProcessed); - if (ret) { - dprintf(1, "LzmaDecode returned %d\n", ret); - return -1; - } - return dstlen; -} - - -/**************************************************************** - * Coreboot flash format - ****************************************************************/ - -#define CBFS_HEADER_MAGIC 0x4F524243 -#define CBFS_HEADPTR_ADDR 0xFFFFFFFc -#define CBFS_VERSION1 0x31313131 - -struct cbfs_header { - u32 magic; - u32 version; - u32 romsize; - u32 bootblocksize; - u32 align; - u32 offset; - u32 pad[2]; -} PACKED; - -#define CBFS_FILE_MAGIC 0x455649484352414cLL // LARCHIVE - -struct cbfs_file { - u64 magic; - u32 len; - u32 type; - u32 checksum; - u32 offset; - char filename[0]; -} PACKED; - -// Copy a file to memory (uncompressing if necessary) -static int -cbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) -{ - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) - return -1; - - u32 size = file->rawsize; - void *src = file->data; - if (file->flags) { - // Compressed - copy to temp ram and uncompress it. - void *temp = malloc_tmphigh(size); - if (!temp) { - warn_noalloc(); - return -1; - } - iomemcpy(temp, src, size); - int ret = ulzma(dst, maxlen, temp, size); - yield(); - free(temp); - return ret; - } - - // Not compressed. - dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst); - if (size > maxlen) { - warn_noalloc(); - return -1; - } - iomemcpy(dst, src, size); - return size; -} - -void -coreboot_cbfs_setup(void) -{ - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) - return; - - struct cbfs_header *hdr = *(void **)CBFS_HEADPTR_ADDR; - if (hdr->magic != htonl(CBFS_HEADER_MAGIC)) { - dprintf(1, "Unable to find CBFS (ptr=%p; got %x not %x)\n" - , hdr, hdr->magic, htonl(CBFS_HEADER_MAGIC)); - return; - } - dprintf(1, "Found CBFS header at %p\n", hdr); - - struct cbfs_file *cfile = (void *)(0 - ntohl(hdr->romsize) - + ntohl(hdr->offset)); - for (;;) { - if (cfile < (struct cbfs_file *)(0xFFFFFFFF - ntohl(hdr->romsize))) - break; - u64 magic = cfile->magic; - if (magic != CBFS_FILE_MAGIC) - break; - struct romfile_s *file = malloc_tmp(sizeof(*file)); - if (!file) { - warn_noalloc(); - break; - } - memset(file, 0, sizeof(*file)); - strtcpy(file->name, cfile->filename, sizeof(file->name)); - dprintf(3, "Found CBFS file: %s\n", file->name); - file->size = file->rawsize = ntohl(cfile->len); - file->id = (u32)cfile; - file->copy = cbfs_copyfile; - file->data = (void*)cfile + ntohl(cfile->offset); - int len = strlen(file->name); - if (len > 5 && strcmp(&file->name[len-5], ".lzma") == 0) { - // Using compression. - file->flags = 1; - file->name[len-5] = '\0'; - file->size = *(u32*)(file->data + LZMA_PROPERTIES_SIZE); - } - romfile_add(file); - - cfile = (void*)ALIGN((u32)file->data + file->size, ntohl(hdr->align)); - } -} - -struct cbfs_payload_segment { - u32 type; - u32 compression; - u32 offset; - u64 load_addr; - u32 len; - u32 mem_len; -} PACKED; - -#define PAYLOAD_SEGMENT_BSS 0x20535342 -#define PAYLOAD_SEGMENT_ENTRY 0x52544E45 - -#define CBFS_COMPRESS_NONE 0 -#define CBFS_COMPRESS_LZMA 1 - -struct cbfs_payload { - struct cbfs_payload_segment segments[1]; -}; - -void -cbfs_run_payload(struct cbfs_file *file) -{ - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH || !file) - return; - dprintf(1, "Run %s\n", file->filename); - struct cbfs_payload *pay = (void*)file + ntohl(file->offset); - struct cbfs_payload_segment *seg = pay->segments; - for (;;) { - void *src = (void*)pay + ntohl(seg->offset); - void *dest = (void*)ntohl((u32)seg->load_addr); - u32 src_len = ntohl(seg->len); - u32 dest_len = ntohl(seg->mem_len); - switch (seg->type) { - case PAYLOAD_SEGMENT_BSS: - dprintf(3, "BSS segment %d@%p\n", dest_len, dest); - memset(dest, 0, dest_len); - break; - case PAYLOAD_SEGMENT_ENTRY: { - dprintf(1, "Calling addr %p\n", dest); - void (*func)() = dest; - func(); - return; - } - default: - dprintf(3, "Segment %x %d@%p -> %d@%p\n" - , seg->type, src_len, src, dest_len, dest); - if (seg->compression == htonl(CBFS_COMPRESS_NONE)) { - if (src_len > dest_len) - src_len = dest_len; - memcpy(dest, src, src_len); - } else if (CONFIG_LZMA - && seg->compression == htonl(CBFS_COMPRESS_LZMA)) { - int ret = ulzma(dest, dest_len, src, src_len); - if (ret < 0) - return; - src_len = ret; - } else { - dprintf(1, "No support for compression type %x\n" - , seg->compression); - return; - } - if (dest_len > src_len) - memset(dest + src_len, 0, dest_len - src_len); - break; - } - seg++; - } -} - -// Register payloads in "img/" directory with boot system. -void -cbfs_payload_setup(void) -{ - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) - return; - struct romfile_s *file = NULL; - for (;;) { - file = romfile_findprefix("img/", file); - if (!file) - break; - const char *filename = file->name; - char *desc = znprintf(MAXDESCSIZE, "Payload [%s]", &filename[4]); - boot_add_cbfs((void*)file->id, desc - , bootprio_find_named_rom(filename, 0)); - } -} diff -Nru seabios-1.7.1/src/disk.c seabios-1.7.4/src/disk.c --- seabios-1.7.1/src/disk.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/disk.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,45 +5,23 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "disk.h" // floppy_13 #include "biosvar.h" // SET_BDA -#include "config.h" // CONFIG_* -#include "util.h" // debug_enter -#include "pic.h" // eoi_pic2 #include "bregs.h" // struct bregs -#include "pci.h" // pci_bdf_to_bus -#include "ata.h" // ATA_CB_DC +#include "config.h" // CONFIG_* +#include "hw/ata.h" // ATA_CB_DC +#include "hw/pci.h" // pci_bdf_to_bus +#include "hw/pic.h" // pic_eoi2 +#include "output.h" // debug_enter +#include "stacks.h" // call16_int +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // CDRom_locks /**************************************************************** * Helper functions ****************************************************************/ -void -__disk_ret(struct bregs *regs, u32 linecode, const char *fname) -{ - u8 code = linecode; - if (regs->dl < EXTSTART_HD) - SET_BDA(floppy_last_status, code); - else - SET_BDA(disk_last_status, code); - if (code) - __set_code_invalid(regs, linecode, fname); - else - set_code_success(regs); -} - -void -__disk_ret_unimplemented(struct bregs *regs, u32 linecode, const char *fname) -{ - u8 code = linecode; - if (regs->dl < EXTSTART_HD) - SET_BDA(floppy_last_status, code); - else - SET_BDA(disk_last_status, code); - __set_code_unimplemented(regs, linecode, fname); -} - static void __disk_stub(struct bregs *regs, int lineno, const char *fname) { @@ -56,32 +34,31 @@ // Get the cylinders/heads/sectors for the given drive. static struct chs_s -getLCHS(struct drive_s *drive_g) +getLCHS(struct drive_s *drive_gf) { struct chs_s res = { }; - if (CONFIG_CDROM_EMU - && drive_g == GLOBALFLAT2GLOBAL(GET_GLOBAL(cdemu_drive_gf))) { + if (CONFIG_CDROM_EMU && drive_gf == GET_GLOBAL(cdemu_drive_gf)) { // Emulated drive - get info from CDEmu. (It's not possible to // populate the geometry directly in the driveid because the // geometry is only known after the bios segment is made // read-only). - res.cylinders = GET_LOW(CDEmu.lchs.cylinders); - res.heads = GET_LOW(CDEmu.lchs.heads); - res.spt = GET_LOW(CDEmu.lchs.spt); + res.cylinder = GET_LOW(CDEmu.lchs.cylinder); + res.head = GET_LOW(CDEmu.lchs.head); + res.sector = GET_LOW(CDEmu.lchs.sector); return res; } - res.cylinders = GET_GLOBAL(drive_g->lchs.cylinders); - res.heads = GET_GLOBAL(drive_g->lchs.heads); - res.spt = GET_GLOBAL(drive_g->lchs.spt); + res.cylinder = GET_GLOBALFLAT(drive_gf->lchs.cylinder); + res.head = GET_GLOBALFLAT(drive_gf->lchs.head); + res.sector = GET_GLOBALFLAT(drive_gf->lchs.sector); return res; } // Perform read/write/verify using old-style chs accesses static void noinline -basic_access(struct bregs *regs, struct drive_s *drive_g, u16 command) +basic_access(struct bregs *regs, struct drive_s *drive_gf, u16 command) { struct disk_op_s dop; - dop.drive_g = drive_g; + dop.drive_gf = drive_gf; dop.command = command; u8 count = regs->al; @@ -96,18 +73,18 @@ } dop.count = count; - struct chs_s chs = getLCHS(drive_g); - u16 nlc=chs.cylinders, nlh=chs.heads, nlspt=chs.spt; + struct chs_s chs = getLCHS(drive_gf); + u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector; // sanity check on cyl heads, sec - if (cylinder >= nlc || head >= nlh || sector > nlspt) { + if (cylinder >= nlc || head >= nlh || sector > nls) { warn_invalid(regs); disk_ret(regs, DISK_RET_EPARAM); return; } // translate lchs to lba - dop.lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) + dop.lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nls) + (u32)sector - 1); dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx); @@ -121,15 +98,15 @@ // Perform read/write/verify using new-style "int13ext" accesses. static void noinline -extended_access(struct bregs *regs, struct drive_s *drive_g, u16 command) +extended_access(struct bregs *regs, struct drive_s *drive_gf, u16 command) { struct disk_op_s dop; struct int13ext_s *param_far = (struct int13ext_s*)(regs->si+0); // Get lba and check. dop.lba = GET_FARVAR(regs->ds, param_far->lba); dop.command = command; - dop.drive_g = drive_g; - if (dop.lba >= GET_GLOBAL(drive_g->sectors)) { + dop.drive_gf = drive_gf; + if (dop.lba >= GET_GLOBALFLAT(drive_gf->sectors)) { warn_invalid(regs); disk_ret(regs, DISK_RET_EPARAM); return; @@ -157,10 +134,10 @@ // disk controller reset static void -disk_1300(struct bregs *regs, struct drive_s *drive_g) +disk_1300(struct bregs *regs, struct drive_s *drive_gf) { struct disk_op_s dop; - dop.drive_g = drive_g; + dop.drive_gf = drive_gf; dop.command = CMD_RESET; int status = send_disk_op(&dop); disk_ret(regs, status); @@ -168,7 +145,7 @@ // read disk status static void -disk_1301(struct bregs *regs, struct drive_s *drive_g) +disk_1301(struct bregs *regs, struct drive_s *drive_gf) { u8 v; if (regs->dl < EXTSTART_HD) @@ -183,47 +160,48 @@ // read disk sectors static void -disk_1302(struct bregs *regs, struct drive_s *drive_g) +disk_1302(struct bregs *regs, struct drive_s *drive_gf) { - basic_access(regs, drive_g, CMD_READ); + basic_access(regs, drive_gf, CMD_READ); } // write disk sectors static void -disk_1303(struct bregs *regs, struct drive_s *drive_g) +disk_1303(struct bregs *regs, struct drive_s *drive_gf) { - basic_access(regs, drive_g, CMD_WRITE); + basic_access(regs, drive_gf, CMD_WRITE); } // verify disk sectors static void -disk_1304(struct bregs *regs, struct drive_s *drive_g) +disk_1304(struct bregs *regs, struct drive_s *drive_gf) { - basic_access(regs, drive_g, CMD_VERIFY); + basic_access(regs, drive_gf, CMD_VERIFY); } // format disk track static void noinline -disk_1305(struct bregs *regs, struct drive_s *drive_g) +disk_1305(struct bregs *regs, struct drive_s *drive_gf) { debug_stub(regs); - struct chs_s chs = getLCHS(drive_g); - u16 nlh=chs.heads, nlspt=chs.spt; + struct chs_s chs = getLCHS(drive_gf); + u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector; - u8 num_sectors = regs->al; - u8 head = regs->dh; + u8 count = regs->al; + u8 cylinder = regs->ch; + u8 head = regs->dh; - if (head >= nlh || num_sectors == 0 || num_sectors > nlspt) { + if (cylinder >= nlc || head >= nlh || count == 0 || count > nls) { disk_ret(regs, DISK_RET_EPARAM); return; } struct disk_op_s dop; - dop.drive_g = drive_g; + dop.drive_gf = drive_gf; dop.command = CMD_FORMAT; - dop.lba = head; - dop.count = num_sectors; + dop.lba = (((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nls; + dop.count = count; dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx); int status = send_disk_op(&dop); disk_ret(regs, status); @@ -231,11 +209,11 @@ // read disk drive parameters static void noinline -disk_1308(struct bregs *regs, struct drive_s *drive_g) +disk_1308(struct bregs *regs, struct drive_s *drive_gf) { // Get logical geometry from table - struct chs_s chs = getLCHS(drive_g); - u16 nlc=chs.cylinders, nlh=chs.heads, nlspt=chs.spt; + struct chs_s chs = getLCHS(drive_gf); + u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector; nlc--; nlh--; u8 count; @@ -243,11 +221,10 @@ // Floppy count = GET_GLOBAL(FloppyCount); - if (CONFIG_CDROM_EMU - && drive_g == GLOBALFLAT2GLOBAL(GET_GLOBAL(cdemu_drive_gf))) + if (CONFIG_CDROM_EMU && drive_gf == GET_GLOBAL(cdemu_drive_gf)) regs->bx = GET_LOW(CDEmu.media) * 2; else - regs->bx = GET_GLOBAL(drive_g->floppy_type); + regs->bx = GET_GLOBALFLAT(drive_gf->floppy_type); // set es & di to point to 11 byte diskette param table in ROM regs->es = SEG_BIOS; @@ -274,7 +251,7 @@ regs->al = 0; regs->ch = nlc & 0xff; - regs->cl = ((nlc >> 2) & 0xc0) | (nlspt & 0x3f); + regs->cl = ((nlc >> 2) & 0xc0) | (nls & 0x3f); regs->dh = nlh; disk_ret(regs, DISK_RET_SUCCESS); @@ -283,33 +260,33 @@ // initialize drive parameters static void -disk_1309(struct bregs *regs, struct drive_s *drive_g) +disk_1309(struct bregs *regs, struct drive_s *drive_gf) { DISK_STUB(regs); } // seek to specified cylinder static void -disk_130c(struct bregs *regs, struct drive_s *drive_g) +disk_130c(struct bregs *regs, struct drive_s *drive_gf) { DISK_STUB(regs); } // alternate disk reset static void -disk_130d(struct bregs *regs, struct drive_s *drive_g) +disk_130d(struct bregs *regs, struct drive_s *drive_gf) { DISK_STUB(regs); } // check drive ready static void -disk_1310(struct bregs *regs, struct drive_s *drive_g) +disk_1310(struct bregs *regs, struct drive_s *drive_gf) { // should look at 40:8E also??? struct disk_op_s dop; - dop.drive_g = drive_g; + dop.drive_gf = drive_gf; dop.command = CMD_ISREADY; int status = send_disk_op(&dop); disk_ret(regs, status); @@ -317,21 +294,21 @@ // recalibrate static void -disk_1311(struct bregs *regs, struct drive_s *drive_g) +disk_1311(struct bregs *regs, struct drive_s *drive_gf) { DISK_STUB(regs); } // controller internal diagnostic static void -disk_1314(struct bregs *regs, struct drive_s *drive_g) +disk_1314(struct bregs *regs, struct drive_s *drive_gf) { DISK_STUB(regs); } // read disk drive size static void noinline -disk_1315(struct bregs *regs, struct drive_s *drive_g) +disk_1315(struct bregs *regs, struct drive_s *drive_gf) { disk_ret(regs, DISK_RET_SUCCESS); if (regs->dl < EXTSTART_HD || regs->dl >= EXTSTART_CD) { @@ -342,18 +319,18 @@ // Hard drive // Get logical geometry from table - struct chs_s chs = getLCHS(drive_g); - u16 nlc=chs.cylinders, nlh=chs.heads, nlspt=chs.spt; + struct chs_s chs = getLCHS(drive_gf); + u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector; // Compute sector count seen by int13 - u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nlspt; + u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nls; regs->cx = lba >> 16; regs->dx = lba & 0xffff; regs->ah = 3; // hard disk accessible } static void -disk_1316(struct bregs *regs, struct drive_s *drive_g) +disk_1316(struct bregs *regs, struct drive_s *drive_gf) { if (regs->dl >= EXTSTART_HD) { // Hard drive @@ -365,7 +342,7 @@ // IBM/MS installation check static void -disk_1341(struct bregs *regs, struct drive_s *drive_g) +disk_1341(struct bregs *regs, struct drive_s *drive_gf) { regs->bx = 0xaa55; // install check regs->cx = 0x0007; // ext disk access and edd, removable supported @@ -375,28 +352,28 @@ // IBM/MS extended read static void -disk_1342(struct bregs *regs, struct drive_s *drive_g) +disk_1342(struct bregs *regs, struct drive_s *drive_gf) { - extended_access(regs, drive_g, CMD_READ); + extended_access(regs, drive_gf, CMD_READ); } // IBM/MS extended write static void -disk_1343(struct bregs *regs, struct drive_s *drive_g) +disk_1343(struct bregs *regs, struct drive_s *drive_gf) { - extended_access(regs, drive_g, CMD_WRITE); + extended_access(regs, drive_gf, CMD_WRITE); } // IBM/MS verify static void -disk_1344(struct bregs *regs, struct drive_s *drive_g) +disk_1344(struct bregs *regs, struct drive_s *drive_gf) { - extended_access(regs, drive_g, CMD_VERIFY); + extended_access(regs, drive_gf, CMD_VERIFY); } // lock static void -disk_134500(struct bregs *regs, struct drive_s *drive_g) +disk_134500(struct bregs *regs, struct drive_s *drive_gf) { int cdid = regs->dl - EXTSTART_CD; u8 locks = GET_LOW(CDRom_locks[cdid]); @@ -412,7 +389,7 @@ // unlock static void -disk_134501(struct bregs *regs, struct drive_s *drive_g) +disk_134501(struct bregs *regs, struct drive_s *drive_gf) { int cdid = regs->dl - EXTSTART_CD; u8 locks = GET_LOW(CDRom_locks[cdid]); @@ -429,7 +406,7 @@ // status static void -disk_134502(struct bregs *regs, struct drive_s *drive_g) +disk_134502(struct bregs *regs, struct drive_s *drive_gf) { int cdid = regs->dl - EXTSTART_CD; u8 locks = GET_LOW(CDRom_locks[cdid]); @@ -438,14 +415,14 @@ } static void -disk_1345XX(struct bregs *regs, struct drive_s *drive_g) +disk_1345XX(struct bregs *regs, struct drive_s *drive_gf) { disk_ret_unimplemented(regs, DISK_RET_EPARAM); } // IBM/MS lock/unlock drive static void -disk_1345(struct bregs *regs, struct drive_s *drive_g) +disk_1345(struct bregs *regs, struct drive_s *drive_gf) { if (regs->dl < EXTSTART_CD) { // Always success for HD @@ -454,16 +431,16 @@ } switch (regs->al) { - case 0x00: disk_134500(regs, drive_g); break; - case 0x01: disk_134501(regs, drive_g); break; - case 0x02: disk_134502(regs, drive_g); break; - default: disk_1345XX(regs, drive_g); break; + case 0x00: disk_134500(regs, drive_gf); break; + case 0x01: disk_134501(regs, drive_gf); break; + case 0x02: disk_134502(regs, drive_gf); break; + default: disk_1345XX(regs, drive_gf); break; } } // IBM/MS eject media static void noinline -disk_1346(struct bregs *regs, struct drive_s *drive_g) +disk_1346(struct bregs *regs, struct drive_s *drive_gf) { if (regs->dl < EXTSTART_CD) { // Volume Not Removable @@ -497,14 +474,14 @@ // IBM/MS extended seek static void -disk_1347(struct bregs *regs, struct drive_s *drive_g) +disk_1347(struct bregs *regs, struct drive_s *drive_gf) { - extended_access(regs, drive_g, CMD_SEEK); + extended_access(regs, drive_gf, CMD_SEEK); } // IBM/MS get drive parameters static void noinline -disk_1348(struct bregs *regs, struct drive_s *drive_g) +disk_1348(struct bregs *regs, struct drive_s *drive_gf) { u16 seg = regs->ds; struct int13dpt_s *param_far = (struct int13dpt_s*)(regs->si+0); @@ -519,15 +496,15 @@ // EDD 1.x - u8 type = GET_GLOBAL(drive_g->type); - u16 npc = GET_GLOBAL(drive_g->pchs.cylinders); - u16 nph = GET_GLOBAL(drive_g->pchs.heads); - u16 npspt = GET_GLOBAL(drive_g->pchs.spt); - u64 lba = GET_GLOBAL(drive_g->sectors); - u16 blksize = GET_GLOBAL(drive_g->blksize); + u8 type = GET_GLOBALFLAT(drive_gf->type); + u16 npc = GET_GLOBALFLAT(drive_gf->pchs.cylinder); + u16 nph = GET_GLOBALFLAT(drive_gf->pchs.head); + u16 nps = GET_GLOBALFLAT(drive_gf->pchs.sector); + u64 lba = GET_GLOBALFLAT(drive_gf->sectors); + u16 blksize = GET_GLOBALFLAT(drive_gf->blksize); dprintf(DEBUG_HDL_13, "disk_1348 size=%d t=%d chs=%d,%d,%d lba=%d bs=%d\n" - , size, type, npc, nph, npspt, (u32)lba, blksize); + , size, type, npc, nph, nps, (u32)lba, blksize); SET_FARVAR(seg, param_far->size, 26); if (type == DTYPE_ATA_ATAPI) { @@ -538,7 +515,7 @@ SET_FARVAR(seg, param_far->spt, 0xffffffff); SET_FARVAR(seg, param_far->sector_count, (u64)-1); } else { - if (lba > (u64)npspt*nph*0x3fff) { + if (lba > (u64)nps*nph*0x3fff) { SET_FARVAR(seg, param_far->infos, 0x00); // geometry is invalid SET_FARVAR(seg, param_far->cylinders, 0x3fff); } else { @@ -546,7 +523,7 @@ SET_FARVAR(seg, param_far->cylinders, (u32)npc); } SET_FARVAR(seg, param_far->heads, (u32)nph); - SET_FARVAR(seg, param_far->spt, (u32)npspt); + SET_FARVAR(seg, param_far->spt, (u32)nps); SET_FARVAR(seg, param_far->sector_count, lba); } SET_FARVAR(seg, param_far->blksize, blksize); @@ -569,10 +546,10 @@ SET_FARVAR(seg, param_far->dpte, SEGOFF(SEG_LOW, (u32)&DefaultDPTE)); // Fill in dpte - struct atadrive_s *adrive_g = container_of( - drive_g, struct atadrive_s, drive); - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u8 slave = GET_GLOBAL(adrive_g->slave); + struct atadrive_s *adrive_gf = container_of( + drive_gf, struct atadrive_s, drive); + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u8 slave = GET_GLOBALFLAT(adrive_gf->slave); u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); u8 irq = GET_GLOBALFLAT(chan_gf->irq); iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); @@ -582,7 +559,7 @@ u16 options = 0; if (type == DTYPE_ATA) { - u8 translation = GET_GLOBAL(drive_g->translation); + u8 translation = GET_GLOBALFLAT(drive_gf->translation); if (translation != TRANSLATION_NONE) { options |= 1<<3; // CHS translation if (translation == TRANSLATION_LBA) @@ -615,8 +592,8 @@ u8 sum = checksum_far(SEG_LOW, &DefaultDPTE, 15); SET_LOW(DefaultDPTE.checksum, -sum); } else { - SET_FARVAR(seg, param_far->dpte.segoff, 0); - bdf = GET_GLOBAL(drive_g->cntl_id); + SET_FARVAR(seg, param_far->dpte.segoff, 0xffffffff); + bdf = GET_GLOBALFLAT(drive_gf->cntl_id); } if (size < 66) { @@ -686,7 +663,7 @@ // IBM/MS extended media change static void -disk_1349(struct bregs *regs, struct drive_s *drive_g) +disk_1349(struct bregs *regs, struct drive_s *drive_gf) { if (regs->dl < EXTSTART_CD) { // Always success for HD @@ -699,56 +676,56 @@ } static void -disk_134e01(struct bregs *regs, struct drive_s *drive_g) +disk_134e01(struct bregs *regs, struct drive_s *drive_gf) { disk_ret(regs, DISK_RET_SUCCESS); } static void -disk_134e03(struct bregs *regs, struct drive_s *drive_g) +disk_134e03(struct bregs *regs, struct drive_s *drive_gf) { disk_ret(regs, DISK_RET_SUCCESS); } static void -disk_134e04(struct bregs *regs, struct drive_s *drive_g) +disk_134e04(struct bregs *regs, struct drive_s *drive_gf) { disk_ret(regs, DISK_RET_SUCCESS); } static void -disk_134e06(struct bregs *regs, struct drive_s *drive_g) +disk_134e06(struct bregs *regs, struct drive_s *drive_gf) { disk_ret(regs, DISK_RET_SUCCESS); } static void -disk_134eXX(struct bregs *regs, struct drive_s *drive_g) +disk_134eXX(struct bregs *regs, struct drive_s *drive_gf) { disk_ret(regs, DISK_RET_EPARAM); } // IBM/MS set hardware configuration static void -disk_134e(struct bregs *regs, struct drive_s *drive_g) +disk_134e(struct bregs *regs, struct drive_s *drive_gf) { switch (regs->al) { - case 0x01: disk_134e01(regs, drive_g); break; - case 0x03: disk_134e03(regs, drive_g); break; - case 0x04: disk_134e04(regs, drive_g); break; - case 0x06: disk_134e06(regs, drive_g); break; - default: disk_134eXX(regs, drive_g); break; + case 0x01: disk_134e01(regs, drive_gf); break; + case 0x03: disk_134e03(regs, drive_gf); break; + case 0x04: disk_134e04(regs, drive_gf); break; + case 0x06: disk_134e06(regs, drive_gf); break; + default: disk_134eXX(regs, drive_gf); break; } } static void -disk_13XX(struct bregs *regs, struct drive_s *drive_g) +disk_13XX(struct bregs *regs, struct drive_s *drive_gf) { disk_ret_unimplemented(regs, DISK_RET_EPARAM); } static void -disk_13(struct bregs *regs, struct drive_s *drive_g) +disk_13(struct bregs *regs, struct drive_s *drive_gf) { //debug_stub(regs); @@ -756,37 +733,37 @@ SET_BDA(disk_interrupt_flag, 0); switch (regs->ah) { - case 0x00: disk_1300(regs, drive_g); break; - case 0x01: disk_1301(regs, drive_g); break; - case 0x02: disk_1302(regs, drive_g); break; - case 0x03: disk_1303(regs, drive_g); break; - case 0x04: disk_1304(regs, drive_g); break; - case 0x05: disk_1305(regs, drive_g); break; - case 0x08: disk_1308(regs, drive_g); break; - case 0x09: disk_1309(regs, drive_g); break; - case 0x0c: disk_130c(regs, drive_g); break; - case 0x0d: disk_130d(regs, drive_g); break; - case 0x10: disk_1310(regs, drive_g); break; - case 0x11: disk_1311(regs, drive_g); break; - case 0x14: disk_1314(regs, drive_g); break; - case 0x15: disk_1315(regs, drive_g); break; - case 0x16: disk_1316(regs, drive_g); break; - case 0x41: disk_1341(regs, drive_g); break; - case 0x42: disk_1342(regs, drive_g); break; - case 0x43: disk_1343(regs, drive_g); break; - case 0x44: disk_1344(regs, drive_g); break; - case 0x45: disk_1345(regs, drive_g); break; - case 0x46: disk_1346(regs, drive_g); break; - case 0x47: disk_1347(regs, drive_g); break; - case 0x48: disk_1348(regs, drive_g); break; - case 0x49: disk_1349(regs, drive_g); break; - case 0x4e: disk_134e(regs, drive_g); break; - default: disk_13XX(regs, drive_g); break; + case 0x00: disk_1300(regs, drive_gf); break; + case 0x01: disk_1301(regs, drive_gf); break; + case 0x02: disk_1302(regs, drive_gf); break; + case 0x03: disk_1303(regs, drive_gf); break; + case 0x04: disk_1304(regs, drive_gf); break; + case 0x05: disk_1305(regs, drive_gf); break; + case 0x08: disk_1308(regs, drive_gf); break; + case 0x09: disk_1309(regs, drive_gf); break; + case 0x0c: disk_130c(regs, drive_gf); break; + case 0x0d: disk_130d(regs, drive_gf); break; + case 0x10: disk_1310(regs, drive_gf); break; + case 0x11: disk_1311(regs, drive_gf); break; + case 0x14: disk_1314(regs, drive_gf); break; + case 0x15: disk_1315(regs, drive_gf); break; + case 0x16: disk_1316(regs, drive_gf); break; + case 0x41: disk_1341(regs, drive_gf); break; + case 0x42: disk_1342(regs, drive_gf); break; + case 0x43: disk_1343(regs, drive_gf); break; + case 0x44: disk_1344(regs, drive_gf); break; + case 0x45: disk_1345(regs, drive_gf); break; + case 0x46: disk_1346(regs, drive_gf); break; + case 0x47: disk_1347(regs, drive_gf); break; + case 0x48: disk_1348(regs, drive_gf); break; + case 0x49: disk_1349(regs, drive_gf); break; + case 0x4e: disk_134e(regs, drive_gf); break; + default: disk_13XX(regs, drive_gf); break; } } static void -floppy_13(struct bregs *regs, struct drive_s *drive_g) +floppy_13(struct bregs *regs, struct drive_s *drive_gf) { // Only limited commands are supported on floppies. switch (regs->ah) { @@ -799,9 +776,9 @@ case 0x08: case 0x15: case 0x16: - disk_13(regs, drive_g); + disk_13(regs, drive_gf); break; - default: disk_13XX(regs, drive_g); break; + default: disk_13XX(regs, drive_gf); break; } } @@ -820,21 +797,21 @@ } if (extdrive < EXTSTART_HD) { - struct drive_s *drive_g = getDrive(EXTTYPE_FLOPPY, extdrive); - if (!drive_g) + struct drive_s *drive_gf = getDrive(EXTTYPE_FLOPPY, extdrive); + if (!drive_gf) goto fail; - floppy_13(regs, drive_g); + floppy_13(regs, drive_gf); return; } - struct drive_s *drive_g; + struct drive_s *drive_gf; if (extdrive >= EXTSTART_CD) - drive_g = getDrive(EXTTYPE_CD, extdrive - EXTSTART_CD); + drive_gf = getDrive(EXTTYPE_CD, extdrive - EXTSTART_CD); else - drive_g = getDrive(EXTTYPE_HD, extdrive - EXTSTART_HD); - if (!drive_g) + drive_gf = getDrive(EXTTYPE_HD, extdrive - EXTSTART_HD); + if (!drive_gf) goto fail; - disk_13(regs, drive_g); + disk_13(regs, drive_gf); return; fail: @@ -865,14 +842,13 @@ u8 emudrive = GET_LOW(CDEmu.emulated_extdrive); if (extdrive == emudrive) { // Access to an emulated drive. - struct drive_s *cdemu_g; - cdemu_g = GLOBALFLAT2GLOBAL(GET_GLOBAL(cdemu_drive_gf)); + struct drive_s *cdemu_gf = GET_GLOBAL(cdemu_drive_gf); if (regs->ah > 0x16) { // Only old-style commands supported. - disk_13XX(regs, cdemu_g); + disk_13XX(regs, cdemu_gf); return; } - disk_13(regs, cdemu_g); + disk_13(regs, cdemu_gf); return; } if (extdrive < EXTSTART_CD && ((emudrive ^ extdrive) & 0x80) == 0) @@ -889,7 +865,7 @@ { debug_isr(DEBUG_ISR_76); SET_BDA(disk_interrupt_flag, 0xff); - eoi_pic2(); + pic_eoi2(); } // Old Fixed Disk Parameter Table (newer tables are in the ebda). diff -Nru seabios-1.7.1/src/disk.h seabios-1.7.4/src/disk.h --- seabios-1.7.1/src/disk.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/disk.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,291 +0,0 @@ -// Definitions for X86 bios disks. -// -// Copyright (C) 2008 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. -#ifndef __DISK_H -#define __DISK_H - -#include "types.h" // u8 -#include "config.h" // CONFIG_* -#include "farptr.h" // struct segoff_s - -#define DISK_RET_SUCCESS 0x00 -#define DISK_RET_EPARAM 0x01 -#define DISK_RET_EADDRNOTFOUND 0x02 -#define DISK_RET_EWRITEPROTECT 0x03 -#define DISK_RET_ECHANGED 0x06 -#define DISK_RET_EBOUNDARY 0x09 -#define DISK_RET_EBADTRACK 0x0c -#define DISK_RET_ECONTROLLER 0x20 -#define DISK_RET_ETIMEOUT 0x80 -#define DISK_RET_ENOTLOCKED 0xb0 -#define DISK_RET_ELOCKED 0xb1 -#define DISK_RET_ENOTREMOVABLE 0xb2 -#define DISK_RET_ETOOMANYLOCKS 0xb4 -#define DISK_RET_EMEDIA 0xC0 -#define DISK_RET_ENOTREADY 0xAA - - -/**************************************************************** - * Interface structs - ****************************************************************/ - -// Bios disk structures. -struct int13ext_s { - u8 size; - u8 reserved; - u16 count; - struct segoff_s data; - u64 lba; -} PACKED; - -// DPTE definition -struct dpte_s { - u16 iobase1; - u16 iobase2; - u8 prefix; - u8 unused; - u8 irq; - u8 blkcount; - u8 dma; - u8 pio; - u16 options; - u16 reserved; - u8 revision; - u8 checksum; -}; - -extern struct dpte_s DefaultDPTE; - -// Disk Physical Table definition -struct int13dpt_s { - u16 size; - u16 infos; - u32 cylinders; - u32 heads; - u32 spt; - u64 sector_count; - u16 blksize; - struct segoff_s dpte; - u16 key; - u8 dpi_length; - u8 reserved1; - u16 reserved2; - u8 host_bus[4]; - u8 iface_type[8]; - u64 iface_path; - union { - struct { - u64 device_path; - u8 reserved3; - u8 checksum; - } phoenix; - struct { - u64 device_path[2]; - u8 reserved3; - u8 checksum; - } t13; - }; -} PACKED; - -// Floppy "Disk Base Table" -struct floppy_dbt_s { - u8 specify1; - u8 specify2; - u8 shutoff_ticks; - u8 bps_code; - u8 sectors; - u8 interblock_len; - u8 data_len; - u8 gap_len; - u8 fill_byte; - u8 settle_time; - u8 startup_time; -} PACKED; - -struct floppy_ext_dbt_s { - struct floppy_dbt_s dbt; - // Extra fields - u8 max_track; - u8 data_rate; - u8 drive_type; -} PACKED; - -// Helper function for setting up a return code. -struct bregs; -void __disk_ret(struct bregs *regs, u32 linecode, const char *fname); -#define disk_ret(regs, code) \ - __disk_ret((regs), (code) | (__LINE__ << 8), __func__) -void __disk_ret_unimplemented(struct bregs *regs, u32 linecode - , const char *fname); -#define disk_ret_unimplemented(regs, code) \ - __disk_ret_unimplemented((regs), (code) | (__LINE__ << 8), __func__) - - -/**************************************************************** - * Master boot record - ****************************************************************/ - -struct packed_chs_s { - u8 heads; - u8 sptcyl; - u8 cyllow; -}; - -struct partition_s { - u8 status; - struct packed_chs_s first; - u8 type; - struct packed_chs_s last; - u32 lba; - u32 count; -} PACKED; - -struct mbr_s { - u8 code[440]; - // 0x01b8 - u32 diskseg; - // 0x01bc - u16 null; - // 0x01be - struct partition_s partitions[4]; - // 0x01fe - u16 signature; -} PACKED; - -#define MBR_SIGNATURE 0xaa55 - - -/**************************************************************** - * Disk command request - ****************************************************************/ - -struct disk_op_s { - u64 lba; - void *buf_fl; - struct drive_s *drive_g; - u16 count; - u8 command; -}; - -#define CMD_RESET 0x00 -#define CMD_READ 0x02 -#define CMD_WRITE 0x03 -#define CMD_VERIFY 0x04 -#define CMD_FORMAT 0x05 -#define CMD_SEEK 0x07 -#define CMD_ISREADY 0x10 - - -/**************************************************************** - * Global storage - ****************************************************************/ - -struct chs_s { - u16 heads; // # heads - u16 cylinders; // # cylinders - u16 spt; // # sectors / track - u16 pad; -}; - -// ElTorito Device Emulation data -struct cdemu_s { - struct drive_s *emulated_drive_gf; - u32 ilba; - u16 buffer_segment; - u16 load_segment; - u16 sector_count; - u8 active; - u8 media; - u8 emulated_extdrive; - - // Virtual device - struct chs_s lchs; -}; - -struct drive_s { - u8 type; // Driver type (DTYPE_*) - u8 floppy_type; // Type of floppy (only for floppy drives). - struct chs_s lchs; // Logical CHS - u64 sectors; // Total sectors count - u32 cntl_id; // Unique id for a given driver type. - u8 removable; // Is media removable (currently unused) - - // Info for EDD calls - u8 translation; // type of translation - u16 blksize; // block size - struct chs_s pchs; // Physical CHS -}; - -#define DISK_SECTOR_SIZE 512 -#define CDROM_SECTOR_SIZE 2048 - -#define DTYPE_NONE 0x00 -#define DTYPE_FLOPPY 0x01 -#define DTYPE_ATA 0x02 -#define DTYPE_ATA_ATAPI 0x03 -#define DTYPE_RAMDISK 0x04 -#define DTYPE_CDEMU 0x05 -#define DTYPE_AHCI 0x06 -#define DTYPE_AHCI_ATAPI 0x07 -#define DTYPE_VIRTIO_SCSI 0x08 -#define DTYPE_VIRTIO_BLK 0x09 -#define DTYPE_USB 0x0a -#define DTYPE_UAS 0x0b -#define DTYPE_LSI_SCSI 0x0c -#define DTYPE_ESP_SCSI 0x0d - -#define MAXDESCSIZE 80 - -#define TRANSLATION_NONE 0 -#define TRANSLATION_LBA 1 -#define TRANSLATION_LARGE 2 -#define TRANSLATION_RECHS 3 - -#define EXTTYPE_FLOPPY 0 -#define EXTTYPE_HD 1 -#define EXTTYPE_CD 2 - -#define EXTSTART_HD 0x80 -#define EXTSTART_CD 0xE0 - - -/**************************************************************** - * Function defs - ****************************************************************/ - -// block.c -extern u8 FloppyCount, CDCount; -extern u8 *bounce_buf_fl; -struct drive_s *getDrive(u8 exttype, u8 extdriveoffset); -int getDriveId(u8 exttype, struct drive_s *drive_g); -void map_floppy_drive(struct drive_s *drive_g); -void map_hd_drive(struct drive_s *drive_g); -void map_cd_drive(struct drive_s *drive_g); -int process_op(struct disk_op_s *op); -int send_disk_op(struct disk_op_s *op); -int bounce_buf_init(void); - -// floppy.c -extern struct floppy_ext_dbt_s diskette_param_table2; -void floppy_setup(void); -struct drive_s *init_floppy(int floppyid, int ftype); -int find_floppy_type(u32 size); -int process_floppy_op(struct disk_op_s *op); -void floppy_tick(void); - -// cdrom.c -extern u8 CDRom_locks[]; -extern struct cdemu_s CDEmu; -extern struct drive_s *cdemu_drive_gf; -int process_cdemu_op(struct disk_op_s *op); -void cdemu_setup(void); -void cdemu_134b(struct bregs *regs); -int cdrom_boot(struct drive_s *drive_g); - -// ramdisk.c -void ramdisk_setup(void); -int process_ramdisk_op(struct disk_op_s *op); - -#endif // disk.h diff -Nru seabios-1.7.1/src/entryfuncs.S seabios-1.7.4/src/entryfuncs.S --- seabios-1.7.1/src/entryfuncs.S 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/entryfuncs.S 2013-12-23 15:40:06.000000000 +0000 @@ -9,6 +9,30 @@ * Entry macros ****************************************************************/ + .macro PUSHBREGS + pushl %eax // Save registers (matches struct bregs) + pushl %ecx + pushl %edx + pushl %ebx + pushl %ebp + pushl %esi + pushl %edi + pushw %es + pushw %ds + .endm + + .macro POPBREGS + popw %ds // Restore registers (from struct bregs) + popw %es + popl %edi + popl %esi + popl %ebp + popl %ebx + popl %edx + popl %ecx + popl %eax + .endm + // Call a C function - this does the minimal work necessary to // call into C. It sets up %ds, backs up %es, and backs up // those registers that are call clobbered by the C compiler. @@ -63,15 +87,7 @@ .macro ENTRY_ARG cfunc cli cld - pushl %eax // Save registers (matches struct bregs) - pushl %ecx - pushl %edx - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - pushw %es - pushw %ds + PUSHBREGS movw %ss, %ax // Move %ss to %ds movw %ax, %ds movl %esp, %ebx // Backup %esp, then zero high bits @@ -79,15 +95,7 @@ movl %esp, %eax // First arg is pointer to struct bregs calll \cfunc movl %ebx, %esp // Restore %esp (including high bits) - popw %ds // Restore registers (from struct bregs) - popw %es - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax + POPBREGS .endm // As above, but get calling function from stack. @@ -111,43 +119,19 @@ movl %esp, %eax // First arg is pointer to struct bregs calll *%ecx movl %ebx, %esp // Restore %esp (including high bits) - popw %ds // Restore registers (from struct bregs) - popw %es - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax + POPBREGS .endm // Same as ENTRY_ARG, but don't mangle %esp .macro ENTRY_ARG_ESP cfunc cli cld - pushl %eax // Save registers (matches struct bregs) - pushl %ecx - pushl %edx - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - pushw %es - pushw %ds + PUSHBREGS movw %ss, %ax // Move %ss to %ds movw %ax, %ds movl %esp, %eax // First arg is pointer to struct bregs calll \cfunc - popw %ds // Restore registers (from struct bregs) - popw %es - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax + POPBREGS .endm // Reset stack, transition to 32bit mode, and call a C function. diff -Nru seabios-1.7.1/src/esp-scsi.c seabios-1.7.4/src/esp-scsi.c --- seabios-1.7.1/src/esp-scsi.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/esp-scsi.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,231 +0,0 @@ -// AMD PCscsi boot support. -// -// Copyright (C) 2012 Red Hat Inc. -// -// Authors: -// Paolo Bonzini -// -// based on lsi-scsi.c which is written by: -// Gerd Hoffman -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // foreachpci -#include "config.h" // CONFIG_* -#include "biosvar.h" // GET_GLOBAL -#include "pci_ids.h" // PCI_DEVICE_ID -#include "pci_regs.h" // PCI_VENDOR_ID -#include "boot.h" // bootprio_find_scsi_device -#include "blockcmd.h" // scsi_init_drive -#include "disk.h" - -#define ESP_TCLO 0x00 -#define ESP_TCMID 0x04 -#define ESP_FIFO 0x08 -#define ESP_CMD 0x0c -#define ESP_WBUSID 0x10 -#define ESP_TCHI 0x38 - -#define ESP_RSTAT 0x10 -#define ESP_RINTR 0x14 -#define ESP_RFLAGS 0x1c - -#define ESP_DMA_CMD 0x40 -#define ESP_DMA_STC 0x44 -#define ESP_DMA_SPA 0x48 -#define ESP_DMA_WBC 0x4c -#define ESP_DMA_WAC 0x50 -#define ESP_DMA_STAT 0x54 -#define ESP_DMA_SMDLA 0x58 -#define ESP_DMA_WMAC 0x58c - -#define ESP_CMD_DMA 0x80 -#define ESP_CMD_RESET 0x02 -#define ESP_CMD_TI 0x10 -#define ESP_CMD_ICCS 0x11 -#define ESP_CMD_SELATN 0x42 - -#define ESP_STAT_DI 0x01 -#define ESP_STAT_CD 0x02 -#define ESP_STAT_MSG 0x04 -#define ESP_STAT_TC 0x10 - -#define ESP_INTR_DC 0x20 - -struct esp_lun_s { - struct drive_s drive; - struct pci_device *pci; - u32 iobase; - u8 target; - u8 lun; -}; - -static void -esp_scsi_dma(u32 iobase, u32 buf, u32 len, int read) -{ - outb(len & 0xff, iobase + ESP_TCLO); - outb((len >> 8) & 0xff, iobase + ESP_TCMID); - outb((len >> 16) & 0xff, iobase + ESP_TCHI); - outl(buf, iobase + ESP_DMA_SPA); - outl(len, iobase + ESP_DMA_STC); - outb(read ? 0x83 : 0x03, iobase + ESP_DMA_CMD); -} - -static int -esp_scsi_cmd(struct esp_lun_s *llun, struct disk_op_s *op, - u8 *cdbcmd, u16 target, u16 lun, u16 blocksize) -{ - u32 iobase = GET_GLOBAL(llun->iobase); - int i, state; - u8 status; - - outb(target, iobase + ESP_WBUSID); - - /* - * We need to pass the LUN at the beginning of the command, and the FIFO - * is only 16 bytes, so we cannot support 16-byte CDBs. The alternative - * would be to use DMA for the 17-byte command too, which is quite - * overkill. - */ - outb(lun, iobase + ESP_FIFO); - cdbcmd[1] &= 0x1f; - cdbcmd[1] |= lun << 5; - for (i = 0; i < 12; i++) - outb(cdbcmd[i], iobase + ESP_FIFO); - outb(ESP_CMD_SELATN, iobase + ESP_CMD); - - for (state = 0;;) { - u8 stat = inb(iobase + ESP_RSTAT); - - /* Detect disconnected device. */ - if (state == 0 && (inb(iobase + ESP_RINTR) & ESP_INTR_DC)) { - return DISK_RET_ENOTREADY; - } - - /* HBA reads command, clears CD, sets TC -> do DMA if needed. */ - if (state == 0 && (stat & ESP_STAT_TC)) { - state++; - if (op->count && blocksize) { - /* Data phase. */ - u32 count = (u32)op->count * blocksize; - esp_scsi_dma(iobase, (u32)op->buf_fl, count, - cdb_is_read(cdbcmd, blocksize)); - outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD); - continue; - } - } - - /* At end of DMA TC is set again -> complete command. */ - if (state == 1 && (stat & ESP_STAT_TC)) { - state++; - outb(ESP_CMD_ICCS, iobase + ESP_CMD); - continue; - } - - /* Finally read data from the message in phase. */ - if (state == 2 && (stat & ESP_STAT_MSG)) { - state++; - status = inb(iobase + ESP_FIFO); - inb(iobase + ESP_FIFO); - break; - } - usleep(5); - } - - if (status == 0) { - return DISK_RET_SUCCESS; - } - - return DISK_RET_EBADTRACK; -} - -int -esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - if (!CONFIG_ESP_SCSI) - return DISK_RET_EBADTRACK; - - struct esp_lun_s *llun = - container_of(op->drive_g, struct esp_lun_s, drive); - - return esp_scsi_cmd(llun, op, cdbcmd, - GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun), - blocksize); -} - -static int -esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) -{ - struct esp_lun_s *llun = malloc_fseg(sizeof(*llun)); - if (!llun) { - warn_noalloc(); - return -1; - } - memset(llun, 0, sizeof(*llun)); - llun->drive.type = DTYPE_ESP_SCSI; - llun->drive.cntl_id = pci->bdf; - llun->pci = pci; - llun->target = target; - llun->lun = lun; - llun->iobase = iobase; - - char *name = znprintf(16, "esp %02x:%02x.%x %d:%d", - pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), - pci_bdf_to_fn(pci->bdf), target, lun); - int prio = bootprio_find_scsi_device(pci, target, lun); - int ret = scsi_init_drive(&llun->drive, name, prio); - free(name); - if (ret) - goto fail; - return 0; - -fail: - free(llun); - return -1; -} - -static void -esp_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target) -{ - esp_scsi_add_lun(pci, iobase, target, 0); -} - -static void -init_esp_scsi(struct pci_device *pci) -{ - u16 bdf = pci->bdf; - u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) - & PCI_BASE_ADDRESS_IO_MASK; - - dprintf(1, "found esp at %02x:%02x.%x, io @ %x\n", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), - pci_bdf_to_fn(bdf), iobase); - - // reset - outb(ESP_CMD_RESET, iobase + ESP_CMD); - - int i; - for (i = 0; i <= 7; i++) - esp_scsi_scan_target(pci, iobase, i); - - return; -} - -void -esp_scsi_setup(void) -{ - ASSERT32FLAT(); - if (!CONFIG_ESP_SCSI) - return; - - dprintf(3, "init esp\n"); - - struct pci_device *pci; - foreachpci(pci) { - if (pci->vendor != PCI_VENDOR_ID_AMD - || pci->device != PCI_DEVICE_ID_AMD_SCSI) - continue; - init_esp_scsi(pci); - } -} diff -Nru seabios-1.7.1/src/esp-scsi.h seabios-1.7.4/src/esp-scsi.h --- seabios-1.7.1/src/esp-scsi.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/esp-scsi.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#ifndef __ESP_SCSI_H -#define __ESP_SCSI_H - -struct disk_op_s; -int esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); -void esp_scsi_setup(void); - -#endif /* __ESP_SCSI_H */ diff -Nru seabios-1.7.1/src/farptr.h seabios-1.7.4/src/farptr.h --- seabios-1.7.1/src/farptr.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/farptr.h 2013-12-23 15:40:06.000000000 +0000 @@ -6,7 +6,7 @@ #ifndef __FARPTR_H #define __FARPTR_H -#include "ioport.h" // insb +#include "x86.h" // insb // Dummy definitions used to make sure gcc understands dependencies // between SET_SEG and GET/READ/WRITE_SEG macros. @@ -26,8 +26,8 @@ #define READ64_SEG(prefix, SEG, value, var) do { \ union u64_u32_u __value; \ union u64_u32_u *__r64_ptr = (union u64_u32_u *)&(var); \ - READ32_SEG(prefix, SEG, __value.hi, __r64_ptr->hi); \ READ32_SEG(prefix, SEG, __value.lo, __r64_ptr->lo); \ + READ32_SEG(prefix, SEG, __value.hi, __r64_ptr->hi); \ *(u64*)&(value) = __value.val; \ } while (0) #define WRITE8_SEG(prefix, SEG, var, value) \ @@ -44,8 +44,8 @@ union u64_u32_u *__w64_ptr = (union u64_u32_u *)&(var); \ typeof(var) __value_tmp = (value); \ __value.val = *(u64*)&__value_tmp; \ - WRITE32_SEG(prefix, SEG, __w64_ptr->hi, __value.hi); \ WRITE32_SEG(prefix, SEG, __w64_ptr->lo, __value.lo); \ + WRITE32_SEG(prefix, SEG, __w64_ptr->hi, __value.hi); \ } while (0) // Macros for automatically choosing the appropriate memory size @@ -196,16 +196,6 @@ #endif -// Definition for common 16bit segment/offset pointers. -struct segoff_s { - union { - struct { - u16 offset; - u16 seg; - }; - u32 segoff; - }; -}; #define SEGOFF(s,o) ({struct segoff_s __so; __so.offset=(o); __so.seg=(s); __so;}) static inline struct segoff_s FLATPTR_TO_SEGOFF(void *p) { diff -Nru seabios-1.7.1/src/floppy.c seabios-1.7.4/src/floppy.c --- seabios-1.7.1/src/floppy.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/floppy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,625 +0,0 @@ -// 16bit code to access floppy drives. -// -// Copyright (C) 2008,2009 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "types.h" // u8 -#include "disk.h" // DISK_RET_SUCCESS -#include "config.h" // CONFIG_FLOPPY -#include "biosvar.h" // SET_BDA -#include "util.h" // dprintf -#include "cmos.h" // inb_cmos -#include "pic.h" // eoi_pic1 -#include "bregs.h" // struct bregs -#include "boot.h" // boot_add_floppy -#include "pci.h" // pci_to_bdf -#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA - -#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors -#define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 -#define FLOPPY_MOTOR_TICKS 37 // ~2 seconds -#define FLOPPY_FILLBYTE 0xf6 -#define FLOPPY_GAPLEN 0x1B -#define FLOPPY_FORMAT_GAPLEN 0x6c - -// New diskette parameter table adding 3 parameters from IBM -// Since no provisions are made for multiple drive types, most -// values in this table are ignored. I set parameters for 1.44M -// floppy here -struct floppy_ext_dbt_s diskette_param_table2 VAR16VISIBLE = { - .dbt = { - .specify1 = 0xAF, // step rate 12ms, head unload 240ms - .specify2 = 0x02, // head load time 4ms, DMA used - .shutoff_ticks = FLOPPY_MOTOR_TICKS, // ~2 seconds - .bps_code = FLOPPY_SIZE_CODE, - .sectors = 18, - .interblock_len = FLOPPY_GAPLEN, - .data_len = FLOPPY_DATALEN, - .gap_len = FLOPPY_FORMAT_GAPLEN, - .fill_byte = FLOPPY_FILLBYTE, - .settle_time = 0x0F, // 15ms - .startup_time = 0x08, // 1 second - }, - .max_track = 79, // maximum track - .data_rate = 0, // data transfer rate - .drive_type = 4, // drive type in cmos -}; - -// Since no provisions are made for multiple drive types, most -// values in this table are ignored. I set parameters for 1.44M -// floppy here -struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7) = { - .specify1 = 0xAF, - .specify2 = 0x02, - .shutoff_ticks = FLOPPY_MOTOR_TICKS, - .bps_code = FLOPPY_SIZE_CODE, - .sectors = 18, - .interblock_len = FLOPPY_GAPLEN, - .data_len = FLOPPY_DATALEN, - .gap_len = FLOPPY_FORMAT_GAPLEN, - .fill_byte = FLOPPY_FILLBYTE, - .settle_time = 0x0F, - .startup_time = 0x08, -}; - -struct floppyinfo_s { - struct chs_s chs; - u8 config_data; - u8 media_state; -}; - -struct floppyinfo_s FloppyInfo[] VAR16VISIBLE = { - // Unknown - { {0, 0, 0}, 0x00, 0x00}, - // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors - { {2, 40, 9}, 0x00, 0x25}, - // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors - { {2, 80, 15}, 0x00, 0x25}, - // 3 - 720KB, 3.5" - 2 heads, 80 tracks, 9 sectors - { {2, 80, 9}, 0x00, 0x17}, - // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors - { {2, 80, 18}, 0x00, 0x17}, - // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors - { {2, 80, 36}, 0xCC, 0xD7}, - // 6 - 160k, 5.25" - 1 heads, 40 tracks, 8 sectors - { {1, 40, 8}, 0x00, 0x27}, - // 7 - 180k, 5.25" - 1 heads, 40 tracks, 9 sectors - { {1, 40, 9}, 0x00, 0x27}, - // 8 - 320k, 5.25" - 2 heads, 40 tracks, 8 sectors - { {2, 40, 8}, 0x00, 0x27}, -}; - -struct drive_s * -init_floppy(int floppyid, int ftype) -{ - if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) { - dprintf(1, "Bad floppy type %d\n", ftype); - return NULL; - } - - struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g)); - if (!drive_g) { - warn_noalloc(); - return NULL; - } - memset(drive_g, 0, sizeof(*drive_g)); - drive_g->cntl_id = floppyid; - drive_g->type = DTYPE_FLOPPY; - drive_g->blksize = DISK_SECTOR_SIZE; - drive_g->floppy_type = ftype; - drive_g->sectors = (u64)-1; - - memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs - , sizeof(FloppyInfo[ftype].chs)); - return drive_g; -} - -static void -addFloppy(int floppyid, int ftype) -{ - struct drive_s *drive_g = init_floppy(floppyid, ftype); - if (!drive_g) - return; - char *desc = znprintf(MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid); - struct pci_device *pci = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */ - int prio = bootprio_find_fdc_device(pci, PORT_FD_BASE, floppyid); - boot_add_floppy(drive_g, desc, prio); -} - -void -floppy_setup(void) -{ - if (! CONFIG_FLOPPY) - return; - dprintf(3, "init floppy drives\n"); - - if (CONFIG_COREBOOT) { - // XXX - disable floppies on coreboot for now. - } else { - u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - if (type & 0xf0) - addFloppy(0, type >> 4); - if (type & 0x0f) - addFloppy(1, type & 0x0f); - } - - outb(0x02, PORT_DMA1_MASK_REG); - - enable_hwirq(6, FUNC16(entry_0e)); -} - -// Find a floppy type that matches a given image size. -int -find_floppy_type(u32 size) -{ - int i; - for (i=1; icylinders * c->heads * c->spt * DISK_SECTOR_SIZE == size) - return i; - } - return -1; -} - - -/**************************************************************** - * Low-level floppy IO - ****************************************************************/ - -static void -floppy_reset_controller(void) -{ - // Reset controller - u8 val8 = inb(PORT_FD_DOR); - outb(val8 & ~0x04, PORT_FD_DOR); - outb(val8 | 0x04, PORT_FD_DOR); - - // Wait for controller to come out of reset - while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80) - ; -} - -static int -wait_floppy_irq(void) -{ - ASSERT16(); - u8 frs; - for (;;) { - if (!GET_BDA(floppy_motor_counter)) - return -1; - frs = GET_BDA(floppy_recalibration_status); - if (frs & FRS_TIMEOUT) - break; - // Could use yield_toirq() here, but that causes issues on - // bochs, so use yield() instead. - yield(); - } - - frs &= ~FRS_TIMEOUT; - SET_BDA(floppy_recalibration_status, frs); - return 0; -} - -static void -floppy_prepare_controller(u8 floppyid) -{ - u8 frs = GET_BDA(floppy_recalibration_status); - SET_BDA(floppy_recalibration_status, frs & ~FRS_TIMEOUT); - - // turn on motor of selected drive, DMA & int enabled, normal operation - u8 prev_reset = inb(PORT_FD_DOR) & 0x04; - u8 dor = 0x10; - if (floppyid) - dor = 0x20; - dor |= 0x0c; - dor |= floppyid; - outb(dor, PORT_FD_DOR); - - // reset the disk motor timeout value of INT 08 - SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS); - - // wait for drive readiness - while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80) - ; - - if (!prev_reset) - wait_floppy_irq(); -} - -static int -floppy_pio(u8 *cmd, u8 cmdlen) -{ - floppy_prepare_controller(cmd[1] & 1); - - // send command to controller - u8 i; - for (i=0; ibuf_fl; - - // check for 64K boundary overrun - u16 end = count - 1; - u32 last_addr = addr + end; - if ((addr >> 16) != (last_addr >> 16)) - return DISK_RET_EBOUNDARY; - - u8 mode_register = 0x4a; // single mode, increment, autoinit disable, - if (cmd[0] == 0xe6) - // read - mode_register = 0x46; - - //DEBUGF("floppy dma c2\n"); - outb(0x06, PORT_DMA1_MASK_REG); - outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop - outb(addr, PORT_DMA_ADDR_2); - outb(addr>>8, PORT_DMA_ADDR_2); - outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop - outb(end, PORT_DMA_CNT_2); - outb(end>>8, PORT_DMA_CNT_2); - - // port 0b: DMA-1 Mode Register - // transfer type=write, channel 2 - outb(mode_register, PORT_DMA1_MODE_REG); - - // port 81: DMA-1 Page Register, channel 2 - outb(addr>>16, PORT_DMA_PAGE_2); - - outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2 - - int ret = floppy_pio(cmd, cmdlen); - if (ret) - return DISK_RET_ETIMEOUT; - - // check port 3f4 for accessibility to status bytes - if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) - return DISK_RET_ECONTROLLER; - - // read 7 return status bytes from controller - u8 i; - for (i=0; i<7; i++) { - u8 v = inb(PORT_FD_DATA); - cmd[i] = v; - SET_BDA(floppy_return_status[i], v); - } - - return DISK_RET_SUCCESS; -} - - -/**************************************************************** - * Floppy media sense - ****************************************************************/ - -static inline void -set_diskette_current_cyl(u8 floppyid, u8 cyl) -{ - SET_BDA(floppy_track[floppyid], cyl); -} - -static void -floppy_drive_recal(u8 floppyid) -{ - // send Recalibrate command (2 bytes) to controller - u8 data[12]; - data[0] = 0x07; // 07: Recalibrate - data[1] = floppyid; // 0=drive0, 1=drive1 - floppy_pio(data, 2); - - u8 frs = GET_BDA(floppy_recalibration_status); - SET_BDA(floppy_recalibration_status, frs | (1<floppy_type); - SET_BDA(floppy_last_data_rate, GET_GLOBAL(FloppyInfo[ftype].config_data)); - u8 floppyid = GET_GLOBAL(drive_g->cntl_id); - SET_BDA(floppy_media_state[floppyid] - , GET_GLOBAL(FloppyInfo[ftype].media_state)); - return DISK_RET_SUCCESS; -} - -static int -check_recal_drive(struct drive_s *drive_g) -{ - u8 floppyid = GET_GLOBAL(drive_g->cntl_id); - if ((GET_BDA(floppy_recalibration_status) & (1<lba; - - u32 tmp = lba + 1; - u16 nlspt = GET_GLOBAL(op->drive_g->lchs.spt); - *sector = tmp % nlspt; - - tmp /= nlspt; - u16 nlh = GET_GLOBAL(op->drive_g->lchs.heads); - *head = tmp % nlh; - - tmp /= nlh; - *track = tmp; -} - -// diskette controller reset -static int -floppy_reset(struct disk_op_s *op) -{ - u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); - set_diskette_current_cyl(floppyid, 0); // current cylinder - return DISK_RET_SUCCESS; -} - -// Read Diskette Sectors -static int -floppy_read(struct disk_op_s *op) -{ - int res = check_recal_drive(op->drive_g); - if (res) - goto fail; - - u8 track, sector, head; - lba2chs(op, &track, §or, &head); - - // send read-normal-data command (9 bytes) to controller - u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); - u8 data[12]; - data[0] = 0xe6; // e6: read normal data - data[1] = (head << 2) | floppyid; // HD DR1 DR2 - data[2] = track; - data[3] = head; - data[4] = sector; - data[5] = FLOPPY_SIZE_CODE; - data[6] = sector + op->count - 1; // last sector to read on track - data[7] = FLOPPY_GAPLEN; - data[8] = FLOPPY_DATALEN; - - res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9); - if (res) - goto fail; - - if (data[0] & 0xc0) { - res = DISK_RET_ECONTROLLER; - goto fail; - } - - // ??? should track be new val from return_status[3] ? - set_diskette_current_cyl(floppyid, track); - return DISK_RET_SUCCESS; -fail: - op->count = 0; // no sectors read - return res; -} - -// Write Diskette Sectors -static int -floppy_write(struct disk_op_s *op) -{ - int res = check_recal_drive(op->drive_g); - if (res) - goto fail; - - u8 track, sector, head; - lba2chs(op, &track, §or, &head); - - // send write-normal-data command (9 bytes) to controller - u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); - u8 data[12]; - data[0] = 0xc5; // c5: write normal data - data[1] = (head << 2) | floppyid; // HD DR1 DR2 - data[2] = track; - data[3] = head; - data[4] = sector; - data[5] = FLOPPY_SIZE_CODE; - data[6] = sector + op->count - 1; // last sector to write on track - data[7] = FLOPPY_GAPLEN; - data[8] = FLOPPY_DATALEN; - - res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9); - if (res) - goto fail; - - if (data[0] & 0xc0) { - if (data[1] & 0x02) - res = DISK_RET_EWRITEPROTECT; - else - res = DISK_RET_ECONTROLLER; - goto fail; - } - - // ??? should track be new val from return_status[3] ? - set_diskette_current_cyl(floppyid, track); - return DISK_RET_SUCCESS; -fail: - op->count = 0; // no sectors read - return res; -} - -// Verify Diskette Sectors -static int -floppy_verify(struct disk_op_s *op) -{ - int res = check_recal_drive(op->drive_g); - if (res) - goto fail; - - u8 track, sector, head; - lba2chs(op, &track, §or, &head); - - // ??? should track be new val from return_status[3] ? - u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); - set_diskette_current_cyl(floppyid, track); - return DISK_RET_SUCCESS; -fail: - op->count = 0; // no sectors read - return res; -} - -// format diskette track -static int -floppy_format(struct disk_op_s *op) -{ - int ret = check_recal_drive(op->drive_g); - if (ret) - return ret; - - u8 head = op->lba; - - // send format-track command (6 bytes) to controller - u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); - u8 data[12]; - data[0] = 0x4d; // 4d: format track - data[1] = (head << 2) | floppyid; // HD DR1 DR2 - data[2] = FLOPPY_SIZE_CODE; - data[3] = op->count; // number of sectors per track - data[4] = FLOPPY_FORMAT_GAPLEN; - data[5] = FLOPPY_FILLBYTE; - - ret = floppy_cmd(op, op->count * 4, data, 6); - if (ret) - return ret; - - if (data[0] & 0xc0) { - if (data[1] & 0x02) - return DISK_RET_EWRITEPROTECT; - return DISK_RET_ECONTROLLER; - } - - set_diskette_current_cyl(floppyid, 0); - return DISK_RET_SUCCESS; -} - -int -process_floppy_op(struct disk_op_s *op) -{ - if (!CONFIG_FLOPPY) - return 0; - - switch (op->command) { - case CMD_RESET: - return floppy_reset(op); - case CMD_READ: - return floppy_read(op); - case CMD_WRITE: - return floppy_write(op); - case CMD_VERIFY: - return floppy_verify(op); - case CMD_FORMAT: - return floppy_format(op); - default: - op->count = 0; - return DISK_RET_EPARAM; - } -} - - -/**************************************************************** - * HW irqs - ****************************************************************/ - -// INT 0Eh Diskette Hardware ISR Entry Point -void VISIBLE16 -handle_0e(void) -{ - debug_isr(DEBUG_ISR_0e); - if (! CONFIG_FLOPPY) - goto done; - - if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) { - outb(0x08, PORT_FD_DATA); // sense interrupt status - while ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) - ; - do { - inb(PORT_FD_DATA); - } while ((inb(PORT_FD_STATUS) & 0xc0) == 0xc0); - } - // diskette interrupt has occurred - u8 frs = GET_BDA(floppy_recalibration_status); - SET_BDA(floppy_recalibration_status, frs | FRS_TIMEOUT); - -done: - eoi_pic1(); -} - -// Called from int08 handler. -void -floppy_tick(void) -{ - if (! CONFIG_FLOPPY) - return; - - // time to turn off drive(s)? - u8 fcount = GET_BDA(floppy_motor_counter); - if (fcount) { - fcount--; - SET_BDA(floppy_motor_counter, fcount); - if (fcount == 0) - // turn motor(s) off - outb(inb(PORT_FD_DOR) & 0xcf, PORT_FD_DOR); - } -} diff -Nru seabios-1.7.1/src/fw/acpi.c seabios-1.7.4/src/fw/acpi.c --- seabios-1.7.1/src/fw/acpi.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/acpi.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,818 @@ +// Support for generating ACPI tables (on emulators) +// +// Copyright (C) 2008-2010 Kevin O'Connor +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "byteorder.h" // cpu_to_le16 +#include "config.h" // CONFIG_* +#include "dev-q35.h" +#include "hw/pci.h" // pci_find_init_device +#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL +#include "hw/pci_regs.h" // PCI_INTERRUPT_LINE +#include "malloc.h" // free +#include "output.h" // dprintf +#include "paravirt.h" // RamSize +#include "romfile.h" // romfile_loadint +#include "std/acpi.h" // struct rsdp_descriptor +#include "string.h" // memset +#include "util.h" // MaxCountCPUs +#include "x86.h" // readl +#include "romfile_loader.h" // romfile_loader_execute + +#include "src/fw/acpi-dsdt.hex" + +u32 acpi_pm1a_cnt VARFSEG; + +static void +build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev) +{ + h->signature = cpu_to_le32(sig); + h->length = cpu_to_le32(len); + h->revision = rev; + memcpy(h->oem_id, BUILD_APPNAME6, 6); + memcpy(h->oem_table_id, BUILD_APPNAME4, 4); + memcpy(h->oem_table_id + 4, (void*)&sig, 4); + h->oem_revision = cpu_to_le32(1); + memcpy(h->asl_compiler_id, BUILD_APPNAME4, 4); + h->asl_compiler_revision = cpu_to_le32(1); + h->checksum -= checksum(h, len); +} + +#define PIIX4_ACPI_ENABLE 0xf1 +#define PIIX4_ACPI_DISABLE 0xf0 +#define PIIX4_GPE0_BLK 0xafe0 +#define PIIX4_GPE0_BLK_LEN 4 + +#define PIIX4_PM_INTRRUPT 9 // irq 9 + +static void piix4_fadt_setup(struct pci_device *pci, void *arg) +{ + struct fadt_descriptor_rev1 *fadt = arg; + + fadt->model = 1; + fadt->reserved1 = 0; + fadt->sci_int = cpu_to_le16(PIIX4_PM_INTRRUPT); + fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD); + fadt->acpi_enable = PIIX4_ACPI_ENABLE; + fadt->acpi_disable = PIIX4_ACPI_DISABLE; + fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE); + fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04); + fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08); + fadt->gpe0_blk = cpu_to_le32(PIIX4_GPE0_BLK); + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = PIIX4_GPE0_BLK_LEN; + fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported + fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported + /* WBINVD + PROC_C1 + SLP_BUTTON + RTC_S4 + USE_PLATFORM_CLOCK */ + fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 7) | + (1 << 15)); +} + +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */ +void ich9_lpc_fadt_setup(struct pci_device *dev, void *arg) +{ + struct fadt_descriptor_rev1 *fadt = arg; + + fadt->model = 1; + fadt->reserved1 = 0; + fadt->sci_int = cpu_to_le16(9); + fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD); + fadt->acpi_enable = ICH9_ACPI_ENABLE; + fadt->acpi_disable = ICH9_ACPI_DISABLE; + fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE); + fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04); + fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08); + fadt->gpe0_blk = cpu_to_le32(PORT_ACPI_PM_BASE + ICH9_PMIO_GPE0_STS); + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = ICH9_PMIO_GPE0_BLK_LEN; + fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported + fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported + /* WBINVD + PROC_C1 + SLP_BUTTON + RTC_S4 + USE_PLATFORM_CLOCK */ + fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 7) | + (1 << 15)); +} + +static const struct pci_device_id fadt_init_tbl[] = { + /* PIIX4 Power Management device (for ACPI) */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, + piix4_fadt_setup), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, + ich9_lpc_fadt_setup), + PCI_DEVICE_END +}; + +static void fill_dsdt(struct fadt_descriptor_rev1 *fadt, void *dsdt) +{ + if (fadt->dsdt) { + free((void *)le32_to_cpu(fadt->dsdt)); + } + fadt->dsdt = cpu_to_le32((u32)dsdt); + fadt->checksum -= checksum(fadt, sizeof(*fadt)); + dprintf(1, "ACPI DSDT=%p\n", dsdt); +} + +static void * +build_fadt(struct pci_device *pci) +{ + struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt)); + struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs)); + + if (!fadt || !facs) { + warn_noalloc(); + return NULL; + } + + /* FACS */ + memset(facs, 0, sizeof(*facs)); + facs->signature = cpu_to_le32(FACS_SIGNATURE); + facs->length = cpu_to_le32(sizeof(*facs)); + + /* FADT */ + memset(fadt, 0, sizeof(*fadt)); + fadt->firmware_ctrl = cpu_to_le32((u32)facs); + fadt->dsdt = 0; /* dsdt will be filled later in acpi_setup() + by fill_dsdt() */ + pci_init_device(fadt_init_tbl, pci, fadt); + + build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1); + + return fadt; +} + +static void* +build_madt(void) +{ + int madt_size = (sizeof(struct multiple_apic_table) + + sizeof(struct madt_processor_apic) * MaxCountCPUs + + sizeof(struct madt_io_apic) + + sizeof(struct madt_intsrcovr) * 16 + + sizeof(struct madt_local_nmi)); + + struct multiple_apic_table *madt = malloc_high(madt_size); + if (!madt) { + warn_noalloc(); + return NULL; + } + memset(madt, 0, madt_size); + madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR); + madt->flags = cpu_to_le32(1); + struct madt_processor_apic *apic = (void*)&madt[1]; + int i; + for (i=0; itype = APIC_PROCESSOR; + apic->length = sizeof(*apic); + apic->processor_id = i; + apic->local_apic_id = i; + if (apic_id_is_present(apic->local_apic_id)) + apic->flags = cpu_to_le32(1); + else + apic->flags = cpu_to_le32(0); + apic++; + } + struct madt_io_apic *io_apic = (void*)apic; + io_apic->type = APIC_IO; + io_apic->length = sizeof(*io_apic); + io_apic->io_apic_id = BUILD_IOAPIC_ID; + io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR); + io_apic->interrupt = cpu_to_le32(0); + + struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1]; + if (romfile_loadint("etc/irq0-override", 0)) { + memset(intsrcovr, 0, sizeof(*intsrcovr)); + intsrcovr->type = APIC_XRUPT_OVERRIDE; + intsrcovr->length = sizeof(*intsrcovr); + intsrcovr->source = 0; + intsrcovr->gsi = cpu_to_le32(2); + intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */ + intsrcovr++; + } + for (i = 1; i < 16; i++) { + if (!(BUILD_PCI_IRQS & (1 << i))) + /* No need for a INT source override structure. */ + continue; + memset(intsrcovr, 0, sizeof(*intsrcovr)); + intsrcovr->type = APIC_XRUPT_OVERRIDE; + intsrcovr->length = sizeof(*intsrcovr); + intsrcovr->source = i; + intsrcovr->gsi = cpu_to_le32(i); + intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */ + intsrcovr++; + } + + struct madt_local_nmi *local_nmi = (void*)intsrcovr; + local_nmi->type = APIC_LOCAL_NMI; + local_nmi->length = sizeof(*local_nmi); + local_nmi->processor_id = 0xff; /* all processors */ + local_nmi->flags = cpu_to_le16(0); + local_nmi->lint = 1; /* LINT1 */ + local_nmi++; + + build_header((void*)madt, APIC_SIGNATURE, (void*)local_nmi - (void*)madt, 1); + return madt; +} + +// Encode a hex value +static inline char getHex(u32 val) { + val &= 0x0f; + return (val <= 9) ? ('0' + val) : ('A' + val - 10); +} + +// Encode a length in an SSDT. +static u8 * +encodeLen(u8 *ssdt_ptr, int length, int bytes) +{ + switch (bytes) { + default: + case 4: ssdt_ptr[3] = ((length >> 20) & 0xff); + case 3: ssdt_ptr[2] = ((length >> 12) & 0xff); + case 2: ssdt_ptr[1] = ((length >> 4) & 0xff); + ssdt_ptr[0] = (((bytes-1) & 0x3) << 6) | (length & 0x0f); + break; + case 1: ssdt_ptr[0] = length & 0x3f; + } + return ssdt_ptr + bytes; +} + +#include "src/fw/ssdt-proc.hex" + +/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */ +#define PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2) +#define PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4) +#define PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start) +#define PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start) +#define PROC_AML (ssdp_proc_aml + *ssdt_proc_start) + +/* 0x5B 0x82 DeviceOp PkgLength NameString */ +#define PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1) +#define PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start) +#define PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start) +#define PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start) +#define PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start) +#define PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start) +#define PCI_SLOTS 32 + +#define SSDT_SIGNATURE 0x54445353 // SSDT +#define SSDT_HEADER_LENGTH 36 + +#include "src/fw/ssdt-misc.hex" +#include "src/fw/ssdt-pcihp.hex" + +#define PCI_RMV_BASE 0xae0c + +static u8* +build_notify(u8 *ssdt_ptr, const char *name, int skip, int count, + const char *target, int ofs) +{ + count -= skip; + + *(ssdt_ptr++) = 0x14; // MethodOp + ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*count), 2); + memcpy(ssdt_ptr, name, 4); + ssdt_ptr += 4; + *(ssdt_ptr++) = 0x02; // MethodOp + + int i; + for (i = skip; count-- > 0; i++) { + *(ssdt_ptr++) = 0xA0; // IfOp + ssdt_ptr = encodeLen(ssdt_ptr, 11, 1); + *(ssdt_ptr++) = 0x93; // LEqualOp + *(ssdt_ptr++) = 0x68; // Arg0Op + *(ssdt_ptr++) = 0x0A; // BytePrefix + *(ssdt_ptr++) = i; + *(ssdt_ptr++) = 0x86; // NotifyOp + memcpy(ssdt_ptr, target, 4); + ssdt_ptr[ofs] = getHex(i >> 4); + ssdt_ptr[ofs + 1] = getHex(i); + ssdt_ptr += 4; + *(ssdt_ptr++) = 0x69; // Arg1Op + } + return ssdt_ptr; +} + +static void patch_pcihp(int slot, u8 *ssdt_ptr, u32 eject) +{ + ssdt_ptr[PCIHP_OFFSET_HEX] = getHex(slot >> 4); + ssdt_ptr[PCIHP_OFFSET_HEX+1] = getHex(slot); + ssdt_ptr[PCIHP_OFFSET_ID] = slot; + ssdt_ptr[PCIHP_OFFSET_ADR + 2] = slot; + + /* Runtime patching of EJ0: to disable hotplug for a slot, + * replace the method name: _EJ0 by EJ0_. */ + /* Sanity check */ + if (memcmp(ssdt_ptr + PCIHP_OFFSET_EJ0, "_EJ0", 4)) { + warn_internalerror(); + } + if (!eject) { + memcpy(ssdt_ptr + PCIHP_OFFSET_EJ0, "EJ0_", 4); + } +} + +static void* +build_ssdt(void) +{ + int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs; + int length = (sizeof(ssdp_misc_aml) // _S3_ / _S4_ / _S5_ + + (1+3+4) // Scope(_SB_) + + (acpi_cpus * PROC_SIZEOF) // procs + + (1+2+5+(12*acpi_cpus)) // NTFY + + (6+2+1+(1*acpi_cpus)) // CPON + + (1+3+4) // Scope(PCI0) + + ((PCI_SLOTS - 1) * PCIHP_SIZEOF) // slots + + (1+2+5+(12*(PCI_SLOTS - 1)))); // PCNT + u8 *ssdt = malloc_high(length); + if (! ssdt) { + warn_noalloc(); + return NULL; + } + u8 *ssdt_ptr = ssdt; + + // Copy header and encode fwcfg values in the S3_ / S4_ / S5_ packages + int sys_state_size; + char *sys_states = romfile_loadfile("etc/system-states", &sys_state_size); + if (!sys_states || sys_state_size != 6) + sys_states = (char[]){128, 0, 0, 129, 128, 128}; + + memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml)); + if (!(sys_states[3] & 128)) + ssdt_ptr[acpi_s3_name[0]] = 'X'; + if (!(sys_states[4] & 128)) + ssdt_ptr[acpi_s4_name[0]] = 'X'; + else + ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127; + + // store pci io windows + *(u32*)&ssdt_ptr[acpi_pci32_start[0]] = cpu_to_le32(pcimem_start); + *(u32*)&ssdt_ptr[acpi_pci32_end[0]] = cpu_to_le32(pcimem_end - 1); + if (pcimem64_start) { + ssdt_ptr[acpi_pci64_valid[0]] = 1; + *(u64*)&ssdt_ptr[acpi_pci64_start[0]] = cpu_to_le64(pcimem64_start); + *(u64*)&ssdt_ptr[acpi_pci64_end[0]] = cpu_to_le64(pcimem64_end - 1); + *(u64*)&ssdt_ptr[acpi_pci64_length[0]] = cpu_to_le64( + pcimem64_end - pcimem64_start); + } else { + ssdt_ptr[acpi_pci64_valid[0]] = 0; + } + + int pvpanic_port = romfile_loadint("etc/pvpanic-port", 0x0); + *(u16 *)(ssdt_ptr + *ssdt_isa_pest) = pvpanic_port; + + ssdt_ptr += sizeof(ssdp_misc_aml); + + // build Scope(_SB_) header + *(ssdt_ptr++) = 0x10; // ScopeOp + ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3); + *(ssdt_ptr++) = '_'; + *(ssdt_ptr++) = 'S'; + *(ssdt_ptr++) = 'B'; + *(ssdt_ptr++) = '_'; + + // build Processor object for each processor + int i; + for (i=0; i> 4); + ssdt_ptr[PROC_OFFSET_CPUHEX+1] = getHex(i); + ssdt_ptr[PROC_OFFSET_CPUID1] = i; + ssdt_ptr[PROC_OFFSET_CPUID2] = i; + ssdt_ptr += PROC_SIZEOF; + } + + // build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}" + // Arg0 = Processor ID = APIC ID + ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2); + + // build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" + *(ssdt_ptr++) = 0x08; // NameOp + *(ssdt_ptr++) = 'C'; + *(ssdt_ptr++) = 'P'; + *(ssdt_ptr++) = 'O'; + *(ssdt_ptr++) = 'N'; + *(ssdt_ptr++) = 0x12; // PackageOp + ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2); + *(ssdt_ptr++) = acpi_cpus; + for (i=0; i> 16; + u32 hpet_period = readl(hpet_base + HPET_PERIOD); + + if (hpet_vendor == 0 || hpet_vendor == 0xffff || + hpet_period == 0 || hpet_period > 100000000) + return NULL; + + hpet = malloc_high(sizeof(*hpet)); + if (!hpet) { + warn_noalloc(); + return NULL; + } + + memset(hpet, 0, sizeof(*hpet)); + /* Note timer_block_id value must be kept in sync with value advertised by + * emulated hpet + */ + hpet->timer_block_id = cpu_to_le32(0x8086a201); + hpet->addr.address = cpu_to_le64(BUILD_HPET_ADDRESS); + build_header((void*)hpet, HPET_SIGNATURE, sizeof(*hpet), 1); + + return hpet; +} + +static void +acpi_build_srat_memory(struct srat_memory_affinity *numamem, + u64 base, u64 len, int node, int enabled) +{ + numamem->type = SRAT_MEMORY; + numamem->length = sizeof(*numamem); + memset(numamem->proximity, 0, 4); + numamem->proximity[0] = node; + numamem->flags = cpu_to_le32(!!enabled); + numamem->base_addr = cpu_to_le64(base); + numamem->range_length = cpu_to_le64(len); +} + +static void * +build_srat(void) +{ + int numadatasize, numacpusize; + u64 *numadata = romfile_loadfile("etc/numa-nodes", &numadatasize); + u64 *numacpumap = romfile_loadfile("etc/numa-cpu-map", &numacpusize); + if (!numadata || !numacpumap) + goto fail; + int max_cpu = numacpusize / sizeof(u64); + int nb_numa_nodes = numadatasize / sizeof(u64); + + struct system_resource_affinity_table *srat; + int srat_size = sizeof(*srat) + + sizeof(struct srat_processor_affinity) * max_cpu + + sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2); + + srat = malloc_high(srat_size); + if (!srat) { + warn_noalloc(); + goto fail; + } + + memset(srat, 0, srat_size); + srat->reserved1=cpu_to_le32(1); + struct srat_processor_affinity *core = (void*)(srat + 1); + int i; + u64 curnode; + + for (i = 0; i < max_cpu; ++i) { + core->type = SRAT_PROCESSOR; + core->length = sizeof(*core); + core->local_apic_id = i; + curnode = *numacpumap++; + core->proximity_lo = curnode; + memset(core->proximity_hi, 0, 3); + core->local_sapic_eid = 0; + if (apic_id_is_present(i)) + core->flags = cpu_to_le32(1); + else + core->flags = cpu_to_le32(0); + core++; + } + + + /* the memory map is a bit tricky, it contains at least one hole + * from 640k-1M and possibly another one from 3.5G-4G. + */ + struct srat_memory_affinity *numamem = (void*)core; + int slots = 0; + u64 mem_len, mem_base, next_base = 0; + + acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1); + next_base = 1024 * 1024; + numamem++; + slots++; + for (i = 1; i < nb_numa_nodes + 1; ++i) { + mem_base = next_base; + mem_len = *numadata++; + if (i == 1) + mem_len -= 1024 * 1024; + next_base = mem_base + mem_len; + + /* Cut out the PCI hole */ + if (mem_base <= RamSize && next_base > RamSize) { + mem_len -= next_base - RamSize; + if (mem_len > 0) { + acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); + numamem++; + slots++; + } + mem_base = 1ULL << 32; + mem_len = next_base - RamSize; + next_base += (1ULL << 32) - RamSize; + } + acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); + numamem++; + slots++; + } + for (; slots < nb_numa_nodes + 2; slots++) { + acpi_build_srat_memory(numamem, 0, 0, 0, 0); + numamem++; + } + + build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1); + + free(numadata); + free(numacpumap); + return srat; +fail: + free(numadata); + free(numacpumap); + return NULL; +} + +static void * +build_mcfg_q35(void) +{ + struct acpi_table_mcfg *mcfg; + + int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]); + mcfg = malloc_high(len); + if (!mcfg) { + warn_noalloc(); + return NULL; + } + memset(mcfg, 0, len); + mcfg->allocation[0].address = cpu_to_le64(Q35_HOST_BRIDGE_PCIEXBAR_ADDR); + mcfg->allocation[0].pci_segment = cpu_to_le16(Q35_HOST_PCIE_PCI_SEGMENT); + mcfg->allocation[0].start_bus_number = Q35_HOST_PCIE_START_BUS_NUMBER; + mcfg->allocation[0].end_bus_number = Q35_HOST_PCIE_END_BUS_NUMBER; + + build_header((void *)mcfg, MCFG_SIGNATURE, len, 1); + return mcfg; +} + +static const struct pci_device_id acpi_find_tbl[] = { + /* PIIX4 Power Management device. */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, NULL), + PCI_DEVICE_END, +}; + +struct rsdp_descriptor *RsdpAddr; + +#define MAX_ACPI_TABLES 20 +void +acpi_setup(void) +{ + if (CONFIG_FW_ROMFILE_LOAD) { + int loader_err; + + dprintf(3, "load ACPI tables\n"); + + loader_err = romfile_loader_execute("etc/table-loader"); + + RsdpAddr = find_acpi_rsdp(); + + if (RsdpAddr) + return; + + /* If present, loader should have installed an RSDP. + * Not installed? We might still be able to continue + * using the builtin RSDP. + */ + if (!loader_err) + warn_internalerror(); + } + + if (! CONFIG_ACPI) + return; + + dprintf(3, "init ACPI tables\n"); + + // This code is hardcoded for PIIX4 Power Management device. + struct pci_device *pci = pci_find_init_device(acpi_find_tbl, NULL); + if (!pci) + // Device not found + return; + + // Build ACPI tables + u32 tables[MAX_ACPI_TABLES], tbl_idx = 0; + +#define ACPI_INIT_TABLE(X) \ + do { \ + tables[tbl_idx] = cpu_to_le32((u32)(X)); \ + if (le32_to_cpu(tables[tbl_idx])) \ + tbl_idx++; \ + } while(0) + + struct fadt_descriptor_rev1 *fadt = build_fadt(pci); + ACPI_INIT_TABLE(fadt); + ACPI_INIT_TABLE(build_ssdt()); + ACPI_INIT_TABLE(build_madt()); + ACPI_INIT_TABLE(build_hpet()); + ACPI_INIT_TABLE(build_srat()); + if (pci->device == PCI_DEVICE_ID_INTEL_ICH9_LPC) + ACPI_INIT_TABLE(build_mcfg_q35()); + + struct romfile_s *file = NULL; + for (;;) { + file = romfile_findprefix("acpi/", file); + if (!file) + break; + struct acpi_table_header *table = malloc_high(file->size); + if (!table) { + warn_noalloc(); + continue; + } + int ret = file->copy(file, table, file->size); + if (ret <= sizeof(*table)) + continue; + if (table->signature == DSDT_SIGNATURE) { + if (fadt) { + fill_dsdt(fadt, table); + } + } else { + ACPI_INIT_TABLE(table); + } + if (tbl_idx == MAX_ACPI_TABLES) { + warn_noalloc(); + break; + } + } + + if (CONFIG_ACPI_DSDT && fadt && !fadt->dsdt) { + /* default DSDT */ + struct acpi_table_header *dsdt = malloc_high(sizeof(AmlCode)); + if (!dsdt) { + warn_noalloc(); + return; + } + memcpy(dsdt, AmlCode, sizeof(AmlCode)); + fill_dsdt(fadt, dsdt); + /* Strip out compiler-generated header if any */ + memset(dsdt, 0, sizeof *dsdt); + build_header(dsdt, DSDT_SIGNATURE, sizeof(AmlCode), 1); + } + + // Build final rsdt table + struct rsdt_descriptor_rev1 *rsdt; + size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx; + rsdt = malloc_high(rsdt_len); + if (!rsdt) { + warn_noalloc(); + return; + } + memset(rsdt, 0, rsdt_len); + memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx); + build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1); + + // Build rsdp pointer table + struct rsdp_descriptor *rsdp = malloc_fseg(sizeof(*rsdp)); + if (!rsdp) { + warn_noalloc(); + return; + } + memset(rsdp, 0, sizeof(*rsdp)); + rsdp->signature = cpu_to_le64(RSDP_SIGNATURE); + memcpy(rsdp->oem_id, BUILD_APPNAME6, 6); + rsdp->rsdt_physical_address = cpu_to_le32((u32)rsdt); + rsdp->checksum -= checksum(rsdp, 20); + RsdpAddr = rsdp; + dprintf(1, "ACPI tables: RSDP=%p RSDT=%p\n", rsdp, rsdt); +} + +static struct fadt_descriptor_rev1 * +find_fadt(void) +{ + dprintf(4, "rsdp=%p\n", RsdpAddr); + if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE) + return NULL; + struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address; + dprintf(4, "rsdt=%p\n", rsdt); + if (!rsdt || rsdt->signature != RSDT_SIGNATURE) + return NULL; + void *end = (void*)rsdt + rsdt->length; + int i; + for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) { + struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i]; + if (!fadt || fadt->signature != FACP_SIGNATURE) + continue; + dprintf(4, "fadt=%p\n", fadt); + return fadt; + } + dprintf(4, "no fadt found\n"); + return NULL; +} + +u32 +find_resume_vector(void) +{ + struct fadt_descriptor_rev1 *fadt = find_fadt(); + if (!fadt) + return 0; + struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl; + dprintf(4, "facs=%p\n", facs); + if (! facs || facs->signature != FACS_SIGNATURE) + return 0; + // Found it. + dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector); + return facs->firmware_waking_vector; +} + +void +find_acpi_features(void) +{ + struct fadt_descriptor_rev1 *fadt = find_fadt(); + if (!fadt) + return; + u32 pm_tmr = le32_to_cpu(fadt->pm_tmr_blk); + u32 pm1a_cnt = le32_to_cpu(fadt->pm1a_cnt_blk); + dprintf(4, "pm_tmr_blk=%x\n", pm_tmr); + if (pm_tmr) + pmtimer_setup(pm_tmr); + if (pm1a_cnt) + acpi_pm1a_cnt = pm1a_cnt; + + // Theoretically we should check the 'reset_reg_sup' flag, but Windows + // doesn't and thus nobody seems to *set* it. If the table is large enough + // to include it, let the sanity checks in acpi_set_reset_reg() suffice. + if (fadt->length >= 129) { + void *p = fadt; + acpi_set_reset_reg(p + 116, *(u8 *)(p + 128)); + } +} + +static struct acpi_20_generic_address acpi_reset_reg; +static u8 acpi_reset_val; + +#define acpi_ga_to_bdf(addr) pci_to_bdf(0, (addr >> 32) & 0xffff, (addr >> 16) & 0xffff) + +void +acpi_reboot(void) +{ + // Check it passed the sanity checks in acpi_set_reset_reg() and was set + if (acpi_reset_reg.register_bit_width != 8) + return; + + u64 addr = le64_to_cpu(acpi_reset_reg.address); + + dprintf(1, "ACPI hard reset %d:%llx (%x)\n", + acpi_reset_reg.address_space_id, addr, acpi_reset_val); + + switch (acpi_reset_reg.address_space_id) { + case 0: // System Memory + writeb((void *)(u32)addr, acpi_reset_val); + break; + case 1: // System I/O + outb(acpi_reset_val, addr); + break; + case 2: // PCI config space + pci_config_writeb(acpi_ga_to_bdf(addr), addr & 0xffff, acpi_reset_val); + break; + } +} + +void +acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val) +{ + if (!reg || reg->address_space_id > 2 || + reg->register_bit_width != 8 || reg->register_bit_offset) + return; + + acpi_reset_reg = *reg; + acpi_reset_val = val; +} diff -Nru seabios-1.7.1/src/fw/acpi-dsdt-cpu-hotplug.dsl seabios-1.7.4/src/fw/acpi-dsdt-cpu-hotplug.dsl --- seabios-1.7.1/src/fw/acpi-dsdt-cpu-hotplug.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/acpi-dsdt-cpu-hotplug.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,78 @@ +/**************************************************************** + * CPU hotplug + ****************************************************************/ + +Scope(\_SB) { + /* Objects filled in by run-time generated SSDT */ + External(NTFY, MethodObj) + External(CPON, PkgObj) + + /* Methods called by run-time generated SSDT Processor objects */ + Method(CPMA, 1, NotSerialized) { + // _MAT method - create an madt apic buffer + // Arg0 = Processor ID = Local APIC ID + // Local0 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Arg0)), Local0) + // Local1 = Buffer (in madt apic form) to return + Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1) + // Update the processor id, lapic id, and enable/disable status + Store(Arg0, Index(Local1, 2)) + Store(Arg0, Index(Local1, 3)) + Store(Local0, Index(Local1, 4)) + Return (Local1) + } + Method(CPST, 1, NotSerialized) { + // _STA method - return ON status of cpu + // Arg0 = Processor ID = Local APIC ID + // Local0 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Arg0)), Local0) + If (Local0) { + Return (0xF) + } Else { + Return (0x0) + } + } + Method(CPEJ, 2, NotSerialized) { + // _EJ0 method - eject callback + Sleep(200) + } + + /* CPU hotplug notify method */ + OperationRegion(PRST, SystemIO, 0xaf00, 32) + Field(PRST, ByteAcc, NoLock, Preserve) { + PRS, 256 + } + Method(PRSC, 0) { + // Local5 = active cpu bitmap + Store(PRS, Local5) + // Local2 = last read byte from bitmap + Store(Zero, Local2) + // Local0 = Processor ID / APIC ID iterator + Store(Zero, Local0) + While (LLess(Local0, SizeOf(CPON))) { + // Local1 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Local0)), Local1) + If (And(Local0, 0x07)) { + // Shift down previously read bitmap byte + ShiftRight(Local2, 1, Local2) + } Else { + // Read next byte from cpu bitmap + Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2) + } + // Local3 = active state for this cpu + Store(And(Local2, 1), Local3) + + If (LNotEqual(Local1, Local3)) { + // State change - update CPON with new state + Store(Local3, Index(CPON, Local0)) + // Do CPU notify + If (LEqual(Local3, 1)) { + NTFY(Local0, 1) + } Else { + NTFY(Local0, 3) + } + } + Increment(Local0) + } + } +} diff -Nru seabios-1.7.1/src/fw/acpi-dsdt-dbug.dsl seabios-1.7.4/src/fw/acpi-dsdt-dbug.dsl --- seabios-1.7.1/src/fw/acpi-dsdt-dbug.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/acpi-dsdt-dbug.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,26 @@ +/**************************************************************** + * Debugging + ****************************************************************/ + +Scope(\) { + /* Debug Output */ + OperationRegion(DBG, SystemIO, 0x0402, 0x01) + Field(DBG, ByteAcc, NoLock, Preserve) { + DBGB, 8, + } + + /* Debug method - use this method to send output to the QEMU + * BIOS debug port. This method handles strings, integers, + * and buffers. For example: DBUG("abc") DBUG(0x123) */ + Method(DBUG, 1) { + ToHexString(Arg0, Local0) + ToBuffer(Local0, Local0) + Subtract(SizeOf(Local0), 1, Local1) + Store(Zero, Local2) + While (LLess(Local2, Local1)) { + Store(DerefOf(Index(Local0, Local2)), DBGB) + Increment(Local2) + } + Store(0x0A, DBGB) + } +} diff -Nru seabios-1.7.1/src/fw/acpi-dsdt.dsl seabios-1.7.4/src/fw/acpi-dsdt.dsl --- seabios-1.7.1/src/fw/acpi-dsdt.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/acpi-dsdt.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,343 @@ +/* + * Bochs/QEMU ACPI DSDT ASL definition + * + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 + */ + +ACPI_EXTRACT_ALL_CODE AmlCode + +DefinitionBlock ( + "acpi-dsdt.aml", // Output Filename + "DSDT", // Signature + 0x01, // DSDT Compliance Revision + "BXPC", // OEMID + "BXDSDT", // TABLE ID + 0x1 // OEM Revision + ) +{ + +#include "acpi-dsdt-dbug.dsl" + + +/**************************************************************** + * PCI Bus definition + ****************************************************************/ + + Scope(\_SB) { + Device(PCI0) { + Name(_HID, EisaId("PNP0A03")) + Name(_ADR, 0x00) + Name(_UID, 1) + } + } + +#include "acpi-dsdt-pci-crs.dsl" +#include "acpi-dsdt-hpet.dsl" + + +/**************************************************************** + * VGA + ****************************************************************/ + + Scope(\_SB.PCI0) { + Device(VGA) { + Name(_ADR, 0x00020000) + OperationRegion(PCIC, PCI_Config, Zero, 0x4) + Field(PCIC, DWordAcc, NoLock, Preserve) { + VEND, 32 + } + Method(_S1D, 0, NotSerialized) { + Return (0x00) + } + Method(_S2D, 0, NotSerialized) { + Return (0x00) + } + Method(_S3D, 0, NotSerialized) { + If (LEqual(VEND, 0x1001b36)) { + Return (0x03) // QXL + } Else { + Return (0x00) + } + } + } + } + + +/**************************************************************** + * PIIX4 PM + ****************************************************************/ + + Scope(\_SB.PCI0) { + Device(PX13) { + Name(_ADR, 0x00010003) + OperationRegion(P13C, PCI_Config, 0x00, 0xff) + } + } + + +/**************************************************************** + * PIIX3 ISA bridge + ****************************************************************/ + + Scope(\_SB.PCI0) { + Device(ISA) { + Name(_ADR, 0x00010000) + + /* PIIX PCI to ISA irq remapping */ + OperationRegion(P40C, PCI_Config, 0x60, 0x04) + + /* enable bits */ + Field(\_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) { + Offset(0x5f), + , 7, + LPEN, 1, // LPT + Offset(0x67), + , 3, + CAEN, 1, // COM1 + , 3, + CBEN, 1, // COM2 + } + Name(FDEN, 1) + } + } + +#include "acpi-dsdt-isa.dsl" + + +/**************************************************************** + * PCI hotplug + ****************************************************************/ + + Scope(\_SB.PCI0) { + OperationRegion(PCST, SystemIO, 0xae00, 0x08) + Field(PCST, DWordAcc, NoLock, WriteAsZeros) { + PCIU, 32, + PCID, 32, + } + + OperationRegion(SEJ, SystemIO, 0xae08, 0x04) + Field(SEJ, DWordAcc, NoLock, WriteAsZeros) { + B0EJ, 32, + } + + /* Methods called by bulk generated PCI devices below */ + + /* Methods called by hotplug devices */ + Method(PCEJ, 1, NotSerialized) { + // _EJ0 method - eject callback + Store(ShiftLeft(1, Arg0), B0EJ) + Return (0x0) + } + + /* Hotplug notification method supplied by SSDT */ + External(\_SB.PCI0.PCNT, MethodObj) + + /* PCI hotplug notify method */ + Method(PCNF, 0) { + // Local0 = iterator + Store(Zero, Local0) + While (LLess(Local0, 31)) { + Increment(Local0) + If (And(PCIU, ShiftLeft(1, Local0))) { + PCNT(Local0, 1) + } + If (And(PCID, ShiftLeft(1, Local0))) { + PCNT(Local0, 3) + } + } + } + } + + +/**************************************************************** + * PCI IRQs + ****************************************************************/ + + Scope(\_SB) { + Scope(PCI0) { + Name(_PRT, Package() { + /* PCI IRQ routing table, example from ACPI 2.0a specification, + section 6.2.8.1 */ + /* Note: we provide the same info as the PCI routing + table of the Bochs BIOS */ + +#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \ + Package() { nr##ffff, 0, lnk0, 0 }, \ + Package() { nr##ffff, 1, lnk1, 0 }, \ + Package() { nr##ffff, 2, lnk2, 0 }, \ + Package() { nr##ffff, 3, lnk3, 0 } + +#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC) +#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD) +#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA) +#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB) + + prt_slot0(0x0000), + /* Device 1 is power mgmt device, and can only use irq 9 */ + prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD), + prt_slot2(0x0002), + prt_slot3(0x0003), + prt_slot0(0x0004), + prt_slot1(0x0005), + prt_slot2(0x0006), + prt_slot3(0x0007), + prt_slot0(0x0008), + prt_slot1(0x0009), + prt_slot2(0x000a), + prt_slot3(0x000b), + prt_slot0(0x000c), + prt_slot1(0x000d), + prt_slot2(0x000e), + prt_slot3(0x000f), + prt_slot0(0x0010), + prt_slot1(0x0011), + prt_slot2(0x0012), + prt_slot3(0x0013), + prt_slot0(0x0014), + prt_slot1(0x0015), + prt_slot2(0x0016), + prt_slot3(0x0017), + prt_slot0(0x0018), + prt_slot1(0x0019), + prt_slot2(0x001a), + prt_slot3(0x001b), + prt_slot0(0x001c), + prt_slot1(0x001d), + prt_slot2(0x001e), + prt_slot3(0x001f), + }) + } + + Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) { + PRQ0, 8, + PRQ1, 8, + PRQ2, 8, + PRQ3, 8 + } + + Method(IQST, 1, NotSerialized) { + // _STA method - get status + If (And(0x80, Arg0)) { + Return (0x09) + } + Return (0x0B) + } + Method(IQCR, 1, Serialized) { + // _CRS method - get current settings + Name(PRR0, ResourceTemplate() { + Interrupt(, Level, ActiveHigh, Shared) { 0 } + }) + CreateDWordField(PRR0, 0x05, PRRI) + If (LLess(Arg0, 0x80)) { + Store(Arg0, PRRI) + } + Return (PRR0) + } + +#define define_link(link, uid, reg) \ + Device(link) { \ + Name(_HID, EISAID("PNP0C0F")) \ + Name(_UID, uid) \ + Name(_PRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + 5, 10, 11 \ + } \ + }) \ + Method(_STA, 0, NotSerialized) { \ + Return (IQST(reg)) \ + } \ + Method(_DIS, 0, NotSerialized) { \ + Or(reg, 0x80, reg) \ + } \ + Method(_CRS, 0, NotSerialized) { \ + Return (IQCR(reg)) \ + } \ + Method(_SRS, 1, NotSerialized) { \ + CreateDWordField(Arg0, 0x05, PRRI) \ + Store(PRRI, reg) \ + } \ + } + + define_link(LNKA, 0, PRQ0) + define_link(LNKB, 1, PRQ1) + define_link(LNKC, 2, PRQ2) + define_link(LNKD, 3, PRQ3) + + Device(LNKS) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 4) + Name(_PRS, ResourceTemplate() { + Interrupt(, Level, ActiveHigh, Shared) { 9 } + }) + + // The SCI cannot be disabled and is always attached to GSI 9, + // so these are no-ops. We only need this link to override the + // polarity to active high and match the content of the MADT. + Method(_STA, 0, NotSerialized) { Return (0x0b) } + Method(_DIS, 0, NotSerialized) { } + Method(_CRS, 0, NotSerialized) { Return (_PRS) } + Method(_SRS, 1, NotSerialized) { } + } + } + +#include "acpi-dsdt-cpu-hotplug.dsl" + + +/**************************************************************** + * General purpose events + ****************************************************************/ + + Scope(\_GPE) { + Name(_HID, "ACPI0006") + + Method(_L00) { + } + Method(_E01) { + // PCI hotplug event + \_SB.PCI0.PCNF() + } + Method(_E02) { + // CPU hotplug event + \_SB.PRSC() + } + Method(_L03) { + } + Method(_L04) { + } + Method(_L05) { + } + Method(_L06) { + } + Method(_L07) { + } + Method(_L08) { + } + Method(_L09) { + } + Method(_L0A) { + } + Method(_L0B) { + } + Method(_L0C) { + } + Method(_L0D) { + } + Method(_L0E) { + } + Method(_L0F) { + } + } +} diff -Nru seabios-1.7.1/src/fw/acpi-dsdt-hpet.dsl seabios-1.7.4/src/fw/acpi-dsdt-hpet.dsl --- seabios-1.7.1/src/fw/acpi-dsdt-hpet.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/acpi-dsdt-hpet.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,36 @@ +/**************************************************************** + * HPET + ****************************************************************/ + +Scope(\_SB) { + Device(HPET) { + Name(_HID, EISAID("PNP0103")) + Name(_UID, 0) + OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400) + Field(HPTM, DWordAcc, Lock, Preserve) { + VEND, 32, + PRD, 32, + } + Method(_STA, 0, NotSerialized) { + Store(VEND, Local0) + Store(PRD, Local1) + ShiftRight(Local0, 16, Local0) + If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) { + Return (0x0) + } + If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) { + Return (0x0) + } + Return (0x0F) + } + Name(_CRS, ResourceTemplate() { +#if 0 /* This makes WinXP BSOD for not yet figured reasons. */ + IRQNoFlags() {2, 8} +#endif + Memory32Fixed(ReadOnly, + 0xFED00000, // Address Base + 0x00000400, // Address Length + ) + }) + } +} diff -Nru seabios-1.7.1/src/fw/acpi-dsdt-isa.dsl seabios-1.7.4/src/fw/acpi-dsdt-isa.dsl --- seabios-1.7.1/src/fw/acpi-dsdt-isa.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/acpi-dsdt-isa.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,102 @@ +/* Common legacy ISA style devices. */ +Scope(\_SB.PCI0.ISA) { + + Device(RTC) { + Name(_HID, EisaId("PNP0B00")) + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x0070, 0x0070, 0x10, 0x02) + IRQNoFlags() { 8 } + IO(Decode16, 0x0072, 0x0072, 0x02, 0x06) + }) + } + + Device(KBD) { + Name(_HID, EisaId("PNP0303")) + Method(_STA, 0, NotSerialized) { + Return (0x0f) + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x0060, 0x0060, 0x01, 0x01) + IO(Decode16, 0x0064, 0x0064, 0x01, 0x01) + IRQNoFlags() { 1 } + }) + } + + Device(MOU) { + Name(_HID, EisaId("PNP0F13")) + Method(_STA, 0, NotSerialized) { + Return (0x0f) + } + Name(_CRS, ResourceTemplate() { + IRQNoFlags() { 12 } + }) + } + + Device(FDC0) { + Name(_HID, EisaId("PNP0700")) + Method(_STA, 0, NotSerialized) { + Store(FDEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04) + IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01) + IRQNoFlags() { 6 } + DMA(Compatibility, NotBusMaster, Transfer8) { 2 } + }) + } + + Device(LPT) { + Name(_HID, EisaId("PNP0400")) + Method(_STA, 0, NotSerialized) { + Store(LPEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x0378, 0x0378, 0x08, 0x08) + IRQNoFlags() { 7 } + }) + } + + Device(COM1) { + Name(_HID, EisaId("PNP0501")) + Name(_UID, 0x01) + Method(_STA, 0, NotSerialized) { + Store(CAEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08) + IRQNoFlags() { 4 } + }) + } + + Device(COM2) { + Name(_HID, EisaId("PNP0501")) + Name(_UID, 0x02) + Method(_STA, 0, NotSerialized) { + Store(CBEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08) + IRQNoFlags() { 3 } + }) + } +} diff -Nru seabios-1.7.1/src/fw/acpi-dsdt-pci-crs.dsl seabios-1.7.4/src/fw/acpi-dsdt-pci-crs.dsl --- seabios-1.7.1/src/fw/acpi-dsdt-pci-crs.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/acpi-dsdt-pci-crs.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,90 @@ +/* PCI CRS (current resources) definition. */ +Scope(\_SB.PCI0) { + + Name(CRES, ResourceTemplate() { + WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x00FF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0100, // Address Length + ,, ) + IO(Decode16, + 0x0CF8, // Address Range Minimum + 0x0CF8, // Address Range Maximum + 0x01, // Address Alignment + 0x08, // Address Length + ) + WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x0CF7, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0CF8, // Address Length + ,, , TypeStatic) + WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0D00, // Address Range Minimum + 0xFFFF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0xF300, // Address Length + ,, , TypeStatic) + DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0x000A0000, // Address Range Minimum + 0x000BFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x00020000, // Address Length + ,, , AddressRangeMemory, TypeStatic) + DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0xE0000000, // Address Range Minimum + 0xFEBFFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x1EC00000, // Address Length + ,, PW32, AddressRangeMemory, TypeStatic) + }) + + Name(CR64, ResourceTemplate() { + QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0x8000000000, // Address Range Minimum + 0xFFFFFFFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x8000000000, // Address Length + ,, PW64, AddressRangeMemory, TypeStatic) + }) + + Method(_CRS, 0) { + /* Fields provided by dynamically created ssdt */ + External(P0S, IntObj) + External(P0E, IntObj) + External(P1V, IntObj) + External(P1S, BuffObj) + External(P1E, BuffObj) + External(P1L, BuffObj) + + /* fixup 32bit pci io window */ + CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32) + CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32) + CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32) + Store(P0S, PS32) + Store(P0E, PE32) + Store(Add(Subtract(P0E, P0S), 1), PL32) + + If (LEqual(P1V, Zero)) { + Return (CRES) + } + + /* fixup 64bit pci io window */ + CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64) + CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64) + CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64) + Store(P1S, PS64) + Store(P1E, PE64) + Store(P1L, PL64) + /* add window and return result */ + ConcatenateResTemplate(CRES, CR64, Local0) + Return (Local0) + } +} diff -Nru seabios-1.7.1/src/fw/biostables.c seabios-1.7.4/src/fw/biostables.c --- seabios-1.7.1/src/fw/biostables.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/biostables.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,147 @@ +// Coreboot interface support. +// +// Copyright (C) 2008,2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "malloc.h" // malloc_fseg +#include "output.h" // dprintf +#include "std/acpi.h" // struct rsdp_descriptor +#include "std/mptable.h" // MPTABLE_SIGNATURE +#include "std/pirtable.h" // struct pir_header +#include "std/smbios.h" // struct smbios_entry_point +#include "string.h" // memcpy +#include "util.h" // copy_table + +static void +copy_pir(void *pos) +{ + struct pir_header *p = pos; + if (p->signature != PIR_SIGNATURE) + return; + if (PirAddr) + return; + if (p->size < sizeof(*p)) + return; + if (checksum(pos, p->size) != 0) + return; + void *newpos = malloc_fseg(p->size); + if (!newpos) { + warn_noalloc(); + return; + } + dprintf(1, "Copying PIR from %p to %p\n", pos, newpos); + memcpy(newpos, pos, p->size); + PirAddr = newpos; +} + +static void +copy_mptable(void *pos) +{ + struct mptable_floating_s *p = pos; + if (p->signature != MPTABLE_SIGNATURE) + return; + if (!p->physaddr) + return; + if (checksum(pos, sizeof(*p)) != 0) + return; + u32 length = p->length * 16; + u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length; + struct mptable_floating_s *newpos = malloc_fseg(length + mpclength); + if (!newpos) { + warn_noalloc(); + return; + } + dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos); + memcpy(newpos, pos, length); + newpos->physaddr = (u32)newpos + length; + newpos->checksum -= checksum(newpos, sizeof(*newpos)); + memcpy((void*)newpos + length, (void*)p->physaddr, mpclength); +} + +static int +get_acpi_rsdp_length(void *pos, unsigned size) +{ + struct rsdp_descriptor *p = pos; + if (p->signature != RSDP_SIGNATURE) + return -1; + u32 length = 20; + if (length > size) + return -1; + if (checksum(pos, length) != 0) + return -1; + if (p->revision > 1) { + length = p->length; + if (length > size) + return -1; + if (checksum(pos, length) != 0) + return -1; + } + return length; +} + +static void +copy_acpi_rsdp(void *pos) +{ + if (RsdpAddr) + return; + int length = get_acpi_rsdp_length(pos, -1); + if (length < 0) + return; + void *newpos = malloc_fseg(length); + if (!newpos) { + warn_noalloc(); + return; + } + dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos); + memcpy(newpos, pos, length); + RsdpAddr = newpos; +} + +void +copy_smbios(void *pos) +{ + if (SMBiosAddr) + return; + struct smbios_entry_point *p = pos; + if (memcmp(p->anchor_string, "_SM_", 4)) + return; + if (checksum(pos, 0x10) != 0) + return; + if (memcmp(p->intermediate_anchor_string, "_DMI_", 5)) + return; + if (checksum(pos+0x10, p->length-0x10) != 0) + return; + struct smbios_entry_point *newpos = malloc_fseg(p->length); + if (!newpos) { + warn_noalloc(); + return; + } + dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos); + memcpy(newpos, pos, p->length); + SMBiosAddr = newpos; +} + +void +copy_table(void *pos) +{ + copy_pir(pos); + copy_mptable(pos); + copy_acpi_rsdp(pos); + copy_smbios(pos); +} + +void *find_acpi_rsdp(void) +{ + extern u8 zonefseg_start[], zonefseg_end[]; + unsigned long start = (unsigned long)zonefseg_start; + unsigned long end = (unsigned long)zonefseg_end; + unsigned long pos; + + for (pos = ALIGN(start, 0x10); pos <= ALIGN_DOWN(end, 0x10); pos += 0x10) + if (get_acpi_rsdp_length((void *)pos, end - pos) >= 0) + return (void *)pos; + + return NULL; +} diff -Nru seabios-1.7.1/src/fw/coreboot.c seabios-1.7.4/src/fw/coreboot.c --- seabios-1.7.1/src/fw/coreboot.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/coreboot.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,499 @@ +// Coreboot interface support. +// +// Copyright (C) 2008,2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "block.h" // MAXDESCSIZE +#include "byteorder.h" // be32_to_cpu +#include "config.h" // CONFIG_* +#include "hw/pci.h" // pci_probe_devices +#include "lzmadecode.h" // LzmaDecode +#include "malloc.h" // free +#include "memmap.h" // add_e820 +#include "output.h" // dprintf +#include "paravirt.h" // PlatformRunningOn +#include "romfile.h" // romfile_findprefix +#include "stacks.h" // yield +#include "string.h" // memset +#include "util.h" // coreboot_preinit + + +/**************************************************************** + * Memory map + ****************************************************************/ + +struct cb_header { + u32 signature; + u32 header_bytes; + u32 header_checksum; + u32 table_bytes; + u32 table_checksum; + u32 table_entries; +}; + +#define CB_SIGNATURE 0x4f49424C // "LBIO" + +struct cb_memory_range { + u64 start; + u64 size; + u32 type; +}; + +#define CB_MEM_TABLE 16 + +struct cb_memory { + u32 tag; + u32 size; + struct cb_memory_range map[0]; +}; + +#define CB_TAG_MEMORY 0x01 + +#define MEM_RANGE_COUNT(_rec) \ + (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0])) + +struct cb_mainboard { + u32 tag; + u32 size; + u8 vendor_idx; + u8 part_idx; + char strings[0]; +}; + +#define CB_TAG_MAINBOARD 0x0003 + +struct cb_forward { + u32 tag; + u32 size; + u64 forward; +}; + +#define CB_TAG_FORWARD 0x11 + +struct cb_cbmem_ref { + u32 tag; + u32 size; + u64 cbmem_addr; +}; + +#define CB_TAG_CBMEM_CONSOLE 0x17 + +struct cbmem_console { + u32 buffer_size; + u32 buffer_cursor; + u8 buffer_body[0]; +} PACKED; +static struct cbmem_console *cbcon = NULL; + +static u16 +ipchksum(char *buf, int count) +{ + u16 *p = (u16*)buf; + u32 sum = 0; + while (count > 1) { + sum += *p++; + count -= 2; + } + if (count) + sum += *(u8*)p; + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return ~sum; +} + +// Try to locate the coreboot header in a given address range. +static struct cb_header * +find_cb_header(char *addr, int len) +{ + char *end = addr + len; + for (; addr < end; addr += 16) { + struct cb_header *cbh = (struct cb_header *)addr; + if (cbh->signature != CB_SIGNATURE) + continue; + if (! cbh->table_bytes) + continue; + if (ipchksum(addr, sizeof(*cbh)) != 0) + continue; + if (ipchksum(addr + sizeof(*cbh), cbh->table_bytes) + != cbh->table_checksum) + continue; + return cbh; + } + return NULL; +} + +// Try to find the coreboot memory table in the given coreboot table. +static void * +find_cb_subtable(struct cb_header *cbh, u32 tag) +{ + char *tbl = (char *)cbh + sizeof(*cbh); + int i; + for (i=0; itable_entries; i++) { + struct cb_memory *cbm = (struct cb_memory *)tbl; + tbl += cbm->size; + if (cbm->tag == tag) + return cbm; + } + return NULL; +} + +static struct cb_memory *CBMemTable; +const char *CBvendor = "", *CBpart = ""; + +// Populate max ram and e820 map info by scanning for a coreboot table. +void +coreboot_preinit(void) +{ + if (!CONFIG_COREBOOT) + return; + + dprintf(3, "Attempting to find coreboot table\n"); + + // Find coreboot table. + struct cb_header *cbh = find_cb_header(0, 0x1000); + if (!cbh) + goto fail; + struct cb_forward *cbf = find_cb_subtable(cbh, CB_TAG_FORWARD); + if (cbf) { + dprintf(3, "Found coreboot table forwarder.\n"); + cbh = find_cb_header((char *)((u32)cbf->forward), 0x100); + if (!cbh) + goto fail; + } + dprintf(3, "Now attempting to find coreboot memory map\n"); + struct cb_memory *cbm = CBMemTable = find_cb_subtable(cbh, CB_TAG_MEMORY); + if (!cbm) + goto fail; + + int i, count = MEM_RANGE_COUNT(cbm); + for (i=0; imap[i]; + u32 type = m->type; + if (type == CB_MEM_TABLE) + type = E820_RESERVED; + add_e820(m->start, m->size, type); + } + + // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this + // confuses grub. So, override it. + add_e820(0, 16*1024, E820_RAM); + + struct cb_cbmem_ref *cbref = find_cb_subtable(cbh, CB_TAG_CBMEM_CONSOLE); + if (cbref) { + cbcon = (void*)(u32)cbref->cbmem_addr; + dprintf(1, "----- [ SeaBIOS %s ] -----\n", VERSION); + dprintf(1, "Found coreboot cbmem console @ %llx\n", cbref->cbmem_addr); + } + + struct cb_mainboard *cbmb = find_cb_subtable(cbh, CB_TAG_MAINBOARD); + if (cbmb) { + CBvendor = &cbmb->strings[cbmb->vendor_idx]; + CBpart = &cbmb->strings[cbmb->part_idx]; + dprintf(1, "Found mainboard %s %s\n", CBvendor, CBpart); + } + + return; + +fail: + // No table found.. Use 16Megs as a dummy value. + dprintf(1, "Unable to find coreboot table!\n"); + add_e820(0, 16*1024*1024, E820_RAM); + return; +} + +void coreboot_debug_putc(char c) +{ + if (!CONFIG_DEBUG_COREBOOT) + return; + if (!cbcon) + return; + u32 cursor = cbcon->buffer_cursor++; + if (cursor < cbcon->buffer_size) + cbcon->buffer_body[cursor] = c; +} + +/**************************************************************** + * BIOS table copying + ****************************************************************/ + +// Attempt to find (and relocate) any standard bios tables found in a +// given address range. +static void +scan_tables(u32 start, u32 size) +{ + void *p = (void*)ALIGN(start, 16); + void *end = (void*)start + size; + for (; pmap[i]; + if (m->type == CB_MEM_TABLE) + scan_tables(m->start, m->size); + } + + find_acpi_features(); +} + + +/**************************************************************** + * ulzma + ****************************************************************/ + +// Uncompress data in flash to an area of memory. +static int +ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen) +{ + dprintf(3, "Uncompressing data %d@%p to %d@%p\n", srclen, src, maxlen, dst); + CLzmaDecoderState state; + int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); + if (ret != LZMA_RESULT_OK) { + dprintf(1, "LzmaDecodeProperties error - %d\n", ret); + return -1; + } + u8 scratch[15980]; + int need = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + if (need > sizeof(scratch)) { + dprintf(1, "LzmaDecode need %d have %d\n", need, (unsigned int)sizeof(scratch)); + return -1; + } + state.Probs = (CProb *)scratch; + + u32 dstlen = *(u32*)(src + LZMA_PROPERTIES_SIZE); + if (dstlen > maxlen) { + dprintf(1, "LzmaDecode too large (max %d need %d)\n", maxlen, dstlen); + return -1; + } + u32 inProcessed, outProcessed; + ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, srclen + , &inProcessed, dst, dstlen, &outProcessed); + if (ret) { + dprintf(1, "LzmaDecode returned %d\n", ret); + return -1; + } + return dstlen; +} + + +/**************************************************************** + * Coreboot flash format + ****************************************************************/ + +#define CBFS_HEADER_MAGIC 0x4F524243 +#define CBFS_HEADPTR_ADDR 0xFFFFFFFc +#define CBFS_VERSION1 0x31313131 + +struct cbfs_header { + u32 magic; + u32 version; + u32 romsize; + u32 bootblocksize; + u32 align; + u32 offset; + u32 pad[2]; +} PACKED; + +#define CBFS_FILE_MAGIC 0x455649484352414cLL // LARCHIVE + +struct cbfs_file { + u64 magic; + u32 len; + u32 type; + u32 checksum; + u32 offset; + char filename[0]; +} PACKED; + +struct cbfs_romfile_s { + struct romfile_s file; + struct cbfs_file *fhdr; + void *data; + u32 rawsize, flags; +}; + +// Copy a file to memory (uncompressing if necessary) +static int +cbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) +{ + if (!CONFIG_COREBOOT_FLASH) + return -1; + + struct cbfs_romfile_s *cfile; + cfile = container_of(file, struct cbfs_romfile_s, file); + u32 size = cfile->rawsize; + void *src = cfile->data; + if (cfile->flags) { + // Compressed - copy to temp ram and uncompress it. + void *temp = malloc_tmphigh(size); + if (!temp) { + warn_noalloc(); + return -1; + } + iomemcpy(temp, src, size); + int ret = ulzma(dst, maxlen, temp, size); + yield(); + free(temp); + return ret; + } + + // Not compressed. + dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst); + if (size > maxlen) { + warn_noalloc(); + return -1; + } + iomemcpy(dst, src, size); + return size; +} + +void +coreboot_cbfs_init(void) +{ + if (!CONFIG_COREBOOT_FLASH) + return; + + struct cbfs_header *hdr = *(void **)CBFS_HEADPTR_ADDR; + if (hdr->magic != cpu_to_be32(CBFS_HEADER_MAGIC)) { + dprintf(1, "Unable to find CBFS (ptr=%p; got %x not %x)\n" + , hdr, hdr->magic, cpu_to_be32(CBFS_HEADER_MAGIC)); + return; + } + dprintf(1, "Found CBFS header at %p\n", hdr); + + struct cbfs_file *fhdr = (void *)(0 - be32_to_cpu(hdr->romsize) + + be32_to_cpu(hdr->offset)); + for (;;) { + if (fhdr < (struct cbfs_file *)(0xFFFFFFFF - be32_to_cpu(hdr->romsize))) + break; + u64 magic = fhdr->magic; + if (magic != CBFS_FILE_MAGIC) + break; + struct cbfs_romfile_s *cfile = malloc_tmp(sizeof(*cfile)); + if (!cfile) { + warn_noalloc(); + break; + } + memset(cfile, 0, sizeof(*cfile)); + strtcpy(cfile->file.name, fhdr->filename, sizeof(cfile->file.name)); + cfile->file.size = cfile->rawsize = be32_to_cpu(fhdr->len); + cfile->fhdr = fhdr; + cfile->file.copy = cbfs_copyfile; + cfile->data = (void*)fhdr + be32_to_cpu(fhdr->offset); + int len = strlen(cfile->file.name); + if (len > 5 && strcmp(&cfile->file.name[len-5], ".lzma") == 0) { + // Using compression. + cfile->flags = 1; + cfile->file.name[len-5] = '\0'; + cfile->file.size = *(u32*)(cfile->data + LZMA_PROPERTIES_SIZE); + } + romfile_add(&cfile->file); + + fhdr = (void*)ALIGN((u32)cfile->data + cfile->rawsize + , be32_to_cpu(hdr->align)); + } +} + +struct cbfs_payload_segment { + u32 type; + u32 compression; + u32 offset; + u64 load_addr; + u32 len; + u32 mem_len; +} PACKED; + +#define PAYLOAD_SEGMENT_BSS 0x20535342 +#define PAYLOAD_SEGMENT_ENTRY 0x52544E45 + +#define CBFS_COMPRESS_NONE 0 +#define CBFS_COMPRESS_LZMA 1 + +struct cbfs_payload { + struct cbfs_payload_segment segments[1]; +}; + +void +cbfs_run_payload(struct cbfs_file *fhdr) +{ + if (!CONFIG_COREBOOT_FLASH || !fhdr) + return; + dprintf(1, "Run %s\n", fhdr->filename); + struct cbfs_payload *pay = (void*)fhdr + be32_to_cpu(fhdr->offset); + struct cbfs_payload_segment *seg = pay->segments; + for (;;) { + void *src = (void*)pay + be32_to_cpu(seg->offset); + void *dest = (void*)(u32)be64_to_cpu(seg->load_addr); + u32 src_len = be32_to_cpu(seg->len); + u32 dest_len = be32_to_cpu(seg->mem_len); + switch (seg->type) { + case PAYLOAD_SEGMENT_BSS: + dprintf(3, "BSS segment %d@%p\n", dest_len, dest); + memset(dest, 0, dest_len); + break; + case PAYLOAD_SEGMENT_ENTRY: { + dprintf(1, "Calling addr %p\n", dest); + void (*func)() = dest; + func(); + return; + } + default: + dprintf(3, "Segment %x %d@%p -> %d@%p\n" + , seg->type, src_len, src, dest_len, dest); + if (seg->compression == cpu_to_be32(CBFS_COMPRESS_NONE)) { + if (src_len > dest_len) + src_len = dest_len; + memcpy(dest, src, src_len); + } else if (CONFIG_LZMA + && seg->compression == cpu_to_be32(CBFS_COMPRESS_LZMA)) { + int ret = ulzma(dest, dest_len, src, src_len); + if (ret < 0) + return; + src_len = ret; + } else { + dprintf(1, "No support for compression type %x\n" + , seg->compression); + return; + } + if (dest_len > src_len) + memset(dest + src_len, 0, dest_len - src_len); + break; + } + seg++; + } +} + +// Register payloads in "img/" directory with boot system. +void +cbfs_payload_setup(void) +{ + if (!CONFIG_COREBOOT_FLASH) + return; + struct romfile_s *file = NULL; + for (;;) { + file = romfile_findprefix("img/", file); + if (!file) + break; + struct cbfs_romfile_s *cfile; + cfile = container_of(file, struct cbfs_romfile_s, file); + const char *filename = file->name; + char *desc = znprintf(MAXDESCSIZE, "Payload [%s]", &filename[4]); + boot_add_cbfs(cfile->fhdr, desc, bootprio_find_named_rom(filename, 0)); + } +} diff -Nru seabios-1.7.1/src/fw/csm.c seabios-1.7.4/src/fw/csm.c --- seabios-1.7.1/src/fw/csm.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/csm.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,338 @@ +// Compatibility Support Module (CSM) for UEFI / EDK-II +// +// Copyright © 2013 Intel Corporation +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "bregs.h" +#include "config.h" // CONFIG_* +#include "farptr.h" // MAKE_FLATPTR +#include "hw/pci.h" +#include "hw/pic.h" +#include "malloc.h" // csm_malloc_preinit +#include "memmap.h" +#include "output.h" // dprintf +#include "stacks.h" // wait_threads +#include "std/acpi.h" // RSDP_SIGNATURE +#include "std/bda.h" // struct bios_data_area_s +#include "std/optionrom.h" // struct rom_header +#include "util.h" // copy_smbios +#include "paravirt.h" // qemu_preinit + +#define UINT8 u8 +#define UINT16 u16 +#define UINT32 u32 +#include "std/LegacyBios.h" + +struct rsdp_descriptor csm_rsdp VARFSEG __aligned(16); + +EFI_COMPATIBILITY16_TABLE csm_compat_table VARFSEG __aligned(16) = { + .Signature = 0x24454649, + .TableChecksum = 0 /* Filled in by checkrom.py */, + .TableLength = sizeof(csm_compat_table), + .Compatibility16CallSegment = SEG_BIOS, + .Compatibility16CallOffset = 0 /* Filled in by checkrom.py */, + .OemIdStringPointer = (u32)"SeaBIOS", + .AcpiRsdPtrPointer = (u32)&csm_rsdp, +}; + +EFI_TO_COMPATIBILITY16_INIT_TABLE *csm_init_table; +EFI_TO_COMPATIBILITY16_BOOT_TABLE *csm_boot_table; + +static u16 PICMask = PIC_IRQMASK_DEFAULT; + +extern void __csm_return(struct bregs *regs) __noreturn; + +static void +csm_return(struct bregs *regs) +{ + dprintf(3, "handle_csm returning AX=%04x\n", regs->ax); + + PICMask = pic_irqmask_read(); + __csm_return(regs); +} + +static void +csm_maininit(struct bregs *regs) +{ + interface_init(); + pci_probe_devices(); + + csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS; + csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset(); + + regs->ax = 0; + + csm_return(regs); +} + +/* Legacy16InitializeYourself */ +static void +handle_csm_0000(struct bregs *regs) +{ + qemu_preinit(); + + dprintf(3, "Legacy16InitializeYourself table %04x:%04x\n", regs->es, + regs->bx); + + csm_init_table = MAKE_FLATPTR(regs->es, regs->bx); + + dprintf(3, "BiosLessThan1MB %08x\n", csm_init_table->BiosLessThan1MB); + dprintf(3, "HiPmmMemory %08x\n", csm_init_table->HiPmmMemory); + dprintf(3, "HiPmmMemorySize %08x\n", csm_init_table->HiPmmMemorySizeInBytes); + dprintf(3, "ReverseThunk %04x:%04x\n", csm_init_table->ReverseThunkCallSegment, + csm_init_table->ReverseThunkCallOffset); + dprintf(3, "NumE820Entries %08x\n", csm_init_table->NumberE820Entries); + dprintf(3, "OsMemoryAbove1M %08x\n", csm_init_table->OsMemoryAbove1Mb); + dprintf(3, "ThunkStart %08x\n", csm_init_table->ThunkStart); + dprintf(3, "ThunkSize %08x\n", csm_init_table->ThunkSizeInBytes); + dprintf(3, "LoPmmMemory %08x\n", csm_init_table->LowPmmMemory); + dprintf(3, "LoPmmMemorySize %08x\n", csm_init_table->LowPmmMemorySizeInBytes); + + csm_malloc_preinit(csm_init_table->LowPmmMemory, + csm_init_table->LowPmmMemorySizeInBytes, + csm_init_table->HiPmmMemory, + csm_init_table->HiPmmMemorySizeInBytes); + reloc_preinit(csm_maininit, regs); +} + +/* Legacy16UpdateBbs */ +static void +handle_csm_0001(struct bregs *regs) +{ + if (!CONFIG_BOOT) { + regs->ax = 1; + return; + } + + dprintf(3, "Legacy16UpdateBbs table %04x:%04x\n", regs->es, regs->bx); + + csm_boot_table = MAKE_FLATPTR(regs->es, regs->bx); + dprintf(3, "MajorVersion %04x\n", csm_boot_table->MajorVersion); + dprintf(3, "MinorVersion %04x\n", csm_boot_table->MinorVersion); + dprintf(3, "AcpiTable %08x\n", csm_boot_table->AcpiTable); + dprintf(3, "SmbiosTable %08x\n", csm_boot_table->SmbiosTable); + dprintf(3, "SmbiosTableLength %08x\n", csm_boot_table->SmbiosTableLength); +// dprintf(3, "SioData %08x\n", csm_boot_table->SioData); + dprintf(3, "DevicePathType %04x\n", csm_boot_table->DevicePathType); + dprintf(3, "PciIrqMask %04x\n", csm_boot_table->PciIrqMask); + dprintf(3, "NumberE820Entries %08x\n", csm_boot_table->NumberE820Entries); +// dprintf(3, "HddInfo %08x\n", csm_boot_table->HddInfo); + dprintf(3, "NumberBbsEntries %08x\n", csm_boot_table->NumberBbsEntries); + dprintf(3, "BBsTable %08x\n", csm_boot_table->BbsTable); + dprintf(3, "SmmTable %08x\n", csm_boot_table->SmmTable); + dprintf(3, "OsMemoryAbove1Mb %08x\n", csm_boot_table->OsMemoryAbove1Mb); + dprintf(3, "UnconventionalDeviceTable %08x\n", csm_boot_table->UnconventionalDeviceTable); + + regs->ax = 0; +} + +/* PrepareToBoot */ +static void +handle_csm_0002(struct bregs *regs) +{ + if (!CONFIG_BOOT) { + regs->ax = 1; + return; + } + + dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx); + + struct e820entry *p = (void *)csm_compat_table.E820Pointer; + int i; + for (i=0; i < csm_compat_table.E820Length / sizeof(struct e820entry); i++) + add_e820(p[i].start, p[i].size, p[i].type); + + if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MAX_HIGHTABLE) { + u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes; + add_e820(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED); + } + + // For PCIBIOS 1ab10e + if (csm_compat_table.IrqRoutingTablePointer && + csm_compat_table.IrqRoutingTableLength) { + PirAddr = (void *)csm_compat_table.IrqRoutingTablePointer; + dprintf(3, "CSM PIRQ table at %p\n", PirAddr); + } + + // For find_resume_vector()... and find_acpi_features() + if (csm_rsdp.signature == RSDP_SIGNATURE) { + RsdpAddr = &csm_rsdp; + dprintf(3, "CSM ACPI RSDP at %p\n", RsdpAddr); + + find_acpi_features(); + } + + // SMBIOS table needs to be copied into the f-seg + // XX: OVMF doesn't seem to set SmbiosTableLength so don't check it + if (csm_boot_table->SmbiosTable && !SMBiosAddr) + copy_smbios((void *)csm_boot_table->SmbiosTable); + + // MPTABLE is just there; we don't care where. + + // EFI may have reinitialised the video using its *own* driver. + enable_vga_console(); + + // EFI fills this in for us. Zero it for now... + struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0); + bda->hdcount = 0; + + mathcp_setup(); + timer_setup(); + clock_setup(); + device_hardware_setup(); + wait_threads(); + interactive_bootmenu(); + + prepareboot(); + + regs->ax = 0; +} + +/* Boot */ +static void +handle_csm_0003(struct bregs *regs) +{ + if (!CONFIG_BOOT) { + regs->ax = 1; + return; + } + + dprintf(3, "Boot\n"); + + startBoot(); + + regs->ax = 1; +} + +/* Legacy16DispatchOprom */ +static void +handle_csm_0005(struct bregs *regs) +{ + EFI_DISPATCH_OPROM_TABLE *table = MAKE_FLATPTR(regs->es, regs->bx); + struct rom_header *rom; + u16 bdf; + + if (!CONFIG_OPTIONROMS) { + regs->ax = 1; + return; + } + + dprintf(3, "Legacy16DispatchOprom rom %p\n", table); + + dprintf(3, "OpromSegment %04x\n", table->OpromSegment); + dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment); + dprintf(3, "PnPInstallationCheck %04x:%04x\n", + table->PnPInstallationCheckSegment, + table->PnPInstallationCheckOffset); + dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment); + + rom = MAKE_FLATPTR(table->OpromSegment, 0); + bdf = pci_bus_devfn_to_bdf(table->PciBus, table->PciDeviceFunction); + + rom_reserve(rom->size * 512); + + // XX PnP seg/ofs should never be other than default + callrom(rom, bdf); + + rom_confirm(rom->size * 512); + + regs->bx = 0; // FIXME + regs->ax = 0; +} + +/* Legacy16GetTableAddress */ +static void +handle_csm_0006(struct bregs *regs) +{ + u16 size = regs->cx; + u16 align = regs->dx; + u16 region = regs->bx; // (1 for F000 seg, 2 for E000 seg, 0 for either) + void *chunk = NULL; + + if (!region) + region = 3; + + dprintf(3, "Legacy16GetTableAddress size %x align %x region %d\n", + size, align, region); + + if (region & 2) + chunk = _malloc(&ZoneLow, MALLOC_DEFAULT_HANDLE, size, align); + if (!chunk && (region & 1)) + chunk = _malloc(&ZoneFSeg, MALLOC_DEFAULT_HANDLE, size, align); + + dprintf(3, "Legacy16GetTableAddress size %x align %x region %d yields %p\n", + size, align, region, chunk); + if (chunk) { + regs->ds = FLATPTR_TO_SEG(chunk); + regs->bx = FLATPTR_TO_OFFSET(chunk); + regs->ax = 0; + } else { + regs->ax = 1; + } +} + +void VISIBLE32INIT +handle_csm(struct bregs *regs) +{ + ASSERT32FLAT(); + + if (!CONFIG_CSM) + return; + + dprintf(3, "handle_csm regs %p AX=%04x\n", regs, regs->ax); + + pic_irqmask_write(PICMask); + + switch(regs->ax) { + case 0000: handle_csm_0000(regs); break; + case 0001: handle_csm_0001(regs); break; + case 0002: handle_csm_0002(regs); break; + case 0003: handle_csm_0003(regs); break; +// case 0004: handle_csm_0004(regs); break; + case 0005: handle_csm_0005(regs); break; + case 0006: handle_csm_0006(regs); break; +// case 0007: handle_csm_0007(regs); break; +// case 0008: hamdle_csm_0008(regs); break; + default: regs->al = 1; + } + + csm_return(regs); +} + +int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave) +{ + if (!csm_boot_table) + return -1; + BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable; + int index = 1 + (chanid * 2) + slave; + dprintf(3, "CSM bootprio for ATA%d,%d (index %d) is %d\n", chanid, slave, + index, bbs[index].BootPriority); + return bbs[index].BootPriority; +} + +int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid) +{ + if (!csm_boot_table) + return -1; + BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable; + dprintf(3, "CSM bootprio for FDC is %d\n", bbs[0].BootPriority); + return bbs[0].BootPriority; +} + +int csm_bootprio_pci(struct pci_device *pci) +{ + if (!csm_boot_table) + return -1; + BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable; + int i; + + for (i = 5; i < csm_boot_table->NumberBbsEntries; i++) { + if (pci->bdf == pci_to_bdf(bbs[i].Bus, bbs[i].Device, bbs[i].Function)) { + dprintf(3, "CSM bootprio for PCI(%d,%d,%d) is %d\n", bbs[i].Bus, + bbs[i].Device, bbs[i].Function, bbs[i].BootPriority); + return bbs[i].BootPriority; + } + } + return -1; +} diff -Nru seabios-1.7.1/src/fw/dev-q35.h seabios-1.7.4/src/fw/dev-q35.h --- seabios-1.7.1/src/fw/dev-q35.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/dev-q35.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,46 @@ +#ifndef __DEV_Q35_H +#define __DEV_Q35_H + +#include "types.h" // u16 + +#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0 +#define Q35_HOST_BRIDGE_PAM0 0x90 +#define Q35_HOST_BRIDGE_SMRAM 0x9d +#define Q35_HOST_BRIDGE_PCIEXBAR 0x60 +#define Q35_HOST_BRIDGE_PCIEXBAR_SIZE (256 * 1024 * 1024) +#define Q35_HOST_BRIDGE_PCIEXBAR_ADDR 0xb0000000 +#define Q35_HOST_BRIDGE_PCIEXBAREN ((u64)1) +#define Q35_HOST_PCIE_PCI_SEGMENT 0 +#define Q35_HOST_PCIE_START_BUS_NUMBER 0 +#define Q35_HOST_PCIE_END_BUS_NUMBER 255 + +#define PCI_DEVICE_ID_INTEL_ICH9_LPC 0x2918 +#define ICH9_LPC_PMBASE 0x40 +#define ICH9_LPC_PMBASE_RTE 0x1 + +#define ICH9_LPC_ACPI_CTRL 0x44 +#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80 +#define ICH9_LPC_PIRQA_ROUT 0x60 +#define ICH9_LPC_PIRQE_ROUT 0x68 +#define ICH9_LPC_PIRQ_ROUT_IRQEN 0x80 +#define ICH9_LPC_PORT_ELCR1 0x4d0 +#define ICH9_LPC_PORT_ELCR2 0x4d1 +#define PCI_DEVICE_ID_INTEL_ICH9_SMBUS 0x2930 +#define ICH9_SMB_SMB_BASE 0x20 +#define ICH9_SMB_HOSTC 0x40 +#define ICH9_SMB_HOSTC_HST_EN 0x01 + +#define ICH9_ACPI_ENABLE 0x2 +#define ICH9_ACPI_DISABLE 0x3 + +/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */ +#define ICH9_PMIO_GPE0_STS 0x20 +#define ICH9_PMIO_GPE0_BLK_LEN 0x10 +#define ICH9_PMIO_SMI_EN 0x30 +#define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5) + +/* FADT ACPI_ENABLE/ACPI_DISABLE */ +#define ICH9_APM_ACPI_ENABLE 0x2 +#define ICH9_APM_ACPI_DISABLE 0x3 + +#endif // dev-q35.h diff -Nru seabios-1.7.1/src/fw/lzmadecode.c seabios-1.7.4/src/fw/lzmadecode.c --- seabios-1.7.1/src/fw/lzmadecode.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/lzmadecode.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,398 @@ +/* + LzmaDecode.c + LZMA Decoder (optimized for Speed version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "lzmadecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + + +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + + *inSizeProcessed = 0; + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + RC_INIT(inStream, inSize); + + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + matchByte = outStream[nowPos - rep0]; + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + UpdateBit0(prob); + + if (nowPos == 0) + return LZMA_RESULT_DATA_ERROR; + + state = state < kNumLitStates ? 9 : 11; + previousByte = outStream[nowPos - rep0]; + outStream[nowPos++] = previousByte; + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + if (rep0 > nowPos) + return LZMA_RESULT_DATA_ERROR; + + + do + { + previousByte = outStream[nowPos - rep0]; + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + RC_NORMALIZE; + + + *inSizeProcessed = (SizeT)(Buffer - inStream); + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} diff -Nru seabios-1.7.1/src/fw/lzmadecode.h seabios-1.7.4/src/fw/lzmadecode.h --- seabios-1.7.1/src/fw/lzmadecode.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/lzmadecode.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,67 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +typedef unsigned char Byte; +typedef unsigned short UInt16; +typedef unsigned int UInt32; +typedef UInt32 SizeT; + +#define CProb UInt16 + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + + +} CLzmaDecoderState; + + +int LzmaDecode(CLzmaDecoderState *vs, + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#endif diff -Nru seabios-1.7.1/src/fw/mptable.c seabios-1.7.4/src/fw/mptable.c --- seabios-1.7.1/src/fw/mptable.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/mptable.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,210 @@ +// MPTable generation (on emulators) +// +// Copyright (C) 2008-2010 Kevin O'Connor +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "hw/pci.h" +#include "hw/pci_regs.h" +#include "malloc.h" // free +#include "output.h" // dprintf +#include "romfile.h" // romfile_loadint +#include "std/mptable.h" // MPTABLE_SIGNATURE +#include "string.h" // memset +#include "util.h" // MaxCountCPUs +#include "x86.h" // cpuid + +void +mptable_setup(void) +{ + if (! CONFIG_MPTABLE) + return; + + dprintf(3, "init MPTable\n"); + + // Config structure in temp area. + struct mptable_config_s *config = malloc_tmp(32*1024); + if (!config) { + warn_noalloc(); + return; + } + memset(config, 0, sizeof(*config)); + config->signature = MPCONFIG_SIGNATURE; + config->spec = 4; + memcpy(config->oemid, BUILD_CPUNAME8, sizeof(config->oemid)); + memcpy(config->productid, "0.1 ", sizeof(config->productid)); + config->lapic = BUILD_APIC_ADDR; + + // Detect cpu info + u32 cpuid_signature, ebx, ecx, cpuid_features; + cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features); + if (! cpuid_signature) { + // Use default values. + cpuid_signature = 0x600; + cpuid_features = 0x201; + } + int pkgcpus = 1; + if (cpuid_features & (1 << 28)) { + /* Only populate the MPS tables with the first logical CPU in + each package */ + pkgcpus = (ebx >> 16) & 0xff; + pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */ + } + u8 apic_version = readl((u8*)BUILD_APIC_ADDR + 0x30) & 0xff; + + // CPU definitions. + struct mpt_cpu *cpus = (void*)&config[1], *cpu = cpus; + int i; + for (i = 0; i < MaxCountCPUs; i+=pkgcpus) { + memset(cpu, 0, sizeof(*cpu)); + cpu->type = MPT_TYPE_CPU; + cpu->apicid = i; + cpu->apicver = apic_version; + /* cpu flags: enabled, bootstrap cpu */ + cpu->cpuflag = (apic_id_is_present(i) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00); + cpu->cpusignature = cpuid_signature; + cpu->featureflag = cpuid_features; + cpu++; + } + int entrycount = cpu - cpus; + + // PCI bus + struct mpt_bus *buses = (void*)cpu, *bus = buses; + if (!hlist_empty(&PCIDevices)) { + memset(bus, 0, sizeof(*bus)); + bus->type = MPT_TYPE_BUS; + bus->busid = 0; + memcpy(bus->bustype, "PCI ", sizeof(bus->bustype)); + bus++; + entrycount++; + } + + /* isa bus */ + int isabusid = bus - buses; + memset(bus, 0, sizeof(*bus)); + bus->type = MPT_TYPE_BUS; + bus->busid = isabusid; + memcpy(bus->bustype, "ISA ", sizeof(bus->bustype)); + bus++; + entrycount++; + + /* ioapic */ + u8 ioapic_id = BUILD_IOAPIC_ID; + struct mpt_ioapic *ioapic = (void*)bus; + memset(ioapic, 0, sizeof(*ioapic)); + ioapic->type = MPT_TYPE_IOAPIC; + ioapic->apicid = ioapic_id; + ioapic->apicver = 0x11; + ioapic->flags = 1; // enable + ioapic->apicaddr = BUILD_IOAPIC_ADDR; + entrycount++; + + /* irqs */ + struct mpt_intsrc *intsrcs = (void*)&ioapic[1], *intsrc = intsrcs; + int dev = -1; + unsigned short pinmask = 0; + + struct pci_device *pci; + foreachpci(pci) { + u16 bdf = pci->bdf; + if (pci_bdf_to_bus(bdf) != 0) + break; + int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); + int irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); + if (pin == 0) + continue; + if (dev != pci_bdf_to_busdev(bdf)) { + dev = pci_bdf_to_busdev(bdf); + pinmask = 0; + } + if (pinmask & (1 << pin)) /* pin was seen already */ + continue; + pinmask |= (1 << pin); + memset(intsrc, 0, sizeof(*intsrc)); + intsrc->type = MPT_TYPE_INTSRC; + intsrc->irqtype = 0; /* INT */ + intsrc->irqflag = 1; /* active high */ + intsrc->srcbus = pci_bdf_to_bus(bdf); /* PCI bus */ + intsrc->srcbusirq = (pci_bdf_to_dev(bdf) << 2) | (pin - 1); + intsrc->dstapic = ioapic_id; + intsrc->dstirq = irq; + intsrc++; + } + + int irq0_override = romfile_loadint("etc/irq0-override", 0); + for (i = 0; i < 16; i++) { + memset(intsrc, 0, sizeof(*intsrc)); + if (BUILD_PCI_IRQS & (1 << i)) + continue; + intsrc->type = MPT_TYPE_INTSRC; + intsrc->irqtype = 0; /* INT */ + intsrc->irqflag = 0; /* conform to bus spec */ + intsrc->srcbus = isabusid; /* ISA bus */ + intsrc->srcbusirq = i; + intsrc->dstapic = ioapic_id; + intsrc->dstirq = i; + if (irq0_override) { + /* Destination 2 is covered by irq0->inti2 override (i == + 0). Source IRQ 2 is unused */ + if (i == 0) + intsrc->dstirq = 2; + else if (i == 2) + intsrc--; + } + intsrc++; + } + + /* Local interrupt assignment */ + intsrc->type = MPT_TYPE_LOCAL_INT; + intsrc->irqtype = 3; /* ExtINT */ + intsrc->irqflag = 0; /* PO, EL default */ + intsrc->srcbus = isabusid; /* ISA */ + intsrc->srcbusirq = 0; + intsrc->dstapic = 0; /* BSP == APIC #0 */ + intsrc->dstirq = 0; /* LINTIN0 */ + intsrc++; + + intsrc->type = MPT_TYPE_LOCAL_INT; + intsrc->irqtype = 1; /* NMI */ + intsrc->irqflag = 0; /* PO, EL default */ + intsrc->srcbus = isabusid; /* ISA */ + intsrc->srcbusirq = 0; + intsrc->dstapic = 0xff; /* to all local APICs */ + intsrc->dstirq = 1; /* LINTIN1 */ + intsrc++; + entrycount += intsrc - intsrcs; + + // Finalize config structure. + int length = (void*)intsrc - (void*)config; + config->entrycount = entrycount; + config->length = length; + config->checksum -= checksum(config, length); + + // Allocate final memory locations. (In theory the config + // structure can go in high memory, but Linux kernels before + // v2.6.30 crash with that.) + struct mptable_config_s *finalconfig = malloc_fseg(length); + struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating)); + if (!finalconfig || !floating) { + warn_noalloc(); + free(config); + free(finalconfig); + free(floating); + return; + } + memcpy(finalconfig, config, length); + free(config); + + /* floating pointer structure */ + memset(floating, 0, sizeof(*floating)); + floating->signature = MPTABLE_SIGNATURE; + floating->physaddr = (u32)finalconfig; + floating->length = 1; + floating->spec_rev = 4; + floating->checksum -= checksum(floating, sizeof(*floating)); + + dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n", + floating, finalconfig, length); +} diff -Nru seabios-1.7.1/src/fw/mtrr.c seabios-1.7.4/src/fw/mtrr.c --- seabios-1.7.1/src/fw/mtrr.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/mtrr.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,106 @@ +// Initialize MTRRs - mostly useful on KVM. +// +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "hw/pci.h" // pcimem_start +#include "output.h" // dprintf +#include "paravirt.h" // RamSize +#include "util.h" // mtrr_setup +#include "x86.h" // cpuid + +#define MSR_MTRRcap 0x000000fe +#define MSR_MTRRfix64K_00000 0x00000250 +#define MSR_MTRRfix16K_80000 0x00000258 +#define MSR_MTRRfix16K_A0000 0x00000259 +#define MSR_MTRRfix4K_C0000 0x00000268 +#define MSR_MTRRfix4K_C8000 0x00000269 +#define MSR_MTRRfix4K_D0000 0x0000026a +#define MSR_MTRRfix4K_D8000 0x0000026b +#define MSR_MTRRfix4K_E0000 0x0000026c +#define MSR_MTRRfix4K_E8000 0x0000026d +#define MSR_MTRRfix4K_F0000 0x0000026e +#define MSR_MTRRfix4K_F8000 0x0000026f +#define MSR_MTRRdefType 0x000002ff + +#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) +#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) + +#define MTRR_MEMTYPE_UC 0 +#define MTRR_MEMTYPE_WC 1 +#define MTRR_MEMTYPE_WT 4 +#define MTRR_MEMTYPE_WP 5 +#define MTRR_MEMTYPE_WB 6 + +void mtrr_setup(void) +{ + if (!CONFIG_MTRR_INIT) + return; + + u32 eax, ebx, ecx, edx, cpuid_features; + cpuid(1, &eax, &ebx, &ecx, &cpuid_features); + if (!(cpuid_features & CPUID_MTRR)) + return; + if (!(cpuid_features & CPUID_MSR)) + return; + + dprintf(3, "init mtrr\n"); + + u32 mtrr_cap = rdmsr(MSR_MTRRcap); + int vcnt = mtrr_cap & 0xff; + int fix = mtrr_cap & 0x100; + if (!vcnt || !fix) + return; + + // Disable MTRRs + wrmsr_smp(MSR_MTRRdefType, 0); + + // Set fixed MTRRs + union u64b { + u8 valb[8]; + u64 val; + } u; + u.val = 0; + int i; + for (i = 0; i < 8; i++) + if (RamSize >= 65536 * (i + 1)) + u.valb[i] = MTRR_MEMTYPE_WB; + wrmsr_smp(MSR_MTRRfix64K_00000, u.val); + u.val = 0; + for (i = 0; i < 8; i++) + if (RamSize >= 0x80000 + 16384 * (i + 1)) + u.valb[i] = MTRR_MEMTYPE_WB; + wrmsr_smp(MSR_MTRRfix16K_80000, u.val); + wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached + int j; + for (j = 0; j < 8; j++) { + u.val = 0; + for (i = 0; i < 8; i++) + if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1)) + u.valb[i] = MTRR_MEMTYPE_WP; + wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val); + } + + // Set variable MTRRs + int phys_bits = 36; + cpuid(0x80000000u, &eax, &ebx, &ecx, &edx); + if (eax >= 0x80000008) { + /* Get physical bits from leaf 0x80000008 (if available) */ + cpuid(0x80000008u, &eax, &ebx, &ecx, &edx); + phys_bits = eax & 0xff; + } + u64 phys_mask = ((1ull << phys_bits) - 1); + for (i=0; i +// Copyright (C) 2009 Red Hat Inc. +// +// Authors: +// Gleb Natapov +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "byteorder.h" // be32_to_cpu +#include "config.h" // CONFIG_QEMU +#include "hw/pci.h" // create_pirtable +#include "hw/pci_regs.h" // PCI_DEVICE_ID +#include "hw/rtc.h" // CMOS_* +#include "malloc.h" // malloc_tmp +#include "memmap.h" // add_e820 +#include "output.h" // dprintf +#include "paravirt.h" // qemu_cfg_preinit +#include "romfile.h" // romfile_loadint +#include "string.h" // memset +#include "util.h" // pci_setup +#include "x86.h" // cpuid +#include "xen.h" // xen_biostable_setup + +// Amount of continuous ram under 4Gig +u32 RamSize; +// Amount of continuous ram >4Gig +u64 RamSizeOver4G; +// Type of emulator platform. +int PlatformRunningOn VARFSEG; + +/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It + * should be used to determine that a VM is running under KVM. + */ +#define KVM_CPUID_SIGNATURE 0x40000000 + +static void kvm_detect(void) +{ + unsigned int eax, ebx, ecx, edx; + char signature[13]; + + cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx); + memcpy(signature + 0, &ebx, 4); + memcpy(signature + 4, &ecx, 4); + memcpy(signature + 8, &edx, 4); + signature[12] = 0; + + if (strcmp(signature, "KVMKVMKVM") == 0) { + dprintf(1, "Running on KVM\n"); + PlatformRunningOn |= PF_KVM; + } +} + +static void qemu_detect(void) +{ + if (!CONFIG_QEMU_HARDWARE) + return; + + // check northbridge @ 00:00.0 + u16 v = pci_config_readw(0, PCI_VENDOR_ID); + if (v == 0x0000 || v == 0xffff) + return; + u16 d = pci_config_readw(0, PCI_DEVICE_ID); + u16 sv = pci_config_readw(0, PCI_SUBSYSTEM_VENDOR_ID); + u16 sd = pci_config_readw(0, PCI_SUBSYSTEM_ID); + + if (sv != 0x1af4 || /* Red Hat, Inc */ + sd != 0x1100) /* Qemu virtual machine */ + return; + + PlatformRunningOn |= PF_QEMU; + switch (d) { + case 0x1237: + dprintf(1, "Running on QEMU (i440fx)\n"); + break; + case 0x29c0: + dprintf(1, "Running on QEMU (q35)\n"); + break; + default: + dprintf(1, "Running on QEMU (unknown nb: %04x:%04x)\n", v, d); + break; + } + kvm_detect(); +} + +void +qemu_preinit(void) +{ + qemu_detect(); + + if (!CONFIG_QEMU) + return; + + if (runningOnXen()) { + xen_ramsize_preinit(); + return; + } + + if (!runningOnQEMU()) { + dprintf(1, "Warning: No QEMU Northbridge found (isapc?)\n"); + PlatformRunningOn |= PF_QEMU; + kvm_detect(); + } + + // On emulators, get memory size from nvram. + u32 rs = ((rtc_read(CMOS_MEM_EXTMEM2_LOW) << 16) + | (rtc_read(CMOS_MEM_EXTMEM2_HIGH) << 24)); + if (rs) + rs += 16 * 1024 * 1024; + else + rs = (((rtc_read(CMOS_MEM_EXTMEM_LOW) << 10) + | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18)) + + 1 * 1024 * 1024); + RamSize = rs; + add_e820(0, rs, E820_RAM); + + /* reserve 256KB BIOS area at the end of 4 GB */ + add_e820(0xfffc0000, 256*1024, E820_RESERVED); + + dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize); +} + +void +qemu_platform_setup(void) +{ + if (!CONFIG_QEMU) + return; + + if (runningOnXen()) { + pci_probe_devices(); + xen_hypercall_setup(); + xen_biostable_setup(); + return; + } + + // Initialize pci + pci_setup(); + smm_device_setup(); + smm_setup(); + + // Initialize mtrr and smp + mtrr_setup(); + smp_setup(); + + // Create bios tables + pirtable_setup(); + mptable_setup(); + smbios_setup(); + acpi_setup(); +} + + +/**************************************************************** + * QEMU firmware config (fw_cfg) interface + ****************************************************************/ + +// List of QEMU fw_cfg entries. DO NOT ADD MORE. (All new content +// should be passed via the fw_cfg "file" interface.) +#define QEMU_CFG_SIGNATURE 0x00 +#define QEMU_CFG_ID 0x01 +#define QEMU_CFG_UUID 0x02 +#define QEMU_CFG_NUMA 0x0d +#define QEMU_CFG_BOOT_MENU 0x0e +#define QEMU_CFG_MAX_CPUS 0x0f +#define QEMU_CFG_FILE_DIR 0x19 +#define QEMU_CFG_ARCH_LOCAL 0x8000 +#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) +#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) +#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2) +#define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3) + +static void +qemu_cfg_select(u16 f) +{ + outw(f, PORT_QEMU_CFG_CTL); +} + +static void +qemu_cfg_read(void *buf, int len) +{ + insb(PORT_QEMU_CFG_DATA, buf, len); +} + +static void +qemu_cfg_skip(int len) +{ + while (len--) + inb(PORT_QEMU_CFG_DATA); +} + +static void +qemu_cfg_read_entry(void *buf, int e, int len) +{ + qemu_cfg_select(e); + qemu_cfg_read(buf, len); +} + +struct qemu_romfile_s { + struct romfile_s file; + int select, skip; +}; + +static int +qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) +{ + if (file->size > maxlen) + return -1; + struct qemu_romfile_s *qfile; + qfile = container_of(file, struct qemu_romfile_s, file); + qemu_cfg_select(qfile->select); + qemu_cfg_skip(qfile->skip); + qemu_cfg_read(dst, file->size); + return file->size; +} + +static void +qemu_romfile_add(char *name, int select, int skip, int size) +{ + struct qemu_romfile_s *qfile = malloc_tmp(sizeof(*qfile)); + if (!qfile) { + warn_noalloc(); + return; + } + memset(qfile, 0, sizeof(*qfile)); + strtcpy(qfile->file.name, name, sizeof(qfile->file.name)); + qfile->file.size = size; + qfile->select = select; + qfile->skip = skip; + qfile->file.copy = qemu_cfg_read_file; + romfile_add(&qfile->file); +} + +struct e820_reservation { + u64 address; + u64 length; + u32 type; +}; + +#define SMBIOS_FIELD_ENTRY 0 +#define SMBIOS_TABLE_ENTRY 1 + +struct qemu_smbios_header { + u16 length; + u8 headertype; + u8 tabletype; + u16 fieldoffset; +} PACKED; + +static void +qemu_cfg_e820(void) +{ + struct e820_reservation *table; + int i, size; + + if (!CONFIG_QEMU) + return; + + // "etc/e820" has both ram and reservations + table = romfile_loadfile("etc/e820", &size); + if (table) { + for (i = 0; i < size / sizeof(struct e820_reservation); i++) { + switch (table[i].type) { + case E820_RAM: + dprintf(1, "RamBlock: addr 0x%016llx len 0x%016llx [e820]\n", + table[i].address, table[i].length); + if (table[i].address < RamSize) + // ignore, preinit got it from cmos already and + // adding this again would ruin any reservations + // done so far + continue; + if (table[i].address < 0x100000000LL) { + // below 4g -- adjust RamSize to mark highest lowram addr + if (RamSize < table[i].address + table[i].length) + RamSize = table[i].address + table[i].length; + } else { + // above 4g -- adjust RamSizeOver4G to mark highest ram addr + if (0x100000000LL + RamSizeOver4G < table[i].address + table[i].length) + RamSizeOver4G = table[i].address + table[i].length - 0x100000000LL; + } + /* fall through */ + case E820_RESERVED: + add_e820(table[i].address, table[i].length, table[i].type); + break; + default: + /* + * Qemu 1.7 uses RAM + RESERVED only. Ignore + * everything else, so we have the option to + * extend this in the future without breakage. + */ + break; + } + } + return; + } + + // QEMU_CFG_E820_TABLE has reservations only + u32 count32; + qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32)); + if (count32) { + struct e820_reservation entry; + int i; + for (i = 0; i < count32; i++) { + qemu_cfg_read(&entry, sizeof(entry)); + add_e820(entry.address, entry.length, entry.type); + } + } else if (runningOnKVM()) { + // Backwards compatibility - provide hard coded range. + // 4 pages before the bios, 3 pages for vmx tss pages, the + // other page for EPT real mode pagetable + add_e820(0xfffbc000, 4*4096, E820_RESERVED); + } + + // Check for memory over 4Gig in cmos + u64 high = ((rtc_read(CMOS_MEM_HIGHMEM_LOW) << 16) + | ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24) + | ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32)); + RamSizeOver4G = high; + add_e820(0x100000000ull, high, E820_RAM); + dprintf(1, "RamSizeOver4G: 0x%016llx [cmos]\n", RamSizeOver4G); +} + +// Populate romfile entries for legacy fw_cfg ports (that predate the +// "file" interface). +static void +qemu_cfg_legacy(void) +{ + if (!CONFIG_QEMU) + return; + + // Misc config items. + qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2); + qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1); + qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2); + + // NUMA data + u64 numacount; + qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount)); + int max_cpu = romfile_loadint("etc/max-cpus", 0); + qemu_romfile_add("etc/numa-cpu-map", QEMU_CFG_NUMA, sizeof(numacount) + , max_cpu*sizeof(u64)); + qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA + , sizeof(numacount) + max_cpu*sizeof(u64) + , numacount*sizeof(u64)); + + // ACPI tables + char name[128]; + u16 cnt; + qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt)); + int i, offset = sizeof(cnt); + for (i = 0; i < cnt; i++) { + u16 len; + qemu_cfg_read(&len, sizeof(len)); + offset += sizeof(len); + snprintf(name, sizeof(name), "acpi/table%d", i); + qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len); + qemu_cfg_skip(len); + offset += len; + } + + // SMBIOS info + qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt)); + offset = sizeof(cnt); + for (i = 0; i < cnt; i++) { + struct qemu_smbios_header header; + qemu_cfg_read(&header, sizeof(header)); + if (header.headertype == SMBIOS_FIELD_ENTRY) { + snprintf(name, sizeof(name), "smbios/field%d-%d" + , header.tabletype, header.fieldoffset); + qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES + , offset + sizeof(header) + , header.length - sizeof(header)); + } else { + snprintf(name, sizeof(name), "smbios/table%d-%d" + , header.tabletype, i); + qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES + , offset + 3, header.length - 3); + } + qemu_cfg_skip(header.length - sizeof(header)); + offset += header.length; + } +} + +struct QemuCfgFile { + u32 size; /* file size */ + u16 select; /* write this to 0x510 to read it */ + u16 reserved; + char name[56]; +}; + +void qemu_cfg_init(void) +{ + if (!runningOnQEMU()) + return; + + // Detect fw_cfg interface. + qemu_cfg_select(QEMU_CFG_SIGNATURE); + char *sig = "QEMU"; + int i; + for (i = 0; i < 4; i++) + if (inb(PORT_QEMU_CFG_DATA) != sig[i]) + return; + dprintf(1, "Found QEMU fw_cfg\n"); + + // Populate romfiles for legacy fw_cfg entries + qemu_cfg_legacy(); + + // Load files found in the fw_cfg file directory + u32 count; + qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count)); + count = be32_to_cpu(count); + u32 e; + for (e = 0; e < count; e++) { + struct QemuCfgFile qfile; + qemu_cfg_read(&qfile, sizeof(qfile)); + qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select) + , 0, be32_to_cpu(qfile.size)); + } + + qemu_cfg_e820(); +} diff -Nru seabios-1.7.1/src/fw/paravirt.h seabios-1.7.4/src/fw/paravirt.h --- seabios-1.7.1/src/fw/paravirt.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/paravirt.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,40 @@ +#ifndef __PV_H +#define __PV_H + +#include "config.h" // CONFIG_* +#include "biosvar.h" // GET_GLOBAL + +// Types of paravirtualized platforms. +#define PF_QEMU (1<<0) +#define PF_XEN (1<<1) +#define PF_KVM (1<<2) + +extern u32 RamSize; +extern u64 RamSizeOver4G; +extern int PlatformRunningOn; + +static inline int runningOnQEMU(void) { + return CONFIG_QEMU || ( + CONFIG_QEMU_HARDWARE && GET_GLOBAL(PlatformRunningOn) & PF_QEMU); +} +static inline int runningOnXen(void) { + return CONFIG_XEN && GET_GLOBAL(PlatformRunningOn) & PF_XEN; +} +static inline int runningOnKVM(void) { + return CONFIG_QEMU && GET_GLOBAL(PlatformRunningOn) & PF_KVM; +} + +// Common paravirt ports. +#define PORT_SMI_CMD 0x00b2 +#define PORT_SMI_STATUS 0x00b3 +#define PORT_QEMU_CFG_CTL 0x0510 +#define PORT_QEMU_CFG_DATA 0x0511 +#define PORT_ACPI_PM_BASE 0xb000 +#define PORT_SMB_BASE 0xb100 +#define PORT_BIOS_APM 0x8900 + +void qemu_preinit(void); +void qemu_platform_setup(void); +void qemu_cfg_init(void); + +#endif diff -Nru seabios-1.7.1/src/fw/pciinit.c seabios-1.7.4/src/fw/pciinit.c --- seabios-1.7.1/src/fw/pciinit.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/pciinit.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,860 @@ +// Initialize PCI devices (on emulators) +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "dev-q35.h" // Q35_HOST_BRIDGE_PCIEXBAR_ADDR +#include "hw/ata.h" // PORT_ATA1_CMD_BASE +#include "hw/pci.h" // pci_config_readl +#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL +#include "hw/pci_regs.h" // PCI_COMMAND +#include "list.h" // struct hlist_node +#include "malloc.h" // free +#include "memmap.h" // add_e820 +#include "output.h" // dprintf +#include "paravirt.h" // RamSize +#include "string.h" // memset +#include "util.h" // pci_setup +#include "x86.h" // outb +#include "byteorder.h" // le64_to_cpu +#include "romfile.h" // romfile_loadint + +#define PCI_DEVICE_MEM_MIN (1<<12) // 4k == page size +#define PCI_BRIDGE_MEM_MIN (1<<21) // 2M == hugepage size +#define PCI_BRIDGE_IO_MIN 0x1000 // mandated by pci bridge spec + +enum pci_region_type { + PCI_REGION_TYPE_IO, + PCI_REGION_TYPE_MEM, + PCI_REGION_TYPE_PREFMEM, + PCI_REGION_TYPE_COUNT, +}; + +static const char *region_type_name[] = { + [ PCI_REGION_TYPE_IO ] = "io", + [ PCI_REGION_TYPE_MEM ] = "mem", + [ PCI_REGION_TYPE_PREFMEM ] = "prefmem", +}; + +u64 pcimem_start = BUILD_PCIMEM_START; +u64 pcimem_end = BUILD_PCIMEM_END; +u64 pcimem64_start = BUILD_PCIMEM64_START; +u64 pcimem64_end = BUILD_PCIMEM64_END; + +struct pci_region_entry { + struct pci_device *dev; + int bar; + u64 size; + u64 align; + int is64; + enum pci_region_type type; + struct hlist_node node; +}; + +struct pci_region { + /* pci region assignments */ + u64 base; + struct hlist_head list; +}; + +struct pci_bus { + struct pci_region r[PCI_REGION_TYPE_COUNT]; + struct pci_device *bus_dev; +}; + +static u32 pci_bar(struct pci_device *pci, int region_num) +{ + if (region_num != PCI_ROM_SLOT) { + return PCI_BASE_ADDRESS_0 + region_num * 4; + } + +#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80 + u8 type = pci->header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION; + return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS; +} + +static void +pci_set_io_region_addr(struct pci_device *pci, int bar, u64 addr, int is64) +{ + u32 ofs = pci_bar(pci, bar); + pci_config_writel(pci->bdf, ofs, addr); + if (is64) + pci_config_writel(pci->bdf, ofs + 4, addr >> 32); +} + + +/**************************************************************** + * Misc. device init + ****************************************************************/ + +/* host irqs corresponding to PCI irqs A-D */ +const u8 pci_irqs[4] = { + 10, 10, 11, 11 +}; + +static int dummy_pci_slot_get_irq(struct pci_device *pci, int pin) +{ + dprintf(1, "pci_slot_get_irq called with unknown routing\n"); + + return 0xff; /* PCI defined "unknown" or "no connection" for x86 */ +} + +static int (*pci_slot_get_irq)(struct pci_device *pci, int pin) = + dummy_pci_slot_get_irq; + +// Return the global irq number corresponding to a host bus device irq pin. +static int piix_pci_slot_get_irq(struct pci_device *pci, int pin) +{ + int slot_addend = 0; + + while (pci->parent != NULL) { + slot_addend += pci_bdf_to_dev(pci->bdf); + pci = pci->parent; + } + slot_addend += pci_bdf_to_dev(pci->bdf) - 1; + return pci_irqs[(pin - 1 + slot_addend) & 3]; +} + +static int mch_pci_slot_get_irq(struct pci_device *pci, int pin) +{ + int irq, slot, pin_addend = 0; + + while (pci->parent != NULL) { + pin_addend += pci_bdf_to_dev(pci->bdf); + pci = pci->parent; + } + slot = pci_bdf_to_dev(pci->bdf); + + switch (slot) { + /* Slots 0-24 rotate slot:pin mapping similar to piix above, but + with a different starting index - see q35-acpi-dsdt.dsl */ + case 0 ... 24: + irq = pci_irqs[(pin - 1 + pin_addend + slot) & 3]; + break; + /* Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H) */ + case 25 ... 31: + irq = pci_irqs[(pin - 1 + pin_addend) & 3]; + break; + } + + return irq; +} + +/* PIIX3/PIIX4 PCI to ISA bridge */ +static void piix_isa_bridge_setup(struct pci_device *pci, void *arg) +{ + int i, irq; + u8 elcr[2]; + + elcr[0] = 0x00; + elcr[1] = 0x00; + for (i = 0; i < 4; i++) { + irq = pci_irqs[i]; + /* set to trigger level */ + elcr[irq >> 3] |= (1 << (irq & 7)); + /* activate irq remapping in PIIX */ + pci_config_writeb(pci->bdf, 0x60 + i, irq); + } + outb(elcr[0], 0x4d0); + outb(elcr[1], 0x4d1); + dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]); +} + +/* ICH9 LPC PCI to ISA bridge */ +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */ +void mch_isa_bridge_setup(struct pci_device *dev, void *arg) +{ + u16 bdf = dev->bdf; + int i, irq; + u8 elcr[2]; + + elcr[0] = 0x00; + elcr[1] = 0x00; + + for (i = 0; i < 4; i++) { + irq = pci_irqs[i]; + /* set to trigger level */ + elcr[irq >> 3] |= (1 << (irq & 7)); + + /* activate irq remapping in LPC */ + + /* PIRQ[A-D] routing */ + pci_config_writeb(bdf, ICH9_LPC_PIRQA_ROUT + i, irq); + /* PIRQ[E-H] routing */ + pci_config_writeb(bdf, ICH9_LPC_PIRQE_ROUT + i, irq); + } + outb(elcr[0], ICH9_LPC_PORT_ELCR1); + outb(elcr[1], ICH9_LPC_PORT_ELCR2); + dprintf(1, "Q35 LPC init: elcr=%02x %02x\n", elcr[0], elcr[1]); + + /* pm io base */ + pci_config_writel(bdf, ICH9_LPC_PMBASE, + PORT_ACPI_PM_BASE | ICH9_LPC_PMBASE_RTE); + + /* acpi enable, SCI: IRQ9 000b = irq9*/ + pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN); + + acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04; + pmtimer_setup(PORT_ACPI_PM_BASE + 0x08); +} + +static void storage_ide_setup(struct pci_device *pci, void *arg) +{ + /* IDE: we map it as in ISA mode */ + pci_set_io_region_addr(pci, 0, PORT_ATA1_CMD_BASE, 0); + pci_set_io_region_addr(pci, 1, PORT_ATA1_CTRL_BASE, 0); + pci_set_io_region_addr(pci, 2, PORT_ATA2_CMD_BASE, 0); + pci_set_io_region_addr(pci, 3, PORT_ATA2_CTRL_BASE, 0); +} + +/* PIIX3/PIIX4 IDE */ +static void piix_ide_setup(struct pci_device *pci, void *arg) +{ + u16 bdf = pci->bdf; + pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0 + pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1 +} + +static void pic_ibm_setup(struct pci_device *pci, void *arg) +{ + /* PIC, IBM, MPIC & MPIC2 */ + pci_set_io_region_addr(pci, 0, 0x80800000 + 0x00040000, 0); +} + +static void apple_macio_setup(struct pci_device *pci, void *arg) +{ + /* macio bridge */ + pci_set_io_region_addr(pci, 0, 0x80800000, 0); +} + +/* PIIX4 Power Management device (for ACPI) */ +static void piix4_pm_setup(struct pci_device *pci, void *arg) +{ + u16 bdf = pci->bdf; + // acpi sci is hardwired to 9 + pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9); + + pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1); + pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */ + pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1); + pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */ + + acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04; + pmtimer_setup(PORT_ACPI_PM_BASE + 0x08); +} + +/* ICH9 SMBUS */ +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_SMBUS */ +void ich9_smbus_setup(struct pci_device *dev, void *arg) +{ + u16 bdf = dev->bdf; + /* map smbus into io space */ + pci_config_writel(bdf, ICH9_SMB_SMB_BASE, + PORT_SMB_BASE | PCI_BASE_ADDRESS_SPACE_IO); + + /* enable SMBus */ + pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN); +} + +static const struct pci_device_id pci_device_tbl[] = { + /* PIIX3/PIIX4 PCI to ISA bridge */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, + piix_isa_bridge_setup), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, + piix_isa_bridge_setup), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, + mch_isa_bridge_setup), + + /* STORAGE IDE */ + PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, + PCI_CLASS_STORAGE_IDE, piix_ide_setup), + PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, + PCI_CLASS_STORAGE_IDE, piix_ide_setup), + PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, + storage_ide_setup), + + /* PIC, IBM, MIPC & MPIC2 */ + PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC, + pic_ibm_setup), + PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC, + pic_ibm_setup), + + /* PIIX4 Power Management device (for ACPI) */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, + piix4_pm_setup), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_SMBUS, + ich9_smbus_setup), + + /* 0xff00 */ + PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_setup), + PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_setup), + + PCI_DEVICE_END, +}; + +static void pci_bios_init_device(struct pci_device *pci) +{ + u16 bdf = pci->bdf; + dprintf(1, "PCI: init bdf=%02x:%02x.%x id=%04x:%04x\n" + , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf) + , pci->vendor, pci->device); + + /* map the interrupt */ + int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); + if (pin != 0) + pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin)); + + pci_init_device(pci_device_tbl, pci, NULL); + + /* enable memory mappings */ + pci_config_maskw(bdf, PCI_COMMAND, 0, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR); +} + +static void pci_bios_init_devices(void) +{ + struct pci_device *pci; + foreachpci(pci) { + pci_bios_init_device(pci); + } +} + +static void pci_enable_default_vga(void) +{ + struct pci_device *pci; + + foreachpci(pci) { + if (is_pci_vga(pci)) { + dprintf(1, "PCI: Using %02x:%02x.%x for primary VGA\n", + pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), + pci_bdf_to_fn(pci->bdf)); + return; + } + } + + pci = pci_find_class(PCI_CLASS_DISPLAY_VGA); + if (!pci) { + dprintf(1, "PCI: No VGA devices found\n"); + return; + } + + dprintf(1, "PCI: Enabling %02x:%02x.%x for primary VGA\n", + pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), + pci_bdf_to_fn(pci->bdf)); + + pci_config_maskw(pci->bdf, PCI_COMMAND, 0, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + + while (pci->parent) { + pci = pci->parent; + + dprintf(1, "PCI: Setting VGA enable on bridge %02x:%02x.%x\n", + pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), + pci_bdf_to_fn(pci->bdf)); + + pci_config_maskw(pci->bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_VGA); + pci_config_maskw(pci->bdf, PCI_COMMAND, 0, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + } +} + +/**************************************************************** + * Platform device initialization + ****************************************************************/ + +void i440fx_mem_addr_setup(struct pci_device *dev, void *arg) +{ + if (RamSize <= 0x80000000) + pcimem_start = 0x80000000; + else if (RamSize <= 0xc0000000) + pcimem_start = 0xc0000000; + + pci_slot_get_irq = piix_pci_slot_get_irq; +} + +void mch_mem_addr_setup(struct pci_device *dev, void *arg) +{ + u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR; + u32 size = Q35_HOST_BRIDGE_PCIEXBAR_SIZE; + + /* setup mmconfig */ + u16 bdf = dev->bdf; + u32 upper = addr >> 32; + u32 lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN; + pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0); + pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper); + pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower); + add_e820(addr, size, E820_RESERVED); + + /* setup pci i/o window (above mmconfig) */ + pcimem_start = addr + size; + + pci_slot_get_irq = mch_pci_slot_get_irq; +} + +static const struct pci_device_id pci_platform_tbl[] = { + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, + i440fx_mem_addr_setup), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH, + mch_mem_addr_setup), + PCI_DEVICE_END +}; + +static void pci_bios_init_platform(void) +{ + struct pci_device *pci; + foreachpci(pci) { + pci_init_device(pci_platform_tbl, pci, NULL); + } +} + + +/**************************************************************** + * Bus initialization + ****************************************************************/ + +static void +pci_bios_init_bus_rec(int bus, u8 *pci_bus) +{ + int bdf; + u16 class; + + dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus); + + /* prevent accidental access to unintended devices */ + foreachbdf(bdf, bus) { + class = pci_config_readw(bdf, PCI_CLASS_DEVICE); + if (class == PCI_CLASS_BRIDGE_PCI) { + pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255); + pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0); + } + } + + foreachbdf(bdf, bus) { + class = pci_config_readw(bdf, PCI_CLASS_DEVICE); + if (class != PCI_CLASS_BRIDGE_PCI) { + continue; + } + dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf); + + u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS); + if (pribus != bus) { + dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus); + pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus); + } else { + dprintf(1, "PCI: primary bus = 0x%x\n", pribus); + } + + u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); + (*pci_bus)++; + if (*pci_bus != secbus) { + dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n", + secbus, *pci_bus); + secbus = *pci_bus; + pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus); + } else { + dprintf(1, "PCI: secondary bus = 0x%x\n", secbus); + } + + /* set to max for access to all subordinate buses. + later set it to accurate value */ + u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS); + pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255); + + pci_bios_init_bus_rec(secbus, pci_bus); + + if (subbus != *pci_bus) { + dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n", + subbus, *pci_bus); + subbus = *pci_bus; + } else { + dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus); + } + pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus); + } +} + +static void +pci_bios_init_bus(void) +{ + u8 pci_bus = 0; + pci_bios_init_bus_rec(0 /* host bus */, &pci_bus); +} + + +/**************************************************************** + * Bus sizing + ****************************************************************/ + +static void +pci_bios_get_bar(struct pci_device *pci, int bar, + int *ptype, u64 *psize, int *pis64) +{ + u32 ofs = pci_bar(pci, bar); + u16 bdf = pci->bdf; + u32 old = pci_config_readl(bdf, ofs); + int is64 = 0, type = PCI_REGION_TYPE_MEM; + u64 mask; + + if (bar == PCI_ROM_SLOT) { + mask = PCI_ROM_ADDRESS_MASK; + pci_config_writel(bdf, ofs, mask); + } else { + if (old & PCI_BASE_ADDRESS_SPACE_IO) { + mask = PCI_BASE_ADDRESS_IO_MASK; + type = PCI_REGION_TYPE_IO; + } else { + mask = PCI_BASE_ADDRESS_MEM_MASK; + if (old & PCI_BASE_ADDRESS_MEM_PREFETCH) + type = PCI_REGION_TYPE_PREFMEM; + is64 = ((old & PCI_BASE_ADDRESS_MEM_TYPE_MASK) + == PCI_BASE_ADDRESS_MEM_TYPE_64); + } + pci_config_writel(bdf, ofs, ~0); + } + u64 val = pci_config_readl(bdf, ofs); + pci_config_writel(bdf, ofs, old); + if (is64) { + u32 hold = pci_config_readl(bdf, ofs + 4); + pci_config_writel(bdf, ofs + 4, ~0); + u32 high = pci_config_readl(bdf, ofs + 4); + pci_config_writel(bdf, ofs + 4, hold); + val |= ((u64)high << 32); + mask |= ((u64)0xffffffff << 32); + *psize = (~(val & mask)) + 1; + } else { + *psize = ((~(val & mask)) + 1) & 0xffffffff; + } + *ptype = type; + *pis64 = is64; +} + +static int pci_bios_bridge_region_is64(struct pci_region *r, + struct pci_device *pci, int type) +{ + if (type != PCI_REGION_TYPE_PREFMEM) + return 0; + u32 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE); + if (!pmem) { + pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0); + pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE); + pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0); + } + if ((pmem & PCI_PREF_RANGE_TYPE_MASK) != PCI_PREF_RANGE_TYPE_64) + return 0; + struct pci_region_entry *entry; + hlist_for_each_entry(entry, &r->list, node) { + if (!entry->is64) + return 0; + } + return 1; +} + +static u64 pci_region_align(struct pci_region *r) +{ + struct pci_region_entry *entry; + hlist_for_each_entry(entry, &r->list, node) { + // The first entry in the sorted list has the largest alignment + return entry->align; + } + return 1; +} + +static u64 pci_region_sum(struct pci_region *r) +{ + u64 sum = 0; + struct pci_region_entry *entry; + hlist_for_each_entry(entry, &r->list, node) { + sum += entry->size; + } + return sum; +} + +static void pci_region_migrate_64bit_entries(struct pci_region *from, + struct pci_region *to) +{ + struct hlist_node *n, **last = &to->list.first; + struct pci_region_entry *entry; + hlist_for_each_entry_safe(entry, n, &from->list, node) { + if (!entry->is64) + continue; + if (entry->dev->class == PCI_CLASS_SERIAL_USB) + continue; + // Move from source list to destination list. + hlist_del(&entry->node); + hlist_add(&entry->node, last); + last = &entry->node.next; + } +} + +static struct pci_region_entry * +pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev, + int bar, u64 size, u64 align, int type, int is64) +{ + struct pci_region_entry *entry = malloc_tmp(sizeof(*entry)); + if (!entry) { + warn_noalloc(); + return NULL; + } + memset(entry, 0, sizeof(*entry)); + entry->dev = dev; + entry->bar = bar; + entry->size = size; + entry->align = align; + entry->is64 = is64; + entry->type = type; + // Insert into list in sorted order. + struct hlist_node **pprev; + struct pci_region_entry *pos; + hlist_for_each_entry_pprev(pos, pprev, &bus->r[type].list, node) { + if (pos->align < align || (pos->align == align && pos->size < size)) + break; + } + hlist_add(&entry->node, pprev); + return entry; +} + +static int pci_bios_check_devices(struct pci_bus *busses) +{ + dprintf(1, "PCI: check devices\n"); + + // Calculate resources needed for regular (non-bus) devices. + struct pci_device *pci; + foreachpci(pci) { + if (pci->class == PCI_CLASS_BRIDGE_PCI) + busses[pci->secondary_bus].bus_dev = pci; + + struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)]; + int i; + for (i = 0; i < PCI_NUM_REGIONS; i++) { + if ((pci->class == PCI_CLASS_BRIDGE_PCI) && + (i >= PCI_BRIDGE_NUM_REGIONS && i < PCI_ROM_SLOT)) + continue; + int type, is64; + u64 size; + pci_bios_get_bar(pci, i, &type, &size, &is64); + if (size == 0) + continue; + + if (type != PCI_REGION_TYPE_IO && size < PCI_DEVICE_MEM_MIN) + size = PCI_DEVICE_MEM_MIN; + struct pci_region_entry *entry = pci_region_create_entry( + bus, pci, i, size, size, type, is64); + if (!entry) + return -1; + + if (is64) + i++; + } + } + + // Propagate required bus resources to parent busses. + int secondary_bus; + for (secondary_bus=MaxPCIBus; secondary_bus>0; secondary_bus--) { + struct pci_bus *s = &busses[secondary_bus]; + if (!s->bus_dev) + continue; + struct pci_bus *parent = &busses[pci_bdf_to_bus(s->bus_dev->bdf)]; + int type; + for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) { + u64 align = (type == PCI_REGION_TYPE_IO) ? + PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN; + if (pci_region_align(&s->r[type]) > align) + align = pci_region_align(&s->r[type]); + u64 sum = pci_region_sum(&s->r[type]); + u64 size = ALIGN(sum, align); + int is64 = pci_bios_bridge_region_is64(&s->r[type], + s->bus_dev, type); + // entry->bar is -1 if the entry represents a bridge region + struct pci_region_entry *entry = pci_region_create_entry( + parent, s->bus_dev, -1, size, align, type, is64); + if (!entry) + return -1; + dprintf(1, "PCI: secondary bus %d size %08llx type %s\n", + entry->dev->secondary_bus, size, + region_type_name[entry->type]); + } + } + return 0; +} + + +/**************************************************************** + * BAR assignment + ****************************************************************/ + +// Setup region bases (given the regions' size and alignment) +static int pci_bios_init_root_regions(struct pci_bus *bus) +{ + bus->r[PCI_REGION_TYPE_IO].base = 0xc000; + + struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM]; + struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM]; + + if (pci_region_align(r_start) < pci_region_align(r_end)) { + // Swap regions to improve alignment. + r_end = r_start; + r_start = &bus->r[PCI_REGION_TYPE_PREFMEM]; + } + u64 sum = pci_region_sum(r_end); + u64 align = pci_region_align(r_end); + r_end->base = ALIGN_DOWN((pcimem_end - sum), align); + sum = pci_region_sum(r_start); + align = pci_region_align(r_start); + r_start->base = ALIGN_DOWN((r_end->base - sum), align); + + if ((r_start->base < pcimem_start) || + (r_start->base > pcimem_end)) + // Memory range requested is larger than available. + return -1; + return 0; +} + +#define PCI_IO_SHIFT 8 +#define PCI_MEMORY_SHIFT 16 +#define PCI_PREF_MEMORY_SHIFT 16 + +static void +pci_region_map_one_entry(struct pci_region_entry *entry, u64 addr) +{ + u16 bdf = entry->dev->bdf; + if (entry->bar >= 0) { + dprintf(1, "PCI: map device bdf=%02x:%02x.%x" + " bar %d, addr %08llx, size %08llx [%s]\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), + entry->bar, addr, entry->size, region_type_name[entry->type]); + + pci_set_io_region_addr(entry->dev, entry->bar, addr, entry->is64); + return; + } + + u64 limit = addr + entry->size - 1; + if (entry->type == PCI_REGION_TYPE_IO) { + pci_config_writeb(bdf, PCI_IO_BASE, addr >> PCI_IO_SHIFT); + pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0); + pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT); + pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0); + } + if (entry->type == PCI_REGION_TYPE_MEM) { + pci_config_writew(bdf, PCI_MEMORY_BASE, addr >> PCI_MEMORY_SHIFT); + pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT); + } + if (entry->type == PCI_REGION_TYPE_PREFMEM) { + pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, addr >> PCI_PREF_MEMORY_SHIFT); + pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT); + pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, addr >> 32); + pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, limit >> 32); + } +} + +static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r) +{ + struct hlist_node *n; + struct pci_region_entry *entry; + hlist_for_each_entry_safe(entry, n, &r->list, node) { + u64 addr = r->base; + r->base += entry->size; + if (entry->bar == -1) + // Update bus base address if entry is a bridge region + busses[entry->dev->secondary_bus].r[entry->type].base = addr; + pci_region_map_one_entry(entry, addr); + hlist_del(&entry->node); + free(entry); + } +} + +static void pci_bios_map_devices(struct pci_bus *busses) +{ + dprintf(1, "PCI: 32: %016llx - %016llx\n", pcimem_start, pcimem_end); + if (pci_bios_init_root_regions(busses)) { + struct pci_region r64_mem, r64_pref; + r64_mem.list.first = NULL; + r64_pref.list.first = NULL; + pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM], + &r64_mem); + pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM], + &r64_pref); + + if (pci_bios_init_root_regions(busses)) + panic("PCI: out of 32bit address space\n"); + + u64 sum_mem = pci_region_sum(&r64_mem); + u64 sum_pref = pci_region_sum(&r64_pref); + u64 align_mem = pci_region_align(&r64_mem); + u64 align_pref = pci_region_align(&r64_pref); + + r64_mem.base = le64_to_cpu(romfile_loadint("etc/reserved-memory-end", 0)); + if (r64_mem.base < 0x100000000LL + RamSizeOver4G) + r64_mem.base = 0x100000000LL + RamSizeOver4G; + r64_mem.base = ALIGN(r64_mem.base, align_mem); + r64_mem.base = ALIGN(r64_mem.base, (1LL<<30)); // 1G hugepage + r64_pref.base = r64_mem.base + sum_mem; + r64_pref.base = ALIGN(r64_pref.base, align_pref); + r64_pref.base = ALIGN(r64_pref.base, (1LL<<30)); // 1G hugepage + pcimem64_start = r64_mem.base; + pcimem64_end = r64_pref.base + sum_pref; + pcimem64_end = ALIGN(pcimem64_end, (1LL<<30)); // 1G hugepage + dprintf(1, "PCI: 64: %016llx - %016llx\n", pcimem64_start, pcimem64_end); + + pci_region_map_entries(busses, &r64_mem); + pci_region_map_entries(busses, &r64_pref); + } else { + // no bars mapped high -> drop 64bit window (see dsdt) + pcimem64_start = 0; + } + // Map regions on each device. + int bus; + for (bus = 0; bus<=MaxPCIBus; bus++) { + int type; + for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) + pci_region_map_entries(busses, &busses[bus].r[type]); + } +} + + +/**************************************************************** + * Main setup code + ****************************************************************/ + +void +pci_setup(void) +{ + if (!CONFIG_QEMU) + return; + + dprintf(3, "pci setup\n"); + + dprintf(1, "=== PCI bus & bridge init ===\n"); + if (pci_probe_host() != 0) { + return; + } + pci_bios_init_bus(); + + dprintf(1, "=== PCI device probing ===\n"); + pci_probe_devices(); + + pcimem_start = RamSize; + pci_bios_init_platform(); + + dprintf(1, "=== PCI new allocation pass #1 ===\n"); + struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1)); + if (!busses) { + warn_noalloc(); + return; + } + memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1)); + if (pci_bios_check_devices(busses)) + return; + + dprintf(1, "=== PCI new allocation pass #2 ===\n"); + pci_bios_map_devices(busses); + + pci_bios_init_devices(); + + free(busses); + + pci_enable_default_vga(); +} diff -Nru seabios-1.7.1/src/fw/pirtable.c seabios-1.7.4/src/fw/pirtable.c --- seabios-1.7.1/src/fw/pirtable.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/pirtable.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,106 @@ +// PIR table generation (for emulators) +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "std/pirtable.h" // struct pir_header +#include "string.h" // checksum + +struct pir_header *PirAddr VARFSEG; + +struct pir_table { + struct pir_header pir; + struct pir_slot slots[6]; +} PACKED; + +extern struct pir_table PIR_TABLE; +#if CONFIG_PIRTABLE +struct pir_table PIR_TABLE __aligned(16) VARFSEG = { + .pir = { + .version = 0x0100, + .size = sizeof(struct pir_table), + .router_devfunc = 0x08, + .compatible_devid = 0x122e8086, + }, + .slots = { + { + // first slot entry PCI-to-ISA (embedded) + .dev = 1<<3, + .links = { + {.link = 0x60, .bitmap = 0xdef8}, // INTA# + {.link = 0x61, .bitmap = 0xdef8}, // INTB# + {.link = 0x62, .bitmap = 0xdef8}, // INTC# + {.link = 0x63, .bitmap = 0xdef8}, // INTD# + }, + .slot_nr = 0, // embedded + }, { + // second slot entry: 1st PCI slot + .dev = 2<<3, + .links = { + {.link = 0x61, .bitmap = 0xdef8}, // INTA# + {.link = 0x62, .bitmap = 0xdef8}, // INTB# + {.link = 0x63, .bitmap = 0xdef8}, // INTC# + {.link = 0x60, .bitmap = 0xdef8}, // INTD# + }, + .slot_nr = 1, + }, { + // third slot entry: 2nd PCI slot + .dev = 3<<3, + .links = { + {.link = 0x62, .bitmap = 0xdef8}, // INTA# + {.link = 0x63, .bitmap = 0xdef8}, // INTB# + {.link = 0x60, .bitmap = 0xdef8}, // INTC# + {.link = 0x61, .bitmap = 0xdef8}, // INTD# + }, + .slot_nr = 2, + }, { + // 4th slot entry: 3rd PCI slot + .dev = 4<<3, + .links = { + {.link = 0x63, .bitmap = 0xdef8}, // INTA# + {.link = 0x60, .bitmap = 0xdef8}, // INTB# + {.link = 0x61, .bitmap = 0xdef8}, // INTC# + {.link = 0x62, .bitmap = 0xdef8}, // INTD# + }, + .slot_nr = 3, + }, { + // 5th slot entry: 4rd PCI slot + .dev = 5<<3, + .links = { + {.link = 0x60, .bitmap = 0xdef8}, // INTA# + {.link = 0x61, .bitmap = 0xdef8}, // INTB# + {.link = 0x62, .bitmap = 0xdef8}, // INTC# + {.link = 0x63, .bitmap = 0xdef8}, // INTD# + }, + .slot_nr = 4, + }, { + // 6th slot entry: 5rd PCI slot + .dev = 6<<3, + .links = { + {.link = 0x61, .bitmap = 0xdef8}, // INTA# + {.link = 0x62, .bitmap = 0xdef8}, // INTB# + {.link = 0x63, .bitmap = 0xdef8}, // INTC# + {.link = 0x60, .bitmap = 0xdef8}, // INTD# + }, + .slot_nr = 5, + }, + } +}; +#endif // CONFIG_PIRTABLE + +void +pirtable_setup(void) +{ + if (! CONFIG_PIRTABLE) + return; + + dprintf(3, "init PIR table\n"); + + PIR_TABLE.pir.signature = PIR_SIGNATURE; + PIR_TABLE.pir.checksum -= checksum(&PIR_TABLE, sizeof(PIR_TABLE)); + PirAddr = &PIR_TABLE.pir; +} diff -Nru seabios-1.7.1/src/fw/q35-acpi-dsdt.dsl seabios-1.7.4/src/fw/q35-acpi-dsdt.dsl --- seabios-1.7.1/src/fw/q35-acpi-dsdt.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/q35-acpi-dsdt.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,450 @@ +/* + * Bochs/QEMU ACPI DSDT ASL definition + * + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * Copyright (c) 2010 Isaku Yamahata + * yamahata at valinux co jp + * Based on acpi-dsdt.dsl, but heavily modified for q35 chipset. + */ + +DefinitionBlock ( + "q35-acpi-dsdt.aml",// Output Filename + "DSDT", // Signature + 0x01, // DSDT Compliance Revision + "BXPC", // OEMID + "BXDSDT", // TABLE ID + 0x2 // OEM Revision + ) +{ + +#include "acpi-dsdt-dbug.dsl" + + Scope(\_SB) { + OperationRegion(PCST, SystemIO, 0xae00, 0x0c) + OperationRegion(PCSB, SystemIO, 0xae0c, 0x01) + Field(PCSB, AnyAcc, NoLock, WriteAsZeros) { + PCIB, 8, + } + } + + +/**************************************************************** + * PCI Bus definition + ****************************************************************/ + + Scope(\_SB) { + Device(PCI0) { + Name(_HID, EisaId("PNP0A08")) + Name(_CID, EisaId("PNP0A03")) + Name(_ADR, 0x00) + Name(_UID, 1) + + // _OSC: based on sample of ACPI3.0b spec + Name(SUPP, 0) // PCI _OSC Support Field value + Name(CTRL, 0) // PCI _OSC Control Field value + Method(_OSC, 4) { + // Create DWORD-addressable fields from the Capabilities Buffer + CreateDWordField(Arg3, 0, CDW1) + + // Check for proper UUID + If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) { + // Create DWORD-addressable fields from the Capabilities Buffer + CreateDWordField(Arg3, 4, CDW2) + CreateDWordField(Arg3, 8, CDW3) + + // Save Capabilities DWORD2 & 3 + Store(CDW2, SUPP) + Store(CDW3, CTRL) + + // Always allow native PME, AER (no dependencies) + // Never allow SHPC (no SHPC controller in this system) + And(CTRL, 0x1D, CTRL) + +#if 0 // For now, nothing to do + If (Not(And(CDW1, 1))) { // Query flag clear? + // Disable GPEs for features granted native control. + If (And(CTRL, 0x01)) { // Hot plug control granted? + Store(0, HPCE) // clear the hot plug SCI enable bit + Store(1, HPCS) // clear the hot plug SCI status bit + } + If (And(CTRL, 0x04)) { // PME control granted? + Store(0, PMCE) // clear the PME SCI enable bit + Store(1, PMCS) // clear the PME SCI status bit + } + If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure? + // Set status to not restore PCI Express cap structure + // upon resume from S3 + Store(1, S3CR) + } + } +#endif + If (LNotEqual(Arg1, One)) { + // Unknown revision + Or(CDW1, 0x08, CDW1) + } + If (LNotEqual(CDW3, CTRL)) { + // Capabilities bits were masked + Or(CDW1, 0x10, CDW1) + } + // Update DWORD3 in the buffer + Store(CTRL, CDW3) + } Else { + Or(CDW1, 4, CDW1) // Unrecognized UUID + } + Return (Arg3) + } + } + } + +#include "acpi-dsdt-pci-crs.dsl" +#include "acpi-dsdt-hpet.dsl" + + +/**************************************************************** + * VGA + ****************************************************************/ + + Scope(\_SB.PCI0) { + Device(VGA) { + Name(_ADR, 0x00010000) + Method(_S1D, 0, NotSerialized) { + Return (0x00) + } + Method(_S2D, 0, NotSerialized) { + Return (0x00) + } + Method(_S3D, 0, NotSerialized) { + Return (0x00) + } + } + } + + +/**************************************************************** + * LPC ISA bridge + ****************************************************************/ + + Scope(\_SB.PCI0) { + /* PCI D31:f0 LPC ISA bridge */ + Device(ISA) { + /* PCI D31:f0 */ + Name(_ADR, 0x001f0000) + + /* ICH9 PCI to ISA irq remapping */ + OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C) + + OperationRegion(LPCD, PCI_Config, 0x80, 0x2) + Field(LPCD, AnyAcc, NoLock, Preserve) { + COMA, 3, + , 1, + COMB, 3, + + Offset(0x01), + LPTD, 2, + , 2, + FDCD, 2 + } + OperationRegion(LPCE, PCI_Config, 0x82, 0x2) + Field(LPCE, AnyAcc, NoLock, Preserve) { + CAEN, 1, + CBEN, 1, + LPEN, 1, + FDEN, 1 + } + } + } + +#include "acpi-dsdt-isa.dsl" + + +/**************************************************************** + * PCI IRQs + ****************************************************************/ + + /* Zero => PIC mode, One => APIC Mode */ + Name(\PICF, Zero) + Method(\_PIC, 1, NotSerialized) { + Store(Arg0, \PICF) + } + + Scope(\_SB) { + Scope(PCI0) { +#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3) \ + Package() { nr##ffff, 0, lnk0, 0 }, \ + Package() { nr##ffff, 1, lnk1, 0 }, \ + Package() { nr##ffff, 2, lnk2, 0 }, \ + Package() { nr##ffff, 3, lnk3, 0 } + +#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD) +#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA) +#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB) +#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC) + +#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH) +#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE) +#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF) +#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG) + + Name(PRTP, package() { + prt_slot_lnkE(0x0000), + prt_slot_lnkF(0x0001), + prt_slot_lnkG(0x0002), + prt_slot_lnkH(0x0003), + prt_slot_lnkE(0x0004), + prt_slot_lnkF(0x0005), + prt_slot_lnkG(0x0006), + prt_slot_lnkH(0x0007), + prt_slot_lnkE(0x0008), + prt_slot_lnkF(0x0009), + prt_slot_lnkG(0x000a), + prt_slot_lnkH(0x000b), + prt_slot_lnkE(0x000c), + prt_slot_lnkF(0x000d), + prt_slot_lnkG(0x000e), + prt_slot_lnkH(0x000f), + prt_slot_lnkE(0x0010), + prt_slot_lnkF(0x0011), + prt_slot_lnkG(0x0012), + prt_slot_lnkH(0x0013), + prt_slot_lnkE(0x0014), + prt_slot_lnkF(0x0015), + prt_slot_lnkG(0x0016), + prt_slot_lnkH(0x0017), + prt_slot_lnkE(0x0018), + + /* INTA -> PIRQA for slot 25 - 31 + see the default value of DIR */ + prt_slot_lnkA(0x0019), + prt_slot_lnkA(0x001a), + prt_slot_lnkA(0x001b), + prt_slot_lnkA(0x001c), + prt_slot_lnkA(0x001d), + + /* PCIe->PCI bridge. use PIRQ[E-H] */ + prt_slot_lnkE(0x001e), + + prt_slot_lnkA(0x001f) + }) + +#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3) \ + Package() { nr##ffff, 0, gsi0, 0 }, \ + Package() { nr##ffff, 1, gsi1, 0 }, \ + Package() { nr##ffff, 2, gsi2, 0 }, \ + Package() { nr##ffff, 3, gsi3, 0 } + +#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID) +#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA) +#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB) +#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC) + +#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH) +#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE) +#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF) +#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG) + + Name(PRTA, package() { + prt_slot_gsiE(0x0000), + prt_slot_gsiF(0x0001), + prt_slot_gsiG(0x0002), + prt_slot_gsiH(0x0003), + prt_slot_gsiE(0x0004), + prt_slot_gsiF(0x0005), + prt_slot_gsiG(0x0006), + prt_slot_gsiH(0x0007), + prt_slot_gsiE(0x0008), + prt_slot_gsiF(0x0009), + prt_slot_gsiG(0x000a), + prt_slot_gsiH(0x000b), + prt_slot_gsiE(0x000c), + prt_slot_gsiF(0x000d), + prt_slot_gsiG(0x000e), + prt_slot_gsiH(0x000f), + prt_slot_gsiE(0x0010), + prt_slot_gsiF(0x0011), + prt_slot_gsiG(0x0012), + prt_slot_gsiH(0x0013), + prt_slot_gsiE(0x0014), + prt_slot_gsiF(0x0015), + prt_slot_gsiG(0x0016), + prt_slot_gsiH(0x0017), + prt_slot_gsiE(0x0018), + + /* INTA -> PIRQA for slot 25 - 31, but 30 + see the default value of DIR */ + prt_slot_gsiA(0x0019), + prt_slot_gsiA(0x001a), + prt_slot_gsiA(0x001b), + prt_slot_gsiA(0x001c), + prt_slot_gsiA(0x001d), + + /* PCIe->PCI bridge. use PIRQ[E-H] */ + prt_slot_gsiE(0x001e), + + prt_slot_gsiA(0x001f) + }) + + Method(_PRT, 0, NotSerialized) { + /* PCI IRQ routing table, example from ACPI 2.0a specification, + section 6.2.8.1 */ + /* Note: we provide the same info as the PCI routing + table of the Bochs BIOS */ + If (LEqual(\PICF, Zero)) { + Return (PRTP) + } Else { + Return (PRTA) + } + } + } + + Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) { + PRQA, 8, + PRQB, 8, + PRQC, 8, + PRQD, 8, + + Offset(0x08), + PRQE, 8, + PRQF, 8, + PRQG, 8, + PRQH, 8 + } + + Method(IQST, 1, NotSerialized) { + // _STA method - get status + If (And(0x80, Arg0)) { + Return (0x09) + } + Return (0x0B) + } + Method(IQCR, 1, Serialized) { + // _CRS method - get current settings + Name(PRR0, ResourceTemplate() { + Interrupt(, Level, ActiveHigh, Shared) { 0 } + }) + CreateDWordField(PRR0, 0x05, PRRI) + Store(And(Arg0, 0x0F), PRRI) + Return (PRR0) + } + +#define define_link(link, uid, reg) \ + Device(link) { \ + Name(_HID, EISAID("PNP0C0F")) \ + Name(_UID, uid) \ + Name(_PRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + 5, 10, 11 \ + } \ + }) \ + Method(_STA, 0, NotSerialized) { \ + Return (IQST(reg)) \ + } \ + Method(_DIS, 0, NotSerialized) { \ + Or(reg, 0x80, reg) \ + } \ + Method(_CRS, 0, NotSerialized) { \ + Return (IQCR(reg)) \ + } \ + Method(_SRS, 1, NotSerialized) { \ + CreateDWordField(Arg0, 0x05, PRRI) \ + Store(PRRI, reg) \ + } \ + } + + define_link(LNKA, 0, PRQA) + define_link(LNKB, 1, PRQB) + define_link(LNKC, 2, PRQC) + define_link(LNKD, 3, PRQD) + define_link(LNKE, 4, PRQE) + define_link(LNKF, 5, PRQF) + define_link(LNKG, 6, PRQG) + define_link(LNKH, 7, PRQH) + +#define define_gsi_link(link, uid, gsi) \ + Device(link) { \ + Name(_HID, EISAID("PNP0C0F")) \ + Name(_UID, uid) \ + Name(_PRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + gsi \ + } \ + }) \ + Name(_CRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + gsi \ + } \ + }) \ + Method(_SRS, 1, NotSerialized) { \ + } \ + } + + define_gsi_link(GSIA, 0, 0x10) + define_gsi_link(GSIB, 0, 0x11) + define_gsi_link(GSIC, 0, 0x12) + define_gsi_link(GSID, 0, 0x13) + define_gsi_link(GSIE, 0, 0x14) + define_gsi_link(GSIF, 0, 0x15) + define_gsi_link(GSIG, 0, 0x16) + define_gsi_link(GSIH, 0, 0x17) + } + +#include "acpi-dsdt-cpu-hotplug.dsl" + + +/**************************************************************** + * General purpose events + ****************************************************************/ + + Scope(\_GPE) { + Name(_HID, "ACPI0006") + + Method(_L00) { + } + Method(_L01) { + // CPU hotplug event + \_SB.PRSC() + } + Method(_L02) { + } + Method(_L03) { + } + Method(_L04) { + } + Method(_L05) { + } + Method(_L06) { + } + Method(_L07) { + } + Method(_L08) { + } + Method(_L09) { + } + Method(_L0A) { + } + Method(_L0B) { + } + Method(_L0C) { + } + Method(_L0D) { + } + Method(_L0E) { + } + Method(_L0F) { + } + } +} diff -Nru seabios-1.7.1/src/fw/romfile_loader.c seabios-1.7.4/src/fw/romfile_loader.c --- seabios-1.7.1/src/fw/romfile_loader.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/romfile_loader.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,177 @@ +#include "romfile_loader.h" +#include "byteorder.h" // leXX_to_cpu/cpu_to_leXX +#include "util.h" // checksum +#include "string.h" // strcmp +#include "romfile.h" // struct romfile_s +#include "malloc.h" // Zone*, _malloc +#include "output.h" // warn_* + +struct romfile_loader_file { + struct romfile_s *file; + void *data; +}; +struct romfile_loader_files { + int nfiles; + struct romfile_loader_file files[]; +}; + +static struct romfile_loader_file * +romfile_loader_find(const char *name, + struct romfile_loader_files *files) +{ + int i; + if (name[ROMFILE_LOADER_FILESZ - 1]) + return NULL; + for (i = 0; i < files->nfiles; ++i) + if (!strcmp(files->files[i].file->name, name)) + return &files->files[i]; + return NULL; +} + +static void romfile_loader_allocate(struct romfile_loader_entry_s *entry, + struct romfile_loader_files *files) +{ + struct zone_s *zone; + struct romfile_loader_file *file = &files->files[files->nfiles]; + void *data; + int ret; + unsigned alloc_align = le32_to_cpu(entry->alloc_align); + + if (alloc_align & (alloc_align - 1)) + goto err; + + switch (entry->alloc_zone) { + case ROMFILE_LOADER_ALLOC_ZONE_HIGH: + zone = &ZoneHigh; + break; + case ROMFILE_LOADER_ALLOC_ZONE_FSEG: + zone = &ZoneFSeg; + break; + default: + goto err; + } + if (alloc_align < MALLOC_MIN_ALIGN) + alloc_align = MALLOC_MIN_ALIGN; + if (entry->alloc_file[ROMFILE_LOADER_FILESZ - 1]) + goto err; + file->file = romfile_find(entry->alloc_file); + if (!file->file || !file->file->size) + return; + data = _malloc(zone, MALLOC_DEFAULT_HANDLE, file->file->size, alloc_align); + if (!data) { + warn_noalloc(); + return; + } + ret = file->file->copy(file->file, data, file->file->size); + if (ret != file->file->size) + goto file_err; + file->data = data; + files->nfiles++; + return; + +file_err: + free(data); +err: + warn_internalerror(); +} + +static void romfile_loader_add_pointer(struct romfile_loader_entry_s *entry, + struct romfile_loader_files *files) +{ + struct romfile_loader_file *dest_file; + struct romfile_loader_file *src_file; + unsigned offset = le32_to_cpu(entry->pointer_offset); + u64 pointer = 0; + + dest_file = romfile_loader_find(entry->pointer_dest_file, files); + src_file = romfile_loader_find(entry->pointer_src_file, files); + + if (!dest_file || !src_file || !dest_file->data || !src_file->data || + offset + entry->pointer_size < offset || + offset + entry->pointer_size > dest_file->file->size || + entry->pointer_size < 1 || entry->pointer_size > 8 || + entry->pointer_size & (entry->pointer_size - 1)) + goto err; + + memcpy(&pointer, dest_file->data + offset, entry->pointer_size); + pointer = le64_to_cpu(pointer); + pointer += (unsigned long)src_file->data; + pointer = cpu_to_le64(pointer); + memcpy(dest_file->data + offset, &pointer, entry->pointer_size); + + return; +err: + warn_internalerror(); +} + +static void romfile_loader_add_checksum(struct romfile_loader_entry_s *entry, + struct romfile_loader_files *files) +{ + struct romfile_loader_file *file; + unsigned offset = le32_to_cpu(entry->cksum_offset); + unsigned start = le32_to_cpu(entry->cksum_start); + unsigned len = le32_to_cpu(entry->cksum_length); + u8 *data; + + file = romfile_loader_find(entry->cksum_file, files); + + if (!file || !file->data || offset >= file->file->size || + start + len < start || start + len > file->file->size) + goto err; + + data = file->data + offset; + *data -= checksum(file->data + start, len); + + return; +err: + warn_internalerror(); +} + +int romfile_loader_execute(const char *name) +{ + struct romfile_loader_entry_s *entry; + int size, offset = 0, nfiles; + struct romfile_loader_files *files; + void *data = romfile_loadfile(name, &size); + if (!data) + return -1; + + if (size % sizeof(*entry)) { + warn_internalerror(); + goto err; + } + + /* (over)estimate the number of files to load. */ + nfiles = size / sizeof(*entry); + files = malloc_tmp(sizeof(*files) + nfiles * sizeof(files->files[0])); + if (!files) { + warn_noalloc(); + goto err; + } + files->nfiles = 0; + + for (offset = 0; offset < size; offset += sizeof(*entry)) { + entry = data + offset; + switch (le32_to_cpu(entry->command)) { + case ROMFILE_LOADER_COMMAND_ALLOCATE: + romfile_loader_allocate(entry, files); + break; + case ROMFILE_LOADER_COMMAND_ADD_POINTER: + romfile_loader_add_pointer(entry, files); + break; + case ROMFILE_LOADER_COMMAND_ADD_CHECKSUM: + romfile_loader_add_checksum(entry, files); + default: + /* Skip commands that we don't recognize. */ + break; + } + } + + free(files); + free(data); + return 0; + +err: + free(data); + return -1; +} diff -Nru seabios-1.7.1/src/fw/romfile_loader.h seabios-1.7.4/src/fw/romfile_loader.h --- seabios-1.7.1/src/fw/romfile_loader.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/romfile_loader.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,72 @@ +#ifndef __ROMFILE_LOADER_H +#define __ROMFILE_LOADER_H + +#include "types.h" // u8 +#include "util.h" // romfile_s + +#define ROMFILE_LOADER_FILESZ 56 + +/* ROM file linker/loader interface. Linker uses little endian format */ +struct romfile_loader_entry_s { + u32 command; + union { + /* + * COMMAND_ALLOCATE - allocate a table from @alloc_file + * subject to @alloc_align alignment (must be power of 2) + * and @alloc_zone (can be HIGH or FSEG) requirements. + * + * Must appear exactly once for each file, and before + * this file is referenced by any other command. + */ + struct { + char alloc_file[ROMFILE_LOADER_FILESZ]; + u32 alloc_align; + u8 alloc_zone; + }; + + /* + * COMMAND_ADD_POINTER - patch the table (originating from + * @dest_file) at @pointer_offset, by adding a pointer to the table + * originating from @src_file. 1,2,4 or 8 byte unsigned + * addition is used depending on @pointer_size. + */ + struct { + char pointer_dest_file[ROMFILE_LOADER_FILESZ]; + char pointer_src_file[ROMFILE_LOADER_FILESZ]; + u32 pointer_offset; + u8 pointer_size; + }; + + /* + * COMMAND_ADD_CHECKSUM - calculate checksum of the range specified by + * @cksum_start and @cksum_length fields, + * and then add the value at @cksum_offset. + * Checksum simply sums -X for each byte X in the range + * using 8-bit math. + */ + struct { + char cksum_file[ROMFILE_LOADER_FILESZ]; + u32 cksum_offset; + u32 cksum_start; + u32 cksum_length; + }; + + /* padding */ + char pad[124]; + }; +}; + +enum { + ROMFILE_LOADER_COMMAND_ALLOCATE = 0x1, + ROMFILE_LOADER_COMMAND_ADD_POINTER = 0x2, + ROMFILE_LOADER_COMMAND_ADD_CHECKSUM = 0x3, +}; + +enum { + ROMFILE_LOADER_ALLOC_ZONE_HIGH = 0x1, + ROMFILE_LOADER_ALLOC_ZONE_FSEG = 0x2, +}; + +int romfile_loader_execute(const char *name); + +#endif diff -Nru seabios-1.7.1/src/fw/shadow.c seabios-1.7.4/src/fw/shadow.c --- seabios-1.7.1/src/fw/shadow.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/shadow.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,172 @@ +// Support for enabling/disabling BIOS ram shadowing. +// +// Copyright (C) 2008-2010 Kevin O'Connor +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "dev-q35.h" // PCI_VENDOR_ID_INTEL +#include "hw/pci.h" // pci_config_writeb +#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL +#include "hw/pci_regs.h" // PCI_VENDOR_ID +#include "malloc.h" // rom_get_last +#include "output.h" // dprintf +#include "paravirt.h" // runningOnXen +#include "string.h" // memset +#include "util.h" // make_bios_writable +#include "x86.h" // wbinvd + +// On the emulators, the bios at 0xf0000 is also at 0xffff0000 +#define BIOS_SRC_OFFSET 0xfff00000 + +#define I440FX_PAM0 0x59 + +// Enable shadowing and copy bios. +static void +__make_bios_writable_intel(u16 bdf, u32 pam0) +{ + // Make ram from 0xc0000-0xf0000 writable + int clear = 0; + int i; + for (i=0; i<6; i++) { + u32 pam = pam0 + 1 + i; + int reg = pci_config_readb(bdf, pam); + if (CONFIG_OPTIONROMS_DEPLOYED && (reg & 0x11) != 0x11) { + // Need to copy optionroms to work around qemu implementation + void *mem = (void*)(BUILD_ROM_START + i * 32*1024); + memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024); + pci_config_writeb(bdf, pam, 0x33); + memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024); + clear = 1; + } else { + pci_config_writeb(bdf, pam, 0x33); + } + } + if (clear) + memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024); + + // Make ram from 0xf0000-0x100000 writable + int reg = pci_config_readb(bdf, pam0); + pci_config_writeb(bdf, pam0, 0x30); + if (reg & 0x10) + // Ram already present. + return; + + // Copy bios. + extern u8 code32flat_start[], code32flat_end[]; + memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET + , code32flat_end - code32flat_start); +} + +static void +make_bios_writable_intel(u16 bdf, u32 pam0) +{ + int reg = pci_config_readb(bdf, pam0); + if (!(reg & 0x10)) { + // QEMU doesn't fully implement the piix shadow capabilities - + // if ram isn't backing the bios segment when shadowing is + // disabled, the code itself wont be in memory. So, run the + // code from the high-memory flash location. + u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET; + void (*func)(u16 bdf, u32 pam0) = (void*)pos; + func(bdf, pam0); + return; + } + // Ram already present - just enable writes + __make_bios_writable_intel(bdf, pam0); +} + +static void +make_bios_readonly_intel(u16 bdf, u32 pam0) +{ + // Flush any pending writes before locking memory. + wbinvd(); + + // Write protect roms from 0xc0000-0xf0000 + u32 romlast = BUILD_BIOS_ADDR, rommax = BUILD_BIOS_ADDR; + if (CONFIG_WRITABLE_UPPERMEMORY) + romlast = rom_get_last(); + if (CONFIG_MALLOC_UPPERMEMORY) + rommax = rom_get_max(); + int i; + for (i=0; i<6; i++) { + u32 mem = BUILD_ROM_START + i * 32*1024; + u32 pam = pam0 + 1 + i; + if (romlast < mem + 16*1024 || rommax < mem + 32*1024) { + if (romlast >= mem && rommax >= mem + 16*1024) + pci_config_writeb(bdf, pam, 0x31); + break; + } + pci_config_writeb(bdf, pam, 0x11); + } + + // Write protect 0xf0000-0x100000 + pci_config_writeb(bdf, pam0, 0x10); +} + +static int ShadowBDF = -1; + +// Make the 0xc0000-0x100000 area read/writable. +void +make_bios_writable(void) +{ + if (!CONFIG_QEMU || runningOnXen()) + return; + + dprintf(3, "enabling shadow ram\n"); + + // At this point, statically allocated variables can't be written, + // so do this search manually. + int bdf; + foreachbdf(bdf, 0) { + u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID); + u16 vendor = vendev & 0xffff, device = vendev >> 16; + if (vendor == PCI_VENDOR_ID_INTEL + && device == PCI_DEVICE_ID_INTEL_82441) { + make_bios_writable_intel(bdf, I440FX_PAM0); + ShadowBDF = bdf; + return; + } + if (vendor == PCI_VENDOR_ID_INTEL + && device == PCI_DEVICE_ID_INTEL_Q35_MCH) { + make_bios_writable_intel(bdf, Q35_HOST_BRIDGE_PAM0); + ShadowBDF = bdf; + return; + } + } + dprintf(1, "Unable to unlock ram - bridge not found\n"); +} + +// Make the BIOS code segment area (0xf0000) read-only. +void +make_bios_readonly(void) +{ + if (!CONFIG_QEMU || runningOnXen()) + return; + dprintf(3, "locking shadow ram\n"); + + if (ShadowBDF < 0) { + dprintf(1, "Unable to lock ram - bridge not found\n"); + return; + } + + u16 device = pci_config_readw(ShadowBDF, PCI_DEVICE_ID); + if (device == PCI_DEVICE_ID_INTEL_82441) + make_bios_readonly_intel(ShadowBDF, I440FX_PAM0); + else + make_bios_readonly_intel(ShadowBDF, Q35_HOST_BRIDGE_PAM0); +} + +void +qemu_prep_reset(void) +{ + if (!CONFIG_QEMU || runningOnXen()) + return; + // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a + // reset, so do that manually before invoking a hard reset. + make_bios_writable(); + extern u8 code32flat_start[], code32flat_end[]; + memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET + , code32flat_end - code32flat_start); +} diff -Nru seabios-1.7.1/src/fw/smbios.c seabios-1.7.4/src/fw/smbios.c --- seabios-1.7.1/src/fw/smbios.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/smbios.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,654 @@ +// smbios table generation (on emulators) +// +// Copyright (C) 2008,2009 Kevin O'Connor +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "paravirt.h" // RamSize +#include "romfile.h" // romfile_findprefix +#include "std/smbios.h" // struct smbios_entry_point +#include "string.h" // memset +#include "util.h" // MaxCountCPUs +#include "x86.h" // cpuid + +struct smbios_entry_point *SMBiosAddr; + +static void +smbios_entry_point_setup(u16 max_structure_size, + u16 structure_table_length, + void *structure_table_address, + u16 number_of_structures) +{ + struct smbios_entry_point *ep = malloc_fseg(sizeof(*ep)); + void *finaltable; + if (structure_table_length <= BUILD_MAX_SMBIOS_FSEG) + // Table is small enough for f-seg - allocate there. This + // works around a bug in JunOS (at least for small SMBIOS tables). + finaltable = malloc_fseg(structure_table_length); + else + finaltable = malloc_high(structure_table_length); + if (!ep || !finaltable) { + warn_noalloc(); + free(ep); + free(finaltable); + return; + } + memcpy(finaltable, structure_table_address, structure_table_length); + + memcpy(ep->anchor_string, "_SM_", 4); + ep->length = 0x1f; + ep->smbios_major_version = 2; + ep->smbios_minor_version = 4; + ep->max_structure_size = max_structure_size; + ep->entry_point_revision = 0; + memset(ep->formatted_area, 0, 5); + memcpy(ep->intermediate_anchor_string, "_DMI_", 5); + + ep->structure_table_length = structure_table_length; + ep->structure_table_address = (u32)finaltable; + ep->number_of_structures = number_of_structures; + ep->smbios_bcd_revision = 0x24; + + ep->checksum -= checksum(ep, 0x10); + + ep->intermediate_checksum -= checksum((void*)ep + 0x10, ep->length - 0x10); + + SMBiosAddr = ep; + dprintf(1, "SMBIOS ptr=%p table=%p size=%d\n" + , ep, finaltable, structure_table_length); +} + +static int +get_field(int type, int offset, void *dest) +{ + char name[128]; + snprintf(name, sizeof(name), "smbios/field%d-%d", type, offset); + struct romfile_s *file = romfile_find(name); + if (!file) + return 0; + file->copy(file, dest, file->size); + return file->size; +} + +static int +get_external(int type, char **p, unsigned *nr_structs, + unsigned *max_struct_size, char *end) +{ + static u64 used_bitmap[4] = { 0 }; + char *start = *p; + + /* Check if we've already reported these tables */ + if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f))) + return 1; + + /* Don't introduce spurious end markers */ + if (type == 127) + return 0; + + char prefix[128]; + snprintf(prefix, sizeof(prefix), "smbios/table%d-", type); + struct romfile_s *file = NULL; + for (;;) { + file = romfile_findprefix(prefix, file); + if (!file) + break; + + if (end - *p < file->size) { + warn_noalloc(); + break; + } + + struct smbios_structure_header *header = (void*)*p; + file->copy(file, header, file->size); + *p += file->size; + + /* Entries end with a double NULL char, if there's a string at + * the end (length is greater than formatted length), the string + * terminator provides the first NULL. */ + *((u8*)*p) = 0; + (*p)++; + if (header->length >= file->size) { + *((u8*)*p) = 0; + (*p)++; + } + + (*nr_structs)++; + if (*p - (char*)header > *max_struct_size) + *max_struct_size = *p - (char*)header; + } + + if (start == *p) + return 0; + + /* Mark that we've reported on this type */ + used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f)); + return 1; +} + +#define load_str_field_with_default(type, field, def) \ + do { \ + size = get_field(type, offsetof(struct smbios_type_##type, \ + field), end); \ + if (size > 0) { \ + end += size; \ + } else { \ + memcpy(end, def, sizeof(def)); \ + end += sizeof(def); \ + } \ + p->field = ++str_index; \ + } while (0) + +#define load_str_field_or_skip(type, field) \ + do { \ + size = get_field(type, offsetof(struct smbios_type_##type, \ + field), end); \ + if (size > 0) { \ + end += size; \ + p->field = ++str_index; \ + } else { \ + p->field = 0; \ + } \ + } while (0) + +#define set_field_with_default(type, field, def) \ + do { \ + if (!get_field(type, offsetof(struct smbios_type_##type, \ + field), &p->field)) { \ + p->field = def; \ + } \ + } while (0) + +/* Type 0 -- BIOS Information */ +#define RELEASE_DATE_STR "01/01/2011" +static void * +smbios_init_type_0(void *start) +{ + struct smbios_type_0 *p = (struct smbios_type_0 *)start; + char *end = (char *)start + sizeof(struct smbios_type_0); + size_t size; + int str_index = 0; + + p->header.type = 0; + p->header.length = sizeof(struct smbios_type_0); + p->header.handle = 0; + + load_str_field_with_default(0, vendor_str, BUILD_APPNAME); + load_str_field_with_default(0, bios_version_str, BUILD_APPNAME); + + p->bios_starting_address_segment = 0xe800; + + load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR); + + p->bios_rom_size = 0; /* FIXME */ + + if (!get_field(0, offsetof(struct smbios_type_0, bios_characteristics), + &p->bios_characteristics)) { + memset(p->bios_characteristics, 0, 8); + /* BIOS characteristics not supported */ + p->bios_characteristics[0] = 0x08; + } + + if (!get_field(0, offsetof(struct smbios_type_0, + bios_characteristics_extension_bytes), + &p->bios_characteristics_extension_bytes)) { + p->bios_characteristics_extension_bytes[0] = 0; + /* Enable targeted content distribution. Needed for SVVP */ + p->bios_characteristics_extension_bytes[1] = 4; + } + + set_field_with_default(0, system_bios_major_release, 1); + set_field_with_default(0, system_bios_minor_release, 0); + set_field_with_default(0, embedded_controller_major_release, 0xff); + set_field_with_default(0, embedded_controller_minor_release, 0xff); + + *end = 0; + end++; + + return end; +} + +/* Type 1 -- System Information */ +static void * +smbios_init_type_1(void *start) +{ + struct smbios_type_1 *p = (struct smbios_type_1 *)start; + char *end = (char *)start + sizeof(struct smbios_type_1); + size_t size; + int str_index = 0; + + p->header.type = 1; + p->header.length = sizeof(struct smbios_type_1); + p->header.handle = 0x100; + + load_str_field_with_default(1, manufacturer_str, BUILD_APPNAME); + load_str_field_with_default(1, product_name_str, BUILD_APPNAME); + load_str_field_or_skip(1, version_str); + load_str_field_or_skip(1, serial_number_str); + + if (!get_field(1, offsetof(struct smbios_type_1, uuid), &p->uuid)) + memset(p->uuid, 0, 16); + + set_field_with_default(1, wake_up_type, 0x06); /* power switch */ + + load_str_field_or_skip(1, sku_number_str); + load_str_field_or_skip(1, family_str); + + *end = 0; + end++; + if (!str_index) { + *end = 0; + end++; + } + + return end; +} + +/* Type 3 -- System Enclosure */ +static void * +smbios_init_type_3(void *start) +{ + struct smbios_type_3 *p = (struct smbios_type_3 *)start; + char *end = (char *)start + sizeof(struct smbios_type_3); + size_t size; + int str_index = 0; + + p->header.type = 3; + p->header.length = sizeof(struct smbios_type_3); + p->header.handle = 0x300; + + load_str_field_with_default(3, manufacturer_str, BUILD_APPNAME); + set_field_with_default(3, type, 0x01); /* other */ + + load_str_field_or_skip(3, version_str); + load_str_field_or_skip(3, serial_number_str); + load_str_field_or_skip(3, asset_tag_number_str); + + set_field_with_default(3, boot_up_state, 0x03); /* safe */ + set_field_with_default(3, power_supply_state, 0x03); /* safe */ + set_field_with_default(3, thermal_state, 0x03); /* safe */ + set_field_with_default(3, security_status, 0x02); /* unknown */ + + set_field_with_default(3, oem_defined, 0); + set_field_with_default(3, height, 0); + set_field_with_default(3, number_of_power_cords, 0); + set_field_with_default(3, contained_element_count, 0); + + *end = 0; + end++; + if (!str_index) { + *end = 0; + end++; + } + + return end; +} + +/* Type 4 -- Processor Information */ +static void * +smbios_init_type_4(void *start, unsigned int cpu_number) +{ + struct smbios_type_4 *p = (struct smbios_type_4 *)start; + char *end = (char *)start + sizeof(struct smbios_type_4); + size_t size; + int str_index = 0; + char name[1024]; + + p->header.type = 4; + p->header.length = sizeof(struct smbios_type_4); + p->header.handle = 0x400 + cpu_number; + + size = get_field(4, offsetof(struct smbios_type_4, socket_designation_str), + name); + if (size) + snprintf(name + size - 1, sizeof(name) - size, "%2x", cpu_number); + else + snprintf(name, sizeof(name), "CPU%2x", cpu_number); + + memcpy(end, name, strlen(name) + 1); + end += strlen(name) + 1; + p->socket_designation_str = ++str_index; + + set_field_with_default(4, processor_type, 0x03); /* CPU */ + set_field_with_default(4, processor_family, 0x01); /* other */ + + load_str_field_with_default(4, processor_manufacturer_str, BUILD_APPNAME); + + if (!get_field(4, offsetof(struct smbios_type_4, processor_id) + , p->processor_id)) { + u32 cpuid_signature, ebx, ecx, cpuid_features; + cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features); + p->processor_id[0] = cpuid_signature; + p->processor_id[1] = cpuid_features; + } + + load_str_field_or_skip(4, processor_version_str); + set_field_with_default(4, voltage, 0); + set_field_with_default(4, external_clock, 0); + + set_field_with_default(4, max_speed, 2000); + set_field_with_default(4, current_speed, 2000); + + set_field_with_default(4, status, 0x41); /* socket populated, CPU enabled */ + set_field_with_default(4, processor_upgrade, 0x01); /* other */ + + /* cache information structure not provided */ + p->l1_cache_handle = 0xffff; + p->l2_cache_handle = 0xffff; + p->l3_cache_handle = 0xffff; + + *end = 0; + end++; + if (!str_index) { + *end = 0; + end++; + } + + return end; +} + +/* Type 16 -- Physical Memory Array */ +static void * +smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs) +{ + struct smbios_type_16 *p = (struct smbios_type_16*)start; + + p->header.type = 16; + p->header.length = sizeof(struct smbios_type_16); + p->header.handle = 0x1000; + + set_field_with_default(16, location, 0x01); /* other */ + set_field_with_default(16, use, 0x03); /* system memory */ + /* Multi-bit ECC to make Microsoft happy */ + set_field_with_default(16, error_correction, 0x06); + /* 0x80000000 = unknown, accept sizes < 2TB - TODO multiple arrays */ + p->maximum_capacity = memory_size_mb < 2 << 20 ? + memory_size_mb << 10 : 0x80000000; + p->memory_error_information_handle = 0xfffe; /* none provided */ + p->number_of_memory_devices = nr_mem_devs; + + start += sizeof(struct smbios_type_16); + *((u16 *)start) = 0; + + return start + 2; +} + +/* Type 17 -- Memory Device */ +static void * +smbios_init_type_17(void *start, u32 size_mb, int instance) +{ + struct smbios_type_17 *p = (struct smbios_type_17 *)start; + char *end = (char *)start + sizeof(struct smbios_type_17); + size_t size; + int str_index = 0; + char name[1024]; + + p->header.type = 17; + p->header.length = sizeof(struct smbios_type_17); + p->header.handle = 0x1100 + instance; + + p->physical_memory_array_handle = 0x1000; + set_field_with_default(17, total_width, 64); + set_field_with_default(17, data_width, 64); +/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */ + p->size = size_mb; + set_field_with_default(17, form_factor, 0x09); /* DIMM */ + p->device_set = 0; + + size = get_field(17, offsetof(struct smbios_type_17, device_locator_str), + name); + if (size) + snprintf(name + size - 1, sizeof(name) - size, "%d", instance); + else + snprintf(name, sizeof(name), "DIMM %d", instance); + + memcpy(end, name, strlen(name) + 1); + end += strlen(name) + 1; + p->device_locator_str = ++str_index; + + load_str_field_or_skip(17, bank_locator_str); + set_field_with_default(17, memory_type, 0x07); /* RAM */ + set_field_with_default(17, type_detail, 0); + + *end = 0; + end++; + if (!str_index) { + *end = 0; + end++; + } + + return end; +} + +/* Type 19 -- Memory Array Mapped Address */ +static void * +smbios_init_type_19(void *start, u32 start_mb, u32 size_mb, int instance) +{ + struct smbios_type_19 *p = (struct smbios_type_19 *)start; + + p->header.type = 19; + p->header.length = sizeof(struct smbios_type_19); + p->header.handle = 0x1300 + instance; + + p->starting_address = start_mb << 10; + p->ending_address = p->starting_address + (size_mb << 10) - 1; + p->memory_array_handle = 0x1000; + p->partition_width = 1; + + start += sizeof(struct smbios_type_19); + *((u16 *)start) = 0; + + return start + 2; +} + +/* Type 20 -- Memory Device Mapped Address */ +static void * +smbios_init_type_20(void *start, u32 start_mb, u32 size_mb, int instance, + int dev_handle, int array_handle) +{ + struct smbios_type_20 *p = (struct smbios_type_20 *)start; + + p->header.type = 20; + p->header.length = sizeof(struct smbios_type_20); + p->header.handle = 0x1400 + instance; + + p->starting_address = start_mb << 10; + p->ending_address = p->starting_address + (size_mb << 10) - 1; + p->memory_device_handle = 0x1100 + dev_handle; + p->memory_array_mapped_address_handle = 0x1300 + array_handle; + p->partition_row_position = 1; + p->interleave_position = 0; + p->interleaved_data_depth = 0; + + start += sizeof(struct smbios_type_20); + + *((u16 *)start) = 0; + return start+2; +} + +/* Type 32 -- System Boot Information */ +static void * +smbios_init_type_32(void *start) +{ + struct smbios_type_32 *p = (struct smbios_type_32 *)start; + + p->header.type = 32; + p->header.length = sizeof(struct smbios_type_32); + p->header.handle = 0x2000; + memset(p->reserved, 0, 6); + set_field_with_default(32, boot_status, 0); /* no errors detected */ + + start += sizeof(struct smbios_type_32); + *((u16 *)start) = 0; + + return start+2; +} + +/* Type 127 -- End of Table */ +static void * +smbios_init_type_127(void *start) +{ + struct smbios_type_127 *p = (struct smbios_type_127 *)start; + + p->header.type = 127; + p->header.length = sizeof(struct smbios_type_127); + p->header.handle = 0x7f00; + + start += sizeof(struct smbios_type_127); + *((u16 *)start) = 0; + + return start + 2; +} + +#define TEMPSMBIOSSIZE (32 * 1024) + +void +smbios_setup(void) +{ + if (! CONFIG_SMBIOS) + return; + + dprintf(3, "init SMBIOS tables\n"); + + char *start = malloc_tmphigh(TEMPSMBIOSSIZE); + if (! start) { + warn_noalloc(); + return; + } + + u32 nr_structs = 0, max_struct_size = 0; + char *q, *p = start; + char *end = start + TEMPSMBIOSSIZE - sizeof(struct smbios_type_127); + +#define add_struct(type, args...) \ + do { \ + if (!get_external(type, &p, &nr_structs, &max_struct_size, end)) { \ + q = smbios_init_type_##type(args); \ + nr_structs++; \ + if ((q - p) > max_struct_size) \ + max_struct_size = q - p; \ + p = q; \ + } \ + } while (0) + + add_struct(0, p); + add_struct(1, p); + add_struct(3, p); + + int cpu_num; + for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++) + add_struct(4, p, cpu_num); + + int ram_mb = (RamSize + RamSizeOver4G) >> 20; + int nr_mem_devs = (ram_mb + 0x3fff) >> 14; + add_struct(16, p, ram_mb, nr_mem_devs); + + int i, j; + for (i = 0; i < nr_mem_devs; i++) { + u32 dev_mb = ((i == (nr_mem_devs - 1)) + ? (((ram_mb - 1) & 0x3fff) + 1) + : 16384); + add_struct(17, p, dev_mb, i); + } + + add_struct(19, p, 0, RamSize >> 20, 0); + if (RamSizeOver4G) + add_struct(19, p, 4096, RamSizeOver4G >> 20, 1); + + add_struct(20, p, 0, RamSize >> 20, 0, 0, 0); + if (RamSizeOver4G) { + u32 start_mb = 4096; + for (j = 1, i = 0; i < nr_mem_devs; i++, j++) { + u32 dev_mb = ((i == (nr_mem_devs - 1)) + ? (((ram_mb - 1) & 0x3fff) + 1) + : 16384); + if (i == 0) + dev_mb -= RamSize >> 20; + + add_struct(20, p, start_mb, dev_mb, j, i, 1); + start_mb += dev_mb; + } + } + + add_struct(32, p); + /* Add any remaining provided entries before the end marker */ + for (i = 0; i < 256; i++) + get_external(i, &p, &nr_structs, &max_struct_size, end); + add_struct(127, p); + +#undef add_struct + + smbios_entry_point_setup(max_struct_size, p - start, start, nr_structs); + free(start); +} + +void +display_uuid(void) +{ + u32 addr, end; + u8 *uuid; + u8 empty_uuid[16] = { 0 }; + + if (SMBiosAddr == NULL) + return; + + addr = SMBiosAddr->structure_table_address; + end = addr + SMBiosAddr->structure_table_length; + + /* the following takes care of any initial wraparound too */ + while (addr < end) { + const struct smbios_structure_header *hdr; + + /* partial structure header */ + if (end - addr < sizeof(struct smbios_structure_header)) + return; + + hdr = (struct smbios_structure_header *)addr; + + /* partial structure */ + if (end - addr < hdr->length) + return; + + /* any Type 1 structure version will do that has the UUID */ + if (hdr->type == 1 && + hdr->length >= offsetof(struct smbios_type_1, uuid) + 16) + break; + + /* done with formatted area, skip string-set */ + addr += hdr->length; + + while (end - addr >= 2 && + (*(u8 *)addr != '\0' || + *(u8 *)(addr+1) != '\0')) + ++addr; + + /* structure terminator not found */ + if (end - addr < 2) + return; + + addr += 2; + } + + /* parsing finished or skipped entirely, UUID not found */ + if (addr >= end) + return; + + uuid = (u8 *)(addr + offsetof(struct smbios_type_1, uuid)); + if (memcmp(uuid, empty_uuid, sizeof empty_uuid) == 0) + return; + + printf("Machine UUID" + " %02x%02x%02x%02x" + "-%02x%02x" + "-%02x%02x" + "-%02x%02x" + "-%02x%02x%02x%02x%02x%02x\n" + , uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3] + , uuid[ 4], uuid[ 5] + , uuid[ 6], uuid[ 7] + , uuid[ 8], uuid[ 9] + , uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); +} diff -Nru seabios-1.7.1/src/fw/smm.c seabios-1.7.4/src/fw/smm.c --- seabios-1.7.1/src/fw/smm.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/smm.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,199 @@ +// System Management Mode support (on emulators) +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "dev-q35.h" +#include "hw/pci.h" // pci_config_writel +#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL +#include "hw/pci_regs.h" // PCI_DEVICE_ID +#include "output.h" // dprintf +#include "paravirt.h" // PORT_SMI_STATUS +#include "string.h" // memcpy +#include "util.h" // smm_setup +#include "x86.h" // wbinvd + +extern u8 smm_relocation_start, smm_relocation_end; +ASM32FLAT( + ".global smm_relocation_start, smm_relocation_end\n" + " .code16gcc\n" + + /* code to relocate SMBASE to 0xa0000 */ + "smm_relocation_start:\n" + " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7efc, %ebx\n" + " addr32 movb (%ebx), %al\n" /* revision ID to see if x86_64 or x86 */ + " cmpb $0x64, %al\n" + " je 1f\n" + " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7ef8, %ebx\n" + " jmp 2f\n" + "1:\n" + " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7f00, %ebx\n" + "2:\n" + " movl $" __stringify(BUILD_SMM_ADDR) " - 0x8000, %eax\n" + " addr32 movl %eax, (%ebx)\n" + /* indicate to the BIOS that the SMM code was executed */ + " movb $0x00, %al\n" + " movw $" __stringify(PORT_SMI_STATUS) ", %dx\n" + " outb %al, %dx\n" + " rsm\n" + "smm_relocation_end:\n" + " .code32\n" + ); + +extern u8 smm_code_start, smm_code_end; +ASM32FLAT( + /* minimal SMM code to enable or disable ACPI */ + ".global smm_code_start, smm_code_end\n" + " .code16gcc\n" + "smm_code_start:\n" + " movw $" __stringify(PORT_SMI_CMD) ", %dx\n" + " inb %dx, %al\n" + " cmpb $0xf0, %al\n" + " jne 1f\n" + + /* ACPI disable */ + " movw $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */ + " inw %dx, %ax\n" + " andw $~1, %ax\n" + " outw %ax, %dx\n" + + " jmp 2f\n" + + "1:\n" + " cmpb $0xf1, %al\n" + " jne 2f\n" + + /* ACPI enable */ + " movw $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */ + " inw %dx, %ax\n" + " orw $1, %ax\n" + " outw %ax, %dx\n" + + "2:\n" + " rsm\n" + "smm_code_end:\n" + " .code32\n" + ); + +static void +smm_save_and_copy(void) +{ + /* save original memory content */ + memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE); + + /* copy the SMM relocation code */ + memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start, + &smm_relocation_end - &smm_relocation_start); +} + +static void +smm_relocate_and_restore(void) +{ + /* init APM status port */ + outb(0x01, PORT_SMI_STATUS); + + /* raise an SMI interrupt */ + outb(0x00, PORT_SMI_CMD); + + /* wait until SMM code executed */ + while (inb(PORT_SMI_STATUS) != 0x00) + ; + + /* restore original memory content */ + memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE); + + /* copy the SMM code */ + memcpy((void *)BUILD_SMM_ADDR, &smm_code_start + , &smm_code_end - &smm_code_start); + wbinvd(); +} + +#define I440FX_SMRAM 0x72 +#define PIIX_DEVACTB 0x58 +#define PIIX_APMC_EN (1 << 25) + +// This code is hardcoded for PIIX4 Power Management device. +static void piix4_apmc_smm_setup(int isabdf, int i440_bdf) +{ + /* check if SMM init is already done */ + u32 value = pci_config_readl(isabdf, PIIX_DEVACTB); + if (value & PIIX_APMC_EN) + return; + + /* enable the SMM memory window */ + pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x48); + + smm_save_and_copy(); + + /* enable SMI generation when writing to the APMC register */ + pci_config_writel(isabdf, PIIX_DEVACTB, value | PIIX_APMC_EN); + + smm_relocate_and_restore(); + + /* close the SMM memory window and enable normal SMM */ + pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x08); +} + +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */ +void ich9_lpc_apmc_smm_setup(int isabdf, int mch_bdf) +{ + /* check if SMM init is already done */ + u32 value = inl(PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN); + if (value & ICH9_PMIO_SMI_EN_APMC_EN) + return; + + /* enable the SMM memory window */ + pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x48); + + smm_save_and_copy(); + + /* enable SMI generation when writing to the APMC register */ + outl(value | ICH9_PMIO_SMI_EN_APMC_EN, + PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN); + + smm_relocate_and_restore(); + + /* close the SMM memory window and enable normal SMM */ + pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x08); +} + +static int SMMISADeviceBDF = -1, SMMPMDeviceBDF = -1; + +void +smm_device_setup(void) +{ + if (!CONFIG_USE_SMM) + return; + + struct pci_device *isapci, *pmpci; + isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3); + pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441); + if (isapci && pmpci) { + SMMISADeviceBDF = isapci->bdf; + SMMPMDeviceBDF = pmpci->bdf; + return; + } + isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC); + pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH); + if (isapci && pmpci) { + SMMISADeviceBDF = isapci->bdf; + SMMPMDeviceBDF = pmpci->bdf; + } +} + +void +smm_setup(void) +{ + if (!CONFIG_USE_SMM || SMMISADeviceBDF < 0) + return; + + dprintf(3, "init smm\n"); + u16 device = pci_config_readw(SMMISADeviceBDF, PCI_DEVICE_ID); + if (device == PCI_DEVICE_ID_INTEL_82371AB_3) + piix4_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF); + else + ich9_lpc_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF); +} diff -Nru seabios-1.7.1/src/fw/smp.c seabios-1.7.4/src/fw/smp.c --- seabios-1.7.1/src/fw/smp.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/smp.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,148 @@ +// CPU count detection +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2006 Fabrice Bellard +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "hw/rtc.h" // CMOS_BIOS_SMP_COUNT +#include "output.h" // dprintf +#include "romfile.h" // romfile_loadint +#include "stacks.h" // yield +#include "util.h" // smp_setup +#include "x86.h" // wrmsr + +#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300) +#define APIC_SVR ((u8*)BUILD_APIC_ADDR + 0x0F0) +#define APIC_LINT0 ((u8*)BUILD_APIC_ADDR + 0x350) +#define APIC_LINT1 ((u8*)BUILD_APIC_ADDR + 0x360) + +#define APIC_ENABLED 0x0100 + +struct { u32 ecx, eax, edx; } smp_mtrr[32] VARFSEG; +u32 smp_mtrr_count VARFSEG; + +void +wrmsr_smp(u32 index, u64 val) +{ + wrmsr(index, val); + if (smp_mtrr_count >= ARRAY_SIZE(smp_mtrr)) { + warn_noalloc(); + return; + } + smp_mtrr[smp_mtrr_count].ecx = index; + smp_mtrr[smp_mtrr_count].eax = val; + smp_mtrr[smp_mtrr_count].edx = val >> 32; + smp_mtrr_count++; +} + +u32 CountCPUs VARFSEG; +u32 MaxCountCPUs; +// 256 bits for the found APIC IDs +u32 FoundAPICIDs[256/32] VARFSEG; +extern void smp_ap_boot_code(void); +ASM16( + " .global smp_ap_boot_code\n" + "smp_ap_boot_code:\n" + + // Setup data segment + " movw $" __stringify(SEG_BIOS) ", %ax\n" + " movw %ax, %ds\n" + + // MTRR setup + " movl $smp_mtrr, %esi\n" + " movl smp_mtrr_count, %ebx\n" + "1:testl %ebx, %ebx\n" + " jz 2f\n" + " movl 0(%esi), %ecx\n" + " movl 4(%esi), %eax\n" + " movl 8(%esi), %edx\n" + " wrmsr\n" + " addl $12, %esi\n" + " decl %ebx\n" + " jmp 1b\n" + "2:\n" + + // get apic ID on EBX, set bit on FoundAPICIDs + " movl $1, %eax\n" + " cpuid\n" + " shrl $24, %ebx\n" + " lock btsl %ebx, FoundAPICIDs\n" + + // Increment the cpu counter + " lock incl CountCPUs\n" + + // Halt the processor. + "1:hlt\n" + " jmp 1b\n" + ); + +int apic_id_is_present(u8 apic_id) +{ + return !!(FoundAPICIDs[apic_id/32] & (1ul << (apic_id % 32))); +} + +// find and initialize the CPUs by launching a SIPI to them +void +smp_setup(void) +{ + if (!CONFIG_QEMU) + return; + + ASSERT32FLAT(); + u32 eax, ebx, ecx, cpuid_features; + cpuid(1, &eax, &ebx, &ecx, &cpuid_features); + if (eax < 1 || !(cpuid_features & CPUID_APIC)) { + // No apic - only the main cpu is present. + dprintf(1, "No apic - only the main cpu is present.\n"); + CountCPUs= 1; + MaxCountCPUs = 1; + return; + } + + // mark the BSP initial APIC ID as found, too: + u8 apic_id = ebx>>24; + FoundAPICIDs[apic_id/32] |= (1 << (apic_id % 32)); + + // Init the counter. + writel(&CountCPUs, 1); + + // Setup jump trampoline to counter code. + u64 old = *(u64*)BUILD_AP_BOOT_ADDR; + // ljmpw $SEG_BIOS, $(smp_ap_boot_code - BUILD_BIOS_ADDR) + u64 new = (0xea | ((u64)SEG_BIOS<<24) + | (((u32)smp_ap_boot_code - BUILD_BIOS_ADDR) << 8)); + *(u64*)BUILD_AP_BOOT_ADDR = new; + + // enable local APIC + u32 val = readl(APIC_SVR); + writel(APIC_SVR, val | APIC_ENABLED); + + /* Set LINT0 as Ext_INT, level triggered */ + writel(APIC_LINT0, 0x8700); + + /* Set LINT1 as NMI, level triggered */ + writel(APIC_LINT1, 0x8400); + + // broadcast SIPI + barrier(); + writel(APIC_ICR_LOW, 0x000C4500); + u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12; + writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector); + + // Wait for other CPUs to process the SIPI. + u8 cmos_smp_count = rtc_read(CMOS_BIOS_SMP_COUNT); + while (cmos_smp_count + 1 != readl(&CountCPUs)) + yield(); + + // Restore memory. + *(u64*)BUILD_AP_BOOT_ADDR = old; + + MaxCountCPUs = romfile_loadint("etc/max-cpus", 0); + if (!MaxCountCPUs || MaxCountCPUs < CountCPUs) + MaxCountCPUs = CountCPUs; + + dprintf(1, "Found %d cpu(s) max supported %d cpu(s)\n", readl(&CountCPUs), + MaxCountCPUs); +} diff -Nru seabios-1.7.1/src/fw/ssdt-misc.dsl seabios-1.7.4/src/fw/ssdt-misc.dsl --- seabios-1.7.1/src/fw/ssdt-misc.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/ssdt-misc.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,104 @@ +ACPI_EXTRACT_ALL_CODE ssdp_misc_aml + +DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1) +{ + +/**************************************************************** + * PCI memory ranges + ****************************************************************/ + + Scope(\) { + ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start + Name(P0S, 0x12345678) + ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end + Name(P0E, 0x12345678) + ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid + Name(P1V, 0x12) + ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start + Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end + Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length + Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + } + + +/**************************************************************** + * Suspend + ****************************************************************/ + + Scope(\) { + /* + * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes: + * must match piix4 emulation. + */ + + ACPI_EXTRACT_NAME_STRING acpi_s3_name + Name(_S3, Package(0x04) { + One, /* PM1a_CNT.SLP_TYP */ + One, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + ACPI_EXTRACT_NAME_STRING acpi_s4_name + ACPI_EXTRACT_PKG_START acpi_s4_pkg + Name(_S4, Package(0x04) { + 0x2, /* PM1a_CNT.SLP_TYP */ + 0x2, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + Name(_S5, Package(0x04) { + Zero, /* PM1a_CNT.SLP_TYP */ + Zero, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + } + + External(\_SB.PCI0, DeviceObj) + External(\_SB.PCI0.ISA, DeviceObj) + + Scope(\_SB.PCI0.ISA) { + Device(PEVT) { + Name(_HID, "QEMU0001") + /* PEST will be patched to be Zero if no such device */ + ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest + Name(PEST, 0xFFFF) + OperationRegion(PEOR, SystemIO, PEST, 0x01) + Field(PEOR, ByteAcc, NoLock, Preserve) { + PEPT, 8, + } + + Method(_STA, 0, NotSerialized) { + Store(PEST, Local0) + If (LEqual(Local0, Zero)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + + Method(RDPT, 0, NotSerialized) { + Store(PEPT, Local0) + Return (Local0) + } + + Method(WRPT, 1, NotSerialized) { + Store(Arg0, PEPT) + } + + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO) + }) + + CreateWordField(_CRS, IO._MIN, IOMN) + CreateWordField(_CRS, IO._MAX, IOMX) + + Method(_INI, 0, NotSerialized) { + Store(PEST, IOMN) + Store(PEST, IOMX) + } + } + } +} diff -Nru seabios-1.7.1/src/fw/ssdt-pcihp.dsl seabios-1.7.4/src/fw/ssdt-pcihp.dsl --- seabios-1.7.1/src/fw/ssdt-pcihp.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/ssdt-pcihp.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,36 @@ +ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml + +DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1) +{ + +/**************************************************************** + * PCI hotplug + ****************************************************************/ + + /* Objects supplied by DSDT */ + External(\_SB.PCI0, DeviceObj) + External(\_SB.PCI0.PCEJ, MethodObj) + + Scope(\_SB.PCI0) { + + /* Bulk generated PCI hotplug devices */ + ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start + ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end + ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name + + // Method _EJ0 can be patched by BIOS to EJ0_ + // at runtime, if the slot is detected to not support hotplug. + // Extract the offset of the address dword and the + // _EJ0 name to allow this patching. + Device(SAA) { + ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id + Name(_SUN, 0xAA) + ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr + Name(_ADR, 0xAA0000) + ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0 + Method(_EJ0, 1) { + Return (PCEJ(_SUN)) + } + } + } +} diff -Nru seabios-1.7.1/src/fw/ssdt-proc.dsl seabios-1.7.4/src/fw/ssdt-proc.dsl --- seabios-1.7.1/src/fw/ssdt-proc.dsl 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/ssdt-proc.dsl 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,48 @@ +/* This file is the basis for the ssdt table generated in src/acpi.c. + * It defines the contents of the per-cpu Processor() object. At + * runtime, a dynamically generated SSDT will contain one copy of this + * AML snippet for every possible cpu in the system. The objects will + * be placed in the \_SB_ namespace. + * + * In addition to the aml code generated from this file, the + * src/acpi.c file creates a NTFY method with an entry for each cpu: + * Method(NTFY, 2) { + * If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) } + * If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) } + * ... + * } + * and a CPON array with the list of active and inactive cpus: + * Name(CPON, Package() { One, One, ..., Zero, Zero, ... }) + */ + +ACPI_EXTRACT_ALL_CODE ssdp_proc_aml + +DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1) +{ + ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start + ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end + ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name + Processor(CPAA, 0xAA, 0x0000b010, 0x06) { + ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id + Name(ID, 0xAA) +/* + * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update + * CPAA and 0xAA with the appropriate CPU id (see + * SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without + * also updating the C code. + */ + Name(_HID, "ACPI0007") + External(CPMA, MethodObj) + External(CPST, MethodObj) + External(CPEJ, MethodObj) + Method(_MAT, 0) { + Return (CPMA(ID)) + } + Method(_STA, 0) { + Return (CPST(ID)) + } + Method(_EJ0, 1, NotSerialized) { + CPEJ(ID, Arg0) + } + } +} diff -Nru seabios-1.7.1/src/fw/xen.c seabios-1.7.4/src/fw/xen.c --- seabios-1.7.1/src/fw/xen.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/xen.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,147 @@ +// Xen HVM support +// +// Copyright (C) 2011 Citrix Systems. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" +#include "hw/serialio.h" // DebugOutputPort +#include "malloc.h" // memalign_high +#include "memmap.h" // add_e820 +#include "output.h" // dprintf +#include "paravirt.h" // PlatformRunningOn +#include "string.h" // memcpy +#include "util.h" // copy_acpi_rsdp +#include "x86.h" // cpuid +#include "xen.h" + +#define INFO_PHYSICAL_ADDRESS 0x00001000 + +u32 xen_cpuid_base = 0; +unsigned long xen_hypercall_page = 0; + +struct xen_seabios_info { + char signature[14]; /* XenHVMSeaBIOS\0 */ + u8 length; /* Length of this struct */ + u8 checksum; /* Set such that the sum over bytes 0..length == 0 */ + /* + * Physical address of an array of tables_nr elements. + * + * Each element is a 32 bit value contianing the physical address + * of a BIOS table. + */ + u32 tables; + u32 tables_nr; + /* + * Physical address of the e820 table, contains e820_nr entries. + */ + u32 e820; + u32 e820_nr; +} PACKED; + +static void validate_info(struct xen_seabios_info *t) +{ + if ( memcmp(t->signature, "XenHVMSeaBIOS", 14) ) + panic("Bad Xen info signature\n"); + + if ( t->length < sizeof(struct xen_seabios_info) ) + panic("Bad Xen info length\n"); + + if (checksum(t, t->length) != 0) + panic("Bad Xen info checksum\n"); +} + +void xen_preinit(void) +{ + u32 base, eax, ebx, ecx, edx; + char signature[13]; + + if (!CONFIG_XEN) + return; + + for (base = 0x40000000; base < 0x40010000; base += 0x100) { + cpuid(base, &eax, &ebx, &ecx, &edx); + memcpy(signature + 0, &ebx, 4); + memcpy(signature + 4, &ecx, 4); + memcpy(signature + 8, &edx, 4); + signature[12] = 0; + + dprintf(9, "Found hypervisor signature \"%s\" at %x\n", + signature, base); + if (strcmp(signature, "XenVMMXenVMM") == 0) { + /* Set debug_io_port first, so the following messages work. */ + DebugOutputPort = 0xe9; + dprintf(1, "SeaBIOS (version %s)\n\n", VERSION); + dprintf(1, "Found Xen hypervisor signature at %x\n", base); + if ((eax - base) < 2) + panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n", + eax, base); + xen_cpuid_base = base; + break; + } + } + if (!xen_cpuid_base) { + dprintf(1, "No Xen hypervisor found.\n"); + return; + } + PlatformRunningOn = PF_QEMU|PF_XEN; +} + +static int hypercall_xen_version( int cmd, void *arg) +{ + return _hypercall2(int, xen_version, cmd, arg); +} + +/* Fill in hypercall transfer pages. */ +void xen_hypercall_setup(void) +{ + u32 eax, ebx, ecx, edx; + xen_extraversion_t extraversion; + unsigned long i; + + if (!runningOnXen()) + return; + + cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx); + + xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE); + if (!xen_hypercall_page) + panic("unable to allocate Xen hypercall page\n"); + + dprintf(1, "Allocated Xen hypercall page at %lx\n", xen_hypercall_page); + for ( i = 0; i < eax; i++ ) + wrmsr(ebx, xen_hypercall_page + (i << 12) + i); + + /* Print version information. */ + cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx); + hypercall_xen_version(XENVER_extraversion, extraversion); + dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion); +} + +void xen_biostable_setup(void) +{ + struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS; + void **tables = (void*)info->tables; + int i; + + dprintf(1, "xen: copy BIOS tables...\n"); + for (i=0; itables_nr; i++) + copy_table(tables[i]); + + find_acpi_features(); +} + +void xen_ramsize_preinit(void) +{ + int i; + struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS; + struct e820entry *e820 = (struct e820entry *)info->e820; + validate_info(info); + + dprintf(1, "xen: copy e820...\n"); + + for (i = 0; i < info->e820_nr; i++) { + struct e820entry *e = &e820[i]; + add_e820(e->start, e->size, e->type); + } +} diff -Nru seabios-1.7.1/src/fw/xen.h seabios-1.7.4/src/fw/xen.h --- seabios-1.7.1/src/fw/xen.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/fw/xen.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,125 @@ +#ifndef __XEN_H +#define __XEN_H + +void xen_preinit(void); +void xen_ramsize_preinit(void); +void xen_hypercall_setup(void); +void xen_biostable_setup(void); + +extern unsigned long xen_hypercall_page; + +#define _hypercall0(type, name) \ +({ \ + unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ + long __res; \ + asm volatile ( \ + "call *%%eax" \ + : "=a" (__res) \ + : "0" (__hentry) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall1(type, name, a1) \ +({ \ + unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ + long __res, __ign1; \ + asm volatile ( \ + "call *%%eax" \ + : "=a" (__res), "=b" (__ign1) \ + : "0" (__hentry), "1" ((long)(a1)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall2(type, name, a1, a2) \ +({ \ + unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ + long __res, __ign1, __ign2; \ + asm volatile ( \ + "call *%%eax" \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ + : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall3(type, name, a1, a2, a3) \ +({ \ + unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ + long __res, __ign1, __ign2, __ign3; \ + asm volatile ( \ + "call *%%eax" \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ + "=d" (__ign3) \ + : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \ + "3" ((long)(a3)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall4(type, name, a1, a2, a3, a4) \ +({ \ + unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ + long __res, __ign1, __ign2, __ign3, __ign4; \ + asm volatile ( \ + "call *%%eax" \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ + "=d" (__ign3), "=S" (__ign4) \ + : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \ + "3" ((long)(a3)), "4" ((long)(a4)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ +({ \ + unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ + long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \ + asm volatile ( \ + "call *%%eax" \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ + "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \ + : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \ + "3" ((long)(a3)), "4" ((long)(a4)), \ + "5" ((long)(a5)) \ + : "memory" ); \ + (type)__res; \ +}) + +/****************************************************************************** + * + * The following interface definitions are taken from Xen and have the + * following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* xen.h */ + +#define __HYPERVISOR_xen_version 17 + +/* version.h */ + +/* arg == xen_extraversion_t. */ +#define XENVER_extraversion 1 +typedef char xen_extraversion_t[16]; +#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t)) + +#endif diff -Nru seabios-1.7.1/src/hw/ahci.c seabios-1.7.4/src/hw/ahci.c --- seabios-1.7.1/src/hw/ahci.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/ahci.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,640 @@ +// Low level AHCI disk access +// +// Copyright (C) 2010 Gerd Hoffmann +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "ahci.h" // CDB_CMD_READ_10 +#include "ata.h" // ATA_CB_STAT +#include "biosvar.h" // GET_GLOBAL +#include "blockcmd.h" // CDB_CMD_READ_10 +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER +#include "pci_regs.h" // PCI_INTERRUPT_LINE +#include "stacks.h" // yield +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // timer_calc +#include "x86.h" // inb + +#define AHCI_REQUEST_TIMEOUT 32000 // 32 seconds max for IDE ops +#define AHCI_RESET_TIMEOUT 500 // 500 miliseconds +#define AHCI_LINK_TIMEOUT 10 // 10 miliseconds + +// prepare sata command fis +static void sata_prep_simple(struct sata_cmd_fis *fis, u8 command) +{ + memset_fl(fis, 0, sizeof(*fis)); + fis->command = command; +} + +static void sata_prep_readwrite(struct sata_cmd_fis *fis, + struct disk_op_s *op, int iswrite) +{ + u64 lba = op->lba; + u8 command; + + memset_fl(fis, 0, sizeof(*fis)); + + if (op->count >= (1<<8) || lba + op->count >= (1<<28)) { + fis->sector_count2 = op->count >> 8; + fis->lba_low2 = lba >> 24; + fis->lba_mid2 = lba >> 32; + fis->lba_high2 = lba >> 40; + lba &= 0xffffff; + command = (iswrite ? ATA_CMD_WRITE_DMA_EXT + : ATA_CMD_READ_DMA_EXT); + } else { + command = (iswrite ? ATA_CMD_WRITE_DMA + : ATA_CMD_READ_DMA); + } + fis->feature = 1; /* dma */ + fis->command = command; + fis->sector_count = op->count; + fis->lba_low = lba; + fis->lba_mid = lba >> 8; + fis->lba_high = lba >> 16; + fis->device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA; +} + +static void sata_prep_atapi(struct sata_cmd_fis *fis, u16 blocksize) +{ + memset_fl(fis, 0, sizeof(*fis)); + fis->command = ATA_CMD_PACKET; + fis->feature = 1; /* dma */ + fis->lba_mid = blocksize; + fis->lba_high = blocksize >> 8; +} + +// ahci register access helpers +static u32 ahci_ctrl_readl(struct ahci_ctrl_s *ctrl, u32 reg) +{ + u32 addr = ctrl->iobase + reg; + return readl((void*)addr); +} + +static void ahci_ctrl_writel(struct ahci_ctrl_s *ctrl, u32 reg, u32 val) +{ + u32 addr = ctrl->iobase + reg; + writel((void*)addr, val); +} + +static u32 ahci_port_to_ctrl(u32 pnr, u32 port_reg) +{ + u32 ctrl_reg = 0x100; + ctrl_reg += pnr * 0x80; + ctrl_reg += port_reg; + return ctrl_reg; +} + +static u32 ahci_port_readl(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg) +{ + u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg); + return ahci_ctrl_readl(ctrl, ctrl_reg); +} + +static void ahci_port_writel(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg, u32 val) +{ + u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg); + ahci_ctrl_writel(ctrl, ctrl_reg, val); +} + +// submit ahci command + wait for result +static int ahci_command(struct ahci_port_s *port_gf, int iswrite, int isatapi, + void *buffer, u32 bsize) +{ + u32 val, status, success, flags, intbits, error; + struct ahci_ctrl_s *ctrl = port_gf->ctrl; + struct ahci_cmd_s *cmd = port_gf->cmd; + struct ahci_fis_s *fis = port_gf->fis; + struct ahci_list_s *list = port_gf->list; + u32 pnr = port_gf->pnr; + + cmd->fis.reg = 0x27; + cmd->fis.pmp_type = 1 << 7; /* cmd fis */ + cmd->prdt[0].base = (u32)buffer; + cmd->prdt[0].baseu = 0; + cmd->prdt[0].flags = bsize-1; + + flags = ((1 << 16) | /* one prd entry */ + (iswrite ? (1 << 6) : 0) | + (isatapi ? (1 << 5) : 0) | + (5 << 0)); /* fis length (dwords) */ + list[0].flags = flags; + list[0].bytes = 0; + list[0].base = (u32)(cmd); + list[0].baseu = 0; + + dprintf(8, "AHCI/%d: send cmd ...\n", pnr); + intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); + if (intbits) + ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); + ahci_port_writel(ctrl, pnr, PORT_SCR_ACT, 1); + ahci_port_writel(ctrl, pnr, PORT_CMD_ISSUE, 1); + + u32 end = timer_calc(AHCI_REQUEST_TIMEOUT); + do { + for (;;) { + intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); + if (intbits) { + ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); + if (intbits & 0x02) { + status = GET_LOWFLAT(fis->psfis[2]); + error = GET_LOWFLAT(fis->psfis[3]); + break; + } + if (intbits & 0x01) { + status = GET_LOWFLAT(fis->rfis[2]); + error = GET_LOWFLAT(fis->rfis[3]); + break; + } + } + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } + dprintf(8, "AHCI/%d: ... intbits 0x%x, status 0x%x ...\n", + pnr, intbits, status); + } while (status & ATA_CB_STAT_BSY); + + success = (0x00 == (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | + ATA_CB_STAT_ERR)) && + ATA_CB_STAT_RDY == (status & (ATA_CB_STAT_RDY))); + if (success) { + dprintf(8, "AHCI/%d: ... finished, status 0x%x, OK\n", pnr, + status); + } else { + dprintf(2, "AHCI/%d: ... finished, status 0x%x, ERROR 0x%x\n", pnr, + status, error); + + // non-queued error recovery (AHCI 1.3 section 6.2.2.1) + // Clears PxCMD.ST to 0 to reset the PxCI register + val = ahci_port_readl(ctrl, pnr, PORT_CMD); + ahci_port_writel(ctrl, pnr, PORT_CMD, val & ~PORT_CMD_START); + + // waits for PxCMD.CR to clear to 0 + while (1) { + val = ahci_port_readl(ctrl, pnr, PORT_CMD); + if ((val & PORT_CMD_LIST_ON) == 0) + break; + yield(); + } + + // Clears any error bits in PxSERR to enable capturing new errors + val = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR); + ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, val); + + // Clears status bits in PxIS as appropriate + val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); + ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val); + + // If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to 1, issue + // a COMRESET to the device to put it in an idle state + val = ahci_port_readl(ctrl, pnr, PORT_TFDATA); + if (val & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ)) { + dprintf(2, "AHCI/%d: issue comreset\n", pnr); + val = ahci_port_readl(ctrl, pnr, PORT_SCR_CTL); + // set Device Detection Initialization (DET) to 1 for 1 ms for comreset + ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val | 1); + mdelay (1); + ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val); + } + + // Sets PxCMD.ST to 1 to enable issuing new commands + val = ahci_port_readl(ctrl, pnr, PORT_CMD); + ahci_port_writel(ctrl, pnr, PORT_CMD, val | PORT_CMD_START); + } + return success ? 0 : -1; +} + +#define CDROM_CDB_SIZE 12 + +int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + if (! CONFIG_AHCI) + return 0; + + struct ahci_port_s *port_gf = container_of( + op->drive_gf, struct ahci_port_s, drive); + struct ahci_cmd_s *cmd = port_gf->cmd; + u8 *atapi = cdbcmd; + int i, rc; + + sata_prep_atapi(&cmd->fis, blocksize); + for (i = 0; i < CDROM_CDB_SIZE; i++) { + cmd->atapi[i] = atapi[i]; + } + rc = ahci_command(port_gf, 0, 1, op->buf_fl, + op->count * blocksize); + if (rc < 0) + return DISK_RET_EBADTRACK; + return DISK_RET_SUCCESS; +} + +// read/write count blocks from a harddrive, op->buf_fl must be word aligned +static int +ahci_disk_readwrite_aligned(struct disk_op_s *op, int iswrite) +{ + struct ahci_port_s *port_gf = container_of( + op->drive_gf, struct ahci_port_s, drive); + struct ahci_cmd_s *cmd = port_gf->cmd; + int rc; + + sata_prep_readwrite(&cmd->fis, op, iswrite); + rc = ahci_command(port_gf, iswrite, 0, op->buf_fl, + op->count * DISK_SECTOR_SIZE); + dprintf(8, "ahci disk %s, lba %6x, count %3x, buf %p, rc %d\n", + iswrite ? "write" : "read", (u32)op->lba, op->count, op->buf_fl, rc); + if (rc < 0) + return DISK_RET_EBADTRACK; + return DISK_RET_SUCCESS; +} + +// read/write count blocks from a harddrive. +static int +ahci_disk_readwrite(struct disk_op_s *op, int iswrite) +{ + // if caller's buffer is word aligned, use it directly + if (((u32) op->buf_fl & 1) == 0) + return ahci_disk_readwrite_aligned(op, iswrite); + + // Use a word aligned buffer for AHCI I/O + int rc; + struct disk_op_s localop = *op; + u8 *alignedbuf_fl = bounce_buf_fl; + u8 *position = op->buf_fl; + + localop.buf_fl = alignedbuf_fl; + localop.count = 1; + + if (iswrite) { + u16 block; + for (block = 0; block < op->count; block++) { + memcpy_fl (alignedbuf_fl, position, DISK_SECTOR_SIZE); + rc = ahci_disk_readwrite_aligned (&localop, 1); + if (rc) + return rc; + position += DISK_SECTOR_SIZE; + localop.lba++; + } + } else { // read + u16 block; + for (block = 0; block < op->count; block++) { + rc = ahci_disk_readwrite_aligned (&localop, 0); + if (rc) + return rc; + memcpy_fl (position, alignedbuf_fl, DISK_SECTOR_SIZE); + position += DISK_SECTOR_SIZE; + localop.lba++; + } + } + return DISK_RET_SUCCESS; +} + +// command demuxer +int VISIBLE32FLAT +process_ahci_op(struct disk_op_s *op) +{ + if (!CONFIG_AHCI) + return 0; + switch (op->command) { + case CMD_READ: + return ahci_disk_readwrite(op, 0); + case CMD_WRITE: + return ahci_disk_readwrite(op, 1); + case CMD_FORMAT: + case CMD_RESET: + case CMD_ISREADY: + case CMD_VERIFY: + case CMD_SEEK: + return DISK_RET_SUCCESS; + default: + dprintf(1, "AHCI: unknown disk command %d\n", op->command); + op->count = 0; + return DISK_RET_EPARAM; + } +} + +static void +ahci_port_reset(struct ahci_ctrl_s *ctrl, u32 pnr) +{ + u32 val; + + /* disable FIS + CMD */ + u32 end = timer_calc(AHCI_RESET_TIMEOUT); + for (;;) { + val = ahci_port_readl(ctrl, pnr, PORT_CMD); + if (!(val & (PORT_CMD_FIS_RX | PORT_CMD_START | + PORT_CMD_FIS_ON | PORT_CMD_LIST_ON))) + break; + val &= ~(PORT_CMD_FIS_RX | PORT_CMD_START); + ahci_port_writel(ctrl, pnr, PORT_CMD, val); + if (timer_check(end)) { + warn_timeout(); + break; + } + yield(); + } + + /* disable + clear IRQs */ + ahci_port_writel(ctrl, pnr, PORT_IRQ_MASK, 0); + val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); + if (val) + ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val); +} + +static struct ahci_port_s* +ahci_port_alloc(struct ahci_ctrl_s *ctrl, u32 pnr) +{ + struct ahci_port_s *port = malloc_tmp(sizeof(*port)); + + if (!port) { + warn_noalloc(); + return NULL; + } + port->pnr = pnr; + port->ctrl = ctrl; + port->list = memalign_tmp(1024, 1024); + port->fis = memalign_tmp(256, 256); + port->cmd = memalign_tmp(256, 256); + if (port->list == NULL || port->fis == NULL || port->cmd == NULL) { + warn_noalloc(); + return NULL; + } + memset(port->list, 0, 1024); + memset(port->fis, 0, 256); + memset(port->cmd, 0, 256); + + ahci_port_writel(ctrl, pnr, PORT_LST_ADDR, (u32)port->list); + ahci_port_writel(ctrl, pnr, PORT_FIS_ADDR, (u32)port->fis); + return port; +} + +static void ahci_port_release(struct ahci_port_s *port) +{ + ahci_port_reset(port->ctrl, port->pnr); + free(port->list); + free(port->fis); + free(port->cmd); + free(port); +} + +static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port) +{ + struct ahci_port_s *tmp; + u32 cmd; + + tmp = malloc_fseg(sizeof(*port)); + if (!tmp) { + warn_noalloc(); + ahci_port_release(port); + return NULL; + } + *tmp = *port; + free(port); + port = tmp; + + ahci_port_reset(port->ctrl, port->pnr); + + free(port->list); + free(port->fis); + free(port->cmd); + port->list = memalign_high(1024, 1024); + port->fis = memalign_high(256, 256); + port->cmd = memalign_high(256, 256); + + ahci_port_writel(port->ctrl, port->pnr, PORT_LST_ADDR, (u32)port->list); + ahci_port_writel(port->ctrl, port->pnr, PORT_FIS_ADDR, (u32)port->fis); + + cmd = ahci_port_readl(port->ctrl, port->pnr, PORT_CMD); + cmd |= (PORT_CMD_FIS_RX|PORT_CMD_START); + ahci_port_writel(port->ctrl, port->pnr, PORT_CMD, cmd); + + return port; +} + +#define MAXMODEL 40 + +/* See ahci spec chapter 10.1 "Software Initialization of HBA" */ +static int ahci_port_setup(struct ahci_port_s *port) +{ + struct ahci_ctrl_s *ctrl = port->ctrl; + u32 pnr = port->pnr; + char model[MAXMODEL+1]; + u16 buffer[256]; + u32 cmd, stat, err, tf; + int rc; + + /* enable FIS recv */ + cmd = ahci_port_readl(ctrl, pnr, PORT_CMD); + cmd |= PORT_CMD_FIS_RX; + ahci_port_writel(ctrl, pnr, PORT_CMD, cmd); + + /* spin up */ + cmd |= PORT_CMD_SPIN_UP; + ahci_port_writel(ctrl, pnr, PORT_CMD, cmd); + u32 end = timer_calc(AHCI_LINK_TIMEOUT); + for (;;) { + stat = ahci_port_readl(ctrl, pnr, PORT_SCR_STAT); + if ((stat & 0x07) == 0x03) { + dprintf(2, "AHCI/%d: link up\n", port->pnr); + break; + } + if (timer_check(end)) { + dprintf(2, "AHCI/%d: link down\n", port->pnr); + return -1; + } + yield(); + } + + /* clear error status */ + err = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR); + if (err) + ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, err); + + /* wait for device becoming ready */ + end = timer_calc(AHCI_REQUEST_TIMEOUT); + for (;;) { + tf = ahci_port_readl(ctrl, pnr, PORT_TFDATA); + if (!(tf & (ATA_CB_STAT_BSY | + ATA_CB_STAT_DRQ))) + break; + if (timer_check(end)) { + warn_timeout(); + dprintf(1, "AHCI/%d: device not ready (tf 0x%x)\n", port->pnr, tf); + return -1; + } + yield(); + } + + /* start device */ + cmd |= PORT_CMD_START; + ahci_port_writel(ctrl, pnr, PORT_CMD, cmd); + + sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_PACKET_DEVICE); + rc = ahci_command(port, 0, 0, buffer, sizeof(buffer)); + if (rc == 0) { + port->atapi = 1; + } else { + port->atapi = 0; + sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_DEVICE); + rc = ahci_command(port, 0, 0, buffer, sizeof(buffer)); + if (rc < 0) + return -1; + } + + port->drive.cntl_id = pnr; + port->drive.removable = (buffer[0] & 0x80) ? 1 : 0; + + if (!port->atapi) { + // found disk (ata) + port->drive.type = DTYPE_AHCI; + port->drive.blksize = DISK_SECTOR_SIZE; + port->drive.pchs.cylinder = buffer[1]; + port->drive.pchs.head = buffer[3]; + port->drive.pchs.sector = buffer[6]; + + u64 sectors; + if (buffer[83] & (1 << 10)) // word 83 - lba48 support + sectors = *(u64*)&buffer[100]; // word 100-103 + else + sectors = *(u32*)&buffer[60]; // word 60 and word 61 + port->drive.sectors = sectors; + u64 adjsize = sectors >> 11; + char adjprefix = 'M'; + if (adjsize >= (1 << 16)) { + adjsize >>= 10; + adjprefix = 'G'; + } + port->desc = znprintf(MAXDESCSIZE + , "AHCI/%d: %s ATA-%d Hard-Disk (%u %ciBytes)" + , port->pnr + , ata_extract_model(model, MAXMODEL, buffer) + , ata_extract_version(buffer) + , (u32)adjsize, adjprefix); + port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0); + } else { + // found cdrom (atapi) + port->drive.type = DTYPE_AHCI_ATAPI; + port->drive.blksize = CDROM_SECTOR_SIZE; + port->drive.sectors = (u64)-1; + u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05; + if (!iscd) { + dprintf(1, "AHCI/%d: atapi device isn't a cdrom\n", port->pnr); + return -1; + } + port->desc = znprintf(MAXDESCSIZE + , "DVD/CD [AHCI/%d: %s ATAPI-%d DVD/CD]" + , port->pnr + , ata_extract_model(model, MAXMODEL, buffer) + , ata_extract_version(buffer)); + port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0); + } + return 0; +} + +// Detect any drives attached to a given controller. +static void +ahci_port_detect(void *data) +{ + struct ahci_port_s *port = data; + int rc; + + dprintf(2, "AHCI/%d: probing\n", port->pnr); + ahci_port_reset(port->ctrl, port->pnr); + rc = ahci_port_setup(port); + if (rc < 0) + ahci_port_release(port); + else { + port = ahci_port_realloc(port); + if (port == NULL) + return; + dprintf(1, "AHCI/%d: registering: \"%s\"\n", port->pnr, port->desc); + if (!port->atapi) { + // Register with bcv system. + boot_add_hd(&port->drive, port->desc, port->prio); + } else { + // fill cdidmap + boot_add_cd(&port->drive, port->desc, port->prio); + } + } +} + +// Initialize an ata controller and detect its drives. +static void +ahci_controller_setup(struct pci_device *pci) +{ + struct ahci_ctrl_s *ctrl = malloc_fseg(sizeof(*ctrl)); + struct ahci_port_s *port; + u16 bdf = pci->bdf; + u32 val, pnr, max; + + if (!ctrl) { + warn_noalloc(); + return; + } + + if (create_bounce_buf() < 0) { + warn_noalloc(); + free(ctrl); + return; + } + + ctrl->pci_tmp = pci; + ctrl->pci_bdf = bdf; + ctrl->iobase = pci_config_readl(bdf, PCI_BASE_ADDRESS_5); + ctrl->irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); + dprintf(1, "AHCI controller at %02x.%x, iobase %x, irq %d\n", + bdf >> 3, bdf & 7, ctrl->iobase, ctrl->irq); + + pci_config_maskw(bdf, PCI_COMMAND, 0, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + val = ahci_ctrl_readl(ctrl, HOST_CTL); + ahci_ctrl_writel(ctrl, HOST_CTL, val | HOST_CTL_AHCI_EN); + + ctrl->caps = ahci_ctrl_readl(ctrl, HOST_CAP); + ctrl->ports = ahci_ctrl_readl(ctrl, HOST_PORTS_IMPL); + dprintf(2, "AHCI: cap 0x%x, ports_impl 0x%x\n", + ctrl->caps, ctrl->ports); + + max = ctrl->caps & 0x1f; + for (pnr = 0; pnr <= max; pnr++) { + if (!(ctrl->ports & (1 << pnr))) + continue; + port = ahci_port_alloc(ctrl, pnr); + if (port == NULL) + continue; + run_thread(ahci_port_detect, port); + } +} + +// Locate and init ahci controllers. +static void +ahci_scan(void) +{ + // Scan PCI bus for ATA adapters + struct pci_device *pci; + foreachpci(pci) { + if (pci->class != PCI_CLASS_STORAGE_SATA) + continue; + if (pci->prog_if != 1 /* AHCI rev 1 */) + continue; + ahci_controller_setup(pci); + } +} + +void +ahci_setup(void) +{ + ASSERT32FLAT(); + if (!CONFIG_AHCI) + return; + + dprintf(3, "init ahci\n"); + ahci_scan(); +} diff -Nru seabios-1.7.1/src/hw/ahci.h seabios-1.7.4/src/hw/ahci.h --- seabios-1.7.1/src/hw/ahci.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/ahci.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,202 @@ +#ifndef __AHCI_H +#define __AHCI_H + +#include "block.h" // struct drive_s +#include "types.h" // u32 + +struct sata_cmd_fis { + u8 reg; + u8 pmp_type; + u8 command; + u8 feature; + + u8 lba_low; + u8 lba_mid; + u8 lba_high; + u8 device; + + u8 lba_low2; + u8 lba_mid2; + u8 lba_high2; + u8 feature2; + + u8 sector_count; + u8 sector_count2; + u8 res_1; + u8 control; + + u8 res_2[64 - 16]; +}; + +struct ahci_ctrl_s { + struct pci_device *pci_tmp; + u16 pci_bdf; + u8 irq; + u32 iobase; + u32 caps; + u32 ports; +}; + +struct ahci_cmd_s { + struct sata_cmd_fis fis; + u8 atapi[0x20]; + u8 res[0x20]; + struct { + u32 base; + u32 baseu; + u32 res; + u32 flags; + } prdt[]; +}; + +/* command list */ +struct ahci_list_s { + u32 flags; + u32 bytes; + u32 base; + u32 baseu; + u32 res[4]; +}; + +struct ahci_fis_s { + u8 dsfis[0x1c]; /* dma setup */ + u8 res_1[0x04]; + u8 psfis[0x14]; /* pio setup */ + u8 res_2[0x0c]; + u8 rfis[0x14]; /* d2h register */ + u8 res_3[0x04]; + u8 sdbfis[0x08]; /* set device bits */ + u8 ufis[0x40]; /* unknown */ + u8 res_4[0x60]; +}; + +struct ahci_port_s { + struct drive_s drive; + struct ahci_ctrl_s *ctrl; + struct ahci_list_s *list; + struct ahci_fis_s *fis; + struct ahci_cmd_s *cmd; + u32 pnr; + u32 atapi; + char *desc; + int prio; +}; + +void ahci_setup(void); +int process_ahci_op(struct disk_op_s *op); +int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); + +#define AHCI_IRQ_ON_SG (1 << 31) +#define AHCI_CMD_ATAPI (1 << 5) +#define AHCI_CMD_WRITE (1 << 6) +#define AHCI_CMD_PREFETCH (1 << 7) +#define AHCI_CMD_RESET (1 << 8) +#define AHCI_CMD_CLR_BUSY (1 << 10) + +#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ +#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ +#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ + +/* global controller registers */ +#define HOST_CAP 0x00 /* host capabilities */ +#define HOST_CTL 0x04 /* global host control */ +#define HOST_IRQ_STAT 0x08 /* interrupt status */ +#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ +#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ + +/* HOST_CTL bits */ +#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ +#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ +#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */ + +/* HOST_CAP bits */ +#define HOST_CAP_SSC (1 << 14) /* Slumber capable */ +#define HOST_CAP_AHCI (1 << 18) /* AHCI only */ +#define HOST_CAP_CLO (1 << 24) /* Command List Override support */ +#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ +#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ +#define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */ + +/* registers for each SATA port */ +#define PORT_LST_ADDR 0x00 /* command list DMA addr */ +#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ +#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ +#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ +#define PORT_IRQ_STAT 0x10 /* interrupt status */ +#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ +#define PORT_CMD 0x18 /* port command */ +#define PORT_TFDATA 0x20 /* taskfile data */ +#define PORT_SIG 0x24 /* device TF signature */ +#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ +#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ +#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ +#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ +#define PORT_CMD_ISSUE 0x38 /* command issue */ +#define PORT_RESERVED 0x3c /* reserved */ + +/* PORT_IRQ_{STAT,MASK} bits */ +#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ +#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ +#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ +#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ +#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ +#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ +#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ +#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ + +#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ +#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ +#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ +#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ +#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ +#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ +#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ +#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ +#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ + +#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \ + PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ + PORT_IRQ_UNK_FIS) +#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \ + PORT_IRQ_HBUS_DATA_ERR) +#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \ + PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ + PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) + +/* PORT_CMD bits */ +#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ +#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ +#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ +#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ +#define PORT_CMD_CLO (1 << 3) /* Command list override */ +#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ +#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ +#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ + +#define PORT_CMD_ICC_MASK (0xf << 28) /* i/f ICC state mask */ +#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ +#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ +#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ + +#define PORT_IRQ_STAT_DHRS (1 << 0) /* Device to Host Register FIS */ +#define PORT_IRQ_STAT_PSS (1 << 1) /* PIO Setup FIS */ +#define PORT_IRQ_STAT_DSS (1 << 2) /* DMA Setup FIS */ +#define PORT_IRQ_STAT_SDBS (1 << 3) /* Set Device Bits */ +#define PORT_IRQ_STAT_UFS (1 << 4) /* Unknown FIS */ +#define PORT_IRQ_STAT_DPS (1 << 5) /* Descriptor Processed */ +#define PORT_IRQ_STAT_PCS (1 << 6) /* Port Connect Change Status */ +#define PORT_IRQ_STAT_DMPS (1 << 7) /* Device Mechanical Presence + Status */ +#define PORT_IRQ_STAT_PRCS (1 << 22) /* File Ready Status */ +#define PORT_IRQ_STAT_IPMS (1 << 23) /* Incorrect Port Multiplier + Status */ +#define PORT_IRQ_STAT_OFS (1 << 24) /* Overflow Status */ +#define PORT_IRQ_STAT_INFS (1 << 26) /* Interface Non-Fatal Error + Status */ +#define PORT_IRQ_STAT_IFS (1 << 27) /* Interface Fatal Error */ +#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */ +#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */ +#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */ +#define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */ + +#endif // ahci.h diff -Nru seabios-1.7.1/src/hw/ata.c seabios-1.7.4/src/hw/ata.c --- seabios-1.7.1/src/hw/ata.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/ata.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1045 @@ +// Low level ATA disk access +// +// Copyright (C) 2008,2009 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "ata.h" // ATA_CB_STAT +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct drive_s +#include "blockcmd.h" // CDB_CMD_READ_10 +#include "byteorder.h" // be16_to_cpu +#include "malloc.h" // malloc_fseg +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER +#include "pci_regs.h" // PCI_INTERRUPT_LINE +#include "pic.h" // enable_hwirq +#include "stacks.h" // yield +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // timer_calc +#include "x86.h" // inb + +#define IDE_TIMEOUT 32000 //32 seconds max for IDE ops + + +/**************************************************************** + * Helper functions + ****************************************************************/ + +// Wait for the specified ide state +static inline int +await_ide(u8 mask, u8 flags, u16 base, u16 timeout) +{ + u32 end = timer_calc(timeout); + for (;;) { + u8 status = inb(base+ATA_CB_STAT); + if ((status & mask) == flags) + return status; + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } +} + +// Wait for the device to be not-busy. +static int +await_not_bsy(u16 base) +{ + return await_ide(ATA_CB_STAT_BSY, 0, base, IDE_TIMEOUT); +} + +// Wait for the device to be ready. +static int +await_rdy(u16 base) +{ + return await_ide(ATA_CB_STAT_RDY, ATA_CB_STAT_RDY, base, IDE_TIMEOUT); +} + +// Wait for ide state - pauses for one ata cycle first. +static inline int +pause_await_not_bsy(u16 iobase1, u16 iobase2) +{ + // Wait one PIO transfer cycle. + inb(iobase2 + ATA_CB_ASTAT); + + return await_not_bsy(iobase1); +} + +// Wait for ide state - pause for 400ns first. +static inline int +ndelay_await_not_bsy(u16 iobase1) +{ + ndelay(400); + return await_not_bsy(iobase1); +} + +// Reset a drive +static void +ata_reset(struct atadrive_s *adrive_gf) +{ + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u8 slave = GET_GLOBALFLAT(adrive_gf->slave); + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); + + dprintf(6, "ata_reset drive=%p\n", &adrive_gf->drive); + // Pulse SRST + outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC); + udelay(5); + outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC); + msleep(2); + + // wait for device to become not busy. + int status = await_not_bsy(iobase1); + if (status < 0) + goto done; + if (slave) { + // Change device. + u32 end = timer_calc(IDE_TIMEOUT); + for (;;) { + outb(ATA_CB_DH_DEV1, iobase1 + ATA_CB_DH); + status = ndelay_await_not_bsy(iobase1); + if (status < 0) + goto done; + if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1) + break; + // Change drive request failed to take effect - retry. + if (timer_check(end)) { + warn_timeout(); + goto done; + } + } + } else { + // QEMU doesn't reset dh on reset, so set it explicitly. + outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH); + } + + // On a user-reset request, wait for RDY if it is an ATA device. + u8 type=GET_GLOBALFLAT(adrive_gf->drive.type); + if (type == DTYPE_ATA) + status = await_rdy(iobase1); + +done: + // Enable interrupts + outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); + + dprintf(6, "ata_reset exit status=%x\n", status); +} + +// Check for drive RDY for 16bit interface command. +static int +isready(struct atadrive_s *adrive_gf) +{ + // Read the status from controller + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + u8 status = inb(iobase1 + ATA_CB_STAT); + if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY) + return DISK_RET_SUCCESS; + return DISK_RET_ENOTREADY; +} + + +/**************************************************************** + * ATA send command + ****************************************************************/ + +struct ata_pio_command { + u8 feature; + u8 sector_count; + u8 lba_low; + u8 lba_mid; + u8 lba_high; + u8 device; + u8 command; + + u8 feature2; + u8 sector_count2; + u8 lba_low2; + u8 lba_mid2; + u8 lba_high2; +}; + +// Send an ata command to the drive. +static int +send_cmd(struct atadrive_s *adrive_gf, struct ata_pio_command *cmd) +{ + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u8 slave = GET_GLOBALFLAT(adrive_gf->slave); + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + + // Select device + int status = await_not_bsy(iobase1); + if (status < 0) + return status; + u8 newdh = ((cmd->device & ~ATA_CB_DH_DEV1) + | (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)); + u8 olddh = inb(iobase1 + ATA_CB_DH); + outb(newdh, iobase1 + ATA_CB_DH); + if ((olddh ^ newdh) & (1<<4)) { + // Was a device change - wait for device to become not busy. + status = ndelay_await_not_bsy(iobase1); + if (status < 0) + return status; + } + + // Check for ATA_CMD_(READ|WRITE)_(SECTORS|DMA)_EXT commands. + if ((cmd->command & ~0x11) == ATA_CMD_READ_SECTORS_EXT) { + outb(cmd->feature2, iobase1 + ATA_CB_FR); + outb(cmd->sector_count2, iobase1 + ATA_CB_SC); + outb(cmd->lba_low2, iobase1 + ATA_CB_SN); + outb(cmd->lba_mid2, iobase1 + ATA_CB_CL); + outb(cmd->lba_high2, iobase1 + ATA_CB_CH); + } + outb(cmd->feature, iobase1 + ATA_CB_FR); + outb(cmd->sector_count, iobase1 + ATA_CB_SC); + outb(cmd->lba_low, iobase1 + ATA_CB_SN); + outb(cmd->lba_mid, iobase1 + ATA_CB_CL); + outb(cmd->lba_high, iobase1 + ATA_CB_CH); + outb(cmd->command, iobase1 + ATA_CB_CMD); + + return 0; +} + +// Wait for data after calling 'send_cmd'. +static int +ata_wait_data(u16 iobase1) +{ + int status = ndelay_await_not_bsy(iobase1); + if (status < 0) + return status; + + if (status & ATA_CB_STAT_ERR) { + dprintf(6, "send_cmd : read error (status=%02x err=%02x)\n" + , status, inb(iobase1 + ATA_CB_ERR)); + return -4; + } + if (!(status & ATA_CB_STAT_DRQ)) { + dprintf(6, "send_cmd : DRQ not set (status %02x)\n", status); + return -5; + } + + return 0; +} + +// Send an ata command that does not transfer any further data. +int +ata_cmd_nondata(struct atadrive_s *adrive_gf, struct ata_pio_command *cmd) +{ + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); + + // Disable interrupts + outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); + + int ret = send_cmd(adrive_gf, cmd); + if (ret) + goto fail; + ret = ndelay_await_not_bsy(iobase1); + if (ret < 0) + goto fail; + + if (ret & ATA_CB_STAT_ERR) { + dprintf(6, "nondata cmd : read error (status=%02x err=%02x)\n" + , ret, inb(iobase1 + ATA_CB_ERR)); + ret = -4; + goto fail; + } + if (ret & ATA_CB_STAT_DRQ) { + dprintf(6, "nondata cmd : DRQ set (status %02x)\n", ret); + ret = -5; + goto fail; + } + +fail: + // Enable interrupts + outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); + + return ret; +} + + +/**************************************************************** + * ATA PIO transfers + ****************************************************************/ + +// Transfer 'op->count' blocks (of 'blocksize' bytes) to/from drive +// 'op->drive_gf'. +static int +ata_pio_transfer(struct disk_op_s *op, int iswrite, int blocksize) +{ + dprintf(16, "ata_pio_transfer id=%p write=%d count=%d bs=%d buf=%p\n" + , op->drive_gf, iswrite, op->count, blocksize, op->buf_fl); + + struct atadrive_s *adrive_gf = container_of( + op->drive_gf, struct atadrive_s, drive); + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); + int count = op->count; + void *buf_fl = op->buf_fl; + int status; + for (;;) { + if (iswrite) { + // Write data to controller + dprintf(16, "Write sector id=%p dest=%p\n", op->drive_gf, buf_fl); + if (CONFIG_ATA_PIO32) + outsl_fl(iobase1, buf_fl, blocksize / 4); + else + outsw_fl(iobase1, buf_fl, blocksize / 2); + } else { + // Read data from controller + dprintf(16, "Read sector id=%p dest=%p\n", op->drive_gf, buf_fl); + if (CONFIG_ATA_PIO32) + insl_fl(iobase1, buf_fl, blocksize / 4); + else + insw_fl(iobase1, buf_fl, blocksize / 2); + } + buf_fl += blocksize; + + status = pause_await_not_bsy(iobase1, iobase2); + if (status < 0) { + // Error + op->count -= count; + return status; + } + + count--; + if (!count) + break; + status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR); + if (status != ATA_CB_STAT_DRQ) { + dprintf(6, "ata_pio_transfer : more sectors left (status %02x)\n" + , status); + op->count -= count; + return -6; + } + } + + status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ + | ATA_CB_STAT_ERR); + if (!iswrite) + status &= ~ATA_CB_STAT_DF; + if (status != 0) { + dprintf(6, "ata_pio_transfer : no sectors left (status %02x)\n", status); + return -7; + } + + return 0; +} + + +/**************************************************************** + * ATA DMA transfers + ****************************************************************/ + +#define BM_CMD 0 +#define BM_CMD_MEMWRITE 0x08 +#define BM_CMD_START 0x01 +#define BM_STATUS 2 +#define BM_STATUS_IRQ 0x04 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_ACTIVE 0x01 +#define BM_TABLE 4 + +struct sff_dma_prd { + u32 buf_fl; + u32 count; +}; + +// Check if DMA available and setup transfer if so. +static int +ata_try_dma(struct disk_op_s *op, int iswrite, int blocksize) +{ + ASSERT16(); + if (! CONFIG_ATA_DMA) + return -1; + u32 dest = (u32)op->buf_fl; + if (dest & 1) + // Need minimum alignment of 1. + return -1; + struct atadrive_s *adrive_gf = container_of( + op->drive_gf, struct atadrive_s, drive); + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster); + if (! iomaster) + return -1; + u32 bytes = op->count * blocksize; + if (! bytes) + return -1; + + // Build PRD dma structure. + struct sff_dma_prd *dma = MAKE_FLATPTR(SEG_LOW, ExtraStack); + struct sff_dma_prd *origdma = dma; + while (bytes) { + if (dma >= &origdma[16]) + // Too many descriptors.. + return -1; + u32 count = bytes; + u32 max = 0x10000 - (dest & 0xffff); + if (count > max) + count = max; + + SET_LOWFLAT(dma->buf_fl, dest); + bytes -= count; + if (!bytes) + // Last descriptor. + count |= 1<<31; + dprintf(16, "dma@%p: %08x %08x\n", dma, dest, count); + dest += count; + SET_LOWFLAT(dma->count, count); + dma++; + } + + // Program bus-master controller. + outl((u32)origdma, iomaster + BM_TABLE); + u8 oldcmd = inb(iomaster + BM_CMD) & ~(BM_CMD_MEMWRITE|BM_CMD_START); + outb(oldcmd | (iswrite ? 0x00 : BM_CMD_MEMWRITE), iomaster + BM_CMD); + outb(BM_STATUS_ERROR|BM_STATUS_IRQ, iomaster + BM_STATUS); + + return 0; +} + +// Transfer data using DMA. +static int +ata_dma_transfer(struct disk_op_s *op) +{ + if (! CONFIG_ATA_DMA) + return -1; + dprintf(16, "ata_dma_transfer id=%p buf=%p\n", op->drive_gf, op->buf_fl); + + struct atadrive_s *adrive_gf = container_of( + op->drive_gf, struct atadrive_s, drive); + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster); + + // Start bus-master controller. + u8 oldcmd = inb(iomaster + BM_CMD); + outb(oldcmd | BM_CMD_START, iomaster + BM_CMD); + + u32 end = timer_calc(IDE_TIMEOUT); + u8 status; + for (;;) { + status = inb(iomaster + BM_STATUS); + if (status & BM_STATUS_IRQ) + break; + // Transfer in progress + if (timer_check(end)) { + // Timeout. + warn_timeout(); + break; + } + yield(); + } + outb(oldcmd & ~BM_CMD_START, iomaster + BM_CMD); + + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); + int idestatus = pause_await_not_bsy(iobase1, iobase2); + + if ((status & (BM_STATUS_IRQ|BM_STATUS_ACTIVE)) == BM_STATUS_IRQ + && idestatus >= 0x00 + && (idestatus & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ + | ATA_CB_STAT_ERR)) == 0x00) + // Success. + return 0; + + dprintf(6, "IDE DMA error (dma=%x ide=%x/%x/%x)\n", status, idestatus + , inb(iobase2 + ATA_CB_ASTAT), inb(iobase1 + ATA_CB_ERR)); + op->count = 0; + return -1; +} + + +/**************************************************************** + * ATA hard drive functions + ****************************************************************/ + +// Transfer data to harddrive using PIO protocol. +static int +ata_pio_cmd_data(struct disk_op_s *op, int iswrite, struct ata_pio_command *cmd) +{ + struct atadrive_s *adrive_gf = container_of( + op->drive_gf, struct atadrive_s, drive); + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); + + // Disable interrupts + outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); + + int ret = send_cmd(adrive_gf, cmd); + if (ret) + goto fail; + ret = ata_wait_data(iobase1); + if (ret) + goto fail; + ret = ata_pio_transfer(op, iswrite, DISK_SECTOR_SIZE); + +fail: + // Enable interrupts + outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); + return ret; +} + +// Transfer data to harddrive using DMA protocol. +static int +ata_dma_cmd_data(struct disk_op_s *op, struct ata_pio_command *cmd) +{ + if (! CONFIG_ATA_DMA) + return -1; + struct atadrive_s *adrive_gf = container_of( + op->drive_gf, struct atadrive_s, drive); + int ret = send_cmd(adrive_gf, cmd); + if (ret) + return ret; + return ata_dma_transfer(op); +} + +// Read/write count blocks from a harddrive. +static int +ata_readwrite(struct disk_op_s *op, int iswrite) +{ + u64 lba = op->lba; + + int usepio = ata_try_dma(op, iswrite, DISK_SECTOR_SIZE); + + struct ata_pio_command cmd; + memset(&cmd, 0, sizeof(cmd)); + + if (op->count >= (1<<8) || lba + op->count >= (1<<28)) { + cmd.sector_count2 = op->count >> 8; + cmd.lba_low2 = lba >> 24; + cmd.lba_mid2 = lba >> 32; + cmd.lba_high2 = lba >> 40; + lba &= 0xffffff; + + if (usepio) + cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS_EXT + : ATA_CMD_READ_SECTORS_EXT); + else + cmd.command = (iswrite ? ATA_CMD_WRITE_DMA_EXT + : ATA_CMD_READ_DMA_EXT); + } else { + if (usepio) + cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS + : ATA_CMD_READ_SECTORS); + else + cmd.command = (iswrite ? ATA_CMD_WRITE_DMA + : ATA_CMD_READ_DMA); + } + + cmd.sector_count = op->count; + cmd.lba_low = lba; + cmd.lba_mid = lba >> 8; + cmd.lba_high = lba >> 16; + cmd.device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA; + + int ret; + if (usepio) + ret = ata_pio_cmd_data(op, iswrite, &cmd); + else + ret = ata_dma_cmd_data(op, &cmd); + if (ret) + return DISK_RET_EBADTRACK; + return DISK_RET_SUCCESS; +} + +// 16bit command demuxer for ATA harddrives. +int +process_ata_op(struct disk_op_s *op) +{ + if (!CONFIG_ATA) + return 0; + + struct atadrive_s *adrive_gf = container_of( + op->drive_gf, struct atadrive_s, drive); + switch (op->command) { + case CMD_READ: + return ata_readwrite(op, 0); + case CMD_WRITE: + return ata_readwrite(op, 1); + case CMD_RESET: + ata_reset(adrive_gf); + return DISK_RET_SUCCESS; + case CMD_ISREADY: + return isready(adrive_gf); + case CMD_FORMAT: + case CMD_VERIFY: + case CMD_SEEK: + return DISK_RET_SUCCESS; + default: + op->count = 0; + return DISK_RET_EPARAM; + } +} + + +/**************************************************************** + * ATAPI functions + ****************************************************************/ + +#define CDROM_CDB_SIZE 12 + +// Low-level atapi command transmit function. +int +atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + if (! CONFIG_ATA) + return 0; + + struct atadrive_s *adrive_gf = container_of( + op->drive_gf, struct atadrive_s, drive); + struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); + u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); + + struct ata_pio_command cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.lba_mid = blocksize; + cmd.lba_high = blocksize >> 8; + cmd.command = ATA_CMD_PACKET; + + // Disable interrupts + outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); + + int ret = send_cmd(adrive_gf, &cmd); + if (ret) + goto fail; + ret = ata_wait_data(iobase1); + if (ret) + goto fail; + + // Send command to device + outsw_fl(iobase1, MAKE_FLATPTR(GET_SEG(SS), cdbcmd), CDROM_CDB_SIZE / 2); + + int status = pause_await_not_bsy(iobase1, iobase2); + if (status < 0) { + ret = status; + goto fail; + } + + if (status & ATA_CB_STAT_ERR) { + u8 err = inb(iobase1 + ATA_CB_ERR); + // skip "Not Ready" + if (err != 0x20) + dprintf(6, "send_atapi_cmd : read error (status=%02x err=%02x)\n" + , status, err); + ret = -2; + goto fail; + } + if (blocksize) { + if (!(status & ATA_CB_STAT_DRQ)) { + dprintf(6, "send_atapi_cmd : DRQ not set (status %02x)\n", status); + ret = -3; + goto fail; + } + + ret = ata_pio_transfer(op, 0, blocksize); + } + +fail: + // Enable interrupts + outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); + if (ret) + return DISK_RET_EBADTRACK; + return DISK_RET_SUCCESS; +} + + +/**************************************************************** + * ATA detect and init + ****************************************************************/ + +// Send an identify device or identify device packet command. +static int +send_ata_identity(struct atadrive_s *adrive, u16 *buffer, int command) +{ + memset(buffer, 0, DISK_SECTOR_SIZE); + + struct disk_op_s dop; + memset(&dop, 0, sizeof(dop)); + dop.drive_gf = &adrive->drive; + dop.count = 1; + dop.lba = 1; + dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer); + + struct ata_pio_command cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = command; + + return ata_pio_cmd_data(&dop, 0, &cmd); +} + +// Extract the ATA/ATAPI version info. +int +ata_extract_version(u16 *buffer) +{ + // Extract ATA/ATAPI version. + u16 ataversion = buffer[80]; + u8 version; + for (version=15; version>0; version--) + if (ataversion & (1<chan_gf = dummy->chan_gf; + adrive->slave = dummy->slave; + adrive->drive.cntl_id = adrive->chan_gf->chanid * 2 + dummy->slave; + adrive->drive.removable = (buffer[0] & 0x80) ? 1 : 0; + return adrive; +} + +// Detect if the given drive is an atapi - initialize it if so. +static struct atadrive_s * +init_drive_atapi(struct atadrive_s *dummy, u16 *buffer) +{ + // Send an IDENTIFY_DEVICE_PACKET command to device + int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_PACKET_DEVICE); + if (ret) + return NULL; + + // Success - setup as ATAPI. + struct atadrive_s *adrive = init_atadrive(dummy, buffer); + if (!adrive) + return NULL; + adrive->drive.type = DTYPE_ATA_ATAPI; + adrive->drive.blksize = CDROM_SECTOR_SIZE; + adrive->drive.sectors = (u64)-1; + u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05; + char model[MAXMODEL+1]; + char *desc = znprintf(MAXDESCSIZE + , "DVD/CD [ata%d-%d: %s ATAPI-%d %s]" + , adrive->chan_gf->chanid, adrive->slave + , ata_extract_model(model, MAXMODEL, buffer) + , ata_extract_version(buffer) + , (iscd ? "DVD/CD" : "Device")); + dprintf(1, "%s\n", desc); + + // fill cdidmap + if (iscd) { + int prio = bootprio_find_ata_device(adrive->chan_gf->pci_tmp, + adrive->chan_gf->chanid, + adrive->slave); + boot_add_cd(&adrive->drive, desc, prio); + } + + return adrive; +} + +// Detect if the given drive is a regular ata drive - initialize it if so. +static struct atadrive_s * +init_drive_ata(struct atadrive_s *dummy, u16 *buffer) +{ + // Send an IDENTIFY_DEVICE command to device + int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_DEVICE); + if (ret) + return NULL; + + // Success - setup as ATA. + struct atadrive_s *adrive = init_atadrive(dummy, buffer); + if (!adrive) + return NULL; + adrive->drive.type = DTYPE_ATA; + adrive->drive.blksize = DISK_SECTOR_SIZE; + + adrive->drive.pchs.cylinder = buffer[1]; + adrive->drive.pchs.head = buffer[3]; + adrive->drive.pchs.sector = buffer[6]; + + u64 sectors; + if (buffer[83] & (1 << 10)) // word 83 - lba48 support + sectors = *(u64*)&buffer[100]; // word 100-103 + else + sectors = *(u32*)&buffer[60]; // word 60 and word 61 + adrive->drive.sectors = sectors; + u64 adjsize = sectors >> 11; + char adjprefix = 'M'; + if (adjsize >= (1 << 16)) { + adjsize >>= 10; + adjprefix = 'G'; + } + char model[MAXMODEL+1]; + char *desc = znprintf(MAXDESCSIZE + , "ata%d-%d: %s ATA-%d Hard-Disk (%u %ciBytes)" + , adrive->chan_gf->chanid, adrive->slave + , ata_extract_model(model, MAXMODEL, buffer) + , ata_extract_version(buffer) + , (u32)adjsize, adjprefix); + dprintf(1, "%s\n", desc); + + int prio = bootprio_find_ata_device(adrive->chan_gf->pci_tmp, + adrive->chan_gf->chanid, + adrive->slave); + // Register with bcv system. + boot_add_hd(&adrive->drive, desc, prio); + + return adrive; +} + +static u32 SpinupEnd; + +// Wait for non-busy status and check for "floating bus" condition. +static int +powerup_await_non_bsy(u16 base) +{ + u8 orstatus = 0; + u8 status; + for (;;) { + status = inb(base+ATA_CB_STAT); + if (!(status & ATA_CB_STAT_BSY)) + break; + orstatus |= status; + if (orstatus == 0xff) { + dprintf(4, "powerup IDE floating\n"); + return orstatus; + } + if (timer_check(SpinupEnd)) { + warn_timeout(); + return -1; + } + yield(); + } + dprintf(6, "powerup iobase=%x st=%x\n", base, status); + return status; +} + +// Detect any drives attached to a given controller. +static void +ata_detect(void *data) +{ + struct ata_channel_s *chan_gf = data; + struct atadrive_s dummy; + memset(&dummy, 0, sizeof(dummy)); + dummy.chan_gf = chan_gf; + // Device detection + int didreset = 0; + u8 slave; + for (slave=0; slave<=1; slave++) { + // Wait for not-bsy. + u16 iobase1 = chan_gf->iobase1; + int status = powerup_await_non_bsy(iobase1); + if (status < 0) + continue; + u8 newdh = slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0; + outb(newdh, iobase1+ATA_CB_DH); + ndelay(400); + status = powerup_await_non_bsy(iobase1); + if (status < 0) + continue; + + // Check if ioport registers look valid. + outb(newdh, iobase1+ATA_CB_DH); + u8 dh = inb(iobase1+ATA_CB_DH); + outb(0x55, iobase1+ATA_CB_SC); + outb(0xaa, iobase1+ATA_CB_SN); + u8 sc = inb(iobase1+ATA_CB_SC); + u8 sn = inb(iobase1+ATA_CB_SN); + dprintf(6, "ata_detect ata%d-%d: sc=%x sn=%x dh=%x\n" + , chan_gf->chanid, slave, sc, sn, dh); + if (sc != 0x55 || sn != 0xaa || dh != newdh) + continue; + + // Prepare new drive. + dummy.slave = slave; + + // reset the channel + if (!didreset) { + ata_reset(&dummy); + didreset = 1; + } + + // check for ATAPI + u16 buffer[256]; + struct atadrive_s *adrive = init_drive_atapi(&dummy, buffer); + if (!adrive) { + // Didn't find an ATAPI drive - look for ATA drive. + u8 st = inb(iobase1+ATA_CB_STAT); + if (!st) + // Status not set - can't be a valid drive. + continue; + + // Wait for RDY. + int ret = await_rdy(iobase1); + if (ret < 0) + continue; + + // check for ATA. + adrive = init_drive_ata(&dummy, buffer); + if (!adrive) + // No ATA drive found + continue; + } + + u16 resetresult = buffer[93]; + dprintf(6, "ata_detect resetresult=%04x\n", resetresult); + if (!slave && (resetresult & 0xdf61) == 0x4041) + // resetresult looks valid and device 0 is responding to + // device 1 requests - device 1 must not be present - skip + // detection. + break; + } +} + +// Initialize an ata controller and detect its drives. +static void +init_controller(struct pci_device *pci, int irq + , u32 port1, u32 port2, u32 master) +{ + static int chanid = 0; + struct ata_channel_s *chan_gf = malloc_fseg(sizeof(*chan_gf)); + if (!chan_gf) { + warn_noalloc(); + return; + } + chan_gf->chanid = chanid++; + chan_gf->irq = irq; + chan_gf->pci_bdf = pci ? pci->bdf : -1; + chan_gf->pci_tmp = pci; + chan_gf->iobase1 = port1; + chan_gf->iobase2 = port2; + chan_gf->iomaster = master; + dprintf(1, "ATA controller %d at %x/%x/%x (irq %d dev %x)\n" + , chanid, port1, port2, master, irq, chan_gf->pci_bdf); + run_thread(ata_detect, chan_gf); +} + +#define IRQ_ATA1 14 +#define IRQ_ATA2 15 + +// Handle controllers on an ATA PCI device. +static void +init_pciata(struct pci_device *pci, u8 prog_if) +{ + pci->have_driver = 1; + u16 bdf = pci->bdf; + u8 pciirq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); + int master = 0; + if (CONFIG_ATA_DMA && prog_if & 0x80) { + // Check for bus-mastering. + u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_4); + if (bar & PCI_BASE_ADDRESS_SPACE_IO) { + master = bar & PCI_BASE_ADDRESS_IO_MASK; + pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + } + } + + u32 port1, port2, irq; + if (prog_if & 1) { + port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_0) + & PCI_BASE_ADDRESS_IO_MASK); + port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_1) + & PCI_BASE_ADDRESS_IO_MASK); + irq = pciirq; + } else { + port1 = PORT_ATA1_CMD_BASE; + port2 = PORT_ATA1_CTRL_BASE; + irq = IRQ_ATA1; + } + init_controller(pci, irq, port1, port2, master); + + if (prog_if & 4) { + port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_2) + & PCI_BASE_ADDRESS_IO_MASK); + port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_3) + & PCI_BASE_ADDRESS_IO_MASK); + irq = pciirq; + } else { + port1 = PORT_ATA2_CMD_BASE; + port2 = PORT_ATA2_CTRL_BASE; + irq = IRQ_ATA2; + } + init_controller(pci, irq, port1, port2, master ? master + 8 : 0); +} + +static void +found_genericata(struct pci_device *pci, void *arg) +{ + init_pciata(pci, pci->prog_if); +} + +static void +found_compatibleahci(struct pci_device *pci, void *arg) +{ + if (CONFIG_AHCI) + // Already handled directly via native ahci interface. + return; + init_pciata(pci, 0x8f); +} + +static const struct pci_device_id pci_ata_tbl[] = { + PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE + , found_genericata), + PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4391, found_compatibleahci), + PCI_DEVICE_END, +}; + +// Locate and init ata controllers. +static void +ata_scan(void) +{ + if (CONFIG_QEMU && hlist_empty(&PCIDevices)) { + // No PCI devices found - probably a QEMU "-M isapc" machine. + // Try using ISA ports for ATA controllers. + init_controller(NULL, IRQ_ATA1 + , PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE, 0); + init_controller(NULL, IRQ_ATA2 + , PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE, 0); + return; + } + + // Scan PCI bus for ATA adapters + struct pci_device *pci; + foreachpci(pci) { + pci_init_device(pci_ata_tbl, pci, NULL); + } +} + +void +ata_setup(void) +{ + ASSERT32FLAT(); + if (!CONFIG_ATA) + return; + + dprintf(3, "init hard drives\n"); + + SpinupEnd = timer_calc(IDE_TIMEOUT); + ata_scan(); + + SET_BDA(disk_control_byte, 0xc0); + + enable_hwirq(14, FUNC16(entry_76)); +} diff -Nru seabios-1.7.1/src/hw/ata.h seabios-1.7.4/src/hw/ata.h --- seabios-1.7.1/src/hw/ata.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/ata.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,158 @@ +#ifndef __ATA_H +#define __ATA_H + +#include "block.h" // struct drive_s +#include "config.h" // CONFIG_MAX_ATA_INTERFACES +#include "types.h" // u8 + +struct ata_channel_s { + u16 iobase1; + u16 iobase2; + u16 iomaster; + u8 irq; + u8 chanid; + int pci_bdf; + struct pci_device *pci_tmp; +}; + +struct atadrive_s { + struct drive_s drive; + struct ata_channel_s *chan_gf; + u8 slave; +}; + +// ata.c +char *ata_extract_model(char *model, u32 size, u16 *buffer); +int ata_extract_version(u16 *buffer); +int cdrom_read(struct disk_op_s *op); +int atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +void ata_setup(void); +int process_ata_op(struct disk_op_s *op); + +#define PORT_ATA2_CMD_BASE 0x0170 +#define PORT_ATA1_CMD_BASE 0x01f0 +#define PORT_ATA2_CTRL_BASE 0x0374 +#define PORT_ATA1_CTRL_BASE 0x03f4 + +// Global defines -- ATA register and register bits. +// command block & control block regs +#define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0 +#define ATA_CB_ERR 1 // error in pio_base_addr1+1 +#define ATA_CB_FR 1 // feature reg out pio_base_addr1+1 +#define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2 +#define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3 +#define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4 +#define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5 +#define ATA_CB_DH 6 // device head in/out pio_base_addr1+6 +#define ATA_CB_STAT 7 // primary status in pio_base_addr1+7 +#define ATA_CB_CMD 7 // command out pio_base_addr1+7 + +#define ATA_CB_ASTAT 2 // alternate status in pio_base_addr2+2 +#define ATA_CB_DC 2 // device control out pio_base_addr2+2 +#define ATA_CB_DA 3 // device address in pio_base_addr2+3 + +#define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC +#define ATA_CB_ER_BBK 0x80 // ATA bad block +#define ATA_CB_ER_UNC 0x40 // ATA uncorrected error +#define ATA_CB_ER_MC 0x20 // ATA media change +#define ATA_CB_ER_IDNF 0x10 // ATA id not found +#define ATA_CB_ER_MCR 0x08 // ATA media change request +#define ATA_CB_ER_ABRT 0x04 // ATA command aborted +#define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found +#define ATA_CB_ER_NDAM 0x01 // ATA address mark not found + +#define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask) +#define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request +#define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort +#define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media +#define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication + +// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC) +#define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask) +#define ATA_CB_SC_P_REL 0x04 // ATAPI release +#define ATA_CB_SC_P_IO 0x02 // ATAPI I/O +#define ATA_CB_SC_P_CD 0x01 // ATAPI C/D + +// bits 7-4 of the device/head (CB_DH) reg +#define ATA_CB_DH_DEV0 0xa0 // select device 0 +#define ATA_CB_DH_DEV1 0xb0 // select device 1 +#define ATA_CB_DH_LBA 0x40 // use LBA + +// status reg (CB_STAT and CB_ASTAT) bits +#define ATA_CB_STAT_BSY 0x80 // busy +#define ATA_CB_STAT_RDY 0x40 // ready +#define ATA_CB_STAT_DF 0x20 // device fault +#define ATA_CB_STAT_WFT 0x20 // write fault (old name) +#define ATA_CB_STAT_SKC 0x10 // seek complete +#define ATA_CB_STAT_SERV 0x10 // service +#define ATA_CB_STAT_DRQ 0x08 // data request +#define ATA_CB_STAT_CORR 0x04 // corrected +#define ATA_CB_STAT_IDX 0x02 // index +#define ATA_CB_STAT_ERR 0x01 // error (ATA) +#define ATA_CB_STAT_CHK 0x01 // check (ATAPI) + +// device control reg (CB_DC) bits +#define ATA_CB_DC_HD15 0x08 // bit should always be set to one +#define ATA_CB_DC_SRST 0x04 // soft reset +#define ATA_CB_DC_NIEN 0x02 // disable interrupts + +// Most mandtory and optional ATA commands (from ATA-3), +#define ATA_CMD_NOP 0x00 +#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03 +#define ATA_CMD_DEVICE_RESET 0x08 +#define ATA_CMD_RECALIBRATE 0x10 +#define ATA_CMD_READ_SECTORS 0x20 +#define ATA_CMD_READ_SECTORS_EXT 0x24 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_READ_DMA_QUEUED_EXT 0x26 +#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT 0x27 +#define ATA_CMD_READ_MULTIPLE_EXT 0x29 +#define ATA_CMD_READ_LOG_EXT 0x2F +#define ATA_CMD_WRITE_SECTORS 0x30 +#define ATA_CMD_WRITE_SECTORS_EXT 0x34 +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_WRITE_DMA_QUEUED_EXT 0x36 +#define ATA_CMD_SET_MAX_ADDRESS_EXT 0x37 +#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38 +#define ATA_CMD_WRITE_MULTIPLE_EXT 0x39 +#define ATA_CMD_WRITE_VERIFY 0x3C +#define ATA_CMD_WRITE_LOG_EXT 0x3F +#define ATA_CMD_READ_VERIFY_SECTORS 0x40 +#define ATA_CMD_READ_VERIFY_SECTORS_EXT 0x42 +#define ATA_CMD_FORMAT_TRACK 0x50 +#define ATA_CMD_SEEK 0x70 +#define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87 +#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 +#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 +#define ATA_CMD_STANDBY_IMMEDIATE2 0x94 +#define ATA_CMD_IDLE_IMMEDIATE2 0x95 +#define ATA_CMD_STANDBY2 0x96 +#define ATA_CMD_IDLE2 0x97 +#define ATA_CMD_CHECK_POWER_MODE2 0x98 +#define ATA_CMD_SLEEP2 0x99 +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1 +#define ATA_CMD_CFA_ERASE_SECTORS 0xC0 +#define ATA_CMD_READ_MULTIPLE 0xC4 +#define ATA_CMD_WRITE_MULTIPLE 0xC5 +#define ATA_CMD_SET_MULTIPLE_MODE 0xC6 +#define ATA_CMD_READ_DMA_QUEUED 0xC7 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_QUEUED 0xCC +#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD +#define ATA_CMD_STANDBY_IMMEDIATE 0xE0 +#define ATA_CMD_IDLE_IMMEDIATE 0xE1 +#define ATA_CMD_STANDBY 0xE2 +#define ATA_CMD_IDLE 0xE3 +#define ATA_CMD_READ_BUFFER 0xE4 +#define ATA_CMD_CHECK_POWER_MODE 0xE5 +#define ATA_CMD_SLEEP 0xE6 +#define ATA_CMD_FLUSH_CACHE 0xE7 +#define ATA_CMD_WRITE_BUFFER 0xE8 +#define ATA_CMD_IDENTIFY_DEVICE 0xEC +#define ATA_CMD_SET_FEATURES 0xEF +#define ATA_CMD_READ_NATIVE_MAX_ADDRESS 0xF8 +#define ATA_CMD_SET_MAX 0xF9 + +#endif // ata.h diff -Nru seabios-1.7.1/src/hw/blockcmd.c seabios-1.7.4/src/hw/blockcmd.c --- seabios-1.7.1/src/hw/blockcmd.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/blockcmd.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,284 @@ +// Support for several common scsi like command data block requests +// +// Copyright (C) 2010 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "ahci.h" // atapi_cmd_data +#include "ata.h" // atapi_cmd_data +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct disk_op_s +#include "blockcmd.h" // struct cdb_request_sense +#include "byteorder.h" // be32_to_cpu +#include "esp-scsi.h" // esp_scsi_cmd_data +#include "lsi-scsi.h" // lsi_scsi_cmd_data +#include "megasas.h" // megasas_cmd_data +#include "pvscsi.h" // pvscsi_cmd_data +#include "output.h" // dprintf +#include "std/disk.h" // DISK_RET_EPARAM +#include "string.h" // memset +#include "usb-msc.h" // usb_cmd_data +#include "usb-uas.h" // usb_cmd_data +#include "util.h" // timer_calc +#include "virtio-scsi.h" // virtio_scsi_cmd_data + +// Route command to low-level handler. +static int +cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + u8 type = GET_GLOBALFLAT(op->drive_gf->type); + switch (type) { + case DTYPE_ATA_ATAPI: + return atapi_cmd_data(op, cdbcmd, blocksize); + case DTYPE_USB: + return usb_cmd_data(op, cdbcmd, blocksize); + case DTYPE_UAS: + return uas_cmd_data(op, cdbcmd, blocksize); + case DTYPE_VIRTIO_SCSI: + return virtio_scsi_cmd_data(op, cdbcmd, blocksize); + case DTYPE_LSI_SCSI: + return lsi_scsi_cmd_data(op, cdbcmd, blocksize); + case DTYPE_ESP_SCSI: + return esp_scsi_cmd_data(op, cdbcmd, blocksize); + case DTYPE_MEGASAS: + return megasas_cmd_data(op, cdbcmd, blocksize); + case DTYPE_PVSCSI: + return pvscsi_cmd_data(op, cdbcmd, blocksize); + case DTYPE_AHCI_ATAPI: + if (!MODESEGMENT) + return ahci_cmd_data(op, cdbcmd, blocksize); + default: + op->count = 0; + return DISK_RET_EPARAM; + } +} + +// Determine if the command is a request to pull data from the device +int +cdb_is_read(u8 *cdbcmd, u16 blocksize) +{ + return blocksize && cdbcmd[0] != CDB_CMD_WRITE_10; +} + +int +scsi_is_ready(struct disk_op_s *op) +{ + dprintf(6, "scsi_is_ready (drive=%p)\n", op->drive_gf); + + /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is + * reported by the device. If the device reports "IN PROGRESS", + * 30 seconds is added. */ + int in_progress = 0; + u32 end = timer_calc(5000); + for (;;) { + if (timer_check(end)) { + dprintf(1, "test unit ready failed\n"); + return -1; + } + + int ret = cdb_test_unit_ready(op); + if (!ret) + // Success + break; + + struct cdbres_request_sense sense; + ret = cdb_get_sense(op, &sense); + if (ret) + // Error - retry. + continue; + + // Sense succeeded. + if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */ + dprintf(1, "Device reports MEDIUM NOT PRESENT\n"); + return -1; + } + + if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) { + /* IN PROGRESS OF BECOMING READY */ + printf("Waiting for device to detect medium... "); + /* Allow 30 seconds more */ + end = timer_calc(30000); + in_progress = 1; + } + } + return 0; +} + +// Validate drive, find block size / sector count, and register drive. +int +scsi_drive_setup(struct drive_s *drive, const char *s, int prio) +{ + struct disk_op_s dop; + memset(&dop, 0, sizeof(dop)); + dop.drive_gf = drive; + struct cdbres_inquiry data; + int ret = cdb_get_inquiry(&dop, &data); + if (ret) + return ret; + char vendor[sizeof(data.vendor)+1], product[sizeof(data.product)+1]; + char rev[sizeof(data.rev)+1]; + strtcpy(vendor, data.vendor, sizeof(vendor)); + nullTrailingSpace(vendor); + strtcpy(product, data.product, sizeof(product)); + nullTrailingSpace(product); + strtcpy(rev, data.rev, sizeof(rev)); + nullTrailingSpace(rev); + int pdt = data.pdt & 0x1f; + int removable = !!(data.removable & 0x80); + dprintf(1, "%s vendor='%s' product='%s' rev='%s' type=%d removable=%d\n" + , s, vendor, product, rev, pdt, removable); + drive->removable = removable; + + if (pdt == SCSI_TYPE_CDROM) { + drive->blksize = CDROM_SECTOR_SIZE; + drive->sectors = (u64)-1; + + char *desc = znprintf(MAXDESCSIZE, "DVD/CD [%s Drive %s %s %s]" + , s, vendor, product, rev); + boot_add_cd(drive, desc, prio); + return 0; + } + + ret = scsi_is_ready(&dop); + if (ret) { + dprintf(1, "scsi_is_ready returned %d\n", ret); + return ret; + } + + struct cdbres_read_capacity capdata; + ret = cdb_read_capacity(&dop, &capdata); + if (ret) + return ret; + + // READ CAPACITY returns the address of the last block. + // We do not bother with READ CAPACITY(16) because BIOS does not support + // 64-bit LBA anyway. + drive->blksize = be32_to_cpu(capdata.blksize); + if (drive->blksize != DISK_SECTOR_SIZE) { + dprintf(1, "%s: unsupported block size %d\n", s, drive->blksize); + return -1; + } + drive->sectors = (u64)be32_to_cpu(capdata.sectors) + 1; + dprintf(1, "%s blksize=%d sectors=%d\n" + , s, drive->blksize, (unsigned)drive->sectors); + + // We do not recover from USB stalls, so try to be safe and avoid + // sending the command if the (obsolete, but still provided by QEMU) + // fixed disk geometry page may not be supported. + // + // We could also send the command only to small disks (e.g. <504MiB) + // but some old USB keys only support a very small subset of SCSI which + // does not even include the MODE SENSE command! + // + if (CONFIG_QEMU_HARDWARE && memcmp(vendor, "QEMU", 5) == 0) { + struct cdbres_mode_sense_geom geomdata; + ret = cdb_mode_sense_geom(&dop, &geomdata); + if (ret == 0) { + u32 cylinders; + cylinders = geomdata.cyl[0] << 16; + cylinders |= geomdata.cyl[1] << 8; + cylinders |= geomdata.cyl[2]; + if (cylinders && geomdata.heads && + drive->sectors <= 0xFFFFFFFFULL && + ((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) { + drive->pchs.cylinder = cylinders; + drive->pchs.head = geomdata.heads; + drive->pchs.sector = (u32)drive->sectors / (geomdata.heads * cylinders); + } + } + } + + char *desc = znprintf(MAXDESCSIZE, "%s Drive %s %s %s" + , s, vendor, product, rev); + boot_add_hd(drive, desc, prio); + return 0; +} + +int +cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data) +{ + struct cdb_request_sense cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = CDB_CMD_INQUIRY; + cmd.length = sizeof(*data); + op->count = 1; + op->buf_fl = data; + return cdb_cmd_data(op, &cmd, sizeof(*data)); +} + +// Request SENSE +int +cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data) +{ + struct cdb_request_sense cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = CDB_CMD_REQUEST_SENSE; + cmd.length = sizeof(*data); + op->count = 1; + op->buf_fl = data; + return cdb_cmd_data(op, &cmd, sizeof(*data)); +} + +// Test unit ready +int +cdb_test_unit_ready(struct disk_op_s *op) +{ + struct cdb_request_sense cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = CDB_CMD_TEST_UNIT_READY; + op->count = 0; + op->buf_fl = NULL; + return cdb_cmd_data(op, &cmd, 0); +} + +// Request capacity +int +cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data) +{ + struct cdb_read_capacity cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = CDB_CMD_READ_CAPACITY; + op->count = 1; + op->buf_fl = data; + return cdb_cmd_data(op, &cmd, sizeof(*data)); +} + +// Mode sense, geometry page. +int +cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data) +{ + struct cdb_mode_sense cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = CDB_CMD_MODE_SENSE; + cmd.flags = 8; /* DBD */ + cmd.page = MODE_PAGE_HD_GEOMETRY; + cmd.count = cpu_to_be16(sizeof(*data)); + op->count = 1; + op->buf_fl = data; + return cdb_cmd_data(op, &cmd, sizeof(*data)); +} + +// Read sectors. +int +cdb_read(struct disk_op_s *op) +{ + struct cdb_rwdata_10 cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = CDB_CMD_READ_10; + cmd.lba = cpu_to_be32(op->lba); + cmd.count = cpu_to_be16(op->count); + return cdb_cmd_data(op, &cmd, GET_GLOBALFLAT(op->drive_gf->blksize)); +} + +// Write sectors. +int +cdb_write(struct disk_op_s *op) +{ + struct cdb_rwdata_10 cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = CDB_CMD_WRITE_10; + cmd.lba = cpu_to_be32(op->lba); + cmd.count = cpu_to_be16(op->count); + return cdb_cmd_data(op, &cmd, GET_GLOBALFLAT(op->drive_gf->blksize)); +} diff -Nru seabios-1.7.1/src/hw/blockcmd.h seabios-1.7.4/src/hw/blockcmd.h --- seabios-1.7.1/src/hw/blockcmd.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/blockcmd.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,118 @@ +// Definitions for SCSI style command data blocks. +#ifndef __BLOCKCMD_H +#define __BLOCKCMD_H + +#include "types.h" // u8 + +#define CDB_CMD_READ_10 0x28 +#define CDB_CMD_VERIFY_10 0x2f +#define CDB_CMD_WRITE_10 0x2a + +struct cdb_rwdata_10 { + u8 command; + u8 flags; + u32 lba; + u8 resreved_06; + u16 count; + u8 reserved_09; + u8 pad[6]; +} PACKED; + +#define CDB_CMD_READ_CAPACITY 0x25 + +struct cdb_read_capacity { + u8 command; + u8 flags; + u8 resreved_02[8]; + u8 pad[6]; +} PACKED; + +struct cdbres_read_capacity { + u32 sectors; + u32 blksize; +} PACKED; + +#define CDB_CMD_TEST_UNIT_READY 0x00 +#define CDB_CMD_INQUIRY 0x12 +#define CDB_CMD_REQUEST_SENSE 0x03 + +struct cdb_request_sense { + u8 command; + u8 flags; + u16 reserved_02; + u8 length; + u8 reserved_05; + u8 pad[10]; +} PACKED; + +struct cdbres_request_sense { + u8 errcode; + u8 segment; + u8 flags; + u32 info; + u8 additional; + u32 specific; + u8 asc; + u8 ascq; + u32 reserved_0e; +} PACKED; + +#define SCSI_TYPE_DISK 0x00 +#define SCSI_TYPE_CDROM 0x05 + +struct cdbres_inquiry { + u8 pdt; + u8 removable; + u8 reserved_02[2]; + u8 additional; + u8 reserved_05[3]; + char vendor[8]; + char product[16]; + char rev[4]; +} PACKED; + +#define CDB_CMD_MODE_SENSE 0x5A +#define MODE_PAGE_HD_GEOMETRY 0x04 + +struct cdb_mode_sense { + u8 command; + u8 flags; + u8 page; + u32 reserved_03; + u16 count; + u8 reserved_09; + u8 pad[6]; +} PACKED; + +struct cdbres_mode_sense_geom { + u8 unused_00[3]; + u8 read_only; + u32 unused_04; + u8 page; + u8 length; + u8 cyl[3]; + u8 heads; + u8 precomp[3]; + u8 reduced[3]; + u16 step_rate; + u8 landing[3]; + u16 rpm; +} PACKED; + +// blockcmd.c +int cdb_is_read(u8 *cdbcmd, u16 blocksize); +struct disk_op_s; +int cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data); +int cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data); +int cdb_test_unit_ready(struct disk_op_s *op); +int cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data); +int cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data); +int cdb_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data); +int cdb_read(struct disk_op_s *op); +int cdb_write(struct disk_op_s *op); + +int scsi_is_ready(struct disk_op_s *op); +struct drive_s; +int scsi_drive_setup(struct drive_s *drive, const char *s, int prio); + +#endif // blockcmd.h diff -Nru seabios-1.7.1/src/hw/dma.c seabios-1.7.4/src/hw/dma.c --- seabios-1.7.1/src/hw/dma.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/dma.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,67 @@ +// Code to support legacy Intel 8237 DMA chip. +// +// Copyright (C) 2008,2009 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "util.h" // dma_setup +#include "x86.h" // outb + +#define PORT_DMA_ADDR_2 0x0004 +#define PORT_DMA_CNT_2 0x0005 +#define PORT_DMA1_MASK_REG 0x000a +#define PORT_DMA1_MODE_REG 0x000b +#define PORT_DMA1_CLEAR_FF_REG 0x000c +#define PORT_DMA1_MASTER_CLEAR 0x000d +#define PORT_DMA_PAGE_2 0x0081 +#define PORT_DMA2_MASK_REG 0x00d4 +#define PORT_DMA2_MODE_REG 0x00d6 +#define PORT_DMA2_MASTER_CLEAR 0x00da + +// Setup the DMA controller for a floppy transfer. +int +dma_floppy(u32 addr, int count, int isWrite) +{ + // check for 64K boundary overrun + u16 end = count - 1; + u32 last_addr = addr + end; + if ((addr >> 16) != (last_addr >> 16)) + return -1; + + u8 mode_register = 0x46; // single mode, increment, autoinit disable, + if (isWrite) + mode_register = 0x4a; + + outb(0x06, PORT_DMA1_MASK_REG); + outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop + outb(addr, PORT_DMA_ADDR_2); + outb(addr>>8, PORT_DMA_ADDR_2); + outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop + outb(end, PORT_DMA_CNT_2); + outb(end>>8, PORT_DMA_CNT_2); + + // port 0b: DMA-1 Mode Register + // transfer type=write, channel 2 + outb(mode_register, PORT_DMA1_MODE_REG); + + // port 81: DMA-1 Page Register, channel 2 + outb(addr>>16, PORT_DMA_PAGE_2); + + outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2 + + return 0; +} + +// Reset DMA controller +void +dma_setup(void) +{ + // first reset the DMA controllers + outb(0, PORT_DMA1_MASTER_CLEAR); + outb(0, PORT_DMA2_MASTER_CLEAR); + + // then initialize the DMA controllers + outb(0xc0, PORT_DMA2_MODE_REG); + outb(0x00, PORT_DMA2_MASK_REG); +} diff -Nru seabios-1.7.1/src/hw/esp-scsi.c seabios-1.7.4/src/hw/esp-scsi.c --- seabios-1.7.1/src/hw/esp-scsi.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/esp-scsi.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,238 @@ +// AMD PCscsi boot support. +// +// Copyright (C) 2012 Red Hat Inc. +// +// Authors: +// Paolo Bonzini +// +// based on lsi-scsi.c which is written by: +// Gerd Hoffman +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct drive_s +#include "blockcmd.h" // scsi_drive_setup +#include "config.h" // CONFIG_* +#include "fw/paravirt.h" // runningOnQEMU +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_DEVICE_ID +#include "pci_regs.h" // PCI_VENDOR_ID +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // usleep + +#define ESP_TCLO 0x00 +#define ESP_TCMID 0x04 +#define ESP_FIFO 0x08 +#define ESP_CMD 0x0c +#define ESP_WBUSID 0x10 +#define ESP_TCHI 0x38 + +#define ESP_RSTAT 0x10 +#define ESP_RINTR 0x14 +#define ESP_RFLAGS 0x1c + +#define ESP_DMA_CMD 0x40 +#define ESP_DMA_STC 0x44 +#define ESP_DMA_SPA 0x48 +#define ESP_DMA_WBC 0x4c +#define ESP_DMA_WAC 0x50 +#define ESP_DMA_STAT 0x54 +#define ESP_DMA_SMDLA 0x58 +#define ESP_DMA_WMAC 0x58c + +#define ESP_CMD_DMA 0x80 +#define ESP_CMD_RESET 0x02 +#define ESP_CMD_TI 0x10 +#define ESP_CMD_ICCS 0x11 +#define ESP_CMD_SELATN 0x42 + +#define ESP_STAT_DI 0x01 +#define ESP_STAT_CD 0x02 +#define ESP_STAT_MSG 0x04 +#define ESP_STAT_TC 0x10 + +#define ESP_INTR_DC 0x20 + +struct esp_lun_s { + struct drive_s drive; + struct pci_device *pci; + u32 iobase; + u8 target; + u8 lun; +}; + +static void +esp_scsi_dma(u32 iobase, u32 buf, u32 len, int read) +{ + outb(len & 0xff, iobase + ESP_TCLO); + outb((len >> 8) & 0xff, iobase + ESP_TCMID); + outb((len >> 16) & 0xff, iobase + ESP_TCHI); + outl(buf, iobase + ESP_DMA_SPA); + outl(len, iobase + ESP_DMA_STC); + outb(read ? 0x83 : 0x03, iobase + ESP_DMA_CMD); +} + +static int +esp_scsi_cmd(struct esp_lun_s *llun_gf, struct disk_op_s *op, + u8 *cdbcmd, u16 target, u16 lun, u16 blocksize) +{ + u32 iobase = GET_GLOBALFLAT(llun_gf->iobase); + int i, state; + u8 status; + + outb(target, iobase + ESP_WBUSID); + + /* + * We need to pass the LUN at the beginning of the command, and the FIFO + * is only 16 bytes, so we cannot support 16-byte CDBs. The alternative + * would be to use DMA for the 17-byte command too, which is quite + * overkill. + */ + outb(lun, iobase + ESP_FIFO); + cdbcmd[1] &= 0x1f; + cdbcmd[1] |= lun << 5; + for (i = 0; i < 12; i++) + outb(cdbcmd[i], iobase + ESP_FIFO); + outb(ESP_CMD_SELATN, iobase + ESP_CMD); + + for (state = 0;;) { + u8 stat = inb(iobase + ESP_RSTAT); + + /* Detect disconnected device. */ + if (state == 0 && (inb(iobase + ESP_RINTR) & ESP_INTR_DC)) { + return DISK_RET_ENOTREADY; + } + + /* HBA reads command, clears CD, sets TC -> do DMA if needed. */ + if (state == 0 && (stat & ESP_STAT_TC)) { + state++; + if (op->count && blocksize) { + /* Data phase. */ + u32 count = (u32)op->count * blocksize; + esp_scsi_dma(iobase, (u32)op->buf_fl, count, + cdb_is_read(cdbcmd, blocksize)); + outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD); + continue; + } + } + + /* At end of DMA TC is set again -> complete command. */ + if (state == 1 && (stat & ESP_STAT_TC)) { + state++; + outb(ESP_CMD_ICCS, iobase + ESP_CMD); + continue; + } + + /* Finally read data from the message in phase. */ + if (state == 2 && (stat & ESP_STAT_MSG)) { + state++; + status = inb(iobase + ESP_FIFO); + inb(iobase + ESP_FIFO); + break; + } + usleep(5); + } + + if (status == 0) { + return DISK_RET_SUCCESS; + } + + return DISK_RET_EBADTRACK; +} + +int +esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + if (!CONFIG_ESP_SCSI) + return DISK_RET_EBADTRACK; + + struct esp_lun_s *llun_gf = + container_of(op->drive_gf, struct esp_lun_s, drive); + + return esp_scsi_cmd(llun_gf, op, cdbcmd, + GET_GLOBALFLAT(llun_gf->target), + GET_GLOBALFLAT(llun_gf->lun), + blocksize); +} + +static int +esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) +{ + struct esp_lun_s *llun = malloc_fseg(sizeof(*llun)); + if (!llun) { + warn_noalloc(); + return -1; + } + memset(llun, 0, sizeof(*llun)); + llun->drive.type = DTYPE_ESP_SCSI; + llun->drive.cntl_id = pci->bdf; + llun->pci = pci; + llun->target = target; + llun->lun = lun; + llun->iobase = iobase; + + char *name = znprintf(16, "esp %02x:%02x.%x %d:%d", + pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), + pci_bdf_to_fn(pci->bdf), target, lun); + int prio = bootprio_find_scsi_device(pci, target, lun); + int ret = scsi_drive_setup(&llun->drive, name, prio); + free(name); + if (ret) + goto fail; + return 0; + +fail: + free(llun); + return -1; +} + +static void +esp_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target) +{ + esp_scsi_add_lun(pci, iobase, target, 0); +} + +static void +init_esp_scsi(struct pci_device *pci) +{ + u16 bdf = pci->bdf; + u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) + & PCI_BASE_ADDRESS_IO_MASK; + + dprintf(1, "found esp at %02x:%02x.%x, io @ %x\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), + pci_bdf_to_fn(bdf), iobase); + + pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + + // reset + outb(ESP_CMD_RESET, iobase + ESP_CMD); + + int i; + for (i = 0; i <= 7; i++) + esp_scsi_scan_target(pci, iobase, i); + + return; +} + +void +esp_scsi_setup(void) +{ + ASSERT32FLAT(); + if (!CONFIG_ESP_SCSI || !runningOnQEMU()) + return; + + dprintf(3, "init esp\n"); + + struct pci_device *pci; + foreachpci(pci) { + if (pci->vendor != PCI_VENDOR_ID_AMD + || pci->device != PCI_DEVICE_ID_AMD_SCSI) + continue; + init_esp_scsi(pci); + } +} diff -Nru seabios-1.7.1/src/hw/esp-scsi.h seabios-1.7.4/src/hw/esp-scsi.h --- seabios-1.7.1/src/hw/esp-scsi.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/esp-scsi.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef __ESP_SCSI_H +#define __ESP_SCSI_H + +struct disk_op_s; +int esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +void esp_scsi_setup(void); + +#endif /* __ESP_SCSI_H */ diff -Nru seabios-1.7.1/src/hw/floppy.c seabios-1.7.4/src/hw/floppy.c --- seabios-1.7.1/src/hw/floppy.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/floppy.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,689 @@ +// 16bit code to access floppy drives. +// +// Copyright (C) 2008,2009 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // SET_BDA +#include "block.h" // struct drive_s +#include "bregs.h" // struct bregs +#include "config.h" // CONFIG_FLOPPY +#include "malloc.h" // malloc_fseg +#include "output.h" // dprintf +#include "pci.h" // pci_to_bdf +#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA +#include "pic.h" // pic_eoi1 +#include "romfile.h" // romfile_loadint +#include "rtc.h" // rtc_read +#include "stacks.h" // yield +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // timer_calc + +#define PORT_FD_BASE 0x03f0 +#define PORT_FD_DOR 0x03f2 +#define PORT_FD_STATUS 0x03f4 +#define PORT_FD_DATA 0x03f5 +#define PORT_FD_DIR 0x03f7 + +#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors +#define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 +#define FLOPPY_MOTOR_TICKS 37 // ~2 seconds +#define FLOPPY_FILLBYTE 0xf6 +#define FLOPPY_GAPLEN 0x1B +#define FLOPPY_FORMAT_GAPLEN 0x6c +#define FLOPPY_PIO_TIMEOUT 1000 + +// New diskette parameter table adding 3 parameters from IBM +// Since no provisions are made for multiple drive types, most +// values in this table are ignored. I set parameters for 1.44M +// floppy here +struct floppy_ext_dbt_s diskette_param_table2 VARFSEG = { + .dbt = { + .specify1 = 0xAF, // step rate 12ms, head unload 240ms + .specify2 = 0x02, // head load time 4ms, DMA used + .shutoff_ticks = FLOPPY_MOTOR_TICKS, // ~2 seconds + .bps_code = FLOPPY_SIZE_CODE, + .sectors = 18, + .interblock_len = FLOPPY_GAPLEN, + .data_len = FLOPPY_DATALEN, + .gap_len = FLOPPY_FORMAT_GAPLEN, + .fill_byte = FLOPPY_FILLBYTE, + .settle_time = 0x0F, // 15ms + .startup_time = 0x08, // 1 second + }, + .max_track = 79, // maximum track + .data_rate = 0, // data transfer rate + .drive_type = 4, // drive type in cmos +}; + +struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7); + +struct floppyinfo_s { + struct chs_s chs; + u8 floppy_size; + u8 data_rate; +}; + +#define FLOPPY_SIZE_525 0x01 +#define FLOPPY_SIZE_350 0x02 + +#define FLOPPY_RATE_500K 0x00 +#define FLOPPY_RATE_300K 0x01 +#define FLOPPY_RATE_250K 0x02 +#define FLOPPY_RATE_1M 0x03 + +struct floppyinfo_s FloppyInfo[] VARFSEG = { + // Unknown + { {0, 0, 0}, 0x00, 0x00}, + // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors + { {2, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K}, + // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors + { {2, 80, 15}, FLOPPY_SIZE_525, FLOPPY_RATE_500K}, + // 3 - 720KB, 3.5" - 2 heads, 80 tracks, 9 sectors + { {2, 80, 9}, FLOPPY_SIZE_350, FLOPPY_RATE_250K}, + // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors + { {2, 80, 18}, FLOPPY_SIZE_350, FLOPPY_RATE_500K}, + // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors + { {2, 80, 36}, FLOPPY_SIZE_350, FLOPPY_RATE_1M}, + // 6 - 160k, 5.25" - 1 heads, 40 tracks, 8 sectors + { {1, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K}, + // 7 - 180k, 5.25" - 1 heads, 40 tracks, 9 sectors + { {1, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K}, + // 8 - 320k, 5.25" - 2 heads, 40 tracks, 8 sectors + { {2, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K}, +}; + +struct drive_s * +init_floppy(int floppyid, int ftype) +{ + if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) { + dprintf(1, "Bad floppy type %d\n", ftype); + return NULL; + } + + struct drive_s *drive = malloc_fseg(sizeof(*drive)); + if (!drive) { + warn_noalloc(); + return NULL; + } + memset(drive, 0, sizeof(*drive)); + drive->cntl_id = floppyid; + drive->type = DTYPE_FLOPPY; + drive->blksize = DISK_SECTOR_SIZE; + drive->floppy_type = ftype; + drive->sectors = (u64)-1; + + memcpy(&drive->lchs, &FloppyInfo[ftype].chs + , sizeof(FloppyInfo[ftype].chs)); + return drive; +} + +static void +addFloppy(int floppyid, int ftype) +{ + struct drive_s *drive = init_floppy(floppyid, ftype); + if (!drive) + return; + char *desc = znprintf(MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid); + struct pci_device *pci = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */ + int prio = bootprio_find_fdc_device(pci, PORT_FD_BASE, floppyid); + boot_add_floppy(drive, desc, prio); +} + +void +floppy_setup(void) +{ + memcpy(&diskette_param_table, &diskette_param_table2 + , sizeof(diskette_param_table)); + SET_IVT(0x1E, SEGOFF(SEG_BIOS + , (u32)&diskette_param_table2 - BUILD_BIOS_ADDR)); + + if (! CONFIG_FLOPPY) + return; + dprintf(3, "init floppy drives\n"); + + if (CONFIG_QEMU) { + u8 type = rtc_read(CMOS_FLOPPY_DRIVE_TYPE); + if (type & 0xf0) + addFloppy(0, type >> 4); + if (type & 0x0f) + addFloppy(1, type & 0x0f); + } else { + u8 type = romfile_loadint("etc/floppy0", 0); + if (type) + addFloppy(0, type); + type = romfile_loadint("etc/floppy1", 0); + if (type) + addFloppy(1, type); + } + + enable_hwirq(6, FUNC16(entry_0e)); +} + +// Find a floppy type that matches a given image size. +int +find_floppy_type(u32 size) +{ + int i; + for (i=1; icylinder * c->head * c->sector * DISK_SECTOR_SIZE == size) + return i; + } + return -1; +} + + +/**************************************************************** + * Low-level floppy IO + ****************************************************************/ + +u8 FloppyDOR VARLOW; + +static inline void +floppy_dor_write(u8 val) +{ + outb(val, PORT_FD_DOR); + SET_LOW(FloppyDOR, val); +} + +static void +floppy_disable_controller(void) +{ + dprintf(2, "Floppy_disable_controller\n"); + floppy_dor_write(0x00); +} + +static int +floppy_wait_irq(void) +{ + u8 frs = GET_BDA(floppy_recalibration_status); + SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ); + for (;;) { + if (!GET_BDA(floppy_motor_counter)) { + warn_timeout(); + floppy_disable_controller(); + return DISK_RET_ETIMEOUT; + } + frs = GET_BDA(floppy_recalibration_status); + if (frs & FRS_IRQ) + break; + // Could use yield_toirq() here, but that causes issues on + // bochs, so use yield() instead. + yield(); + } + + SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ); + return DISK_RET_SUCCESS; +} + +// Floppy commands +#define FCF_WAITIRQ 0x10000 +#define FC_CHECKIRQ (0x08 | (0<<8) | (2<<12)) +#define FC_SEEK (0x0f | (2<<8) | (0<<12) | FCF_WAITIRQ) +#define FC_RECALIBRATE (0x07 | (1<<8) | (0<<12) | FCF_WAITIRQ) +#define FC_READID (0x4a | (1<<8) | (7<<12) | FCF_WAITIRQ) +#define FC_READ (0xe6 | (8<<8) | (7<<12) | FCF_WAITIRQ) +#define FC_WRITE (0xc5 | (8<<8) | (7<<12) | FCF_WAITIRQ) +#define FC_FORMAT (0x4d | (5<<8) | (7<<12) | FCF_WAITIRQ) + +// Send the specified command and it's parameters to the floppy controller. +static int +floppy_pio(int command, u8 *param) +{ + dprintf(9, "Floppy pio command %x\n", command); + // Send command and parameters to controller. + u32 end = timer_calc(FLOPPY_PIO_TIMEOUT); + int send = (command >> 8) & 0xf; + int i = 0; + for (;;) { + u8 sts = inb(PORT_FD_STATUS); + if (!(sts & 0x80)) { + if (timer_check(end)) { + warn_timeout(); + floppy_disable_controller(); + return DISK_RET_ETIMEOUT; + } + continue; + } + if (sts & 0x40) { + floppy_disable_controller(); + return DISK_RET_ECONTROLLER; + } + if (i == 0) + outb(command & 0xff, PORT_FD_DATA); + else + outb(param[i-1], PORT_FD_DATA); + if (i++ >= send) + break; + } + + // Wait for command to complete. + if (command & FCF_WAITIRQ) { + int ret = floppy_wait_irq(); + if (ret) + return ret; + } + + // Read response from controller. + end = timer_calc(FLOPPY_PIO_TIMEOUT); + int receive = (command >> 12) & 0xf; + i = 0; + for (;;) { + u8 sts = inb(PORT_FD_STATUS); + if (!(sts & 0x80)) { + if (timer_check(end)) { + warn_timeout(); + floppy_disable_controller(); + return DISK_RET_ETIMEOUT; + } + continue; + } + if (i >= receive) { + if (sts & 0x40) { + floppy_disable_controller(); + return DISK_RET_ECONTROLLER; + } + break; + } + if (!(sts & 0x40)) { + floppy_disable_controller(); + return DISK_RET_ECONTROLLER; + } + param[i++] = inb(PORT_FD_DATA); + } + + return DISK_RET_SUCCESS; +} + +static int +floppy_enable_controller(void) +{ + dprintf(2, "Floppy_enable_controller\n"); + SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS); + floppy_dor_write(0x00); + floppy_dor_write(0x0c); + int ret = floppy_wait_irq(); + if (ret) + return ret; + + u8 param[2]; + return floppy_pio(FC_CHECKIRQ, param); +} + +// Activate a drive and send a command to it. +static int +floppy_drive_pio(u8 floppyid, int command, u8 *param) +{ + // Enable controller if it isn't running. + if (!(GET_LOW(FloppyDOR) & 0x04)) { + int ret = floppy_enable_controller(); + if (ret) + return ret; + } + + // reset the disk motor timeout value of INT 08 + SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS); + + // Turn on motor of selected drive, DMA & int enabled, normal operation + floppy_dor_write((floppyid ? 0x20 : 0x10) | 0x0c | floppyid); + + // Send command. + int ret = floppy_pio(command, param); + if (ret) + return ret; + + // Check IRQ command is needed after irq commands with no results + if ((command & FCF_WAITIRQ) && ((command >> 12) & 0xf) == 0) + return floppy_pio(FC_CHECKIRQ, param); + return DISK_RET_SUCCESS; +} + + +/**************************************************************** + * Floppy media sense and seeking + ****************************************************************/ + +static int +floppy_drive_recal(u8 floppyid) +{ + dprintf(2, "Floppy_drive_recal %d\n", floppyid); + // send Recalibrate command to controller + u8 param[2]; + param[0] = floppyid; + int ret = floppy_drive_pio(floppyid, FC_RECALIBRATE, param); + if (ret) + return ret; + + u8 frs = GET_BDA(floppy_recalibration_status); + SET_BDA(floppy_recalibration_status, frs | (1<floppy_type), stype = ftype; + u8 floppyid = GET_GLOBALFLAT(drive_gf->cntl_id); + + u8 data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate); + int ret = floppy_drive_readid(floppyid, data_rate, 0); + if (ret) { + // Attempt media sense. + for (stype=1; ; stype++) { + if (stype >= ARRAY_SIZE(FloppyInfo)) + return DISK_RET_EMEDIA; + if (stype==ftype + || (GET_GLOBAL(FloppyInfo[stype].floppy_size) + != GET_GLOBAL(FloppyInfo[ftype].floppy_size)) + || (GET_GLOBAL(FloppyInfo[stype].chs.head) + > GET_GLOBAL(FloppyInfo[ftype].chs.head)) + || (GET_GLOBAL(FloppyInfo[stype].chs.cylinder) + > GET_GLOBAL(FloppyInfo[ftype].chs.cylinder)) + || (GET_GLOBAL(FloppyInfo[stype].chs.sector) + > GET_GLOBAL(FloppyInfo[ftype].chs.sector))) + continue; + data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate); + ret = floppy_drive_readid(floppyid, data_rate, 0); + if (!ret) + break; + } + } + dprintf(2, "Floppy_media_sense on drive %d found rate %d\n" + , floppyid, data_rate); + + u8 old_data_rate = GET_BDA(floppy_media_state[floppyid]) >> 6; + SET_BDA(floppy_last_data_rate, (old_data_rate<<2) | (data_rate<<6)); + u8 media = (stype == 1 ? 0x04 : (stype == 2 ? 0x05 : 0x07)); + u8 fms = (data_rate<<6) | FMS_MEDIA_DRIVE_ESTABLISHED | media; + if (GET_GLOBAL(FloppyInfo[stype].chs.cylinder) + < GET_GLOBAL(FloppyInfo[ftype].chs.cylinder)) + fms |= FMS_DOUBLE_STEPPING; + SET_BDA(floppy_media_state[floppyid], fms); + + return DISK_RET_SUCCESS; +} + +// Prepare a floppy for a data transfer. +static int +floppy_prep(struct drive_s *drive_gf, u8 cylinder) +{ + u8 floppyid = GET_GLOBALFLAT(drive_gf->cntl_id); + if (!(GET_BDA(floppy_recalibration_status) & (1<buf_fl, count, isWrite); + if (ret) + return DISK_RET_EBOUNDARY; + + // Invoke floppy controller + u8 floppyid = GET_GLOBALFLAT(op->drive_gf->cntl_id); + ret = floppy_drive_pio(floppyid, command, param); + if (ret) + return ret; + + // Populate floppy_return_status in BDA + int i; + for (i=0; i<7; i++) + SET_BDA(floppy_return_status[i], param[i]); + + if (param[0] & 0xc0) { + if (param[1] & 0x02) + return DISK_RET_EWRITEPROTECT; + dprintf(1, "floppy error: %02x %02x %02x %02x %02x %02x %02x\n" + , param[0], param[1], param[2], param[3] + , param[4], param[5], param[6]); + return DISK_RET_ECONTROLLER; + } + + return DISK_RET_SUCCESS; +} + + +/**************************************************************** + * Floppy handlers + ****************************************************************/ + +static struct chs_s +lba2chs(struct disk_op_s *op) +{ + struct chs_s res = { }; + + u32 tmp = op->lba; + u16 nls = GET_GLOBALFLAT(op->drive_gf->lchs.sector); + res.sector = (tmp % nls) + 1; + + tmp /= nls; + u16 nlh = GET_GLOBALFLAT(op->drive_gf->lchs.head); + res.head = tmp % nlh; + + tmp /= nlh; + res.cylinder = tmp; + + return res; +} + +// diskette controller reset +static int +floppy_reset(struct disk_op_s *op) +{ + SET_BDA(floppy_recalibration_status, 0); + SET_BDA(floppy_media_state[0], 0); + SET_BDA(floppy_media_state[1], 0); + SET_BDA(floppy_track[0], 0); + SET_BDA(floppy_track[1], 0); + SET_BDA(floppy_last_data_rate, 0); + floppy_disable_controller(); + return floppy_enable_controller(); +} + +// Read Diskette Sectors +static int +floppy_read(struct disk_op_s *op) +{ + struct chs_s chs = lba2chs(op); + int res = floppy_prep(op->drive_gf, chs.cylinder); + if (res) + goto fail; + + // send read-normal-data command to controller + u8 floppyid = GET_GLOBALFLAT(op->drive_gf->cntl_id); + u8 param[8]; + param[0] = (chs.head << 2) | floppyid; // HD DR1 DR2 + param[1] = chs.cylinder; + param[2] = chs.head; + param[3] = chs.sector; + param[4] = FLOPPY_SIZE_CODE; + param[5] = chs.sector + op->count - 1; // last sector to read on track + param[6] = FLOPPY_GAPLEN; + param[7] = FLOPPY_DATALEN; + res = floppy_dma_cmd(op, op->count * DISK_SECTOR_SIZE, FC_READ, param); + if (res) + goto fail; + return DISK_RET_SUCCESS; +fail: + op->count = 0; // no sectors read + return res; +} + +// Write Diskette Sectors +static int +floppy_write(struct disk_op_s *op) +{ + struct chs_s chs = lba2chs(op); + int res = floppy_prep(op->drive_gf, chs.cylinder); + if (res) + goto fail; + + // send write-normal-data command to controller + u8 floppyid = GET_GLOBALFLAT(op->drive_gf->cntl_id); + u8 param[8]; + param[0] = (chs.head << 2) | floppyid; // HD DR1 DR2 + param[1] = chs.cylinder; + param[2] = chs.head; + param[3] = chs.sector; + param[4] = FLOPPY_SIZE_CODE; + param[5] = chs.sector + op->count - 1; // last sector to write on track + param[6] = FLOPPY_GAPLEN; + param[7] = FLOPPY_DATALEN; + res = floppy_dma_cmd(op, op->count * DISK_SECTOR_SIZE, FC_WRITE, param); + if (res) + goto fail; + return DISK_RET_SUCCESS; +fail: + op->count = 0; // no sectors read + return res; +} + +// Verify Diskette Sectors +static int +floppy_verify(struct disk_op_s *op) +{ + struct chs_s chs = lba2chs(op); + int res = floppy_prep(op->drive_gf, chs.cylinder); + if (res) + goto fail; + + // This command isn't implemented - just return success. + return DISK_RET_SUCCESS; +fail: + op->count = 0; // no sectors read + return res; +} + +// format diskette track +static int +floppy_format(struct disk_op_s *op) +{ + struct chs_s chs = lba2chs(op); + int res = floppy_prep(op->drive_gf, chs.cylinder); + if (res) + return res; + + // send format-track command to controller + u8 floppyid = GET_GLOBALFLAT(op->drive_gf->cntl_id); + u8 param[7]; + param[0] = (chs.head << 2) | floppyid; // HD DR1 DR2 + param[1] = FLOPPY_SIZE_CODE; + param[2] = op->count; // number of sectors per track + param[3] = FLOPPY_FORMAT_GAPLEN; + param[4] = FLOPPY_FILLBYTE; + return floppy_dma_cmd(op, op->count * 4, FC_FORMAT, param); +} + +int +process_floppy_op(struct disk_op_s *op) +{ + if (!CONFIG_FLOPPY) + return 0; + + switch (op->command) { + case CMD_RESET: + return floppy_reset(op); + case CMD_READ: + return floppy_read(op); + case CMD_WRITE: + return floppy_write(op); + case CMD_VERIFY: + return floppy_verify(op); + case CMD_FORMAT: + return floppy_format(op); + default: + op->count = 0; + return DISK_RET_EPARAM; + } +} + + +/**************************************************************** + * HW irqs + ****************************************************************/ + +// INT 0Eh Diskette Hardware ISR Entry Point +void VISIBLE16 +handle_0e(void) +{ + if (! CONFIG_FLOPPY) + return; + debug_isr(DEBUG_ISR_0e); + + // diskette interrupt has occurred + u8 frs = GET_BDA(floppy_recalibration_status); + SET_BDA(floppy_recalibration_status, frs | FRS_IRQ); + + pic_eoi1(); +} + +// Called from int08 handler. +void +floppy_tick(void) +{ + if (! CONFIG_FLOPPY) + return; + + // time to turn off drive(s)? + u8 fcount = GET_BDA(floppy_motor_counter); + if (fcount) { + fcount--; + SET_BDA(floppy_motor_counter, fcount); + if (fcount == 0) + // turn motor(s) off + floppy_dor_write(GET_LOW(FloppyDOR) & ~0xf0); + } +} diff -Nru seabios-1.7.1/src/hw/lsi-scsi.c seabios-1.7.4/src/hw/lsi-scsi.c --- seabios-1.7.1/src/hw/lsi-scsi.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/lsi-scsi.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,217 @@ +// (qemu-emulated) lsi53c895a boot support. +// +// Copyright (C) 2012 Red Hat Inc. +// +// Authors: +// Gerd Hoffmann +// +// based on virtio-scsi.c which is written by: +// Paolo Bonzini +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct drive_s +#include "blockcmd.h" // scsi_drive_setup +#include "config.h" // CONFIG_* +#include "fw/paravirt.h" // runningOnQEMU +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK +#include "pci_regs.h" // PCI_VENDOR_ID +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // usleep + +#define LSI_REG_DSTAT 0x0c +#define LSI_REG_ISTAT0 0x14 +#define LSI_REG_DSP0 0x2c +#define LSI_REG_DSP1 0x2d +#define LSI_REG_DSP2 0x2e +#define LSI_REG_DSP3 0x2f +#define LSI_REG_SIST0 0x42 +#define LSI_REG_SIST1 0x43 + +#define LSI_ISTAT0_DIP 0x01 +#define LSI_ISTAT0_SIP 0x02 +#define LSI_ISTAT0_INTF 0x04 +#define LSI_ISTAT0_CON 0x08 +#define LSI_ISTAT0_SEM 0x10 +#define LSI_ISTAT0_SIGP 0x20 +#define LSI_ISTAT0_SRST 0x40 +#define LSI_ISTAT0_ABRT 0x80 + +struct lsi_lun_s { + struct drive_s drive; + struct pci_device *pci; + u32 iobase; + u8 target; + u8 lun; +}; + +static int +lsi_scsi_cmd(struct lsi_lun_s *llun_gf, struct disk_op_s *op, + void *cdbcmd, u16 target, u16 lun, u16 blocksize) +{ + u32 iobase = GET_GLOBALFLAT(llun_gf->iobase); + u32 dma = ((cdb_is_read(cdbcmd, blocksize) ? 0x01000000 : 0x00000000) | + (op->count * blocksize)); + u8 msgout[] = { + 0x80 | lun, // select lun + 0x08, + }; + u8 status = 0xff; + u8 msgin_tmp[2]; + u8 msgin = 0xff; + + u32 script[] = { + /* select target, send scsi command */ + 0x40000000 | target << 16, // select target + 0x00000000, + 0x06000001, // msgout + (u32)MAKE_FLATPTR(GET_SEG(SS), &msgout), + 0x02000010, // scsi command + (u32)MAKE_FLATPTR(GET_SEG(SS), cdbcmd), + + /* handle disconnect */ + 0x87820000, // phase == msgin ? + 0x00000018, + 0x07000002, // msgin + (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp), + 0x50000000, // re-select + 0x00000000, + 0x07000002, // msgin + (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp), + + /* dma data, get status, raise irq */ + dma, // dma data + (u32)op->buf_fl, + 0x03000001, // status + (u32)MAKE_FLATPTR(GET_SEG(SS), &status), + 0x07000001, // msgin + (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin), + 0x98080000, // dma irq + 0x00000000, + }; + u32 dsp = (u32)MAKE_FLATPTR(GET_SEG(SS), &script); + + outb(dsp & 0xff, iobase + LSI_REG_DSP0); + outb((dsp >> 8) & 0xff, iobase + LSI_REG_DSP1); + outb((dsp >> 16) & 0xff, iobase + LSI_REG_DSP2); + outb((dsp >> 24) & 0xff, iobase + LSI_REG_DSP3); + + for (;;) { + u8 dstat = inb(iobase + LSI_REG_DSTAT); + u8 sist0 = inb(iobase + LSI_REG_SIST0); + u8 sist1 = inb(iobase + LSI_REG_SIST1); + if (sist0 || sist1) { + goto fail; + } + if (dstat & 0x04) { + break; + } + usleep(5); + } + + if (msgin == 0 && status == 0) { + return DISK_RET_SUCCESS; + } + +fail: + return DISK_RET_EBADTRACK; +} + +int +lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + if (!CONFIG_LSI_SCSI) + return DISK_RET_EBADTRACK; + + struct lsi_lun_s *llun_gf = + container_of(op->drive_gf, struct lsi_lun_s, drive); + + return lsi_scsi_cmd(llun_gf, op, cdbcmd, + GET_GLOBALFLAT(llun_gf->target), + GET_GLOBALFLAT(llun_gf->lun), + blocksize); +} + +static int +lsi_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) +{ + struct lsi_lun_s *llun = malloc_fseg(sizeof(*llun)); + if (!llun) { + warn_noalloc(); + return -1; + } + memset(llun, 0, sizeof(*llun)); + llun->drive.type = DTYPE_LSI_SCSI; + llun->drive.cntl_id = pci->bdf; + llun->pci = pci; + llun->target = target; + llun->lun = lun; + llun->iobase = iobase; + + char *name = znprintf(16, "lsi %02x:%02x.%x %d:%d", + pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), + pci_bdf_to_fn(pci->bdf), target, lun); + int prio = bootprio_find_scsi_device(pci, target, lun); + int ret = scsi_drive_setup(&llun->drive, name, prio); + free(name); + if (ret) + goto fail; + return 0; + +fail: + free(llun); + return -1; +} + +static void +lsi_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target) +{ + /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ + lsi_scsi_add_lun(pci, iobase, target, 0); +} + +static void +init_lsi_scsi(struct pci_device *pci) +{ + u16 bdf = pci->bdf; + u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) + & PCI_BASE_ADDRESS_IO_MASK; + + pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + + dprintf(1, "found lsi53c895a at %02x:%02x.%x, io @ %x\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), + pci_bdf_to_fn(bdf), iobase); + + // reset + outb(LSI_ISTAT0_SRST, iobase + LSI_REG_ISTAT0); + + int i; + for (i = 0; i < 7; i++) + lsi_scsi_scan_target(pci, iobase, i); + + return; +} + +void +lsi_scsi_setup(void) +{ + ASSERT32FLAT(); + if (!CONFIG_LSI_SCSI || !runningOnQEMU()) + return; + + dprintf(3, "init lsi53c895a\n"); + + struct pci_device *pci; + foreachpci(pci) { + if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC + || pci->device != PCI_DEVICE_ID_LSI_53C895A) + continue; + init_lsi_scsi(pci); + } +} diff -Nru seabios-1.7.1/src/hw/lsi-scsi.h seabios-1.7.4/src/hw/lsi-scsi.h --- seabios-1.7.1/src/hw/lsi-scsi.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/lsi-scsi.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef __LSI_SCSI_H +#define __LSI_SCSI_H + +struct disk_op_s; +int lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +void lsi_scsi_setup(void); + +#endif /* __LSI_SCSI_H */ diff -Nru seabios-1.7.1/src/hw/megasas.c seabios-1.7.4/src/hw/megasas.c --- seabios-1.7.1/src/hw/megasas.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/megasas.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,400 @@ +// MegaRAID SAS boot support. +// +// Copyright (C) 2012 Hannes Reinecke, SUSE Linux Products GmbH +// +// Authors: +// Hannes Reinecke +// +// based on virtio-scsi.c which is written by: +// Paolo Bonzini +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct drive_s +#include "blockcmd.h" // scsi_drive_setup +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_DEVICE_ID_XXX +#include "pci_regs.h" // PCI_VENDOR_ID +#include "stacks.h" // yield +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // timer_calc + +#define MFI_DB 0x0 // Doorbell +#define MFI_OMSG0 0x18 // Outbound message 0 +#define MFI_IDB 0x20 // Inbound doorbell +#define MFI_ODB 0x2c // Outbound doorbell +#define MFI_IQP 0x40 // Inbound queue port +#define MFI_OSP0 0xb0 // Outbound scratch pad0 +#define MFI_IQPL 0xc0 // Inbound queue port (low bytes) +#define MFI_IQPH 0xc4 // Inbound queue port (high bytes) + +#define MFI_STATE_MASK 0xf0000000 +#define MFI_STATE_WAIT_HANDSHAKE 0x60000000 +#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000 +#define MFI_STATE_READY 0xb0000000 +#define MFI_STATE_OPERATIONAL 0xc0000000 +#define MFI_STATE_FAULT 0xf0000000 + +/* MFI Commands */ +typedef enum { + MFI_CMD_INIT = 0x00, + MFI_CMD_LD_READ, + MFI_CMD_LD_WRITE, + MFI_CMD_LD_SCSI_IO, + MFI_CMD_PD_SCSI_IO, + MFI_CMD_DCMD, + MFI_CMD_ABORT, + MFI_CMD_SMP, + MFI_CMD_STP +} mfi_cmd_t; + +struct megasas_cmd_frame { + u8 cmd; /*00h */ + u8 sense_len; /*01h */ + u8 cmd_status; /*02h */ + u8 scsi_status; /*03h */ + + u8 target_id; /*04h */ + u8 lun; /*05h */ + u8 cdb_len; /*06h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 context_64; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + u32 data_xfer_len; /*14h */ + + union { + struct { + u32 opcode; /*18h */ + u8 mbox[12]; /*1Ch */ + u32 sgl_addr; /*28h */ + u32 sgl_len; /*32h */ + u32 pad; /*34h */ + } dcmd; + struct { + u32 sense_buf_lo; /*18h */ + u32 sense_buf_hi; /*1Ch */ + u8 cdb[16]; /*20h */ + u32 sgl_addr; /*30h */ + u32 sgl_len; /*34h */ + } pthru; + struct { + u8 pad[22]; /*18h */ + } gen; + }; +} __attribute__ ((packed)); + +struct mfi_ld_list_s { + u32 count; + u32 reserved_0; + struct { + u8 target; + u8 lun; + u16 seq; + u8 state; + u8 reserved_1[3]; + u64 size; + } lds[64]; +} __attribute__ ((packed)); + +#define MEGASAS_POLL_TIMEOUT 60000 // 60 seconds polling timeout + +struct megasas_lun_s { + struct drive_s drive; + struct megasas_cmd_frame *frame; + u32 iobase; + u16 pci_id; + u8 target; + u8 lun; +}; + +static int megasas_fire_cmd(u16 pci_id, u32 ioaddr, + struct megasas_cmd_frame *frame) +{ + u32 frame_addr = (u32)frame; + int frame_count = 1; + u8 cmd_state; + + dprintf(2, "Frame 0x%x\n", frame_addr); + if (pci_id == PCI_DEVICE_ID_LSI_SAS2004 || + pci_id == PCI_DEVICE_ID_LSI_SAS2008) { + outl(0, ioaddr + MFI_IQPH); + outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQPL); + } else if (pci_id == PCI_DEVICE_ID_DELL_PERC5 || + pci_id == PCI_DEVICE_ID_LSI_SAS1064R || + pci_id == PCI_DEVICE_ID_LSI_VERDE_ZCR) { + outl(frame_addr >> 3 | frame_count, ioaddr + MFI_IQP); + } else { + outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQP); + } + + u32 end = timer_calc(MEGASAS_POLL_TIMEOUT); + do { + for (;;) { + cmd_state = GET_LOWFLAT(frame->cmd_status); + if (cmd_state != 0xff) + break; + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } + } while (cmd_state == 0xff); + + if (cmd_state == 0 || cmd_state == 0x2d) + return 0; + dprintf(1, "ERROR: Frame 0x%x, status 0x%x\n", frame_addr, cmd_state); + return -1; +} + +int +megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + struct megasas_lun_s *mlun_gf = + container_of(op->drive_gf, struct megasas_lun_s, drive); + u8 *cdb = cdbcmd; + struct megasas_cmd_frame *frame = GET_GLOBALFLAT(mlun_gf->frame); + u16 pci_id = GET_GLOBALFLAT(mlun_gf->pci_id); + int i; + + if (!CONFIG_MEGASAS) + return DISK_RET_EBADTRACK; + + memset_fl(frame, 0, sizeof(*frame)); + SET_LOWFLAT(frame->cmd, MFI_CMD_LD_SCSI_IO); + SET_LOWFLAT(frame->cmd_status, 0xFF); + SET_LOWFLAT(frame->target_id, GET_GLOBALFLAT(mlun_gf->target)); + SET_LOWFLAT(frame->lun, GET_GLOBALFLAT(mlun_gf->lun)); + SET_LOWFLAT(frame->flags, 0x0001); + SET_LOWFLAT(frame->data_xfer_len, op->count * blocksize); + SET_LOWFLAT(frame->cdb_len, 16); + + for (i = 0; i < 16; i++) { + SET_LOWFLAT(frame->pthru.cdb[i], cdb[i]); + } + dprintf(2, "pthru cmd 0x%x count %d bs %d\n", + cdb[0], op->count, blocksize); + + if (op->count) { + SET_LOWFLAT(frame->pthru.sgl_addr, (u32)op->buf_fl); + SET_LOWFLAT(frame->pthru.sgl_len, op->count * blocksize); + SET_LOWFLAT(frame->sge_count, 1); + } + SET_LOWFLAT(frame->context, (u32)frame); + + if (megasas_fire_cmd(pci_id, GET_GLOBALFLAT(mlun_gf->iobase), frame) == 0) + return DISK_RET_SUCCESS; + + dprintf(2, "pthru cmd 0x%x failed\n", cdb[0]); + return DISK_RET_EBADTRACK; +} + +static int +megasas_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) +{ + struct megasas_lun_s *mlun = malloc_fseg(sizeof(*mlun)); + char *name; + int prio, ret = 0; + + if (!mlun) { + warn_noalloc(); + return -1; + } + memset(mlun, 0, sizeof(*mlun)); + mlun->drive.type = DTYPE_MEGASAS; + mlun->drive.cntl_id = pci->bdf; + mlun->pci_id = pci->device; + mlun->target = target; + mlun->lun = lun; + mlun->iobase = iobase; + mlun->frame = memalign_low(256, sizeof(struct megasas_cmd_frame)); + if (!mlun->frame) { + warn_noalloc(); + free(mlun); + return -1; + } + name = znprintf(36, "MegaRAID SAS (PCI %02x:%02x.%x) LD %d:%d", + pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), + pci_bdf_to_fn(pci->bdf), target, lun); + prio = bootprio_find_scsi_device(pci, target, lun); + ret = scsi_drive_setup(&mlun->drive, name, prio); + free(name); + if (ret) { + free(mlun->frame); + free(mlun); + ret = -1; + } + + return ret; +} + +static void megasas_scan_target(struct pci_device *pci, u32 iobase) +{ + struct mfi_ld_list_s ld_list; + struct megasas_cmd_frame *frame = memalign_tmp(256, sizeof(*frame)); + int i; + + memset(&ld_list, 0, sizeof(ld_list)); + memset_fl(frame, 0, sizeof(*frame)); + + frame->cmd = MFI_CMD_DCMD; + frame->cmd_status = 0xFF; + frame->sge_count = 1; + frame->flags = 0x0011; + frame->data_xfer_len = sizeof(ld_list); + frame->dcmd.opcode = 0x03010000; + frame->dcmd.sgl_addr = (u32)MAKE_FLATPTR(GET_SEG(SS), &ld_list); + frame->dcmd.sgl_len = sizeof(ld_list); + frame->context = (u32)frame; + + if (megasas_fire_cmd(pci->device, iobase, frame) == 0) { + dprintf(2, "%d LD found\n", ld_list.count); + for (i = 0; i < ld_list.count; i++) { + dprintf(2, "LD %d:%d state 0x%x\n", + ld_list.lds[i].target, ld_list.lds[i].lun, + ld_list.lds[i].state); + if (ld_list.lds[i].state != 0) { + megasas_add_lun(pci, iobase, + ld_list.lds[i].target, ld_list.lds[i].lun); + } + } + } +} + +static int megasas_transition_to_ready(struct pci_device *pci, u32 ioaddr) +{ + u32 fw_state = 0, new_state, mfi_flags = 0; + + if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R || + pci->device == PCI_DEVICE_ID_DELL_PERC5) + new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK; + else + new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK; + + while (fw_state != new_state) { + switch (new_state) { + case MFI_STATE_FAULT: + dprintf(1, "ERROR: fw in fault state\n"); + return -1; + break; + case MFI_STATE_WAIT_HANDSHAKE: + mfi_flags = 0x08; + /* fallthrough */ + case MFI_STATE_BOOT_MESSAGE_PENDING: + mfi_flags |= 0x10; + if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 || + pci->device == PCI_DEVICE_ID_LSI_SAS2008 || + pci->device == PCI_DEVICE_ID_LSI_SAS2208 || + pci->device == PCI_DEVICE_ID_LSI_SAS3108) { + outl(ioaddr + MFI_DB, mfi_flags); + } else { + outl(ioaddr + MFI_IDB, mfi_flags); + } + break; + case MFI_STATE_OPERATIONAL: + mfi_flags = 0x07; + if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 || + pci->device == PCI_DEVICE_ID_LSI_SAS2008 || + pci->device == PCI_DEVICE_ID_LSI_SAS2208 || + pci->device == PCI_DEVICE_ID_LSI_SAS3108) { + outl(ioaddr + MFI_DB, mfi_flags); + if (pci->device == PCI_DEVICE_ID_LSI_SAS2208 || + pci->device == PCI_DEVICE_ID_LSI_SAS3108) { + int j = 0; + u32 doorbell; + + while (j < MEGASAS_POLL_TIMEOUT) { + doorbell = inl(ioaddr + MFI_DB) & 1; + if (!doorbell) + break; + msleep(20); + j++; + } + } + } else { + outw(ioaddr + MFI_IDB, mfi_flags); + } + break; + case MFI_STATE_READY: + dprintf(2, "MegaRAID SAS fw ready\n"); + return 0; + } + // The current state should not last longer than poll timeout + u32 end = timer_calc(MEGASAS_POLL_TIMEOUT); + for (;;) { + if (timer_check(end)) { + break; + } + yield(); + fw_state = new_state; + if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R || + pci->device == PCI_DEVICE_ID_DELL_PERC5) + new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK; + else + new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK; + if (new_state != fw_state) { + break; + } + } + } + dprintf(1, "ERROR: fw in state %x\n", new_state & MFI_STATE_MASK); + return -1; +} + +static void +init_megasas(struct pci_device *pci) +{ + u16 bdf = pci->bdf; + u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_2) + & PCI_BASE_ADDRESS_IO_MASK; + + dprintf(1, "found MegaRAID SAS at %02x:%02x.%x, io @ %x\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), + pci_bdf_to_fn(bdf), iobase); + + pci_config_maskw(pci->bdf, PCI_COMMAND, 0, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + // reset + if (megasas_transition_to_ready(pci, iobase) == 0) + megasas_scan_target(pci, iobase); + + return; +} + +void +megasas_setup(void) +{ + ASSERT32FLAT(); + if (!CONFIG_MEGASAS) + return; + + dprintf(3, "init megasas\n"); + + struct pci_device *pci; + foreachpci(pci) { + if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC && + pci->vendor != PCI_VENDOR_ID_DELL) + continue; + if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R || + pci->device == PCI_DEVICE_ID_LSI_SAS1078 || + pci->device == PCI_DEVICE_ID_LSI_SAS1078DE || + pci->device == PCI_DEVICE_ID_LSI_SAS2108 || + pci->device == PCI_DEVICE_ID_LSI_SAS2108E || + pci->device == PCI_DEVICE_ID_LSI_SAS2004 || + pci->device == PCI_DEVICE_ID_LSI_SAS2008 || + pci->device == PCI_DEVICE_ID_LSI_VERDE_ZCR || + pci->device == PCI_DEVICE_ID_DELL_PERC5 || + pci->device == PCI_DEVICE_ID_LSI_SAS2208 || + pci->device == PCI_DEVICE_ID_LSI_SAS3108) + init_megasas(pci); + } +} diff -Nru seabios-1.7.1/src/hw/megasas.h seabios-1.7.4/src/hw/megasas.h --- seabios-1.7.1/src/hw/megasas.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/megasas.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef __MEGASAS_H +#define __MEGASAS_H + +struct disk_op_s; +int megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +void megasas_setup(void); + +#endif /* __MEGASAS_H */ diff -Nru seabios-1.7.1/src/hw/pci.c seabios-1.7.4/src/hw/pci.c --- seabios-1.7.1/src/hw/pci.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pci.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,282 @@ +// PCI config space access functions. +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_* +#include "farptr.h" // MAKE_FLATPTR +#include "malloc.h" // malloc_tmp +#include "output.h" // dprintf +#include "pci.h" // pci_config_writel +#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA +#include "pci_regs.h" // PCI_VENDOR_ID +#include "romfile.h" // romfile_loadint +#include "stacks.h" // call32 +#include "string.h" // memset +#include "util.h" // udelay +#include "x86.h" // readl + +void pci_config_writel(u16 bdf, u32 addr, u32 val) +{ + outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); + outl(val, PORT_PCI_DATA); +} + +void pci_config_writew(u16 bdf, u32 addr, u16 val) +{ + outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); + outw(val, PORT_PCI_DATA + (addr & 2)); +} + +void pci_config_writeb(u16 bdf, u32 addr, u8 val) +{ + outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); + outb(val, PORT_PCI_DATA + (addr & 3)); +} + +u32 pci_config_readl(u16 bdf, u32 addr) +{ + outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); + return inl(PORT_PCI_DATA); +} + +u16 pci_config_readw(u16 bdf, u32 addr) +{ + outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); + return inw(PORT_PCI_DATA + (addr & 2)); +} + +u8 pci_config_readb(u16 bdf, u32 addr) +{ + outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); + return inb(PORT_PCI_DATA + (addr & 3)); +} + +void +pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on) +{ + u16 val = pci_config_readw(bdf, addr); + val = (val & ~off) | on; + pci_config_writew(bdf, addr, val); +} + +// Helper function for foreachbdf() macro - return next device +int +pci_next(int bdf, int bus) +{ + if (pci_bdf_to_fn(bdf) == 0 + && (pci_config_readb(bdf, PCI_HEADER_TYPE) & 0x80) == 0) + // Last found device wasn't a multi-function device - skip to + // the next device. + bdf += 8; + else + bdf += 1; + + for (;;) { + if (pci_bdf_to_bus(bdf) != bus) + return -1; + + u16 v = pci_config_readw(bdf, PCI_VENDOR_ID); + if (v != 0x0000 && v != 0xffff) + // Device is present. + return bdf; + + if (pci_bdf_to_fn(bdf) == 0) + bdf += 8; + else + bdf += 1; + } +} + +struct hlist_head PCIDevices VARVERIFY32INIT; +int MaxPCIBus VARFSEG; + +// Check if PCI is available at all +int +pci_probe_host(void) +{ + outl(0x80000000, PORT_PCI_CMD); + if (inl(PORT_PCI_CMD) != 0x80000000) { + dprintf(1, "Detected non-PCI system\n"); + return -1; + } + return 0; +} + +// Find all PCI devices and populate PCIDevices linked list. +void +pci_probe_devices(void) +{ + dprintf(3, "PCI probe\n"); + struct pci_device *busdevs[256]; + memset(busdevs, 0, sizeof(busdevs)); + struct hlist_node **pprev = &PCIDevices.first; + int extraroots = romfile_loadint("etc/extra-pci-roots", 0); + int bus = -1, lastbus = 0, rootbuses = 0, count=0; + while (bus < 0xff && (bus < MaxPCIBus || rootbuses < extraroots)) { + bus++; + int bdf; + foreachbdf(bdf, bus) { + // Create new pci_device struct and add to list. + struct pci_device *dev = malloc_tmp(sizeof(*dev)); + if (!dev) { + warn_noalloc(); + return; + } + memset(dev, 0, sizeof(*dev)); + hlist_add(&dev->node, pprev); + pprev = &dev->node.next; + count++; + + // Find parent device. + int rootbus; + struct pci_device *parent = busdevs[bus]; + if (!parent) { + if (bus != lastbus) + rootbuses++; + lastbus = bus; + rootbus = rootbuses; + if (bus > MaxPCIBus) + MaxPCIBus = bus; + } else { + rootbus = parent->rootbus; + } + + // Populate pci_device info. + dev->bdf = bdf; + dev->parent = parent; + dev->rootbus = rootbus; + u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID); + dev->vendor = vendev & 0xffff; + dev->device = vendev >> 16; + u32 classrev = pci_config_readl(bdf, PCI_CLASS_REVISION); + dev->class = classrev >> 16; + dev->prog_if = classrev >> 8; + dev->revision = classrev & 0xff; + dev->header_type = pci_config_readb(bdf, PCI_HEADER_TYPE); + u8 v = dev->header_type & 0x7f; + if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) { + u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); + dev->secondary_bus = secbus; + if (secbus > bus && !busdevs[secbus]) + busdevs[secbus] = dev; + if (secbus > MaxPCIBus) + MaxPCIBus = secbus; + } + dprintf(4, "PCI device %02x:%02x.%x (vd=%04x:%04x c=%04x)\n" + , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) + , pci_bdf_to_fn(bdf) + , dev->vendor, dev->device, dev->class); + } + } + dprintf(1, "Found %d PCI devices (max PCI bus is %02x)\n", count, MaxPCIBus); +} + +// Search for a device with the specified vendor and device ids. +struct pci_device * +pci_find_device(u16 vendid, u16 devid) +{ + struct pci_device *pci; + foreachpci(pci) { + if (pci->vendor == vendid && pci->device == devid) + return pci; + } + return NULL; +} + +// Search for a device with the specified class id. +struct pci_device * +pci_find_class(u16 classid) +{ + struct pci_device *pci; + foreachpci(pci) { + if (pci->class == classid) + return pci; + } + return NULL; +} + +int pci_init_device(const struct pci_device_id *ids + , struct pci_device *pci, void *arg) +{ + while (ids->vendid || ids->class_mask) { + if ((ids->vendid == PCI_ANY_ID || ids->vendid == pci->vendor) && + (ids->devid == PCI_ANY_ID || ids->devid == pci->device) && + !((ids->class ^ pci->class) & ids->class_mask)) { + if (ids->func) + ids->func(pci, arg); + return 0; + } + ids++; + } + return -1; +} + +struct pci_device * +pci_find_init_device(const struct pci_device_id *ids, void *arg) +{ + struct pci_device *pci; + foreachpci(pci) { + if (pci_init_device(ids, pci, arg) == 0) + return pci; + } + return NULL; +} + +void +pci_reboot(void) +{ + u8 v = inb(PORT_PCI_REBOOT) & ~6; + outb(v|2, PORT_PCI_REBOOT); /* Request hard reset */ + udelay(50); + outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */ + udelay(50); +} + +// helper functions to access pci mmio bars from real mode + +u32 VISIBLE32FLAT +pci_readl_32(u32 addr) +{ + dprintf(9, "32: pci read : %x\n", addr); + return readl((void*)addr); +} + +u32 pci_readl(u32 addr) +{ + if (MODESEGMENT) { + dprintf(9, "16: pci read : %x\n", addr); + extern void _cfunc32flat_pci_readl_32(u32 addr); + return call32(_cfunc32flat_pci_readl_32, addr, -1); + } else { + return pci_readl_32(addr); + } +} + +struct reg32 { + u32 addr; + u32 data; +}; + +void VISIBLE32FLAT +pci_writel_32(struct reg32 *reg32) +{ + dprintf(9, "32: pci write: %x, %x (%p)\n", reg32->addr, reg32->data, reg32); + writel((void*)(reg32->addr), reg32->data); +} + +void pci_writel(u32 addr, u32 val) +{ + struct reg32 reg32 = { .addr = addr, .data = val }; + if (MODESEGMENT) { + dprintf(9, "16: pci write: %x, %x (%x:%p)\n", + reg32.addr, reg32.data, GET_SEG(SS), ®32); + void *flatptr = MAKE_FLATPTR(GET_SEG(SS), ®32); + extern void _cfunc32flat_pci_writel_32(struct reg32 *reg32); + call32(_cfunc32flat_pci_writel_32, (u32)flatptr, -1); + } else { + pci_writel_32(®32); + } +} diff -Nru seabios-1.7.1/src/hw/pci.h seabios-1.7.4/src/hw/pci.h --- seabios-1.7.1/src/hw/pci.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pci.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,125 @@ +#ifndef __PCI_H +#define __PCI_H + +#include "types.h" // u32 +#include "list.h" // hlist_node + +#define PORT_PCI_CMD 0x0cf8 +#define PORT_PCI_REBOOT 0x0cf9 +#define PORT_PCI_DATA 0x0cfc + +#define PCI_ROM_SLOT 6 +#define PCI_NUM_REGIONS 7 +#define PCI_BRIDGE_NUM_REGIONS 2 + +static inline u8 pci_bdf_to_bus(u16 bdf) { + return bdf >> 8; +} +static inline u8 pci_bdf_to_devfn(u16 bdf) { + return bdf & 0xff; +} +static inline u16 pci_bdf_to_busdev(u16 bdf) { + return bdf & ~0x07; +} +static inline u8 pci_bdf_to_dev(u16 bdf) { + return (bdf >> 3) & 0x1f; +} +static inline u8 pci_bdf_to_fn(u16 bdf) { + return bdf & 0x07; +} +static inline u16 pci_to_bdf(int bus, int dev, int fn) { + return (bus<<8) | (dev<<3) | fn; +} +static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) { + return (bus << 8) | devfn; +} + +void pci_config_writel(u16 bdf, u32 addr, u32 val); +void pci_config_writew(u16 bdf, u32 addr, u16 val); +void pci_config_writeb(u16 bdf, u32 addr, u8 val); +u32 pci_config_readl(u16 bdf, u32 addr); +u16 pci_config_readw(u16 bdf, u32 addr); +u8 pci_config_readb(u16 bdf, u32 addr); +void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on); + +struct pci_device *pci_find_device(u16 vendid, u16 devid); +struct pci_device *pci_find_class(u16 classid); + +struct pci_device { + u16 bdf; + u8 rootbus; + struct hlist_node node; + struct pci_device *parent; + + // Configuration space device information + u16 vendor, device; + u16 class; + u8 prog_if, revision; + u8 header_type; + u8 secondary_bus; + + // Local information on device. + int have_driver; +}; +extern u64 pcimem_start, pcimem_end; +extern u64 pcimem64_start, pcimem64_end; +extern struct hlist_head PCIDevices; +extern int MaxPCIBus; +int pci_probe_host(void); +void pci_probe_devices(void); +static inline u32 pci_classprog(struct pci_device *pci) { + return (pci->class << 8) | pci->prog_if; +} + +#define foreachpci(PCI) \ + hlist_for_each_entry(PCI, &PCIDevices, node) + +int pci_next(int bdf, int bus); +#define foreachbdf(BDF, BUS) \ + for (BDF=pci_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS)) \ + ; BDF >= 0 \ + ; BDF=pci_next(BDF, (BUS))) + +#define PCI_ANY_ID (~0) +struct pci_device_id { + u32 vendid; + u32 devid; + u32 class; + u32 class_mask; + void (*func)(struct pci_device *pci, void *arg); +}; + +#define PCI_DEVICE(vendor_id, device_id, init_func) \ + { \ + .vendid = (vendor_id), \ + .devid = (device_id), \ + .class = PCI_ANY_ID, \ + .class_mask = 0, \ + .func = (init_func) \ + } + +#define PCI_DEVICE_CLASS(vendor_id, device_id, class_code, init_func) \ + { \ + .vendid = (vendor_id), \ + .devid = (device_id), \ + .class = (class_code), \ + .class_mask = ~0, \ + .func = (init_func) \ + } + +#define PCI_DEVICE_END \ + { \ + .vendid = 0, \ + } + +int pci_init_device(const struct pci_device_id *ids + , struct pci_device *pci, void *arg); +struct pci_device *pci_find_init_device(const struct pci_device_id *ids + , void *arg); +void pci_reboot(void); + +// helper functions to access pci mmio bars from real mode +u32 pci_readl(u32 addr); +void pci_writel(u32 addr, u32 val); + +#endif diff -Nru seabios-1.7.1/src/hw/pci_ids.h seabios-1.7.4/src/hw/pci_ids.h --- seabios-1.7.1/src/hw/pci_ids.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pci_ids.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,2623 @@ +/* + * PCI Class, Vendor and Device IDs + * + * Please keep sorted. + */ + +/* Device classes and subclasses */ + +#define PCI_CLASS_NOT_DEFINED 0x0000 +#define PCI_CLASS_NOT_DEFINED_VGA 0x0001 + +#define PCI_BASE_CLASS_STORAGE 0x01 +#define PCI_CLASS_STORAGE_SCSI 0x0100 +#define PCI_CLASS_STORAGE_IDE 0x0101 +#define PCI_CLASS_STORAGE_FLOPPY 0x0102 +#define PCI_CLASS_STORAGE_IPI 0x0103 +#define PCI_CLASS_STORAGE_RAID 0x0104 +#define PCI_CLASS_STORAGE_SATA 0x0106 +#define PCI_CLASS_STORAGE_SATA_AHCI 0x010601 +#define PCI_CLASS_STORAGE_SAS 0x0107 +#define PCI_CLASS_STORAGE_OTHER 0x0180 + +#define PCI_BASE_CLASS_NETWORK 0x02 +#define PCI_CLASS_NETWORK_ETHERNET 0x0200 +#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201 +#define PCI_CLASS_NETWORK_FDDI 0x0202 +#define PCI_CLASS_NETWORK_ATM 0x0203 +#define PCI_CLASS_NETWORK_OTHER 0x0280 + +#define PCI_BASE_CLASS_DISPLAY 0x03 +#define PCI_CLASS_DISPLAY_VGA 0x0300 +#define PCI_CLASS_DISPLAY_XGA 0x0301 +#define PCI_CLASS_DISPLAY_3D 0x0302 +#define PCI_CLASS_DISPLAY_OTHER 0x0380 + +#define PCI_BASE_CLASS_MULTIMEDIA 0x04 +#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400 +#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401 +#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402 +#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480 + +#define PCI_BASE_CLASS_MEMORY 0x05 +#define PCI_CLASS_MEMORY_RAM 0x0500 +#define PCI_CLASS_MEMORY_FLASH 0x0501 +#define PCI_CLASS_MEMORY_OTHER 0x0580 + +#define PCI_BASE_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x0600 +#define PCI_CLASS_BRIDGE_ISA 0x0601 +#define PCI_CLASS_BRIDGE_EISA 0x0602 +#define PCI_CLASS_BRIDGE_MC 0x0603 +#define PCI_CLASS_BRIDGE_PCI 0x0604 +#define PCI_CLASS_BRIDGE_PCMCIA 0x0605 +#define PCI_CLASS_BRIDGE_NUBUS 0x0606 +#define PCI_CLASS_BRIDGE_CARDBUS 0x0607 +#define PCI_CLASS_BRIDGE_RACEWAY 0x0608 +#define PCI_CLASS_BRIDGE_OTHER 0x0680 + +#define PCI_BASE_CLASS_COMMUNICATION 0x07 +#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 +#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701 +#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702 +#define PCI_CLASS_COMMUNICATION_MODEM 0x0703 +#define PCI_CLASS_COMMUNICATION_OTHER 0x0780 + +#define PCI_BASE_CLASS_SYSTEM 0x08 +#define PCI_CLASS_SYSTEM_PIC 0x0800 +#define PCI_CLASS_SYSTEM_PIC_IOAPIC 0x080010 +#define PCI_CLASS_SYSTEM_PIC_IOXAPIC 0x080020 +#define PCI_CLASS_SYSTEM_DMA 0x0801 +#define PCI_CLASS_SYSTEM_TIMER 0x0802 +#define PCI_CLASS_SYSTEM_RTC 0x0803 +#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804 +#define PCI_CLASS_SYSTEM_SDHCI 0x0805 +#define PCI_CLASS_SYSTEM_OTHER 0x0880 + +#define PCI_BASE_CLASS_INPUT 0x09 +#define PCI_CLASS_INPUT_KEYBOARD 0x0900 +#define PCI_CLASS_INPUT_PEN 0x0901 +#define PCI_CLASS_INPUT_MOUSE 0x0902 +#define PCI_CLASS_INPUT_SCANNER 0x0903 +#define PCI_CLASS_INPUT_GAMEPORT 0x0904 +#define PCI_CLASS_INPUT_OTHER 0x0980 + +#define PCI_BASE_CLASS_DOCKING 0x0a +#define PCI_CLASS_DOCKING_GENERIC 0x0a00 +#define PCI_CLASS_DOCKING_OTHER 0x0a80 + +#define PCI_BASE_CLASS_PROCESSOR 0x0b +#define PCI_CLASS_PROCESSOR_386 0x0b00 +#define PCI_CLASS_PROCESSOR_486 0x0b01 +#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02 +#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10 +#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20 +#define PCI_CLASS_PROCESSOR_MIPS 0x0b30 +#define PCI_CLASS_PROCESSOR_CO 0x0b40 + +#define PCI_BASE_CLASS_SERIAL 0x0c +#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00 +#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010 +#define PCI_CLASS_SERIAL_ACCESS 0x0c01 +#define PCI_CLASS_SERIAL_SSA 0x0c02 +#define PCI_CLASS_SERIAL_USB 0x0c03 +#define PCI_CLASS_SERIAL_USB_UHCI 0x0c0300 +#define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310 +#define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320 +#define PCI_CLASS_SERIAL_USB_XHCI 0x0c0330 +#define PCI_CLASS_SERIAL_FIBER 0x0c04 +#define PCI_CLASS_SERIAL_SMBUS 0x0c05 + +#define PCI_BASE_CLASS_WIRELESS 0x0d +#define PCI_CLASS_WIRELESS_RF_CONTROLLER 0x0d10 +#define PCI_CLASS_WIRELESS_WHCI 0x0d1010 + +#define PCI_BASE_CLASS_INTELLIGENT 0x0e +#define PCI_CLASS_INTELLIGENT_I2O 0x0e00 + +#define PCI_BASE_CLASS_SATELLITE 0x0f +#define PCI_CLASS_SATELLITE_TV 0x0f00 +#define PCI_CLASS_SATELLITE_AUDIO 0x0f01 +#define PCI_CLASS_SATELLITE_VOICE 0x0f03 +#define PCI_CLASS_SATELLITE_DATA 0x0f04 + +#define PCI_BASE_CLASS_CRYPT 0x10 +#define PCI_CLASS_CRYPT_NETWORK 0x1000 +#define PCI_CLASS_CRYPT_ENTERTAINMENT 0x1001 +#define PCI_CLASS_CRYPT_OTHER 0x1080 + +#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11 +#define PCI_CLASS_SP_DPIO 0x1100 +#define PCI_CLASS_SP_OTHER 0x1180 + +#define PCI_CLASS_OTHERS 0xff + +/* Vendors and devices. Sort key: vendor first, device next. */ + +#define PCI_VENDOR_ID_TTTECH 0x0357 +#define PCI_DEVICE_ID_TTTECH_MC322 0x000a + +#define PCI_VENDOR_ID_DYNALINK 0x0675 +#define PCI_DEVICE_ID_DYNALINK_IS64PH 0x1702 + +#define PCI_VENDOR_ID_BERKOM 0x0871 +#define PCI_DEVICE_ID_BERKOM_A1T 0xffa1 +#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xffa2 +#define PCI_DEVICE_ID_BERKOM_A4T 0xffa4 +#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO 0xffa8 + +#define PCI_VENDOR_ID_COMPAQ 0x0e11 +#define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508 +#define PCI_DEVICE_ID_COMPAQ_TACHYON 0xa0fc +#define PCI_DEVICE_ID_COMPAQ_SMART2P 0xae10 +#define PCI_DEVICE_ID_COMPAQ_NETEL100 0xae32 +#define PCI_DEVICE_ID_COMPAQ_NETEL10 0xae34 +#define PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE 0xae33 +#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I 0xae35 +#define PCI_DEVICE_ID_COMPAQ_NETEL100D 0xae40 +#define PCI_DEVICE_ID_COMPAQ_NETEL100PI 0xae43 +#define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011 +#define PCI_DEVICE_ID_COMPAQ_CISS 0xb060 +#define PCI_DEVICE_ID_COMPAQ_CISSB 0xb178 +#define PCI_DEVICE_ID_COMPAQ_CISSC 0x46 +#define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130 +#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150 + +#define PCI_VENDOR_ID_NCR 0x1000 +#define PCI_VENDOR_ID_LSI_LOGIC 0x1000 +#define PCI_DEVICE_ID_NCR_53C810 0x0001 +#define PCI_DEVICE_ID_NCR_53C820 0x0002 +#define PCI_DEVICE_ID_NCR_53C825 0x0003 +#define PCI_DEVICE_ID_NCR_53C815 0x0004 +#define PCI_DEVICE_ID_LSI_53C810AP 0x0005 +#define PCI_DEVICE_ID_NCR_53C860 0x0006 +#define PCI_DEVICE_ID_LSI_53C1510 0x000a +#define PCI_DEVICE_ID_NCR_53C896 0x000b +#define PCI_DEVICE_ID_NCR_53C895 0x000c +#define PCI_DEVICE_ID_NCR_53C885 0x000d +#define PCI_DEVICE_ID_NCR_53C875 0x000f +#define PCI_DEVICE_ID_NCR_53C1510 0x0010 +#define PCI_DEVICE_ID_LSI_53C895A 0x0012 +#define PCI_DEVICE_ID_LSI_53C875A 0x0013 +#define PCI_DEVICE_ID_LSI_53C1010_33 0x0020 +#define PCI_DEVICE_ID_LSI_53C1010_66 0x0021 +#define PCI_DEVICE_ID_LSI_53C1030 0x0030 +#define PCI_DEVICE_ID_LSI_1030_53C1035 0x0032 +#define PCI_DEVICE_ID_LSI_53C1035 0x0040 +#define PCI_DEVICE_ID_NCR_53C875J 0x008f +#define PCI_DEVICE_ID_LSI_FC909 0x0621 +#define PCI_DEVICE_ID_LSI_FC929 0x0622 +#define PCI_DEVICE_ID_LSI_FC929_LAN 0x0623 +#define PCI_DEVICE_ID_LSI_FC919 0x0624 +#define PCI_DEVICE_ID_LSI_FC919_LAN 0x0625 +#define PCI_DEVICE_ID_LSI_FC929X 0x0626 +#define PCI_DEVICE_ID_LSI_FC939X 0x0642 +#define PCI_DEVICE_ID_LSI_FC949X 0x0640 +#define PCI_DEVICE_ID_LSI_FC949ES 0x0646 +#define PCI_DEVICE_ID_LSI_FC919X 0x0628 +#define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701 +#define PCI_DEVICE_ID_LSI_61C102 0x0901 +#define PCI_DEVICE_ID_LSI_63C815 0x1000 +#define PCI_DEVICE_ID_LSI_SAS1064 0x0050 +#define PCI_DEVICE_ID_LSI_SAS1064R 0x0411 +#define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 +#define PCI_DEVICE_ID_LSI_SAS1066 0x005E +#define PCI_DEVICE_ID_LSI_SAS1068 0x0054 +#define PCI_DEVICE_ID_LSI_SAS1064A 0x005C +#define PCI_DEVICE_ID_LSI_SAS1064E 0x0056 +#define PCI_DEVICE_ID_LSI_SAS1066E 0x005A +#define PCI_DEVICE_ID_LSI_SAS1068E 0x0058 +#define PCI_DEVICE_ID_LSI_SAS1078 0x0060 +#define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C +#define PCI_DEVICE_ID_LSI_SAS2108E 0x0078 +#define PCI_DEVICE_ID_LSI_SAS2108 0x0079 +#define PCI_DEVICE_ID_LSI_SAS2208 0x005B +#define PCI_DEVICE_ID_LSI_SAS3108 0x005D +#define PCI_DEVICE_ID_LSI_SAS2004 0x0071 +#define PCI_DEVICE_ID_LSI_SAS2008 0x0073 + +#define PCI_VENDOR_ID_ATI 0x1002 +/* Mach64 */ +#define PCI_DEVICE_ID_ATI_68800 0x4158 +#define PCI_DEVICE_ID_ATI_215CT222 0x4354 +#define PCI_DEVICE_ID_ATI_210888CX 0x4358 +#define PCI_DEVICE_ID_ATI_215ET222 0x4554 +/* Mach64 / Rage */ +#define PCI_DEVICE_ID_ATI_215GB 0x4742 +#define PCI_DEVICE_ID_ATI_215GD 0x4744 +#define PCI_DEVICE_ID_ATI_215GI 0x4749 +#define PCI_DEVICE_ID_ATI_215GP 0x4750 +#define PCI_DEVICE_ID_ATI_215GQ 0x4751 +#define PCI_DEVICE_ID_ATI_215XL 0x4752 +#define PCI_DEVICE_ID_ATI_215GT 0x4754 +#define PCI_DEVICE_ID_ATI_215GTB 0x4755 +#define PCI_DEVICE_ID_ATI_215_IV 0x4756 +#define PCI_DEVICE_ID_ATI_215_IW 0x4757 +#define PCI_DEVICE_ID_ATI_215_IZ 0x475A +#define PCI_DEVICE_ID_ATI_210888GX 0x4758 +#define PCI_DEVICE_ID_ATI_215_LB 0x4c42 +#define PCI_DEVICE_ID_ATI_215_LD 0x4c44 +#define PCI_DEVICE_ID_ATI_215_LG 0x4c47 +#define PCI_DEVICE_ID_ATI_215_LI 0x4c49 +#define PCI_DEVICE_ID_ATI_215_LM 0x4c4D +#define PCI_DEVICE_ID_ATI_215_LN 0x4c4E +#define PCI_DEVICE_ID_ATI_215_LR 0x4c52 +#define PCI_DEVICE_ID_ATI_215_LS 0x4c53 +#define PCI_DEVICE_ID_ATI_264_LT 0x4c54 +/* Mach64 VT */ +#define PCI_DEVICE_ID_ATI_264VT 0x5654 +#define PCI_DEVICE_ID_ATI_264VU 0x5655 +#define PCI_DEVICE_ID_ATI_264VV 0x5656 +/* Rage128 GL */ +#define PCI_DEVICE_ID_ATI_RAGE128_RE 0x5245 +#define PCI_DEVICE_ID_ATI_RAGE128_RF 0x5246 +#define PCI_DEVICE_ID_ATI_RAGE128_RG 0x5247 +/* Rage128 VR */ +#define PCI_DEVICE_ID_ATI_RAGE128_RK 0x524b +#define PCI_DEVICE_ID_ATI_RAGE128_RL 0x524c +#define PCI_DEVICE_ID_ATI_RAGE128_SE 0x5345 +#define PCI_DEVICE_ID_ATI_RAGE128_SF 0x5346 +#define PCI_DEVICE_ID_ATI_RAGE128_SG 0x5347 +#define PCI_DEVICE_ID_ATI_RAGE128_SH 0x5348 +#define PCI_DEVICE_ID_ATI_RAGE128_SK 0x534b +#define PCI_DEVICE_ID_ATI_RAGE128_SL 0x534c +#define PCI_DEVICE_ID_ATI_RAGE128_SM 0x534d +#define PCI_DEVICE_ID_ATI_RAGE128_SN 0x534e +/* Rage128 Ultra */ +#define PCI_DEVICE_ID_ATI_RAGE128_TF 0x5446 +#define PCI_DEVICE_ID_ATI_RAGE128_TL 0x544c +#define PCI_DEVICE_ID_ATI_RAGE128_TR 0x5452 +#define PCI_DEVICE_ID_ATI_RAGE128_TS 0x5453 +#define PCI_DEVICE_ID_ATI_RAGE128_TT 0x5454 +#define PCI_DEVICE_ID_ATI_RAGE128_TU 0x5455 +/* Rage128 M3 */ +#define PCI_DEVICE_ID_ATI_RAGE128_LE 0x4c45 +#define PCI_DEVICE_ID_ATI_RAGE128_LF 0x4c46 +/* Rage128 M4 */ +#define PCI_DEVICE_ID_ATI_RAGE128_MF 0x4d46 +#define PCI_DEVICE_ID_ATI_RAGE128_ML 0x4d4c +/* Rage128 Pro GL */ +#define PCI_DEVICE_ID_ATI_RAGE128_PA 0x5041 +#define PCI_DEVICE_ID_ATI_RAGE128_PB 0x5042 +#define PCI_DEVICE_ID_ATI_RAGE128_PC 0x5043 +#define PCI_DEVICE_ID_ATI_RAGE128_PD 0x5044 +#define PCI_DEVICE_ID_ATI_RAGE128_PE 0x5045 +#define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046 +/* Rage128 Pro VR */ +#define PCI_DEVICE_ID_ATI_RAGE128_PG 0x5047 +#define PCI_DEVICE_ID_ATI_RAGE128_PH 0x5048 +#define PCI_DEVICE_ID_ATI_RAGE128_PI 0x5049 +#define PCI_DEVICE_ID_ATI_RAGE128_PJ 0x504A +#define PCI_DEVICE_ID_ATI_RAGE128_PK 0x504B +#define PCI_DEVICE_ID_ATI_RAGE128_PL 0x504C +#define PCI_DEVICE_ID_ATI_RAGE128_PM 0x504D +#define PCI_DEVICE_ID_ATI_RAGE128_PN 0x504E +#define PCI_DEVICE_ID_ATI_RAGE128_PO 0x504F +#define PCI_DEVICE_ID_ATI_RAGE128_PP 0x5050 +#define PCI_DEVICE_ID_ATI_RAGE128_PQ 0x5051 +#define PCI_DEVICE_ID_ATI_RAGE128_PR 0x5052 +#define PCI_DEVICE_ID_ATI_RAGE128_PS 0x5053 +#define PCI_DEVICE_ID_ATI_RAGE128_PT 0x5054 +#define PCI_DEVICE_ID_ATI_RAGE128_PU 0x5055 +#define PCI_DEVICE_ID_ATI_RAGE128_PV 0x5056 +#define PCI_DEVICE_ID_ATI_RAGE128_PW 0x5057 +#define PCI_DEVICE_ID_ATI_RAGE128_PX 0x5058 +/* Rage128 M4 */ +/* Radeon R100 */ +#define PCI_DEVICE_ID_ATI_RADEON_QD 0x5144 +#define PCI_DEVICE_ID_ATI_RADEON_QE 0x5145 +#define PCI_DEVICE_ID_ATI_RADEON_QF 0x5146 +#define PCI_DEVICE_ID_ATI_RADEON_QG 0x5147 +/* Radeon RV100 (VE) */ +#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 +#define PCI_DEVICE_ID_ATI_RADEON_QZ 0x515a +/* Radeon R200 (8500) */ +#define PCI_DEVICE_ID_ATI_RADEON_QL 0x514c +#define PCI_DEVICE_ID_ATI_RADEON_QN 0x514e +#define PCI_DEVICE_ID_ATI_RADEON_QO 0x514f +#define PCI_DEVICE_ID_ATI_RADEON_Ql 0x516c +#define PCI_DEVICE_ID_ATI_RADEON_BB 0x4242 +/* Radeon R200 (9100) */ +#define PCI_DEVICE_ID_ATI_RADEON_QM 0x514d +/* Radeon RV200 (7500) */ +#define PCI_DEVICE_ID_ATI_RADEON_QW 0x5157 +#define PCI_DEVICE_ID_ATI_RADEON_QX 0x5158 +/* Radeon NV-100 */ +/* Radeon RV250 (9000) */ +#define PCI_DEVICE_ID_ATI_RADEON_Id 0x4964 +#define PCI_DEVICE_ID_ATI_RADEON_Ie 0x4965 +#define PCI_DEVICE_ID_ATI_RADEON_If 0x4966 +#define PCI_DEVICE_ID_ATI_RADEON_Ig 0x4967 +/* Radeon RV280 (9200) */ +#define PCI_DEVICE_ID_ATI_RADEON_Ya 0x5961 +#define PCI_DEVICE_ID_ATI_RADEON_Yd 0x5964 +/* Radeon R300 (9500) */ +/* Radeon R300 (9700) */ +#define PCI_DEVICE_ID_ATI_RADEON_ND 0x4e44 +#define PCI_DEVICE_ID_ATI_RADEON_NE 0x4e45 +#define PCI_DEVICE_ID_ATI_RADEON_NF 0x4e46 +#define PCI_DEVICE_ID_ATI_RADEON_NG 0x4e47 +/* Radeon R350 (9800) */ +/* Radeon RV350 (9600) */ +/* Radeon M6 */ +#define PCI_DEVICE_ID_ATI_RADEON_LY 0x4c59 +#define PCI_DEVICE_ID_ATI_RADEON_LZ 0x4c5a +/* Radeon M7 */ +#define PCI_DEVICE_ID_ATI_RADEON_LW 0x4c57 +#define PCI_DEVICE_ID_ATI_RADEON_LX 0x4c58 +/* Radeon M9 */ +#define PCI_DEVICE_ID_ATI_RADEON_Ld 0x4c64 +#define PCI_DEVICE_ID_ATI_RADEON_Le 0x4c65 +#define PCI_DEVICE_ID_ATI_RADEON_Lf 0x4c66 +#define PCI_DEVICE_ID_ATI_RADEON_Lg 0x4c67 +/* Radeon */ +/* RadeonIGP */ +#define PCI_DEVICE_ID_ATI_RS100 0xcab0 +#define PCI_DEVICE_ID_ATI_RS200 0xcab2 +#define PCI_DEVICE_ID_ATI_RS200_B 0xcbb2 +#define PCI_DEVICE_ID_ATI_RS250 0xcab3 +#define PCI_DEVICE_ID_ATI_RS300_100 0x5830 +#define PCI_DEVICE_ID_ATI_RS300_133 0x5831 +#define PCI_DEVICE_ID_ATI_RS300_166 0x5832 +#define PCI_DEVICE_ID_ATI_RS300_200 0x5833 +#define PCI_DEVICE_ID_ATI_RS350_100 0x7830 +#define PCI_DEVICE_ID_ATI_RS350_133 0x7831 +#define PCI_DEVICE_ID_ATI_RS350_166 0x7832 +#define PCI_DEVICE_ID_ATI_RS350_200 0x7833 +#define PCI_DEVICE_ID_ATI_RS400_100 0x5a30 +#define PCI_DEVICE_ID_ATI_RS400_133 0x5a31 +#define PCI_DEVICE_ID_ATI_RS400_166 0x5a32 +#define PCI_DEVICE_ID_ATI_RS400_200 0x5a33 +#define PCI_DEVICE_ID_ATI_RS480 0x5950 +/* ATI IXP Chipset */ +#define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349 +#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 +#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363 +#define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369 +#define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e +#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372 +#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376 +#define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379 +#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a +#define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380 +#define PCI_DEVICE_ID_ATI_SBX00_SMBUS 0x4385 +#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c +#define PCI_DEVICE_ID_ATI_IXP700_SATA 0x4390 +#define PCI_DEVICE_ID_ATI_IXP700_IDE 0x439c + +#define PCI_VENDOR_ID_VLSI 0x1004 +#define PCI_DEVICE_ID_VLSI_82C592 0x0005 +#define PCI_DEVICE_ID_VLSI_82C593 0x0006 +#define PCI_DEVICE_ID_VLSI_82C594 0x0007 +#define PCI_DEVICE_ID_VLSI_82C597 0x0009 +#define PCI_DEVICE_ID_VLSI_82C541 0x000c +#define PCI_DEVICE_ID_VLSI_82C543 0x000d +#define PCI_DEVICE_ID_VLSI_82C532 0x0101 +#define PCI_DEVICE_ID_VLSI_82C534 0x0102 +#define PCI_DEVICE_ID_VLSI_82C535 0x0104 +#define PCI_DEVICE_ID_VLSI_82C147 0x0105 +#define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 + +#define PCI_VENDOR_ID_ADL 0x1005 +#define PCI_DEVICE_ID_ADL_2301 0x2301 + +#define PCI_VENDOR_ID_NS 0x100b +#define PCI_DEVICE_ID_NS_87415 0x0002 +#define PCI_DEVICE_ID_NS_87560_LIO 0x000e +#define PCI_DEVICE_ID_NS_87560_USB 0x0012 +#define PCI_DEVICE_ID_NS_83815 0x0020 +#define PCI_DEVICE_ID_NS_83820 0x0022 +#define PCI_DEVICE_ID_NS_CS5535_ISA 0x002b +#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d +#define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e +#define PCI_DEVICE_ID_NS_CS5535_USB 0x002f +#define PCI_DEVICE_ID_NS_GX_VIDEO 0x0030 +#define PCI_DEVICE_ID_NS_SATURN 0x0035 +#define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500 +#define PCI_DEVICE_ID_NS_SCx200_SMI 0x0501 +#define PCI_DEVICE_ID_NS_SCx200_IDE 0x0502 +#define PCI_DEVICE_ID_NS_SCx200_AUDIO 0x0503 +#define PCI_DEVICE_ID_NS_SCx200_VIDEO 0x0504 +#define PCI_DEVICE_ID_NS_SCx200_XBUS 0x0505 +#define PCI_DEVICE_ID_NS_SC1100_BRIDGE 0x0510 +#define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 +#define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 +#define PCI_DEVICE_ID_NS_87410 0xd001 + +#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE 0x0028 + +#define PCI_VENDOR_ID_TSENG 0x100c +#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 +#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205 +#define PCI_DEVICE_ID_TSENG_W32P_c 0x3206 +#define PCI_DEVICE_ID_TSENG_W32P_d 0x3207 +#define PCI_DEVICE_ID_TSENG_ET6000 0x3208 + +#define PCI_VENDOR_ID_WEITEK 0x100e +#define PCI_DEVICE_ID_WEITEK_P9000 0x9001 +#define PCI_DEVICE_ID_WEITEK_P9100 0x9100 + +#define PCI_VENDOR_ID_DEC 0x1011 +#define PCI_DEVICE_ID_DEC_BRD 0x0001 +#define PCI_DEVICE_ID_DEC_TULIP 0x0002 +#define PCI_DEVICE_ID_DEC_TGA 0x0004 +#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 +#define PCI_DEVICE_ID_DEC_TGA2 0x000D +#define PCI_DEVICE_ID_DEC_FDDI 0x000F +#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 +#define PCI_DEVICE_ID_DEC_21142 0x0019 +#define PCI_DEVICE_ID_DEC_21052 0x0021 +#define PCI_DEVICE_ID_DEC_21150 0x0022 +#define PCI_DEVICE_ID_DEC_21152 0x0024 +#define PCI_DEVICE_ID_DEC_21153 0x0025 +#define PCI_DEVICE_ID_DEC_21154 0x0026 +#define PCI_DEVICE_ID_DEC_21285 0x1065 +#define PCI_DEVICE_ID_COMPAQ_42XX 0x0046 + +#define PCI_VENDOR_ID_CIRRUS 0x1013 +#define PCI_DEVICE_ID_CIRRUS_7548 0x0038 +#define PCI_DEVICE_ID_CIRRUS_5430 0x00a0 +#define PCI_DEVICE_ID_CIRRUS_5434_4 0x00a4 +#define PCI_DEVICE_ID_CIRRUS_5434_8 0x00a8 +#define PCI_DEVICE_ID_CIRRUS_5436 0x00ac +#define PCI_DEVICE_ID_CIRRUS_5446 0x00b8 +#define PCI_DEVICE_ID_CIRRUS_5480 0x00bc +#define PCI_DEVICE_ID_CIRRUS_5462 0x00d0 +#define PCI_DEVICE_ID_CIRRUS_5464 0x00d4 +#define PCI_DEVICE_ID_CIRRUS_5465 0x00d6 +#define PCI_DEVICE_ID_CIRRUS_6729 0x1100 +#define PCI_DEVICE_ID_CIRRUS_6832 0x1110 +#define PCI_DEVICE_ID_CIRRUS_7543 0x1202 +#define PCI_DEVICE_ID_CIRRUS_4610 0x6001 +#define PCI_DEVICE_ID_CIRRUS_4612 0x6003 +#define PCI_DEVICE_ID_CIRRUS_4615 0x6004 + +#define PCI_VENDOR_ID_IBM 0x1014 +#define PCI_DEVICE_ID_IBM_TR 0x0018 +#define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e +#define PCI_DEVICE_ID_IBM_CPC710_PCI64 0x00fc +#define PCI_DEVICE_ID_IBM_SNIPE 0x0180 +#define PCI_DEVICE_ID_IBM_CITRINE 0x028C +#define PCI_DEVICE_ID_IBM_GEMSTONE 0xB166 +#define PCI_DEVICE_ID_IBM_OBSIDIAN 0x02BD +#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1 0x0031 +#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2 0x0219 +#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX 0x021A +#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251 +#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361 +#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252 + +#define PCI_VENDOR_ID_UNISYS 0x1018 +#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C + +#define PCI_VENDOR_ID_COMPEX2 0x101a /* pci.ids says "AT&T GIS (NCR)" */ +#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005 + +#define PCI_VENDOR_ID_WD 0x101c +#define PCI_DEVICE_ID_WD_90C 0xc24a + +#define PCI_VENDOR_ID_AMI 0x101e +#define PCI_DEVICE_ID_AMI_MEGARAID3 0x1960 +#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010 +#define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 + +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_K8_NB 0x1100 +#define PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP 0x1101 +#define PCI_DEVICE_ID_AMD_K8_NB_MEMCTL 0x1102 +#define PCI_DEVICE_ID_AMD_K8_NB_MISC 0x1103 +#define PCI_DEVICE_ID_AMD_10H_NB_HT 0x1200 +#define PCI_DEVICE_ID_AMD_10H_NB_MAP 0x1201 +#define PCI_DEVICE_ID_AMD_10H_NB_DRAM 0x1202 +#define PCI_DEVICE_ID_AMD_10H_NB_MISC 0x1203 +#define PCI_DEVICE_ID_AMD_10H_NB_LINK 0x1204 +#define PCI_DEVICE_ID_AMD_11H_NB_HT 0x1300 +#define PCI_DEVICE_ID_AMD_11H_NB_MAP 0x1301 +#define PCI_DEVICE_ID_AMD_11H_NB_DRAM 0x1302 +#define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 +#define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 +#define PCI_DEVICE_ID_AMD_LANCE 0x2000 +#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 +#define PCI_DEVICE_ID_AMD_SCSI 0x2020 +#define PCI_DEVICE_ID_AMD_SERENADE 0x36c0 +#define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006 +#define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007 +#define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C +#define PCI_DEVICE_ID_AMD_FE_GATE_700E 0x700E +#define PCI_DEVICE_ID_AMD_COBRA_7401 0x7401 +#define PCI_DEVICE_ID_AMD_VIPER_7409 0x7409 +#define PCI_DEVICE_ID_AMD_VIPER_740B 0x740B +#define PCI_DEVICE_ID_AMD_VIPER_7410 0x7410 +#define PCI_DEVICE_ID_AMD_VIPER_7411 0x7411 +#define PCI_DEVICE_ID_AMD_VIPER_7413 0x7413 +#define PCI_DEVICE_ID_AMD_VIPER_7440 0x7440 +#define PCI_DEVICE_ID_AMD_OPUS_7441 0x7441 +#define PCI_DEVICE_ID_AMD_OPUS_7443 0x7443 +#define PCI_DEVICE_ID_AMD_VIPER_7443 0x7443 +#define PCI_DEVICE_ID_AMD_OPUS_7445 0x7445 +#define PCI_DEVICE_ID_AMD_8111_LPC 0x7468 +#define PCI_DEVICE_ID_AMD_8111_IDE 0x7469 +#define PCI_DEVICE_ID_AMD_8111_SMBUS2 0x746a +#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b +#define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d +#define PCI_DEVICE_ID_AMD_8151_0 0x7454 +#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450 +#define PCI_DEVICE_ID_AMD_8131_APIC 0x7451 +#define PCI_DEVICE_ID_AMD_8132_BRIDGE 0x7458 +#define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090 +#define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091 +#define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 +#define PCI_DEVICE_ID_AMD_CS5536_OHC 0x2094 +#define PCI_DEVICE_ID_AMD_CS5536_EHC 0x2095 +#define PCI_DEVICE_ID_AMD_CS5536_UDC 0x2096 +#define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097 +#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A + +#define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081 +#define PCI_DEVICE_ID_AMD_LX_AES 0x2082 + +#define PCI_VENDOR_ID_TRIDENT 0x1023 +#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 +#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 +#define PCI_DEVICE_ID_TRIDENT_9320 0x9320 +#define PCI_DEVICE_ID_TRIDENT_9388 0x9388 +#define PCI_DEVICE_ID_TRIDENT_9397 0x9397 +#define PCI_DEVICE_ID_TRIDENT_939A 0x939A +#define PCI_DEVICE_ID_TRIDENT_9520 0x9520 +#define PCI_DEVICE_ID_TRIDENT_9525 0x9525 +#define PCI_DEVICE_ID_TRIDENT_9420 0x9420 +#define PCI_DEVICE_ID_TRIDENT_9440 0x9440 +#define PCI_DEVICE_ID_TRIDENT_9660 0x9660 +#define PCI_DEVICE_ID_TRIDENT_9750 0x9750 +#define PCI_DEVICE_ID_TRIDENT_9850 0x9850 +#define PCI_DEVICE_ID_TRIDENT_9880 0x9880 +#define PCI_DEVICE_ID_TRIDENT_8400 0x8400 +#define PCI_DEVICE_ID_TRIDENT_8420 0x8420 +#define PCI_DEVICE_ID_TRIDENT_8500 0x8500 + +#define PCI_VENDOR_ID_AI 0x1025 +#define PCI_DEVICE_ID_AI_M1435 0x1435 + +#define PCI_VENDOR_ID_DELL 0x1028 +#define PCI_DEVICE_ID_DELL_RACIII 0x0008 +#define PCI_DEVICE_ID_DELL_RAC4 0x0012 +#define PCI_DEVICE_ID_DELL_PERC5 0x0015 + +#define PCI_VENDOR_ID_MATROX 0x102B +#define PCI_DEVICE_ID_MATROX_MGA_2 0x0518 +#define PCI_DEVICE_ID_MATROX_MIL 0x0519 +#define PCI_DEVICE_ID_MATROX_MYS 0x051A +#define PCI_DEVICE_ID_MATROX_MIL_2 0x051b +#define PCI_DEVICE_ID_MATROX_MYS_AGP 0x051e +#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f +#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 +#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 +#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001 +#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520 +#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521 +#define PCI_DEVICE_ID_MATROX_G400 0x0525 +#define PCI_DEVICE_ID_MATROX_G200EV_PCI 0x0530 +#define PCI_DEVICE_ID_MATROX_G550 0x2527 +#define PCI_DEVICE_ID_MATROX_VIA 0x4536 + +#define PCI_VENDOR_ID_CT 0x102c +#define PCI_DEVICE_ID_CT_69000 0x00c0 +#define PCI_DEVICE_ID_CT_65545 0x00d8 +#define PCI_DEVICE_ID_CT_65548 0x00dc +#define PCI_DEVICE_ID_CT_65550 0x00e0 +#define PCI_DEVICE_ID_CT_65554 0x00e4 +#define PCI_DEVICE_ID_CT_65555 0x00e5 + +#define PCI_VENDOR_ID_MIRO 0x1031 +#define PCI_DEVICE_ID_MIRO_36050 0x5601 +#define PCI_DEVICE_ID_MIRO_DC10PLUS 0x7efe +#define PCI_DEVICE_ID_MIRO_DC30PLUS 0xd801 + +#define PCI_VENDOR_ID_NEC 0x1033 +#define PCI_DEVICE_ID_NEC_CBUS_1 0x0001 /* PCI-Cbus Bridge */ +#define PCI_DEVICE_ID_NEC_LOCAL 0x0002 /* Local Bridge */ +#define PCI_DEVICE_ID_NEC_ATM 0x0003 /* ATM LAN Controller */ +#define PCI_DEVICE_ID_NEC_R4000 0x0004 /* R4000 Bridge */ +#define PCI_DEVICE_ID_NEC_486 0x0005 /* 486 Like Peripheral Bus Bridge */ +#define PCI_DEVICE_ID_NEC_ACCEL_1 0x0006 /* Graphic Accelerator */ +#define PCI_DEVICE_ID_NEC_UXBUS 0x0007 /* UX-Bus Bridge */ +#define PCI_DEVICE_ID_NEC_ACCEL_2 0x0008 /* Graphic Accelerator */ +#define PCI_DEVICE_ID_NEC_GRAPH 0x0009 /* PCI-CoreGraph Bridge */ +#define PCI_DEVICE_ID_NEC_VL 0x0016 /* PCI-VL Bridge */ +#define PCI_DEVICE_ID_NEC_STARALPHA2 0x002c /* STAR ALPHA2 */ +#define PCI_DEVICE_ID_NEC_CBUS_2 0x002d /* PCI-Cbus Bridge */ +#define PCI_DEVICE_ID_NEC_USB 0x0035 /* PCI-USB Host */ +#define PCI_DEVICE_ID_NEC_CBUS_3 0x003b +#define PCI_DEVICE_ID_NEC_NAPCCARD 0x003e +#define PCI_DEVICE_ID_NEC_PCX2 0x0046 /* PowerVR */ +#define PCI_DEVICE_ID_NEC_VRC5476 0x009b +#define PCI_DEVICE_ID_NEC_VRC4173 0x00a5 +#define PCI_DEVICE_ID_NEC_VRC5477_AC97 0x00a6 +#define PCI_DEVICE_ID_NEC_PC9821CS01 0x800c /* PC-9821-CS01 */ +#define PCI_DEVICE_ID_NEC_PC9821NRB06 0x800d /* PC-9821NR-B06 */ + +#define PCI_VENDOR_ID_FD 0x1036 +#define PCI_DEVICE_ID_FD_36C70 0x0000 + +#define PCI_VENDOR_ID_SI 0x1039 +#define PCI_DEVICE_ID_SI_5591_AGP 0x0001 +#define PCI_DEVICE_ID_SI_6202 0x0002 +#define PCI_DEVICE_ID_SI_503 0x0008 +#define PCI_DEVICE_ID_SI_ACPI 0x0009 +#define PCI_DEVICE_ID_SI_SMBUS 0x0016 +#define PCI_DEVICE_ID_SI_LPC 0x0018 +#define PCI_DEVICE_ID_SI_5597_VGA 0x0200 +#define PCI_DEVICE_ID_SI_6205 0x0205 +#define PCI_DEVICE_ID_SI_501 0x0406 +#define PCI_DEVICE_ID_SI_496 0x0496 +#define PCI_DEVICE_ID_SI_300 0x0300 +#define PCI_DEVICE_ID_SI_315H 0x0310 +#define PCI_DEVICE_ID_SI_315 0x0315 +#define PCI_DEVICE_ID_SI_315PRO 0x0325 +#define PCI_DEVICE_ID_SI_530 0x0530 +#define PCI_DEVICE_ID_SI_540 0x0540 +#define PCI_DEVICE_ID_SI_550 0x0550 +#define PCI_DEVICE_ID_SI_540_VGA 0x5300 +#define PCI_DEVICE_ID_SI_550_VGA 0x5315 +#define PCI_DEVICE_ID_SI_620 0x0620 +#define PCI_DEVICE_ID_SI_630 0x0630 +#define PCI_DEVICE_ID_SI_633 0x0633 +#define PCI_DEVICE_ID_SI_635 0x0635 +#define PCI_DEVICE_ID_SI_640 0x0640 +#define PCI_DEVICE_ID_SI_645 0x0645 +#define PCI_DEVICE_ID_SI_646 0x0646 +#define PCI_DEVICE_ID_SI_648 0x0648 +#define PCI_DEVICE_ID_SI_650 0x0650 +#define PCI_DEVICE_ID_SI_651 0x0651 +#define PCI_DEVICE_ID_SI_655 0x0655 +#define PCI_DEVICE_ID_SI_661 0x0661 +#define PCI_DEVICE_ID_SI_730 0x0730 +#define PCI_DEVICE_ID_SI_733 0x0733 +#define PCI_DEVICE_ID_SI_630_VGA 0x6300 +#define PCI_DEVICE_ID_SI_735 0x0735 +#define PCI_DEVICE_ID_SI_740 0x0740 +#define PCI_DEVICE_ID_SI_741 0x0741 +#define PCI_DEVICE_ID_SI_745 0x0745 +#define PCI_DEVICE_ID_SI_746 0x0746 +#define PCI_DEVICE_ID_SI_755 0x0755 +#define PCI_DEVICE_ID_SI_760 0x0760 +#define PCI_DEVICE_ID_SI_900 0x0900 +#define PCI_DEVICE_ID_SI_961 0x0961 +#define PCI_DEVICE_ID_SI_962 0x0962 +#define PCI_DEVICE_ID_SI_963 0x0963 +#define PCI_DEVICE_ID_SI_965 0x0965 +#define PCI_DEVICE_ID_SI_966 0x0966 +#define PCI_DEVICE_ID_SI_968 0x0968 +#define PCI_DEVICE_ID_SI_1180 0x1180 +#define PCI_DEVICE_ID_SI_5511 0x5511 +#define PCI_DEVICE_ID_SI_5513 0x5513 +#define PCI_DEVICE_ID_SI_5517 0x5517 +#define PCI_DEVICE_ID_SI_5518 0x5518 +#define PCI_DEVICE_ID_SI_5571 0x5571 +#define PCI_DEVICE_ID_SI_5581 0x5581 +#define PCI_DEVICE_ID_SI_5582 0x5582 +#define PCI_DEVICE_ID_SI_5591 0x5591 +#define PCI_DEVICE_ID_SI_5596 0x5596 +#define PCI_DEVICE_ID_SI_5597 0x5597 +#define PCI_DEVICE_ID_SI_5598 0x5598 +#define PCI_DEVICE_ID_SI_5600 0x5600 +#define PCI_DEVICE_ID_SI_7012 0x7012 +#define PCI_DEVICE_ID_SI_7013 0x7013 +#define PCI_DEVICE_ID_SI_7016 0x7016 +#define PCI_DEVICE_ID_SI_7018 0x7018 + +#define PCI_VENDOR_ID_HP 0x103c +#define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX2 0x100a +#define PCI_DEVICE_ID_HP_TACHYON 0x1028 +#define PCI_DEVICE_ID_HP_TACHLITE 0x1029 +#define PCI_DEVICE_ID_HP_J2585A 0x1030 +#define PCI_DEVICE_ID_HP_J2585B 0x1031 +#define PCI_DEVICE_ID_HP_J2973A 0x1040 +#define PCI_DEVICE_ID_HP_J2970A 0x1042 +#define PCI_DEVICE_ID_HP_DIVA 0x1048 +#define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 +#define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A +#define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B +#define PCI_DEVICE_ID_HP_REO_IOC 0x10f1 +#define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b +#define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 +#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 +#define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227 +#define PCI_DEVICE_ID_HP_ZX1_IOC 0x122a +#define PCI_DEVICE_ID_HP_PCIX_LBA 0x122e +#define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c +#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 +#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 +#define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301 +#define PCI_DEVICE_ID_HP_DIVA_HURRICANE 0x132a +#define PCI_DEVICE_ID_HP_CISSA 0x3220 +#define PCI_DEVICE_ID_HP_CISSC 0x3230 +#define PCI_DEVICE_ID_HP_CISSD 0x3238 +#define PCI_DEVICE_ID_HP_CISSE 0x323a +#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 + +#define PCI_VENDOR_ID_PCTECH 0x1042 +#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 +#define PCI_DEVICE_ID_PCTECH_RZ1001 0x1001 +#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020 + +#define PCI_VENDOR_ID_ASUSTEK 0x1043 +#define PCI_DEVICE_ID_ASUSTEK_0675 0x0675 + +#define PCI_VENDOR_ID_DPT 0x1044 +#define PCI_DEVICE_ID_DPT 0xa400 + +#define PCI_VENDOR_ID_OPTI 0x1045 +#define PCI_DEVICE_ID_OPTI_82C558 0xc558 +#define PCI_DEVICE_ID_OPTI_82C621 0xc621 +#define PCI_DEVICE_ID_OPTI_82C700 0xc700 +#define PCI_DEVICE_ID_OPTI_82C825 0xd568 + +#define PCI_VENDOR_ID_ELSA 0x1048 +#define PCI_DEVICE_ID_ELSA_MICROLINK 0x1000 +#define PCI_DEVICE_ID_ELSA_QS3000 0x3000 + +#define PCI_VENDOR_ID_BUSLOGIC 0x104B +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140 +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040 +#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130 + +#define PCI_VENDOR_ID_TI 0x104c +#define PCI_DEVICE_ID_TI_TVP4020 0x3d07 +#define PCI_DEVICE_ID_TI_4450 0x8011 +#define PCI_DEVICE_ID_TI_TSB43AB22 0x8023 +#define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 +#define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033 +#define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034 +#define PCI_DEVICE_ID_TI_X515 0x8036 +#define PCI_DEVICE_ID_TI_XX12 0x8039 +#define PCI_DEVICE_ID_TI_XX12_FM 0x803b +#define PCI_DEVICE_ID_TI_1130 0xac12 +#define PCI_DEVICE_ID_TI_1031 0xac13 +#define PCI_DEVICE_ID_TI_1131 0xac15 +#define PCI_DEVICE_ID_TI_1250 0xac16 +#define PCI_DEVICE_ID_TI_1220 0xac17 +#define PCI_DEVICE_ID_TI_1221 0xac19 +#define PCI_DEVICE_ID_TI_1210 0xac1a +#define PCI_DEVICE_ID_TI_1450 0xac1b +#define PCI_DEVICE_ID_TI_1225 0xac1c +#define PCI_DEVICE_ID_TI_1251A 0xac1d +#define PCI_DEVICE_ID_TI_1211 0xac1e +#define PCI_DEVICE_ID_TI_1251B 0xac1f +#define PCI_DEVICE_ID_TI_4410 0xac41 +#define PCI_DEVICE_ID_TI_4451 0xac42 +#define PCI_DEVICE_ID_TI_4510 0xac44 +#define PCI_DEVICE_ID_TI_4520 0xac46 +#define PCI_DEVICE_ID_TI_7510 0xac47 +#define PCI_DEVICE_ID_TI_7610 0xac48 +#define PCI_DEVICE_ID_TI_7410 0xac49 +#define PCI_DEVICE_ID_TI_1410 0xac50 +#define PCI_DEVICE_ID_TI_1420 0xac51 +#define PCI_DEVICE_ID_TI_1451A 0xac52 +#define PCI_DEVICE_ID_TI_1620 0xac54 +#define PCI_DEVICE_ID_TI_1520 0xac55 +#define PCI_DEVICE_ID_TI_1510 0xac56 +#define PCI_DEVICE_ID_TI_X620 0xac8d +#define PCI_DEVICE_ID_TI_X420 0xac8e +#define PCI_DEVICE_ID_TI_XX20_FM 0xac8f + +#define PCI_VENDOR_ID_SONY 0x104d + +/* Winbond have two vendor IDs! See 0x10ad as well */ +#define PCI_VENDOR_ID_WINBOND2 0x1050 +#define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a +#define PCI_DEVICE_ID_WINBOND2_6692 0x6692 + +#define PCI_VENDOR_ID_ANIGMA 0x1051 +#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100 + +#define PCI_VENDOR_ID_EFAR 0x1055 +#define PCI_DEVICE_ID_EFAR_SLC90E66_1 0x9130 +#define PCI_DEVICE_ID_EFAR_SLC90E66_3 0x9463 + +#define PCI_VENDOR_ID_MOTOROLA 0x1057 +#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001 +#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002 +#define PCI_DEVICE_ID_MOTOROLA_MPC107 0x0004 +#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801 +#define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802 +#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803 +#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b +#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803 +#define PCI_DEVICE_ID_MOTOROLA_MPC5200B 0x5809 + +#define PCI_VENDOR_ID_PROMISE 0x105a +#define PCI_DEVICE_ID_PROMISE_20265 0x0d30 +#define PCI_DEVICE_ID_PROMISE_20267 0x4d30 +#define PCI_DEVICE_ID_PROMISE_20246 0x4d33 +#define PCI_DEVICE_ID_PROMISE_20262 0x4d38 +#define PCI_DEVICE_ID_PROMISE_20263 0x0D38 +#define PCI_DEVICE_ID_PROMISE_20268 0x4d68 +#define PCI_DEVICE_ID_PROMISE_20269 0x4d69 +#define PCI_DEVICE_ID_PROMISE_20270 0x6268 +#define PCI_DEVICE_ID_PROMISE_20271 0x6269 +#define PCI_DEVICE_ID_PROMISE_20275 0x1275 +#define PCI_DEVICE_ID_PROMISE_20276 0x5275 +#define PCI_DEVICE_ID_PROMISE_20277 0x7275 + +#define PCI_VENDOR_ID_UMC 0x1060 +#define PCI_DEVICE_ID_UMC_UM8673F 0x0101 +#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a +#define PCI_DEVICE_ID_UMC_UM8886A 0x886a + +#define PCI_VENDOR_ID_PICOPOWER 0x1066 +#define PCI_DEVICE_ID_PICOPOWER_PT86C523 0x0002 +#define PCI_DEVICE_ID_PICOPOWER_PT86C523BBP 0x8002 + +#define PCI_VENDOR_ID_MYLEX 0x1069 +#define PCI_DEVICE_ID_MYLEX_DAC960_P 0x0001 +#define PCI_DEVICE_ID_MYLEX_DAC960_PD 0x0002 +#define PCI_DEVICE_ID_MYLEX_DAC960_PG 0x0010 +#define PCI_DEVICE_ID_MYLEX_DAC960_LA 0x0020 +#define PCI_DEVICE_ID_MYLEX_DAC960_LP 0x0050 +#define PCI_DEVICE_ID_MYLEX_DAC960_BA 0xBA56 +#define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166 + +#define PCI_VENDOR_ID_APPLE 0x106b +#define PCI_DEVICE_ID_APPLE_BANDIT 0x0001 +#define PCI_DEVICE_ID_APPLE_HYDRA 0x000e +#define PCI_DEVICE_ID_APPLE_UNI_N_FW 0x0018 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020 +#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021 +#define PCI_DEVICE_ID_APPLE_UNI_N_GMACP 0x0024 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P 0x0027 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15 0x002d +#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15 0x002e +#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2 0x0032 +#define PCI_DEVICE_ID_APPLE_UNI_N_ATA 0x0033 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034 +#define PCI_DEVICE_ID_APPLE_IPID_ATA100 0x003b +#define PCI_DEVICE_ID_APPLE_K2_ATA100 0x0043 +#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b +#define PCI_DEVICE_ID_APPLE_K2_GMAC 0x004c +#define PCI_DEVICE_ID_APPLE_SH_ATA 0x0050 +#define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051 +#define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058 +#define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059 +#define PCI_DEVICE_ID_APPLE_IPID2_AGP 0x0066 +#define PCI_DEVICE_ID_APPLE_IPID2_ATA 0x0069 +#define PCI_DEVICE_ID_APPLE_IPID2_FW 0x006a +#define PCI_DEVICE_ID_APPLE_IPID2_GMAC 0x006b +#define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 + +#define PCI_VENDOR_ID_YAMAHA 0x1073 +#define PCI_DEVICE_ID_YAMAHA_724 0x0004 +#define PCI_DEVICE_ID_YAMAHA_724F 0x000d +#define PCI_DEVICE_ID_YAMAHA_740 0x000a +#define PCI_DEVICE_ID_YAMAHA_740C 0x000c +#define PCI_DEVICE_ID_YAMAHA_744 0x0010 +#define PCI_DEVICE_ID_YAMAHA_754 0x0012 + +#define PCI_VENDOR_ID_QLOGIC 0x1077 +#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 +#define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020 +#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 +#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 +#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 +#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 +#define PCI_DEVICE_ID_QLOGIC_ISP2100 0x2100 +#define PCI_DEVICE_ID_QLOGIC_ISP2200 0x2200 +#define PCI_DEVICE_ID_QLOGIC_ISP2300 0x2300 +#define PCI_DEVICE_ID_QLOGIC_ISP2312 0x2312 +#define PCI_DEVICE_ID_QLOGIC_ISP2322 0x2322 +#define PCI_DEVICE_ID_QLOGIC_ISP6312 0x6312 +#define PCI_DEVICE_ID_QLOGIC_ISP6322 0x6322 +#define PCI_DEVICE_ID_QLOGIC_ISP2422 0x2422 +#define PCI_DEVICE_ID_QLOGIC_ISP2432 0x2432 +#define PCI_DEVICE_ID_QLOGIC_ISP2512 0x2512 +#define PCI_DEVICE_ID_QLOGIC_ISP2522 0x2522 +#define PCI_DEVICE_ID_QLOGIC_ISP5422 0x5422 +#define PCI_DEVICE_ID_QLOGIC_ISP5432 0x5432 + +#define PCI_VENDOR_ID_CYRIX 0x1078 +#define PCI_DEVICE_ID_CYRIX_5510 0x0000 +#define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001 +#define PCI_DEVICE_ID_CYRIX_5520 0x0002 +#define PCI_DEVICE_ID_CYRIX_5530_LEGACY 0x0100 +#define PCI_DEVICE_ID_CYRIX_5530_IDE 0x0102 +#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103 +#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104 + +#define PCI_VENDOR_ID_CONTAQ 0x1080 +#define PCI_DEVICE_ID_CONTAQ_82C693 0xc693 + +#define PCI_VENDOR_ID_OLICOM 0x108d +#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012 +#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013 +#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014 + +#define PCI_VENDOR_ID_SUN 0x108e +#define PCI_DEVICE_ID_SUN_EBUS 0x1000 +#define PCI_DEVICE_ID_SUN_HAPPYMEAL 0x1001 +#define PCI_DEVICE_ID_SUN_RIO_EBUS 0x1100 +#define PCI_DEVICE_ID_SUN_RIO_GEM 0x1101 +#define PCI_DEVICE_ID_SUN_RIO_1394 0x1102 +#define PCI_DEVICE_ID_SUN_RIO_USB 0x1103 +#define PCI_DEVICE_ID_SUN_GEM 0x2bad +#define PCI_DEVICE_ID_SUN_SIMBA 0x5000 +#define PCI_DEVICE_ID_SUN_PBM 0x8000 +#define PCI_DEVICE_ID_SUN_SCHIZO 0x8001 +#define PCI_DEVICE_ID_SUN_SABRE 0xa000 +#define PCI_DEVICE_ID_SUN_HUMMINGBIRD 0xa001 +#define PCI_DEVICE_ID_SUN_TOMATILLO 0xa801 +#define PCI_DEVICE_ID_SUN_CASSINI 0xabba + +#define PCI_VENDOR_ID_CMD 0x1095 +#define PCI_DEVICE_ID_CMD_643 0x0643 +#define PCI_DEVICE_ID_CMD_646 0x0646 +#define PCI_DEVICE_ID_CMD_648 0x0648 +#define PCI_DEVICE_ID_CMD_649 0x0649 + +#define PCI_DEVICE_ID_SII_680 0x0680 +#define PCI_DEVICE_ID_SII_3112 0x3112 +#define PCI_DEVICE_ID_SII_1210SA 0x0240 + +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#define PCI_DEVICE_ID_BROOKTREE_878 0x0878 +#define PCI_DEVICE_ID_BROOKTREE_879 0x0879 + +#define PCI_VENDOR_ID_SGI 0x10a9 +#define PCI_DEVICE_ID_SGI_IOC3 0x0003 +#define PCI_DEVICE_ID_SGI_LITHIUM 0x1002 +#define PCI_DEVICE_ID_SGI_IOC4 0x100a + +#define PCI_VENDOR_ID_WINBOND 0x10ad +#define PCI_DEVICE_ID_WINBOND_82C105 0x0105 +#define PCI_DEVICE_ID_WINBOND_83C553 0x0565 + +#define PCI_VENDOR_ID_PLX 0x10b5 +#define PCI_DEVICE_ID_PLX_R685 0x1030 +#define PCI_DEVICE_ID_PLX_ROMULUS 0x106a +#define PCI_DEVICE_ID_PLX_SPCOM800 0x1076 +#define PCI_DEVICE_ID_PLX_1077 0x1077 +#define PCI_DEVICE_ID_PLX_SPCOM200 0x1103 +#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151 +#define PCI_DEVICE_ID_PLX_R753 0x1152 +#define PCI_DEVICE_ID_PLX_OLITEC 0x1187 +#define PCI_DEVICE_ID_PLX_PCI200SYN 0x3196 +#define PCI_DEVICE_ID_PLX_9030 0x9030 +#define PCI_DEVICE_ID_PLX_9050 0x9050 +#define PCI_DEVICE_ID_PLX_9080 0x9080 +#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001 + +#define PCI_VENDOR_ID_MADGE 0x10b6 +#define PCI_DEVICE_ID_MADGE_MK2 0x0002 + +#define PCI_VENDOR_ID_3COM 0x10b7 +#define PCI_DEVICE_ID_3COM_3C985 0x0001 +#define PCI_DEVICE_ID_3COM_3C940 0x1700 +#define PCI_DEVICE_ID_3COM_3C339 0x3390 +#define PCI_DEVICE_ID_3COM_3C359 0x3590 +#define PCI_DEVICE_ID_3COM_3C940B 0x80eb +#define PCI_DEVICE_ID_3COM_3CR990 0x9900 +#define PCI_DEVICE_ID_3COM_3CR990_TX_95 0x9902 +#define PCI_DEVICE_ID_3COM_3CR990_TX_97 0x9903 +#define PCI_DEVICE_ID_3COM_3CR990B 0x9904 +#define PCI_DEVICE_ID_3COM_3CR990_FX 0x9905 +#define PCI_DEVICE_ID_3COM_3CR990SVR95 0x9908 +#define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909 +#define PCI_DEVICE_ID_3COM_3CR990SVR 0x990a + +#define PCI_VENDOR_ID_AL 0x10b9 +#define PCI_DEVICE_ID_AL_M1533 0x1533 +#define PCI_DEVICE_ID_AL_M1535 0x1535 +#define PCI_DEVICE_ID_AL_M1541 0x1541 +#define PCI_DEVICE_ID_AL_M1563 0x1563 +#define PCI_DEVICE_ID_AL_M1621 0x1621 +#define PCI_DEVICE_ID_AL_M1631 0x1631 +#define PCI_DEVICE_ID_AL_M1632 0x1632 +#define PCI_DEVICE_ID_AL_M1641 0x1641 +#define PCI_DEVICE_ID_AL_M1644 0x1644 +#define PCI_DEVICE_ID_AL_M1647 0x1647 +#define PCI_DEVICE_ID_AL_M1651 0x1651 +#define PCI_DEVICE_ID_AL_M1671 0x1671 +#define PCI_DEVICE_ID_AL_M1681 0x1681 +#define PCI_DEVICE_ID_AL_M1683 0x1683 +#define PCI_DEVICE_ID_AL_M1689 0x1689 +#define PCI_DEVICE_ID_AL_M5219 0x5219 +#define PCI_DEVICE_ID_AL_M5228 0x5228 +#define PCI_DEVICE_ID_AL_M5229 0x5229 +#define PCI_DEVICE_ID_AL_M5451 0x5451 +#define PCI_DEVICE_ID_AL_M7101 0x7101 + +#define PCI_VENDOR_ID_NEOMAGIC 0x10c8 +#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005 +#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006 +#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016 + +#define PCI_VENDOR_ID_TCONRAD 0x10da +#define PCI_DEVICE_ID_TCONRAD_TOKENRING 0x0508 + +#define PCI_VENDOR_ID_NVIDIA 0x10de +#define PCI_DEVICE_ID_NVIDIA_TNT 0x0020 +#define PCI_DEVICE_ID_NVIDIA_TNT2 0x0028 +#define PCI_DEVICE_ID_NVIDIA_UTNT2 0x0029 +#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN 0x002a +#define PCI_DEVICE_ID_NVIDIA_VTNT2 0x002C +#define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS 0x0034 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE 0x0035 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036 +#define PCI_DEVICE_ID_NVIDIA_NVENET_10 0x0037 +#define PCI_DEVICE_ID_NVIDIA_NVENET_11 0x0038 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2 0x003e +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800 0x0041 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE 0x0042 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x0045 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000 0x004E +#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS 0x0052 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE 0x0053 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2 0x0055 +#define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056 +#define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057 +#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 +#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE 0x005d +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 +#define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 +#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069 +#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a +#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085 +#define PCI_DEVICE_ID_NVIDIA_NVENET_4 0x0086 +#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089 +#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a +#define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c +#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT 0x0090 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX 0x0091 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800 0x0098 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099 +#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 +#define PCI_DEVICE_ID_GEFORCE_6800A 0x00c1 +#define PCI_DEVICE_ID_GEFORCE_6800A_LE 0x00c2 +#define PCI_DEVICE_ID_GEFORCE_GO_6800 0x00c8 +#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA 0x00c9 +#define PCI_DEVICE_ID_QUADRO_FX_GO1400 0x00cc +#define PCI_DEVICE_ID_QUADRO_FX_1400 0x00ce +#define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5 +#define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6 +#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9 +#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da +#define PCI_DEVICE_ID_NVIDIA_NVENET_7 0x00df +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA 0x00e3 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00e4 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5 +#define PCI_DEVICE_ID_NVIDIA_NVENET_6 0x00e6 +#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9 +#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280 0x00fd +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 +#define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX 0x0110 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2 0x0111 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO 0x0112 +#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR 0x0113 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT 0x0140 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600 0x0141 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL 0x0145 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540 0x014E +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200 0x014F +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS 0x0150 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2 0x0151 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA 0x0152 +#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO 0x0153 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200 0x0164 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250 0x0166 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1 0x0167 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1 0x0168 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460 0x0170 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440 0x0171 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420 0x0172 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE 0x0173 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO 0x0174 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO 0x0175 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO 0x0177 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL 0x0178 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_200 0x017A +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL 0x017B +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL 0x017C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000 0x0185 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO 0x0186 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO 0x0187 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL 0x0188 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC 0x0189 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS 0x018A +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL 0x018B +#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2 0x01a0 +#define PCI_DEVICE_ID_NVIDIA_NFORCE 0x01a4 +#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc +#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM 0x01c1 +#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1 0x0201 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2 0x0202 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC 0x0203 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B 0x0211 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE 0x0212 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT 0x0215 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600 0x0250 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400 0x0251 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200 0x0253 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS 0x0264 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS 0x0368 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE 0x036E +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2 0x037F +#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268 +#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO 0x0286 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL 0x0288 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL 0x0289 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL 0x028C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA 0x0301 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800 0x0302 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000 0x0308 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000 0x0309 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA 0x0311 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600 0x0312 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE 0x0314 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600 0x031A +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650 0x031B +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700 0x031C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200 0x0320 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA 0x0321 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1 0x0322 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE 0x0323 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200 0x0324 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250 0x0325 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500 0x0326 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100 0x0327 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32 0x0328 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200 0x0329 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI 0x032A +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500 0x032B +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300 0x032C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100 0x032D +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA 0x0330 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900 0x0331 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT 0x0332 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA 0x0333 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT 0x0334 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000 0x0338 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700 0x033F +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA 0x0341 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700 0x0342 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE 0x0343 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE 0x0344 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1 0x0347 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E +#define PCI_DEVICE_ID_NVIDIA_NVENET_14 0x0372 +#define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 +#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5 +#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS 0x03EB +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC +#define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE +#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS 0x0446 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448 +#define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450 +#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 +#define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452 +#define PCI_DEVICE_ID_NVIDIA_NVENET_23 0x0453 +#define PCI_DEVICE_ID_NVIDIA_NVENET_24 0x054C +#define PCI_DEVICE_ID_NVIDIA_NVENET_25 0x054D +#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E +#define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F +#define PCI_DEVICE_ID_NVIDIA_NVENET_28 0x07DC +#define PCI_DEVICE_ID_NVIDIA_NVENET_29 0x07DD +#define PCI_DEVICE_ID_NVIDIA_NVENET_30 0x07DE +#define PCI_DEVICE_ID_NVIDIA_NVENET_31 0x07DF +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 +#define PCI_DEVICE_ID_NVIDIA_NVENET_32 0x0760 +#define PCI_DEVICE_ID_NVIDIA_NVENET_33 0x0761 +#define PCI_DEVICE_ID_NVIDIA_NVENET_34 0x0762 +#define PCI_DEVICE_ID_NVIDIA_NVENET_35 0x0763 +#define PCI_DEVICE_ID_NVIDIA_NVENET_36 0x0AB0 +#define PCI_DEVICE_ID_NVIDIA_NVENET_37 0x0AB1 +#define PCI_DEVICE_ID_NVIDIA_NVENET_38 0x0AB2 +#define PCI_DEVICE_ID_NVIDIA_NVENET_39 0x0AB3 + +#define PCI_VENDOR_ID_IMS 0x10e0 +#define PCI_DEVICE_ID_IMS_TT128 0x9128 +#define PCI_DEVICE_ID_IMS_TT3D 0x9135 + +#define PCI_VENDOR_ID_INTERG 0x10ea +#define PCI_DEVICE_ID_INTERG_1682 0x1682 +#define PCI_DEVICE_ID_INTERG_2000 0x2000 +#define PCI_DEVICE_ID_INTERG_2010 0x2010 +#define PCI_DEVICE_ID_INTERG_5000 0x5000 +#define PCI_DEVICE_ID_INTERG_5050 0x5050 + +#define PCI_VENDOR_ID_REALTEK 0x10ec +#define PCI_DEVICE_ID_REALTEK_8139 0x8139 + +#define PCI_VENDOR_ID_XILINX 0x10ee +#define PCI_DEVICE_ID_RME_DIGI96 0x3fc0 +#define PCI_DEVICE_ID_RME_DIGI96_8 0x3fc1 +#define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2 +#define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3 +#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 +#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6 + +#define PCI_VENDOR_ID_INIT 0x1101 + +#define PCI_VENDOR_ID_CREATIVE 0x1102 /* duplicate: ECTIVA */ +#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002 + +#define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */ +#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938 + +#define PCI_VENDOR_ID_TTI 0x1103 +#define PCI_DEVICE_ID_TTI_HPT343 0x0003 +#define PCI_DEVICE_ID_TTI_HPT366 0x0004 +#define PCI_DEVICE_ID_TTI_HPT372 0x0005 +#define PCI_DEVICE_ID_TTI_HPT302 0x0006 +#define PCI_DEVICE_ID_TTI_HPT371 0x0007 +#define PCI_DEVICE_ID_TTI_HPT374 0x0008 +#define PCI_DEVICE_ID_TTI_HPT372N 0x0009 /* apparently a 372N variant? */ + +#define PCI_VENDOR_ID_VIA 0x1106 +#define PCI_DEVICE_ID_VIA_8763_0 0x0198 +#define PCI_DEVICE_ID_VIA_8380_0 0x0204 +#define PCI_DEVICE_ID_VIA_3238_0 0x0238 +#define PCI_DEVICE_ID_VIA_PT880 0x0258 +#define PCI_DEVICE_ID_VIA_PT880ULTRA 0x0308 +#define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259 +#define PCI_DEVICE_ID_VIA_3269_0 0x0269 +#define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282 +#define PCI_DEVICE_ID_VIA_3296_0 0x0296 +#define PCI_DEVICE_ID_VIA_8363_0 0x0305 +#define PCI_DEVICE_ID_VIA_P4M800CE 0x0314 +#define PCI_DEVICE_ID_VIA_P4M890 0x0327 +#define PCI_DEVICE_ID_VIA_VT3324 0x0324 +#define PCI_DEVICE_ID_VIA_VT3336 0x0336 +#define PCI_DEVICE_ID_VIA_VT3351 0x0351 +#define PCI_DEVICE_ID_VIA_VT3364 0x0364 +#define PCI_DEVICE_ID_VIA_8371_0 0x0391 +#define PCI_DEVICE_ID_VIA_8501_0 0x0501 +#define PCI_DEVICE_ID_VIA_82C561 0x0561 +#define PCI_DEVICE_ID_VIA_82C586_1 0x0571 +#define PCI_DEVICE_ID_VIA_82C576 0x0576 +#define PCI_DEVICE_ID_VIA_82C586_0 0x0586 +#define PCI_DEVICE_ID_VIA_82C596 0x0596 +#define PCI_DEVICE_ID_VIA_82C597_0 0x0597 +#define PCI_DEVICE_ID_VIA_82C598_0 0x0598 +#define PCI_DEVICE_ID_VIA_8601_0 0x0601 +#define PCI_DEVICE_ID_VIA_8605_0 0x0605 +#define PCI_DEVICE_ID_VIA_82C686 0x0686 +#define PCI_DEVICE_ID_VIA_82C691_0 0x0691 +#define PCI_DEVICE_ID_VIA_82C576_1 0x1571 +#define PCI_DEVICE_ID_VIA_82C586_2 0x3038 +#define PCI_DEVICE_ID_VIA_82C586_3 0x3040 +#define PCI_DEVICE_ID_VIA_82C596_3 0x3050 +#define PCI_DEVICE_ID_VIA_82C596B_3 0x3051 +#define PCI_DEVICE_ID_VIA_82C686_4 0x3057 +#define PCI_DEVICE_ID_VIA_82C686_5 0x3058 +#define PCI_DEVICE_ID_VIA_8233_5 0x3059 +#define PCI_DEVICE_ID_VIA_8233_0 0x3074 +#define PCI_DEVICE_ID_VIA_8633_0 0x3091 +#define PCI_DEVICE_ID_VIA_8367_0 0x3099 +#define PCI_DEVICE_ID_VIA_8653_0 0x3101 +#define PCI_DEVICE_ID_VIA_8622 0x3102 +#define PCI_DEVICE_ID_VIA_8235_USB_2 0x3104 +#define PCI_DEVICE_ID_VIA_8233C_0 0x3109 +#define PCI_DEVICE_ID_VIA_8361 0x3112 +#define PCI_DEVICE_ID_VIA_XM266 0x3116 +#define PCI_DEVICE_ID_VIA_612X 0x3119 +#define PCI_DEVICE_ID_VIA_862X_0 0x3123 +#define PCI_DEVICE_ID_VIA_8753_0 0x3128 +#define PCI_DEVICE_ID_VIA_8233A 0x3147 +#define PCI_DEVICE_ID_VIA_8703_51_0 0x3148 +#define PCI_DEVICE_ID_VIA_8237_SATA 0x3149 +#define PCI_DEVICE_ID_VIA_XN266 0x3156 +#define PCI_DEVICE_ID_VIA_6410 0x3164 +#define PCI_DEVICE_ID_VIA_8754C_0 0x3168 +#define PCI_DEVICE_ID_VIA_8235 0x3177 +#define PCI_DEVICE_ID_VIA_8385_0 0x3188 +#define PCI_DEVICE_ID_VIA_8377_0 0x3189 +#define PCI_DEVICE_ID_VIA_8378_0 0x3205 +#define PCI_DEVICE_ID_VIA_8783_0 0x3208 +#define PCI_DEVICE_ID_VIA_8237 0x3227 +#define PCI_DEVICE_ID_VIA_8251 0x3287 +#define PCI_DEVICE_ID_VIA_8237A 0x3337 +#define PCI_DEVICE_ID_VIA_8237S 0x3372 +#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x5324 +#define PCI_DEVICE_ID_VIA_8231 0x8231 +#define PCI_DEVICE_ID_VIA_8231_4 0x8235 +#define PCI_DEVICE_ID_VIA_8365_1 0x8305 +#define PCI_DEVICE_ID_VIA_CX700 0x8324 +#define PCI_DEVICE_ID_VIA_CX700_IDE 0x0581 +#define PCI_DEVICE_ID_VIA_VX800 0x8353 +#define PCI_DEVICE_ID_VIA_8371_1 0x8391 +#define PCI_DEVICE_ID_VIA_82C598_1 0x8598 +#define PCI_DEVICE_ID_VIA_838X_1 0xB188 +#define PCI_DEVICE_ID_VIA_83_87XX_1 0xB198 + +#define PCI_VENDOR_ID_SIEMENS 0x110A +#define PCI_DEVICE_ID_SIEMENS_DSCC4 0x2102 + +#define PCI_VENDOR_ID_VORTEX 0x1119 +#define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000 +#define PCI_DEVICE_ID_VORTEX_GDT6000B 0x0001 +#define PCI_DEVICE_ID_VORTEX_GDT6x10 0x0002 +#define PCI_DEVICE_ID_VORTEX_GDT6x20 0x0003 +#define PCI_DEVICE_ID_VORTEX_GDT6530 0x0004 +#define PCI_DEVICE_ID_VORTEX_GDT6550 0x0005 +#define PCI_DEVICE_ID_VORTEX_GDT6x17 0x0006 +#define PCI_DEVICE_ID_VORTEX_GDT6x27 0x0007 +#define PCI_DEVICE_ID_VORTEX_GDT6537 0x0008 +#define PCI_DEVICE_ID_VORTEX_GDT6557 0x0009 +#define PCI_DEVICE_ID_VORTEX_GDT6x15 0x000a +#define PCI_DEVICE_ID_VORTEX_GDT6x25 0x000b +#define PCI_DEVICE_ID_VORTEX_GDT6535 0x000c +#define PCI_DEVICE_ID_VORTEX_GDT6555 0x000d +#define PCI_DEVICE_ID_VORTEX_GDT6x17RP 0x0100 +#define PCI_DEVICE_ID_VORTEX_GDT6x27RP 0x0101 +#define PCI_DEVICE_ID_VORTEX_GDT6537RP 0x0102 +#define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103 +#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104 +#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105 + +#define PCI_VENDOR_ID_EF 0x111a +#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000 +#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002 +#define PCI_DEVICE_ID_EF_ATM_LANAI2 0x0003 +#define PCI_DEVICE_ID_EF_ATM_LANAIHB 0x0005 + +#define PCI_VENDOR_ID_IDT 0x111d +#define PCI_DEVICE_ID_IDT_IDT77201 0x0001 + +#define PCI_VENDOR_ID_FORE 0x1127 +#define PCI_DEVICE_ID_FORE_PCA200E 0x0300 + +#define PCI_VENDOR_ID_PHILIPS 0x1131 +#define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146 +#define PCI_DEVICE_ID_PHILIPS_SAA9730 0x9730 + +#define PCI_VENDOR_ID_EICON 0x1133 +#define PCI_DEVICE_ID_EICON_DIVA20 0xe002 +#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004 +#define PCI_DEVICE_ID_EICON_DIVA201 0xe005 +#define PCI_DEVICE_ID_EICON_DIVA202 0xe00b +#define PCI_DEVICE_ID_EICON_MAESTRA 0xe010 +#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012 +#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 +#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014 + +#define PCI_VENDOR_ID_CISCO 0x1137 + +#define PCI_VENDOR_ID_ZIATECH 0x1138 +#define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550 + + +#define PCI_VENDOR_ID_SYSKONNECT 0x1148 +#define PCI_DEVICE_ID_SYSKONNECT_TR 0x4200 +#define PCI_DEVICE_ID_SYSKONNECT_GE 0x4300 +#define PCI_DEVICE_ID_SYSKONNECT_YU 0x4320 +#define PCI_DEVICE_ID_SYSKONNECT_9DXX 0x4400 +#define PCI_DEVICE_ID_SYSKONNECT_9MXX 0x4500 + +#define PCI_VENDOR_ID_DIGI 0x114f +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070 +#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071 +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072 +#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073 +#define PCI_DEVICE_ID_NEO_2DB9 0x00C8 +#define PCI_DEVICE_ID_NEO_2DB9PRI 0x00C9 +#define PCI_DEVICE_ID_NEO_2RJ45 0x00CA +#define PCI_DEVICE_ID_NEO_2RJ45PRI 0x00CB +#define PCIE_DEVICE_ID_NEO_4_IBM 0x00F4 + +#define PCI_VENDOR_ID_XIRCOM 0x115d +#define PCI_DEVICE_ID_XIRCOM_RBM56G 0x0101 +#define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103 + +#define PCI_VENDOR_ID_SERVERWORKS 0x1166 +#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008 +#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 +#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB 0x0036 +#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103 +#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132 +#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 +#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 +#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 +#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227 + +#define PCI_VENDOR_ID_SBE 0x1176 +#define PCI_DEVICE_ID_SBE_WANXL100 0x0301 +#define PCI_DEVICE_ID_SBE_WANXL200 0x0302 +#define PCI_DEVICE_ID_SBE_WANXL400 0x0104 + +#define PCI_VENDOR_ID_TOSHIBA 0x1179 +#define PCI_DEVICE_ID_TOSHIBA_PICCOLO 0x0102 +#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1 0x0103 +#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2 0x0105 +#define PCI_DEVICE_ID_TOSHIBA_TOPIC95 0x060a +#define PCI_DEVICE_ID_TOSHIBA_TOPIC97 0x060f +#define PCI_DEVICE_ID_TOSHIBA_TOPIC100 0x0617 + +#define PCI_VENDOR_ID_TOSHIBA_2 0x102f +#define PCI_DEVICE_ID_TOSHIBA_TC35815CF 0x0030 +#define PCI_DEVICE_ID_TOSHIBA_TC35815_NWU 0x0031 +#define PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939 0x0032 +#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE 0x0105 +#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 +#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 + +#define PCI_VENDOR_ID_ATTO 0x117c + +#define PCI_VENDOR_ID_RICOH 0x1180 +#define PCI_DEVICE_ID_RICOH_RL5C465 0x0465 +#define PCI_DEVICE_ID_RICOH_RL5C466 0x0466 +#define PCI_DEVICE_ID_RICOH_RL5C475 0x0475 +#define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 +#define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 +#define PCI_DEVICE_ID_RICOH_R5C822 0x0822 +#define PCI_DEVICE_ID_RICOH_R5C832 0x0832 +#define PCI_DEVICE_ID_RICOH_R5C843 0x0843 + +#define PCI_VENDOR_ID_DLINK 0x1186 +#define PCI_DEVICE_ID_DLINK_DGE510T 0x4c00 + +#define PCI_VENDOR_ID_ARTOP 0x1191 +#define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005 +#define PCI_DEVICE_ID_ARTOP_ATP860 0x0006 +#define PCI_DEVICE_ID_ARTOP_ATP860R 0x0007 +#define PCI_DEVICE_ID_ARTOP_ATP865 0x0008 +#define PCI_DEVICE_ID_ARTOP_ATP865R 0x0009 +#define PCI_DEVICE_ID_ARTOP_AEC7610 0x8002 +#define PCI_DEVICE_ID_ARTOP_AEC7612UW 0x8010 +#define PCI_DEVICE_ID_ARTOP_AEC7612U 0x8020 +#define PCI_DEVICE_ID_ARTOP_AEC7612S 0x8030 +#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040 +#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050 +#define PCI_DEVICE_ID_ARTOP_8060 0x8060 + +#define PCI_VENDOR_ID_ZEITNET 0x1193 +#define PCI_DEVICE_ID_ZEITNET_1221 0x0001 +#define PCI_DEVICE_ID_ZEITNET_1225 0x0002 + +#define PCI_VENDOR_ID_FUJITSU_ME 0x119e +#define PCI_DEVICE_ID_FUJITSU_FS155 0x0001 +#define PCI_DEVICE_ID_FUJITSU_FS50 0x0003 + +#define PCI_SUBVENDOR_ID_KEYSPAN 0x11a9 +#define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334 + +#define PCI_VENDOR_ID_MARVELL 0x11ab +#define PCI_DEVICE_ID_MARVELL_GT64111 0x4146 +#define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 +#define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 +#define PCI_DEVICE_ID_MARVELL_MV64460 0x6480 +#define PCI_DEVICE_ID_MARVELL_88ALP01_NAND 0x4100 +#define PCI_DEVICE_ID_MARVELL_88ALP01_SD 0x4101 +#define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC 0x4102 + +#define PCI_VENDOR_ID_V3 0x11b0 +#define PCI_DEVICE_ID_V3_V960 0x0001 +#define PCI_DEVICE_ID_V3_V351 0x0002 + +#define PCI_VENDOR_ID_ATT 0x11c1 +#define PCI_DEVICE_ID_ATT_VENUS_MODEM 0x480 + +#define PCI_VENDOR_ID_SPECIALIX 0x11cb +#define PCI_DEVICE_ID_SPECIALIX_IO8 0x2000 +#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000 +#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004 + +#define PCI_VENDOR_ID_ANALOG_DEVICES 0x11d4 +#define PCI_DEVICE_ID_AD1889JS 0x1889 + +#define PCI_DEVICE_ID_SEGA_BBA 0x1234 + +#define PCI_VENDOR_ID_ZORAN 0x11de +#define PCI_DEVICE_ID_ZORAN_36057 0x6057 +#define PCI_DEVICE_ID_ZORAN_36120 0x6120 + +#define PCI_VENDOR_ID_COMPEX 0x11f6 +#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112 + +#define PCI_VENDOR_ID_RP 0x11fe +#define PCI_DEVICE_ID_RP32INTF 0x0001 +#define PCI_DEVICE_ID_RP8INTF 0x0002 +#define PCI_DEVICE_ID_RP16INTF 0x0003 +#define PCI_DEVICE_ID_RP4QUAD 0x0004 +#define PCI_DEVICE_ID_RP8OCTA 0x0005 +#define PCI_DEVICE_ID_RP8J 0x0006 +#define PCI_DEVICE_ID_RP4J 0x0007 +#define PCI_DEVICE_ID_RP8SNI 0x0008 +#define PCI_DEVICE_ID_RP16SNI 0x0009 +#define PCI_DEVICE_ID_RPP4 0x000A +#define PCI_DEVICE_ID_RPP8 0x000B +#define PCI_DEVICE_ID_RP4M 0x000D +#define PCI_DEVICE_ID_RP2_232 0x000E +#define PCI_DEVICE_ID_RP2_422 0x000F +#define PCI_DEVICE_ID_URP32INTF 0x0801 +#define PCI_DEVICE_ID_URP8INTF 0x0802 +#define PCI_DEVICE_ID_URP16INTF 0x0803 +#define PCI_DEVICE_ID_URP8OCTA 0x0805 +#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C +#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D +#define PCI_DEVICE_ID_CRP16INTF 0x0903 + +#define PCI_VENDOR_ID_CYCLADES 0x120e +#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100 +#define PCI_DEVICE_ID_CYCLOM_Y_Hi 0x0101 +#define PCI_DEVICE_ID_CYCLOM_4Y_Lo 0x0102 +#define PCI_DEVICE_ID_CYCLOM_4Y_Hi 0x0103 +#define PCI_DEVICE_ID_CYCLOM_8Y_Lo 0x0104 +#define PCI_DEVICE_ID_CYCLOM_8Y_Hi 0x0105 +#define PCI_DEVICE_ID_CYCLOM_Z_Lo 0x0200 +#define PCI_DEVICE_ID_CYCLOM_Z_Hi 0x0201 +#define PCI_DEVICE_ID_PC300_RX_2 0x0300 +#define PCI_DEVICE_ID_PC300_RX_1 0x0301 +#define PCI_DEVICE_ID_PC300_TE_2 0x0310 +#define PCI_DEVICE_ID_PC300_TE_1 0x0311 +#define PCI_DEVICE_ID_PC300_TE_M_2 0x0320 +#define PCI_DEVICE_ID_PC300_TE_M_1 0x0321 + +#define PCI_VENDOR_ID_ESSENTIAL 0x120f +#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001 + +#define PCI_VENDOR_ID_O2 0x1217 +#define PCI_DEVICE_ID_O2_6729 0x6729 +#define PCI_DEVICE_ID_O2_6730 0x673a +#define PCI_DEVICE_ID_O2_6832 0x6832 +#define PCI_DEVICE_ID_O2_6836 0x6836 + +#define PCI_VENDOR_ID_3DFX 0x121a +#define PCI_DEVICE_ID_3DFX_VOODOO 0x0001 +#define PCI_DEVICE_ID_3DFX_VOODOO2 0x0002 +#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003 +#define PCI_DEVICE_ID_3DFX_VOODOO3 0x0005 +#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009 + +#define PCI_VENDOR_ID_AVM 0x1244 +#define PCI_DEVICE_ID_AVM_B1 0x0700 +#define PCI_DEVICE_ID_AVM_C4 0x0800 +#define PCI_DEVICE_ID_AVM_A1 0x0a00 +#define PCI_DEVICE_ID_AVM_A1_V2 0x0e00 +#define PCI_DEVICE_ID_AVM_C2 0x1100 +#define PCI_DEVICE_ID_AVM_T1 0x1200 + +#define PCI_VENDOR_ID_STALLION 0x124d + +/* Allied Telesyn */ +#define PCI_VENDOR_ID_AT 0x1259 +#define PCI_SUBDEVICE_ID_AT_2700FX 0x2701 +#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703 + +#define PCI_VENDOR_ID_ESS 0x125d +#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 +#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 +#define PCI_DEVICE_ID_ESS_ALLEGRO_1 0x1988 +#define PCI_DEVICE_ID_ESS_ALLEGRO 0x1989 +#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990 +#define PCI_DEVICE_ID_ESS_CANYON3D_2 0x1992 +#define PCI_DEVICE_ID_ESS_MAESTRO3 0x1998 +#define PCI_DEVICE_ID_ESS_MAESTRO3_1 0x1999 +#define PCI_DEVICE_ID_ESS_MAESTRO3_HW 0x199a +#define PCI_DEVICE_ID_ESS_MAESTRO3_2 0x199b + +#define PCI_VENDOR_ID_SATSAGEM 0x1267 +#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016 + +#define PCI_VENDOR_ID_ENSONIQ 0x1274 +#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880 +#define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000 +#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371 + +#define PCI_VENDOR_ID_TRANSMETA 0x1279 +#define PCI_DEVICE_ID_EFFICEON 0x0060 + +#define PCI_VENDOR_ID_ROCKWELL 0x127A + +#define PCI_VENDOR_ID_ITE 0x1283 +#define PCI_DEVICE_ID_ITE_8211 0x8211 +#define PCI_DEVICE_ID_ITE_8212 0x8212 +#define PCI_DEVICE_ID_ITE_8213 0x8213 +#define PCI_DEVICE_ID_ITE_8152 0x8152 +#define PCI_DEVICE_ID_ITE_8872 0x8872 +#define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886 + +/* formerly Platform Tech */ +#define PCI_DEVICE_ID_ESS_ESS0100 0x0100 + +#define PCI_VENDOR_ID_ALTEON 0x12ae + +#define PCI_SUBVENDOR_ID_CONNECT_TECH 0x12c4 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232 0x0001 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232 0x0002 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232 0x0003 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485 0x0004 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4 0x0005 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485 0x0006 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2 0x0007 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485 0x0008 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6 0x0009 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1 0x000A +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1 0x000B +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ 0x000C +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_PTM 0x000D +#define PCI_SUBDEVICE_ID_CONNECT_TECH_NT960PCI 0x0100 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2 0x0201 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4 0x0202 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232 0x0300 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232 0x0301 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232 0x0302 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1 0x0310 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2 0x0311 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4 0x0312 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2 0x0320 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4 0x0321 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8 0x0322 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485 0x0330 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485 0x0331 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485 0x0332 + +#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2 +#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018 + +#define PCI_SUBVENDOR_ID_CHASE_PCIFAST 0x12E0 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4 0x0031 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8 0x0021 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16 0x0011 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC 0x0041 +#define PCI_SUBVENDOR_ID_CHASE_PCIRAS 0x124D +#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4 0xF001 +#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8 0xF010 + +#define PCI_VENDOR_ID_AUREAL 0x12eb +#define PCI_DEVICE_ID_AUREAL_VORTEX_1 0x0001 +#define PCI_DEVICE_ID_AUREAL_VORTEX_2 0x0002 +#define PCI_DEVICE_ID_AUREAL_ADVANTAGE 0x0003 + +#define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8 +#define PCI_DEVICE_ID_LML_33R10 0x8a02 + +#define PCI_VENDOR_ID_ESDGMBH 0x12fe +#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111 + +#define PCI_VENDOR_ID_SIIG 0x131f +#define PCI_SUBVENDOR_ID_SIIG 0x131f +#define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000 +#define PCI_DEVICE_ID_SIIG_1S_10x_650 0x1001 +#define PCI_DEVICE_ID_SIIG_1S_10x_850 0x1002 +#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010 +#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011 +#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012 +#define PCI_DEVICE_ID_SIIG_1P_10x 0x1020 +#define PCI_DEVICE_ID_SIIG_2P_10x 0x1021 +#define PCI_DEVICE_ID_SIIG_2S_10x_550 0x1030 +#define PCI_DEVICE_ID_SIIG_2S_10x_650 0x1031 +#define PCI_DEVICE_ID_SIIG_2S_10x_850 0x1032 +#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034 +#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035 +#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036 +#define PCI_DEVICE_ID_SIIG_4S_10x_550 0x1050 +#define PCI_DEVICE_ID_SIIG_4S_10x_650 0x1051 +#define PCI_DEVICE_ID_SIIG_4S_10x_850 0x1052 +#define PCI_DEVICE_ID_SIIG_1S_20x_550 0x2000 +#define PCI_DEVICE_ID_SIIG_1S_20x_650 0x2001 +#define PCI_DEVICE_ID_SIIG_1S_20x_850 0x2002 +#define PCI_DEVICE_ID_SIIG_1P_20x 0x2020 +#define PCI_DEVICE_ID_SIIG_2P_20x 0x2021 +#define PCI_DEVICE_ID_SIIG_2S_20x_550 0x2030 +#define PCI_DEVICE_ID_SIIG_2S_20x_650 0x2031 +#define PCI_DEVICE_ID_SIIG_2S_20x_850 0x2032 +#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040 +#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041 +#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042 +#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010 +#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011 +#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012 +#define PCI_DEVICE_ID_SIIG_4S_20x_550 0x2050 +#define PCI_DEVICE_ID_SIIG_4S_20x_650 0x2051 +#define PCI_DEVICE_ID_SIIG_4S_20x_850 0x2052 +#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060 +#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061 +#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062 +#define PCI_DEVICE_ID_SIIG_8S_20x_550 0x2080 +#define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 +#define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 +#define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 + +#define PCI_VENDOR_ID_RADISYS 0x1331 + +#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332 +#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415 +#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425 +#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155 + +#define PCI_VENDOR_ID_DOMEX 0x134a +#define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 + +#define PCI_VENDOR_ID_INTASHIELD 0x135a +#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80 +#define PCI_DEVICE_ID_INTASHIELD_IS400 0x0dc0 + +#define PCI_VENDOR_ID_QUATECH 0x135C +#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 +#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020 +#define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050 +#define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060 +#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278 + +#define PCI_VENDOR_ID_SEALEVEL 0x135e +#define PCI_DEVICE_ID_SEALEVEL_U530 0x7101 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM2 0x7201 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM422 0x7402 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM232 0x7202 +#define PCI_DEVICE_ID_SEALEVEL_COMM4 0x7401 +#define PCI_DEVICE_ID_SEALEVEL_COMM8 0x7801 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM8 0x7804 + +#define PCI_VENDOR_ID_HYPERCOPE 0x1365 +#define PCI_DEVICE_ID_HYPERCOPE_PLX 0x9050 +#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO 0x0104 +#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO 0x0106 +#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO 0x0107 +#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108 + +#define PCI_VENDOR_ID_KAWASAKI 0x136b +#define PCI_DEVICE_ID_MCHIP_KL5A72002 0xff01 + +#define PCI_VENDOR_ID_CNET 0x1371 +#define PCI_DEVICE_ID_CNET_GIGACARD 0x434e + +#define PCI_VENDOR_ID_LMC 0x1376 +#define PCI_DEVICE_ID_LMC_HSSI 0x0003 +#define PCI_DEVICE_ID_LMC_DS3 0x0004 +#define PCI_DEVICE_ID_LMC_SSI 0x0005 +#define PCI_DEVICE_ID_LMC_T1 0x0006 + +#define PCI_VENDOR_ID_NETGEAR 0x1385 +#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a + +#define PCI_VENDOR_ID_APPLICOM 0x1389 +#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001 +#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002 +#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 + +#define PCI_VENDOR_ID_MOXA 0x1393 +#define PCI_DEVICE_ID_MOXA_RC7000 0x0001 +#define PCI_DEVICE_ID_MOXA_CP102 0x1020 +#define PCI_DEVICE_ID_MOXA_CP102UL 0x1021 +#define PCI_DEVICE_ID_MOXA_CP102U 0x1022 +#define PCI_DEVICE_ID_MOXA_C104 0x1040 +#define PCI_DEVICE_ID_MOXA_CP104U 0x1041 +#define PCI_DEVICE_ID_MOXA_CP104JU 0x1042 +#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043 +#define PCI_DEVICE_ID_MOXA_CT114 0x1140 +#define PCI_DEVICE_ID_MOXA_CP114 0x1141 +#define PCI_DEVICE_ID_MOXA_CP118U 0x1180 +#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181 +#define PCI_DEVICE_ID_MOXA_CP132 0x1320 +#define PCI_DEVICE_ID_MOXA_CP132U 0x1321 +#define PCI_DEVICE_ID_MOXA_CP134U 0x1340 +#define PCI_DEVICE_ID_MOXA_C168 0x1680 +#define PCI_DEVICE_ID_MOXA_CP168U 0x1681 +#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682 +#define PCI_DEVICE_ID_MOXA_CP204J 0x2040 +#define PCI_DEVICE_ID_MOXA_C218 0x2180 +#define PCI_DEVICE_ID_MOXA_C320 0x3200 + +#define PCI_VENDOR_ID_CCD 0x1397 +#define PCI_DEVICE_ID_CCD_HFC4S 0x08B4 +#define PCI_SUBDEVICE_ID_CCD_PMX2S 0x1234 +#define PCI_DEVICE_ID_CCD_HFC8S 0x16B8 +#define PCI_DEVICE_ID_CCD_2BD0 0x2bd0 +#define PCI_DEVICE_ID_CCD_HFCE1 0x30B1 +#define PCI_SUBDEVICE_ID_CCD_SPD4S 0x3136 +#define PCI_SUBDEVICE_ID_CCD_SPDE1 0x3137 +#define PCI_DEVICE_ID_CCD_B000 0xb000 +#define PCI_DEVICE_ID_CCD_B006 0xb006 +#define PCI_DEVICE_ID_CCD_B007 0xb007 +#define PCI_DEVICE_ID_CCD_B008 0xb008 +#define PCI_DEVICE_ID_CCD_B009 0xb009 +#define PCI_DEVICE_ID_CCD_B00A 0xb00a +#define PCI_DEVICE_ID_CCD_B00B 0xb00b +#define PCI_DEVICE_ID_CCD_B00C 0xb00c +#define PCI_DEVICE_ID_CCD_B100 0xb100 +#define PCI_SUBDEVICE_ID_CCD_IOB4ST 0xB520 +#define PCI_SUBDEVICE_ID_CCD_IOB8STR 0xB521 +#define PCI_SUBDEVICE_ID_CCD_IOB8ST 0xB522 +#define PCI_SUBDEVICE_ID_CCD_IOB1E1 0xB523 +#define PCI_SUBDEVICE_ID_CCD_SWYX4S 0xB540 +#define PCI_SUBDEVICE_ID_CCD_JH4S20 0xB550 +#define PCI_SUBDEVICE_ID_CCD_IOB8ST_1 0xB552 +#define PCI_SUBDEVICE_ID_CCD_BN4S 0xB560 +#define PCI_SUBDEVICE_ID_CCD_BN8S 0xB562 +#define PCI_SUBDEVICE_ID_CCD_BNE1 0xB563 +#define PCI_SUBDEVICE_ID_CCD_BNE1D 0xB564 +#define PCI_SUBDEVICE_ID_CCD_BNE1DP 0xB565 +#define PCI_SUBDEVICE_ID_CCD_BN2S 0xB566 +#define PCI_SUBDEVICE_ID_CCD_BN1SM 0xB567 +#define PCI_SUBDEVICE_ID_CCD_BN4SM 0xB568 +#define PCI_SUBDEVICE_ID_CCD_BN2SM 0xB569 +#define PCI_SUBDEVICE_ID_CCD_BNE1M 0xB56A +#define PCI_SUBDEVICE_ID_CCD_BN8SP 0xB56B +#define PCI_SUBDEVICE_ID_CCD_HFC4S 0xB620 +#define PCI_SUBDEVICE_ID_CCD_HFC8S 0xB622 +#define PCI_DEVICE_ID_CCD_B700 0xb700 +#define PCI_DEVICE_ID_CCD_B701 0xb701 +#define PCI_SUBDEVICE_ID_CCD_HFCE1 0xC523 +#define PCI_SUBDEVICE_ID_CCD_OV2S 0xE884 +#define PCI_SUBDEVICE_ID_CCD_OV4S 0xE888 +#define PCI_SUBDEVICE_ID_CCD_OV8S 0xE998 + +#define PCI_VENDOR_ID_EXAR 0x13a8 +#define PCI_DEVICE_ID_EXAR_XR17C152 0x0152 +#define PCI_DEVICE_ID_EXAR_XR17C154 0x0154 +#define PCI_DEVICE_ID_EXAR_XR17C158 0x0158 + +#define PCI_VENDOR_ID_MICROGATE 0x13c0 +#define PCI_DEVICE_ID_MICROGATE_USC 0x0010 +#define PCI_DEVICE_ID_MICROGATE_SCA 0x0030 + +#define PCI_VENDOR_ID_3WARE 0x13C1 +#define PCI_DEVICE_ID_3WARE_1000 0x1000 +#define PCI_DEVICE_ID_3WARE_7000 0x1001 +#define PCI_DEVICE_ID_3WARE_9000 0x1002 + +#define PCI_VENDOR_ID_IOMEGA 0x13ca +#define PCI_DEVICE_ID_IOMEGA_BUZ 0x4231 + +#define PCI_VENDOR_ID_ABOCOM 0x13D1 +#define PCI_DEVICE_ID_ABOCOM_2BD1 0x2BD1 + +#define PCI_VENDOR_ID_SUNDANCE 0x13f0 + +#define PCI_VENDOR_ID_CMEDIA 0x13f6 +#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100 +#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101 +#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 +#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112 + +#define PCI_VENDOR_ID_LAVA 0x1407 +#define PCI_DEVICE_ID_LAVA_DSERIAL 0x0100 /* 2x 16550 */ +#define PCI_DEVICE_ID_LAVA_QUATRO_A 0x0101 /* 2x 16550, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_QUATRO_B 0x0102 /* 2x 16550, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_OCTO_A 0x0180 /* 4x 16550A, half of 8 port */ +#define PCI_DEVICE_ID_LAVA_OCTO_B 0x0181 /* 4x 16550A, half of 8 port */ +#define PCI_DEVICE_ID_LAVA_PORT_PLUS 0x0200 /* 2x 16650 */ +#define PCI_DEVICE_ID_LAVA_QUAD_A 0x0201 /* 2x 16650, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_QUAD_B 0x0202 /* 2x 16650, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_SSERIAL 0x0500 /* 1x 16550 */ +#define PCI_DEVICE_ID_LAVA_PORT_650 0x0600 /* 1x 16650 */ +#define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000 +#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8002 /* The Lava Dual Parallel is */ +#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8003 /* two PCI devices on a card */ +#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR 0x8800 + +#define PCI_VENDOR_ID_TIMEDIA 0x1409 +#define PCI_DEVICE_ID_TIMEDIA_1889 0x7168 + +#define PCI_VENDOR_ID_ICE 0x1412 +#define PCI_DEVICE_ID_ICE_1712 0x1712 +#define PCI_DEVICE_ID_VT1724 0x1724 + +#define PCI_VENDOR_ID_OXSEMI 0x1415 +#define PCI_DEVICE_ID_OXSEMI_12PCI840 0x8403 +#define PCI_DEVICE_ID_OXSEMI_PCIe840 0xC000 +#define PCI_DEVICE_ID_OXSEMI_PCIe840_G 0xC004 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_0 0xC100 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_0_G 0xC104 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1 0xC110 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_G 0xC114 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_U 0xC118 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU 0xC11C +#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501 +#define PCI_DEVICE_ID_OXSEMI_16PCI95N 0x9511 +#define PCI_DEVICE_ID_OXSEMI_16PCI954PP 0x9513 +#define PCI_DEVICE_ID_OXSEMI_16PCI952 0x9521 +#define PCI_DEVICE_ID_OXSEMI_16PCI952PP 0x9523 + +#define PCI_VENDOR_ID_CHELSIO 0x1425 + +#define PCI_VENDOR_ID_SAMSUNG 0x144d + +#define PCI_VENDOR_ID_MYRICOM 0x14c1 + +#define PCI_VENDOR_ID_TITAN 0x14D2 +#define PCI_DEVICE_ID_TITAN_010L 0x8001 +#define PCI_DEVICE_ID_TITAN_100L 0x8010 +#define PCI_DEVICE_ID_TITAN_110L 0x8011 +#define PCI_DEVICE_ID_TITAN_200L 0x8020 +#define PCI_DEVICE_ID_TITAN_210L 0x8021 +#define PCI_DEVICE_ID_TITAN_400L 0x8040 +#define PCI_DEVICE_ID_TITAN_800L 0x8080 +#define PCI_DEVICE_ID_TITAN_100 0xA001 +#define PCI_DEVICE_ID_TITAN_200 0xA005 +#define PCI_DEVICE_ID_TITAN_400 0xA003 +#define PCI_DEVICE_ID_TITAN_800B 0xA004 + +#define PCI_VENDOR_ID_PANACOM 0x14d4 +#define PCI_DEVICE_ID_PANACOM_QUADMODEM 0x0400 +#define PCI_DEVICE_ID_PANACOM_DUALMODEM 0x0402 + +#define PCI_VENDOR_ID_SIPACKETS 0x14d9 +#define PCI_DEVICE_ID_SP1011 0x0010 + +#define PCI_VENDOR_ID_AFAVLAB 0x14db +#define PCI_DEVICE_ID_AFAVLAB_P028 0x2180 +#define PCI_DEVICE_ID_AFAVLAB_P030 0x2182 +#define PCI_SUBDEVICE_ID_AFAVLAB_P061 0x2150 + +#define PCI_VENDOR_ID_BROADCOM 0x14e4 +#define PCI_DEVICE_ID_TIGON3_5752 0x1600 +#define PCI_DEVICE_ID_TIGON3_5752M 0x1601 +#define PCI_DEVICE_ID_NX2_5709 0x1639 +#define PCI_DEVICE_ID_NX2_5709S 0x163a +#define PCI_DEVICE_ID_TIGON3_5700 0x1644 +#define PCI_DEVICE_ID_TIGON3_5701 0x1645 +#define PCI_DEVICE_ID_TIGON3_5702 0x1646 +#define PCI_DEVICE_ID_TIGON3_5703 0x1647 +#define PCI_DEVICE_ID_TIGON3_5704 0x1648 +#define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 +#define PCI_DEVICE_ID_NX2_5706 0x164a +#define PCI_DEVICE_ID_NX2_5708 0x164c +#define PCI_DEVICE_ID_TIGON3_5702FE 0x164d +#define PCI_DEVICE_ID_NX2_57710 0x164e +#define PCI_DEVICE_ID_NX2_57711 0x164f +#define PCI_DEVICE_ID_NX2_57711E 0x1650 +#define PCI_DEVICE_ID_TIGON3_5705 0x1653 +#define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 +#define PCI_DEVICE_ID_TIGON3_5720 0x1658 +#define PCI_DEVICE_ID_TIGON3_5721 0x1659 +#define PCI_DEVICE_ID_TIGON3_5722 0x165a +#define PCI_DEVICE_ID_TIGON3_5723 0x165b +#define PCI_DEVICE_ID_TIGON3_5705M 0x165d +#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e +#define PCI_DEVICE_ID_TIGON3_5714 0x1668 +#define PCI_DEVICE_ID_TIGON3_5714S 0x1669 +#define PCI_DEVICE_ID_TIGON3_5780 0x166a +#define PCI_DEVICE_ID_TIGON3_5780S 0x166b +#define PCI_DEVICE_ID_TIGON3_5705F 0x166e +#define PCI_DEVICE_ID_TIGON3_5754M 0x1672 +#define PCI_DEVICE_ID_TIGON3_5755M 0x1673 +#define PCI_DEVICE_ID_TIGON3_5756 0x1674 +#define PCI_DEVICE_ID_TIGON3_5750 0x1676 +#define PCI_DEVICE_ID_TIGON3_5751 0x1677 +#define PCI_DEVICE_ID_TIGON3_5715 0x1678 +#define PCI_DEVICE_ID_TIGON3_5715S 0x1679 +#define PCI_DEVICE_ID_TIGON3_5754 0x167a +#define PCI_DEVICE_ID_TIGON3_5755 0x167b +#define PCI_DEVICE_ID_TIGON3_5750M 0x167c +#define PCI_DEVICE_ID_TIGON3_5751M 0x167d +#define PCI_DEVICE_ID_TIGON3_5751F 0x167e +#define PCI_DEVICE_ID_TIGON3_5787F 0x167f +#define PCI_DEVICE_ID_TIGON3_5761E 0x1680 +#define PCI_DEVICE_ID_TIGON3_5761 0x1681 +#define PCI_DEVICE_ID_TIGON3_5764 0x1684 +#define PCI_DEVICE_ID_TIGON3_5787M 0x1693 +#define PCI_DEVICE_ID_TIGON3_5782 0x1696 +#define PCI_DEVICE_ID_TIGON3_5784 0x1698 +#define PCI_DEVICE_ID_TIGON3_5785 0x1699 +#define PCI_DEVICE_ID_TIGON3_5786 0x169a +#define PCI_DEVICE_ID_TIGON3_5787 0x169b +#define PCI_DEVICE_ID_TIGON3_5788 0x169c +#define PCI_DEVICE_ID_TIGON3_5789 0x169d +#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 +#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 +#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 +#define PCI_DEVICE_ID_NX2_5706S 0x16aa +#define PCI_DEVICE_ID_NX2_5708S 0x16ac +#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 +#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 +#define PCI_DEVICE_ID_TIGON3_5781 0x16dd +#define PCI_DEVICE_ID_TIGON3_5753 0x16f7 +#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd +#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe +#define PCI_DEVICE_ID_TIGON3_5901 0x170d +#define PCI_DEVICE_ID_BCM4401B1 0x170c +#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e +#define PCI_DEVICE_ID_TIGON3_5906 0x1712 +#define PCI_DEVICE_ID_TIGON3_5906M 0x1713 +#define PCI_DEVICE_ID_BCM4401 0x4401 +#define PCI_DEVICE_ID_BCM4401B0 0x4402 + +#define PCI_VENDOR_ID_TOPIC 0x151f +#define PCI_DEVICE_ID_TOPIC_TP560 0x0000 + +#define PCI_VENDOR_ID_MAINPINE 0x1522 +#define PCI_DEVICE_ID_MAINPINE_PBRIDGE 0x0100 +#define PCI_VENDOR_ID_ENE 0x1524 +#define PCI_DEVICE_ID_ENE_CB712_SD 0x0550 +#define PCI_DEVICE_ID_ENE_CB712_SD_2 0x0551 +#define PCI_DEVICE_ID_ENE_CB714_SD 0x0750 +#define PCI_DEVICE_ID_ENE_CB714_SD_2 0x0751 +#define PCI_DEVICE_ID_ENE_1211 0x1211 +#define PCI_DEVICE_ID_ENE_1225 0x1225 +#define PCI_DEVICE_ID_ENE_1410 0x1410 +#define PCI_DEVICE_ID_ENE_710 0x1411 +#define PCI_DEVICE_ID_ENE_712 0x1412 +#define PCI_DEVICE_ID_ENE_1420 0x1420 +#define PCI_DEVICE_ID_ENE_720 0x1421 +#define PCI_DEVICE_ID_ENE_722 0x1422 + +#define PCI_SUBVENDOR_ID_PERLE 0x155f +#define PCI_SUBDEVICE_ID_PCI_RAS4 0xf001 +#define PCI_SUBDEVICE_ID_PCI_RAS8 0xf010 + +#define PCI_VENDOR_ID_SYBA 0x1592 +#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782 +#define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783 + +#define PCI_VENDOR_ID_MORETON 0x15aa +#define PCI_DEVICE_ID_RASTEL_2PORT 0x2000 + +#define PCI_VENDOR_ID_ZOLTRIX 0x15b0 +#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0 + +#define PCI_VENDOR_ID_MELLANOX 0x15b3 +#define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 +#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE 0x5a46 +#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 +#define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 +#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c +#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274 + +#define PCI_VENDOR_ID_QUICKNET 0x15e2 +#define PCI_DEVICE_ID_QUICKNET_XJ 0x0500 + +/* + * ADDI-DATA GmbH communication cards + */ +#define PCI_VENDOR_ID_ADDIDATA_OLD 0x10E8 +#define PCI_VENDOR_ID_ADDIDATA 0x15B8 +#define PCI_DEVICE_ID_ADDIDATA_APCI7500 0x7000 +#define PCI_DEVICE_ID_ADDIDATA_APCI7420 0x7001 +#define PCI_DEVICE_ID_ADDIDATA_APCI7300 0x7002 +#define PCI_DEVICE_ID_ADDIDATA_APCI7800 0x818E +#define PCI_DEVICE_ID_ADDIDATA_APCI7500_2 0x7009 +#define PCI_DEVICE_ID_ADDIDATA_APCI7420_2 0x700A +#define PCI_DEVICE_ID_ADDIDATA_APCI7300_2 0x700B +#define PCI_DEVICE_ID_ADDIDATA_APCI7500_3 0x700C +#define PCI_DEVICE_ID_ADDIDATA_APCI7420_3 0x700D +#define PCI_DEVICE_ID_ADDIDATA_APCI7300_3 0x700E +#define PCI_DEVICE_ID_ADDIDATA_APCI7800_3 0x700F + +#define PCI_VENDOR_ID_PDC 0x15e9 + +#define PCI_VENDOR_ID_FARSITE 0x1619 +#define PCI_DEVICE_ID_FARSITE_T2P 0x0400 +#define PCI_DEVICE_ID_FARSITE_T4P 0x0440 +#define PCI_DEVICE_ID_FARSITE_T1U 0x0610 +#define PCI_DEVICE_ID_FARSITE_T2U 0x0620 +#define PCI_DEVICE_ID_FARSITE_T4U 0x0640 +#define PCI_DEVICE_ID_FARSITE_TE1 0x1610 +#define PCI_DEVICE_ID_FARSITE_TE1C 0x1612 + +#define PCI_VENDOR_ID_ARIMA 0x161f + +#define PCI_VENDOR_ID_BROCADE 0x1657 + +#define PCI_VENDOR_ID_SIBYTE 0x166d +#define PCI_DEVICE_ID_BCM1250_PCI 0x0001 +#define PCI_DEVICE_ID_BCM1250_HT 0x0002 + +#define PCI_VENDOR_ID_ATHEROS 0x168c + +#define PCI_VENDOR_ID_NETCELL 0x169c +#define PCI_DEVICE_ID_REVOLUTION 0x0044 + +#define PCI_VENDOR_ID_CENATEK 0x16CA +#define PCI_DEVICE_ID_CENATEK_IDE 0x0001 + +#define PCI_VENDOR_ID_VITESSE 0x1725 +#define PCI_DEVICE_ID_VITESSE_VSC7174 0x7174 + +#define PCI_VENDOR_ID_LINKSYS 0x1737 +#define PCI_DEVICE_ID_LINKSYS_EG1064 0x1064 + +#define PCI_VENDOR_ID_ALTIMA 0x173b +#define PCI_DEVICE_ID_ALTIMA_AC1000 0x03e8 +#define PCI_DEVICE_ID_ALTIMA_AC1001 0x03e9 +#define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea +#define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb + +#define PCI_VENDOR_ID_BELKIN 0x1799 +#define PCI_DEVICE_ID_BELKIN_F5D7010V7 0x701f + +#define PCI_VENDOR_ID_RDC 0x17f3 +#define PCI_DEVICE_ID_RDC_R6020 0x6020 +#define PCI_DEVICE_ID_RDC_R6030 0x6030 +#define PCI_DEVICE_ID_RDC_R6040 0x6040 +#define PCI_DEVICE_ID_RDC_R6060 0x6060 +#define PCI_DEVICE_ID_RDC_R6061 0x6061 + +#define PCI_VENDOR_ID_LENOVO 0x17aa + +#define PCI_VENDOR_ID_ARECA 0x17d3 +#define PCI_DEVICE_ID_ARECA_1110 0x1110 +#define PCI_DEVICE_ID_ARECA_1120 0x1120 +#define PCI_DEVICE_ID_ARECA_1130 0x1130 +#define PCI_DEVICE_ID_ARECA_1160 0x1160 +#define PCI_DEVICE_ID_ARECA_1170 0x1170 +#define PCI_DEVICE_ID_ARECA_1200 0x1200 +#define PCI_DEVICE_ID_ARECA_1201 0x1201 +#define PCI_DEVICE_ID_ARECA_1202 0x1202 +#define PCI_DEVICE_ID_ARECA_1210 0x1210 +#define PCI_DEVICE_ID_ARECA_1220 0x1220 +#define PCI_DEVICE_ID_ARECA_1230 0x1230 +#define PCI_DEVICE_ID_ARECA_1260 0x1260 +#define PCI_DEVICE_ID_ARECA_1270 0x1270 +#define PCI_DEVICE_ID_ARECA_1280 0x1280 +#define PCI_DEVICE_ID_ARECA_1380 0x1380 +#define PCI_DEVICE_ID_ARECA_1381 0x1381 +#define PCI_DEVICE_ID_ARECA_1680 0x1680 +#define PCI_DEVICE_ID_ARECA_1681 0x1681 + +#define PCI_VENDOR_ID_S2IO 0x17d5 +#define PCI_DEVICE_ID_S2IO_WIN 0x5731 +#define PCI_DEVICE_ID_S2IO_UNI 0x5831 +#define PCI_DEVICE_ID_HERC_WIN 0x5732 +#define PCI_DEVICE_ID_HERC_UNI 0x5832 + +#define PCI_VENDOR_ID_SITECOM 0x182d +#define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 + +#define PCI_VENDOR_ID_TOPSPIN 0x1867 + +#define PCI_VENDOR_ID_TDI 0x192E +#define PCI_DEVICE_ID_TDI_EHCI 0x0101 + +#define PCI_VENDOR_ID_FREESCALE 0x1957 +#define PCI_DEVICE_ID_MPC8548E 0x0012 +#define PCI_DEVICE_ID_MPC8548 0x0013 +#define PCI_DEVICE_ID_MPC8543E 0x0014 +#define PCI_DEVICE_ID_MPC8543 0x0015 +#define PCI_DEVICE_ID_MPC8547E 0x0018 +#define PCI_DEVICE_ID_MPC8545E 0x0019 +#define PCI_DEVICE_ID_MPC8545 0x001a +#define PCI_DEVICE_ID_MPC8568E 0x0020 +#define PCI_DEVICE_ID_MPC8568 0x0021 +#define PCI_DEVICE_ID_MPC8567E 0x0022 +#define PCI_DEVICE_ID_MPC8567 0x0023 +#define PCI_DEVICE_ID_MPC8533E 0x0030 +#define PCI_DEVICE_ID_MPC8533 0x0031 +#define PCI_DEVICE_ID_MPC8544E 0x0032 +#define PCI_DEVICE_ID_MPC8544 0x0033 +#define PCI_DEVICE_ID_MPC8572E 0x0040 +#define PCI_DEVICE_ID_MPC8572 0x0041 +#define PCI_DEVICE_ID_MPC8536E 0x0050 +#define PCI_DEVICE_ID_MPC8536 0x0051 +#define PCI_DEVICE_ID_MPC8641 0x7010 +#define PCI_DEVICE_ID_MPC8641D 0x7011 +#define PCI_DEVICE_ID_MPC8610 0x7018 + +#define PCI_VENDOR_ID_PASEMI 0x1959 + +#define PCI_VENDOR_ID_ATTANSIC 0x1969 +#define PCI_DEVICE_ID_ATTANSIC_L1 0x1048 +#define PCI_DEVICE_ID_ATTANSIC_L2 0x2048 + +#define PCI_VENDOR_ID_JMICRON 0x197B +#define PCI_DEVICE_ID_JMICRON_JMB360 0x2360 +#define PCI_DEVICE_ID_JMICRON_JMB361 0x2361 +#define PCI_DEVICE_ID_JMICRON_JMB363 0x2363 +#define PCI_DEVICE_ID_JMICRON_JMB365 0x2365 +#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366 +#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368 +#define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381 +#define PCI_DEVICE_ID_JMICRON_JMB38X_MMC 0x2382 +#define PCI_DEVICE_ID_JMICRON_JMB38X_MS 0x2383 + +#define PCI_VENDOR_ID_KORENIX 0x1982 +#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 +#define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff + +#define PCI_VENDOR_ID_TEKRAM 0x1de1 +#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 + +#define PCI_VENDOR_ID_TEHUTI 0x1fc9 +#define PCI_DEVICE_ID_TEHUTI_3009 0x3009 +#define PCI_DEVICE_ID_TEHUTI_3010 0x3010 +#define PCI_DEVICE_ID_TEHUTI_3014 0x3014 + +#define PCI_VENDOR_ID_HINT 0x3388 +#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013 + +#define PCI_VENDOR_ID_3DLABS 0x3d3d +#define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007 +#define PCI_DEVICE_ID_3DLABS_PERMEDIA2V 0x0009 + +#define PCI_VENDOR_ID_NETXEN 0x4040 +#define PCI_DEVICE_ID_NX2031_10GXSR 0x0001 +#define PCI_DEVICE_ID_NX2031_10GCX4 0x0002 +#define PCI_DEVICE_ID_NX2031_4GCU 0x0003 +#define PCI_DEVICE_ID_NX2031_IMEZ 0x0004 +#define PCI_DEVICE_ID_NX2031_HMEZ 0x0005 +#define PCI_DEVICE_ID_NX2031_XG_MGMT 0x0024 +#define PCI_DEVICE_ID_NX2031_XG_MGMT2 0x0025 +#define PCI_DEVICE_ID_NX3031 0x0100 + +#define PCI_VENDOR_ID_AKS 0x416c +#define PCI_DEVICE_ID_AKS_ALADDINCARD 0x0100 + +#define PCI_VENDOR_ID_S3 0x5333 +#define PCI_DEVICE_ID_S3_TRIO 0x8811 +#define PCI_DEVICE_ID_S3_868 0x8880 +#define PCI_DEVICE_ID_S3_968 0x88f0 +#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25 +#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04 +#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00 + +#define PCI_VENDOR_ID_DUNORD 0x5544 +#define PCI_DEVICE_ID_DUNORD_I3000 0x0001 + +#define PCI_VENDOR_ID_DCI 0x6666 +#define PCI_DEVICE_ID_DCI_PCCOM4 0x0001 +#define PCI_DEVICE_ID_DCI_PCCOM8 0x0002 +#define PCI_DEVICE_ID_DCI_PCCOM2 0x0004 + +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_EESSC 0x0008 +#define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 +#define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321 +#define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 +#define PCI_DEVICE_ID_INTEL_PXH_1 0x032A +#define PCI_DEVICE_ID_INTEL_PXHV 0x032C +#define PCI_DEVICE_ID_INTEL_82375 0x0482 +#define PCI_DEVICE_ID_INTEL_82424 0x0483 +#define PCI_DEVICE_ID_INTEL_82378 0x0484 +#define PCI_DEVICE_ID_INTEL_I960 0x0960 +#define PCI_DEVICE_ID_INTEL_I960RM 0x0962 +#define PCI_DEVICE_ID_INTEL_82815_MC 0x1130 +#define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132 +#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 +#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 +#define PCI_DEVICE_ID_INTEL_7205_0 0x255d +#define PCI_DEVICE_ID_INTEL_82437 0x122d +#define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e +#define PCI_DEVICE_ID_INTEL_82371FB_1 0x1230 +#define PCI_DEVICE_ID_INTEL_82371MX 0x1234 +#define PCI_DEVICE_ID_INTEL_82441 0x1237 +#define PCI_DEVICE_ID_INTEL_82380FB 0x124b +#define PCI_DEVICE_ID_INTEL_82439 0x1250 +#define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 +#define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 +#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 +#define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 +#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 +#define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 +#define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 +#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415 +#define PCI_DEVICE_ID_INTEL_82801AA_6 0x2416 +#define PCI_DEVICE_ID_INTEL_82801AA_8 0x2418 +#define PCI_DEVICE_ID_INTEL_82801AB_0 0x2420 +#define PCI_DEVICE_ID_INTEL_82801AB_1 0x2421 +#define PCI_DEVICE_ID_INTEL_82801AB_3 0x2423 +#define PCI_DEVICE_ID_INTEL_82801AB_5 0x2425 +#define PCI_DEVICE_ID_INTEL_82801AB_6 0x2426 +#define PCI_DEVICE_ID_INTEL_82801AB_8 0x2428 +#define PCI_DEVICE_ID_INTEL_82801BA_0 0x2440 +#define PCI_DEVICE_ID_INTEL_82801BA_2 0x2443 +#define PCI_DEVICE_ID_INTEL_82801BA_4 0x2445 +#define PCI_DEVICE_ID_INTEL_82801BA_6 0x2448 +#define PCI_DEVICE_ID_INTEL_82801BA_8 0x244a +#define PCI_DEVICE_ID_INTEL_82801BA_9 0x244b +#define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c +#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e +#define PCI_DEVICE_ID_INTEL_82801E_0 0x2450 +#define PCI_DEVICE_ID_INTEL_82801E_11 0x245b +#define PCI_DEVICE_ID_INTEL_82801CA_0 0x2480 +#define PCI_DEVICE_ID_INTEL_82801CA_3 0x2483 +#define PCI_DEVICE_ID_INTEL_82801CA_5 0x2485 +#define PCI_DEVICE_ID_INTEL_82801CA_6 0x2486 +#define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a +#define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b +#define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c +#define PCI_DEVICE_ID_INTEL_82801DB_0 0x24c0 +#define PCI_DEVICE_ID_INTEL_82801DB_1 0x24c1 +#define PCI_DEVICE_ID_INTEL_82801DB_3 0x24c3 +#define PCI_DEVICE_ID_INTEL_82801DB_5 0x24c5 +#define PCI_DEVICE_ID_INTEL_82801DB_6 0x24c6 +#define PCI_DEVICE_ID_INTEL_82801DB_9 0x24c9 +#define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca +#define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb +#define PCI_DEVICE_ID_INTEL_82801DB_12 0x24cc +#define PCI_DEVICE_ID_INTEL_82801EB_0 0x24d0 +#define PCI_DEVICE_ID_INTEL_82801EB_1 0x24d1 +#define PCI_DEVICE_ID_INTEL_82801EB_3 0x24d3 +#define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 +#define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 +#define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db +#define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc +#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd +#define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 +#define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 +#define PCI_DEVICE_ID_INTEL_ESB_4 0x25a4 +#define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6 +#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab +#define PCI_DEVICE_ID_INTEL_82820_HB 0x2500 +#define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 +#define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 +#define PCI_DEVICE_ID_INTEL_82860_HB 0x2531 +#define PCI_DEVICE_ID_INTEL_E7501_MCH 0x254c +#define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560 +#define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 +#define PCI_DEVICE_ID_INTEL_82865_HB 0x2570 +#define PCI_DEVICE_ID_INTEL_82865_IG 0x2572 +#define PCI_DEVICE_ID_INTEL_82875_HB 0x2578 +#define PCI_DEVICE_ID_INTEL_82915G_HB 0x2580 +#define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582 +#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590 +#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 +#define PCI_DEVICE_ID_INTEL_5000_ERR 0x25F0 +#define PCI_DEVICE_ID_INTEL_5000_FBD0 0x25F5 +#define PCI_DEVICE_ID_INTEL_5000_FBD1 0x25F6 +#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 +#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 +#define PCI_DEVICE_ID_INTEL_3000_HB 0x2778 +#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0 +#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2 +#define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640 +#define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641 +#define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642 +#define PCI_DEVICE_ID_INTEL_ICH6_16 0x266a +#define PCI_DEVICE_ID_INTEL_ICH6_17 0x266d +#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e +#define PCI_DEVICE_ID_INTEL_ICH6_19 0x266f +#define PCI_DEVICE_ID_INTEL_ESB2_0 0x2670 +#define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698 +#define PCI_DEVICE_ID_INTEL_ESB2_17 0x269b +#define PCI_DEVICE_ID_INTEL_ESB2_18 0x269e +#define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8 +#define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9 +#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 +#define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd +#define PCI_DEVICE_ID_INTEL_ICH7_17 0x27da +#define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd +#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de +#define PCI_DEVICE_ID_INTEL_ICH7_21 0x27df +#define PCI_DEVICE_ID_INTEL_ICH8_0 0x2810 +#define PCI_DEVICE_ID_INTEL_ICH8_1 0x2811 +#define PCI_DEVICE_ID_INTEL_ICH8_2 0x2812 +#define PCI_DEVICE_ID_INTEL_ICH8_3 0x2814 +#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 +#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e +#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 +#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910 +#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917 +#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912 +#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913 +#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914 +#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919 +#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 +#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916 +#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918 +#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a +#define PCI_DEVICE_ID_INTEL_IOAT_TBG6 0x342b +#define PCI_DEVICE_ID_INTEL_IOAT_TBG7 0x342c +#define PCI_DEVICE_ID_INTEL_IOAT_TBG0 0x3430 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433 +#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 +#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 +#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 +#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 +#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590 +#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592 +#define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595 +#define PCI_DEVICE_ID_INTEL_MCH_PA1 0x3596 +#define PCI_DEVICE_ID_INTEL_MCH_PB 0x3597 +#define PCI_DEVICE_ID_INTEL_MCH_PB1 0x3598 +#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599 +#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a +#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e +#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b +#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c +#define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14 +#define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16 +#define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18 +#define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a +#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 +#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 +#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN 0x3b00 +#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX 0x3b1f +#define PCI_DEVICE_ID_INTEL_PCH_SMBUS 0x3b30 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f +#define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 +#define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 +#define PCI_DEVICE_ID_INTEL_5100_22 0x65f6 +#define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 +#define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 +#define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 +#define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff +#define PCI_DEVICE_ID_INTEL_TOLAPAI_0 0x5031 +#define PCI_DEVICE_ID_INTEL_TOLAPAI_1 0x5032 +#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 +#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010 +#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020 +#define PCI_DEVICE_ID_INTEL_82437VX 0x7030 +#define PCI_DEVICE_ID_INTEL_82439TX 0x7100 +#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110 +#define PCI_DEVICE_ID_INTEL_82371AB 0x7111 +#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112 +#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113 +#define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120 +#define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121 +#define PCI_DEVICE_ID_INTEL_82810_MC3 0x7122 +#define PCI_DEVICE_ID_INTEL_82810_IG3 0x7123 +#define PCI_DEVICE_ID_INTEL_82810E_MC 0x7124 +#define PCI_DEVICE_ID_INTEL_82810E_IG 0x7125 +#define PCI_DEVICE_ID_INTEL_82443LX_0 0x7180 +#define PCI_DEVICE_ID_INTEL_82443LX_1 0x7181 +#define PCI_DEVICE_ID_INTEL_82443BX_0 0x7190 +#define PCI_DEVICE_ID_INTEL_82443BX_1 0x7191 +#define PCI_DEVICE_ID_INTEL_82443BX_2 0x7192 +#define PCI_DEVICE_ID_INTEL_440MX 0x7195 +#define PCI_DEVICE_ID_INTEL_440MX_6 0x7196 +#define PCI_DEVICE_ID_INTEL_82443MX_0 0x7198 +#define PCI_DEVICE_ID_INTEL_82443MX_1 0x7199 +#define PCI_DEVICE_ID_INTEL_82443MX_3 0x719b +#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0 +#define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2 +#define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 +#define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119 +#define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a +#define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 +#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5 +#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca +#define PCI_DEVICE_ID_INTEL_82454NX 0x84cb +#define PCI_DEVICE_ID_INTEL_84460GX 0x84ea +#define PCI_DEVICE_ID_INTEL_IXP4XX 0x8500 +#define PCI_DEVICE_ID_INTEL_IXP2800 0x9004 +#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 + +#define PCI_VENDOR_ID_SCALEMP 0x8686 +#define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010 + +#define PCI_VENDOR_ID_COMPUTONE 0x8e0e +#define PCI_DEVICE_ID_COMPUTONE_IP2EX 0x0291 +#define PCI_DEVICE_ID_COMPUTONE_PG 0x0302 +#define PCI_SUBVENDOR_ID_COMPUTONE 0x8e0e +#define PCI_SUBDEVICE_ID_COMPUTONE_PG4 0x0001 +#define PCI_SUBDEVICE_ID_COMPUTONE_PG8 0x0002 +#define PCI_SUBDEVICE_ID_COMPUTONE_PG6 0x0003 + +#define PCI_VENDOR_ID_KTI 0x8e2e + +#define PCI_VENDOR_ID_ADAPTEC 0x9004 +#define PCI_DEVICE_ID_ADAPTEC_7810 0x1078 +#define PCI_DEVICE_ID_ADAPTEC_7821 0x2178 +#define PCI_DEVICE_ID_ADAPTEC_38602 0x3860 +#define PCI_DEVICE_ID_ADAPTEC_7850 0x5078 +#define PCI_DEVICE_ID_ADAPTEC_7855 0x5578 +#define PCI_DEVICE_ID_ADAPTEC_3860 0x6038 +#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075 +#define PCI_DEVICE_ID_ADAPTEC_7860 0x6078 +#define PCI_DEVICE_ID_ADAPTEC_7861 0x6178 +#define PCI_DEVICE_ID_ADAPTEC_7870 0x7078 +#define PCI_DEVICE_ID_ADAPTEC_7871 0x7178 +#define PCI_DEVICE_ID_ADAPTEC_7872 0x7278 +#define PCI_DEVICE_ID_ADAPTEC_7873 0x7378 +#define PCI_DEVICE_ID_ADAPTEC_7874 0x7478 +#define PCI_DEVICE_ID_ADAPTEC_7895 0x7895 +#define PCI_DEVICE_ID_ADAPTEC_7880 0x8078 +#define PCI_DEVICE_ID_ADAPTEC_7881 0x8178 +#define PCI_DEVICE_ID_ADAPTEC_7882 0x8278 +#define PCI_DEVICE_ID_ADAPTEC_7883 0x8378 +#define PCI_DEVICE_ID_ADAPTEC_7884 0x8478 +#define PCI_DEVICE_ID_ADAPTEC_7885 0x8578 +#define PCI_DEVICE_ID_ADAPTEC_7886 0x8678 +#define PCI_DEVICE_ID_ADAPTEC_7887 0x8778 +#define PCI_DEVICE_ID_ADAPTEC_7888 0x8878 + +#define PCI_VENDOR_ID_ADAPTEC2 0x9005 +#define PCI_DEVICE_ID_ADAPTEC2_2940U2 0x0010 +#define PCI_DEVICE_ID_ADAPTEC2_2930U2 0x0011 +#define PCI_DEVICE_ID_ADAPTEC2_7890B 0x0013 +#define PCI_DEVICE_ID_ADAPTEC2_7890 0x001f +#define PCI_DEVICE_ID_ADAPTEC2_3940U2 0x0050 +#define PCI_DEVICE_ID_ADAPTEC2_3950U2D 0x0051 +#define PCI_DEVICE_ID_ADAPTEC2_7896 0x005f +#define PCI_DEVICE_ID_ADAPTEC2_7892A 0x0080 +#define PCI_DEVICE_ID_ADAPTEC2_7892B 0x0081 +#define PCI_DEVICE_ID_ADAPTEC2_7892D 0x0083 +#define PCI_DEVICE_ID_ADAPTEC2_7892P 0x008f +#define PCI_DEVICE_ID_ADAPTEC2_7899A 0x00c0 +#define PCI_DEVICE_ID_ADAPTEC2_7899B 0x00c1 +#define PCI_DEVICE_ID_ADAPTEC2_7899D 0x00c3 +#define PCI_DEVICE_ID_ADAPTEC2_7899P 0x00cf +#define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN 0x0500 +#define PCI_DEVICE_ID_ADAPTEC2_SCAMP 0x0503 + +#define PCI_VENDOR_ID_HOLTEK 0x9412 +#define PCI_DEVICE_ID_HOLTEK_6565 0x6565 + +#define PCI_VENDOR_ID_NETMOS 0x9710 +#define PCI_DEVICE_ID_NETMOS_9705 0x9705 +#define PCI_DEVICE_ID_NETMOS_9715 0x9715 +#define PCI_DEVICE_ID_NETMOS_9735 0x9735 +#define PCI_DEVICE_ID_NETMOS_9745 0x9745 +#define PCI_DEVICE_ID_NETMOS_9755 0x9755 +#define PCI_DEVICE_ID_NETMOS_9805 0x9805 +#define PCI_DEVICE_ID_NETMOS_9815 0x9815 +#define PCI_DEVICE_ID_NETMOS_9835 0x9835 +#define PCI_DEVICE_ID_NETMOS_9845 0x9845 +#define PCI_DEVICE_ID_NETMOS_9855 0x9855 + +#define PCI_VENDOR_ID_3COM_2 0xa727 + +#define PCI_VENDOR_ID_DIGIUM 0xd161 +#define PCI_DEVICE_ID_DIGIUM_HFC4S 0xb410 + +#define PCI_SUBVENDOR_ID_EXSYS 0xd84d +#define PCI_SUBDEVICE_ID_EXSYS_4014 0x4014 +#define PCI_SUBDEVICE_ID_EXSYS_4055 0x4055 + +#define PCI_VENDOR_ID_TIGERJET 0xe159 +#define PCI_DEVICE_ID_TIGERJET_300 0x0001 +#define PCI_DEVICE_ID_TIGERJET_100 0x0002 + +#define PCI_VENDOR_ID_XILINX_RME 0xea60 +#define PCI_DEVICE_ID_RME_DIGI32 0x9896 +#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897 +#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898 + +#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_DEVICE_ID_VIRTIO_BLK 0x1001 +#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004 + +#define PCI_VENDOR_ID_VMWARE 0x15ad +#define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0 diff -Nru seabios-1.7.1/src/hw/pci_regs.h seabios-1.7.4/src/hw/pci_regs.h --- seabios-1.7.1/src/hw/pci_regs.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pci_regs.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,556 @@ +/* + * pci_regs.h + * + * PCI standard defines + * Copyright 1994, Drew Eckhardt + * Copyright 1997--1999 Martin Mares + * + * For more information, please consult the following manuals (look at + * http://www.pcisig.com/ for how to get them): + * + * PCI BIOS Specification + * PCI Local Bus Specification + * PCI to PCI Bridge Specification + * PCI System Design Guide + * + * For hypertransport information, please consult the following manuals + * from http://www.hypertransport.org + * + * The Hypertransport I/O Link Specification + */ + +#ifndef LINUX_PCI_REGS_H +#define LINUX_PCI_REGS_H + +/* + * Under PCI, each device has 256 bytes of configuration address space, + * of which the first 64 bytes are standardized as follows: + */ +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ +#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ +#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ +#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ +#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ +#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ +#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ +#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ +#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ + +#define PCI_STATUS 0x06 /* 16 bits */ +#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ +#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ +#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ +#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ +#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ +#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ +#define PCI_STATUS_DEVSEL_FAST 0x000 +#define PCI_STATUS_DEVSEL_MEDIUM 0x200 +#define PCI_STATUS_DEVSEL_SLOW 0x400 +#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ +#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ +#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ +#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ +#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ + +#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */ +#define PCI_REVISION_ID 0x08 /* Revision ID */ +#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ +#define PCI_CLASS_DEVICE 0x0a /* Device class */ + +#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ +#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ +#define PCI_HEADER_TYPE 0x0e /* 8 bits */ +#define PCI_HEADER_TYPE_NORMAL 0 +#define PCI_HEADER_TYPE_BRIDGE 1 +#define PCI_HEADER_TYPE_CARDBUS 2 + +#define PCI_BIST 0x0f /* 8 bits */ +#define PCI_BIST_CODE_MASK 0x0f /* Return result */ +#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ +#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ + +/* + * Base addresses specify locations in memory or I/O space. + * Decoded size can be determined by writing a value of + * 0xffffffff to the register, and reading it back. Only + * 1 bits are decoded. + */ +#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ +#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ +#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ +#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ +#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ +#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ +#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ +#define PCI_BASE_ADDRESS_SPACE_IO 0x01 +#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 +#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 +#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ +#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ +#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ +#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ +#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) +#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) +/* bit 1 is reserved if address_space = 1 */ + +/* Header type 0 (normal devices) */ +#define PCI_CARDBUS_CIS 0x28 +#define PCI_SUBSYSTEM_VENDOR_ID 0x2c +#define PCI_SUBSYSTEM_ID 0x2e +#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ +#define PCI_ROM_ADDRESS_ENABLE 0x01 +#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) + +#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ + +/* 0x35-0x3b are reserved */ +#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ +#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ +#define PCI_MIN_GNT 0x3e /* 8 bits */ +#define PCI_MAX_LAT 0x3f /* 8 bits */ + +/* Header type 1 (PCI-to-PCI bridges) */ +#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ +#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ +#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ +#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ +#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ +#define PCI_IO_LIMIT 0x1d +#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */ +#define PCI_IO_RANGE_TYPE_16 0x00 +#define PCI_IO_RANGE_TYPE_32 0x01 +#define PCI_IO_RANGE_MASK (~0x0fUL) +#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */ +#define PCI_MEMORY_BASE 0x20 /* Memory range behind */ +#define PCI_MEMORY_LIMIT 0x22 +#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL +#define PCI_MEMORY_RANGE_MASK (~0x0fUL) +#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ +#define PCI_PREF_MEMORY_LIMIT 0x26 +#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL +#define PCI_PREF_RANGE_TYPE_32 0x00 +#define PCI_PREF_RANGE_TYPE_64 0x01 +#define PCI_PREF_RANGE_MASK (~0x0fUL) +#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ +#define PCI_PREF_LIMIT_UPPER32 0x2c +#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */ +#define PCI_IO_LIMIT_UPPER16 0x32 +/* 0x34 same as for htype 0 */ +/* 0x35-0x3b is reserved */ +#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */ +/* 0x3c-0x3d are same as for htype 0 */ +#define PCI_BRIDGE_CONTROL 0x3e +#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */ +#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */ +#define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */ +#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */ +#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ +#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */ +#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */ + +/* Header type 2 (CardBus bridges) */ +#define PCI_CB_CAPABILITY_LIST 0x14 +/* 0x15 reserved */ +#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */ +#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */ +#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */ +#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */ +#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */ +#define PCI_CB_MEMORY_BASE_0 0x1c +#define PCI_CB_MEMORY_LIMIT_0 0x20 +#define PCI_CB_MEMORY_BASE_1 0x24 +#define PCI_CB_MEMORY_LIMIT_1 0x28 +#define PCI_CB_IO_BASE_0 0x2c +#define PCI_CB_IO_BASE_0_HI 0x2e +#define PCI_CB_IO_LIMIT_0 0x30 +#define PCI_CB_IO_LIMIT_0_HI 0x32 +#define PCI_CB_IO_BASE_1 0x34 +#define PCI_CB_IO_BASE_1_HI 0x36 +#define PCI_CB_IO_LIMIT_1 0x38 +#define PCI_CB_IO_LIMIT_1_HI 0x3a +#define PCI_CB_IO_RANGE_MASK (~0x03UL) +/* 0x3c-0x3d are same as for htype 0 */ +#define PCI_CB_BRIDGE_CONTROL 0x3e +#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */ +#define PCI_CB_BRIDGE_CTL_SERR 0x02 +#define PCI_CB_BRIDGE_CTL_ISA 0x04 +#define PCI_CB_BRIDGE_CTL_VGA 0x08 +#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20 +#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */ +#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */ +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */ +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200 +#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400 +#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40 +#define PCI_CB_SUBSYSTEM_ID 0x42 +#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */ +/* 0x48-0x7f reserved */ + +/* Capability lists */ + +#define PCI_CAP_LIST_ID 0 /* Capability ID */ +#define PCI_CAP_ID_PM 0x01 /* Power Management */ +#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */ +#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */ +#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ +#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ +#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ +#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ +#define PCI_CAP_ID_HT 0x08 /* HyperTransport */ +#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */ +#define PCI_CAP_ID_DBG 0x0A /* Debug port */ +#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */ +#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ +#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */ +#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */ +#define PCI_CAP_ID_EXP 0x10 /* PCI Express */ +#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ +#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ +#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ +#define PCI_CAP_SIZEOF 4 + +/* Power Management Registers */ + +#define PCI_PM_PMC 2 /* PM Capabilities Register */ +#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */ +#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ +#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */ +#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ +#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */ +#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ +#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ +#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ +#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */ +#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */ +#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */ +#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */ +#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */ +#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ +#define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */ +#define PCI_PM_CTRL 4 /* PM control and status register */ +#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ +#define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */ +#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ +#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ +#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ +#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */ +#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */ +#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */ +#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */ +#define PCI_PM_DATA_REGISTER 7 /* (??) */ +#define PCI_PM_SIZEOF 8 + +/* AGP registers */ + +#define PCI_AGP_VERSION 2 /* BCD version number */ +#define PCI_AGP_RFU 3 /* Rest of capability flags */ +#define PCI_AGP_STATUS 4 /* Status register */ +#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */ +#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */ +#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */ +#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */ +#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */ +#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */ +#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */ +#define PCI_AGP_COMMAND 8 /* Control register */ +#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ +#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */ +#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */ +#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */ +#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */ +#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */ +#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */ +#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */ +#define PCI_AGP_SIZEOF 12 + +/* Vital Product Data */ + +#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */ +#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */ +#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */ +#define PCI_VPD_DATA 4 /* 32-bits of data returned here */ + +/* Slot Identification */ + +#define PCI_SID_ESR 2 /* Expansion Slot Register */ +#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */ +#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */ +#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */ + +/* Message Signalled Interrupts registers */ + +#define PCI_MSI_FLAGS 2 /* Various flags */ +#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */ +#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ +#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ +#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ +#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */ +#define PCI_MSI_RFU 3 /* Rest of capability flags */ +#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ +#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ +#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ +#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ +#define PCI_MSI_MASK_BIT 16 /* Mask bits register */ + +/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */ +#define PCI_MSIX_FLAGS 2 +#define PCI_MSIX_FLAGS_QSIZE 0x7FF +#define PCI_MSIX_FLAGS_ENABLE (1 << 15) +#define PCI_MSIX_FLAGS_MASKALL (1 << 14) +#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) +#define PCI_MSIX_FLAGS_BITMASK (1 << 0) + +/* CompactPCI Hotswap Register */ + +#define PCI_CHSWP_CSR 2 /* Control and Status Register */ +#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */ +#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */ +#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */ +#define PCI_CHSWP_LOO 0x08 /* LED On / Off */ +#define PCI_CHSWP_PI 0x30 /* Programming Interface */ +#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */ +#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */ + +/* PCI-X registers */ + +#define PCI_X_CMD 2 /* Modes & Features */ +#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */ +#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */ +#define PCI_X_CMD_READ_512 0x0000 /* 512 byte maximum read byte count */ +#define PCI_X_CMD_READ_1K 0x0004 /* 1Kbyte maximum read byte count */ +#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */ +#define PCI_X_CMD_READ_4K 0x000c /* 4Kbyte maximum read byte count */ +#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */ + /* Max # of outstanding split transactions */ +#define PCI_X_CMD_SPLIT_1 0x0000 /* Max 1 */ +#define PCI_X_CMD_SPLIT_2 0x0010 /* Max 2 */ +#define PCI_X_CMD_SPLIT_3 0x0020 /* Max 3 */ +#define PCI_X_CMD_SPLIT_4 0x0030 /* Max 4 */ +#define PCI_X_CMD_SPLIT_8 0x0040 /* Max 8 */ +#define PCI_X_CMD_SPLIT_12 0x0050 /* Max 12 */ +#define PCI_X_CMD_SPLIT_16 0x0060 /* Max 16 */ +#define PCI_X_CMD_SPLIT_32 0x0070 /* Max 32 */ +#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */ +#define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */ +#define PCI_X_STATUS 4 /* PCI-X capabilities */ +#define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */ +#define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */ +#define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */ +#define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */ +#define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */ +#define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */ +#define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */ +#define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */ +#define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */ +#define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */ +#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */ +#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ +#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ + +/* PCI Express capability registers */ + +#define PCI_EXP_FLAGS 2 /* Capabilities register */ +#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */ +#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */ +#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */ +#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */ +#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */ +#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */ +#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ +#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ +#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ +#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ +#define PCI_EXP_DEVCAP 4 /* Device capabilities */ +#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */ +#define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */ +#define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */ +#define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */ +#define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */ +#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ +#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ +#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ +#define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */ +#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ +#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ +#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ +#define PCI_EXP_DEVCTL 8 /* Device Control */ +#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ +#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ +#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */ +#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ +#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ +#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ +#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ +#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ +#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ +#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ +#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ +#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */ +#define PCI_EXP_DEVSTA 10 /* Device Status */ +#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ +#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ +#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */ +#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */ +#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */ +#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ +#define PCI_EXP_LNKCAP 12 /* Link Capabilities */ +#define PCI_EXP_LNKCAP_ASPMS 0xc00 /* ASPM Support */ +#define PCI_EXP_LNKCAP_L0SEL 0x7000 /* L0s Exit Latency */ +#define PCI_EXP_LNKCAP_L1EL 0x38000 /* L1 Exit Latency */ +#define PCI_EXP_LNKCAP_CLKPM 0x40000 /* L1 Clock Power Management */ +#define PCI_EXP_LNKCTL 16 /* Link Control */ +#define PCI_EXP_LNKCTL_RL 0x20 /* Retrain Link */ +#define PCI_EXP_LNKCTL_CCC 0x40 /* Common Clock COnfiguration */ +#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ +#define PCI_EXP_LNKSTA 18 /* Link Status */ +#define PCI_EXP_LNKSTA_LT 0x800 /* Link Training */ +#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */ +#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ +#define PCI_EXP_SLTCTL 24 /* Slot Control */ +#define PCI_EXP_SLTSTA 26 /* Slot Status */ +#define PCI_EXP_RTCTL 28 /* Root Control */ +#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */ +#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */ +#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */ +#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */ +#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */ +#define PCI_EXP_RTCAP 30 /* Root Capabilities */ +#define PCI_EXP_RTSTA 32 /* Root Status */ +#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ +#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */ +#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ +#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */ + +/* Extended Capabilities (PCI-X 2.0 and Express) */ +#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) +#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) +#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) + +#define PCI_EXT_CAP_ID_ERR 1 +#define PCI_EXT_CAP_ID_VC 2 +#define PCI_EXT_CAP_ID_DSN 3 +#define PCI_EXT_CAP_ID_PWR 4 +#define PCI_EXT_CAP_ID_ARI 14 + +/* Advanced Error Reporting */ +#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ +#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */ +#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ +#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */ +#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */ +#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */ +#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */ +#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */ +#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */ +#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */ +#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */ +#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */ +#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ + /* Same bits as above */ +#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */ + /* Same bits as above */ +#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */ +#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */ +#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */ +#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ +#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */ +#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */ +#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */ + /* Same bits as above */ +#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */ +#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */ +#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */ +#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */ +#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */ +#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */ +#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */ +#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */ +/* Correctable Err Reporting Enable */ +#define PCI_ERR_ROOT_CMD_COR_EN 0x00000001 +/* Non-fatal Err Reporting Enable */ +#define PCI_ERR_ROOT_CMD_NONFATAL_EN 0x00000002 +/* Fatal Err Reporting Enable */ +#define PCI_ERR_ROOT_CMD_FATAL_EN 0x00000004 +#define PCI_ERR_ROOT_STATUS 48 +#define PCI_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */ +/* Multi ERR_COR Received */ +#define PCI_ERR_ROOT_MULTI_COR_RCV 0x00000002 +/* ERR_FATAL/NONFATAL Recevied */ +#define PCI_ERR_ROOT_UNCOR_RCV 0x00000004 +/* Multi ERR_FATAL/NONFATAL Recevied */ +#define PCI_ERR_ROOT_MULTI_UNCOR_RCV 0x00000008 +#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */ +#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */ +#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */ +#define PCI_ERR_ROOT_COR_SRC 52 +#define PCI_ERR_ROOT_SRC 54 + +/* Virtual Channel */ +#define PCI_VC_PORT_REG1 4 +#define PCI_VC_PORT_REG2 8 +#define PCI_VC_PORT_CTRL 12 +#define PCI_VC_PORT_STATUS 14 +#define PCI_VC_RES_CAP 16 +#define PCI_VC_RES_CTRL 20 +#define PCI_VC_RES_STATUS 26 + +/* Power Budgeting */ +#define PCI_PWR_DSR 4 /* Data Select Register */ +#define PCI_PWR_DATA 8 /* Data Register */ +#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ +#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ +#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ +#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ +#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ +#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ +#define PCI_PWR_CAP 12 /* Capability */ +#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ + +/* + * Hypertransport sub capability types + * + * Unfortunately there are both 3 bit and 5 bit capability types defined + * in the HT spec, catering for that is a little messy. You probably don't + * want to use these directly, just use pci_find_ht_capability() and it + * will do the right thing for you. + */ +#define HT_3BIT_CAP_MASK 0xE0 +#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */ +#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */ + +#define HT_5BIT_CAP_MASK 0xF8 +#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */ +#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */ +#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */ +#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */ +#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */ +#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */ +#define HT_MSI_FLAGS 0x02 /* Offset to flags */ +#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */ +#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */ +#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */ +#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */ +#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */ +#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */ +#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */ +#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */ +#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */ +#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */ +#define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */ + +/* Alternative Routing-ID Interpretation */ +#define PCI_ARI_CAP 0x04 /* ARI Capability Register */ +#define PCI_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */ +#define PCI_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */ +#define PCI_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) /* Next Function Number */ +#define PCI_ARI_CTRL 0x06 /* ARI Control Register */ +#define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */ +#define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */ +#define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */ + +#endif /* LINUX_PCI_REGS_H */ diff -Nru seabios-1.7.1/src/hw/pic.c seabios-1.7.4/src/hw/pic.c --- seabios-1.7.1/src/hw/pic.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pic.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,101 @@ +// Helpers for working with i8259 interrupt controller. +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // SET_IVT +#include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "pic.h" // pic_* + +u16 +pic_irqmask_read(void) +{ + return inb(PORT_PIC1_DATA) | (inb(PORT_PIC2_DATA) << 8); +} + +void +pic_irqmask_write(u16 mask) +{ + outb(mask, PORT_PIC1_DATA); + outb(mask >> 8, PORT_PIC2_DATA); +} + +void +pic_irqmask_mask(u16 off, u16 on) +{ + u8 pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8; + outb((inb(PORT_PIC1_DATA) & ~pic1off) | pic1on, PORT_PIC1_DATA); + outb((inb(PORT_PIC2_DATA) & ~pic2off) | pic2on, PORT_PIC2_DATA); +} + +void +pic_reset(u8 irq0, u8 irq8) +{ + // Send ICW1 (select OCW1 + will send ICW4) + outb(0x11, PORT_PIC1_CMD); + outb(0x11, PORT_PIC2_CMD); + // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15) + outb(irq0, PORT_PIC1_DATA); + outb(irq8, PORT_PIC2_DATA); + // Send ICW3 (cascaded pic ids) + outb(0x04, PORT_PIC1_DATA); + outb(0x02, PORT_PIC2_DATA); + // Send ICW4 (enable 8086 mode) + outb(0x01, PORT_PIC1_DATA); + outb(0x01, PORT_PIC2_DATA); + // Mask all irqs (except cascaded PIC2 irq) + pic_irqmask_write(PIC_IRQMASK_DEFAULT); +} + +void +pic_setup(void) +{ + dprintf(3, "init pic\n"); + pic_reset(BIOS_HWIRQ0_VECTOR, BIOS_HWIRQ8_VECTOR); +} + +void +enable_hwirq(int hwirq, struct segoff_s func) +{ + pic_irqmask_mask(1 << hwirq, 0); + int vector; + if (hwirq < 8) + vector = BIOS_HWIRQ0_VECTOR + hwirq; + else + vector = BIOS_HWIRQ8_VECTOR + hwirq - 8; + SET_IVT(vector, func); +} + +static u8 +pic_isr1_read(void) +{ + // 0x0b == select OCW1 + read ISR + outb(0x0b, PORT_PIC1_CMD); + return inb(PORT_PIC1_CMD); +} + +static u8 +pic_isr2_read(void) +{ + // 0x0b == select OCW1 + read ISR + outb(0x0b, PORT_PIC2_CMD); + return inb(PORT_PIC2_CMD); +} + +// Handler for otherwise unused hardware irqs. +void VISIBLE16 +handle_hwpic1(struct bregs *regs) +{ + dprintf(DEBUG_ISR_hwpic1, "handle_hwpic1 irq=%x\n", pic_isr1_read()); + pic_eoi1(); +} + +void VISIBLE16 +handle_hwpic2(struct bregs *regs) +{ + dprintf(DEBUG_ISR_hwpic2, "handle_hwpic2 irq=%x\n", pic_isr2_read()); + pic_eoi2(); +} diff -Nru seabios-1.7.1/src/hw/pic.h seabios-1.7.4/src/hw/pic.h --- seabios-1.7.1/src/hw/pic.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pic.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,56 @@ +// Helpers for working with i8259 interrupt controller. +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. +#ifndef __PIC_H +#define __PIC_H + +#include "x86.h" // outb + +#define PORT_PIC1_CMD 0x0020 +#define PORT_PIC1_DATA 0x0021 +#define PORT_PIC2_CMD 0x00a0 +#define PORT_PIC2_DATA 0x00a1 + +// PORT_PIC1 bitdefs +#define PIC1_IRQ0 (1<<0) +#define PIC1_IRQ1 (1<<1) +#define PIC1_IRQ2 (1<<2) +#define PIC1_IRQ5 (1<<5) +#define PIC1_IRQ6 (1<<6) +// PORT_PIC2 bitdefs +#define PIC2_IRQ8 (1<<8) +#define PIC2_IRQ12 (1<<12) +#define PIC2_IRQ13 (1<<13) +#define PIC2_IRQ14 (1<<14) + +#define PIC_IRQMASK_DEFAULT ((u16)~PIC1_IRQ2) + +#define BIOS_HWIRQ0_VECTOR 0x08 +#define BIOS_HWIRQ8_VECTOR 0x70 + +static inline void +pic_eoi1(void) +{ + // Send eoi (select OCW2 + eoi) + outb(0x20, PORT_PIC1_CMD); +} + +static inline void +pic_eoi2(void) +{ + // Send eoi (select OCW2 + eoi) + outb(0x20, PORT_PIC2_CMD); + pic_eoi1(); +} + +u16 pic_irqmask_read(void); +void pic_irqmask_write(u16 mask); +void pic_irqmask_mask(u16 off, u16 on); +void pic_reset(u8 irq0, u8 irq8); +void pic_setup(void); +void enable_hwirq(int hwirq, struct segoff_s func); + +#endif // pic.h diff -Nru seabios-1.7.1/src/hw/ps2port.c seabios-1.7.4/src/hw/ps2port.c --- seabios-1.7.1/src/hw/ps2port.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/ps2port.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,507 @@ +// Support for handling the PS/2 mouse/keyboard ports. +// +// Copyright (C) 2008 Kevin O'Connor +// Several ideas taken from code Copyright (c) 1999-2004 Vojtech Pavlik +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_LOW +#include "output.h" // dprintf +#include "pic.h" // pic_eoi1 +#include "ps2port.h" // ps2_kbd_command +#include "romfile.h" // romfile_loadint +#include "stacks.h" // yield +#include "util.h" // udelay +#include "x86.h" // inb + + +/**************************************************************** + * Low level i8042 commands. + ****************************************************************/ + +// Timeout value. +#define I8042_CTL_TIMEOUT 10000 + +#define I8042_BUFFER_SIZE 16 + +static int +i8042_wait_read(void) +{ + dprintf(7, "i8042_wait_read\n"); + int i; + for (i=0; i> 8) & 0xf; + int send = (command >> 12) & 0xf; + + // Send the command. + int ret = i8042_wait_write(); + if (ret) + return ret; + outb(command, PORT_PS2_STATUS); + + // Send parameters (if any). + int i; + for (i = 0; i < send; i++) { + ret = i8042_wait_write(); + if (ret) + return ret; + outb(param[i], PORT_PS2_DATA); + } + + // Receive parameters (if any). + for (i = 0; i < receive; i++) { + ret = i8042_wait_read(); + if (ret) + return ret; + param[i] = inb(PORT_PS2_DATA); + dprintf(7, "i8042 param=%x\n", param[i]); + } + + return 0; +} + +static int +i8042_command(int command, u8 *param) +{ + dprintf(7, "i8042_command cmd=%x\n", command); + int ret = __i8042_command(command, param); + if (ret) + dprintf(2, "i8042 command %x failed\n", command); + return ret; +} + +static int +i8042_kbd_write(u8 c) +{ + dprintf(7, "i8042_kbd_write c=%d\n", c); + int ret = i8042_wait_write(); + if (! ret) + outb(c, PORT_PS2_DATA); + return ret; +} + +static int +i8042_aux_write(u8 c) +{ + return i8042_command(I8042_CMD_AUX_SEND, &c); +} + +void +i8042_reboot(void) +{ + if (! CONFIG_PS2PORT) + return; + int i; + for (i=0; i<10; i++) { + i8042_wait_write(); + udelay(50); + outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */ + udelay(50); + } +} + + +/**************************************************************** + * Device commands. + ****************************************************************/ + +#define PS2_RET_ACK 0xfa +#define PS2_RET_NAK 0xfe + +static int +ps2_recvbyte(int aux, int needack, int timeout) +{ + u32 end = timer_calc(timeout); + for (;;) { + u8 status = inb(PORT_PS2_STATUS); + if (status & I8042_STR_OBF) { + u8 data = inb(PORT_PS2_DATA); + dprintf(7, "ps2 read %x\n", data); + + if (!!(status & I8042_STR_AUXDATA) == aux) { + if (!needack) + return data; + if (data == PS2_RET_ACK) + return data; + if (data == PS2_RET_NAK) { + dprintf(1, "Got ps2 nak (status=%x)\n", status); + return data; + } + } + + // This data not part of command - just discard it. + dprintf(1, "Discarding ps2 data %02x (status=%02x)\n", data, status); + } + + if (timer_check(end)) { + // Don't warn on second byte of a reset + if (timeout > 100) + warn_timeout(); + return -1; + } + yield(); + } +} + +static int +ps2_sendbyte(int aux, u8 command, int timeout) +{ + dprintf(7, "ps2_sendbyte aux=%d cmd=%x\n", aux, command); + int ret; + if (aux) + ret = i8042_aux_write(command); + else + ret = i8042_kbd_write(command); + if (ret) + return ret; + + // Read ack. + ret = ps2_recvbyte(aux, 1, timeout); + if (ret < 0) + return ret; + if (ret != PS2_RET_ACK) + return -1; + + return 0; +} + +u8 Ps2ctr VARLOW; + +static int +__ps2_command(int aux, int command, u8 *param) +{ + int ret2; + int receive = (command >> 8) & 0xf; + int send = (command >> 12) & 0xf; + + // Disable interrupts and keyboard/mouse. + u8 ps2ctr = GET_LOW(Ps2ctr); + u8 newctr = ((ps2ctr | I8042_CTR_AUXDIS | I8042_CTR_KBDDIS) + & ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT)); + dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr); + int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); + if (ret) + return ret; + + // Flush any interrupts already pending. + yield(); + + // Enable port command is being sent to. + if (aux) + newctr &= ~I8042_CTR_AUXDIS; + else + newctr &= ~I8042_CTR_KBDDIS; + ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); + if (ret) + goto fail; + + if (command == ATKBD_CMD_RESET_BAT) { + // Reset is special wrt timeouts and bytes received. + + // Send command. + ret = ps2_sendbyte(aux, command, 1000); + if (ret) + goto fail; + + // Receive parameters. + ret = ps2_recvbyte(aux, 0, 4000); + if (ret < 0) + goto fail; + param[0] = ret; + ret = ps2_recvbyte(aux, 0, 100); + if (ret < 0) + // Some devices only respond with one byte on reset. + ret = 0; + param[1] = ret; + } else if (command == ATKBD_CMD_GETID) { + // Getid is special wrt bytes received. + + // Send command. + ret = ps2_sendbyte(aux, command, 200); + if (ret) + goto fail; + + // Receive parameters. + ret = ps2_recvbyte(aux, 0, 500); + if (ret < 0) + goto fail; + param[0] = ret; + if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d + || ret == 0x60 || ret == 0x47) { + // These ids (keyboards) return two bytes. + ret = ps2_recvbyte(aux, 0, 500); + if (ret < 0) + goto fail; + param[1] = ret; + } else { + param[1] = 0; + } + } else { + // Send command. + ret = ps2_sendbyte(aux, command, 200); + if (ret) + goto fail; + + // Send parameters (if any). + int i; + for (i = 0; i < send; i++) { + ret = ps2_sendbyte(aux, param[i], 200); + if (ret) + goto fail; + } + + // Receive parameters (if any). + for (i = 0; i < receive; i++) { + ret = ps2_recvbyte(aux, 0, 500); + if (ret < 0) + goto fail; + param[i] = ret; + } + } + + ret = 0; + +fail: + // Restore interrupts and keyboard/mouse. + ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr); + if (ret2) + return ret2; + + return ret; +} + +static int +ps2_command(int aux, int command, u8 *param) +{ + dprintf(7, "ps2_command aux=%d cmd=%x\n", aux, command); + int ret = __ps2_command(aux, command, param); + if (ret) + dprintf(2, "ps2 command %x failed (aux=%d)\n", command, aux); + return ret; +} + +int +ps2_kbd_command(int command, u8 *param) +{ + if (! CONFIG_PS2PORT) + return -1; + return ps2_command(0, command, param); +} + +int +ps2_mouse_command(int command, u8 *param) +{ + if (! CONFIG_PS2PORT) + return -1; + + // Update ps2ctr for mouse enable/disable. + if (command == PSMOUSE_CMD_ENABLE || command == PSMOUSE_CMD_DISABLE) { + u8 ps2ctr = GET_LOW(Ps2ctr); + if (command == PSMOUSE_CMD_ENABLE) + ps2ctr = (ps2ctr | I8042_CTR_AUXINT) & ~I8042_CTR_AUXDIS; + else + ps2ctr = (ps2ctr | I8042_CTR_AUXDIS) & ~I8042_CTR_AUXINT; + SET_LOW(Ps2ctr, ps2ctr); + } + + return ps2_command(1, command, param); +} + + +/**************************************************************** + * IRQ handlers + ****************************************************************/ + +// INT74h : PS/2 mouse hardware interrupt +void VISIBLE16 +handle_74(void) +{ + if (! CONFIG_PS2PORT) + return; + + debug_isr(DEBUG_ISR_74); + + u8 v = inb(PORT_PS2_STATUS); + if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA)) + != (I8042_STR_OBF|I8042_STR_AUXDATA)) { + dprintf(1, "ps2 mouse irq but no mouse data.\n"); + goto done; + } + v = inb(PORT_PS2_DATA); + + if (!(GET_LOW(Ps2ctr) & I8042_CTR_AUXINT)) + // Interrupts not enabled. + goto done; + + process_mouse(v); + +done: + pic_eoi2(); +} + +// INT09h : Keyboard Hardware Service Entry Point +void VISIBLE16 +handle_09(void) +{ + if (! CONFIG_PS2PORT) + return; + + debug_isr(DEBUG_ISR_09); + + // read key from keyboard controller + u8 v = inb(PORT_PS2_STATUS); + if (v & I8042_STR_AUXDATA) { + dprintf(1, "ps2 keyboard irq but found mouse data?!\n"); + goto done; + } + v = inb(PORT_PS2_DATA); + + if (!(GET_LOW(Ps2ctr) & I8042_CTR_KBDINT)) + // Interrupts not enabled. + goto done; + + process_key(v); + + // Some old programs expect ISR to turn keyboard back on. + i8042_command(I8042_CMD_KBD_ENABLE, NULL); + +done: + pic_eoi1(); +} + + +/**************************************************************** + * Setup + ****************************************************************/ + +static void +ps2_keyboard_setup(void *data) +{ + /* flush incoming keys */ + int ret = i8042_flush(); + if (ret) + return; + + // Controller self-test. + u8 param[2]; + ret = i8042_command(I8042_CMD_CTL_TEST, param); + if (ret) + return; + if (param[0] != 0x55) { + dprintf(1, "i8042 self test failed (got %x not 0x55)\n", param[0]); + return; + } + + // Controller keyboard test. + ret = i8042_command(I8042_CMD_KBD_TEST, param); + if (ret) + return; + if (param[0] != 0x00) { + dprintf(1, "i8042 keyboard test failed (got %x not 0x00)\n", param[0]); + return; + } + + // Disable keyboard and mouse events. + SET_LOW(Ps2ctr, I8042_CTR_KBDDIS | I8042_CTR_AUXDIS); + + + /* ------------------- keyboard side ------------------------*/ + /* reset keyboard and self test (keyboard side) */ + int spinupdelay = romfile_loadint("etc/ps2-keyboard-spinup", 0); + u32 end = timer_calc(spinupdelay); + for (;;) { + ret = ps2_kbd_command(ATKBD_CMD_RESET_BAT, param); + if (!ret) + break; + if (timer_check(end)) { + if (spinupdelay) + warn_timeout(); + return; + } + yield(); + } + if (param[0] != 0xaa) { + dprintf(1, "keyboard self test failed (got %x not 0xaa)\n", param[0]); + return; + } + + /* Disable keyboard */ + ret = ps2_kbd_command(ATKBD_CMD_RESET_DIS, NULL); + if (ret) + return; + + // Set scancode command (mode 2) + param[0] = 0x02; + ret = ps2_kbd_command(ATKBD_CMD_SSCANSET, param); + if (ret) + return; + + // Keyboard Mode: disable mouse, scan code convert, enable kbd IRQ + SET_LOW(Ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT); + + /* Enable keyboard */ + ret = ps2_kbd_command(ATKBD_CMD_ENABLE, NULL); + if (ret) + return; + + dprintf(1, "PS2 keyboard initialized\n"); +} + +void +ps2port_setup(void) +{ + ASSERT32FLAT(); + if (! CONFIG_PS2PORT) + return; + dprintf(3, "init ps2port\n"); + + enable_hwirq(1, FUNC16(entry_09)); + enable_hwirq(12, FUNC16(entry_74)); + + run_thread(ps2_keyboard_setup, NULL); +} diff -Nru seabios-1.7.1/src/hw/ps2port.h seabios-1.7.4/src/hw/ps2port.h --- seabios-1.7.1/src/hw/ps2port.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/ps2port.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,75 @@ +// Basic ps2 port (keyboard/mouse) command handling. +#ifndef __PS2PORT_H +#define __PS2PORT_H + +#define PORT_PS2_DATA 0x0060 +#define PORT_PS2_CTRLB 0x0061 +#define PORT_PS2_STATUS 0x0064 +#define PORT_A20 0x0092 + +// PORT_A20 bitdefs +#define A20_ENABLE_BIT 0x02 + +// Standard commands. +#define I8042_CMD_CTL_RCTR 0x0120 +#define I8042_CMD_CTL_WCTR 0x1060 +#define I8042_CMD_CTL_TEST 0x01aa + +#define I8042_CMD_KBD_TEST 0x01ab +#define I8042_CMD_KBD_DISABLE 0x00ad +#define I8042_CMD_KBD_ENABLE 0x00ae + +#define I8042_CMD_AUX_DISABLE 0x00a7 +#define I8042_CMD_AUX_ENABLE 0x00a8 +#define I8042_CMD_AUX_SEND 0x10d4 + +// Keyboard commands +#define ATKBD_CMD_SETLEDS 0x10ed +#define ATKBD_CMD_SSCANSET 0x10f0 +#define ATKBD_CMD_GETID 0x02f2 +#define ATKBD_CMD_ENABLE 0x00f4 +#define ATKBD_CMD_RESET_DIS 0x00f5 +#define ATKBD_CMD_RESET_BAT 0x02ff + +// Mouse commands +#define PSMOUSE_CMD_SETSCALE11 0x00e6 +#define PSMOUSE_CMD_SETSCALE21 0x00e7 +#define PSMOUSE_CMD_SETRES 0x10e8 +#define PSMOUSE_CMD_GETINFO 0x03e9 +#define PSMOUSE_CMD_GETID 0x02f2 +#define PSMOUSE_CMD_SETRATE 0x10f3 +#define PSMOUSE_CMD_ENABLE 0x00f4 +#define PSMOUSE_CMD_DISABLE 0x00f5 +#define PSMOUSE_CMD_RESET_BAT 0x02ff + +// Status register bits. +#define I8042_STR_PARITY 0x80 +#define I8042_STR_TIMEOUT 0x40 +#define I8042_STR_AUXDATA 0x20 +#define I8042_STR_KEYLOCK 0x10 +#define I8042_STR_CMDDAT 0x08 +#define I8042_STR_MUXERR 0x04 +#define I8042_STR_IBF 0x02 +#define I8042_STR_OBF 0x01 + +// Control register bits. +#define I8042_CTR_KBDINT 0x01 +#define I8042_CTR_AUXINT 0x02 +#define I8042_CTR_IGNKEYLOCK 0x08 +#define I8042_CTR_KBDDIS 0x10 +#define I8042_CTR_AUXDIS 0x20 +#define I8042_CTR_XLATE 0x40 + +#ifndef __ASSEMBLY__ + +#include "types.h" // u8 + +// functions +void i8042_reboot(void); +int ps2_kbd_command(int command, u8 *param); +int ps2_mouse_command(int command, u8 *param); +void ps2port_setup(void); + +#endif // !__ASSEMBLY__ + +#endif // ps2port.h diff -Nru seabios-1.7.1/src/hw/pvscsi.c seabios-1.7.4/src/hw/pvscsi.c --- seabios-1.7.1/src/hw/pvscsi.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pvscsi.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,364 @@ +// QEMU VMWARE Paravirtualized SCSI boot support. +// +// Copyright (c) 2013 Ravello Systems LTD (http://ravellosystems.com) +// +// Authors: +// Evgeny Budilovsky +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct drive_s +#include "blockcmd.h" // scsi_drive_setup +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_DEVICE_ID_VMWARE_PVSCSI +#include "pci_regs.h" // PCI_VENDOR_ID +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // usleep +#include "pvscsi.h" +#include "virtio-ring.h" // PAGE_SHIFT, virt_to_phys + +#define MASK(n) ((1 << (n)) - 1) + +#define SIMPLE_QUEUE_TAG 0x20 + +#define PVSCSI_INTR_CMPL_0 (1 << 0) +#define PVSCSI_INTR_CMPL_1 (1 << 1) +#define PVSCSI_INTR_CMPL_MASK MASK(2) + +#define PVSCSI_INTR_MSG_0 (1 << 2) +#define PVSCSI_INTR_MSG_1 (1 << 3) +#define PVSCSI_INTR_MSG_MASK (MASK(2) << 2) +#define PVSCSI_INTR_ALL_SUPPORTED MASK(4) + +#define PVSCSI_FLAG_CMD_WITH_SG_LIST (1 << 0) +#define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB (1 << 1) +#define PVSCSI_FLAG_CMD_DIR_NONE (1 << 2) +#define PVSCSI_FLAG_CMD_DIR_TOHOST (1 << 3) +#define PVSCSI_FLAG_CMD_DIR_TODEVICE (1 << 4) + +enum PVSCSIRegOffset { + PVSCSI_REG_OFFSET_COMMAND = 0x0, + PVSCSI_REG_OFFSET_COMMAND_DATA = 0x4, + PVSCSI_REG_OFFSET_COMMAND_STATUS = 0x8, + PVSCSI_REG_OFFSET_LAST_STS_0 = 0x100, + PVSCSI_REG_OFFSET_LAST_STS_1 = 0x104, + PVSCSI_REG_OFFSET_LAST_STS_2 = 0x108, + PVSCSI_REG_OFFSET_LAST_STS_3 = 0x10c, + PVSCSI_REG_OFFSET_INTR_STATUS = 0x100c, + PVSCSI_REG_OFFSET_INTR_MASK = 0x2010, + PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014, + PVSCSI_REG_OFFSET_DEBUG = 0x3018, + PVSCSI_REG_OFFSET_KICK_RW_IO = 0x4018, +}; + +enum PVSCSICommands { + PVSCSI_CMD_FIRST = 0, + PVSCSI_CMD_ADAPTER_RESET = 1, + PVSCSI_CMD_ISSUE_SCSI = 2, + PVSCSI_CMD_SETUP_RINGS = 3, + PVSCSI_CMD_RESET_BUS = 4, + PVSCSI_CMD_RESET_DEVICE = 5, + PVSCSI_CMD_ABORT_CMD = 6, + PVSCSI_CMD_CONFIG = 7, + PVSCSI_CMD_SETUP_MSG_RING = 8, + PVSCSI_CMD_DEVICE_UNPLUG = 9, + PVSCSI_CMD_LAST = 10 +}; + +#define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES 32 +struct PVSCSICmdDescSetupRings { + u32 reqRingNumPages; + u32 cmpRingNumPages; + u64 ringsStatePPN; + u64 reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES]; + u64 cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES]; +} PACKED; + +struct PVSCSIRingCmpDesc { + u64 context; + u64 dataLen; + u32 senseLen; + u16 hostStatus; + u16 scsiStatus; + u32 pad[2]; +} PACKED; + +struct PVSCSIRingsState { + u32 reqProdIdx; + u32 reqConsIdx; + u32 reqNumEntriesLog2; + + u32 cmpProdIdx; + u32 cmpConsIdx; + u32 cmpNumEntriesLog2; + + u8 pad[104]; + + u32 msgProdIdx; + u32 msgConsIdx; + u32 msgNumEntriesLog2; +} PACKED; + +struct PVSCSIRingReqDesc { + u64 context; + u64 dataAddr; + u64 dataLen; + u64 senseAddr; + u32 senseLen; + u32 flags; + u8 cdb[16]; + u8 cdbLen; + u8 lun[8]; + u8 tag; + u8 bus; + u8 target; + u8 vcpuHint; + u8 unused[59]; +} PACKED; + +struct pvscsi_ring_dsc_s { + struct PVSCSIRingsState *ring_state; + struct PVSCSIRingReqDesc *ring_reqs; + struct PVSCSIRingCmpDesc *ring_cmps; +}; + +struct pvscsi_lun_s { + struct drive_s drive; + struct pci_device *pci; + u32 iobase; + u8 target; + u8 lun; + struct pvscsi_ring_dsc_s *ring_dsc; +}; + +static void +pvscsi_write_cmd_desc(u32 iobase, u32 cmd, const void *desc, size_t len) +{ + const u32 *ptr = desc; + size_t i; + + len /= sizeof(*ptr); + pci_writel(iobase + PVSCSI_REG_OFFSET_COMMAND, cmd); + for (i = 0; i < len; i++) + pci_writel(iobase + PVSCSI_REG_OFFSET_COMMAND_DATA, ptr[i]); +} + +static void +pvscsi_kick_rw_io(u32 iobase) +{ + pci_writel(iobase + PVSCSI_REG_OFFSET_KICK_RW_IO, 0); +} + +static void +pvscsi_wait_intr_cmpl(u32 iobase) +{ + while (!(pci_readl(iobase + PVSCSI_REG_OFFSET_INTR_STATUS) & PVSCSI_INTR_CMPL_MASK)) + usleep(5); + pci_writel(iobase + PVSCSI_REG_OFFSET_INTR_STATUS, PVSCSI_INTR_CMPL_MASK); + +} + +static void +pvscsi_init_rings(u32 iobase, struct pvscsi_ring_dsc_s **ring_dsc) +{ + struct PVSCSICmdDescSetupRings cmd = {0,}; + + struct pvscsi_ring_dsc_s *dsc = memalign_low(sizeof(*dsc), PAGE_SIZE); + if (!dsc) { + warn_noalloc(); + return; + } + + dsc->ring_state = + (struct PVSCSIRingsState *)memalign_low(PAGE_SIZE, PAGE_SIZE); + dsc->ring_reqs = + (struct PVSCSIRingReqDesc *)memalign_low(PAGE_SIZE, PAGE_SIZE); + dsc->ring_cmps = + (struct PVSCSIRingCmpDesc *)memalign_low(PAGE_SIZE, PAGE_SIZE); + if (!dsc->ring_state || !dsc->ring_reqs || !dsc->ring_cmps) { + warn_noalloc(); + return; + } + memset(dsc->ring_state, 0, PAGE_SIZE); + memset(dsc->ring_reqs, 0, PAGE_SIZE); + memset(dsc->ring_cmps, 0, PAGE_SIZE); + + cmd.reqRingNumPages = 1; + cmd.cmpRingNumPages = 1; + cmd.ringsStatePPN = virt_to_phys(dsc->ring_state) >> PAGE_SHIFT; + cmd.reqRingPPNs[0] = virt_to_phys(dsc->ring_reqs) >> PAGE_SHIFT; + cmd.cmpRingPPNs[0] = virt_to_phys(dsc->ring_cmps) >> PAGE_SHIFT; + + pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_SETUP_RINGS, + &cmd, sizeof(cmd)); + *ring_dsc = dsc; +} + +static void pvscsi_fill_req(struct PVSCSIRingsState *s, + struct PVSCSIRingReqDesc *req, + u16 target, u16 lun, void *cdbcmd, u16 blocksize, + struct disk_op_s *op) +{ + SET_LOWFLAT(req->bus, 0); + SET_LOWFLAT(req->target, target); + memset(LOWFLAT2LOW(&req->lun[0]), 0, sizeof(req->lun)); + SET_LOWFLAT(req->lun[1], lun); + SET_LOWFLAT(req->senseLen, 0); + SET_LOWFLAT(req->senseAddr, 0); + SET_LOWFLAT(req->cdbLen, 16); + SET_LOWFLAT(req->vcpuHint, 0); + memcpy(LOWFLAT2LOW(&req->cdb[0]), cdbcmd, 16); + SET_LOWFLAT(req->tag, SIMPLE_QUEUE_TAG); + SET_LOWFLAT(req->flags, + cdb_is_read(cdbcmd, blocksize) ? + PVSCSI_FLAG_CMD_DIR_TOHOST : PVSCSI_FLAG_CMD_DIR_TODEVICE); + + SET_LOWFLAT(req->dataLen, op->count * blocksize); + SET_LOWFLAT(req->dataAddr, (u32)op->buf_fl); + SET_LOWFLAT(s->reqProdIdx, GET_LOWFLAT(s->reqProdIdx) + 1); + +} + +static u32 +pvscsi_get_rsp(struct PVSCSIRingsState *s, + struct PVSCSIRingCmpDesc *rsp) +{ + u32 status = GET_LOWFLAT(rsp->hostStatus); + SET_LOWFLAT(s->cmpConsIdx, GET_LOWFLAT(s->cmpConsIdx)+1); + return status; +} + +static int +pvscsi_cmd(struct pvscsi_lun_s *plun_gf, struct disk_op_s *op, + void *cdbcmd, u16 target, u16 lun, u16 blocksize) +{ + struct pvscsi_ring_dsc_s *ring_dsc = GET_GLOBALFLAT(plun_gf->ring_dsc); + struct PVSCSIRingsState *s = GET_LOWFLAT(ring_dsc->ring_state); + u32 req_entries = GET_LOWFLAT(s->reqNumEntriesLog2); + u32 cmp_entries = GET_LOWFLAT(s->cmpNumEntriesLog2); + struct PVSCSIRingReqDesc *req; + struct PVSCSIRingCmpDesc *rsp; + u32 status; + + if (GET_LOWFLAT(s->reqProdIdx) - GET_LOWFLAT(s->cmpConsIdx) >= 1 << req_entries) { + dprintf(1, "pvscsi: ring full: reqProdIdx=%d cmpConsIdx=%d\n", + GET_LOWFLAT(s->reqProdIdx), GET_LOWFLAT(s->cmpConsIdx)); + return DISK_RET_EBADTRACK; + } + + req = GET_LOWFLAT(ring_dsc->ring_reqs) + (GET_LOWFLAT(s->reqProdIdx) & MASK(req_entries)); + pvscsi_fill_req(s, req, target, lun, cdbcmd, blocksize, op); + + pvscsi_kick_rw_io(GET_GLOBALFLAT(plun_gf->iobase)); + pvscsi_wait_intr_cmpl(GET_GLOBALFLAT(plun_gf->iobase)); + + rsp = GET_LOWFLAT(ring_dsc->ring_cmps) + (GET_LOWFLAT(s->cmpConsIdx) & MASK(cmp_entries)); + status = pvscsi_get_rsp(s, rsp); + + return status == 0 ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK; +} + +int +pvscsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + if (!CONFIG_PVSCSI) + return DISK_RET_EBADTRACK; + + struct pvscsi_lun_s *plun_gf = + container_of(op->drive_gf, struct pvscsi_lun_s, drive); + + return pvscsi_cmd(plun_gf, op, cdbcmd, + GET_GLOBALFLAT(plun_gf->target), + GET_GLOBALFLAT(plun_gf->lun), + blocksize); + +} + +static int +pvscsi_add_lun(struct pci_device *pci, u32 iobase, + struct pvscsi_ring_dsc_s *ring_dsc, u8 target, u8 lun) +{ + struct pvscsi_lun_s *plun = malloc_fseg(sizeof(*plun)); + if (!plun) { + warn_noalloc(); + return -1; + } + memset(plun, 0, sizeof(*plun)); + plun->drive.type = DTYPE_PVSCSI; + plun->drive.cntl_id = pci->bdf; + plun->pci = pci; + plun->target = target; + plun->lun = lun; + plun->iobase = iobase; + plun->ring_dsc = ring_dsc; + + char *name = znprintf(16, "pvscsi %02x:%02x.%x %d:%d", + pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), + pci_bdf_to_fn(pci->bdf), target, lun); + int prio = bootprio_find_scsi_device(pci, target, lun); + int ret = scsi_drive_setup(&plun->drive, name, prio); + free(name); + if (ret) + goto fail; + return 0; + +fail: + free(plun); + return -1; +} + +static void +pvscsi_scan_target(struct pci_device *pci, u32 iobase, + struct pvscsi_ring_dsc_s *ring_dsc, u8 target) +{ + /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ + pvscsi_add_lun(pci, iobase, ring_dsc, target, 0); +} + +static void +init_pvscsi(struct pci_device *pci) +{ + struct pvscsi_ring_dsc_s *ring_dsc = NULL; + int i; + u16 bdf = pci->bdf; + u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) + & PCI_BASE_ADDRESS_MEM_MASK; + + pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + + dprintf(1, "found pvscsi at %02x:%02x.%x, io @ %x\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), + pci_bdf_to_fn(bdf), iobase); + + pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_ADAPTER_RESET, NULL, 0); + + pvscsi_init_rings(iobase, &ring_dsc); + for (i = 0; i < 7; i++) + pvscsi_scan_target(pci, iobase, ring_dsc, i); + + return; + +} + +void +pvscsi_setup(void) +{ + ASSERT32FLAT(); + if (! CONFIG_PVSCSI) + return; + + dprintf(3, "init pvscsi\n"); + + struct pci_device *pci; + foreachpci(pci) { + if (pci->vendor != PCI_VENDOR_ID_VMWARE + || pci->device != PCI_DEVICE_ID_VMWARE_PVSCSI) + continue; + init_pvscsi(pci); + } +} diff -Nru seabios-1.7.1/src/hw/pvscsi.h seabios-1.7.4/src/hw/pvscsi.h --- seabios-1.7.1/src/hw/pvscsi.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/pvscsi.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef _PVSCSI_H_ +#define _PVSCSI_H_ + +struct disk_op_s; +int pvscsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +void pvscsi_setup(void); + +#endif /* _PVSCSI_H_ */ diff -Nru seabios-1.7.1/src/hw/ramdisk.c seabios-1.7.4/src/hw/ramdisk.c --- seabios-1.7.1/src/hw/ramdisk.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/ramdisk.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,112 @@ +// Code for emulating a drive via high-memory accesses. +// +// Copyright (C) 2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct drive_s +#include "bregs.h" // struct bregs +#include "malloc.h" // malloc_fseg +#include "memmap.h" // add_e820 +#include "output.h" // dprintf +#include "romfile.h" // romfile_findprefix +#include "stacks.h" // call16_int +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // process_ramdisk_op + +void +ramdisk_setup(void) +{ + if (!CONFIG_FLASH_FLOPPY) + return; + + // Find image. + struct romfile_s *file = romfile_findprefix("floppyimg/", NULL); + if (!file) + return; + const char *filename = file->name; + u32 size = file->size; + dprintf(3, "Found floppy file %s of size %d\n", filename, size); + int ftype = find_floppy_type(size); + if (ftype < 0) { + dprintf(3, "No floppy type found for ramdisk size\n"); + return; + } + + // Allocate ram for image. + void *pos = memalign_tmphigh(PAGE_SIZE, size); + if (!pos) { + warn_noalloc(); + return; + } + add_e820((u32)pos, size, E820_RESERVED); + + // Copy image into ram. + int ret = file->copy(file, pos, size); + if (ret < 0) + return; + + // Setup driver. + struct drive_s *drive = init_floppy((u32)pos, ftype); + if (!drive) + return; + drive->type = DTYPE_RAMDISK; + dprintf(1, "Mapping CBFS floppy %s to addr %p\n", filename, pos); + char *desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", &filename[10]); + boot_add_floppy(drive, desc, bootprio_find_named_rom(filename, 0)); +} + +static int +ramdisk_copy(struct disk_op_s *op, int iswrite) +{ + u32 offset = GET_GLOBALFLAT(op->drive_gf->cntl_id); + offset += (u32)op->lba * DISK_SECTOR_SIZE; + u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl); + u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset); + + u64 gdt[6]; + if (iswrite) { + gdt[2] = opd; + gdt[3] = ramd; + } else { + gdt[2] = ramd; + gdt[3] = opd; + } + + // Call int 1587 to copy data. + struct bregs br; + memset(&br, 0, sizeof(br)); + br.flags = F_CF|F_IF; + br.ah = 0x87; + br.es = GET_SEG(SS); + br.si = (u32)gdt; + br.cx = op->count * DISK_SECTOR_SIZE / 2; + call16_int(0x15, &br); + + if (br.flags & F_CF) + return DISK_RET_EBADTRACK; + return DISK_RET_SUCCESS; +} + +int +process_ramdisk_op(struct disk_op_s *op) +{ + if (!CONFIG_FLASH_FLOPPY) + return 0; + + switch (op->command) { + case CMD_READ: + return ramdisk_copy(op, 0); + case CMD_WRITE: + return ramdisk_copy(op, 1); + case CMD_VERIFY: + case CMD_FORMAT: + case CMD_RESET: + return DISK_RET_SUCCESS; + default: + op->count = 0; + return DISK_RET_EPARAM; + } +} diff -Nru seabios-1.7.1/src/hw/rtc.c seabios-1.7.4/src/hw/rtc.c --- seabios-1.7.1/src/hw/rtc.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/rtc.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,93 @@ +// Support for MC146818 Real Time Clock chip. +// +// Copyright (C) 2008-2013 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_LOW +#include "rtc.h" // rtc_read +#include "stacks.h" // yield +#include "util.h" // timer_calc +#include "x86.h" // inb + +u8 +rtc_read(u8 index) +{ + index |= NMI_DISABLE_BIT; + outb(index, PORT_CMOS_INDEX); + return inb(PORT_CMOS_DATA); +} + +void +rtc_write(u8 index, u8 val) +{ + index |= NMI_DISABLE_BIT; + outb(index, PORT_CMOS_INDEX); + outb(val, PORT_CMOS_DATA); +} + +void +rtc_mask(u8 index, u8 off, u8 on) +{ + outb(index, PORT_CMOS_INDEX); + u8 val = inb(PORT_CMOS_DATA); + outb((val & ~off) | on, PORT_CMOS_DATA); +} + +int +rtc_updating(void) +{ + // This function checks to see if the update-in-progress bit + // is set in CMOS Status Register A. If not, it returns 0. + // If it is set, it tries to wait until there is a transition + // to 0, and will return 0 if such a transition occurs. A -1 + // is returned only after timing out. The maximum period + // that this bit should be set is constrained to (1984+244) + // useconds, but we wait for longer just to be sure. + + if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0) + return 0; + u32 end = timer_calc(15); + for (;;) { + if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0) + return 0; + if (timer_check(end)) + // update-in-progress never transitioned to 0 + return -1; + yield(); + } +} + +void +rtc_setup(void) +{ + rtc_write(CMOS_STATUS_A, 0x26); // 32,768Khz src, 976.5625us updates + rtc_mask(CMOS_STATUS_B, ~RTC_B_DSE, RTC_B_24HR); + rtc_read(CMOS_STATUS_C); + rtc_read(CMOS_STATUS_D); +} + +int RTCusers VARLOW; + +void +rtc_use(void) +{ + int count = GET_LOW(RTCusers); + SET_LOW(RTCusers, count+1); + if (count) + return; + // Turn on the Periodic Interrupt timer + rtc_mask(CMOS_STATUS_B, 0, RTC_B_PIE); +} + +void +rtc_release(void) +{ + int count = GET_LOW(RTCusers); + SET_LOW(RTCusers, count-1); + if (count != 1) + return; + // Clear the Periodic Interrupt. + rtc_mask(CMOS_STATUS_B, RTC_B_PIE, 0); +} diff -Nru seabios-1.7.1/src/hw/rtc.h seabios-1.7.4/src/hw/rtc.h --- seabios-1.7.1/src/hw/rtc.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/rtc.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,75 @@ +#ifndef __RTC_H +#define __RTC_H + +#define PORT_CMOS_INDEX 0x0070 +#define PORT_CMOS_DATA 0x0071 + +// PORT_CMOS_INDEX nmi disable bit +#define NMI_DISABLE_BIT 0x80 + +// Standard BIOS RTC chip entries +#define CMOS_RTC_SECONDS 0x00 +#define CMOS_RTC_SECONDS_ALARM 0x01 +#define CMOS_RTC_MINUTES 0x02 +#define CMOS_RTC_MINUTES_ALARM 0x03 +#define CMOS_RTC_HOURS 0x04 +#define CMOS_RTC_HOURS_ALARM 0x05 +#define CMOS_RTC_DAY_WEEK 0x06 +#define CMOS_RTC_DAY_MONTH 0x07 +#define CMOS_RTC_MONTH 0x08 +#define CMOS_RTC_YEAR 0x09 +#define CMOS_STATUS_A 0x0a +#define CMOS_STATUS_B 0x0b +#define CMOS_STATUS_C 0x0c +#define CMOS_STATUS_D 0x0d +#define CMOS_RESET_CODE 0x0f + +// QEMU cmos config fields. DO NOT ADD MORE. (All new content should +// be passed via the fw_cfg "file" interface.) +#define CMOS_FLOPPY_DRIVE_TYPE 0x10 +#define CMOS_DISK_DATA 0x12 +#define CMOS_EQUIPMENT_INFO 0x14 +#define CMOS_DISK_DRIVE1_TYPE 0x19 +#define CMOS_DISK_DRIVE2_TYPE 0x1a +#define CMOS_DISK_DRIVE1_CYL 0x1b +#define CMOS_DISK_DRIVE2_CYL 0x24 +#define CMOS_MEM_EXTMEM_LOW 0x30 +#define CMOS_MEM_EXTMEM_HIGH 0x31 +#define CMOS_CENTURY 0x32 +#define CMOS_MEM_EXTMEM2_LOW 0x34 +#define CMOS_MEM_EXTMEM2_HIGH 0x35 +#define CMOS_BIOS_BOOTFLAG1 0x38 +#define CMOS_BIOS_DISKTRANSFLAG 0x39 +#define CMOS_BIOS_BOOTFLAG2 0x3d +#define CMOS_MEM_HIGHMEM_LOW 0x5b +#define CMOS_MEM_HIGHMEM_MID 0x5c +#define CMOS_MEM_HIGHMEM_HIGH 0x5d +#define CMOS_BIOS_SMP_COUNT 0x5f + +// RTC register flags +#define RTC_A_UIP 0x80 + +#define RTC_B_SET 0x80 +#define RTC_B_PIE 0x40 +#define RTC_B_AIE 0x20 +#define RTC_B_UIE 0x10 +#define RTC_B_BIN 0x04 +#define RTC_B_24HR 0x02 +#define RTC_B_DSE 0x01 + +#ifndef __ASSEMBLY__ + +#include "types.h" // u8 + +// rtc.c +u8 rtc_read(u8 index); +void rtc_write(u8 index, u8 val); +void rtc_mask(u8 index, u8 off, u8 on); +int rtc_updating(void); +void rtc_setup(void); +void rtc_use(void); +void rtc_release(void); + +#endif // !__ASSEMBLY__ + +#endif // rtc.h diff -Nru seabios-1.7.1/src/hw/serialio.c seabios-1.7.4/src/hw/serialio.c --- seabios-1.7.1/src/hw/serialio.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/serialio.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,89 @@ +// Low-level serial (and serial-like) device access. +// +// Copyright (C) 2008-1013 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_DEBUG_SERIAL +#include "fw/paravirt.h" // RunningOnQEMU +#include "output.h" // dprintf +#include "serialio.h" // serial_debug_preinit +#include "x86.h" // outb + + +/**************************************************************** + * Serial port debug output + ****************************************************************/ + +#define DEBUG_TIMEOUT 100000 + +// Setup the debug serial port for output. +void +serial_debug_preinit(void) +{ + if (!CONFIG_DEBUG_SERIAL) + return; + // setup for serial logging: 8N1 + u8 oldparam, newparam = 0x03; + oldparam = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); + outb(newparam, CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); + // Disable irqs + u8 oldier, newier = 0; + oldier = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); + outb(newier, CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); + + if (oldparam != newparam || oldier != newier) + dprintf(1, "Changing serial settings was %x/%x now %x/%x\n" + , oldparam, oldier, newparam, newier); +} + +// Write a character to the serial port. +static void +serial_debug(char c) +{ + if (!CONFIG_DEBUG_SERIAL) + return; + int timeout = DEBUG_TIMEOUT; + while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x20) != 0x20) + if (!timeout--) + // Ran out of time. + return; + outb(c, CONFIG_DEBUG_SERIAL_PORT+SEROFF_DATA); +} + +void +serial_debug_putc(char c) +{ + if (c == '\n') + serial_debug('\r'); + serial_debug(c); +} + +// Make sure all serial port writes have been completely sent. +void +serial_debug_flush(void) +{ + if (!CONFIG_DEBUG_SERIAL) + return; + int timeout = DEBUG_TIMEOUT; + while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x60) != 0x60) + if (!timeout--) + // Ran out of time. + return; +} + + +/**************************************************************** + * QEMU debug port + ****************************************************************/ + +u16 DebugOutputPort VARFSEG = 0x402; + +// Write a character to the special debugging port. +void +qemu_debug_putc(char c) +{ + if (CONFIG_DEBUG_IO && runningOnQEMU()) + // Send character to debug port. + outb(c, GET_GLOBAL(DebugOutputPort)); +} diff -Nru seabios-1.7.1/src/hw/serialio.h seabios-1.7.4/src/hw/serialio.h --- seabios-1.7.1/src/hw/serialio.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/serialio.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,29 @@ +#ifndef __SERIALIO_H +#define __SERIALIO_H + +#include "types.h" // u16 + +#define PORT_LPT2 0x0278 +#define PORT_SERIAL4 0x02e8 +#define PORT_SERIAL2 0x02f8 +#define PORT_LPT1 0x0378 +#define PORT_SERIAL3 0x03e8 +#define PORT_SERIAL1 0x03f8 + +// Serial port offsets +#define SEROFF_DATA 0 +#define SEROFF_DLL 0 +#define SEROFF_IER 1 +#define SEROFF_DLH 1 +#define SEROFF_IIR 2 +#define SEROFF_LCR 3 +#define SEROFF_LSR 5 +#define SEROFF_MSR 6 + +void serial_debug_preinit(void); +void serial_debug_putc(char c); +void serial_debug_flush(void); +extern u16 DebugOutputPort; +void qemu_debug_putc(char c); + +#endif // serialio.h diff -Nru seabios-1.7.1/src/hw/timer.c seabios-1.7.4/src/hw/timer.c --- seabios-1.7.1/src/hw/timer.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/timer.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,257 @@ +// Internal timer and Intel 8253 Programmable Interrupt Timer (PIT) support. +// +// Copyright (C) 2008-2013 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_LOW +#include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "ps2port.h" // PORT_PS2_CTRLB +#include "stacks.h" // yield +#include "util.h" // timer_setup +#include "x86.h" // cpuid + +#define PORT_PIT_COUNTER0 0x0040 +#define PORT_PIT_COUNTER1 0x0041 +#define PORT_PIT_COUNTER2 0x0042 +#define PORT_PIT_MODE 0x0043 + +// Bits for PORT_PIT_MODE +#define PM_SEL_TIMER0 (0<<6) +#define PM_SEL_TIMER1 (1<<6) +#define PM_SEL_TIMER2 (2<<6) +#define PM_SEL_READBACK (3<<6) +#define PM_ACCESS_LATCH (0<<4) +#define PM_ACCESS_LOBYTE (1<<4) +#define PM_ACCESS_HIBYTE (2<<4) +#define PM_ACCESS_WORD (3<<4) +#define PM_MODE0 (0<<1) +#define PM_MODE1 (1<<1) +#define PM_MODE2 (2<<1) +#define PM_MODE3 (3<<1) +#define PM_MODE4 (4<<1) +#define PM_MODE5 (5<<1) +#define PM_CNT_BINARY (0<<0) +#define PM_CNT_BCD (1<<0) +#define PM_READ_COUNTER0 (1<<1) +#define PM_READ_COUNTER1 (1<<2) +#define PM_READ_COUNTER2 (1<<3) +#define PM_READ_STATUSVALUE (0<<4) +#define PM_READ_VALUE (1<<4) +#define PM_READ_STATUS (2<<4) + +// Bits for PORT_PS2_CTRLB +#define PPCB_T2GATE (1<<0) +#define PPCB_SPKR (1<<1) +#define PPCB_T2OUT (1<<5) + +#define PMTIMER_HZ 3579545 // Underlying Hz of the PM Timer +#define PMTIMER_TO_PIT 3 // Ratio of pmtimer rate to pit rate + +u32 TimerKHz VARFSEG; +u16 TimerPort VARFSEG; +u8 ShiftTSC VARFSEG; + + +/**************************************************************** + * Internal timer setup + ****************************************************************/ + +#define CALIBRATE_COUNT 0x800 // Approx 1.7ms + +// Calibrate the CPU time-stamp-counter +static void +tsctimer_setup(void) +{ + // Setup "timer2" + u8 orig = inb(PORT_PS2_CTRLB); + outb((orig & ~PPCB_SPKR) | PPCB_T2GATE, PORT_PS2_CTRLB); + /* binary, mode 0, LSB/MSB, Ch 2 */ + outb(PM_SEL_TIMER2|PM_ACCESS_WORD|PM_MODE0|PM_CNT_BINARY, PORT_PIT_MODE); + /* LSB of ticks */ + outb(CALIBRATE_COUNT & 0xFF, PORT_PIT_COUNTER2); + /* MSB of ticks */ + outb(CALIBRATE_COUNT >> 8, PORT_PIT_COUNTER2); + + u64 start = rdtscll(); + while ((inb(PORT_PS2_CTRLB) & PPCB_T2OUT) == 0) + ; + u64 end = rdtscll(); + + // Restore PORT_PS2_CTRLB + outb(orig, PORT_PS2_CTRLB); + + // Store calibrated cpu khz. + u64 diff = end - start; + dprintf(6, "tsc calibrate start=%u end=%u diff=%u\n" + , (u32)start, (u32)end, (u32)diff); + u64 t = DIV_ROUND_UP(diff * PMTIMER_HZ, CALIBRATE_COUNT); + while (t >= (1<<24)) { + ShiftTSC++; + t = (t + 1) >> 1; + } + TimerKHz = DIV_ROUND_UP((u32)t, 1000 * PMTIMER_TO_PIT); + + dprintf(1, "CPU Mhz=%u\n", (TimerKHz << ShiftTSC) / 1000); +} + +// Setup internal timers. +void +timer_setup(void) +{ + if (CONFIG_PMTIMER && TimerPort) { + dprintf(3, "pmtimer already configured; will not calibrate TSC\n"); + return; + } + + u32 eax, ebx, ecx, edx, cpuid_features = 0; + cpuid(0, &eax, &ebx, &ecx, &edx); + if (eax > 0) + cpuid(1, &eax, &ebx, &ecx, &cpuid_features); + + if (!(cpuid_features & CPUID_TSC)) { + TimerPort = PORT_PIT_COUNTER0; + TimerKHz = DIV_ROUND_UP(PMTIMER_HZ, 1000 * PMTIMER_TO_PIT); + dprintf(3, "386/486 class CPU. Using TSC emulation\n"); + return; + } + + tsctimer_setup(); +} + +void +pmtimer_setup(u16 ioport) +{ + if (!CONFIG_PMTIMER) + return; + dprintf(1, "Using pmtimer, ioport 0x%x\n", ioport); + TimerPort = ioport; + TimerKHz = DIV_ROUND_UP(PMTIMER_HZ, 1000); +} + + +/**************************************************************** + * Internal timer reading + ****************************************************************/ + +u32 TimerLast VARLOW; + +// Add extra high bits to timers that have less than 32bits of precision. +static u32 +timer_adjust_bits(u32 value, u32 validbits) +{ + u32 last = GET_LOW(TimerLast); + value = (last & ~validbits) | (value & validbits); + if (value < last) + value += validbits + 1; + SET_LOW(TimerLast, value); + return value; +} + +// Sample the current timer value. +static u32 +timer_read(void) +{ + u16 port = GET_GLOBAL(TimerPort); + if (!port) + // Read from CPU TSC + return rdtscll() >> GET_GLOBAL(ShiftTSC); + if (CONFIG_PMTIMER && port != PORT_PIT_COUNTER0) + // Read from PMTIMER + return timer_adjust_bits(inl(port), 0xffffff); + // Read from PIT. + outb(PM_SEL_READBACK | PM_READ_VALUE | PM_READ_COUNTER0, PORT_PIT_MODE); + u16 v = inb(PORT_PIT_COUNTER0) | (inb(PORT_PIT_COUNTER0) << 8); + return timer_adjust_bits(v, 0xffff); +} + +// Check if the current time is past a previously calculated end time. +int +timer_check(u32 end) +{ + return (s32)(timer_read() - end) > 0; +} + +static void +timer_delay(u32 diff) +{ + u32 start = timer_read(); + u32 end = start + diff; + while (!timer_check(end)) + cpu_relax(); +} + +static void +timer_sleep(u32 diff) +{ + u32 start = timer_read(); + u32 end = start + diff; + while (!timer_check(end)) + yield(); +} + +void ndelay(u32 count) { + timer_delay(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000000)); +} +void udelay(u32 count) { + timer_delay(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000)); +} +void mdelay(u32 count) { + timer_delay(count * GET_GLOBAL(TimerKHz)); +} + +void nsleep(u32 count) { + timer_sleep(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000000)); +} +void usleep(u32 count) { + timer_sleep(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000)); +} +void msleep(u32 count) { + timer_sleep(count * GET_GLOBAL(TimerKHz)); +} + +// Return the TSC value that is 'msecs' time in the future. +u32 +timer_calc(u32 msecs) +{ + return timer_read() + (GET_GLOBAL(TimerKHz) * msecs); +} +u32 +timer_calc_usec(u32 usecs) +{ + return timer_read() + DIV_ROUND_UP(GET_GLOBAL(TimerKHz) * usecs, 1000); +} + + +/**************************************************************** + * PIT setup + ****************************************************************/ + +#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer + +// Return the number of milliseconds in 'ticks' number of timer irqs. +u32 +ticks_to_ms(u32 ticks) +{ + u32 t = PIT_TICK_INTERVAL * 1000 * PMTIMER_TO_PIT * ticks; + return DIV_ROUND_UP(t, PMTIMER_HZ); +} + +// Return the number of timer irqs in 'ms' number of milliseconds. +u32 +ticks_from_ms(u32 ms) +{ + u32 t = DIV_ROUND_UP((u64)ms * PMTIMER_HZ, PIT_TICK_INTERVAL); + return DIV_ROUND_UP(t, 1000 * PMTIMER_TO_PIT); +} + +void +pit_setup(void) +{ + // timer0: binary count, 16bit count, mode 2 + outb(PM_SEL_TIMER0|PM_ACCESS_WORD|PM_MODE2|PM_CNT_BINARY, PORT_PIT_MODE); + // maximum count of 0000H = 18.2Hz + outb(0x0, PORT_PIT_COUNTER0); + outb(0x0, PORT_PIT_COUNTER0); +} diff -Nru seabios-1.7.1/src/hw/usb.c seabios-1.7.4/src/hw/usb.c --- seabios-1.7.1/src/hw/usb.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,490 @@ +// Main code for handling USB controllers and devices. +// +// Copyright (C) 2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBAL +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI +#include "pci_regs.h" // PCI_CLASS_REVISION +#include "string.h" // memset +#include "usb.h" // struct usb_s +#include "usb-ehci.h" // ehci_setup +#include "usb-xhci.h" // xhci_setup +#include "usb-hid.h" // usb_keyboard_setup +#include "usb-hub.h" // usb_hub_setup +#include "usb-msc.h" // usb_msc_setup +#include "usb-ohci.h" // ohci_setup +#include "usb-uas.h" // usb_uas_setup +#include "usb-uhci.h" // uhci_setup +#include "util.h" // msleep +#include "x86.h" // __fls + + +/**************************************************************** + * Controller function wrappers + ****************************************************************/ + +// Allocate an async pipe (control or bulk). +struct usb_pipe * +usb_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + switch (usbdev->hub->cntl->type) { + default: + case USB_TYPE_UHCI: + return uhci_alloc_pipe(usbdev, epdesc); + case USB_TYPE_OHCI: + return ohci_alloc_pipe(usbdev, epdesc); + case USB_TYPE_EHCI: + return ehci_alloc_pipe(usbdev, epdesc); + case USB_TYPE_XHCI: + return xhci_alloc_pipe(usbdev, epdesc); + } +} + +// Update an pipe (used for control only) +struct usb_pipe * +usb_update_pipe(struct usbdevice_s *usbdev, struct usb_pipe *pipe + , struct usb_endpoint_descriptor *epdesc) +{ + switch (usbdev->hub->cntl->type) { + case USB_TYPE_XHCI: + return xhci_update_pipe(usbdev, pipe, epdesc); + default: + free_pipe(pipe); + return usb_alloc_pipe(usbdev, epdesc); + } +} + +// Send a message on a control pipe using the default control descriptor. +static int +send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize + , void *data, int datasize) +{ + ASSERT32FLAT(); + switch (pipe->type) { + default: + case USB_TYPE_UHCI: + return uhci_control(pipe, dir, cmd, cmdsize, data, datasize); + case USB_TYPE_OHCI: + return ohci_control(pipe, dir, cmd, cmdsize, data, datasize); + case USB_TYPE_EHCI: + return ehci_control(pipe, dir, cmd, cmdsize, data, datasize); + case USB_TYPE_XHCI: + return xhci_control(pipe, dir, cmd, cmdsize, data, datasize); + } +} + +int +usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize) +{ + switch (GET_LOWFLAT(pipe_fl->type)) { + default: + case USB_TYPE_UHCI: + return uhci_send_bulk(pipe_fl, dir, data, datasize); + case USB_TYPE_OHCI: + return ohci_send_bulk(pipe_fl, dir, data, datasize); + case USB_TYPE_EHCI: + return ehci_send_bulk(pipe_fl, dir, data, datasize); + case USB_TYPE_XHCI: + return xhci_send_bulk(pipe_fl, dir, data, datasize); + } +} + +int +usb_poll_intr(struct usb_pipe *pipe_fl, void *data) +{ + switch (GET_LOWFLAT(pipe_fl->type)) { + default: + case USB_TYPE_UHCI: + return uhci_poll_intr(pipe_fl, data); + case USB_TYPE_OHCI: + return ohci_poll_intr(pipe_fl, data); + case USB_TYPE_EHCI: + return ehci_poll_intr(pipe_fl, data); + case USB_TYPE_XHCI: + return xhci_poll_intr(pipe_fl, data); + } +} + + +/**************************************************************** + * Helper functions + ****************************************************************/ + +// Send a message to the default control pipe of a device. +int +send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req + , void *data) +{ + return send_control(pipe, req->bRequestType & USB_DIR_IN + , req, sizeof(*req), data, req->wLength); +} + +// Free an allocated control or bulk pipe. +void +free_pipe(struct usb_pipe *pipe) +{ + ASSERT32FLAT(); + if (!pipe) + return; + // Add to controller's free list. + struct usb_s *cntl = pipe->cntl; + pipe->freenext = cntl->freelist; + cntl->freelist = pipe; +} + +// Check for an available pipe on the freelist. +struct usb_pipe * +usb_getFreePipe(struct usb_s *cntl, u8 eptype) +{ + struct usb_pipe **pfree = &cntl->freelist; + for (;;) { + struct usb_pipe *pipe = *pfree; + if (!pipe) + return NULL; + if (pipe->eptype == eptype) { + *pfree = pipe->freenext; + return pipe; + } + pfree = &pipe->freenext; + } +} + +// Fill "pipe" endpoint info from an endpoint descriptor. +void +usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + pipe->cntl = usbdev->hub->cntl; + pipe->type = usbdev->hub->cntl->type; + pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + pipe->devaddr = usbdev->devaddr; + pipe->speed = usbdev->speed; + pipe->maxpacket = epdesc->wMaxPacketSize; + pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; +} + +// Find the exponential period of the requested interrupt end point. +int +usb_getFrameExp(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + int period = epdesc->bInterval; + if (usbdev->speed != USB_HIGHSPEED) + return (period <= 0) ? 0 : __fls(period); + return (period <= 4) ? 0 : period - 4; +} + +// Find the first endpoing of a given type in an interface description. +struct usb_endpoint_descriptor * +findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir) +{ + struct usb_endpoint_descriptor *epdesc = (void*)&usbdev->iface[1]; + for (;;) { + if ((void*)epdesc >= (void*)usbdev->iface + usbdev->imax + || epdesc->bDescriptorType == USB_DT_INTERFACE) { + return NULL; + } + if (epdesc->bDescriptorType == USB_DT_ENDPOINT + && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir + && (epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == type) + return epdesc; + epdesc = (void*)epdesc + epdesc->bLength; + } +} + +// Get the first 8 bytes of the device descriptor. +static int +get_device_info8(struct usb_pipe *pipe, struct usb_device_descriptor *dinfo) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; + req.bRequest = USB_REQ_GET_DESCRIPTOR; + req.wValue = USB_DT_DEVICE<<8; + req.wIndex = 0; + req.wLength = 8; + return send_default_control(pipe, &req, dinfo); +} + +static struct usb_config_descriptor * +get_device_config(struct usb_pipe *pipe) +{ + struct usb_config_descriptor cfg; + + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; + req.bRequest = USB_REQ_GET_DESCRIPTOR; + req.wValue = USB_DT_CONFIG<<8; + req.wIndex = 0; + req.wLength = sizeof(cfg); + int ret = send_default_control(pipe, &req, &cfg); + if (ret) + return NULL; + + void *config = malloc_tmphigh(cfg.wTotalLength); + if (!config) + return NULL; + req.wLength = cfg.wTotalLength; + ret = send_default_control(pipe, &req, config); + if (ret) + return NULL; + //hexdump(config, cfg.wTotalLength); + return config; +} + +static int +set_configuration(struct usb_pipe *pipe, u16 val) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; + req.bRequest = USB_REQ_SET_CONFIGURATION; + req.wValue = val; + req.wIndex = 0; + req.wLength = 0; + return send_default_control(pipe, &req, NULL); +} + + +/**************************************************************** + * Initialization and enumeration + ****************************************************************/ + +// Assign an address to a device in the default state on the given +// controller. +static int +usb_set_address(struct usbdevice_s *usbdev) +{ + ASSERT32FLAT(); + struct usb_s *cntl = usbdev->hub->cntl; + dprintf(3, "set_address %p\n", cntl); + if (cntl->maxaddr >= USB_MAXADDR) + return -1; + + // Create a pipe for the default address. + struct usb_endpoint_descriptor epdesc = { + .wMaxPacketSize = 8, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + }; + usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); + if (!usbdev->defpipe) + return -1; + + msleep(USB_TIME_RSTRCY); + + // Send set_address command. + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; + req.bRequest = USB_REQ_SET_ADDRESS; + req.wValue = cntl->maxaddr + 1; + req.wIndex = 0; + req.wLength = 0; + int ret = send_default_control(usbdev->defpipe, &req, NULL); + if (ret) { + free_pipe(usbdev->defpipe); + return -1; + } + + msleep(USB_TIME_SETADDR_RECOVERY); + + cntl->maxaddr++; + usbdev->devaddr = cntl->maxaddr; + usbdev->defpipe = usb_update_pipe(usbdev, usbdev->defpipe, &epdesc); + if (!usbdev->defpipe) + return -1; + return 0; +} + +// Called for every found device - see if a driver is available for +// this device and do setup if so. +static int +configure_usb_device(struct usbdevice_s *usbdev) +{ + ASSERT32FLAT(); + dprintf(3, "config_usb: %p\n", usbdev->defpipe); + + // Set the max packet size for endpoint 0 of this device. + struct usb_device_descriptor dinfo; + int ret = get_device_info8(usbdev->defpipe, &dinfo); + if (ret) + return 0; + dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%02x\n" + , dinfo.bcdUSB, dinfo.bDeviceClass, dinfo.bDeviceSubClass + , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0); + if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64) + return 0; + struct usb_endpoint_descriptor epdesc = { + .wMaxPacketSize = dinfo.bMaxPacketSize0, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + }; + usbdev->defpipe = usb_update_pipe(usbdev, usbdev->defpipe, &epdesc); + if (!usbdev->defpipe) + return -1; + + // Get configuration + struct usb_config_descriptor *config = get_device_config(usbdev->defpipe); + if (!config) + return 0; + + // Determine if a driver exists for this device - only look at the + // first interface of the first configuration. + struct usb_interface_descriptor *iface = (void*)(&config[1]); + if (iface->bInterfaceClass != USB_CLASS_HID + && iface->bInterfaceClass != USB_CLASS_MASS_STORAGE + && iface->bInterfaceClass != USB_CLASS_HUB) + // Not a supported device. + goto fail; + + // Set the configuration. + ret = set_configuration(usbdev->defpipe, config->bConfigurationValue); + if (ret) + goto fail; + + // Configure driver. + usbdev->config = config; + usbdev->iface = iface; + usbdev->imax = (void*)config + config->wTotalLength - (void*)iface; + if (iface->bInterfaceClass == USB_CLASS_HUB) + ret = usb_hub_setup(usbdev); + else if (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE) { + if (iface->bInterfaceProtocol == US_PR_BULK) + ret = usb_msc_setup(usbdev); + if (iface->bInterfaceProtocol == US_PR_UAS) + ret = usb_uas_setup(usbdev); + } else + ret = usb_hid_setup(usbdev); + if (ret) + goto fail; + + free(config); + return 1; +fail: + free(config); + return 0; +} + +static void +usb_hub_port_setup(void *data) +{ + struct usbdevice_s *usbdev = data; + struct usbhub_s *hub = usbdev->hub; + u32 port = usbdev->port; + + // Detect if device present (and possibly start reset) + int ret = hub->op->detect(hub, port); + if (ret) + // No device present + goto done; + + // Reset port and determine device speed + mutex_lock(&hub->cntl->resetlock); + ret = hub->op->reset(hub, port); + if (ret < 0) + // Reset failed + goto resetfail; + usbdev->speed = ret; + + // Set address of port + ret = usb_set_address(usbdev); + if (ret) { + hub->op->disconnect(hub, port); + goto resetfail; + } + mutex_unlock(&hub->cntl->resetlock); + + // Configure the device + int count = configure_usb_device(usbdev); + free_pipe(usbdev->defpipe); + if (!count) + hub->op->disconnect(hub, port); + hub->devcount += count; +done: + hub->threads--; + free(usbdev); + return; + +resetfail: + mutex_unlock(&hub->cntl->resetlock); + goto done; +} + +void +usb_enumerate(struct usbhub_s *hub) +{ + u32 portcount = hub->portcount; + hub->threads = portcount; + + // Launch a thread for every port. + int i; + for (i=0; ihub = hub; + usbdev->port = i; + run_thread(usb_hub_port_setup, usbdev); + } + + // Wait for threads to complete. + while (hub->threads) + yield(); +} + +void +usb_setup(void) +{ + ASSERT32FLAT(); + if (! CONFIG_USB) + return; + + dprintf(3, "init usb\n"); + + // Look for USB controllers + int count = 0; + struct pci_device *pci, *ehcipci = NULL; + foreachpci(pci) { + if (pci->class != PCI_CLASS_SERIAL_USB) + continue; + + if (!ehcipci || pci->bdf >= ehcipci->bdf) { + // Check to see if this device has an ehci controller + int found = 0; + ehcipci = pci; + for (;;) { + if (pci_classprog(ehcipci) == PCI_CLASS_SERIAL_USB_EHCI) { + // Found an ehci controller. + int ret = ehci_setup(ehcipci, count++, pci); + if (ret) + // Error + break; + count += found; + pci = ehcipci; + break; + } + if (ehcipci->class == PCI_CLASS_SERIAL_USB) + found++; + ehcipci = container_of_or_null( + ehcipci->node.next, struct pci_device, node); + if (!ehcipci || (pci_bdf_to_busdev(ehcipci->bdf) + != pci_bdf_to_busdev(pci->bdf))) + // No ehci controller found. + break; + } + } + + if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI) + uhci_setup(pci, count++); + else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI) + ohci_setup(pci, count++); + else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_XHCI) + xhci_setup(pci, count++); + } +} diff -Nru seabios-1.7.1/src/hw/usb-ehci.c seabios-1.7.4/src/hw/usb-ehci.c --- seabios-1.7.1/src/hw/usb-ehci.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-ehci.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,726 @@ +// Code for handling EHCI USB controllers. +// +// Copyright (C) 2010 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_LOWFLAT +#include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "malloc.h" // free +#include "pci.h" // pci_bdf_to_bus +#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI +#include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "string.h" // memset +#include "usb.h" // struct usb_s +#include "usb-ehci.h" // struct ehci_qh +#include "usb-ohci.h" // ohci_setup +#include "usb-uhci.h" // uhci_setup +#include "util.h" // msleep +#include "x86.h" // readl + +struct usb_ehci_s { + struct usb_s usb; + struct ehci_caps *caps; + struct ehci_regs *regs; + struct ehci_qh *async_qh; + struct pci_device *companion[8]; + int checkports; + int legacycount; +}; + +struct ehci_pipe { + struct ehci_qh qh; + struct ehci_qtd *next_td, *tds; + void *data; + struct usb_pipe pipe; +}; + + +/**************************************************************** + * Root hub + ****************************************************************/ + +#define EHCI_TIME_POSTPOWER 20 +#define EHCI_TIME_POSTRESET 2 + +// Check if need companion controllers for full/low speed devices +static void +ehci_note_port(struct usb_ehci_s *cntl) +{ + if (--cntl->checkports) + // Ports still being detected. + return; + if (! cntl->legacycount) + // No full/low speed devices found. + return; + // Start companion controllers. + int i; + for (i=0; icompanion); i++) { + struct pci_device *pci = cntl->companion[i]; + if (!pci) + break; + + // ohci/uhci_setup call pci_config_X - don't run from irq handler. + wait_preempt(); + + if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI) + uhci_setup(pci, cntl->usb.busid + i); + else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI) + ohci_setup(pci, cntl->usb.busid + i); + } +} + +// Check if device attached to port +static int +ehci_hub_detect(struct usbhub_s *hub, u32 port) +{ + struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb); + u32 *portreg = &cntl->regs->portsc[port]; + u32 portsc = readl(portreg); + + // Power up port. + if (!(portsc & PORT_POWER)) { + portsc |= PORT_POWER; + writel(portreg, portsc); + msleep(EHCI_TIME_POSTPOWER); + } else { + // Port is already powered up, but we don't know how long it + // has been powered up, so wait the 20ms. + msleep(EHCI_TIME_POSTPOWER); + } + portsc = readl(portreg); + + if (!(portsc & PORT_CONNECT)) + // No device present + goto doneearly; + + if ((portsc & PORT_LINESTATUS_MASK) == PORT_LINESTATUS_KSTATE) { + // low speed device + cntl->legacycount++; + writel(portreg, portsc | PORT_OWNER); + goto doneearly; + } + + // XXX - if just powered up, need to wait for USB_TIME_ATTDB? + + // Begin reset on port + portsc = (portsc & ~PORT_PE) | PORT_RESET; + writel(portreg, portsc); + msleep(USB_TIME_DRSTR); + return 0; + +doneearly: + ehci_note_port(cntl); + return -1; +} + +// Reset device on port +static int +ehci_hub_reset(struct usbhub_s *hub, u32 port) +{ + struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb); + u32 *portreg = &cntl->regs->portsc[port]; + u32 portsc = readl(portreg); + + // Finish reset on port + portsc &= ~PORT_RESET; + writel(portreg, portsc); + msleep(EHCI_TIME_POSTRESET); + + int rv = -1; + portsc = readl(portreg); + if (!(portsc & PORT_CONNECT)) + // No longer connected + goto resetfail; + if (!(portsc & PORT_PE)) { + // full speed device + cntl->legacycount++; + writel(portreg, portsc | PORT_OWNER); + goto resetfail; + } + + rv = USB_HIGHSPEED; +resetfail: + ehci_note_port(cntl); + return rv; +} + +// Disable port +static void +ehci_hub_disconnect(struct usbhub_s *hub, u32 port) +{ + struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb); + u32 *portreg = &cntl->regs->portsc[port]; + u32 portsc = readl(portreg); + writel(portreg, portsc & ~PORT_PE); +} + +static struct usbhub_op_s ehci_HubOp = { + .detect = ehci_hub_detect, + .reset = ehci_hub_reset, + .disconnect = ehci_hub_disconnect, +}; + +// Find any devices connected to the root hub. +static int +check_ehci_ports(struct usb_ehci_s *cntl) +{ + ASSERT32FLAT(); + struct usbhub_s hub; + memset(&hub, 0, sizeof(hub)); + hub.cntl = &cntl->usb; + hub.portcount = cntl->checkports; + hub.op = &ehci_HubOp; + usb_enumerate(&hub); + return hub.devcount; +} + + +/**************************************************************** + * Setup + ****************************************************************/ + +// Wait for next USB async frame to start - for ensuring safe memory release. +static void +ehci_waittick(struct usb_ehci_s *cntl) +{ + if (MODE16) { + msleep(10); + return; + } + // Wait for access to "doorbell" + barrier(); + u32 cmd, sts; + u32 end = timer_calc(100); + for (;;) { + sts = readl(&cntl->regs->usbsts); + if (!(sts & STS_IAA)) { + cmd = readl(&cntl->regs->usbcmd); + if (!(cmd & CMD_IAAD)) + break; + } + if (timer_check(end)) { + warn_timeout(); + return; + } + yield(); + } + // Ring "doorbell" + writel(&cntl->regs->usbcmd, cmd | CMD_IAAD); + // Wait for completion + for (;;) { + sts = readl(&cntl->regs->usbsts); + if (sts & STS_IAA) + break; + if (timer_check(end)) { + warn_timeout(); + return; + } + yield(); + } + // Ack completion + writel(&cntl->regs->usbsts, STS_IAA); +} + +static void +ehci_free_pipes(struct usb_ehci_s *cntl) +{ + dprintf(7, "ehci_free_pipes %p\n", cntl); + + struct ehci_qh *start = cntl->async_qh; + struct ehci_qh *pos = start; + for (;;) { + struct ehci_qh *next = (void*)(pos->next & ~EHCI_PTR_BITS); + if (next == start) + break; + struct ehci_pipe *pipe = container_of(next, struct ehci_pipe, qh); + if (pipe->pipe.cntl != &cntl->usb) + pos->next = next->next; + else + pos = next; + } + ehci_waittick(cntl); + for (;;) { + struct usb_pipe *usbpipe = cntl->usb.freelist; + if (!usbpipe) + break; + cntl->usb.freelist = usbpipe->freenext; + struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe); + free(pipe); + } +} + +static void +configure_ehci(void *data) +{ + struct usb_ehci_s *cntl = data; + + // Allocate ram for schedule storage + struct ehci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl)); + struct ehci_qh *intr_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*intr_qh)); + struct ehci_qh *async_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*async_qh)); + if (!fl || !intr_qh || !async_qh) { + warn_noalloc(); + goto fail; + } + + // XXX - check for halted? + + // Reset the HC + u32 cmd = readl(&cntl->regs->usbcmd); + writel(&cntl->regs->usbcmd, (cmd & ~(CMD_ASE | CMD_PSE)) | CMD_HCRESET); + u32 end = timer_calc(250); + for (;;) { + cmd = readl(&cntl->regs->usbcmd); + if (!(cmd & CMD_HCRESET)) + break; + if (timer_check(end)) { + warn_timeout(); + goto fail; + } + yield(); + } + + // Disable interrupts (just to be safe). + writel(&cntl->regs->usbintr, 0); + + // Set schedule to point to primary intr queue head + memset(intr_qh, 0, sizeof(*intr_qh)); + intr_qh->next = EHCI_PTR_TERM; + intr_qh->info2 = (0x01 << QH_SMASK_SHIFT); + intr_qh->token = QTD_STS_HALT; + intr_qh->qtd_next = intr_qh->alt_next = EHCI_PTR_TERM; + int i; + for (i=0; ilinks); i++) + fl->links[i] = (u32)intr_qh | EHCI_PTR_QH; + writel(&cntl->regs->periodiclistbase, (u32)fl); + + // Set async list to point to primary async queue head + memset(async_qh, 0, sizeof(*async_qh)); + async_qh->next = (u32)async_qh | EHCI_PTR_QH; + async_qh->info1 = QH_HEAD; + async_qh->token = QTD_STS_HALT; + async_qh->qtd_next = async_qh->alt_next = EHCI_PTR_TERM; + cntl->async_qh = async_qh; + writel(&cntl->regs->asynclistbase, (u32)async_qh); + + // Enable queues + writel(&cntl->regs->usbcmd, cmd | CMD_ASE | CMD_PSE | CMD_RUN); + + // Set default of high speed for root hub. + writel(&cntl->regs->configflag, 1); + cntl->checkports = readl(&cntl->caps->hcsparams) & HCS_N_PORTS_MASK; + + // Find devices + int count = check_ehci_ports(cntl); + ehci_free_pipes(cntl); + if (count) + // Success + return; + + // No devices found - shutdown and free controller. + writel(&cntl->regs->usbcmd, cmd & ~CMD_RUN); + msleep(4); // 2ms to stop reading memory - XXX +fail: + free(fl); + free(intr_qh); + free(async_qh); + free(cntl); +} + +int +ehci_setup(struct pci_device *pci, int busid, struct pci_device *comppci) +{ + if (! CONFIG_USB_EHCI) + return -1; + + u16 bdf = pci->bdf; + u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); + struct ehci_caps *caps = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); + u32 hcc_params = readl(&caps->hccparams); + + struct usb_ehci_s *cntl = malloc_tmphigh(sizeof(*cntl)); + if (!cntl) { + warn_noalloc(); + return -1; + } + memset(cntl, 0, sizeof(*cntl)); + cntl->usb.busid = busid; + cntl->usb.pci = pci; + cntl->usb.type = USB_TYPE_EHCI; + cntl->caps = caps; + cntl->regs = (void*)caps + readb(&caps->caplength); + if (hcc_params & HCC_64BIT_ADDR) + cntl->regs->ctrldssegment = 0; + + dprintf(1, "EHCI init on dev %02x:%02x.%x (regs=%p)\n" + , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) + , pci_bdf_to_fn(bdf), cntl->regs); + + pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + + // XXX - check for and disable SMM control? + + // Find companion controllers. + int count = 0; + for (;;) { + if (!comppci || comppci == pci) + break; + if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_UHCI) + cntl->companion[count++] = comppci; + else if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_OHCI) + cntl->companion[count++] = comppci; + comppci = container_of(comppci->node.next, struct pci_device, node); + } + + run_thread(configure_ehci, cntl); + return 0; +} + + +/**************************************************************** + * End point communication + ****************************************************************/ + +// Setup fields in qh +static void +ehci_desc2pipe(struct ehci_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + + pipe->qh.info1 = ((pipe->pipe.maxpacket << QH_MAXPACKET_SHIFT) + | (pipe->pipe.speed << QH_SPEED_SHIFT) + | (pipe->pipe.ep << QH_EP_SHIFT) + | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); + + pipe->qh.info2 = (1 << QH_MULT_SHIFT); + struct usbdevice_s *hubdev = usbdev->hub->usbdev; + if (hubdev) { + struct ehci_pipe *hpipe = container_of( + hubdev->defpipe, struct ehci_pipe, pipe); + if (hpipe->pipe.speed == USB_HIGHSPEED) + pipe->qh.info2 |= ((usbdev->port << QH_HUBPORT_SHIFT) + | (hpipe->pipe.devaddr << QH_HUBADDR_SHIFT)); + else + pipe->qh.info2 = hpipe->qh.info2; + } + + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_CONTROL) + pipe->qh.info1 |= ((pipe->pipe.speed != USB_HIGHSPEED ? QH_CONTROL : 0) + | QH_TOGGLECONTROL); + else if (eptype == USB_ENDPOINT_XFER_INT) + pipe->qh.info2 |= (0x01 << QH_SMASK_SHIFT) | (0x1c << QH_CMASK_SHIFT); +} + +static struct usb_pipe * +ehci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + struct usb_ehci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_ehci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); + dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); + + if (frameexp > 10) + frameexp = 10; + int maxpacket = epdesc->wMaxPacketSize; + // Determine number of entries needed for 2 timer ticks. + int ms = 1<next_td = pipe->tds = tds; + pipe->data = data; + pipe->qh.qtd_next = (u32)tds; + + int i; + for (i=0; iqtd_next = (i==count-1 ? (u32)tds : (u32)&td[1]); + td->alt_next = EHCI_PTR_TERM; + td->token = (ehci_explen(maxpacket) | QTD_STS_ACTIVE + | QTD_PID_IN | ehci_maxerr(3)); + td->buf[0] = (u32)data + maxpacket * i; + } + + // Add to interrupt schedule. + struct ehci_framelist *fl = (void*)readl(&cntl->regs->periodiclistbase); + if (frameexp == 0) { + // Add to existing interrupt entry. + struct ehci_qh *intr_qh = (void*)(fl->links[0] & ~EHCI_PTR_BITS); + pipe->qh.next = intr_qh->next; + barrier(); + intr_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; + } else { + int startpos = 1<<(frameexp-1); + pipe->qh.next = fl->links[startpos]; + barrier(); + for (i=startpos; ilinks); i+=ms) + fl->links[i] = (u32)&pipe->qh | EHCI_PTR_QH; + } + + return &pipe->pipe; +fail: + free(pipe); + free(tds); + free(data); + return NULL; +} + +struct usb_pipe * +ehci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + if (! CONFIG_USB_EHCI) + return NULL; + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_INT) + return ehci_alloc_intr_pipe(usbdev, epdesc); + struct usb_ehci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_ehci_s, usb); + dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); + + struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); + if (usbpipe) { + // Use previously allocated pipe. + struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe); + ehci_desc2pipe(pipe, usbdev, epdesc); + return usbpipe; + } + + // Allocate a new queue head. + struct ehci_pipe *pipe; + if (eptype == USB_ENDPOINT_XFER_CONTROL) + pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe)); + else + pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); + if (!pipe) { + warn_noalloc(); + return NULL; + } + memset(pipe, 0, sizeof(*pipe)); + ehci_desc2pipe(pipe, usbdev, epdesc); + pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM; + + // Add queue head to controller list. + struct ehci_qh *async_qh = cntl->async_qh; + pipe->qh.next = async_qh->next; + barrier(); + async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; + return &pipe->pipe; +} + +static void +ehci_reset_pipe(struct ehci_pipe *pipe) +{ + SET_LOWFLAT(pipe->qh.qtd_next, EHCI_PTR_TERM); + SET_LOWFLAT(pipe->qh.alt_next, EHCI_PTR_TERM); + barrier(); + SET_LOWFLAT(pipe->qh.token, GET_LOWFLAT(pipe->qh.token) & QTD_TOGGLE); +} + +static int +ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) +{ + u32 end = timer_calc(timeout); + u32 status; + for (;;) { + status = td->token; + if (!(status & QTD_STS_ACTIVE)) + break; + if (timer_check(end)) { + u32 cur = GET_LOWFLAT(pipe->qh.current); + u32 tok = GET_LOWFLAT(pipe->qh.token); + u32 next = GET_LOWFLAT(pipe->qh.qtd_next); + warn_timeout(); + dprintf(1, "ehci pipe=%p cur=%08x tok=%08x next=%x td=%p status=%x\n" + , pipe, cur, tok, next, td, status); + ehci_reset_pipe(pipe); + struct usb_ehci_s *cntl = container_of( + GET_LOWFLAT(pipe->pipe.cntl), struct usb_ehci_s, usb); + ehci_waittick(cntl); + return -1; + } + yield(); + } + if (status & QTD_STS_HALT) { + dprintf(1, "ehci_wait_td error - status=%x\n", status); + ehci_reset_pipe(pipe); + return -2; + } + return 0; +} + +static int +fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes) +{ + u32 dest = (u32)buf; + u32 *pos = td->buf; + while (bytes) { + if (pos >= &td->buf[ARRAY_SIZE(td->buf)]) + // More data than can transfer in a single qtd - only use + // full packets to prevent a babble error. + return ALIGN_DOWN(dest - (u32)buf, maxpacket); + u32 count = bytes; + u32 max = 0x1000 - (dest & 0xfff); + if (count > max) + count = max; + *pos = dest; + bytes -= count; + dest += count; + pos++; + } + return dest - (u32)buf; +} + +int +ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datasize) +{ + ASSERT32FLAT(); + if (! CONFIG_USB_EHCI) + return -1; + dprintf(5, "ehci_control %p (dir=%d cmd=%d data=%d)\n" + , p, dir, cmdsize, datasize); + if (datasize > 4*4096 || cmdsize > 4*4096) { + // XXX - should support larger sizes. + warn_noalloc(); + return -1; + } + struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); + + // Setup transfer descriptors + struct ehci_qtd *tds = memalign_tmphigh(EHCI_QTD_ALIGN, sizeof(*tds) * 3); + if (!tds) { + warn_noalloc(); + return -1; + } + memset(tds, 0, sizeof(*tds) * 3); + struct ehci_qtd *td = tds; + + td->qtd_next = (u32)&td[1]; + td->alt_next = EHCI_PTR_TERM; + td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE + | QTD_PID_SETUP | ehci_maxerr(3)); + u16 maxpacket = pipe->pipe.maxpacket; + fillTDbuffer(td, maxpacket, cmd, cmdsize); + td++; + + if (datasize) { + td->qtd_next = (u32)&td[1]; + td->alt_next = EHCI_PTR_TERM; + td->token = (QTD_TOGGLE | ehci_explen(datasize) | QTD_STS_ACTIVE + | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3)); + fillTDbuffer(td, maxpacket, data, datasize); + td++; + } + + td->qtd_next = EHCI_PTR_TERM; + td->alt_next = EHCI_PTR_TERM; + td->token = (QTD_TOGGLE | QTD_STS_ACTIVE + | (dir ? QTD_PID_OUT : QTD_PID_IN) | ehci_maxerr(3)); + + // Transfer data + barrier(); + pipe->qh.qtd_next = (u32)tds; + int i, ret=0; + for (i=0; i<3; i++) { + struct ehci_qtd *td = &tds[i]; + ret = ehci_wait_td(pipe, td, 500); + if (ret) + break; + } + free(tds); + return ret; +} + +#define STACKQTDS 4 + +int +ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) +{ + if (! CONFIG_USB_EHCI) + return -1; + struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); + dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n" + , &pipe->qh, dir, data, datasize); + + // Allocate 4 tds on stack (with required alignment) + u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1]; + struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN); + memset(tds, 0, sizeof(*tds) * STACKQTDS); + barrier(); + SET_LOWFLAT(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds)); + + u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); + int tdpos = 0; + while (datasize) { + struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; + int ret = ehci_wait_td(pipe, td, 5000); + if (ret) + return -1; + + struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS) + , &tds[tdpos % STACKQTDS]); + + int transfer = fillTDbuffer(td, maxpacket, data, datasize); + td->qtd_next = (transfer==datasize ? EHCI_PTR_TERM : (u32)nexttd_fl); + td->alt_next = EHCI_PTR_TERM; + barrier(); + td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE + | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3)); + + data += transfer; + datasize -= transfer; + } + int i; + for (i=0; inext_td); + u32 token = GET_LOWFLAT(td->token); + if (token & QTD_STS_ACTIVE) + // No intrs found. + return -1; + // XXX - check for errors. + + // Copy data. + int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); + int pos = td - GET_LOWFLAT(pipe->tds); + void *tddata = GET_LOWFLAT(pipe->data) + maxpacket * pos; + memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata), maxpacket); + + // Reenable this td. + struct ehci_qtd *next = (void*)(GET_LOWFLAT(td->qtd_next) & ~EHCI_PTR_BITS); + SET_LOWFLAT(pipe->next_td, next); + SET_LOWFLAT(td->buf[0], (u32)tddata); + barrier(); + SET_LOWFLAT(td->token, (ehci_explen(maxpacket) | QTD_STS_ACTIVE + | QTD_PID_IN | ehci_maxerr(3))); + + return 0; +} diff -Nru seabios-1.7.1/src/hw/usb-ehci.h seabios-1.7.4/src/hw/usb-ehci.h --- seabios-1.7.1/src/hw/usb-ehci.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-ehci.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,176 @@ +#ifndef __USB_EHCI_H +#define __USB_EHCI_H + +// usb-ehci.c +int ehci_setup(struct pci_device *pci, int busid, struct pci_device *comppci); +struct usbdevice_s; +struct usb_endpoint_descriptor; +struct usb_pipe *ehci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe; +int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datasize); +int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); +int ehci_poll_intr(struct usb_pipe *p, void *data); + + +/**************************************************************** + * ehci structs and flags + ****************************************************************/ + +struct ehci_caps { + u8 caplength; + u8 reserved_01; + u16 hciversion; + u32 hcsparams; + u32 hccparams; + u64 portroute; +} PACKED; + +#define HCC_64BIT_ADDR 1 + +#define HCS_N_PORTS_MASK 0xf + +struct ehci_regs { + u32 usbcmd; + u32 usbsts; + u32 usbintr; + u32 frindex; + u32 ctrldssegment; + u32 periodiclistbase; + u32 asynclistbase; + u32 reserved[9]; + u32 configflag; + u32 portsc[0]; +} PACKED; + +#define CMD_PARK (1<<11) +#define CMD_PARK_CNT(c) (((c)>>8)&3) +#define CMD_LRESET (1<<7) +#define CMD_IAAD (1<<6) +#define CMD_ASE (1<<5) +#define CMD_PSE (1<<4) +#define CMD_HCRESET (1<<1) +#define CMD_RUN (1<<0) + +#define STS_ASS (1<<15) +#define STS_PSS (1<<14) +#define STS_RECL (1<<13) +#define STS_HALT (1<<12) +#define STS_IAA (1<<5) +#define STS_FATAL (1<<4) +#define STS_FLR (1<<3) +#define STS_PCD (1<<2) +#define STS_ERR (1<<1) +#define STS_INT (1<<0) + +#define FLAG_CF (1<<0) + +#define PORT_WKOC_E (1<<22) +#define PORT_WKDISC_E (1<<21) +#define PORT_WKCONN_E (1<<20) +#define PORT_TEST_PKT (0x4<<16) +#define PORT_LED_OFF (0<<14) +#define PORT_LED_AMBER (1<<14) +#define PORT_LED_GREEN (2<<14) +#define PORT_LED_MASK (3<<14) +#define PORT_OWNER (1<<13) +#define PORT_POWER (1<<12) +#define PORT_LINESTATUS_MASK (3<<10) +#define PORT_LINESTATUS_KSTATE (1<<10) +#define PORT_RESET (1<<8) +#define PORT_SUSPEND (1<<7) +#define PORT_RESUME (1<<6) +#define PORT_OCC (1<<5) +#define PORT_OC (1<<4) +#define PORT_PEC (1<<3) +#define PORT_PE (1<<2) +#define PORT_CSC (1<<1) +#define PORT_CONNECT (1<<0) +#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) + + +#define EHCI_QH_ALIGN 128 // Can't span a 4K boundary, so increase from 32 + +struct ehci_qh { + u32 next; + u32 info1; + u32 info2; + u32 current; + + u32 qtd_next; + u32 alt_next; + u32 token; + u32 buf[5]; + u32 buf_hi[5]; +} PACKED; + +#define QH_CONTROL (1 << 27) +#define QH_MAXPACKET_SHIFT 16 +#define QH_MAXPACKET_MASK (0x7ff << QH_MAXPACKET_SHIFT) +#define QH_HEAD (1 << 15) +#define QH_TOGGLECONTROL (1 << 14) +#define QH_SPEED_SHIFT 12 +#define QH_SPEED_MASK (0x3 << QH_SPEED_SHIFT) +#define QH_EP_SHIFT 8 +#define QH_EP_MASK (0xf << QH_EP_SHIFT) +#define QH_DEVADDR_SHIFT 0 +#define QH_DEVADDR_MASK (0x7f << QH_DEVADDR_SHIFT) + +#define QH_SMASK_SHIFT 0 +#define QH_SMASK_MASK (0xff << QH_SMASK_SHIFT) +#define QH_CMASK_SHIFT 8 +#define QH_CMASK_MASK (0xff << QH_CMASK_SHIFT) +#define QH_HUBADDR_SHIFT 16 +#define QH_HUBADDR_MASK (0x7f << QH_HUBADDR_SHIFT) +#define QH_HUBPORT_SHIFT 23 +#define QH_HUBPORT_MASK (0x7f << QH_HUBPORT_SHIFT) +#define QH_MULT_SHIFT 30 +#define QH_MULT_MASK (0x3 << QH_MULT_SHIFT) + +#define EHCI_PTR_BITS 0x001F +#define EHCI_PTR_TERM 0x0001 +#define EHCI_PTR_QH 0x0002 + + +#define EHCI_QTD_ALIGN 64 // Can't span a 4K boundary, so increase from 32 + +struct ehci_qtd { + u32 qtd_next; + u32 alt_next; + u32 token; + u32 buf[5]; + u32 buf_hi[5]; + /* keep struct size a multiple of 64 bytes, as we're allocating + arrays. Without this padding, the second qtd could have the + wrong alignment. */ +} PACKED __aligned(EHCI_QTD_ALIGN); + +#define QTD_TOGGLE (1 << 31) +#define QTD_LENGTH_SHIFT 16 +#define QTD_LENGTH_MASK (0x7fff << QTD_LENGTH_SHIFT) +#define QTD_CERR_SHIFT 10 +#define QTD_CERR_MASK (0x3 << QTD_CERR_SHIFT) +#define QTD_IOC (1 << 15) +#define QTD_PID_OUT (0x0 << 8) +#define QTD_PID_IN (0x1 << 8) +#define QTD_PID_SETUP (0x2 << 8) +#define QTD_STS_ACTIVE (1 << 7) +#define QTD_STS_HALT (1 << 6) +#define QTD_STS_DBE (1 << 5) +#define QTD_STS_BABBLE (1 << 4) +#define QTD_STS_XACT (1 << 3) +#define QTD_STS_MMF (1 << 2) +#define QTD_STS_STS (1 << 1) +#define QTD_STS_PING (1 << 0) + +#define ehci_explen(len) (((len) << QTD_LENGTH_SHIFT) & QTD_LENGTH_MASK) + +#define ehci_maxerr(err) (((err) << QTD_CERR_SHIFT) & QTD_CERR_MASK) + + +struct ehci_framelist { + u32 links[1024]; +} PACKED; + +#endif // usb-ehci.h diff -Nru seabios-1.7.1/src/hw/usb.h seabios-1.7.4/src/hw/usb.h --- seabios-1.7.1/src/hw/usb.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,244 @@ +// USB functions and data. +#ifndef __USB_H +#define __USB_H + +#include "stacks.h" // struct mutex_s + +// Information on a USB end point. +struct usb_pipe { + union { + struct usb_s *cntl; + struct usb_pipe *freenext; + }; + u8 type; + u8 ep; + u8 devaddr; + u8 speed; + u16 maxpacket; + u8 eptype; +}; + +// Common information for usb devices. +struct usbdevice_s { + struct usbhub_s *hub; + struct usb_pipe *defpipe; + u32 port; + struct usb_config_descriptor *config; + struct usb_interface_descriptor *iface; + int imax; + u8 speed; + u8 devaddr; +}; + +// Common information for usb controllers. +struct usb_s { + struct usb_pipe *freelist; + struct mutex_s resetlock; + struct pci_device *pci; + int busid; + u8 type; + u8 maxaddr; +}; + +// Information for enumerating USB hubs +struct usbhub_s { + struct usbhub_op_s *op; + struct usbdevice_s *usbdev; + struct usb_s *cntl; + struct mutex_s lock; + u32 powerwait; + u32 port; + u32 threads; + u32 portcount; + u32 devcount; +}; + +// Hub callback (32bit) info +struct usbhub_op_s { + int (*detect)(struct usbhub_s *hub, u32 port); + int (*reset)(struct usbhub_s *hub, u32 port); + void (*disconnect)(struct usbhub_s *hub, u32 port); +}; + +#define USB_TYPE_UHCI 1 +#define USB_TYPE_OHCI 2 +#define USB_TYPE_EHCI 3 +#define USB_TYPE_XHCI 4 + +#define USB_FULLSPEED 0 +#define USB_LOWSPEED 1 +#define USB_HIGHSPEED 2 +#define USB_SUPERSPEED 3 + +#define USB_MAXADDR 127 + + +/**************************************************************** + * usb structs and flags + ****************************************************************/ + +// USB mandated timings (in ms) +#define USB_TIME_SIGATT 100 +#define USB_TIME_ATTDB 100 +#define USB_TIME_DRST 10 +#define USB_TIME_DRSTR 50 +#define USB_TIME_RSTRCY 10 + +#define USB_TIME_SETADDR_RECOVERY 2 + +#define USB_PID_OUT 0xe1 +#define USB_PID_IN 0x69 +#define USB_PID_SETUP 0x2d + +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +struct usb_ctrlrequest { + u8 bRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; +} PACKED; + +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_DT_ENDPOINT_COMPANION 0x30 + +struct usb_device_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 bcdUSB; + u8 bDeviceClass; + u8 bDeviceSubClass; + u8 bDeviceProtocol; + u8 bMaxPacketSize0; + u16 idVendor; + u16 idProduct; + u16 bcdDevice; + u8 iManufacturer; + u8 iProduct; + u8 iSerialNumber; + u8 bNumConfigurations; +} PACKED; + +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 + +struct usb_config_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 wTotalLength; + u8 bNumInterfaces; + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u8 bMaxPower; +} PACKED; + +struct usb_interface_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bInterfaceNumber; + u8 bAlternateSetting; + u8 bNumEndpoints; + u8 bInterfaceClass; + u8 bInterfaceSubClass; + u8 bInterfaceProtocol; + u8 iInterface; +} PACKED; + +struct usb_endpoint_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bEndpointAddress; + u8 bmAttributes; + u16 wMaxPacketSize; + u8 bInterval; +} PACKED; + +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 +#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 + + +/**************************************************************** + * usb mass storage flags + ****************************************************************/ + +#define US_SC_ATAPI_8020 0x02 +#define US_SC_ATAPI_8070 0x05 +#define US_SC_SCSI 0x06 + +#define US_PR_BULK 0x50 /* bulk-only transport */ +#define US_PR_UAS 0x62 /* usb attached scsi */ + +/**************************************************************** + * function defs + ****************************************************************/ + +// usb.c +struct usb_pipe *usb_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize); +int usb_poll_intr(struct usb_pipe *pipe, void *data); +int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req + , void *data); +void free_pipe(struct usb_pipe *pipe); +struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype); +void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +int usb_getFrameExp(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev + , int type, int dir); +void usb_enumerate(struct usbhub_s *hub); +void usb_setup(void); + +#endif // usb.h diff -Nru seabios-1.7.1/src/hw/usb-hid.c seabios-1.7.4/src/hw/usb-hid.c --- seabios-1.7.1/src/hw/usb-hid.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-hid.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,432 @@ +// Code for handling USB Human Interface Devices (HID). +// +// Copyright (C) 2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBAL +#include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "ps2port.h" // ATKBD_CMD_GETID +#include "usb.h" // usb_ctrlrequest +#include "usb-hid.h" // usb_keyboard_setup +#include "util.h" // process_key + +struct usb_pipe *keyboard_pipe VARFSEG; +struct usb_pipe *mouse_pipe VARFSEG; + + +/**************************************************************** + * Setup + ****************************************************************/ + +// Send USB HID protocol message. +static int +set_protocol(struct usb_pipe *pipe, u16 val) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + req.bRequest = HID_REQ_SET_PROTOCOL; + req.wValue = val; + req.wIndex = 0; + req.wLength = 0; + return send_default_control(pipe, &req, NULL); +} + +// Send USB HID SetIdle request. +static int +set_idle(struct usb_pipe *pipe, int ms) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + req.bRequest = HID_REQ_SET_IDLE; + req.wValue = (ms/4)<<8; + req.wIndex = 0; + req.wLength = 0; + return send_default_control(pipe, &req, NULL); +} + +#define KEYREPEATWAITMS 500 +#define KEYREPEATMS 33 + +static int +usb_kbd_setup(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + if (! CONFIG_USB_KEYBOARD) + return -1; + if (keyboard_pipe) + // XXX - this enables the first found keyboard (could be random) + return -1; + + if (epdesc->wMaxPacketSize != 8) + return -1; + + // Enable "boot" protocol. + int ret = set_protocol(usbdev->defpipe, 0); + if (ret) + return -1; + // Periodically send reports to enable key repeat. + ret = set_idle(usbdev->defpipe, KEYREPEATMS); + if (ret) + return -1; + + keyboard_pipe = usb_alloc_pipe(usbdev, epdesc); + if (!keyboard_pipe) + return -1; + + dprintf(1, "USB keyboard initialized\n"); + return 0; +} + +static int +usb_mouse_setup(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + if (! CONFIG_USB_MOUSE) + return -1; + if (mouse_pipe) + // XXX - this enables the first found mouse (could be random) + return -1; + + if (epdesc->wMaxPacketSize < 3 || epdesc->wMaxPacketSize > 8) + return -1; + + // Enable "boot" protocol. + int ret = set_protocol(usbdev->defpipe, 0); + if (ret) + return -1; + + mouse_pipe = usb_alloc_pipe(usbdev, epdesc); + if (!mouse_pipe) + return -1; + + dprintf(1, "USB mouse initialized\n"); + return 0; +} + +// Initialize a found USB HID device (if applicable). +int +usb_hid_setup(struct usbdevice_s *usbdev) +{ + if (! CONFIG_USB_KEYBOARD || ! CONFIG_USB_MOUSE) + return -1; + dprintf(2, "usb_hid_setup %p\n", usbdev->defpipe); + + struct usb_interface_descriptor *iface = usbdev->iface; + if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT) + // Doesn't support boot protocol. + return -1; + + // Find intr in endpoint. + struct usb_endpoint_descriptor *epdesc = findEndPointDesc( + usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN); + if (!epdesc) { + dprintf(1, "No usb hid intr in?\n"); + return -1; + } + + if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD) + return usb_kbd_setup(usbdev, epdesc); + if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) + return usb_mouse_setup(usbdev, epdesc); + return -1; +} + + +/**************************************************************** + * Keyboard events + ****************************************************************/ + +// Mapping from USB key id to ps2 key sequence. +static u16 KeyToScanCode[] VAR16 = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020, + 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, + 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, + 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, + 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a, + 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034, + 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046, + 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d, + 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e, + 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047, + 0x0048, 0x0049, 0x0052, 0x0053 +}; + +// Mapping from USB modifier id to ps2 key sequence. +static u16 ModifierToScanCode[] VAR16 = { + //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui + 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c +}; + +#define RELEASEBIT 0x80 + +// Format of USB keyboard event data +struct keyevent { + u8 modifiers; + u8 reserved; + u8 keys[6]; +}; + +// Translate data from KeyToScanCode[] to calls to process_key(). +static void +prockeys(u16 keys) +{ + if (keys > 0xff) { + u8 key = keys>>8; + if (key == 0xe1) { + // Pause key + process_key(0xe1); + process_key(0x1d | (keys & RELEASEBIT)); + process_key(0x45 | (keys & RELEASEBIT)); + return; + } + process_key(key); + } + process_key(keys); +} + +// Handle a USB key press/release event. +static void +procscankey(u8 key, u8 flags) +{ + if (key >= ARRAY_SIZE(KeyToScanCode)) + return; + u16 keys = GET_GLOBAL(KeyToScanCode[key]); + if (keys) + prockeys(keys | flags); +} + +// Handle a USB modifier press/release event. +static void +procmodkey(u8 mods, u8 flags) +{ + int i; + for (i=0; mods; i++) + if (mods & (1<modifiers, data->keys[0]); + + // Load old keys. + struct usbkeyinfo old; + old.data = GET_LOW(LastUSBkey.data); + + // Check for keys no longer pressed. + int addpos = 0; + int i; + for (i=0; i=ARRAY_SIZE(data->keys)) { + // Key released. + procscankey(key, RELEASEBIT); + if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1]) + // Last pressed key released - disable repeat. + old.repeatcount = 0xff; + break; + } + if (data->keys[j] == key) { + // Key still pressed. + data->keys[j] = 0; + old.keys[addpos++] = key; + break; + } + } + } + procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT); + + // Process new keys + procmodkey(data->modifiers & ~old.modifiers, 0); + old.modifiers = data->modifiers; + for (i=0; ikeys); i++) { + u8 key = data->keys[i]; + if (!key) + continue; + // New key pressed. + procscankey(key, 0); + old.keys[addpos++] = key; + old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1; + } + if (addpos < ARRAY_SIZE(old.keys)) + old.keys[addpos] = 0; + + // Check for key repeat event. + if (addpos) { + if (!old.repeatcount) + procscankey(old.keys[addpos-1], 0); + else if (old.repeatcount != 0xff) + old.repeatcount--; + } + + // Update old keys + SET_LOW(LastUSBkey.data, old.data); +} + +// Check if a USB keyboard event is pending and process it if so. +static void +usb_check_key(void) +{ + if (! CONFIG_USB_KEYBOARD) + return; + struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe); + if (!pipe) + return; + + for (;;) { + struct keyevent data; + int ret = usb_poll_intr(pipe, &data); + if (ret) + break; + handle_key(&data); + } +} + +// Test if USB keyboard is active. +inline int +usb_kbd_active(void) +{ + if (! CONFIG_USB_KEYBOARD) + return 0; + return GET_GLOBAL(keyboard_pipe) != NULL; +} + +// Handle a ps2 style keyboard command. +inline int +usb_kbd_command(int command, u8 *param) +{ + if (! CONFIG_USB_KEYBOARD) + return -1; + dprintf(9, "usb keyboard cmd=%x\n", command); + switch (command) { + case ATKBD_CMD_GETID: + // Return the id of a standard AT keyboard. + param[0] = 0xab; + param[1] = 0x83; + return 0; + default: + return -1; + } +} + + +/**************************************************************** + * Mouse events + ****************************************************************/ + +// Format of USB mouse event data +struct mouseevent { + u8 buttons; + u8 x, y; + u8 reserved[5]; +}; + +// Process USB mouse data. +static void +handle_mouse(struct mouseevent *data) +{ + dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y); + + s8 x = data->x, y = -data->y; + u8 flag = ((data->buttons & 0x7) | (1<<3) + | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0)); + process_mouse(flag); + process_mouse(x); + process_mouse(y); +} + +// Check if a USB mouse event is pending and process it if so. +static void +usb_check_mouse(void) +{ + if (! CONFIG_USB_MOUSE) + return; + struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe); + if (!pipe) + return; + + for (;;) { + struct mouseevent data; + int ret = usb_poll_intr(pipe, &data); + if (ret) + break; + handle_mouse(&data); + } +} + +// Test if USB mouse is active. +inline int +usb_mouse_active(void) +{ + if (! CONFIG_USB_MOUSE) + return 0; + return GET_GLOBAL(mouse_pipe) != NULL; +} + +// Handle a ps2 style mouse command. +inline int +usb_mouse_command(int command, u8 *param) +{ + if (! CONFIG_USB_MOUSE) + return -1; + dprintf(9, "usb mouse cmd=%x\n", command); + switch (command) { + case PSMOUSE_CMD_ENABLE: + case PSMOUSE_CMD_DISABLE: + case PSMOUSE_CMD_SETSCALE11: + return 0; + case PSMOUSE_CMD_SETSCALE21: + case PSMOUSE_CMD_SETRATE: + case PSMOUSE_CMD_SETRES: + // XXX + return 0; + case PSMOUSE_CMD_RESET_BAT: + case PSMOUSE_CMD_GETID: + // Return the id of a standard AT mouse. + param[0] = 0xaa; + param[1] = 0x00; + return 0; + + case PSMOUSE_CMD_GETINFO: + param[0] = 0x00; + param[1] = 4; + param[2] = 100; + return 0; + + default: + return -1; + } +} + +// Check for USB events pending - called periodically from timer interrupt. +void +usb_check_event(void) +{ + usb_check_key(); + usb_check_mouse(); +} diff -Nru seabios-1.7.1/src/hw/usb-hid.h seabios-1.7.4/src/hw/usb-hid.h --- seabios-1.7.1/src/hw/usb-hid.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-hid.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,29 @@ +#ifndef __USB_HID_H +#define __USB_HID_H + +// usb-hid.c +struct usbdevice_s; +int usb_hid_setup(struct usbdevice_s *usbdev); +inline int usb_kbd_active(void); +inline int usb_kbd_command(int command, u8 *param); +inline int usb_mouse_active(void); +inline int usb_mouse_command(int command, u8 *param); +void usb_check_event(void); + + +/**************************************************************** + * hid flags + ****************************************************************/ + +#define USB_INTERFACE_SUBCLASS_BOOT 1 +#define USB_INTERFACE_PROTOCOL_KEYBOARD 1 +#define USB_INTERFACE_PROTOCOL_MOUSE 2 + +#define HID_REQ_GET_REPORT 0x01 +#define HID_REQ_GET_IDLE 0x02 +#define HID_REQ_GET_PROTOCOL 0x03 +#define HID_REQ_SET_REPORT 0x09 +#define HID_REQ_SET_IDLE 0x0A +#define HID_REQ_SET_PROTOCOL 0x0B + +#endif // ush-hid.h diff -Nru seabios-1.7.1/src/hw/usb-hub.c seabios-1.7.4/src/hw/usb-hub.c --- seabios-1.7.1/src/hw/usb-hub.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-hub.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,187 @@ +// Code for handling standard USB hubs. +// +// Copyright (C) 2010 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_USB_HUB +#include "output.h" // dprintf +#include "string.h" // memset +#include "usb.h" // struct usb_s +#include "usb-hub.h" // struct usb_hub_descriptor +#include "util.h" // timer_calc + +static int +get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE; + req.bRequest = USB_REQ_GET_DESCRIPTOR; + req.wValue = USB_DT_HUB<<8; + req.wIndex = 0; + req.wLength = sizeof(*desc); + return send_default_control(pipe, &req, desc); +} + +static int +set_port_feature(struct usbhub_s *hub, int port, int feature) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER; + req.bRequest = USB_REQ_SET_FEATURE; + req.wValue = feature; + req.wIndex = port + 1; + req.wLength = 0; + mutex_lock(&hub->lock); + int ret = send_default_control(hub->usbdev->defpipe, &req, NULL); + mutex_unlock(&hub->lock); + return ret; +} + +static int +clear_port_feature(struct usbhub_s *hub, int port, int feature) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER; + req.bRequest = USB_REQ_CLEAR_FEATURE; + req.wValue = feature; + req.wIndex = port + 1; + req.wLength = 0; + mutex_lock(&hub->lock); + int ret = send_default_control(hub->usbdev->defpipe, &req, NULL); + mutex_unlock(&hub->lock); + return ret; +} + +static int +get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER; + req.bRequest = USB_REQ_GET_STATUS; + req.wValue = 0; + req.wIndex = port + 1; + req.wLength = sizeof(*sts); + mutex_lock(&hub->lock); + int ret = send_default_control(hub->usbdev->defpipe, &req, sts); + mutex_unlock(&hub->lock); + return ret; +} + +// Check if device attached to port +static int +usb_hub_detect(struct usbhub_s *hub, u32 port) +{ + // Turn on power to port. + int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER); + if (ret) + goto fail; + + // Wait for port power to stabilize. + msleep(hub->powerwait); + + // Check periodically for a device connect. + struct usb_port_status sts; + u32 end = timer_calc(USB_TIME_SIGATT); + for (;;) { + ret = get_port_status(hub, port, &sts); + if (ret) + goto fail; + if (sts.wPortStatus & USB_PORT_STAT_CONNECTION) + // Device connected. + break; + if (timer_check(end)) + // No device found. + return -1; + msleep(5); + } + + // XXX - wait USB_TIME_ATTDB time? + + return 0; + +fail: + dprintf(1, "Failure on hub port %d detect\n", port); + return -1; +} + +// Disable port +static void +usb_hub_disconnect(struct usbhub_s *hub, u32 port) +{ + int ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE); + if (ret) + dprintf(1, "Failure on hub port %d disconnect\n", port); +} + +// Reset device on port +static int +usb_hub_reset(struct usbhub_s *hub, u32 port) +{ + int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET); + if (ret) + goto fail; + + // Wait for reset to complete. + struct usb_port_status sts; + u32 end = timer_calc(USB_TIME_DRST * 2); + for (;;) { + ret = get_port_status(hub, port, &sts); + if (ret) + goto fail; + if (!(sts.wPortStatus & USB_PORT_STAT_RESET)) + break; + if (timer_check(end)) { + warn_timeout(); + goto fail; + } + msleep(5); + } + + // Reset complete. + if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION)) + // Device no longer present + return -1; + + return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK) + >> USB_PORT_STAT_SPEED_SHIFT); + +fail: + dprintf(1, "Failure on hub port %d reset\n", port); + usb_hub_disconnect(hub, port); + return -1; +} + +static struct usbhub_op_s HubOp = { + .detect = usb_hub_detect, + .reset = usb_hub_reset, + .disconnect = usb_hub_disconnect, +}; + +// Configure a usb hub and then find devices connected to it. +int +usb_hub_setup(struct usbdevice_s *usbdev) +{ + ASSERT32FLAT(); + if (!CONFIG_USB_HUB) + return -1; + + struct usb_hub_descriptor desc; + int ret = get_hub_desc(usbdev->defpipe, &desc); + if (ret) + return ret; + + struct usbhub_s hub; + memset(&hub, 0, sizeof(hub)); + hub.usbdev = usbdev; + hub.cntl = usbdev->defpipe->cntl; + hub.powerwait = desc.bPwrOn2PwrGood * 2; + hub.portcount = desc.bNbrPorts; + hub.op = &HubOp; + usb_enumerate(&hub); + + dprintf(1, "Initialized USB HUB (%d ports used)\n", hub.devcount); + if (hub.devcount) + return 0; + return -1; +} diff -Nru seabios-1.7.1/src/hw/usb-hub.h seabios-1.7.4/src/hw/usb-hub.h --- seabios-1.7.1/src/hw/usb-hub.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-hub.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,60 @@ +#ifndef __USB_HUB_H +#define __USB_HUB_H + +// usb-hub.c +struct usbdevice_s; +int usb_hub_setup(struct usbdevice_s *usbdev); + + +/**************************************************************** + * hub flags + ****************************************************************/ + +#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) + +struct usb_hub_descriptor { + u8 bDescLength; + u8 bDescriptorType; + u8 bNbrPorts; + u16 wHubCharacteristics; + u8 bPwrOn2PwrGood; + u8 bHubContrCurrent; + // Variable length fields for DeviceRemovable[], PortPwrCtrlMask[] follow. +} PACKED; + +#define USB_PORT_FEAT_CONNECTION 0 +#define USB_PORT_FEAT_ENABLE 1 +#define USB_PORT_FEAT_SUSPEND 2 +#define USB_PORT_FEAT_OVER_CURRENT 3 +#define USB_PORT_FEAT_RESET 4 +#define USB_PORT_FEAT_POWER 8 +#define USB_PORT_FEAT_LOWSPEED 9 +#define USB_PORT_FEAT_C_CONNECTION 16 +#define USB_PORT_FEAT_C_ENABLE 17 +#define USB_PORT_FEAT_C_SUSPEND 18 +#define USB_PORT_FEAT_C_OVER_CURRENT 19 +#define USB_PORT_FEAT_C_RESET 20 +#define USB_PORT_FEAT_TEST 21 +#define USB_PORT_FEAT_INDICATOR 22 +#define USB_PORT_FEAT_C_PORT_L1 23 + +struct usb_port_status { + u16 wPortStatus; + u16 wPortChange; +} PACKED; + +#define USB_PORT_STAT_CONNECTION 0x0001 +#define USB_PORT_STAT_ENABLE 0x0002 +#define USB_PORT_STAT_SUSPEND 0x0004 +#define USB_PORT_STAT_OVERCURRENT 0x0008 +#define USB_PORT_STAT_RESET 0x0010 +#define USB_PORT_STAT_L1 0x0020 +#define USB_PORT_STAT_POWER 0x0100 +#define USB_PORT_STAT_SPEED_SHIFT 9 +#define USB_PORT_STAT_SPEED_MASK (0x3 << USB_PORT_STAT_SPEED_SHIFT) +#define USB_PORT_STAT_LOW_SPEED 0x0200 +#define USB_PORT_STAT_HIGH_SPEED 0x0400 +#define USB_PORT_STAT_TEST 0x0800 +#define USB_PORT_STAT_INDICATOR 0x1000 + +#endif // ush-hid.h diff -Nru seabios-1.7.1/src/hw/usb-msc.c seabios-1.7.4/src/hw/usb-msc.c --- seabios-1.7.1/src/hw/usb-msc.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-msc.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,218 @@ +// Code for handling USB Mass Storage Controller devices. +// +// Copyright (C) 2010 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // DTYPE_USB +#include "blockcmd.h" // cdb_read +#include "config.h" // CONFIG_USB_MSC +#include "malloc.h" // free +#include "output.h" // dprintf +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "usb.h" // struct usb_s +#include "usb-msc.h" // usb_msc_setup +#include "util.h" // bootprio_find_usb + +struct usbdrive_s { + struct drive_s drive; + struct usb_pipe *bulkin, *bulkout; + int lun; +}; + + +/**************************************************************** + * Bulk-only drive command processing + ****************************************************************/ + +#define USB_CDB_SIZE 12 + +#define CBW_SIGNATURE 0x43425355 // USBC + +struct cbw_s { + u32 dCBWSignature; + u32 dCBWTag; + u32 dCBWDataTransferLength; + u8 bmCBWFlags; + u8 bCBWLUN; + u8 bCBWCBLength; + u8 CBWCB[16]; +} PACKED; + +#define CSW_SIGNATURE 0x53425355 // USBS + +struct csw_s { + u32 dCSWSignature; + u32 dCSWTag; + u32 dCSWDataResidue; + u8 bCSWStatus; +} PACKED; + +static int +usb_msc_send(struct usbdrive_s *udrive_gf, int dir, void *buf, u32 bytes) +{ + struct usb_pipe *pipe; + if (dir == USB_DIR_OUT) + pipe = GET_GLOBALFLAT(udrive_gf->bulkout); + else + pipe = GET_GLOBALFLAT(udrive_gf->bulkin); + return usb_send_bulk(pipe, dir, buf, bytes); +} + +// Low-level usb command transmit function. +int +usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + if (!CONFIG_USB_MSC) + return 0; + + dprintf(16, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n" + , op->drive_gf, 0, op->count, blocksize, op->buf_fl); + struct usbdrive_s *udrive_gf = container_of( + op->drive_gf, struct usbdrive_s, drive); + + // Setup command block wrapper. + u32 bytes = blocksize * op->count; + struct cbw_s cbw; + memset(&cbw, 0, sizeof(cbw)); + memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE); + cbw.dCBWSignature = CBW_SIGNATURE; + cbw.dCBWTag = 999; // XXX + cbw.dCBWDataTransferLength = bytes; + cbw.bmCBWFlags = cdb_is_read(cdbcmd, blocksize) ? USB_DIR_IN : USB_DIR_OUT; + cbw.bCBWLUN = GET_GLOBALFLAT(udrive_gf->lun); + cbw.bCBWCBLength = USB_CDB_SIZE; + + // Transfer cbw to device. + int ret = usb_msc_send(udrive_gf, USB_DIR_OUT + , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw)); + if (ret) + goto fail; + + // Transfer data to/from device. + if (bytes) { + ret = usb_msc_send(udrive_gf, cbw.bmCBWFlags, op->buf_fl, bytes); + if (ret) + goto fail; + } + + // Transfer csw info. + struct csw_s csw; + ret = usb_msc_send(udrive_gf, USB_DIR_IN + , MAKE_FLATPTR(GET_SEG(SS), &csw), sizeof(csw)); + if (ret) + goto fail; + + if (!csw.bCSWStatus) + return DISK_RET_SUCCESS; + if (csw.bCSWStatus == 2) + goto fail; + + if (blocksize) + op->count -= csw.dCSWDataResidue / blocksize; + return DISK_RET_EBADTRACK; + +fail: + // XXX - reset connection + dprintf(1, "USB transmission failed\n"); + op->count = 0; + return DISK_RET_EBADTRACK; +} + +static int +usb_msc_maxlun(struct usb_pipe *pipe) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + req.bRequest = 0xfe; + req.wValue = 0; + req.wIndex = 0; + req.wLength = 1; + unsigned char maxlun; + int ret = send_default_control(pipe, &req, &maxlun); + if (ret) + return 0; + return maxlun; +} + +static int +usb_msc_lun_setup(struct usb_pipe *inpipe, struct usb_pipe *outpipe, + struct usbdevice_s *usbdev, int lun) +{ + // Allocate drive structure. + struct usbdrive_s *drive = malloc_fseg(sizeof(*drive)); + if (!drive) { + warn_noalloc(); + return -1; + } + memset(drive, 0, sizeof(*drive)); + drive->drive.type = DTYPE_USB; + drive->bulkin = inpipe; + drive->bulkout = outpipe; + drive->lun = lun; + + int prio = bootprio_find_usb(usbdev, lun); + int ret = scsi_drive_setup(&drive->drive, "USB MSC", prio); + if (ret) { + dprintf(1, "Unable to configure USB MSC drive.\n"); + free(drive); + return -1; + } + return 0; +} + +/**************************************************************** + * Setup + ****************************************************************/ + +// Configure a usb msc device. +int +usb_msc_setup(struct usbdevice_s *usbdev) +{ + if (!CONFIG_USB_MSC) + return -1; + + // Verify right kind of device + struct usb_interface_descriptor *iface = usbdev->iface; + if ((iface->bInterfaceSubClass != US_SC_SCSI && + iface->bInterfaceSubClass != US_SC_ATAPI_8070 && + iface->bInterfaceSubClass != US_SC_ATAPI_8020) + || iface->bInterfaceProtocol != US_PR_BULK) { + dprintf(1, "Unsupported MSC USB device (subclass=%02x proto=%02x)\n" + , iface->bInterfaceSubClass, iface->bInterfaceProtocol); + return -1; + } + + // Find bulk in and bulk out endpoints. + struct usb_pipe *inpipe = NULL, *outpipe = NULL; + struct usb_endpoint_descriptor *indesc = findEndPointDesc( + usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_IN); + struct usb_endpoint_descriptor *outdesc = findEndPointDesc( + usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); + if (!indesc || !outdesc) + goto fail; + inpipe = usb_alloc_pipe(usbdev, indesc); + outpipe = usb_alloc_pipe(usbdev, outdesc); + if (!inpipe || !outpipe) + goto fail; + + int maxlun = usb_msc_maxlun(usbdev->defpipe); + int lun, pipesused = 0; + for (lun = 0; lun < maxlun + 1; lun++) { + int ret = usb_msc_lun_setup(inpipe, outpipe, usbdev, lun); + if (!ret) + pipesused = 1; + } + + if (!pipesused) + goto fail; + + return 0; +fail: + dprintf(1, "Unable to configure USB MSC device.\n"); + free_pipe(inpipe); + free_pipe(outpipe); + return -1; +} diff -Nru seabios-1.7.1/src/hw/usb-msc.h seabios-1.7.4/src/hw/usb-msc.h --- seabios-1.7.1/src/hw/usb-msc.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-msc.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,10 @@ +#ifndef __USB_MSC_H +#define __USB_MSC_H + +// usb-msc.c +struct disk_op_s; +int usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +struct usbdevice_s; +int usb_msc_setup(struct usbdevice_s *usbdev); + +#endif // ush-msc.h diff -Nru seabios-1.7.1/src/hw/usb-ohci.c seabios-1.7.4/src/hw/usb-ohci.c --- seabios-1.7.1/src/hw/usb-ohci.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-ohci.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,538 @@ +// Code for handling OHCI USB controllers. +// +// Copyright (C) 2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_LOWFLAT +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // pci_bdf_to_bus +#include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "string.h" // memset +#include "usb.h" // struct usb_s +#include "usb-ohci.h" // struct ohci_hcca +#include "util.h" // msleep +#include "x86.h" // readl + +#define FIT (1 << 31) + +struct usb_ohci_s { + struct usb_s usb; + struct ohci_regs *regs; +}; + +struct ohci_pipe { + struct ohci_ed ed; + struct usb_pipe pipe; + void *data; + int count; + struct ohci_td *tds; +}; + + +/**************************************************************** + * Root hub + ****************************************************************/ + +// Check if device attached to port +static int +ohci_hub_detect(struct usbhub_s *hub, u32 port) +{ + struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb); + u32 sts = readl(&cntl->regs->roothub_portstatus[port]); + if (!(sts & RH_PS_CCS)) + // No device. + return -1; + + // XXX - need to wait for USB_TIME_ATTDB if just powered up? + + return 0; +} + +// Disable port +static void +ohci_hub_disconnect(struct usbhub_s *hub, u32 port) +{ + struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb); + writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA); +} + +// Reset device on port +static int +ohci_hub_reset(struct usbhub_s *hub, u32 port) +{ + struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb); + writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS); + u32 sts; + u32 end = timer_calc(USB_TIME_DRSTR * 2); + for (;;) { + sts = readl(&cntl->regs->roothub_portstatus[port]); + if (!(sts & RH_PS_PRS)) + // XXX - need to ensure USB_TIME_DRSTR time in reset? + break; + if (timer_check(end)) { + // Timeout. + warn_timeout(); + ohci_hub_disconnect(hub, port); + return -1; + } + yield(); + } + + if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES)) + // Device no longer present + return -1; + + return !!(sts & RH_PS_LSDA); +} + +static struct usbhub_op_s ohci_HubOp = { + .detect = ohci_hub_detect, + .reset = ohci_hub_reset, + .disconnect = ohci_hub_disconnect, +}; + +// Find any devices connected to the root hub. +static int +check_ohci_ports(struct usb_ohci_s *cntl) +{ + ASSERT32FLAT(); + // Turn on power for all devices on roothub. + u32 rha = readl(&cntl->regs->roothub_a); + rha &= ~(RH_A_PSM | RH_A_OCPM); + writel(&cntl->regs->roothub_status, RH_HS_LPSC); + writel(&cntl->regs->roothub_b, RH_B_PPCM); + msleep((rha >> 24) * 2); + // XXX - need to sleep for USB_TIME_SIGATT if just powered up? + + struct usbhub_s hub; + memset(&hub, 0, sizeof(hub)); + hub.cntl = &cntl->usb; + hub.portcount = rha & RH_A_NDP; + hub.op = &ohci_HubOp; + usb_enumerate(&hub); + return hub.devcount; +} + + +/**************************************************************** + * Setup + ****************************************************************/ + +// Wait for next USB frame to start - for ensuring safe memory release. +static void +ohci_waittick(struct usb_ohci_s *cntl) +{ + barrier(); + struct ohci_hcca *hcca = (void*)cntl->regs->hcca; + u32 startframe = hcca->frame_no; + u32 end = timer_calc(1000 * 5); + for (;;) { + if (hcca->frame_no != startframe) + break; + if (timer_check(end)) { + warn_timeout(); + return; + } + yield(); + } +} + +static void +ohci_free_pipes(struct usb_ohci_s *cntl) +{ + dprintf(7, "ohci_free_pipes %p\n", cntl); + + u32 creg = readl(&cntl->regs->control); + if (creg & (OHCI_CTRL_CLE|OHCI_CTRL_BLE)) { + writel(&cntl->regs->control, creg & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE)); + ohci_waittick(cntl); + } + + u32 *pos = &cntl->regs->ed_controlhead; + for (;;) { + struct ohci_ed *next = (void*)*pos; + if (!next) + break; + struct ohci_pipe *pipe = container_of(next, struct ohci_pipe, ed); + if (pipe->pipe.cntl != &cntl->usb) { + *pos = next->hwNextED; + free(pipe); + } else { + pos = &next->hwNextED; + } + } + + writel(&cntl->regs->ed_controlcurrent, 0); + writel(&cntl->regs->ed_bulkcurrent, 0); + writel(&cntl->regs->control, creg); + cntl->usb.freelist = NULL; +} + +static int +start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca) +{ + u32 oldfminterval = readl(&cntl->regs->fminterval); + u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC; + + // XXX - check if already running? + + // Do reset + writel(&cntl->regs->control, OHCI_USB_RESET | oldrwc); + readl(&cntl->regs->control); // flush writes + msleep(USB_TIME_DRSTR); + + // Do software init (min 10us, max 2ms) + u32 end = timer_calc_usec(10); + writel(&cntl->regs->cmdstatus, OHCI_HCR); + for (;;) { + u32 status = readl(&cntl->regs->cmdstatus); + if (! status & OHCI_HCR) + break; + if (timer_check(end)) { + warn_timeout(); + return -1; + } + } + + // Init memory + writel(&cntl->regs->ed_controlhead, 0); + writel(&cntl->regs->ed_bulkhead, 0); + writel(&cntl->regs->hcca, (u32)hcca); + + // Init fminterval + u32 fi = oldfminterval & 0x3fff; + writel(&cntl->regs->fminterval + , (((oldfminterval & FIT) ^ FIT) + | fi | (((6 * (fi - 210)) / 7) << 16))); + writel(&cntl->regs->periodicstart, ((9 * fi) / 10) & 0x3fff); + readl(&cntl->regs->control); // flush writes + + // XXX - verify that fminterval was setup correctly. + + // Go into operational state + writel(&cntl->regs->control + , (OHCI_CTRL_CBSR | OHCI_CTRL_CLE | OHCI_CTRL_PLE + | OHCI_USB_OPER | oldrwc)); + readl(&cntl->regs->control); // flush writes + + return 0; +} + +static void +stop_ohci(struct usb_ohci_s *cntl) +{ + u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC; + writel(&cntl->regs->control, oldrwc); + readl(&cntl->regs->control); // flush writes +} + +static void +configure_ohci(void *data) +{ + struct usb_ohci_s *cntl = data; + + // Allocate memory + struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca)); + struct ohci_ed *intr_ed = malloc_high(sizeof(*intr_ed)); + if (!hcca || !intr_ed) { + warn_noalloc(); + goto free; + } + memset(hcca, 0, sizeof(*hcca)); + memset(intr_ed, 0, sizeof(*intr_ed)); + intr_ed->hwINFO = ED_SKIP; + int i; + for (i=0; iint_table); i++) + hcca->int_table[i] = (u32)intr_ed; + + int ret = start_ohci(cntl, hcca); + if (ret) + goto err; + + int count = check_ohci_ports(cntl); + ohci_free_pipes(cntl); + if (! count) + goto err; + return; + +err: + stop_ohci(cntl); +free: + free(hcca); + free(intr_ed); +} + +void +ohci_setup(struct pci_device *pci, int busid) +{ + if (! CONFIG_USB_OHCI) + return; + struct usb_ohci_s *cntl = malloc_tmphigh(sizeof(*cntl)); + if (!cntl) { + warn_noalloc(); + return; + } + memset(cntl, 0, sizeof(*cntl)); + cntl->usb.busid = busid; + cntl->usb.pci = pci; + cntl->usb.type = USB_TYPE_OHCI; + + u16 bdf = pci->bdf; + u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); + cntl->regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); + + dprintf(1, "OHCI init on dev %02x:%02x.%x (regs=%p)\n" + , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) + , pci_bdf_to_fn(bdf), cntl->regs); + + // Enable bus mastering and memory access. + pci_config_maskw(bdf, PCI_COMMAND + , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY); + + // XXX - check for and disable SMM control? + + // Disable interrupts + writel(&cntl->regs->intrdisable, ~0); + writel(&cntl->regs->intrstatus, ~0); + + run_thread(configure_ohci, cntl); +} + + +/**************************************************************** + * End point communication + ****************************************************************/ + +// Setup fields in ed +static void +ohci_desc2pipe(struct ohci_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + pipe->ed.hwINFO = (ED_SKIP | usbdev->devaddr | (pipe->pipe.ep << 7) + | (epdesc->wMaxPacketSize << 16) + | (usbdev->speed ? ED_LOWSPEED : 0)); +} + +static struct usb_pipe * +ohci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + struct usb_ohci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_ohci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); + dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); + + if (frameexp > 5) + frameexp = 5; + int maxpacket = epdesc->wMaxPacketSize; + // Determine number of entries needed for 2 timer ticks. + int ms = 1<ed.hwINFO &= ~ED_SKIP; + pipe->data = data; + pipe->count = count; + pipe->tds = tds; + + struct ohci_ed *ed = &pipe->ed; + ed->hwHeadP = (u32)&tds[0]; + ed->hwTailP = (u32)&tds[count-1]; + + int i; + for (i=0; iregs->hcca; + if (frameexp == 0) { + // Add to existing interrupt entry. + struct ohci_ed *intr_ed = (void*)hcca->int_table[0]; + ed->hwNextED = intr_ed->hwNextED; + barrier(); + intr_ed->hwNextED = (u32)ed; + } else { + int startpos = 1<<(frameexp-1); + ed->hwNextED = hcca->int_table[startpos]; + barrier(); + for (i=startpos; iint_table); i+=ms) + hcca->int_table[i] = (u32)ed; + } + + return &pipe->pipe; + +err: + free(pipe); + free(tds); + free(data); + return NULL; +} + +struct usb_pipe * +ohci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + if (! CONFIG_USB_OHCI) + return NULL; + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_INT) + return ohci_alloc_intr_pipe(usbdev, epdesc); + if (eptype != USB_ENDPOINT_XFER_CONTROL) { + dprintf(1, "OHCI Bulk transfers not supported.\n"); + return NULL; + } + struct usb_ohci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_ohci_s, usb); + dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb); + + struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); + if (usbpipe) { + // Use previously allocated pipe. + struct ohci_pipe *pipe = container_of(usbpipe, struct ohci_pipe, pipe); + ohci_desc2pipe(pipe, usbdev, epdesc); + return usbpipe; + } + + // Allocate a new queue head. + struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe)); + if (!pipe) { + warn_noalloc(); + return NULL; + } + memset(pipe, 0, sizeof(*pipe)); + ohci_desc2pipe(pipe, usbdev, epdesc); + + // Add queue head to controller list. + pipe->ed.hwNextED = cntl->regs->ed_controlhead; + barrier(); + cntl->regs->ed_controlhead = (u32)&pipe->ed; + return &pipe->pipe; +} + +static int +wait_ed(struct ohci_ed *ed) +{ + // XXX - 500ms just a guess + u32 end = timer_calc(500); + for (;;) { + if (ed->hwHeadP == ed->hwTailP) + return 0; + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } +} + +int +ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datasize) +{ + if (! CONFIG_USB_OHCI) + return -1; + dprintf(5, "ohci_control %p\n", p); + if (datasize > 4096) { + // XXX - should support larger sizes. + warn_noalloc(); + return -1; + } + struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); + struct usb_ohci_s *cntl = container_of( + pipe->pipe.cntl, struct usb_ohci_s, usb); + + // Setup transfer descriptors + struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3); + if (!tds) { + warn_noalloc(); + return -1; + } + struct ohci_td *td = tds; + td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC; + td->hwCBP = (u32)cmd; + td->hwNextTD = (u32)&td[1]; + td->hwBE = (u32)cmd + cmdsize - 1; + td++; + if (datasize) { + td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC; + td->hwCBP = (u32)data; + td->hwNextTD = (u32)&td[1]; + td->hwBE = (u32)data + datasize - 1; + td++; + } + td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC; + td->hwCBP = 0; + td->hwNextTD = (u32)&td[1]; + td->hwBE = 0; + td++; + + // Transfer data + pipe->ed.hwHeadP = (u32)tds; + pipe->ed.hwTailP = (u32)td; + barrier(); + pipe->ed.hwINFO &= ~ED_SKIP; + writel(&cntl->regs->cmdstatus, OHCI_CLF); + + int ret = wait_ed(&pipe->ed); + pipe->ed.hwINFO |= ED_SKIP; + if (ret) + ohci_waittick(cntl); + free(tds); + return ret; +} + +int +ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) +{ + return -1; +} + +int +ohci_poll_intr(struct usb_pipe *p, void *data) +{ + ASSERT16(); + if (! CONFIG_USB_OHCI) + return -1; + + struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); + struct ohci_td *tds = GET_LOWFLAT(pipe->tds); + struct ohci_td *head = (void*)(GET_LOWFLAT(pipe->ed.hwHeadP) & ~(ED_C|ED_H)); + struct ohci_td *tail = (void*)GET_LOWFLAT(pipe->ed.hwTailP); + int count = GET_LOWFLAT(pipe->count); + int pos = (tail - tds + 1) % count; + struct ohci_td *next = &tds[pos]; + if (head == next) + // No intrs found. + return -1; + // XXX - check for errors. + + // Copy data. + int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); + void *pipedata = GET_LOWFLAT((pipe->data)); + void *intrdata = pipedata + maxpacket * pos; + memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(intrdata), maxpacket); + + // Reenable this td. + SET_LOWFLAT(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC); + intrdata = pipedata + maxpacket * (tail-tds); + SET_LOWFLAT(tail->hwCBP, (u32)intrdata); + SET_LOWFLAT(tail->hwNextTD, (u32)next); + SET_LOWFLAT(tail->hwBE, (u32)intrdata + maxpacket - 1); + barrier(); + SET_LOWFLAT(pipe->ed.hwTailP, (u32)next); + + return 0; +} diff -Nru seabios-1.7.1/src/hw/usb-ohci.h seabios-1.7.4/src/hw/usb-ohci.h --- seabios-1.7.1/src/hw/usb-ohci.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-ohci.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,143 @@ +#ifndef __USB_OHCI_H +#define __USB_OHCI_H + +// usb-ohci.c +void ohci_setup(struct pci_device *pci, int busid); +struct usbdevice_s; +struct usb_endpoint_descriptor; +struct usb_pipe *ohci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe; +int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datasize); +int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); +int ohci_poll_intr(struct usb_pipe *p, void *data); + + +/**************************************************************** + * ohci structs and flags + ****************************************************************/ + +struct ohci_ed { + u32 hwINFO; + u32 hwTailP; + u32 hwHeadP; + u32 hwNextED; +} PACKED; + +#define ED_ISO (1 << 15) +#define ED_SKIP (1 << 14) +#define ED_LOWSPEED (1 << 13) +#define ED_OUT (0x01 << 11) +#define ED_IN (0x02 << 11) + +#define ED_C (0x02) +#define ED_H (0x01) + +struct ohci_td { + u32 hwINFO; + u32 hwCBP; + u32 hwNextTD; + u32 hwBE; +} PACKED; + +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_DI 0x00E00000 + +#define TD_DONE 0x00020000 +#define TD_ISO 0x00010000 + +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_R 0x00040000 + +struct ohci_hcca { + u32 int_table[32]; + u32 frame_no; + u32 done_head; + u8 reserved[120]; +} PACKED; + +struct ohci_regs { + u32 revision; + u32 control; + u32 cmdstatus; + u32 intrstatus; + u32 intrenable; + u32 intrdisable; + + u32 hcca; + u32 ed_periodcurrent; + u32 ed_controlhead; + u32 ed_controlcurrent; + u32 ed_bulkhead; + u32 ed_bulkcurrent; + u32 donehead; + + u32 fminterval; + u32 fmremaining; + u32 fmnumber; + u32 periodicstart; + u32 lsthresh; + + u32 roothub_a; + u32 roothub_b; + u32 roothub_status; + u32 roothub_portstatus[15]; +} PACKED; + +#define OHCI_CTRL_CBSR (3 << 0) +#define OHCI_CTRL_PLE (1 << 2) +#define OHCI_CTRL_CLE (1 << 4) +#define OHCI_CTRL_BLE (1 << 5) +#define OHCI_CTRL_HCFS (3 << 6) +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_OPER (2 << 6) +#define OHCI_CTRL_RWC (1 << 9) + +#define OHCI_HCR (1 << 0) +#define OHCI_CLF (1 << 1) + +#define OHCI_INTR_MIE (1 << 31) + +#define RH_PS_CCS 0x00000001 +#define RH_PS_PES 0x00000002 +#define RH_PS_PSS 0x00000004 +#define RH_PS_POCI 0x00000008 +#define RH_PS_PRS 0x00000010 +#define RH_PS_PPS 0x00000100 +#define RH_PS_LSDA 0x00000200 +#define RH_PS_CSC 0x00010000 +#define RH_PS_PESC 0x00020000 +#define RH_PS_PSSC 0x00040000 +#define RH_PS_OCIC 0x00080000 +#define RH_PS_PRSC 0x00100000 + +#define RH_HS_LPS 0x00000001 +#define RH_HS_OCI 0x00000002 +#define RH_HS_DRWE 0x00008000 +#define RH_HS_LPSC 0x00010000 +#define RH_HS_OCIC 0x00020000 +#define RH_HS_CRWE 0x80000000 + +#define RH_B_DR 0x0000ffff +#define RH_B_PPCM 0xffff0000 + +#define RH_A_NDP (0xff << 0) +#define RH_A_PSM (1 << 8) +#define RH_A_NPS (1 << 9) +#define RH_A_DT (1 << 10) +#define RH_A_OCPM (1 << 11) +#define RH_A_NOCP (1 << 12) +#define RH_A_POTPGT (0xff << 24) + +#endif // usb-ohci.h diff -Nru seabios-1.7.1/src/hw/usb-uas.c seabios-1.7.4/src/hw/usb-uas.c --- seabios-1.7.1/src/hw/usb-uas.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-uas.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,271 @@ +// Code for handling usb attached scsi devices. +// +// only usb 2.0 for now. +// +// once we have xhci driver with usb 3.0 support this must +// be updated to use usb3 streams so booting from usb3 +// devices actually works. +// +// Authors: +// Gerd Hoffmann +// +// based on usb-msc.c which is written by: +// Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // DTYPE_USB +#include "blockcmd.h" // cdb_read +#include "config.h" // CONFIG_USB_UAS +#include "malloc.h" // free +#include "output.h" // dprintf +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "usb.h" // struct usb_s +#include "usb-uas.h" // usb_uas_init +#include "util.h" // bootprio_find_usb + +#define UAS_UI_COMMAND 0x01 +#define UAS_UI_SENSE 0x03 +#define UAS_UI_RESPONSE 0x04 +#define UAS_UI_TASK_MGMT 0x05 +#define UAS_UI_READ_READY 0x06 +#define UAS_UI_WRITE_READY 0x07 + +#define UAS_PIPE_ID_COMMAND 0x01 +#define UAS_PIPE_ID_STATUS 0x02 +#define UAS_PIPE_ID_DATA_IN 0x03 +#define UAS_PIPE_ID_DATA_OUT 0x04 + +typedef struct { + u8 id; + u8 reserved; + u16 tag; +} PACKED uas_ui_header; + +typedef struct { + u8 prio_taskattr; /* 6:3 priority, 2:0 task attribute */ + u8 reserved_1; + u8 add_cdb_length; /* 7:2 additional adb length (dwords) */ + u8 reserved_2; + u8 lun[8]; + u8 cdb[16]; + u8 add_cdb[]; +} PACKED uas_ui_command; + +typedef struct { + u16 status_qualifier; + u8 status; + u8 reserved[7]; + u16 sense_length; + u8 sense_data[18]; +} PACKED uas_ui_sense; + +typedef struct { + u16 add_response_info; + u8 response_code; +} PACKED uas_ui_response; + +typedef struct { + u8 function; + u8 reserved; + u16 task_tag; + u8 lun[8]; +} PACKED uas_ui_task_mgmt; + +typedef struct { + uas_ui_header hdr; + union { + uas_ui_command command; + uas_ui_sense sense; + uas_ui_task_mgmt task; + uas_ui_response response; + }; +} PACKED uas_ui; + +struct uasdrive_s { + struct drive_s drive; + struct usb_pipe *command, *status, *data_in, *data_out; + int lun; +}; + +int +uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + if (!CONFIG_USB_UAS) + return DISK_RET_EBADTRACK; + + struct uasdrive_s *drive_gf = container_of( + op->drive_gf, struct uasdrive_s, drive); + + uas_ui ui; + memset(&ui, 0, sizeof(ui)); + ui.hdr.id = UAS_UI_COMMAND; + ui.hdr.tag = 0xdead; + ui.command.lun[1] = GET_GLOBALFLAT(drive_gf->lun); + memcpy(ui.command.cdb, cdbcmd, sizeof(ui.command.cdb)); + int ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->command), + USB_DIR_OUT, MAKE_FLATPTR(GET_SEG(SS), &ui), + sizeof(ui.hdr) + sizeof(ui.command)); + if (ret) { + dprintf(1, "uas: command send fail"); + goto fail; + } + + memset(&ui, 0xff, sizeof(ui)); + ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->status), + USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui)); + if (ret) { + dprintf(1, "uas: status recv fail"); + goto fail; + } + + switch (ui.hdr.id) { + case UAS_UI_SENSE: + goto have_sense; + case UAS_UI_READ_READY: + ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->data_in), + USB_DIR_IN, op->buf_fl, op->count * blocksize); + if (ret) { + dprintf(1, "uas: data read fail"); + goto fail; + } + break; + case UAS_UI_WRITE_READY: + ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->data_out), + USB_DIR_OUT, op->buf_fl, op->count * blocksize); + if (ret) { + dprintf(1, "uas: data write fail"); + goto fail; + } + break; + default: + dprintf(1, "uas: unknown status ui id %d", ui.hdr.id); + goto fail; + } + + memset(&ui, 0xff, sizeof(ui)); + ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->status), + USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui)); + if (ret) { + dprintf(1, "uas: status recv fail"); + goto fail; + } + if (ui.hdr.id != UAS_UI_SENSE) { + dprintf(1, "uas: expected sense ui, got ui id %d", ui.hdr.id); + goto fail; + } + +have_sense: + if (ui.sense.status == 0) { + return DISK_RET_SUCCESS; + } + +fail: + return DISK_RET_EBADTRACK; +} + +static int +uas_lun_setup(struct usbdevice_s *usbdev, + struct usb_pipe *command, struct usb_pipe *status, + struct usb_pipe *data_in, struct usb_pipe *data_out, + int lun) +{ + // Allocate drive structure. + struct uasdrive_s *drive = malloc_fseg(sizeof(*drive)); + if (!drive) { + warn_noalloc(); + return -1; + } + memset(drive, 0, sizeof(*drive)); + drive->drive.type = DTYPE_UAS; + drive->command = command; + drive->status = status; + drive->data_in = data_in; + drive->data_out = data_out; + drive->lun = lun; + + int prio = bootprio_find_usb(usbdev, lun); + int ret = scsi_drive_setup(&drive->drive, "USB UAS", prio); + if (ret) { + free(drive); + return -1; + } + return 0; +} + +int +usb_uas_setup(struct usbdevice_s *usbdev) +{ + if (!CONFIG_USB_UAS) + return -1; + + // Verify right kind of device + struct usb_interface_descriptor *iface = usbdev->iface; + if (iface->bInterfaceSubClass != US_SC_SCSI || + iface->bInterfaceProtocol != US_PR_UAS) { + dprintf(1, "Unsupported UAS device (subclass=%02x proto=%02x)\n" + , iface->bInterfaceSubClass, iface->bInterfaceProtocol); + return -1; + } + + /* find & allocate pipes */ + struct usb_endpoint_descriptor *ep = NULL; + struct usb_pipe *command = NULL; + struct usb_pipe *status = NULL; + struct usb_pipe *data_in = NULL; + struct usb_pipe *data_out = NULL; + u8 *desc = (u8*)iface; + while (desc) { + desc += desc[0]; + switch (desc[1]) { + case USB_DT_ENDPOINT: + ep = (void*)desc; + break; + case USB_DT_ENDPOINT_COMPANION: + /* No support (yet) for usb3 streams */ + dprintf(1, "Superspeed UAS devices not supported (yet)\n"); + goto fail; + case 0x24: + switch (desc[2]) { + case UAS_PIPE_ID_COMMAND: + command = usb_alloc_pipe(usbdev, ep); + break; + case UAS_PIPE_ID_STATUS: + status = usb_alloc_pipe(usbdev, ep); + break; + case UAS_PIPE_ID_DATA_IN: + data_in = usb_alloc_pipe(usbdev, ep); + break; + case UAS_PIPE_ID_DATA_OUT: + data_out = usb_alloc_pipe(usbdev, ep); + break; + default: + goto fail; + } + break; + default: + desc = NULL; + break; + } + } + if (!command || !status || !data_in || !data_out) + goto fail; + + /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ + int ret = uas_lun_setup(usbdev, command, status, data_in, data_out, 0); + if (ret < 0) { + dprintf(1, "Unable to configure UAS drive.\n"); + goto fail; + } + + return 0; + +fail: + free_pipe(command); + free_pipe(status); + free_pipe(data_in); + free_pipe(data_out); + return -1; +} diff -Nru seabios-1.7.1/src/hw/usb-uas.h seabios-1.7.4/src/hw/usb-uas.h --- seabios-1.7.1/src/hw/usb-uas.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-uas.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,9 @@ +#ifndef __USB_UAS_H +#define __USB_UAS_H + +struct disk_op_s; +int uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +struct usbdevice_s; +int usb_uas_setup(struct usbdevice_s *usbdev); + +#endif /* __USB_UAS_H */ diff -Nru seabios-1.7.1/src/hw/usb-uhci.c seabios-1.7.4/src/hw/usb-uhci.c --- seabios-1.7.1/src/hw/usb-uhci.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-uhci.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,581 @@ +// Code for handling UHCI USB controllers. +// +// Copyright (C) 2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_LOWFLAT +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // pci_bdf_to_bus +#include "pci_regs.h" // PCI_BASE_ADDRESS_4 +#include "string.h" // memset +#include "usb.h" // struct usb_s +#include "usb-uhci.h" // USBLEGSUP +#include "util.h" // msleep +#include "x86.h" // outw + +struct usb_uhci_s { + struct usb_s usb; + u16 iobase; + struct uhci_qh *control_qh; + struct uhci_framelist *framelist; +}; + +struct uhci_pipe { + struct uhci_qh qh; + struct uhci_td *next_td; + struct usb_pipe pipe; + u16 iobase; + u8 toggle; +}; + + +/**************************************************************** + * Root hub + ****************************************************************/ + +// Check if device attached to a given port +static int +uhci_hub_detect(struct usbhub_s *hub, u32 port) +{ + struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); + u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; + + u16 status = inw(ioport); + if (!(status & USBPORTSC_CCS)) + // No device + return -1; + + // XXX - if just powered up, need to wait for USB_TIME_ATTDB? + + // Begin reset on port + outw(USBPORTSC_PR, ioport); + msleep(USB_TIME_DRSTR); + return 0; +} + +// Reset device on port +static int +uhci_hub_reset(struct usbhub_s *hub, u32 port) +{ + struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); + u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; + + // Finish reset on port + outw(0, ioport); + udelay(6); // 64 high-speed bit times + u16 status = inw(ioport); + if (!(status & USBPORTSC_CCS)) + // No longer connected + return -1; + outw(USBPORTSC_PE, ioport); + return !!(status & USBPORTSC_LSDA); +} + +// Disable port +static void +uhci_hub_disconnect(struct usbhub_s *hub, u32 port) +{ + struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); + u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; + outw(0, ioport); +} + +static struct usbhub_op_s uhci_HubOp = { + .detect = uhci_hub_detect, + .reset = uhci_hub_reset, + .disconnect = uhci_hub_disconnect, +}; + +// Find any devices connected to the root hub. +static int +check_uhci_ports(struct usb_uhci_s *cntl) +{ + ASSERT32FLAT(); + struct usbhub_s hub; + memset(&hub, 0, sizeof(hub)); + hub.cntl = &cntl->usb; + hub.portcount = 2; + hub.op = &uhci_HubOp; + usb_enumerate(&hub); + return hub.devcount; +} + + +/**************************************************************** + * Setup + ****************************************************************/ + +// Wait for next USB frame to start - for ensuring safe memory release. +static void +uhci_waittick(u16 iobase) +{ + barrier(); + u16 startframe = inw(iobase + USBFRNUM); + u32 end = timer_calc(1000 * 5); + for (;;) { + if (inw(iobase + USBFRNUM) != startframe) + break; + if (timer_check(end)) { + warn_timeout(); + return; + } + yield(); + } +} + +static void +uhci_free_pipes(struct usb_uhci_s *cntl) +{ + dprintf(7, "uhci_free_pipes %p\n", cntl); + + struct uhci_qh *pos = (void*)(cntl->framelist->links[0] & ~UHCI_PTR_BITS); + for (;;) { + u32 link = pos->link; + if (link == UHCI_PTR_TERM) + break; + struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS); + struct uhci_pipe *pipe = container_of(next, struct uhci_pipe, qh); + if (pipe->pipe.cntl != &cntl->usb) + pos->link = next->link; + else + pos = next; + } + uhci_waittick(cntl->iobase); + for (;;) { + struct usb_pipe *usbpipe = cntl->usb.freelist; + if (!usbpipe) + break; + cntl->usb.freelist = usbpipe->freenext; + struct uhci_pipe *pipe = container_of(usbpipe, struct uhci_pipe, pipe); + free(pipe); + } +} + +static void +reset_uhci(struct usb_uhci_s *cntl, u16 bdf) +{ + // XXX - don't reset if not needed. + + // Reset PIRQ and SMI + pci_config_writew(bdf, USBLEGSUP, USBLEGSUP_RWC); + + // Reset the HC + outw(USBCMD_HCRESET, cntl->iobase + USBCMD); + udelay(5); + + // Disable interrupts and commands (just to be safe). + outw(0, cntl->iobase + USBINTR); + outw(0, cntl->iobase + USBCMD); +} + +static void +configure_uhci(void *data) +{ + struct usb_uhci_s *cntl = data; + + // Allocate ram for schedule storage + struct uhci_td *term_td = malloc_high(sizeof(*term_td)); + struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl)); + struct uhci_pipe *intr_pipe = malloc_high(sizeof(*intr_pipe)); + struct uhci_pipe *term_pipe = malloc_high(sizeof(*term_pipe)); + if (!term_td || !fl || !intr_pipe || !term_pipe) { + warn_noalloc(); + goto fail; + } + + // Work around for PIIX errata + memset(term_td, 0, sizeof(*term_td)); + term_td->link = UHCI_PTR_TERM; + term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT) + | USB_PID_IN); + memset(term_pipe, 0, sizeof(*term_pipe)); + term_pipe->qh.element = (u32)term_td; + term_pipe->qh.link = UHCI_PTR_TERM; + term_pipe->pipe.cntl = &cntl->usb; + + // Set schedule to point to primary intr queue head + memset(intr_pipe, 0, sizeof(*intr_pipe)); + intr_pipe->qh.element = UHCI_PTR_TERM; + intr_pipe->qh.link = (u32)&term_pipe->qh | UHCI_PTR_QH; + intr_pipe->pipe.cntl = &cntl->usb; + int i; + for (i=0; ilinks); i++) + fl->links[i] = (u32)&intr_pipe->qh | UHCI_PTR_QH; + cntl->framelist = fl; + cntl->control_qh = &intr_pipe->qh; + barrier(); + + // Set the frame length to the default: 1 ms exactly + outb(USBSOF_DEFAULT, cntl->iobase + USBSOF); + + // Store the frame list base address + outl((u32)fl->links, cntl->iobase + USBFLBASEADD); + + // Set the current frame number + outw(0, cntl->iobase + USBFRNUM); + + // Mark as configured and running with a 64-byte max packet. + outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->iobase + USBCMD); + + // Find devices + int count = check_uhci_ports(cntl); + uhci_free_pipes(cntl); + if (count) + // Success + return; + + // No devices found - shutdown and free controller. + outw(0, cntl->iobase + USBCMD); +fail: + free(term_td); + free(fl); + free(intr_pipe); + free(term_pipe); + free(cntl); +} + +void +uhci_setup(struct pci_device *pci, int busid) +{ + if (! CONFIG_USB_UHCI) + return; + u16 bdf = pci->bdf; + struct usb_uhci_s *cntl = malloc_tmphigh(sizeof(*cntl)); + if (!cntl) { + warn_noalloc(); + return; + } + memset(cntl, 0, sizeof(*cntl)); + cntl->usb.busid = busid; + cntl->usb.pci = pci; + cntl->usb.type = USB_TYPE_UHCI; + cntl->iobase = (pci_config_readl(bdf, PCI_BASE_ADDRESS_4) + & PCI_BASE_ADDRESS_IO_MASK); + + dprintf(1, "UHCI init on dev %02x:%02x.%x (io=%x)\n" + , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) + , pci_bdf_to_fn(bdf), cntl->iobase); + + pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + + reset_uhci(cntl, bdf); + + run_thread(configure_uhci, cntl); +} + + +/**************************************************************** + * End point communication + ****************************************************************/ + +static struct usb_pipe * +uhci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + struct usb_uhci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_uhci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); + dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); + + if (frameexp > 10) + frameexp = 10; + int maxpacket = epdesc->wMaxPacketSize; + // Determine number of entries needed for 2 timer ticks. + int ms = 1<pipe, usbdev, epdesc); + int lowspeed = pipe->pipe.speed; + int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); + pipe->qh.element = (u32)tds; + pipe->next_td = &tds[0]; + pipe->iobase = cntl->iobase; + + int toggle = 0; + int i; + for (i=0; iframelist; + if (frameexp == 0) { + // Add to existing interrupt entry. + struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS); + pipe->qh.link = intr_qh->link; + barrier(); + intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; + if (cntl->control_qh == intr_qh) + cntl->control_qh = &pipe->qh; + } else { + int startpos = 1<<(frameexp-1); + pipe->qh.link = fl->links[startpos]; + barrier(); + for (i=startpos; ilinks); i+=ms) + fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH; + } + + return &pipe->pipe; +fail: + free(pipe); + free(tds); + free(data); + return NULL; +} + +struct usb_pipe * +uhci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + if (! CONFIG_USB_UHCI) + return NULL; + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_INT) + return uhci_alloc_intr_pipe(usbdev, epdesc); + struct usb_uhci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_uhci_s, usb); + dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); + + struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); + if (usbpipe) { + // Use previously allocated pipe. + usb_desc2pipe(usbpipe, usbdev, epdesc); + return usbpipe; + } + + // Allocate a new queue head. + struct uhci_pipe *pipe; + if (eptype == USB_ENDPOINT_XFER_CONTROL) + pipe = malloc_tmphigh(sizeof(*pipe)); + else + pipe = malloc_low(sizeof(*pipe)); + if (!pipe) { + warn_noalloc(); + return NULL; + } + memset(pipe, 0, sizeof(*pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + pipe->qh.element = UHCI_PTR_TERM; + pipe->iobase = cntl->iobase; + + // Add queue head to controller list. + struct uhci_qh *control_qh = cntl->control_qh; + pipe->qh.link = control_qh->link; + barrier(); + control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; + if (eptype == USB_ENDPOINT_XFER_CONTROL) + cntl->control_qh = &pipe->qh; + return &pipe->pipe; +} + +static int +wait_pipe(struct uhci_pipe *pipe, int timeout) +{ + u32 end = timer_calc(timeout); + for (;;) { + u32 el_link = GET_LOWFLAT(pipe->qh.element); + if (el_link & UHCI_PTR_TERM) + return 0; + if (timer_check(end)) { + warn_timeout(); + u16 iobase = GET_LOWFLAT(pipe->iobase); + struct uhci_td *td = (void*)(el_link & ~UHCI_PTR_BITS); + dprintf(1, "Timeout on wait_pipe %p (td=%p s=%x c=%x/%x)\n" + , pipe, (void*)el_link, GET_LOWFLAT(td->status) + , inw(iobase + USBCMD) + , inw(iobase + USBSTS)); + SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM); + uhci_waittick(iobase); + return -1; + } + yield(); + } +} + +static int +wait_td(struct uhci_td *td) +{ + u32 end = timer_calc(5000); // XXX - lookup real time. + u32 status; + for (;;) { + status = td->status; + if (!(status & TD_CTRL_ACTIVE)) + break; + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } + if (status & TD_CTRL_ANY_ERROR) { + dprintf(1, "wait_td error - status=%x\n", status); + return -2; + } + return 0; +} + +int +uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datasize) +{ + ASSERT32FLAT(); + if (! CONFIG_USB_UHCI) + return -1; + dprintf(5, "uhci_control %p\n", p); + struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); + + int maxpacket = pipe->pipe.maxpacket; + int lowspeed = pipe->pipe.speed; + int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); + + // Setup transfer descriptors + int count = 2 + DIV_ROUND_UP(datasize, maxpacket); + struct uhci_td *tds = malloc_tmphigh(sizeof(*tds) * count); + if (!tds) { + warn_noalloc(); + return -1; + } + + tds[0].link = (u32)&tds[1] | UHCI_PTR_DEPTH; + tds[0].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) + | TD_CTRL_ACTIVE); + tds[0].token = (uhci_explen(cmdsize) | (devaddr << TD_TOKEN_DEVADDR_SHIFT) + | USB_PID_SETUP); + tds[0].buffer = (void*)cmd; + int toggle = TD_TOKEN_TOGGLE; + int i; + for (i=1; iqh.element = (u32)&tds[0]; + int ret = wait_pipe(pipe, 500); + free(tds); + return ret; +} + +#define STACKTDS 4 +#define TDALIGN 16 + +int +uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) +{ + if (! CONFIG_USB_UHCI) + return -1; + struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); + dprintf(7, "uhci_send_bulk qh=%p dir=%d data=%p size=%d\n" + , &pipe->qh, dir, data, datasize); + int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); + int lowspeed = GET_LOWFLAT(pipe->pipe.speed); + int devaddr = (GET_LOWFLAT(pipe->pipe.devaddr) + | (GET_LOWFLAT(pipe->pipe.ep) << 7)); + int toggle = GET_LOWFLAT(pipe->toggle) ? TD_TOKEN_TOGGLE : 0; + + // Allocate 4 tds on stack (16byte aligned) + u8 tdsbuf[sizeof(struct uhci_td) * STACKTDS + TDALIGN - 1]; + struct uhci_td *tds = (void*)ALIGN((u32)tdsbuf, TDALIGN); + memset(tds, 0, sizeof(*tds) * STACKTDS); + + // Enable tds + barrier(); + SET_LOWFLAT(pipe->qh.element, (u32)MAKE_FLATPTR(GET_SEG(SS), tds)); + + int tdpos = 0; + while (datasize) { + struct uhci_td *td = &tds[tdpos++ % STACKTDS]; + int ret = wait_td(td); + if (ret) + goto fail; + + int transfer = datasize; + if (transfer > maxpacket) + transfer = maxpacket; + struct uhci_td *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS) + , &tds[tdpos % STACKTDS]); + td->link = (transfer==datasize ? UHCI_PTR_TERM : (u32)nexttd_fl); + td->token = (uhci_explen(transfer) | toggle + | (devaddr << TD_TOKEN_DEVADDR_SHIFT) + | (dir ? USB_PID_IN : USB_PID_OUT)); + td->buffer = data; + barrier(); + td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) + | TD_CTRL_ACTIVE); + toggle ^= TD_TOKEN_TOGGLE; + + data += transfer; + datasize -= transfer; + } + SET_LOWFLAT(pipe->toggle, !!toggle); + return wait_pipe(pipe, 5000); +fail: + dprintf(1, "uhci_send_bulk failed\n"); + SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM); + uhci_waittick(GET_LOWFLAT(pipe->iobase)); + return -1; +} + +int +uhci_poll_intr(struct usb_pipe *p, void *data) +{ + ASSERT16(); + if (! CONFIG_USB_UHCI) + return -1; + + struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); + struct uhci_td *td = GET_LOWFLAT(pipe->next_td); + u32 status = GET_LOWFLAT(td->status); + u32 token = GET_LOWFLAT(td->token); + if (status & TD_CTRL_ACTIVE) + // No intrs found. + return -1; + // XXX - check for errors. + + // Copy data. + void *tddata = GET_LOWFLAT(td->buffer); + memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata) + , uhci_expected_length(token)); + + // Reenable this td. + struct uhci_td *next = (void*)(GET_LOWFLAT(td->link) & ~UHCI_PTR_BITS); + SET_LOWFLAT(pipe->next_td, next); + barrier(); + SET_LOWFLAT(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS) + | TD_CTRL_ACTIVE)); + + return 0; +} diff -Nru seabios-1.7.1/src/hw/usb-uhci.h seabios-1.7.4/src/hw/usb-uhci.h --- seabios-1.7.1/src/hw/usb-uhci.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-uhci.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,128 @@ +#ifndef __USB_UHCI_H +#define __USB_UHCI_H + +// usb-uhci.c +void uhci_setup(struct pci_device *pci, int busid); +struct usbdevice_s; +struct usb_endpoint_descriptor; +struct usb_pipe *uhci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe; +int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datasize); +int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); +int uhci_poll_intr(struct usb_pipe *p, void *data); + + +/**************************************************************** + * uhci structs and flags + ****************************************************************/ + +/* USB port status and control registers */ +#define USBPORTSC1 16 +#define USBPORTSC2 18 +#define USBPORTSC_CCS 0x0001 /* Current Connect Status + * ("device present") */ +#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ +#define USBPORTSC_PE 0x0004 /* Port Enable */ +#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ +#define USBPORTSC_DPLUS 0x0010 /* D+ high (line status) */ +#define USBPORTSC_DMINUS 0x0020 /* D- high (line status) */ +#define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_RES1 0x0080 /* reserved, always 1 */ +#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ +#define USBPORTSC_PR 0x0200 /* Port Reset */ + +/* Legacy support register */ +#define USBLEGSUP 0xc0 +#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ + +/* Command register */ +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error: PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error: + * the schedule is buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 +#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ +#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ +#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ +#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 +#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */ + +struct uhci_framelist { + u32 links[1024]; +} PACKED; + +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_C_ERR_SHIFT 27 +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ +#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ + +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIMEO | \ + TD_CTRL_BITSTUFF) +#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) + +#define TD_TOKEN_DEVADDR_SHIFT 8 +#define TD_TOKEN_TOGGLE_SHIFT 19 +#define TD_TOKEN_TOGGLE (1 << 19) +#define TD_TOKEN_EXPLEN_SHIFT 21 +#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n-1 */ +#define TD_TOKEN_PID_MASK 0xFF + +#define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \ + TD_TOKEN_EXPLEN_SHIFT) + +#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \ + 1) & TD_TOKEN_EXPLEN_MASK) + +struct uhci_td { + u32 link; + u32 status; + u32 token; + void *buffer; +} PACKED; + +struct uhci_qh { + u32 link; + u32 element; +} PACKED; + +#define UHCI_PTR_BITS 0x000F +#define UHCI_PTR_TERM 0x0001 +#define UHCI_PTR_QH 0x0002 +#define UHCI_PTR_DEPTH 0x0004 +#define UHCI_PTR_BREADTH 0x0000 + +#endif // usb-uhci.h diff -Nru seabios-1.7.1/src/hw/usb-xhci.c seabios-1.7.4/src/hw/usb-xhci.c --- seabios-1.7.1/src/hw/usb-xhci.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-xhci.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,1129 @@ +#include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "string.h" // memcpy_fl +#include "util.h" // timer_calc +#include "x86.h" // readl +#include "malloc.h" // memalign_low +#include "pci.h" // pci_bdf_to_bus +#include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "usb.h" // struct usb_s +#include "usb-xhci.h" // struct ehci_qh +#include "biosvar.h" // GET_LOWFLAT + +// -------------------------------------------------------------- +// configuration + +#define XHCI_RING_ITEMS 16 +#define XHCI_RING_SIZE (XHCI_RING_ITEMS*sizeof(struct xhci_trb)) + +/* + * xhci_ring structs are allocated with XHCI_RING_SIZE alignment, + * then we can get it from a trb pointer (provided by evt ring). + */ +#define XHCI_RING(_trb) \ + ((struct xhci_ring*)((u32)(_trb) & ~(XHCI_RING_SIZE-1))) + +// -------------------------------------------------------------- +// bit definitions + +#define XHCI_CMD_RS (1<<0) +#define XHCI_CMD_HCRST (1<<1) +#define XHCI_CMD_INTE (1<<2) +#define XHCI_CMD_HSEE (1<<3) +#define XHCI_CMD_LHCRST (1<<7) +#define XHCI_CMD_CSS (1<<8) +#define XHCI_CMD_CRS (1<<9) +#define XHCI_CMD_EWE (1<<10) +#define XHCI_CMD_EU3S (1<<11) + +#define XHCI_STS_HCH (1<<0) +#define XHCI_STS_HSE (1<<2) +#define XHCI_STS_EINT (1<<3) +#define XHCI_STS_PCD (1<<4) +#define XHCI_STS_SSS (1<<8) +#define XHCI_STS_RSS (1<<9) +#define XHCI_STS_SRE (1<<10) +#define XHCI_STS_CNR (1<<11) +#define XHCI_STS_HCE (1<<12) + +#define XHCI_PORTSC_CCS (1<<0) +#define XHCI_PORTSC_PED (1<<1) +#define XHCI_PORTSC_OCA (1<<3) +#define XHCI_PORTSC_PR (1<<4) +#define XHCI_PORTSC_PLS_SHIFT 5 +#define XHCI_PORTSC_PLS_MASK 0xf +#define XHCI_PORTSC_PP (1<<9) +#define XHCI_PORTSC_SPEED_SHIFT 10 +#define XHCI_PORTSC_SPEED_MASK 0xf +#define XHCI_PORTSC_SPEED_FULL (1<<10) +#define XHCI_PORTSC_SPEED_LOW (2<<10) +#define XHCI_PORTSC_SPEED_HIGH (3<<10) +#define XHCI_PORTSC_SPEED_SUPER (4<<10) +#define XHCI_PORTSC_PIC_SHIFT 14 +#define XHCI_PORTSC_PIC_MASK 0x3 +#define XHCI_PORTSC_LWS (1<<16) +#define XHCI_PORTSC_CSC (1<<17) +#define XHCI_PORTSC_PEC (1<<18) +#define XHCI_PORTSC_WRC (1<<19) +#define XHCI_PORTSC_OCC (1<<20) +#define XHCI_PORTSC_PRC (1<<21) +#define XHCI_PORTSC_PLC (1<<22) +#define XHCI_PORTSC_CEC (1<<23) +#define XHCI_PORTSC_CAS (1<<24) +#define XHCI_PORTSC_WCE (1<<25) +#define XHCI_PORTSC_WDE (1<<26) +#define XHCI_PORTSC_WOE (1<<27) +#define XHCI_PORTSC_DR (1<<30) +#define XHCI_PORTSC_WPR (1<<31) + +#define TRB_C (1<<0) +#define TRB_TYPE_SHIFT 10 +#define TRB_TYPE_MASK 0x3f +#define TRB_TYPE(t) (((t) >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) + +#define TRB_EV_ED (1<<2) + +#define TRB_TR_ENT (1<<1) +#define TRB_TR_ISP (1<<2) +#define TRB_TR_NS (1<<3) +#define TRB_TR_CH (1<<4) +#define TRB_TR_IOC (1<<5) +#define TRB_TR_IDT (1<<6) +#define TRB_TR_TBC_SHIFT 7 +#define TRB_TR_TBC_MASK 0x3 +#define TRB_TR_BEI (1<<9) +#define TRB_TR_TLBPC_SHIFT 16 +#define TRB_TR_TLBPC_MASK 0xf +#define TRB_TR_FRAMEID_SHIFT 20 +#define TRB_TR_FRAMEID_MASK 0x7ff +#define TRB_TR_SIA (1<<31) + +#define TRB_TR_DIR (1<<16) + +#define TRB_CR_SLOTID_SHIFT 24 +#define TRB_CR_SLOTID_MASK 0xff +#define TRB_CR_EPID_SHIFT 16 +#define TRB_CR_EPID_MASK 0x1f + +#define TRB_CR_BSR (1<<9) +#define TRB_CR_DC (1<<9) + +#define TRB_LK_TC (1<<1) + +#define TRB_INTR_SHIFT 22 +#define TRB_INTR_MASK 0x3ff +#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) + +typedef enum TRBType { + TRB_RESERVED = 0, + TR_NORMAL, + TR_SETUP, + TR_DATA, + TR_STATUS, + TR_ISOCH, + TR_LINK, + TR_EVDATA, + TR_NOOP, + CR_ENABLE_SLOT, + CR_DISABLE_SLOT, + CR_ADDRESS_DEVICE, + CR_CONFIGURE_ENDPOINT, + CR_EVALUATE_CONTEXT, + CR_RESET_ENDPOINT, + CR_STOP_ENDPOINT, + CR_SET_TR_DEQUEUE, + CR_RESET_DEVICE, + CR_FORCE_EVENT, + CR_NEGOTIATE_BW, + CR_SET_LATENCY_TOLERANCE, + CR_GET_PORT_BANDWIDTH, + CR_FORCE_HEADER, + CR_NOOP, + ER_TRANSFER = 32, + ER_COMMAND_COMPLETE, + ER_PORT_STATUS_CHANGE, + ER_BANDWIDTH_REQUEST, + ER_DOORBELL, + ER_HOST_CONTROLLER, + ER_DEVICE_NOTIFICATION, + ER_MFINDEX_WRAP, +} TRBType; + +typedef enum TRBCCode { + CC_INVALID = 0, + CC_SUCCESS, + CC_DATA_BUFFER_ERROR, + CC_BABBLE_DETECTED, + CC_USB_TRANSACTION_ERROR, + CC_TRB_ERROR, + CC_STALL_ERROR, + CC_RESOURCE_ERROR, + CC_BANDWIDTH_ERROR, + CC_NO_SLOTS_ERROR, + CC_INVALID_STREAM_TYPE_ERROR, + CC_SLOT_NOT_ENABLED_ERROR, + CC_EP_NOT_ENABLED_ERROR, + CC_SHORT_PACKET, + CC_RING_UNDERRUN, + CC_RING_OVERRUN, + CC_VF_ER_FULL, + CC_PARAMETER_ERROR, + CC_BANDWIDTH_OVERRUN, + CC_CONTEXT_STATE_ERROR, + CC_NO_PING_RESPONSE_ERROR, + CC_EVENT_RING_FULL_ERROR, + CC_INCOMPATIBLE_DEVICE_ERROR, + CC_MISSED_SERVICE_ERROR, + CC_COMMAND_RING_STOPPED, + CC_COMMAND_ABORTED, + CC_STOPPED, + CC_STOPPED_LENGTH_INVALID, + CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, + CC_ISOCH_BUFFER_OVERRUN = 31, + CC_EVENT_LOST_ERROR, + CC_UNDEFINED_ERROR, + CC_INVALID_STREAM_ID_ERROR, + CC_SECONDARY_BANDWIDTH_ERROR, + CC_SPLIT_TRANSACTION_ERROR +} TRBCCode; + +enum { + PLS_U0 = 0, + PLS_U1 = 1, + PLS_U2 = 2, + PLS_U3 = 3, + PLS_DISABLED = 4, + PLS_RX_DETECT = 5, + PLS_INACTIVE = 6, + PLS_POLLING = 7, + PLS_RECOVERY = 8, + PLS_HOT_RESET = 9, + PLS_COMPILANCE_MODE = 10, + PLS_TEST_MODE = 11, + PLS_RESUME = 15, +}; + +#define xhci_get_field(data, field) \ + (((data) >> field##_SHIFT) & field##_MASK) + +// -------------------------------------------------------------- +// state structs + +struct xhci_ring { + struct xhci_trb ring[XHCI_RING_ITEMS]; + struct xhci_trb evt; + u32 eidx; + u32 nidx; + u32 cs; + struct mutex_s lock; +}; + +struct usb_xhci_s { + struct usb_s usb; + struct usbhub_s hub; + + /* devinfo */ + u32 baseaddr; + u32 xcap; + u32 ports; + u32 slots; + + /* xhci registers */ + struct xhci_caps *caps; + struct xhci_op *op; + struct xhci_pr *pr; + struct xhci_ir *ir; + struct xhci_db *db; + + /* xhci data structures */ + struct xhci_devlist *devs; + struct xhci_ring *cmds; + struct xhci_ring *evts; + struct xhci_er_seg *eseg; + + /* usb devices */ + struct hlist_head list; +}; + +struct xhci_device { + struct xhci_devctx devctx; + struct xhci_inctx inctx; + + struct usbdevice_s *usbdev; + struct usb_xhci_s *xhci; + u32 slotid; + struct hlist_node next; +}; + +struct xhci_pipe { + struct xhci_ring reqs; + + struct usb_pipe pipe; + struct xhci_device *dev; + u32 epid; + void *buf; + int bufused; +}; + +// -------------------------------------------------------------- +// tables + +static const char *speed_name[16] = { + [ 0 ] = " - ", + [ 1 ] = "Full", + [ 2 ] = "Low", + [ 3 ] = "High", + [ 4 ] = "Super", +}; + +static const int speed_from_xhci[16] = { + [ 0 ] = -1, + [ 1 ] = USB_FULLSPEED, + [ 2 ] = USB_LOWSPEED, + [ 3 ] = USB_HIGHSPEED, + [ 4 ] = USB_SUPERSPEED, + [ 5 ... 15 ] = -1, +}; + +static const int speed_to_xhci[] = { + [ USB_FULLSPEED ] = 1, + [ USB_LOWSPEED ] = 2, + [ USB_HIGHSPEED ] = 3, + [ USB_SUPERSPEED ] = 4, +}; + +static const int speed_to_ctlsize[] = { + [ USB_FULLSPEED ] = 8, + [ USB_LOWSPEED ] = 8, + [ USB_HIGHSPEED ] = 64, + [ USB_SUPERSPEED ] = 256, +}; + +static const int eptype_to_xhci_in[] = { + [ USB_ENDPOINT_XFER_CONTROL] = 4, + [ USB_ENDPOINT_XFER_ISOC ] = 5, + [ USB_ENDPOINT_XFER_BULK ] = 6, + [ USB_ENDPOINT_XFER_INT ] = 7, +}; + +static const int eptype_to_xhci_out[] = { + [ USB_ENDPOINT_XFER_CONTROL] = 4, + [ USB_ENDPOINT_XFER_ISOC ] = 1, + [ USB_ENDPOINT_XFER_BULK ] = 2, + [ USB_ENDPOINT_XFER_INT ] = 3, +}; + +// -------------------------------------------------------------- +// internal functions, 16bit + 32bit + +static void xhci_doorbell(struct usb_xhci_s *xhci, u32 slotid, u32 value) +{ + struct xhci_db *db = GET_LOWFLAT(xhci->db); + u32 addr = (u32)(&db[slotid].doorbell); + pci_writel(addr, value); +} + +static void xhci_process_events(struct usb_xhci_s *xhci) +{ + struct xhci_ring *evts = GET_LOWFLAT(xhci->evts); + + for (;;) { + /* check for event */ + u32 nidx = GET_LOWFLAT(evts->nidx); + u32 cs = GET_LOWFLAT(evts->cs); + struct xhci_trb *etrb = evts->ring + nidx; + u32 control = GET_LOWFLAT(etrb->control); + if ((control & TRB_C) != (cs ? 1 : 0)) + return; + + /* process event */ + u32 evt_type = TRB_TYPE(control); + u32 evt_cc = (GET_LOWFLAT(etrb->status) >> 24) & 0xff; + switch (evt_type) { + case ER_TRANSFER: + case ER_COMMAND_COMPLETE: + { + struct xhci_trb *rtrb = (void*)GET_LOWFLAT(etrb->ptr_low); + struct xhci_ring *ring = XHCI_RING(rtrb); + struct xhci_trb *evt = &ring->evt; + u32 eidx = rtrb - ring->ring + 1; + dprintf(5, "%s: ring %p [trb %p, evt %p, type %d, eidx %d, cc %d]\n", + __func__, ring, rtrb, evt, evt_type, eidx, evt_cc); + memcpy_fl(evt, etrb, sizeof(*etrb)); + SET_LOWFLAT(ring->eidx, eidx); + break; + } + case ER_PORT_STATUS_CHANGE: + { + u32 portid = (GET_LOWFLAT(etrb->ptr_low) >> 24) & 0xff; + dprintf(3, "%s: status change port #%d\n", + __func__, portid); + break; + } + default: + dprintf(1, "%s: unknown event, type %d, cc %d\n", + __func__, evt_type, evt_cc); + break; + } + + /* move ring index, notify xhci */ + nidx++; + if (nidx == XHCI_RING_ITEMS) { + nidx = 0; + cs = cs ? 0 : 1; + SET_LOWFLAT(evts->cs, cs); + } + SET_LOWFLAT(evts->nidx, nidx); + struct xhci_ir *ir = GET_LOWFLAT(xhci->ir); + u32 addr = (u32)(&ir->erdp_low); + u32 erdp = (u32)(evts->ring + nidx); + pci_writel(addr, erdp); + } +} + +static int xhci_ring_busy(struct xhci_ring *ring) +{ + u32 eidx = GET_LOWFLAT(ring->eidx); + u32 nidx = GET_LOWFLAT(ring->nidx); + return (eidx != nidx); +} + +static int xhci_event_wait(struct usb_xhci_s *xhci, + struct xhci_ring *ring, + u32 timeout) +{ + u32 end = timer_calc(timeout); + + for (;;) { + xhci_process_events(xhci); + if (!xhci_ring_busy(ring)) { + u32 status = GET_LOWFLAT(ring->evt.status); + return (status >> 24) & 0xff; + } + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } +} + +static void xhci_trb_queue(struct xhci_ring *ring, + struct xhci_trb *trb) +{ + u32 nidx = GET_LOWFLAT(ring->nidx); + u32 cs = GET_LOWFLAT(ring->cs); + struct xhci_trb *dst; + u32 control; + + if (nidx == XHCI_RING_ITEMS-1) { + dst = ring->ring + nidx; + control = (TR_LINK << 10); // trb type + control |= TRB_LK_TC; + control |= (cs ? TRB_C : 0); + SET_LOWFLAT(dst->ptr_low, (u32)&ring[0]); + SET_LOWFLAT(dst->ptr_high, 0); + SET_LOWFLAT(dst->status, 0); + SET_LOWFLAT(dst->control, control); + nidx = 0; + cs = cs ? 0 : 1; + SET_LOWFLAT(ring->nidx, nidx); + SET_LOWFLAT(ring->cs, cs); + + dprintf(5, "%s: ring %p [linked]\n", __func__, ring); + } + + dst = ring->ring + nidx; + control = GET_LOWFLAT(trb->control) | (cs ? TRB_C : 0); + + SET_LOWFLAT(dst->ptr_low, GET_LOWFLAT(trb->ptr_low)); + SET_LOWFLAT(dst->ptr_high, GET_LOWFLAT(trb->ptr_high)); + SET_LOWFLAT(dst->status, GET_LOWFLAT(trb->status)); + SET_LOWFLAT(dst->control, control); + nidx++; + SET_LOWFLAT(ring->nidx, nidx); + + dprintf(5, "%s: ring %p [nidx %d, len %d]\n", + __func__, ring, nidx, + GET_LOWFLAT(trb->status) & 0xffff); +} + +static void xhci_xfer_queue(struct xhci_pipe *pipe, + struct xhci_trb *trb) +{ + xhci_trb_queue(&pipe->reqs, trb); +} + +static void xhci_xfer_kick(struct xhci_pipe *pipe) +{ + struct xhci_device *dev = GET_LOWFLAT(pipe->dev); + struct usb_xhci_s *xhci = GET_LOWFLAT(dev->xhci); + u32 slotid = GET_LOWFLAT(dev->slotid); + u32 epid = GET_LOWFLAT(pipe->epid); + + dprintf(5, "%s: ring %p, slotid %d, epid %d\n", + __func__, &pipe->reqs, slotid, epid); + xhci_doorbell(xhci, slotid, epid); +} + +static void xhci_xfer_normal(struct xhci_pipe *pipe, + void *data, int datalen) +{ + struct xhci_trb trb; + + memset(&trb, 0, sizeof(trb)); + trb.ptr_low = (u32)data; + trb.status = datalen; + trb.control |= (TR_NORMAL << 10); // trb type + trb.control |= TRB_TR_IOC; + + xhci_xfer_queue(pipe, MAKE_FLATPTR(GET_SEG(SS), &trb)); + xhci_xfer_kick(pipe); +} + +// -------------------------------------------------------------- +// internal functions, pure 32bit + +static int wait_bit(u32 *reg, u32 mask, int value, u32 timeout) +{ + ASSERT32FLAT(); + u32 end = timer_calc(timeout); + + while ((readl(reg) & mask) != value) { + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } + return 0; +} + +static int xhci_cmd_submit(struct usb_xhci_s *xhci, + struct xhci_trb *cmd) +{ + ASSERT32FLAT(); + int rc; + + mutex_lock(&xhci->cmds->lock); + xhci_trb_queue(xhci->cmds, cmd); + xhci_doorbell(xhci, 0, 0); + rc = xhci_event_wait(xhci, xhci->cmds, 1000); + mutex_unlock(&xhci->cmds->lock); + return rc; +} + +static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci) +{ + ASSERT32FLAT(); + struct xhci_trb cmd = { + .ptr_low = 0, + .ptr_high = 0, + .status = 0, + .control = (CR_ENABLE_SLOT << 10) + }; + dprintf(3, "%s:\n", __func__); + int cc = xhci_cmd_submit(xhci, &cmd); + if (cc != CC_SUCCESS) + return -1; + return (xhci->cmds->evt.control >> 24) & 0xff; +} + +static int xhci_cmd_disable_slot(struct xhci_device *dev) +{ + ASSERT32FLAT(); + struct xhci_trb cmd = { + .ptr_low = 0, + .ptr_high = 0, + .status = 0, + .control = (dev->slotid << 24) | (CR_DISABLE_SLOT << 10) + }; + dprintf(3, "%s: slotid %d\n", __func__, dev->slotid); + return xhci_cmd_submit(dev->xhci, &cmd); +} + +static int xhci_cmd_address_device(struct xhci_device *dev) +{ + ASSERT32FLAT(); + struct xhci_trb cmd = { + .ptr_low = (u32)&dev->inctx, + .ptr_high = 0, + .status = 0, + .control = (dev->slotid << 24) | (CR_ADDRESS_DEVICE << 10) + }; + dprintf(3, "%s: slotid %d\n", __func__, dev->slotid); + return xhci_cmd_submit(dev->xhci, &cmd); +} + +static int xhci_cmd_configure_endpoint(struct xhci_device *dev) +{ + ASSERT32FLAT(); + struct xhci_trb cmd = { + .ptr_low = (u32)&dev->inctx, + .ptr_high = 0, + .status = 0, + .control = (dev->slotid << 24) | (CR_CONFIGURE_ENDPOINT << 10) + }; + dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__, + dev->slotid, dev->inctx.add, dev->inctx.del); + return xhci_cmd_submit(dev->xhci, &cmd); +} + +static int xhci_cmd_evaluate_context(struct xhci_device *dev) +{ + ASSERT32FLAT(); + struct xhci_trb cmd = { + .ptr_low = (u32)&dev->inctx, + .ptr_high = 0, + .status = 0, + .control = (dev->slotid << 24) | (CR_EVALUATE_CONTEXT << 10) + }; + dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__, + dev->slotid, dev->inctx.add, dev->inctx.del); + return xhci_cmd_submit(dev->xhci, &cmd); +} + +static void xhci_xfer_setup(struct xhci_pipe *pipe, + const struct usb_ctrlrequest *req, + int dir, int datalen) +{ + ASSERT32FLAT(); + struct xhci_trb trb; + + memset(&trb, 0, sizeof(trb)); + trb.ptr_low |= req->bRequestType; + trb.ptr_low |= (req->bRequest) << 8; + trb.ptr_low |= (req->wValue) << 16; + trb.ptr_high |= req->wIndex; + trb.ptr_high |= (req->wLength) << 16; + trb.status |= 8; // length + trb.control |= (TR_SETUP << 10); // trb type + trb.control |= TRB_TR_IDT; + if (datalen) + trb.control |= (dir ? 3 : 2) << 16; // transfer type + xhci_xfer_queue(pipe, &trb); +} + +static void xhci_xfer_data(struct xhci_pipe *pipe, + int dir, void *data, int datalen) +{ + ASSERT32FLAT(); + struct xhci_trb trb; + + memset(&trb, 0, sizeof(trb)); + trb.ptr_low = (u32)data; + trb.status = datalen; + trb.control |= (TR_DATA << 10); // trb type + if (dir) + trb.control |= (1 << 16); + xhci_xfer_queue(pipe, &trb); +} + +static void xhci_xfer_status(struct xhci_pipe *pipe, int dir) +{ + ASSERT32FLAT(); + struct xhci_trb trb; + + memset(&trb, 0, sizeof(trb)); + trb.control |= (TR_STATUS << 10); // trb type + trb.control |= TRB_TR_IOC; + if (dir) + trb.control |= (1 << 16); + + xhci_xfer_queue(pipe, &trb); + xhci_xfer_kick(pipe); +} + +static struct xhci_device *xhci_find_alloc_device(struct usb_xhci_s *xhci, + struct usbdevice_s *usbdev) +{ + ASSERT32FLAT(); + struct xhci_device *dev; + + hlist_for_each_entry(dev, &xhci->list, next) { + if (dev->usbdev == usbdev) { + return dev; + } + } + + dev = memalign_low(64, sizeof(*dev)); + if (!dev) { + warn_noalloc(); + return NULL; + } + memset(dev, 0, sizeof(*dev)); + dev->usbdev = usbdev; + dev->xhci = xhci; + hlist_add_head(&dev->next, &xhci->list); + return dev; +} + +static void +configure_xhci(void *data) +{ + ASSERT32FLAT(); + struct usb_xhci_s *xhci = data; + u32 reg; + + xhci->devs = memalign_high(64, sizeof(*xhci->devs) * (xhci->slots + 1)); + xhci->eseg = memalign_high(64, sizeof(*xhci->eseg)); + xhci->cmds = memalign_high(XHCI_RING_SIZE, sizeof(*xhci->cmds)); + xhci->evts = memalign_low(XHCI_RING_SIZE, sizeof(*xhci->evts)); + if (!xhci->devs || !xhci->cmds || !xhci->evts || !xhci->eseg) { + warn_noalloc(); + goto fail; + } + memset(xhci->devs, 0, sizeof(*xhci->devs) * (xhci->slots + 1)); + memset(xhci->cmds, 0, sizeof(*xhci->cmds)); + memset(xhci->evts, 0, sizeof(*xhci->evts)); + memset(xhci->eseg, 0, sizeof(*xhci->eseg)); + + reg = readl(&xhci->op->usbcmd); + if (reg & XHCI_CMD_RS) { + reg &= ~XHCI_CMD_RS; + writel(&xhci->op->usbcmd, reg); + if (wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32) != 0) + goto fail; + } + + dprintf(3, "%s: resetting\n", __func__); + writel(&xhci->op->usbcmd, XHCI_CMD_HCRST); + if (wait_bit(&xhci->op->usbcmd, XHCI_CMD_HCRST, 0, 100) != 0) + goto fail; + if (wait_bit(&xhci->op->usbsts, XHCI_STS_CNR, 0, 100) != 0) + goto fail; + + writel(&xhci->op->config, xhci->slots); + writel(&xhci->op->dcbaap_low, (u32)xhci->devs); + writel(&xhci->op->dcbaap_high, 0); + writel(&xhci->op->crcr_low, (u32)xhci->cmds | 1); + writel(&xhci->op->crcr_high, 0); + xhci->cmds->cs = 1; + + xhci->eseg->ptr_low = (u32)xhci->evts; + xhci->eseg->ptr_high = 0; + xhci->eseg->size = XHCI_RING_ITEMS; + writel(&xhci->ir->erstsz, 1); + writel(&xhci->ir->erdp_low, (u32)xhci->evts); + writel(&xhci->ir->erdp_high, 0); + writel(&xhci->ir->erstba_low, (u32)xhci->eseg); + writel(&xhci->ir->erstba_high, 0); + xhci->evts->cs = 1; + + reg = readl(&xhci->op->usbcmd); + reg |= XHCI_CMD_RS; + writel(&xhci->op->usbcmd, reg); + + // FIXME: try find a more elegant way than a fixed delay + mdelay(100); + + usb_enumerate(&xhci->hub); + if (xhci->hub.devcount) + return; + + // No devices found - shutdown and free controller. + dprintf(1, "XHCI no devices found\n"); + reg = readl(&xhci->op->usbcmd); + reg &= ~XHCI_CMD_RS; + writel(&xhci->op->usbcmd, reg); + wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32); + +fail: + free(xhci->eseg); + free(xhci->evts); + free(xhci->cmds); + free(xhci->devs); + free(xhci); +} + +// -------------------------------------------------------------- +// xhci root hub + +// Check if device attached to port +static void +xhci_print_port_state(int loglevel, const char *prefix, u32 port, u32 portsc) +{ + ASSERT32FLAT(); + u32 pls = xhci_get_field(portsc, XHCI_PORTSC_PLS); + u32 speed = xhci_get_field(portsc, XHCI_PORTSC_SPEED); + + dprintf(loglevel, "%s port #%d: 0x%08x,%s%s pls %d, speed %d [%s]\n", + prefix, port + 1, portsc, + (portsc & XHCI_PORTSC_PP) ? " powered," : "", + (portsc & XHCI_PORTSC_PED) ? " enabled," : "", + pls, speed, speed_name[speed]); +} + +static int +xhci_hub_detect(struct usbhub_s *hub, u32 port) +{ + ASSERT32FLAT(); + struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); + u32 portsc = readl(&xhci->pr[port].portsc); + + xhci_print_port_state(3, __func__, port, portsc); + switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) { + case PLS_U0: + case PLS_POLLING: + return 0; + default: + return -1; + } +} + +// Reset device on port +static int +xhci_hub_reset(struct usbhub_s *hub, u32 port) +{ + ASSERT32FLAT(); + struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); + u32 portsc = readl(&xhci->pr[port].portsc); + int rc; + + switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) { + case PLS_U0: + rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)]; + break; + case PLS_POLLING: + xhci_print_port_state(3, __func__, port, portsc); + portsc |= XHCI_PORTSC_PR; + writel(&xhci->pr[port].portsc, portsc); + if (wait_bit(&xhci->pr[port].portsc, XHCI_PORTSC_PED, XHCI_PORTSC_PED, 100) != 0) + return -1; + portsc = readl(&xhci->pr[port].portsc); + rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)]; + break; + default: + rc = -1; + break; + } + + xhci_print_port_state(1, "XHCI", port, portsc); + return rc; +} + +static void +xhci_hub_disconnect(struct usbhub_s *hub, u32 port) +{ + ASSERT32FLAT(); + struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); + struct xhci_device *dev; + + hlist_for_each_entry(dev, &xhci->list, next) { + if (dev->usbdev->hub == hub && + dev->usbdev->port == port && + dev->slotid != 0) { + xhci_cmd_disable_slot(dev); + hlist_del(&dev->next); + return; + } + } +} + +static struct usbhub_op_s xhci_hub_ops = { + .detect = xhci_hub_detect, + .reset = xhci_hub_reset, + .disconnect = xhci_hub_disconnect, +}; + +// -------------------------------------------------------------- +// external interface + +struct usb_pipe * +xhci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + ASSERT32FLAT(); + if (!CONFIG_USB_XHCI) + return NULL; + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + struct usb_xhci_s *xhci = container_of( + usbdev->hub->cntl, struct usb_xhci_s, usb); + struct xhci_pipe *pipe; + u32 epid; + + if (epdesc->bEndpointAddress == 0) { + epid = 1; + } else { + epid = (epdesc->bEndpointAddress & 0x0f) * 2; + epid += (epdesc->bEndpointAddress & USB_DIR_IN) ? 1 : 0; + } + + if (eptype == USB_ENDPOINT_XFER_CONTROL) + pipe = memalign_high(XHCI_RING_SIZE, sizeof(*pipe)); + else + pipe = memalign_low(XHCI_RING_SIZE, sizeof(*pipe)); + if (!pipe) { + warn_noalloc(); + return NULL; + } + memset(pipe, 0, sizeof(*pipe)); + + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + pipe->dev = xhci_find_alloc_device(xhci, usbdev); + if (!pipe->dev) { + free(pipe); + return NULL; + } + pipe->epid = epid; + pipe->reqs.cs = 1; + if (eptype == USB_ENDPOINT_XFER_INT) + pipe->buf = malloc_low(pipe->pipe.maxpacket); + + dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__, + usbdev, &pipe->reqs, pipe->dev->slotid, pipe->epid); + if (pipe->epid > 1 && pipe->dev->slotid) { + struct xhci_inctx *in = &pipe->dev->inctx; + in->add = (1 << pipe->epid) | 1; + in->del = 0; + + in->slot.ctx[0] |= (31 << 27); // context entries + + int e = pipe->epid-1; + in->ep[e].ctx[1] |= (eptype << 3); + if (epdesc->bEndpointAddress & USB_DIR_IN) + in->ep[e].ctx[1] |= (1 << 5); + in->ep[e].ctx[1] |= (pipe->pipe.maxpacket << 16); + in->ep[e].deq_low = (u32)&pipe->reqs.ring[0]; + in->ep[e].deq_low |= 1; // dcs + in->ep[e].deq_high = 0; + in->ep[e].length = pipe->pipe.maxpacket; + + int cc = xhci_cmd_configure_endpoint(pipe->dev); + if (cc != CC_SUCCESS) { + dprintf(1, "%s: configure endpoint: failed (cc %d)\n", __func__, cc); + free(pipe); + return NULL; + } + } + + return &pipe->pipe; +} + +struct usb_pipe * +xhci_update_pipe(struct usbdevice_s *usbdev, struct usb_pipe *upipe + , struct usb_endpoint_descriptor *epdesc) +{ + ASSERT32FLAT(); + if (!CONFIG_USB_XHCI) + return NULL; + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + struct xhci_pipe *pipe = container_of(upipe, struct xhci_pipe, pipe); + dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__, + usbdev, &pipe->reqs, pipe->dev->slotid, pipe->epid); + if (eptype == USB_ENDPOINT_XFER_CONTROL && + pipe->pipe.maxpacket != epdesc->wMaxPacketSize) { + dprintf(1, "%s: reconf ctl endpoint pkt size: %d -> %d\n", + __func__, pipe->pipe.maxpacket, epdesc->wMaxPacketSize); + pipe->pipe.maxpacket = epdesc->wMaxPacketSize; + struct xhci_inctx *in = &pipe->dev->inctx; + in->add = (1 << 1); + in->del = 0; + in->ep[0].ctx[1] &= 0xffff; + in->ep[0].ctx[1] |= (pipe->pipe.maxpacket << 16); + int cc = xhci_cmd_evaluate_context(pipe->dev); + if (cc != CC_SUCCESS) { + dprintf(1, "%s: reconf ctl endpoint: failed (cc %d)\n", + __func__, cc); + } + } + return upipe; +} + +int +xhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datalen) +{ + ASSERT32FLAT(); + if (!CONFIG_USB_XHCI) + return -1; + const struct usb_ctrlrequest *req = cmd; + struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe); + struct usb_xhci_s *xhci = pipe->dev->xhci; + int cc; + + if (req->bRequest == USB_REQ_SET_ADDRESS) { + int slotid = xhci_cmd_enable_slot(xhci); + if (slotid < 0) { + dprintf(1, "%s: enable slot: failed\n", __func__); + return -1; + } + dprintf(3, "%s: enable slot: got slotid %d\n", __func__, slotid); + pipe->dev->slotid = slotid; + xhci->devs[slotid].ptr_low = (u32)&pipe->dev->devctx; + xhci->devs[slotid].ptr_high = 0; + + struct usbdevice_s *usbdev = pipe->dev->usbdev; + u32 route = 0; + while (usbdev->hub->usbdev) { + route <<= 4; + route |= (usbdev->port+1) & 0xf; + usbdev = usbdev->hub->usbdev; + } + dprintf(3, "%s: root port %d, route 0x%x\n", + __func__, usbdev->port+1, route); + + struct xhci_inctx *in = &pipe->dev->inctx; + in->add = 0x03; + in->slot.ctx[0] |= (1 << 27); // context entries + in->slot.ctx[0] |= speed_to_xhci[pipe->dev->usbdev->speed] << 20; + in->slot.ctx[0] |= route; + in->slot.ctx[1] |= (usbdev->port+1) << 16; + /* TODO ctx0: hub bit */ + /* TODO ctx1: hub ports */ + + in->ep[0].ctx[0] |= (3 << 16); // interval: 1ms + in->ep[0].ctx[1] |= (4 << 3); // control pipe + in->ep[0].ctx[1] |= (speed_to_ctlsize[pipe->dev->usbdev->speed] << 16); + + in->ep[0].deq_low = (u32)&pipe->reqs.ring[0]; + in->ep[0].deq_low |= 1; // dcs + in->ep[0].deq_high = 0; + in->ep[0].length = 8; + + cc = xhci_cmd_address_device(pipe->dev); + if (cc != CC_SUCCESS) { + dprintf(1, "%s: address device: failed (cc %d)\n", __func__, cc); + return -1; + } + return 0; + } + + xhci_xfer_setup(pipe, req, dir, datalen); + if (datalen) + xhci_xfer_data(pipe, dir, data, datalen); + xhci_xfer_status(pipe, dir); + + cc = xhci_event_wait(xhci, &pipe->reqs, 1000); + if (cc != CC_SUCCESS) { + dprintf(1, "%s: control xfer failed (cc %d)\n", __func__, cc); + return -1; + } + + return 0; +} + +int +xhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datalen) +{ + if (!CONFIG_USB_XHCI) + return -1; + + struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe); + struct xhci_device *dev = GET_LOWFLAT(pipe->dev); + struct usb_xhci_s *xhci = GET_LOWFLAT(dev->xhci); + + xhci_xfer_normal(pipe, data, datalen); + int cc = xhci_event_wait(xhci, &pipe->reqs, 1000); + if (cc != CC_SUCCESS) { + dprintf(1, "%s: bulk xfer failed (cc %d)\n", __func__, cc); + return -1; + } + return 0; +} + +int +xhci_poll_intr(struct usb_pipe *p, void *data) +{ + if (!CONFIG_USB_XHCI) + return -1; + + struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe); + struct xhci_device *dev = GET_LOWFLAT(pipe->dev); + struct usb_xhci_s *xhci = GET_LOWFLAT(dev->xhci); + u32 len = GET_LOWFLAT(pipe->pipe.maxpacket); + void *buf = GET_LOWFLAT(pipe->buf); + int bufused = GET_LOWFLAT(pipe->bufused); + + if (!bufused) { + xhci_xfer_normal(pipe, buf, len); + bufused = 1; + SET_LOWFLAT(pipe->bufused, bufused); + return -1; + } + + xhci_process_events(xhci); + if (xhci_ring_busy(&pipe->reqs)) + return -1; + dprintf(5, "%s: st %x ct %x [ %p <= %p / %d ]\n", __func__, + GET_LOWFLAT(pipe->reqs.evt.status), + GET_LOWFLAT(pipe->reqs.evt.control), + MAKE_FLATPTR(GET_SEG(SS), data), buf, len); + memcpy_fl(MAKE_FLATPTR(GET_SEG(SS), data), buf, len); + xhci_xfer_normal(pipe, buf, len); + return 0; +} + +int +xhci_setup(struct pci_device *pci, int busid) +{ + ASSERT32FLAT(); + if (!CONFIG_USB_XHCI) + return -1; + + struct usb_xhci_s *xhci = malloc_low(sizeof(*xhci)); + if (!xhci) { + warn_noalloc(); + return -1; + } + memset(xhci, 0, sizeof(*xhci)); + + xhci->baseaddr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) + & PCI_BASE_ADDRESS_MEM_MASK; + xhci->caps = (void*)(xhci->baseaddr); + xhci->op = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength)); + xhci->pr = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength) + 0x400); + xhci->db = (void*)(xhci->baseaddr + readl(&xhci->caps->dboff)); + xhci->ir = (void*)(xhci->baseaddr + readl(&xhci->caps->rtsoff) + 0x20); + + u32 hcs1 = readl(&xhci->caps->hcsparams1); + u32 hcc = readl(&xhci->caps->hccparams); + xhci->ports = (hcs1 >> 24) & 0xff; + xhci->slots = hcs1 & 0xff; + xhci->xcap = ((hcc >> 16) & 0xffff) << 2; + + xhci->usb.busid = busid; + xhci->usb.pci = pci; + xhci->usb.type = USB_TYPE_XHCI; + xhci->hub.cntl = &xhci->usb; + xhci->hub.portcount = xhci->ports; + xhci->hub.op = &xhci_hub_ops; + + dprintf(1, "XHCI init on dev %02x:%02x.%x: regs @ %p, %d ports, %d slots\n" + , pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf) + , pci_bdf_to_fn(pci->bdf), xhci->caps + , xhci->ports, xhci->slots); + + if (xhci->xcap) { + u32 off, addr = xhci->baseaddr + xhci->xcap; + do { + struct xhci_xcap *xcap = (void*)addr; + u32 ports, name, cap = readl(&xcap->cap); + switch (cap & 0xff) { + case 0x02: + name = readl(&xcap->data[0]); + ports = readl(&xcap->data[1]); + dprintf(1, "XHCI protocol %c%c%c%c %x.%02x, %d ports (offset %d)\n" + , (name >> 0) & 0xff + , (name >> 8) & 0xff + , (name >> 16) & 0xff + , (name >> 24) & 0xff + , (cap >> 24) & 0xff + , (cap >> 16) & 0xff + , (ports >> 8) & 0xff + , (ports >> 0) & 0xff); + break; + default: + dprintf(1, "XHCI extcap 0x%x @ %x\n", cap & 0xff, addr); + break; + } + off = (cap >> 8) & 0xff; + addr += off << 2; + } while (off > 0); + } + + pci_config_maskw(pci->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + + run_thread(configure_xhci, xhci); + return 0; +} diff -Nru seabios-1.7.1/src/hw/usb-xhci.h seabios-1.7.4/src/hw/usb-xhci.h --- seabios-1.7.1/src/hw/usb-xhci.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/usb-xhci.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,144 @@ +#ifndef __USB_XHCI_H +#define __USB_XHCI_H + +struct usbdevice_s; +struct usb_endpoint_descriptor; +struct usb_pipe; + +// -------------------------------------------------------------- + +// usb-xhci.c +int xhci_setup(struct pci_device *pci, int busid); +struct usb_pipe *xhci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe *xhci_update_pipe(struct usbdevice_s *usbdev + , struct usb_pipe *pipe + , struct usb_endpoint_descriptor *epdesc); +int xhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize + , void *data, int datasize); +int xhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); +int xhci_poll_intr(struct usb_pipe *p, void *data); + +// -------------------------------------------------------------- +// register interface + +// capabilities +struct xhci_caps { + u8 caplength; + u8 reserved_01; + u16 hciversion; + u32 hcsparams1; + u32 hcsparams2; + u32 hcsparams3; + u32 hccparams; + u32 dboff; + u32 rtsoff; +} PACKED; + +// extended capabilities +struct xhci_xcap { + u32 cap; + u32 data[]; +} PACKED; + +// operational registers +struct xhci_op { + u32 usbcmd; + u32 usbsts; + u32 pagesize; + u32 reserved_01[2]; + u32 dnctl; + u32 crcr_low; + u32 crcr_high; + u32 reserved_02[4]; + u32 dcbaap_low; + u32 dcbaap_high; + u32 config; +} PACKED; + +// port registers +struct xhci_pr { + u32 portsc; + u32 portpmsc; + u32 portli; + u32 reserved_01; +} PACKED; + +// doorbell registers +struct xhci_db { + u32 doorbell; +} PACKED; + +// runtime registers +struct xhci_rts { + u32 mfindex; +} PACKED; + +// interrupter registers +struct xhci_ir { + u32 iman; + u32 imod; + u32 erstsz; + u32 reserved_01; + u32 erstba_low; + u32 erstba_high; + u32 erdp_low; + u32 erdp_high; +} PACKED; + +// -------------------------------------------------------------- +// memory data structs + +// slot context +struct xhci_slotctx { + u32 ctx[4]; + u32 reserved_01[4]; +} PACKED; + +// endpoint context +struct xhci_epctx { + u32 ctx[2]; + u32 deq_low; + u32 deq_high; + u32 length; + u32 reserved_01[3]; +} PACKED; + +// device context +struct xhci_devctx { + struct xhci_slotctx slot; + struct xhci_epctx ep[31]; +} PACKED; + +// device context array element +struct xhci_devlist { + u32 ptr_low; + u32 ptr_high; +} PACKED; + +// input context +struct xhci_inctx { + u32 del; + u32 add; + u32 reserved_01[6]; + struct xhci_slotctx slot; + struct xhci_epctx ep[31]; +} PACKED; + +// transfer block (ring element) +struct xhci_trb { + u32 ptr_low; + u32 ptr_high; + u32 status; + u32 control; +} PACKED; + +// event ring segment +struct xhci_er_seg { + u32 ptr_low; + u32 ptr_high; + u32 size; + u32 reserved_01; +} PACKED; + +#endif // usb-xhci.h diff -Nru seabios-1.7.1/src/hw/virtio-blk.c seabios-1.7.4/src/hw/virtio-blk.c --- seabios-1.7.1/src/hw/virtio-blk.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-blk.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,177 @@ +// Virtio block boot support. +// +// Copyright (C) 2010 Red Hat Inc. +// +// Authors: +// Gleb Natapov +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "config.h" // CONFIG_* +#include "block.h" // struct drive_s +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK +#include "pci_regs.h" // PCI_VENDOR_ID +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // usleep +#include "virtio-pci.h" +#include "virtio-ring.h" +#include "virtio-blk.h" + +struct virtiodrive_s { + struct drive_s drive; + struct vring_virtqueue *vq; + u16 ioaddr; +}; + +static int +virtio_blk_op(struct disk_op_s *op, int write) +{ + struct virtiodrive_s *vdrive_gf = + container_of(op->drive_gf, struct virtiodrive_s, drive); + struct vring_virtqueue *vq = GET_GLOBALFLAT(vdrive_gf->vq); + struct virtio_blk_outhdr hdr = { + .type = write ? VIRTIO_BLK_T_OUT : VIRTIO_BLK_T_IN, + .ioprio = 0, + .sector = op->lba, + }; + u8 status = VIRTIO_BLK_S_UNSUPP; + struct vring_list sg[] = { + { + .addr = MAKE_FLATPTR(GET_SEG(SS), &hdr), + .length = sizeof(hdr), + }, + { + .addr = op->buf_fl, + .length = GET_GLOBALFLAT(vdrive_gf->drive.blksize) * op->count, + }, + { + .addr = MAKE_FLATPTR(GET_SEG(SS), &status), + .length = sizeof(status), + }, + }; + + /* Add to virtqueue and kick host */ + if (write) + vring_add_buf(vq, sg, 2, 1, 0, 0); + else + vring_add_buf(vq, sg, 1, 2, 0, 0); + vring_kick(GET_GLOBALFLAT(vdrive_gf->ioaddr), vq, 1); + + /* Wait for reply */ + while (!vring_more_used(vq)) + usleep(5); + + /* Reclaim virtqueue element */ + vring_get_buf(vq, NULL); + + /* Clear interrupt status register. Avoid leaving interrupts stuck if + * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised. + */ + vp_get_isr(GET_GLOBALFLAT(vdrive_gf->ioaddr)); + + return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK; +} + +int +process_virtio_blk_op(struct disk_op_s *op) +{ + if (! CONFIG_VIRTIO_BLK) + return 0; + switch (op->command) { + case CMD_READ: + return virtio_blk_op(op, 0); + case CMD_WRITE: + return virtio_blk_op(op, 1); + case CMD_FORMAT: + case CMD_RESET: + case CMD_ISREADY: + case CMD_VERIFY: + case CMD_SEEK: + return DISK_RET_SUCCESS; + default: + op->count = 0; + return DISK_RET_EPARAM; + } +} + +static void +init_virtio_blk(struct pci_device *pci) +{ + u16 bdf = pci->bdf; + dprintf(1, "found virtio-blk at %x:%x\n", pci_bdf_to_bus(bdf), + pci_bdf_to_dev(bdf)); + struct virtiodrive_s *vdrive = malloc_fseg(sizeof(*vdrive)); + if (!vdrive) { + warn_noalloc(); + return; + } + memset(vdrive, 0, sizeof(*vdrive)); + vdrive->drive.type = DTYPE_VIRTIO_BLK; + vdrive->drive.cntl_id = bdf; + + u16 ioaddr = vp_init_simple(bdf); + vdrive->ioaddr = ioaddr; + if (vp_find_vq(ioaddr, 0, &vdrive->vq) < 0 ) { + dprintf(1, "fail to find vq for virtio-blk %x:%x\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); + goto fail; + } + + struct virtio_blk_config cfg; + vp_get(ioaddr, 0, &cfg, sizeof(cfg)); + + u32 f = vp_get_features(ioaddr); + vdrive->drive.blksize = (f & (1 << VIRTIO_BLK_F_BLK_SIZE)) ? + cfg.blk_size : DISK_SECTOR_SIZE; + + vdrive->drive.sectors = cfg.capacity; + dprintf(3, "virtio-blk %x:%x blksize=%d sectors=%u\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), + vdrive->drive.blksize, (u32)vdrive->drive.sectors); + + if (vdrive->drive.blksize != DISK_SECTOR_SIZE) { + dprintf(1, "virtio-blk %x:%x block size %d is unsupported\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), + vdrive->drive.blksize); + goto fail; + } + + vdrive->drive.pchs.cylinder = cfg.cylinders; + vdrive->drive.pchs.head = cfg.heads; + vdrive->drive.pchs.sector = cfg.sectors; + char *desc = znprintf(MAXDESCSIZE, "Virtio disk PCI:%x:%x", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); + + boot_add_hd(&vdrive->drive, desc, bootprio_find_pci_device(pci)); + + vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK); + return; + +fail: + free(vdrive->vq); + free(vdrive); +} + +void +virtio_blk_setup(void) +{ + ASSERT32FLAT(); + if (! CONFIG_VIRTIO_BLK) + return; + + dprintf(3, "init virtio-blk\n"); + + struct pci_device *pci; + foreachpci(pci) { + if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET + || pci->device != PCI_DEVICE_ID_VIRTIO_BLK) + continue; + init_virtio_blk(pci); + } +} diff -Nru seabios-1.7.1/src/hw/virtio-blk.h seabios-1.7.4/src/hw/virtio-blk.h --- seabios-1.7.1/src/hw/virtio-blk.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-blk.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,43 @@ +#ifndef _VIRTIO_BLK_H +#define _VIRTIO_BLK_H + +struct virtio_blk_config +{ + u64 capacity; + u32 size_max; + u32 seg_max; + u16 cylinders; + u8 heads; + u8 sectors; + u32 blk_size; + u8 physical_block_exp; + u8 alignment_offset; + u16 min_io_size; + u32 opt_io_size; +} __attribute__((packed)); + +#define VIRTIO_BLK_F_BLK_SIZE 6 + +/* These two define direction. */ +#define VIRTIO_BLK_T_IN 0 +#define VIRTIO_BLK_T_OUT 1 + +/* This is the first element of the read scatter-gather list. */ +struct virtio_blk_outhdr { + /* VIRTIO_BLK_T* */ + u32 type; + /* io priority. */ + u32 ioprio; + /* Sector (ie. 512 byte offset) */ + u64 sector; +}; + +#define VIRTIO_BLK_S_OK 0 +#define VIRTIO_BLK_S_IOERR 1 +#define VIRTIO_BLK_S_UNSUPP 2 + +struct disk_op_s; +int process_virtio_blk_op(struct disk_op_s *op); +void virtio_blk_setup(void); + +#endif /* _VIRTIO_BLK_H */ diff -Nru seabios-1.7.1/src/hw/virtio-pci.c seabios-1.7.4/src/hw/virtio-pci.c --- seabios-1.7.1/src/hw/virtio-pci.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-pci.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,96 @@ +/* virtio-pci.c - pci interface for virtio interface + * + * (c) Copyright 2008 Bull S.A.S. + * + * Author: Laurent Vivier + * + * some parts from Linux Virtio PCI driver + * + * Copyright IBM Corp. 2007 + * Authors: Anthony Liguori + * + * Adopted for Seabios: Gleb Natapov + * + * This work is licensed under the terms of the GNU LGPLv3 + * See the COPYING file in the top-level directory. + */ + +#include "config.h" // CONFIG_DEBUG_LEVEL +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // pci_config_readl +#include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "string.h" // memset +#include "virtio-pci.h" +#include "virtio-ring.h" + +int vp_find_vq(unsigned int ioaddr, int queue_index, + struct vring_virtqueue **p_vq) +{ + u16 num; + + ASSERT32FLAT(); + struct vring_virtqueue *vq = *p_vq = memalign_low(PAGE_SIZE, sizeof(*vq)); + if (!vq) { + warn_noalloc(); + goto fail; + } + memset(vq, 0, sizeof(*vq)); + + /* select the queue */ + + outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); + + /* check if the queue is available */ + + num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); + if (!num) { + dprintf(1, "ERROR: queue size is 0\n"); + goto fail; + } + + if (num > MAX_QUEUE_NUM) { + dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); + goto fail; + } + + /* check if the queue is already active */ + + if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { + dprintf(1, "ERROR: queue already active\n"); + goto fail; + } + + vq->queue_index = queue_index; + + /* initialize the queue */ + + struct vring * vr = &vq->vring; + vring_init(vr, num, (unsigned char*)&vq->queue); + + /* activate the queue + * + * NOTE: vr->desc is initialized by vring_init() + */ + + outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, + ioaddr + VIRTIO_PCI_QUEUE_PFN); + + return num; + +fail: + free(vq); + *p_vq = NULL; + return -1; +} + +u16 vp_init_simple(u16 bdf) +{ + u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & + PCI_BASE_ADDRESS_IO_MASK; + + vp_reset(ioaddr); + vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER ); + return ioaddr; +} diff -Nru seabios-1.7.1/src/hw/virtio-pci.h seabios-1.7.4/src/hw/virtio-pci.h --- seabios-1.7.1/src/hw/virtio-pci.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-pci.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,105 @@ +#ifndef _VIRTIO_PCI_H +#define _VIRTIO_PCI_H + +#include "x86.h" // inl + +/* A 32-bit r/o bitmask of the features supported by the host */ +#define VIRTIO_PCI_HOST_FEATURES 0 + +/* A 32-bit r/w bitmask of features activated by the guest */ +#define VIRTIO_PCI_GUEST_FEATURES 4 + +/* A 32-bit r/w PFN for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_PFN 8 + +/* A 16-bit r/o queue size for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_NUM 12 + +/* A 16-bit r/w queue selector */ +#define VIRTIO_PCI_QUEUE_SEL 14 + +/* A 16-bit r/w queue notifier */ +#define VIRTIO_PCI_QUEUE_NOTIFY 16 + +/* An 8-bit device status register. */ +#define VIRTIO_PCI_STATUS 18 + +/* An 8-bit r/o interrupt status register. Reading the value will return the + * current contents of the ISR and will also clear it. This is effectively + * a read-and-acknowledge. */ +#define VIRTIO_PCI_ISR 19 + +/* The bit of the ISR which indicates a device configuration change. */ +#define VIRTIO_PCI_ISR_CONFIG 0x2 + +/* The remaining space is defined by each driver as the per-driver + * configuration space */ +#define VIRTIO_PCI_CONFIG 20 + +/* Virtio ABI version, this must match exactly */ +#define VIRTIO_PCI_ABI_VERSION 0 + +static inline u32 vp_get_features(unsigned int ioaddr) +{ + return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES); +} + +static inline void vp_set_features(unsigned int ioaddr, u32 features) +{ + outl(features, ioaddr + VIRTIO_PCI_GUEST_FEATURES); +} + +static inline void vp_get(unsigned int ioaddr, unsigned offset, + void *buf, unsigned len) +{ + u8 *ptr = buf; + unsigned i; + + for (i = 0; i < len; i++) + ptr[i] = inb(ioaddr + VIRTIO_PCI_CONFIG + offset + i); +} + +static inline u8 vp_get_status(unsigned int ioaddr) +{ + return inb(ioaddr + VIRTIO_PCI_STATUS); +} + +static inline void vp_set_status(unsigned int ioaddr, u8 status) +{ + if (status == 0) /* reset */ + return; + outb(status, ioaddr + VIRTIO_PCI_STATUS); +} + +static inline u8 vp_get_isr(unsigned int ioaddr) +{ + return inb(ioaddr + VIRTIO_PCI_ISR); +} + +static inline void vp_reset(unsigned int ioaddr) +{ + outb(0, ioaddr + VIRTIO_PCI_STATUS); + (void)inb(ioaddr + VIRTIO_PCI_ISR); +} + +static inline void vp_notify(unsigned int ioaddr, int queue_index) +{ + outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); +} + +static inline void vp_del_vq(unsigned int ioaddr, int queue_index) +{ + /* select the queue */ + + outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); + + /* deactivate the queue */ + + outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN); +} + +struct vring_virtqueue; +u16 vp_init_simple(u16 bdf); +int vp_find_vq(unsigned int ioaddr, int queue_index, + struct vring_virtqueue **p_vq); +#endif /* _VIRTIO_PCI_H_ */ diff -Nru seabios-1.7.1/src/hw/virtio-ring.c seabios-1.7.4/src/hw/virtio-ring.c --- seabios-1.7.1/src/hw/virtio-ring.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-ring.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,149 @@ +/* virtio-pci.c - virtio ring management + * + * (c) Copyright 2008 Bull S.A.S. + * + * Author: Laurent Vivier + * + * some parts from Linux Virtio Ring + * + * Copyright Rusty Russell IBM Corporation 2007 + * + * Adopted for Seabios: Gleb Natapov + * + * This work is licensed under the terms of the GNU LGPLv3 + * See the COPYING file in the top-level directory. + * + * + */ + +#include "biosvar.h" // GET_GLOBAL +#include "output.h" // panic +#include "virtio-ring.h" +#include "virtio-pci.h" + +#define BUG() do { \ + panic("BUG: failure at %d/%s()!\n", __LINE__, __func__); \ + } while (0) +#define BUG_ON(condition) do { if (condition) BUG(); } while (0) + +/* + * vring_more_used + * + * is there some used buffers ? + * + */ + +int vring_more_used(struct vring_virtqueue *vq) +{ + struct vring_used *used = GET_LOWFLAT(vq->vring.used); + int more = GET_LOWFLAT(vq->last_used_idx) != GET_LOWFLAT(used->idx); + /* Make sure ring reads are done after idx read above. */ + smp_rmb(); + return more; +} + +/* + * vring_free + * + * put at the begin of the free list the current desc[head] + */ + +void vring_detach(struct vring_virtqueue *vq, unsigned int head) +{ + struct vring *vr = &vq->vring; + struct vring_desc *desc = GET_LOWFLAT(vr->desc); + unsigned int i; + + /* find end of given descriptor */ + + i = head; + while (GET_LOWFLAT(desc[i].flags) & VRING_DESC_F_NEXT) + i = GET_LOWFLAT(desc[i].next); + + /* link it with free list and point to it */ + + SET_LOWFLAT(desc[i].next, GET_LOWFLAT(vq->free_head)); + SET_LOWFLAT(vq->free_head, head); +} + +/* + * vring_get_buf + * + * get a buffer from the used list + * + */ + +int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len) +{ + struct vring *vr = &vq->vring; + struct vring_used_elem *elem; + struct vring_used *used = GET_LOWFLAT(vq->vring.used); + u32 id; + int ret; + +// BUG_ON(!vring_more_used(vq)); + + elem = &used->ring[GET_LOWFLAT(vq->last_used_idx) % GET_LOWFLAT(vr->num)]; + id = GET_LOWFLAT(elem->id); + if (len != NULL) + *len = GET_LOWFLAT(elem->len); + + ret = GET_LOWFLAT(vq->vdata[id]); + + vring_detach(vq, id); + + SET_LOWFLAT(vq->last_used_idx, GET_LOWFLAT(vq->last_used_idx) + 1); + + return ret; +} + +void vring_add_buf(struct vring_virtqueue *vq, + struct vring_list list[], + unsigned int out, unsigned int in, + int index, int num_added) +{ + struct vring *vr = &vq->vring; + int i, av, head, prev; + struct vring_desc *desc = GET_LOWFLAT(vr->desc); + struct vring_avail *avail = GET_LOWFLAT(vr->avail); + + BUG_ON(out + in == 0); + + prev = 0; + head = GET_LOWFLAT(vq->free_head); + for (i = head; out; i = GET_LOWFLAT(desc[i].next), out--) { + SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT); + SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr)); + SET_LOWFLAT(desc[i].len, list->length); + prev = i; + list++; + } + for ( ; in; i = GET_LOWFLAT(desc[i].next), in--) { + SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT|VRING_DESC_F_WRITE); + SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr)); + SET_LOWFLAT(desc[i].len, list->length); + prev = i; + list++; + } + SET_LOWFLAT(desc[prev].flags, + GET_LOWFLAT(desc[prev].flags) & ~VRING_DESC_F_NEXT); + + SET_LOWFLAT(vq->free_head, i); + + SET_LOWFLAT(vq->vdata[head], index); + + av = (GET_LOWFLAT(avail->idx) + num_added) % GET_LOWFLAT(vr->num); + SET_LOWFLAT(avail->ring[av], head); +} + +void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) +{ + struct vring *vr = &vq->vring; + struct vring_avail *avail = GET_LOWFLAT(vr->avail); + + /* Make sure idx update is done after ring write. */ + smp_wmb(); + SET_LOWFLAT(avail->idx, GET_LOWFLAT(avail->idx) + num_added); + + vp_notify(ioaddr, GET_LOWFLAT(vq->queue_index)); +} diff -Nru seabios-1.7.1/src/hw/virtio-ring.h seabios-1.7.4/src/hw/virtio-ring.h --- seabios-1.7.1/src/hw/virtio-ring.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-ring.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,131 @@ +#ifndef _VIRTIO_RING_H +#define _VIRTIO_RING_H + +#include "types.h" // u64 +#include "memmap.h" // PAGE_SIZE + +#define PAGE_SHIFT 12 +#define PAGE_MASK (PAGE_SIZE-1) + +#define virt_to_phys(v) (unsigned long)(v) +#define phys_to_virt(p) (void*)(p) +/* Compiler barrier is enough as an x86 CPU does not reorder reads or writes */ +#define smp_rmb() barrier() +#define smp_wmb() barrier() + +/* Status byte for guest to report progress, and synchronize features. */ +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define VIRTIO_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* We've given up on this device. */ +#define VIRTIO_CONFIG_S_FAILED 0x80 + +#define MAX_QUEUE_NUM (128) + +#define VRING_DESC_F_NEXT 1 +#define VRING_DESC_F_WRITE 2 + +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +#define VRING_USED_F_NO_NOTIFY 1 + +struct vring_desc +{ + u64 addr; + u32 len; + u16 flags; + u16 next; +}; + +struct vring_avail +{ + u16 flags; + u16 idx; + u16 ring[0]; +}; + +struct vring_used_elem +{ + u32 id; + u32 len; +}; + +struct vring_used +{ + u16 flags; + u16 idx; + struct vring_used_elem ring[]; +}; + +struct vring { + unsigned int num; + struct vring_desc *desc; + struct vring_avail *avail; + struct vring_used *used; +}; + +#define vring_size(num) \ + (((((sizeof(struct vring_desc) * num) + \ + (sizeof(struct vring_avail) + sizeof(u16) * num)) \ + + PAGE_MASK) & ~PAGE_MASK) + \ + (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num)) + +typedef unsigned char virtio_queue_t[vring_size(MAX_QUEUE_NUM)]; + +struct vring_virtqueue { + virtio_queue_t queue; + struct vring vring; + u16 free_head; + u16 last_used_idx; + u16 vdata[MAX_QUEUE_NUM]; + /* PCI */ + int queue_index; +}; + +struct vring_list { + char *addr; + unsigned int length; +}; + +static inline void vring_init(struct vring *vr, + unsigned int num, unsigned char *queue) +{ + unsigned int i; + unsigned long pa; + + ASSERT32FLAT(); + vr->num = num; + + /* physical address of desc must be page aligned */ + + pa = virt_to_phys(queue); + pa = (pa + PAGE_MASK) & ~PAGE_MASK; + vr->desc = phys_to_virt(pa); + + vr->avail = (struct vring_avail *)&vr->desc[num]; + /* disable interrupts */ + vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; + + /* physical address of used must be page aligned */ + + pa = virt_to_phys(&vr->avail->ring[num]); + pa = (pa + PAGE_MASK) & ~PAGE_MASK; + vr->used = phys_to_virt(pa); + + for (i = 0; i < num - 1; i++) + vr->desc[i].next = i + 1; + vr->desc[i].next = 0; +} + +int vring_more_used(struct vring_virtqueue *vq); +void vring_detach(struct vring_virtqueue *vq, unsigned int head); +int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len); +void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[], + unsigned int out, unsigned int in, + int index, int num_added); +void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added); + +#endif /* _VIRTIO_RING_H_ */ diff -Nru seabios-1.7.1/src/hw/virtio-scsi.c seabios-1.7.4/src/hw/virtio-scsi.c --- seabios-1.7.1/src/hw/virtio-scsi.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-scsi.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,186 @@ +// Virtio SCSI boot support. +// +// Copyright (C) 2012 Red Hat Inc. +// +// Authors: +// Paolo Bonzini +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_GLOBALFLAT +#include "block.h" // struct drive_s +#include "blockcmd.h" // scsi_drive_setup +#include "config.h" // CONFIG_* +#include "malloc.h" // free +#include "output.h" // dprintf +#include "pci.h" // foreachpci +#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK +#include "pci_regs.h" // PCI_VENDOR_ID +#include "std/disk.h" // DISK_RET_SUCCESS +#include "string.h" // memset +#include "util.h" // usleep +#include "virtio-pci.h" +#include "virtio-ring.h" +#include "virtio-scsi.h" + +struct virtio_lun_s { + struct drive_s drive; + struct pci_device *pci; + struct vring_virtqueue *vq; + u16 ioaddr; + u16 target; + u16 lun; +}; + +static int +virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op, + void *cdbcmd, u16 target, u16 lun, u16 blocksize) +{ + struct virtio_scsi_req_cmd req; + struct virtio_scsi_resp_cmd resp; + struct vring_list sg[3]; + + memset(&req, 0, sizeof(req)); + req.lun[0] = 1; + req.lun[1] = target; + req.lun[2] = (lun >> 8) | 0x40; + req.lun[3] = (lun & 0xff); + memcpy(req.cdb, cdbcmd, 16); + + u32 len = op->count * blocksize; + int datain = cdb_is_read(cdbcmd, blocksize); + int in_num = (datain ? 2 : 1); + int out_num = (len ? 3 : 2) - in_num; + + sg[0].addr = MAKE_FLATPTR(GET_SEG(SS), &req); + sg[0].length = sizeof(req); + + sg[out_num].addr = MAKE_FLATPTR(GET_SEG(SS), &resp); + sg[out_num].length = sizeof(resp); + + if (len) { + int data_idx = (datain ? 2 : 1); + sg[data_idx].addr = op->buf_fl; + sg[data_idx].length = len; + } + + /* Add to virtqueue and kick host */ + vring_add_buf(vq, sg, out_num, in_num, 0, 0); + vring_kick(ioaddr, vq, 1); + + /* Wait for reply */ + while (!vring_more_used(vq)) + usleep(5); + + /* Reclaim virtqueue element */ + vring_get_buf(vq, NULL); + + /* Clear interrupt status register. Avoid leaving interrupts stuck if + * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised. + */ + vp_get_isr(ioaddr); + + if (resp.response == VIRTIO_SCSI_S_OK && resp.status == 0) { + return DISK_RET_SUCCESS; + } + return DISK_RET_EBADTRACK; +} + +int +virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) +{ + struct virtio_lun_s *vlun_gf = + container_of(op->drive_gf, struct virtio_lun_s, drive); + + return virtio_scsi_cmd(GET_GLOBALFLAT(vlun_gf->ioaddr), + GET_GLOBALFLAT(vlun_gf->vq), op, cdbcmd, + GET_GLOBALFLAT(vlun_gf->target), + GET_GLOBALFLAT(vlun_gf->lun), + blocksize); +} + +static int +virtio_scsi_add_lun(struct pci_device *pci, u16 ioaddr, + struct vring_virtqueue *vq, u16 target, u16 lun) +{ + struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun)); + if (!vlun) { + warn_noalloc(); + return -1; + } + memset(vlun, 0, sizeof(*vlun)); + vlun->drive.type = DTYPE_VIRTIO_SCSI; + vlun->drive.cntl_id = pci->bdf; + vlun->pci = pci; + vlun->ioaddr = ioaddr; + vlun->vq = vq; + vlun->target = target; + vlun->lun = lun; + + int prio = bootprio_find_scsi_device(pci, target, lun); + int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio); + if (ret) + goto fail; + return 0; + +fail: + free(vlun); + return -1; +} + +static int +virtio_scsi_scan_target(struct pci_device *pci, u16 ioaddr, + struct vring_virtqueue *vq, u16 target) +{ + /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ + int ret = virtio_scsi_add_lun(pci, ioaddr, vq, target, 0); + return ret < 0 ? 0 : 1; +} + +static void +init_virtio_scsi(struct pci_device *pci) +{ + u16 bdf = pci->bdf; + dprintf(1, "found virtio-scsi at %x:%x\n", pci_bdf_to_bus(bdf), + pci_bdf_to_dev(bdf)); + struct vring_virtqueue *vq = NULL; + u16 ioaddr = vp_init_simple(bdf); + if (vp_find_vq(ioaddr, 2, &vq) < 0 ) { + dprintf(1, "fail to find vq for virtio-scsi %x:%x\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); + goto fail; + } + + vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK); + + int i, tot; + for (tot = 0, i = 0; i < 256; i++) + tot += virtio_scsi_scan_target(pci, ioaddr, vq, i); + + if (!tot) + goto fail; + + return; + +fail: + free(vq); +} + +void +virtio_scsi_setup(void) +{ + ASSERT32FLAT(); + if (! CONFIG_VIRTIO_SCSI) + return; + + dprintf(3, "init virtio-scsi\n"); + + struct pci_device *pci; + foreachpci(pci) { + if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET + || pci->device != PCI_DEVICE_ID_VIRTIO_SCSI) + continue; + init_virtio_scsi(pci); + } +} diff -Nru seabios-1.7.1/src/hw/virtio-scsi.h seabios-1.7.4/src/hw/virtio-scsi.h --- seabios-1.7.1/src/hw/virtio-scsi.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/hw/virtio-scsi.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,47 @@ +#ifndef _VIRTIO_SCSI_H +#define _VIRTIO_SCSI_H + +#define VIRTIO_SCSI_CDB_SIZE 32 +#define VIRTIO_SCSI_SENSE_SIZE 96 + +struct virtio_scsi_config +{ + u32 num_queues; + u32 seg_max; + u32 max_sectors; + u32 cmd_per_lun; + u32 event_info_size; + u32 sense_size; + u32 cdb_size; + u16 max_channel; + u16 max_target; + u32 max_lun; +} __attribute__((packed)); + +/* This is the first element of the "out" scatter-gather list. */ +struct virtio_scsi_req_cmd { + u8 lun[8]; + u64 id; + u8 task_attr; + u8 prio; + u8 crn; + char cdb[VIRTIO_SCSI_CDB_SIZE]; +} __attribute__((packed)); + +/* This is the first element of the "in" scatter-gather list. */ +struct virtio_scsi_resp_cmd { + u32 sense_len; + u32 residual; + u16 status_qualifier; + u8 status; + u8 response; + u8 sense[VIRTIO_SCSI_SENSE_SIZE]; +} __attribute__((packed)); + +#define VIRTIO_SCSI_S_OK 0 + +struct disk_op_s; +int virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); +void virtio_scsi_setup(void); + +#endif /* _VIRTIO_SCSI_H */ diff -Nru seabios-1.7.1/src/ioport.h seabios-1.7.4/src/ioport.h --- seabios-1.7.1/src/ioport.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ioport.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -// Definitions for X86 IO port access. -// -// Copyright (C) 2008 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. -#ifndef __IOPORT_H -#define __IOPORT_H - -#define PORT_DMA_ADDR_2 0x0004 -#define PORT_DMA_CNT_2 0x0005 -#define PORT_DMA1_MASK_REG 0x000a -#define PORT_DMA1_MODE_REG 0x000b -#define PORT_DMA1_CLEAR_FF_REG 0x000c -#define PORT_DMA1_MASTER_CLEAR 0x000d -#define PORT_PIC1_CMD 0x0020 -#define PORT_PIC1_DATA 0x0021 -#define PORT_PIT_COUNTER0 0x0040 -#define PORT_PIT_COUNTER1 0x0041 -#define PORT_PIT_COUNTER2 0x0042 -#define PORT_PIT_MODE 0x0043 -#define PORT_PS2_DATA 0x0060 -#define PORT_PS2_CTRLB 0x0061 -#define PORT_PS2_STATUS 0x0064 -#define PORT_CMOS_INDEX 0x0070 -#define PORT_CMOS_DATA 0x0071 -#define PORT_DIAG 0x0080 -#define PORT_DMA_PAGE_2 0x0081 -#define PORT_A20 0x0092 -#define PORT_PIC2_CMD 0x00a0 -#define PORT_PIC2_DATA 0x00a1 -#define PORT_SMI_CMD 0x00b2 -#define PORT_SMI_STATUS 0x00b3 -#define PORT_DMA2_MASK_REG 0x00d4 -#define PORT_DMA2_MODE_REG 0x00d6 -#define PORT_DMA2_MASTER_CLEAR 0x00da -#define PORT_MATH_CLEAR 0x00f0 -#define PORT_ATA2_CMD_BASE 0x0170 -#define PORT_ATA1_CMD_BASE 0x01f0 -#define PORT_LPT2 0x0278 -#define PORT_SERIAL4 0x02e8 -#define PORT_SERIAL2 0x02f8 -#define PORT_ATA2_CTRL_BASE 0x0374 -#define PORT_LPT1 0x0378 -#define PORT_SERIAL3 0x03e8 -#define PORT_ATA1_CTRL_BASE 0x03f4 -#define PORT_FD_BASE 0x03f0 -#define PORT_FD_DOR 0x03f2 -#define PORT_FD_STATUS 0x03f4 -#define PORT_FD_DATA 0x03f5 -#define PORT_HD_DATA 0x03f6 -#define PORT_FD_DIR 0x03f7 -#define PORT_SERIAL1 0x03f8 -#define PORT_PCI_CMD 0x0cf8 -#define PORT_PCI_REBOOT 0x0cf9 -#define PORT_PCI_DATA 0x0cfc -#define PORT_BIOS_DEBUG 0x0402 -#define PORT_QEMU_CFG_CTL 0x0510 -#define PORT_QEMU_CFG_DATA 0x0511 -#define PORT_ACPI_PM_BASE 0xb000 -#define PORT_SMB_BASE 0xb100 -#define PORT_BIOS_APM 0x8900 - -// Serial port offsets -#define SEROFF_DATA 0 -#define SEROFF_DLL 0 -#define SEROFF_IER 1 -#define SEROFF_DLH 1 -#define SEROFF_IIR 2 -#define SEROFF_LCR 3 -#define SEROFF_LSR 5 -#define SEROFF_MSR 6 - -// PORT_A20 bitdefs -#define A20_ENABLE_BIT 0x02 - -// PORT_CMOS_INDEX nmi disable bit -#define NMI_DISABLE_BIT 0x80 - -#ifndef __ASSEMBLY__ - -#include "types.h" // u8 - -static inline void outb(u8 value, u16 port) { - __asm__ __volatile__("outb %b0, %w1" : : "a"(value), "Nd"(port)); -} -static inline void outw(u16 value, u16 port) { - __asm__ __volatile__("outw %w0, %w1" : : "a"(value), "Nd"(port)); -} -static inline void outl(u32 value, u16 port) { - __asm__ __volatile__("outl %0, %w1" : : "a"(value), "Nd"(port)); -} -static inline u8 inb(u16 port) { - u8 value; - __asm__ __volatile__("inb %w1, %b0" : "=a"(value) : "Nd"(port)); - return value; -} -static inline u16 inw(u16 port) { - u16 value; - __asm__ __volatile__("inw %w1, %w0" : "=a"(value) : "Nd"(port)); - return value; -} -static inline u32 inl(u16 port) { - u32 value; - __asm__ __volatile__("inl %w1, %0" : "=a"(value) : "Nd"(port)); - return value; -} - -static inline void insb(u16 port, u8 *data, u32 count) { - asm volatile("rep insb (%%dx), %%es:(%%edi)" - : "+c"(count), "+D"(data) : "d"(port) : "memory"); -} -static inline void insw(u16 port, u16 *data, u32 count) { - asm volatile("rep insw (%%dx), %%es:(%%edi)" - : "+c"(count), "+D"(data) : "d"(port) : "memory"); -} -static inline void insl(u16 port, u32 *data, u32 count) { - asm volatile("rep insl (%%dx), %%es:(%%edi)" - : "+c"(count), "+D"(data) : "d"(port) : "memory"); -} -// XXX - outs not limited to es segment -static inline void outsb(u16 port, u8 *data, u32 count) { - asm volatile("rep outsb %%es:(%%esi), (%%dx)" - : "+c"(count), "+S"(data) : "d"(port) : "memory"); -} -static inline void outsw(u16 port, u16 *data, u32 count) { - asm volatile("rep outsw %%es:(%%esi), (%%dx)" - : "+c"(count), "+S"(data) : "d"(port) : "memory"); -} -static inline void outsl(u16 port, u32 *data, u32 count) { - asm volatile("rep outsl %%es:(%%esi), (%%dx)" - : "+c"(count), "+S"(data) : "d"(port) : "memory"); -} - -#endif // !__ASSEMBLY__ - -#endif // ioport.h diff -Nru seabios-1.7.1/src/jpeg.c seabios-1.7.4/src/jpeg.c --- seabios-1.7.1/src/jpeg.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/jpeg.c 2013-12-23 15:40:06.000000000 +0000 @@ -40,8 +40,9 @@ */ #define __LITTLE_ENDIAN +#include "malloc.h" +#include "string.h" #include "util.h" -#include "jpeg.h" #define ISHIFT 11 #define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5)) diff -Nru seabios-1.7.1/src/jpeg.h seabios-1.7.4/src/jpeg.h --- seabios-1.7.1/src/jpeg.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/jpeg.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#ifndef __JPEG_H -#define __JPEG_H - -struct jpeg_decdata; -struct jpeg_decdata *jpeg_alloc(void); -int jpeg_decode(struct jpeg_decdata *jpeg, unsigned char *buf); -void jpeg_get_size(struct jpeg_decdata *jpeg, int *width, int *height); -int jpeg_show(struct jpeg_decdata *jpeg, unsigned char *pic, int width - , int height, int depth, int bytes_per_line_dest); - -#endif diff -Nru seabios-1.7.1/src/kbd.c seabios-1.7.4/src/kbd.c --- seabios-1.7.1/src/kbd.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/kbd.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,11 +6,14 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "biosvar.h" // GET_BDA -#include "util.h" // debug_enter -#include "config.h" // CONFIG_* #include "bregs.h" // struct bregs -#include "ps2port.h" // ps2_kbd_command -#include "usb-hid.h" // usb_kbd_command +#include "config.h" // CONFIG_* +#include "hw/ps2port.h" // ps2_kbd_command +#include "hw/usb-hid.h" // usb_kbd_command +#include "output.h" // debug_enter +#include "stacks.h" // stack_hop +#include "string.h" // memset +#include "util.h" // kbd_init // Bit definitions for BDA kbd_flag[012] #define KF0_RSHIFT (1<<0) @@ -35,7 +38,7 @@ #define KF2_101KBD (1<<4) void -kbd_setup(void) +kbd_init(void) { dprintf(3, "init keyboard\n"); u16 x = offsetof(struct bios_data_area_s, kbd_buf); diff -Nru seabios-1.7.1/src/Kconfig seabios-1.7.4/src/Kconfig --- seabios-1.7.1/src/Kconfig 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/Kconfig 2013-12-23 15:40:06.000000000 +0000 @@ -4,15 +4,39 @@ menu "General Features" +choice + prompt "Build Target" + default QEMU + config COREBOOT bool "Build for coreboot" - default n help Configure as a coreboot payload. + config QEMU + bool "Build for QEMU/Xen/KVM/Bochs" + select QEMU_HARDWARE + help + Configure for an emulated machine (QEMU, Xen, KVM, or Bochs). + + config CSM + bool "Build as Compatibilty Support Module for EFI BIOS" + help + Configure to be used by EFI firmware as Compatibility Support + module (CSM) to provide legacy BIOS services. + +endchoice + + config QEMU_HARDWARE + bool "Support hardware found on emulators (QEMU/Xen/KVM/Bochs)" if !QEMU + default n + help + Support virtual hardware when the code detects it is + running on an emulator. + config XEN - depends on !COREBOOT - bool "Build for Xen HVM" + depends on QEMU + bool "Support Xen HVM" default y help Configure to be used by xen hvmloader, for a HVM guest. @@ -23,7 +47,7 @@ help Support running hardware initialization in parallel. config THREAD_OPTIONROMS - depends on THREADS + depends on THREADS && !CSM bool "Hardware init during option ROM execution" default n help @@ -79,6 +103,35 @@ default y help Support floppy images in coreboot flash. + config ENTRY_EXTRASTACK + bool "Use internal stack for 16bit interrupt entry points" + default y + help + Utilize an internal stack for all the legacy 16bit + interrupt entry points. This reduces the amount of space + on the caller's stack that SeaBIOS uses. This may + adversely impact any legacy operating systems that call + the BIOS in 16bit protected mode. + + config MALLOC_UPPERMEMORY + bool "Allocate memory that needs to be in first Meg above 0xc0000" + default y + help + Use the "Upper Memory Block" area (0xc0000-0xf0000) for + internal "low memory" allocations. If this is not + selected, the memory is instead allocated from the + "9-segment" (0x90000-0xa0000). + + config ROM_SIZE + int "ROM size (in KB)" + default 0 + help + Set the ROM size. Say '0' here to make seabios figure the + needed size automatically. + + Currently SeaBIOS will easily fit into 256 KB. To make it fit + it into 128 KB (which was big enouth for a long time) you'll + probably have to disable some featues such as xhci support. endmenu @@ -108,29 +161,47 @@ help Support for AHCI disk code. config VIRTIO_BLK - depends on DRIVES && !COREBOOT + depends on DRIVES && QEMU_HARDWARE bool "virtio-blk controllers" default y help Support boot from virtio-blk storage. config VIRTIO_SCSI - depends on DRIVES && !COREBOOT + depends on DRIVES && QEMU_HARDWARE bool "virtio-scsi controllers" default y help Support boot from virtio-scsi storage. + config PVSCSI + depends on DRIVES && QEMU_HARDWARE + bool "PVSCSI controllers" + default y + help + Support boot from Paravirtualized SCSI storage. This kind of storage + is mainly supported by VMware ESX hypervisor. It is commonly used + to allow fast storage access by communicating directly with the + underlying hypervisor. Enabling this type of boot will allow + booting directly from images imported from an ESX platform, + without the need to use slower emulation of storage controllers + such as IDE. config ESP_SCSI - depends on DRIVES && !COREBOOT + depends on DRIVES && QEMU_HARDWARE bool "AMD PCscsi controllers" default y help Support boot from AMD PCscsi storage. config LSI_SCSI - depends on DRIVES && !COREBOOT + depends on DRIVES && QEMU_HARDWARE bool "lsi53c895a scsi controllers" default y help Support boot from qemu-emulated lsi53c895a scsi storage. + config MEGASAS + depends on DRIVES + bool "LSI MegaRAID SAS controllers" + default y + help + Support boot from LSI MegaRAID SAS scsi storage. config FLOPPY depends on DRIVES bool "Floppy controller" @@ -168,6 +239,12 @@ default y help Support USB EHCI controllers. + config USB_XHCI + depends on USB && QEMU_HARDWARE + bool "USB XHCI controllers" + default y + help + Support USB XHCI controllers. config USB_MSC depends on USB && DRIVES bool "USB drives" @@ -211,17 +288,22 @@ Support parallel ports. This also enables int 17 parallel port calls. config USE_SMM - depends on !COREBOOT + depends on QEMU bool "System Management Mode (SMM)" default y help Support System Management Mode (on emulators). config MTRR_INIT - depends on !COREBOOT + depends on QEMU bool "Initialize MTRRs" default y help Initialize the Memory Type Range Registers (on emulators). + config PMTIMER + bool "Use ACPI timer" + default y + help + Use the ACPI timer instead of the TSC for timekeeping (on qemu). endmenu menu "BIOS interfaces" @@ -265,7 +347,7 @@ help Support finding and running option roms during POST. config OPTIONROMS_DEPLOYED - depends on OPTIONROMS + depends on OPTIONROMS && QEMU bool "Option roms are already at 0xc0000-0xf0000" default n help @@ -318,10 +400,22 @@ default n help Disable A20 on 16bit boot. + + config WRITABLE_UPPERMEMORY + depends on QEMU + bool "Make unused UMB memory read/writeable." + default n + help + When selected, the "Upper Memory Block" area + (0x90000-0xa0000) that is not used for option roms will be + made writable. This allows the ram to be directly + modified by programs. However, some old DOS high memory + managers may require the UMB region to be read-only. + endmenu menu "BIOS Tables" - depends on !COREBOOT + depends on QEMU config PIRTABLE bool "PIR table" default y @@ -343,9 +437,30 @@ default y help Support generation of ACPI tables. + config ACPI_DSDT + bool "Include default ACPI DSDT" + default y + depends on ACPI + help + Include default DSDT ACPI table in BIOS. + Required for QEMU 1.3 and older. + This option can be disabled for QEMU 1.4 and newer + to save some space in the ROM file. + If unsure, say Y. + config FW_ROMFILE_LOAD + bool "Load BIOS tables from ROM files" + depends on QEMU_HARDWARE + default y + help + Support loading BIOS firmware tables from ROM files. + At the moment, only ACPI tables can be loaded in this way. + Required for QEMU 1.7 and newer. + This option can be disabled for QEMU 1.6 and older + to save some space in the ROM file. + If unsure, say Y. endmenu -source ../vgasrc/Kconfig +source vgasrc/Kconfig menu "Debugging" config DEBUG_LEVEL @@ -371,7 +486,7 @@ Base port for serial - generally 0x3f8, 0x2f8, 0x3e8, or 0x2e8. config DEBUG_IO - depends on !COREBOOT && DEBUG_LEVEL != 0 + depends on QEMU_HARDWARE && DEBUG_LEVEL != 0 bool "Special IO port debugging" default y help @@ -379,4 +494,14 @@ information by outputing strings in a special port present in the IO space. + config DEBUG_COREBOOT + depends on COREBOOT && DEBUG_LEVEL != 0 + bool "coreboot cbmem debug logging" + default y + help + Send debugging information to the coreboot cbmem console buffer. + Needs CONFIG_CONSOLE_CBMEM in coreboot. You can read the log + after boot using 'cbmem -c'. Only 32bit code (basically every- + thing before booting the OS) writes to the log buffer. + endmenu diff -Nru seabios-1.7.1/src/list.h seabios-1.7.4/src/list.h --- seabios-1.7.1/src/list.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/list.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,81 @@ +#ifndef __LIST_H +#define __LIST_H + +#include "types.h" // container_of + + +/**************************************************************** + * hlist - Double linked lists with a single pointer list head + ****************************************************************/ + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +struct hlist_head { + struct hlist_node *first; +}; + +static inline int +hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void +hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void +hlist_add(struct hlist_node *n, struct hlist_node **pprev) +{ + struct hlist_node *next = *pprev; + n->pprev = pprev; + n->next = next; + if (next) + next->pprev = &n->next; + *pprev = n; +} + +static inline void +hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + hlist_add(n, &h->first); +} + +static inline void +hlist_add_before(struct hlist_node *n, struct hlist_node *next) +{ + hlist_add(n, next->pprev); +} + +static inline void +hlist_add_after(struct hlist_node *n, struct hlist_node *prev) +{ + hlist_add(n, &prev->next); +} + +#define hlist_for_each_entry(pos, head, member) \ + for (pos = container_of((head)->first, typeof(*pos), member) \ + ; pos != container_of(NULL, typeof(*pos), member) \ + ; pos = container_of(pos->member.next, typeof(*pos), member)) + +#define hlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = container_of((head)->first, typeof(*pos), member) \ + ; pos != container_of(NULL, typeof(*pos), member) \ + && ({ n = pos->member.next; 1; }) \ + ; pos = container_of(n, typeof(*pos), member)) + +#define hlist_for_each_entry_pprev(pos, pprev, head, member) \ + for (pprev = &(head)->first \ + ; *pprev && ({ pos=container_of(*pprev, typeof(*pos), member); 1; }) \ + ; pprev = &(*pprev)->next) + + +#endif // list.h diff -Nru seabios-1.7.1/src/lsi-scsi.c seabios-1.7.4/src/lsi-scsi.c --- seabios-1.7.1/src/lsi-scsi.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/lsi-scsi.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,210 +0,0 @@ -// (qemu-emulated) lsi53c895a boot support. -// -// Copyright (C) 2012 Red Hat Inc. -// -// Authors: -// Gerd Hoffmann -// -// based on virtio-scsi.c which is written by: -// Paolo Bonzini -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // foreachpci -#include "config.h" // CONFIG_* -#include "biosvar.h" // GET_GLOBAL -#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK -#include "pci_regs.h" // PCI_VENDOR_ID -#include "boot.h" // bootprio_find_scsi_device -#include "blockcmd.h" // scsi_init_drive -#include "disk.h" - -#define LSI_REG_DSTAT 0x0c -#define LSI_REG_ISTAT0 0x14 -#define LSI_REG_DSP0 0x2c -#define LSI_REG_DSP1 0x2d -#define LSI_REG_DSP2 0x2e -#define LSI_REG_DSP3 0x2f -#define LSI_REG_SIST0 0x42 -#define LSI_REG_SIST1 0x43 - -#define LSI_ISTAT0_DIP 0x01 -#define LSI_ISTAT0_SIP 0x02 -#define LSI_ISTAT0_INTF 0x04 -#define LSI_ISTAT0_CON 0x08 -#define LSI_ISTAT0_SEM 0x10 -#define LSI_ISTAT0_SIGP 0x20 -#define LSI_ISTAT0_SRST 0x40 -#define LSI_ISTAT0_ABRT 0x80 - -struct lsi_lun_s { - struct drive_s drive; - struct pci_device *pci; - u32 iobase; - u8 target; - u8 lun; -}; - -static int -lsi_scsi_cmd(struct lsi_lun_s *llun, struct disk_op_s *op, - void *cdbcmd, u16 target, u16 lun, u16 blocksize) -{ - u32 iobase = GET_GLOBAL(llun->iobase); - u32 dma = ((cdb_is_read(cdbcmd, blocksize) ? 0x01000000 : 0x00000000) | - (op->count * blocksize)); - u8 msgout[] = { - 0x80 | lun, // select lun - 0x08, - }; - u8 status = 0xff; - u8 msgin_tmp[2]; - u8 msgin = 0xff; - - u32 script[] = { - /* select target, send scsi command */ - 0x40000000 | target << 16, // select target - 0x00000000, - 0x06000001, // msgout - (u32)MAKE_FLATPTR(GET_SEG(SS), &msgout), - 0x02000010, // scsi command - (u32)MAKE_FLATPTR(GET_SEG(SS), cdbcmd), - - /* handle disconnect */ - 0x87820000, // phase == msgin ? - 0x00000018, - 0x07000002, // msgin - (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp), - 0x50000000, // re-select - 0x00000000, - 0x07000002, // msgin - (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp), - - /* dma data, get status, raise irq */ - dma, // dma data - (u32)op->buf_fl, - 0x03000001, // status - (u32)MAKE_FLATPTR(GET_SEG(SS), &status), - 0x07000001, // msgin - (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin), - 0x98080000, // dma irq - 0x00000000, - }; - u32 dsp = (u32)MAKE_FLATPTR(GET_SEG(SS), &script); - - outb(dsp & 0xff, iobase + LSI_REG_DSP0); - outb((dsp >> 8) & 0xff, iobase + LSI_REG_DSP1); - outb((dsp >> 16) & 0xff, iobase + LSI_REG_DSP2); - outb((dsp >> 24) & 0xff, iobase + LSI_REG_DSP3); - - for (;;) { - u8 dstat = inb(iobase + LSI_REG_DSTAT); - u8 sist0 = inb(iobase + LSI_REG_SIST0); - u8 sist1 = inb(iobase + LSI_REG_SIST1); - if (sist0 || sist1) { - goto fail; - } - if (dstat & 0x04) { - break; - } - usleep(5); - } - - if (msgin == 0 && status == 0) { - return DISK_RET_SUCCESS; - } - -fail: - return DISK_RET_EBADTRACK; -} - -int -lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - if (!CONFIG_LSI_SCSI) - return DISK_RET_EBADTRACK; - - struct lsi_lun_s *llun = - container_of(op->drive_g, struct lsi_lun_s, drive); - - return lsi_scsi_cmd(llun, op, cdbcmd, - GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun), - blocksize); -} - -static int -lsi_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) -{ - struct lsi_lun_s *llun = malloc_fseg(sizeof(*llun)); - if (!llun) { - warn_noalloc(); - return -1; - } - memset(llun, 0, sizeof(*llun)); - llun->drive.type = DTYPE_LSI_SCSI; - llun->drive.cntl_id = pci->bdf; - llun->pci = pci; - llun->target = target; - llun->lun = lun; - llun->iobase = iobase; - - char *name = znprintf(16, "lsi %02x:%02x.%x %d:%d", - pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), - pci_bdf_to_fn(pci->bdf), target, lun); - int prio = bootprio_find_scsi_device(pci, target, lun); - int ret = scsi_init_drive(&llun->drive, name, prio); - free(name); - if (ret) - goto fail; - return 0; - -fail: - free(llun); - return -1; -} - -static void -lsi_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target) -{ - /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ - lsi_scsi_add_lun(pci, iobase, target, 0); -} - -static void -init_lsi_scsi(struct pci_device *pci) -{ - u16 bdf = pci->bdf; - u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) - & PCI_BASE_ADDRESS_IO_MASK; - - dprintf(1, "found lsi53c895a at %02x:%02x.%x, io @ %x\n", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), - pci_bdf_to_fn(bdf), iobase); - - // reset - outb(LSI_ISTAT0_SRST, iobase + LSI_REG_ISTAT0); - - int i; - for (i = 0; i < 7; i++) - lsi_scsi_scan_target(pci, iobase, i); - - return; -} - -void -lsi_scsi_setup(void) -{ - ASSERT32FLAT(); - if (!CONFIG_LSI_SCSI) - return; - - dprintf(3, "init lsi53c895a\n"); - - struct pci_device *pci; - foreachpci(pci) { - if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC - || pci->device != PCI_DEVICE_ID_LSI_53C895A) - continue; - init_lsi_scsi(pci); - } -} diff -Nru seabios-1.7.1/src/lsi-scsi.h seabios-1.7.4/src/lsi-scsi.h --- seabios-1.7.1/src/lsi-scsi.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/lsi-scsi.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#ifndef __LSI_SCSI_H -#define __LSI_SCSI_H - -struct disk_op_s; -int lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); -void lsi_scsi_setup(void); - -#endif /* __LSI_SCSI_H */ diff -Nru seabios-1.7.1/src/lzmadecode.c seabios-1.7.4/src/lzmadecode.c --- seabios-1.7.1/src/lzmadecode.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/lzmadecode.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,398 +0,0 @@ -/* - LzmaDecode.c - LZMA Decoder (optimized for Speed version) - - LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) - http://www.7-zip.org/ - - LZMA SDK is licensed under two licenses: - 1) GNU Lesser General Public License (GNU LGPL) - 2) Common Public License (CPL) - It means that you can select one of these two licenses and - follow rules of that license. - - SPECIAL EXCEPTION: - Igor Pavlov, as the author of this Code, expressly permits you to - statically or dynamically link your Code (or bind by name) to the - interfaces of this file without subjecting your linked Code to the - terms of the CPL or GNU LGPL. Any modifications or additions - to this file, however, are subject to the LGPL or CPL terms. -*/ - -#include "lzmadecode.h" - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_READ_BYTE (*Buffer++) - -#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ - { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} - - -#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } - -#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 - - -#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } - -#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) -#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; -#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; - -#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ - { UpdateBit0(p); mi <<= 1; A0; } else \ - { UpdateBit1(p); mi = (mi + mi) + 1; A1; } - -#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) - -#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ - { int i = numLevels; res = 1; \ - do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \ - res -= (1 << numLevels); } - - -#define kNumPosBitsMax 4 -#define kNumPosStatesMax (1 << kNumPosBitsMax) - -#define kLenNumLowBits 3 -#define kLenNumLowSymbols (1 << kLenNumLowBits) -#define kLenNumMidBits 3 -#define kLenNumMidSymbols (1 << kLenNumMidBits) -#define kLenNumHighBits 8 -#define kLenNumHighSymbols (1 << kLenNumHighBits) - -#define LenChoice 0 -#define LenChoice2 (LenChoice + 1) -#define LenLow (LenChoice2 + 1) -#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -#define kNumLenProbs (LenHigh + kLenNumHighSymbols) - - -#define kNumStates 12 -#define kNumLitStates 7 - -#define kStartPosModelIndex 4 -#define kEndPosModelIndex 14 -#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) - -#define kNumPosSlotBits 6 -#define kNumLenToPosStates 4 - -#define kNumAlignBits 4 -#define kAlignTableSize (1 << kNumAlignBits) - -#define kMatchMinLen 2 - -#define IsMatch 0 -#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -#define IsRepG0 (IsRep + kNumStates) -#define IsRepG1 (IsRepG0 + kNumStates) -#define IsRepG2 (IsRepG1 + kNumStates) -#define IsRep0Long (IsRepG2 + kNumStates) -#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -#define LenCoder (Align + kAlignTableSize) -#define RepLenCoder (LenCoder + kNumLenProbs) -#define Literal (RepLenCoder + kNumLenProbs) - -#if Literal != LZMA_BASE_SIZE -StopCompilingDueBUG -#endif - -int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) -{ - unsigned char prop0; - if (size < LZMA_PROPERTIES_SIZE) - return LZMA_RESULT_DATA_ERROR; - prop0 = propsData[0]; - if (prop0 >= (9 * 5 * 5)) - return LZMA_RESULT_DATA_ERROR; - { - for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); - for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); - propsRes->lc = prop0; - /* - unsigned char remainder = (unsigned char)(prop0 / 9); - propsRes->lc = prop0 % 9; - propsRes->pb = remainder / 5; - propsRes->lp = remainder % 5; - */ - } - - return LZMA_RESULT_OK; -} - -#define kLzmaStreamWasFinishedId (-1) - -int LzmaDecode(CLzmaDecoderState *vs, - const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, - unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) -{ - CProb *p = vs->Probs; - SizeT nowPos = 0; - Byte previousByte = 0; - UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; - UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; - int lc = vs->Properties.lc; - - - int state = 0; - UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; - int len = 0; - const Byte *Buffer; - const Byte *BufferLim; - UInt32 Range; - UInt32 Code; - - *inSizeProcessed = 0; - *outSizeProcessed = 0; - - { - UInt32 i; - UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); - for (i = 0; i < numProbs; i++) - p[i] = kBitModelTotal >> 1; - } - - RC_INIT(inStream, inSize); - - - while(nowPos < outSize) - { - CProb *prob; - UInt32 bound; - int posState = (int)( - (nowPos - ) - & posStateMask); - - prob = p + IsMatch + (state << kNumPosBitsMax) + posState; - IfBit0(prob) - { - int symbol = 1; - UpdateBit0(prob) - prob = p + Literal + (LZMA_LIT_SIZE * - ((( - (nowPos - ) - & literalPosMask) << lc) + (previousByte >> (8 - lc)))); - - if (state >= kNumLitStates) - { - int matchByte; - matchByte = outStream[nowPos - rep0]; - do - { - int bit; - CProb *probLit; - matchByte <<= 1; - bit = (matchByte & 0x100); - probLit = prob + 0x100 + bit + symbol; - RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) - } - while (symbol < 0x100); - } - while (symbol < 0x100) - { - CProb *probLit = prob + symbol; - RC_GET_BIT(probLit, symbol) - } - previousByte = (Byte)symbol; - - outStream[nowPos++] = previousByte; - if (state < 4) state = 0; - else if (state < 10) state -= 3; - else state -= 6; - } - else - { - UpdateBit1(prob); - prob = p + IsRep + state; - IfBit0(prob) - { - UpdateBit0(prob); - rep3 = rep2; - rep2 = rep1; - rep1 = rep0; - state = state < kNumLitStates ? 0 : 3; - prob = p + LenCoder; - } - else - { - UpdateBit1(prob); - prob = p + IsRepG0 + state; - IfBit0(prob) - { - UpdateBit0(prob); - prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; - IfBit0(prob) - { - UpdateBit0(prob); - - if (nowPos == 0) - return LZMA_RESULT_DATA_ERROR; - - state = state < kNumLitStates ? 9 : 11; - previousByte = outStream[nowPos - rep0]; - outStream[nowPos++] = previousByte; - - continue; - } - else - { - UpdateBit1(prob); - } - } - else - { - UInt32 distance; - UpdateBit1(prob); - prob = p + IsRepG1 + state; - IfBit0(prob) - { - UpdateBit0(prob); - distance = rep1; - } - else - { - UpdateBit1(prob); - prob = p + IsRepG2 + state; - IfBit0(prob) - { - UpdateBit0(prob); - distance = rep2; - } - else - { - UpdateBit1(prob); - distance = rep3; - rep3 = rep2; - } - rep2 = rep1; - } - rep1 = rep0; - rep0 = distance; - } - state = state < kNumLitStates ? 8 : 11; - prob = p + RepLenCoder; - } - { - int numBits, offset; - CProb *probLen = prob + LenChoice; - IfBit0(probLen) - { - UpdateBit0(probLen); - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - numBits = kLenNumLowBits; - } - else - { - UpdateBit1(probLen); - probLen = prob + LenChoice2; - IfBit0(probLen) - { - UpdateBit0(probLen); - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - numBits = kLenNumMidBits; - } - else - { - UpdateBit1(probLen); - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - numBits = kLenNumHighBits; - } - } - RangeDecoderBitTreeDecode(probLen, numBits, len); - len += offset; - } - - if (state < 4) - { - int posSlot; - state += kNumLitStates; - prob = p + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << - kNumPosSlotBits); - RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); - if (posSlot >= kStartPosModelIndex) - { - int numDirectBits = ((posSlot >> 1) - 1); - rep0 = (2 | ((UInt32)posSlot & 1)); - if (posSlot < kEndPosModelIndex) - { - rep0 <<= numDirectBits; - prob = p + SpecPos + rep0 - posSlot - 1; - } - else - { - numDirectBits -= kNumAlignBits; - do - { - RC_NORMALIZE - Range >>= 1; - rep0 <<= 1; - if (Code >= Range) - { - Code -= Range; - rep0 |= 1; - } - } - while (--numDirectBits != 0); - prob = p + Align; - rep0 <<= kNumAlignBits; - numDirectBits = kNumAlignBits; - } - { - int i = 1; - int mi = 1; - do - { - CProb *prob3 = prob + mi; - RC_GET_BIT2(prob3, mi, ; , rep0 |= i); - i <<= 1; - } - while(--numDirectBits != 0); - } - } - else - rep0 = posSlot; - if (++rep0 == (UInt32)(0)) - { - /* it's for stream version */ - len = kLzmaStreamWasFinishedId; - break; - } - } - - len += kMatchMinLen; - if (rep0 > nowPos) - return LZMA_RESULT_DATA_ERROR; - - - do - { - previousByte = outStream[nowPos - rep0]; - len--; - outStream[nowPos++] = previousByte; - } - while(len != 0 && nowPos < outSize); - } - } - RC_NORMALIZE; - - - *inSizeProcessed = (SizeT)(Buffer - inStream); - *outSizeProcessed = nowPos; - return LZMA_RESULT_OK; -} diff -Nru seabios-1.7.1/src/lzmadecode.h seabios-1.7.4/src/lzmadecode.h --- seabios-1.7.1/src/lzmadecode.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/lzmadecode.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -/* - LzmaDecode.h - LZMA Decoder interface - - LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) - http://www.7-zip.org/ - - LZMA SDK is licensed under two licenses: - 1) GNU Lesser General Public License (GNU LGPL) - 2) Common Public License (CPL) - It means that you can select one of these two licenses and - follow rules of that license. - - SPECIAL EXCEPTION: - Igor Pavlov, as the author of this code, expressly permits you to - statically or dynamically link your code (or bind by name) to the - interfaces of this file without subjecting your linked code to the - terms of the CPL or GNU LGPL. Any modifications or additions - to this file, however, are subject to the LGPL or CPL terms. -*/ - -#ifndef __LZMADECODE_H -#define __LZMADECODE_H - -typedef unsigned char Byte; -typedef unsigned short UInt16; -typedef unsigned int UInt32; -typedef UInt32 SizeT; - -#define CProb UInt16 - -#define LZMA_RESULT_OK 0 -#define LZMA_RESULT_DATA_ERROR 1 - - -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LZMA_PROPERTIES_SIZE 5 - -typedef struct _CLzmaProperties -{ - int lc; - int lp; - int pb; -}CLzmaProperties; - -int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); - -#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) - -#define kLzmaNeedInitId (-2) - -typedef struct _CLzmaDecoderState -{ - CLzmaProperties Properties; - CProb *Probs; - - -} CLzmaDecoderState; - - -int LzmaDecode(CLzmaDecoderState *vs, - const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, - unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); - -#endif diff -Nru seabios-1.7.1/src/malloc.c seabios-1.7.4/src/malloc.c --- seabios-1.7.1/src/malloc.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/malloc.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,528 @@ +// Internal dynamic memory allocations. +// +// Copyright (C) 2009-2013 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_BDA +#include "config.h" // BUILD_BIOS_ADDR +#include "list.h" // hlist_node +#include "malloc.h" // _malloc +#include "memmap.h" // struct e820entry +#include "output.h" // dprintf +#include "stacks.h" // wait_preempt +#include "std/optionrom.h" // OPTION_ROM_ALIGN +#include "string.h" // memset + +// Information on a reserved area. +struct allocinfo_s { + struct hlist_node node; + void *data, *dataend, *allocend; +}; + +// Information on a tracked memory allocation. +struct allocdetail_s { + struct allocinfo_s detailinfo; + struct allocinfo_s datainfo; + u32 handle; +}; + +// The various memory zones. +struct zone_s { + struct hlist_head head; +}; + +struct zone_s ZoneLow VARVERIFY32INIT, ZoneHigh VARVERIFY32INIT; +struct zone_s ZoneFSeg VARVERIFY32INIT; +struct zone_s ZoneTmpLow VARVERIFY32INIT, ZoneTmpHigh VARVERIFY32INIT; + +static struct zone_s *Zones[] VARVERIFY32INIT = { + &ZoneTmpLow, &ZoneLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh +}; + + +/**************************************************************** + * low-level memory reservations + ****************************************************************/ + +// Find and reserve space from a given zone +static void * +allocSpace(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill) +{ + struct allocinfo_s *info; + hlist_for_each_entry(info, &zone->head, node) { + void *dataend = info->dataend; + void *allocend = info->allocend; + void *newallocend = (void*)ALIGN_DOWN((u32)allocend - size, align); + if (newallocend >= dataend && newallocend <= allocend) { + // Found space - now reserve it. + if (!fill) + fill = newallocend; + fill->data = newallocend; + fill->dataend = newallocend + size; + fill->allocend = allocend; + + info->allocend = newallocend; + hlist_add_before(&fill->node, &info->node); + return newallocend; + } + } + return NULL; +} + +// Release space allocated with allocSpace() +static void +freeSpace(struct allocinfo_s *info) +{ + struct allocinfo_s *next = container_of_or_null( + info->node.next, struct allocinfo_s, node); + if (next && next->allocend == info->data) + next->allocend = info->allocend; + hlist_del(&info->node); +} + +// Add new memory to a zone +static void +addSpace(struct zone_s *zone, void *start, void *end) +{ + // Find position to add space + struct allocinfo_s *info; + struct hlist_node **pprev; + hlist_for_each_entry_pprev(info, pprev, &zone->head, node) { + if (info->data < start) + break; + } + + // Add space using temporary allocation info. + struct allocdetail_s tempdetail; + tempdetail.datainfo.data = tempdetail.datainfo.dataend = start; + tempdetail.datainfo.allocend = end; + hlist_add(&tempdetail.datainfo.node, pprev); + + // Allocate final allocation info. + struct allocdetail_s *detail = allocSpace( + &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL); + if (!detail) { + detail = allocSpace(&ZoneTmpLow, sizeof(*detail) + , MALLOC_MIN_ALIGN, NULL); + if (!detail) { + hlist_del(&tempdetail.datainfo.node); + warn_noalloc(); + return; + } + } + + // Replace temp alloc space with final alloc space + pprev = tempdetail.datainfo.node.pprev; + hlist_del(&tempdetail.datainfo.node); + memcpy(&detail->datainfo, &tempdetail.datainfo, sizeof(detail->datainfo)); + detail->handle = MALLOC_DEFAULT_HANDLE; + hlist_add(&detail->datainfo.node, pprev); +} + +// Search all zones for an allocation obtained from allocSpace() +static struct allocinfo_s * +findAlloc(void *data) +{ + int i; + for (i=0; ihead, node) { + if (info->data == data) + return info; + } + } + return NULL; +} + +// Return the last sentinal node of a zone +static struct allocinfo_s * +findLast(struct zone_s *zone) +{ + struct allocinfo_s *info, *last = NULL; + hlist_for_each_entry(info, &zone->head, node) { + last = info; + } + return last; +} + + +/**************************************************************** + * ebda movement + ****************************************************************/ + +// Move ebda +static int +relocate_ebda(u32 newebda, u32 oldebda, u8 ebda_size) +{ + u32 lowram = GET_BDA(mem_size_kb) * 1024; + if (oldebda != lowram) + // EBDA isn't at end of ram - give up. + return -1; + + // Do copy + memmove((void*)newebda, (void*)oldebda, ebda_size * 1024); + + // Update indexes + dprintf(1, "ebda moved from %x to %x\n", oldebda, newebda); + SET_BDA(mem_size_kb, newebda / 1024); + SET_BDA(ebda_seg, FLATPTR_TO_SEG(newebda)); + return 0; +} + +// Support expanding the ZoneLow dynamically. +static void * +zonelow_expand(u32 size, u32 align, struct allocinfo_s *fill) +{ + // Make sure to not move ebda while an optionrom is running. + if (unlikely(wait_preempt())) { + void *data = allocSpace(&ZoneLow, size, align, fill); + if (data) + return data; + } + + struct allocinfo_s *info = findLast(&ZoneLow); + if (!info) + return NULL; + u32 oldpos = (u32)info->allocend; + u32 newpos = ALIGN_DOWN(oldpos - size, align); + u32 bottom = (u32)info->dataend; + if (newpos >= bottom && newpos <= oldpos) + // Space already present. + return allocSpace(&ZoneLow, size, align, fill); + u16 ebda_seg = get_ebda_seg(); + u32 ebda_pos = (u32)MAKE_FLATPTR(ebda_seg, 0); + u8 ebda_size = GET_EBDA(ebda_seg, size); + u32 ebda_end = ebda_pos + ebda_size * 1024; + if (ebda_end != bottom) + // Something else is after ebda - can't use any existing space. + newpos = ALIGN_DOWN(ebda_end - size, align); + u32 newbottom = ALIGN_DOWN(newpos, 1024); + u32 newebda = ALIGN_DOWN(newbottom - ebda_size * 1024, 1024); + if (newebda < BUILD_EBDA_MINIMUM) + // Not enough space. + return NULL; + + // Move ebda + int ret = relocate_ebda(newebda, ebda_pos, ebda_size); + if (ret) + return NULL; + + // Update zone + if (ebda_end == bottom) { + info->data = (void*)newbottom; + info->dataend = (void*)newbottom; + } else + addSpace(&ZoneLow, (void*)newbottom, (void*)ebda_end); + + return allocSpace(&ZoneLow, size, align, fill); +} + + +/**************************************************************** + * tracked memory allocations + ****************************************************************/ + +// Allocate memory from the given zone and track it as a PMM allocation +void * __malloc +_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align) +{ + ASSERT32FLAT(); + if (!size) + return NULL; + + // Find and reserve space for bookkeeping. + struct allocdetail_s *detail = allocSpace( + &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL); + if (!detail) { + detail = allocSpace(&ZoneTmpLow, sizeof(*detail) + , MALLOC_MIN_ALIGN, NULL); + if (!detail) + return NULL; + } + + // Find and reserve space for main allocation + void *data = allocSpace(zone, size, align, &detail->datainfo); + if (!CONFIG_MALLOC_UPPERMEMORY && !data && zone == &ZoneLow) + data = zonelow_expand(size, align, &detail->datainfo); + if (!data) { + freeSpace(&detail->detailinfo); + return NULL; + } + + dprintf(8, "_malloc zone=%p handle=%x size=%d align=%x ret=%p (detail=%p)\n" + , zone, handle, size, align, data, detail); + detail->handle = handle; + + return data; +} + +// Free a data block allocated with _malloc +int +_free(void *data) +{ + ASSERT32FLAT(); + struct allocinfo_s *info = findAlloc(data); + if (!info || data == (void*)info || data == info->dataend) + return -1; + struct allocdetail_s *detail = container_of( + info, struct allocdetail_s, datainfo); + dprintf(8, "_free %p (detail=%p)\n", data, detail); + freeSpace(info); + freeSpace(&detail->detailinfo); + return 0; +} + +// Find the amount of free space in a given zone. +u32 +malloc_getspace(struct zone_s *zone) +{ + // XXX - doesn't account for ZoneLow being able to grow. + // XXX - results not reliable when CONFIG_THREAD_OPTIONROMS + u32 maxspace = 0; + struct allocinfo_s *info; + hlist_for_each_entry(info, &zone->head, node) { + u32 space = info->allocend - info->dataend; + if (space > maxspace) + maxspace = space; + } + + if (zone != &ZoneTmpHigh && zone != &ZoneTmpLow) + return maxspace; + // Account for space needed for PMM tracking. + u32 reserve = ALIGN(sizeof(struct allocdetail_s), MALLOC_MIN_ALIGN); + if (maxspace <= reserve) + return 0; + return maxspace - reserve; +} + +// Find the data block allocated with _malloc with a given handle. +void * +malloc_find(u32 handle) +{ + int i; + for (i=0; ihead, node) { + if (info->data != (void*)info) + continue; + struct allocdetail_s *detail = container_of( + info, struct allocdetail_s, detailinfo); + if (detail->handle == handle) + return detail->datainfo.data; + } + } + return NULL; +} + + +/**************************************************************** + * 0xc0000-0xf0000 management + ****************************************************************/ + +static u32 RomEnd = BUILD_ROM_START; +static struct allocinfo_s *RomBase; + +#define OPROM_HEADER_RESERVE 16 + +// Return the maximum memory position option roms may use. +u32 +rom_get_max(void) +{ + if (CONFIG_MALLOC_UPPERMEMORY) + return ALIGN_DOWN((u32)RomBase->allocend - OPROM_HEADER_RESERVE + , OPTION_ROM_ALIGN); + extern u8 final_readonly_start[]; + return (u32)final_readonly_start; +} + +// Return the end of the last deployed option rom. +u32 +rom_get_last(void) +{ + return RomEnd; +} + +// Request space for an optionrom in 0xc0000-0xf0000 area. +struct rom_header * +rom_reserve(u32 size) +{ + u32 newend = ALIGN(RomEnd + size, OPTION_ROM_ALIGN); + if (newend > rom_get_max()) + return NULL; + if (CONFIG_MALLOC_UPPERMEMORY) { + if (newend < (u32)zonelow_base) + newend = (u32)zonelow_base; + RomBase->data = RomBase->dataend = (void*)newend + OPROM_HEADER_RESERVE; + } + return (void*)RomEnd; +} + +// Confirm space as in use by an optionrom. +int +rom_confirm(u32 size) +{ + void *new = rom_reserve(size); + if (!new) { + warn_noalloc(); + return -1; + } + RomEnd = ALIGN(RomEnd + size, OPTION_ROM_ALIGN); + return 0; +} + + +/**************************************************************** + * Setup + ****************************************************************/ + +void +malloc_preinit(void) +{ + ASSERT32FLAT(); + dprintf(3, "malloc preinit\n"); + + // Don't declare any memory between 0xa0000 and 0x100000 + add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE); + + // Mark known areas as reserved. + add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED); + + // Populate temp high ram + u32 highram = 0; + int i; + for (i=e820_count-1; i>=0; i--) { + struct e820entry *en = &e820_list[i]; + u64 end = en->start + en->size; + if (end < 1024*1024) + break; + if (en->type != E820_RAM || end > 0xffffffff) + continue; + u32 s = en->start, e = end; + if (!highram) { + u32 newe = ALIGN_DOWN(e - BUILD_MAX_HIGHTABLE, MALLOC_MIN_ALIGN); + if (newe <= e && newe >= s) { + highram = newe; + e = newe; + } + } + addSpace(&ZoneTmpHigh, (void*)s, (void*)e); + } + + // Populate regions + addSpace(&ZoneTmpLow, (void*)BUILD_STACK_ADDR, (void*)BUILD_EBDA_MINIMUM); + if (highram) { + addSpace(&ZoneHigh, (void*)highram + , (void*)highram + BUILD_MAX_HIGHTABLE); + add_e820(highram, BUILD_MAX_HIGHTABLE, E820_RESERVED); + } +} + +void +csm_malloc_preinit(u32 low_pmm, u32 low_pmm_size, u32 hi_pmm, u32 hi_pmm_size) +{ + ASSERT32FLAT(); + + if (hi_pmm_size > BUILD_MAX_HIGHTABLE) { + void *hi_pmm_end = (void *)hi_pmm + hi_pmm_size; + addSpace(&ZoneTmpHigh, (void *)hi_pmm, hi_pmm_end - BUILD_MAX_HIGHTABLE); + addSpace(&ZoneHigh, hi_pmm_end - BUILD_MAX_HIGHTABLE, hi_pmm_end); + } else { + addSpace(&ZoneTmpHigh, (void *)hi_pmm, (void *)hi_pmm + hi_pmm_size); + } + addSpace(&ZoneTmpLow, (void *)low_pmm, (void *)low_pmm + low_pmm_size); +} + +u32 LegacyRamSize VARFSEG; + +// Calculate the maximum ramsize (less than 4gig) from e820 map. +static void +calcRamSize(void) +{ + u32 rs = 0; + int i; + for (i=e820_count-1; i>=0; i--) { + struct e820entry *en = &e820_list[i]; + u64 end = en->start + en->size; + u32 type = en->type; + if (end <= 0xffffffff && (type == E820_ACPI || type == E820_RAM)) { + rs = end; + break; + } + } + LegacyRamSize = rs >= 1024*1024 ? rs : 1024*1024; +} + +// Update pointers after code relocation. +void +malloc_init(void) +{ + ASSERT32FLAT(); + dprintf(3, "malloc init\n"); + + if (CONFIG_RELOCATE_INIT) { + // Fixup malloc pointers after relocation + int i; + for (i=0; ihead.first) + zone->head.first->pprev = &zone->head.first; + } + } + + // Initialize low-memory region + extern u8 varlow_start[], varlow_end[], final_varlow_start[]; + memmove(final_varlow_start, varlow_start, varlow_end - varlow_start); + if (CONFIG_MALLOC_UPPERMEMORY) { + addSpace(&ZoneLow, zonelow_base + OPROM_HEADER_RESERVE + , final_varlow_start); + RomBase = findLast(&ZoneLow); + } else { + addSpace(&ZoneLow, (void*)ALIGN_DOWN((u32)final_varlow_start, 1024) + , final_varlow_start); + } + + // Add space available in f-segment to ZoneFSeg + extern u8 zonefseg_start[], zonefseg_end[]; + memset(zonefseg_start, 0, zonefseg_end - zonefseg_start); + addSpace(&ZoneFSeg, zonefseg_start, zonefseg_end); + + calcRamSize(); +} + +void +malloc_prepboot(void) +{ + ASSERT32FLAT(); + dprintf(3, "malloc finalize\n"); + + u32 base = rom_get_max(); + memset((void*)RomEnd, 0, base-RomEnd); + if (CONFIG_MALLOC_UPPERMEMORY) { + // Place an optionrom signature around used low mem area. + struct rom_header *dummyrom = (void*)base; + dummyrom->signature = OPTION_ROM_SIGNATURE; + int size = (BUILD_BIOS_ADDR - base) / 512; + dummyrom->size = (size > 255) ? 255 : size; + } + + // Reserve more low-mem if needed. + u32 endlow = GET_BDA(mem_size_kb)*1024; + add_e820(endlow, BUILD_LOWRAM_END-endlow, E820_RESERVED); + + // Clear unused f-seg ram. + struct allocinfo_s *info = findLast(&ZoneFSeg); + memset(info->dataend, 0, info->allocend - info->dataend); + dprintf(1, "Space available for UMB: %x-%x, %x-%x\n" + , RomEnd, base, (u32)info->dataend, (u32)info->allocend); + + // Give back unused high ram. + info = findLast(&ZoneHigh); + if (info) { + u32 giveback = ALIGN_DOWN(info->allocend - info->dataend, PAGE_SIZE); + add_e820((u32)info->dataend, giveback, E820_RAM); + dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback); + } + + calcRamSize(); +} diff -Nru seabios-1.7.1/src/malloc.h seabios-1.7.4/src/malloc.h --- seabios-1.7.1/src/malloc.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/malloc.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,70 @@ +#ifndef __MALLOC_H +#define __MALLOC_H + +#include "types.h" // u32 + +// malloc.c +extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh; +u32 rom_get_max(void); +u32 rom_get_last(void); +struct rom_header *rom_reserve(u32 size); +int rom_confirm(u32 size); +void csm_malloc_preinit(u32 low_pmm, u32 low_pmm_size, u32 hi_pmm, + u32 hi_pmm_size); +void malloc_preinit(void); +extern u32 LegacyRamSize; +void malloc_init(void); +void malloc_prepboot(void); +void *_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align); +int _free(void *data); +u32 malloc_getspace(struct zone_s *zone); +void *malloc_find(u32 handle); + +#define MALLOC_DEFAULT_HANDLE 0xFFFFFFFF +// Minimum alignment of malloc'd memory +#define MALLOC_MIN_ALIGN 16 +// Helper functions for memory allocation. +static inline void *malloc_low(u32 size) { + return _malloc(&ZoneLow, MALLOC_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); +} +static inline void *malloc_high(u32 size) { + return _malloc(&ZoneHigh, MALLOC_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); +} +static inline void *malloc_fseg(u32 size) { + return _malloc(&ZoneFSeg, MALLOC_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); +} +static inline void *malloc_tmplow(u32 size) { + return _malloc(&ZoneTmpLow, MALLOC_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); +} +static inline void *malloc_tmphigh(u32 size) { + return _malloc(&ZoneTmpHigh, MALLOC_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); +} +static inline void *malloc_tmp(u32 size) { + void *ret = malloc_tmphigh(size); + if (ret) + return ret; + return malloc_tmplow(size); +} +static inline void *memalign_low(u32 align, u32 size) { + return _malloc(&ZoneLow, MALLOC_DEFAULT_HANDLE, size, align); +} +static inline void *memalign_high(u32 align, u32 size) { + return _malloc(&ZoneHigh, MALLOC_DEFAULT_HANDLE, size, align); +} +static inline void *memalign_tmplow(u32 align, u32 size) { + return _malloc(&ZoneTmpLow, MALLOC_DEFAULT_HANDLE, size, align); +} +static inline void *memalign_tmphigh(u32 align, u32 size) { + return _malloc(&ZoneTmpHigh, MALLOC_DEFAULT_HANDLE, size, align); +} +static inline void *memalign_tmp(u32 align, u32 size) { + void *ret = memalign_tmphigh(align, size); + if (ret) + return ret; + return memalign_tmplow(align, size); +} +static inline void free(void *data) { + _free(data); +} + +#endif // malloc.h diff -Nru seabios-1.7.1/src/memmap.c seabios-1.7.4/src/memmap.c --- seabios-1.7.1/src/memmap.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/memmap.c 2013-12-23 15:40:06.000000000 +0000 @@ -4,15 +4,20 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. +#include "config.h" // BUILD_MAX_E820 #include "memmap.h" // struct e820entry -#include "config.h" // CONFIG_* -#include "util.h" // dprintf.h +#include "output.h" // dprintf +#include "string.h" // memmove /**************************************************************** * e820 memory map ****************************************************************/ +// Info on e820 map location and size. +struct e820entry e820_list[BUILD_MAX_E820] VARFSEG; +int e820_count VARFSEG; + // Remove an entry from the e820_list. static void remove_e820(int i) @@ -26,7 +31,7 @@ static void insert_e820(int i, u64 start, u64 size, u32 type) { - if (e820_count >= CONFIG_MAX_E820) { + if (e820_count >= BUILD_MAX_E820) { warn_noalloc(); return; } @@ -133,7 +138,7 @@ // Report on final memory locations. void -memmap_finalize(void) +memmap_prepboot(void) { dump_map(); } diff -Nru seabios-1.7.1/src/memmap.h seabios-1.7.4/src/memmap.h --- seabios-1.7.1/src/memmap.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/memmap.h 2013-12-23 15:40:06.000000000 +0000 @@ -17,16 +17,13 @@ }; void add_e820(u64 start, u64 size, u32 type); -void memmap_finalize(void); +void memmap_prepboot(void); // A typical OS page size #define PAGE_SIZE 4096 -// e820 map storage (defined in system.c) +// e820 map storage extern struct e820entry e820_list[]; extern int e820_count; -// Space for exported bios tables (defined in misc.c) -extern char BiosTableSpace[]; - #endif // e820map.h diff -Nru seabios-1.7.1/src/misc.c seabios-1.7.4/src/misc.c --- seabios-1.7.1/src/misc.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/misc.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,17 +5,14 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "bregs.h" // struct bregs #include "biosvar.h" // GET_BDA -#include "util.h" // debug_enter -#include "pic.h" // enable_hwirq +#include "bregs.h" // struct bregs +#include "hw/pic.h" // enable_hwirq +#include "output.h" // debug_enter +#include "stacks.h" // call16_int +#include "string.h" // memset -// Amount of continuous ram under 4Gig -u32 RamSize VAR16VISIBLE; -// Amount of continuous ram >4Gig -u64 RamSizeOver4G; -// Space for bios tables built an run-time. -char BiosTableSpace[CONFIG_MAX_BIOSTABLE] __aligned(MALLOC_MIN_ALIGN) VAR16VISIBLE; +#define PORT_MATH_CLEAR 0x00f0 /**************************************************************** @@ -78,7 +75,7 @@ // clear irq13 outb(0, PORT_MATH_CLEAR); // clear interrupt - eoi_pic2(); + pic_eoi2(); // legacy nmi call struct bregs br; memset(&br, 0, sizeof(br)); @@ -113,9 +110,9 @@ struct bios_config_table_s BIOS_CONFIG_TABLE VAR16FIXED(0xe6f5) = { .size = sizeof(BIOS_CONFIG_TABLE) - 2, - .model = CONFIG_MODEL_ID, - .submodel = CONFIG_SUBMODEL_ID, - .biosrev = CONFIG_BIOS_REVISION, + .model = BUILD_MODEL_ID, + .submodel = BUILD_SUBMODEL_ID, + .biosrev = BUILD_BIOS_REVISION, .feature1 = ( CBT_F1_2NDPIC | CBT_F1_RTC | CBT_F1_EBDA | (CONFIG_KBD_CALL_INT15_4F ? CBT_F1_INT154F : 0)), @@ -131,23 +128,23 @@ ****************************************************************/ // Real mode IDT descriptor -struct descloc_s rmode_IDT_info VAR16VISIBLE = { +struct descloc_s rmode_IDT_info VARFSEG = { .length = sizeof(struct rmode_IVT) - 1, .addr = (u32)MAKE_FLATPTR(SEG_IVT, 0), }; // Dummy IDT that forces a machine shutdown if an irq happens in // protected mode. -u8 dummy_IDT VAR16VISIBLE; +u8 dummy_IDT VARFSEG; // Protected mode IDT descriptor -struct descloc_s pmode_IDT_info VAR16VISIBLE = { +struct descloc_s pmode_IDT_info VARFSEG = { .length = sizeof(dummy_IDT) - 1, - .addr = (u32)MAKE_FLATPTR(SEG_BIOS, &dummy_IDT), + .addr = (u32)&dummy_IDT, }; // GDT -u64 rombios32_gdt[] VAR16VISIBLE __aligned(8) = { +u64 rombios32_gdt[] VARFSEG __aligned(8) = { // First entry can't be used. 0x0000000000000000LL, // 32 bit flat code segment (SEG32_MODE32_CS) @@ -165,9 +162,9 @@ }; // GDT descriptor -struct descloc_s rombios32_gdt_48 VAR16VISIBLE = { +struct descloc_s rombios32_gdt_48 VARFSEG = { .length = sizeof(rombios32_gdt) - 1, - .addr = (u32)MAKE_FLATPTR(SEG_BIOS, rombios32_gdt), + .addr = (u32)rombios32_gdt, }; @@ -181,7 +178,7 @@ // BIOS build date char BiosDate[] VAR16FIXED(0xfff5) = "06/23/99"; -u8 BiosModelId VAR16FIXED(0xfffe) = CONFIG_MODEL_ID; +u8 BiosModelId VAR16FIXED(0xfffe) = BUILD_MODEL_ID; u8 BiosChecksum VAR16FIXED(0xffff); diff -Nru seabios-1.7.1/src/mouse.c seabios-1.7.4/src/mouse.c --- seabios-1.7.1/src/mouse.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/mouse.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,13 +6,15 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "biosvar.h" // GET_EBDA -#include "util.h" // dprintf #include "bregs.h" // struct bregs -#include "ps2port.h" // ps2_mouse_command -#include "usb-hid.h" // usb_mouse_command +#include "hw/ps2port.h" // ps2_mouse_command +#include "hw/usb-hid.h" // usb_mouse_command +#include "output.h" // dprintf +#include "stacks.h" // stack_hop +#include "util.h" // mouse_init void -mouse_setup(void) +mouse_init(void) { if (! CONFIG_MOUSE) return; diff -Nru seabios-1.7.1/src/mptable.c seabios-1.7.4/src/mptable.c --- seabios-1.7.1/src/mptable.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/mptable.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +0,0 @@ -// MPTable generation (on emulators) -// -// Copyright (C) 2008-2010 Kevin O'Connor -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "config.h" // CONFIG_* -#include "mptable.h" // MPTABLE_SIGNATURE -#include "paravirt.h" // qemu_cfg_irq0_override -#include "pci.h" -#include "pci_regs.h" - -void -mptable_init(void) -{ - if (! CONFIG_MPTABLE) - return; - - dprintf(3, "init MPTable\n"); - - // Config structure in temp area. - struct mptable_config_s *config = malloc_tmp(32*1024); - if (!config) { - warn_noalloc(); - return; - } - memset(config, 0, sizeof(*config)); - config->signature = MPCONFIG_SIGNATURE; - config->spec = 4; - memcpy(config->oemid, CONFIG_CPUNAME8, sizeof(config->oemid)); - memcpy(config->productid, "0.1 ", sizeof(config->productid)); - config->lapic = BUILD_APIC_ADDR; - - // Detect cpu info - u32 cpuid_signature, ebx, ecx, cpuid_features; - cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features); - if (! cpuid_signature) { - // Use default values. - cpuid_signature = 0x600; - cpuid_features = 0x201; - } - int pkgcpus = 1; - if (cpuid_features & (1 << 28)) { - /* Only populate the MPS tables with the first logical CPU in - each package */ - pkgcpus = (ebx >> 16) & 0xff; - pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */ - } - u8 apic_version = readl((u8*)BUILD_APIC_ADDR + 0x30) & 0xff; - - // CPU definitions. - struct mpt_cpu *cpus = (void*)&config[1], *cpu = cpus; - int i; - for (i = 0; i < MaxCountCPUs; i+=pkgcpus) { - memset(cpu, 0, sizeof(*cpu)); - cpu->type = MPT_TYPE_CPU; - cpu->apicid = i; - cpu->apicver = apic_version; - /* cpu flags: enabled, bootstrap cpu */ - cpu->cpuflag = (apic_id_is_present(i) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00); - cpu->cpusignature = cpuid_signature; - cpu->featureflag = cpuid_features; - cpu++; - } - int entrycount = cpu - cpus; - - // PCI buses - struct mpt_bus *buses = (void*)cpu, *bus = buses; - int lastbus = -1; - struct pci_device *pci; - foreachpci(pci) { - int curbus = pci_bdf_to_bus(pci->bdf); - if (curbus == lastbus) - continue; - lastbus = curbus; - memset(bus, 0, sizeof(*bus)); - bus->type = MPT_TYPE_BUS; - bus->busid = curbus; - memcpy(bus->bustype, "PCI ", sizeof(bus->bustype)); - bus++; - } - - /* isa bus */ - int isabusid; - memset(bus, 0, sizeof(*bus)); - bus->type = MPT_TYPE_BUS; - isabusid = bus->busid = lastbus + 1; - memcpy(bus->bustype, "ISA ", sizeof(bus->bustype)); - bus++; - entrycount += bus - buses; - - /* ioapic */ - u8 ioapic_id = BUILD_IOAPIC_ID; - struct mpt_ioapic *ioapic = (void*)bus; - memset(ioapic, 0, sizeof(*ioapic)); - ioapic->type = MPT_TYPE_IOAPIC; - ioapic->apicid = ioapic_id; - ioapic->apicver = 0x11; - ioapic->flags = 1; // enable - ioapic->apicaddr = BUILD_IOAPIC_ADDR; - entrycount++; - - /* irqs */ - struct mpt_intsrc *intsrcs = (void*)&ioapic[1], *intsrc = intsrcs; - int dev = -1; - unsigned short mask = 0, pinmask = 0; - - foreachpci(pci) { - u16 bdf = pci->bdf; - int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); - int irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); - if (pin == 0) - continue; - if (dev != pci_bdf_to_busdev(bdf)) { - dev = pci_bdf_to_busdev(bdf); - pinmask = 0; - } - if (pinmask & (1 << pin)) /* pin was seen already */ - continue; - pinmask |= (1 << pin); - mask |= (1 << irq); - memset(intsrc, 0, sizeof(*intsrc)); - intsrc->type = MPT_TYPE_INTSRC; - intsrc->irqtype = 0; /* INT */ - intsrc->irqflag = 1; /* active high */ - intsrc->srcbus = pci_bdf_to_bus(bdf); /* PCI bus */ - intsrc->srcbusirq = (pci_bdf_to_dev(bdf) << 2) | (pin - 1); - intsrc->dstapic = ioapic_id; - intsrc->dstirq = irq; - intsrc++; - } - - for (i = 0; i < 16; i++) { - memset(intsrc, 0, sizeof(*intsrc)); - if (mask & (1 << i)) - continue; - intsrc->type = MPT_TYPE_INTSRC; - intsrc->irqtype = 0; /* INT */ - intsrc->irqflag = 0; /* conform to bus spec */ - intsrc->srcbus = isabusid; /* ISA bus */ - intsrc->srcbusirq = i; - intsrc->dstapic = ioapic_id; - intsrc->dstirq = i; - if (qemu_cfg_irq0_override()) { - /* Destination 2 is covered by irq0->inti2 override (i == - 0). Source IRQ 2 is unused */ - if (i == 0) - intsrc->dstirq = 2; - else if (i == 2) - intsrc--; - } - intsrc++; - } - - /* Local interrupt assignment */ - intsrc->type = MPT_TYPE_LOCAL_INT; - intsrc->irqtype = 3; /* ExtINT */ - intsrc->irqflag = 0; /* PO, EL default */ - intsrc->srcbus = isabusid; /* ISA */ - intsrc->srcbusirq = 0; - intsrc->dstapic = 0; /* BSP == APIC #0 */ - intsrc->dstirq = 0; /* LINTIN0 */ - intsrc++; - - intsrc->type = MPT_TYPE_LOCAL_INT; - intsrc->irqtype = 1; /* NMI */ - intsrc->irqflag = 0; /* PO, EL default */ - intsrc->srcbus = isabusid; /* ISA */ - intsrc->srcbusirq = 0; - intsrc->dstapic = 0xff; /* to all local APICs */ - intsrc->dstirq = 1; /* LINTIN1 */ - intsrc++; - entrycount += intsrc - intsrcs; - - // Finalize config structure. - int length = (void*)intsrc - (void*)config; - config->entrycount = entrycount; - config->length = length; - config->checksum -= checksum(config, length); - - // Allocate final memory locations. (In theory the config - // structure can go in high memory, but Linux kernels before - // v2.6.30 crash with that.) - struct mptable_config_s *finalconfig = malloc_fseg(length); - struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating)); - if (!finalconfig || !floating) { - warn_noalloc(); - free(config); - free(finalconfig); - free(floating); - return; - } - memcpy(finalconfig, config, length); - free(config); - - /* floating pointer structure */ - memset(floating, 0, sizeof(*floating)); - floating->signature = MPTABLE_SIGNATURE; - floating->physaddr = (u32)finalconfig; - floating->length = 1; - floating->spec_rev = 4; - floating->checksum -= checksum(floating, sizeof(*floating)); - - dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n", - floating, finalconfig, length); -} diff -Nru seabios-1.7.1/src/mptable.h seabios-1.7.4/src/mptable.h --- seabios-1.7.1/src/mptable.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/mptable.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -#ifndef __MPTABLE_H -#define __MPTABLE_H - -#include "types.h" // u32 - -#define MPTABLE_SIGNATURE 0x5f504d5f // "_MP_" - -struct mptable_floating_s { - u32 signature; - u32 physaddr; - u8 length; - u8 spec_rev; - u8 checksum; - u8 feature1; - u8 feature2; - u8 reserved[3]; -}; - -#define MPCONFIG_SIGNATURE 0x504d4350 // "PCMP" - -struct mptable_config_s { - u32 signature; - u16 length; - u8 spec; - u8 checksum; - char oemid[8]; - char productid[12]; - u32 oemptr; - u16 oemsize; - u16 entrycount; - u32 lapic; - u16 exttable_length; - u8 exttable_checksum; - u8 reserved; -} PACKED; - -#define MPT_TYPE_CPU 0 -#define MPT_TYPE_BUS 1 -#define MPT_TYPE_IOAPIC 2 -#define MPT_TYPE_INTSRC 3 -#define MPT_TYPE_LOCAL_INT 4 - -struct mpt_cpu { - u8 type; - u8 apicid; - u8 apicver; - u8 cpuflag; - u32 cpusignature; - u32 featureflag; - u32 reserved[2]; -} PACKED; - -struct mpt_bus { - u8 type; - u8 busid; - char bustype[6]; -} PACKED; - -struct mpt_ioapic { - u8 type; - u8 apicid; - u8 apicver; - u8 flags; - u32 apicaddr; -} PACKED; - -struct mpt_intsrc { - u8 type; - u8 irqtype; - u16 irqflag; - u8 srcbus; - u8 srcbusirq; - u8 dstapic; - u8 dstirq; -} PACKED; - -// mptable.c -void mptable_init(void); - -#endif // mptable.h diff -Nru seabios-1.7.1/src/mtrr.c seabios-1.7.4/src/mtrr.c --- seabios-1.7.1/src/mtrr.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/mtrr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -// Initialize MTRRs - mostly useful on KVM. -// -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "config.h" // CONFIG_* -#include "xen.h" // usingXen - -#define MSR_MTRRcap 0x000000fe -#define MSR_MTRRfix64K_00000 0x00000250 -#define MSR_MTRRfix16K_80000 0x00000258 -#define MSR_MTRRfix16K_A0000 0x00000259 -#define MSR_MTRRfix4K_C0000 0x00000268 -#define MSR_MTRRfix4K_C8000 0x00000269 -#define MSR_MTRRfix4K_D0000 0x0000026a -#define MSR_MTRRfix4K_D8000 0x0000026b -#define MSR_MTRRfix4K_E0000 0x0000026c -#define MSR_MTRRfix4K_E8000 0x0000026d -#define MSR_MTRRfix4K_F0000 0x0000026e -#define MSR_MTRRfix4K_F8000 0x0000026f -#define MSR_MTRRdefType 0x000002ff - -#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) -#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) - -#define MTRR_MEMTYPE_UC 0 -#define MTRR_MEMTYPE_WC 1 -#define MTRR_MEMTYPE_WT 4 -#define MTRR_MEMTYPE_WP 5 -#define MTRR_MEMTYPE_WB 6 - -void mtrr_setup(void) -{ - if (!CONFIG_MTRR_INIT || CONFIG_COREBOOT || usingXen()) - return; - - u32 eax, ebx, ecx, edx, cpuid_features; - cpuid(1, &eax, &ebx, &ecx, &cpuid_features); - if (!(cpuid_features & CPUID_MTRR)) - return; - if (!(cpuid_features & CPUID_MSR)) - return; - - dprintf(3, "init mtrr\n"); - - u32 mtrr_cap = rdmsr(MSR_MTRRcap); - int vcnt = mtrr_cap & 0xff; - int fix = mtrr_cap & 0x100; - if (!vcnt || !fix) - return; - - // Disable MTRRs - wrmsr_smp(MSR_MTRRdefType, 0); - - // Set fixed MTRRs - union u64b { - u8 valb[8]; - u64 val; - } u; - u.val = 0; - int i; - for (i = 0; i < 8; i++) - if (RamSize >= 65536 * (i + 1)) - u.valb[i] = MTRR_MEMTYPE_WB; - wrmsr_smp(MSR_MTRRfix64K_00000, u.val); - u.val = 0; - for (i = 0; i < 8; i++) - if (RamSize >= 0x80000 + 16384 * (i + 1)) - u.valb[i] = MTRR_MEMTYPE_WB; - wrmsr_smp(MSR_MTRRfix16K_80000, u.val); - wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached - int j; - for (j = 0; j < 8; j++) { - u.val = 0; - for (i = 0; i < 8; i++) - if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1)) - u.valb[i] = MTRR_MEMTYPE_WP; - wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val); - } - - // Set variable MTRRs - int phys_bits = 36; - cpuid(0x80000000u, &eax, &ebx, &ecx, &edx); - if (eax >= 0x80000008) { - /* Get physical bits from leaf 0x80000008 (if available) */ - cpuid(0x80000008u, &eax, &ebx, &ecx, &edx); - phys_bits = eax & 0xff; - } - u64 phys_mask = ((1ull << phys_bits) - 1); - for (i=0; ipcioffset); if (pd->signature != PCI_ROM_SIGNATURE) return NULL; + if (rom->pcioffset & 3) + dprintf(1, "WARNING! Found unaligned PCI rom (vd=%04x:%04x)\n" + , pd->vendor, pd->device); return pd; } @@ -210,7 +218,7 @@ ****************************************************************/ // Verify device is a vga device with legacy address decoding enabled. -static int +int is_pci_vga(struct pci_device *pci) { if (pci->class != PCI_CLASS_DISPLAY_VGA) @@ -351,7 +359,7 @@ if (CONFIG_OPTIONROMS_DEPLOYED) { // Option roms are already deployed on the system. u32 pos = post_vga; - while (pos < rom_get_top()) { + while (pos < rom_get_max()) { int ret = init_optionrom((void*)pos, 0, 0); if (ret) pos += OPTION_ROM_ALIGN; @@ -410,13 +418,13 @@ * VGA init ****************************************************************/ -static int S3ResumeVgaInit; +static int S3ResumeVga; int ScreenAndDebug; struct rom_header *VgaROM; // Call into vga code to turn on console. void -vga_setup(void) +vgarom_setup(void) { if (! CONFIG_OPTIONROMS) return; @@ -425,7 +433,7 @@ // Load some config settings that impact VGA. EnforceChecksum = romfile_loadint("etc/optionroms-checksum", 1); - S3ResumeVgaInit = romfile_loadint("etc/s3-resume-vga-init", !CONFIG_COREBOOT); + S3ResumeVga = romfile_loadint("etc/s3-resume-vga-init", CONFIG_QEMU); ScreenAndDebug = romfile_loadint("etc/screen-and-debug", 1); if (CONFIG_OPTIONROMS_DEPLOYED) { @@ -433,7 +441,7 @@ init_optionrom((void*)BUILD_ROM_START, 0, 1); } else { // Clear option rom memory - memset((void*)BUILD_ROM_START, 0, rom_get_top() - BUILD_ROM_START); + memset((void*)BUILD_ROM_START, 0, rom_get_max() - BUILD_ROM_START); // Find and deploy PCI VGA rom. struct pci_device *pci; @@ -459,9 +467,9 @@ } void -s3_resume_vga_init(void) +s3_resume_vga(void) { - if (!S3ResumeVgaInit) + if (!S3ResumeVga) return; if (!VgaROM || ! is_valid_rom(VgaROM)) return; diff -Nru seabios-1.7.1/src/optionroms.h seabios-1.7.4/src/optionroms.h --- seabios-1.7.1/src/optionroms.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/optionroms.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#ifndef __OPTIONROMS_H -#define __OPTIONROMS_H - -#include "types.h" // u32 - -#define OPTION_ROM_SIGNATURE 0xaa55 - -struct rom_header { - u16 signature; - u8 size; - u8 initVector[4]; - u8 reserved[17]; - u16 pcioffset; - u16 pnpoffset; -} PACKED; - -#define PCI_ROM_SIGNATURE 0x52494350 // "PCIR" - -struct pci_data { - u32 signature; - u16 vendor; - u16 device; - u16 vitaldata; - u16 dlen; - u8 drevision; - u8 class_lo; - u16 class_hi; - u16 ilen; - u16 irevision; - u8 type; - u8 indicator; - u16 reserved; -} PACKED; - -struct pnp_data { - u32 signature; - u8 revision; - u8 len; - u16 nextoffset; - u8 reserved_08; - u8 checksum; - u32 devid; - u16 manufacturer; - u16 productname; - u8 type_lo; - u16 type_hi; - u8 dev_flags; - u16 bcv; - u16 dv; - u16 bev; - u16 reserved_1c; - u16 staticresource; -} PACKED; - -#define OPTION_ROM_ALIGN 2048 -#define OPTION_ROM_INITVECTOR offsetof(struct rom_header, initVector[0]) -#define PCIROM_CODETYPE_X86 0 - -#endif diff -Nru seabios-1.7.1/src/output.c seabios-1.7.4/src/output.c --- seabios-1.7.1/src/output.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/output.c 2013-12-23 15:40:06.000000000 +0000 @@ -1,16 +1,21 @@ // Raw screen writing and debug output code. // -// Copyright (C) 2008,2009 Kevin O'Connor +// Copyright (C) 2008-2013 Kevin O'Connor // // This file may be distributed under the terms of the GNU LGPLv3 license. #include // va_list #include "farptr.h" // GET_VAR -#include "util.h" // printf #include "bregs.h" // struct bregs #include "config.h" // CONFIG_* #include "biosvar.h" // GET_GLOBAL +#include "hw/serialio.h" // serial_debug_putc +#include "malloc.h" // malloc_tmp +#include "output.h" // dprintf +#include "stacks.h" // call16_int +#include "string.h" // memset +#include "util.h" // ScreenAndDebug struct putcinfo { void (*func)(struct putcinfo *info, char c); @@ -21,79 +26,41 @@ * Debug output ****************************************************************/ -#define DEBUG_TIMEOUT 100000 - -u16 DebugOutputPort VAR16VISIBLE = 0x402; - +// Setup debugging port(s). void -debug_serial_setup(void) +debug_preinit(void) { - if (!CONFIG_DEBUG_SERIAL) - return; - // setup for serial logging: 8N1 - u8 oldparam, newparam = 0x03; - oldparam = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); - outb(newparam, CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); - // Disable irqs - u8 oldier, newier = 0; - oldier = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); - outb(newier, CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); - - if (oldparam != newparam || oldier != newier) - dprintf(1, "Changing serial settings was %x/%x now %x/%x\n" - , oldparam, oldier, newparam, newier); + serial_debug_preinit(); } -// Write a character to the serial port. -static void -debug_serial(char c) -{ - if (!CONFIG_DEBUG_SERIAL) - return; - int timeout = DEBUG_TIMEOUT; - while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x20) != 0x20) - if (!timeout--) - // Ran out of time. - return; - outb(c, CONFIG_DEBUG_SERIAL_PORT+SEROFF_DATA); -} - -// Make sure all serial port writes have been completely sent. +// Write a character to debug port(s). static void -debug_serial_flush(void) +debug_putc(struct putcinfo *action, char c) { - if (!CONFIG_DEBUG_SERIAL) + if (! CONFIG_DEBUG_LEVEL) return; - int timeout = DEBUG_TIMEOUT; - while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x60) != 0x60) - if (!timeout--) - // Ran out of time. - return; + qemu_debug_putc(c); + if (!MODESEGMENT) + coreboot_debug_putc(c); + serial_debug_putc(c); } -// Write a character to debug port(s). +// Flush any pending output to debug port(s). static void -putc_debug(struct putcinfo *action, char c) +debug_flush(void) { - if (! CONFIG_DEBUG_LEVEL) - return; - if (CONFIG_DEBUG_IO) - // Send character to debug port. - outb(c, GET_GLOBAL(DebugOutputPort)); - if (c == '\n') - debug_serial('\r'); - debug_serial(c); + serial_debug_flush(); } -// In segmented mode just need a dummy variable (putc_debug is always +// In segmented mode just need a dummy variable (debug_putc is always // used anyway), and in 32bit flat mode need a pointer to the 32bit -// instance of putc_debug(). +// instance of debug_putc(). #if MODE16 static struct putcinfo debuginfo VAR16; #elif MODESEGMENT static struct putcinfo debuginfo VAR32SEG; #else -static struct putcinfo debuginfo = { putc_debug }; +static struct putcinfo debuginfo = { debug_putc }; #endif @@ -115,16 +82,16 @@ // Handle a character from a printf request. static void -putc_screen(struct putcinfo *action, char c) +screen_putc(struct putcinfo *action, char c) { if (ScreenAndDebug) - putc_debug(&debuginfo, c); + debug_putc(&debuginfo, c); if (c == '\n') screenc('\r'); screenc(c); } -static struct putcinfo screeninfo = { putc_screen }; +static struct putcinfo screeninfo = { screen_putc }; /**************************************************************** @@ -137,7 +104,7 @@ { if (MODESEGMENT) { // Only debugging output supported in segmented mode. - putc_debug(action, c); + debug_putc(action, c); return; } @@ -340,7 +307,7 @@ va_start(args, fmt); bvprintf(&debuginfo, fmt, args); va_end(args); - debug_serial_flush(); + debug_flush(); } // XXX - use PANIC PORT. @@ -357,10 +324,10 @@ struct thread_info *cur = getCurThread(); if (cur != &MainThread) { // Show "thread id" for this debug message. - putc_debug(&debuginfo, '|'); + debug_putc(&debuginfo, '|'); puthex(&debuginfo, (u32)cur, 8); - putc_debug(&debuginfo, '|'); - putc_debug(&debuginfo, ' '); + debug_putc(&debuginfo, '|'); + debug_putc(&debuginfo, ' '); } } @@ -368,7 +335,7 @@ va_start(args, fmt); bvprintf(&debuginfo, fmt, args); va_end(args); - debug_serial_flush(); + debug_flush(); } void @@ -380,7 +347,7 @@ bvprintf(&screeninfo, fmt, args); va_end(args); if (ScreenAndDebug) - debug_serial_flush(); + debug_flush(); } @@ -471,7 +438,7 @@ d+=4; } putc(&debuginfo, '\n'); - debug_serial_flush(); + debug_flush(); } static void @@ -495,7 +462,7 @@ { puts_cs(&debuginfo, fname); putc(&debuginfo, '\n'); - debug_serial_flush(); + debug_flush(); } // Function called on handler startup. diff -Nru seabios-1.7.1/src/output.h seabios-1.7.4/src/output.h --- seabios-1.7.1/src/output.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/output.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,67 @@ +#ifndef __OUTPUT_H +#define __OUTPUT_H + +#include "types.h" // u32 + +// output.c +void debug_preinit(void); +void panic(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))) __noreturn; +void printf(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); +int snprintf(char *str, size_t size, const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +char * znprintf(size_t size, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +void __dprintf(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); +struct bregs; +void __debug_enter(struct bregs *regs, const char *fname); +void __debug_isr(const char *fname); +void __debug_stub(struct bregs *regs, int lineno, const char *fname); +void __warn_invalid(struct bregs *regs, int lineno, const char *fname); +void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname); +void __warn_internalerror(int lineno, const char *fname); +void __warn_noalloc(int lineno, const char *fname); +void __warn_timeout(int lineno, const char *fname); +void __set_invalid(struct bregs *regs, int lineno, const char *fname); +void __set_unimplemented(struct bregs *regs, int lineno, const char *fname); +void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname); +void __set_code_unimplemented(struct bregs *regs, u32 linecode + , const char *fname); +void hexdump(const void *d, int len); + +#define dprintf(lvl, fmt, args...) do { \ + if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL) \ + __dprintf((fmt) , ##args ); \ + } while (0) +#define debug_enter(regs, lvl) do { \ + if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ + __debug_enter((regs), __func__); \ + } while (0) +#define debug_isr(lvl) do { \ + if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ + __debug_isr(__func__); \ + } while (0) +#define debug_stub(regs) \ + __debug_stub((regs), __LINE__, __func__) +#define warn_invalid(regs) \ + __warn_invalid((regs), __LINE__, __func__) +#define warn_unimplemented(regs) \ + __warn_unimplemented((regs), __LINE__, __func__) +#define warn_internalerror() \ + __warn_internalerror(__LINE__, __func__) +#define warn_noalloc() \ + __warn_noalloc(__LINE__, __func__) +#define warn_timeout() \ + __warn_timeout(__LINE__, __func__) +#define set_invalid(regs) \ + __set_invalid((regs), __LINE__, __func__) +#define set_code_invalid(regs, code) \ + __set_code_invalid((regs), (code) | (__LINE__ << 8), __func__) +#define set_unimplemented(regs) \ + __set_unimplemented((regs), __LINE__, __func__) +#define set_code_unimplemented(regs, code) \ + __set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__) + +#endif // output.h diff -Nru seabios-1.7.1/src/paravirt.c seabios-1.7.4/src/paravirt.c --- seabios-1.7.1/src/paravirt.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/paravirt.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,348 +0,0 @@ -// Paravirtualization support. -// -// Copyright (C) 2009 Red Hat Inc. -// -// Authors: -// Gleb Natapov -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "config.h" // CONFIG_COREBOOT -#include "util.h" // ntoh[ls] -#include "ioport.h" // outw -#include "paravirt.h" // qemu_cfg_port_probe -#include "smbios.h" // struct smbios_structure_header - -int qemu_cfg_present; - -static void -qemu_cfg_select(u16 f) -{ - outw(f, PORT_QEMU_CFG_CTL); -} - -static void -qemu_cfg_read(u8 *buf, int len) -{ - insb(PORT_QEMU_CFG_DATA, buf, len); -} - -static void -qemu_cfg_skip(int len) -{ - while (len--) - inb(PORT_QEMU_CFG_DATA); -} - -static void -qemu_cfg_read_entry(void *buf, int e, int len) -{ - qemu_cfg_select(e); - qemu_cfg_read(buf, len); -} - -void qemu_cfg_port_probe(void) -{ - char *sig = "QEMU"; - int i; - - if (CONFIG_COREBOOT) - return; - - qemu_cfg_present = 1; - - qemu_cfg_select(QEMU_CFG_SIGNATURE); - - for (i = 0; i < 4; i++) - if (inb(PORT_QEMU_CFG_DATA) != sig[i]) { - qemu_cfg_present = 0; - break; - } - dprintf(4, "qemu_cfg_present=%d\n", qemu_cfg_present); -} - -void qemu_cfg_get_uuid(u8 *uuid) -{ - if (!qemu_cfg_present) - return; - - qemu_cfg_read_entry(uuid, QEMU_CFG_UUID, 16); -} - -int qemu_cfg_show_boot_menu(void) -{ - u16 v; - if (!qemu_cfg_present) - return 1; - - qemu_cfg_read_entry(&v, QEMU_CFG_BOOT_MENU, sizeof(v)); - - return v; -} - -int qemu_cfg_irq0_override(void) -{ - u8 v; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&v, QEMU_CFG_IRQ0_OVERRIDE, sizeof(v)); - - return v; -} - -u16 qemu_cfg_acpi_additional_tables(void) -{ - u16 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt)); - - return cnt; -} - -u16 qemu_cfg_next_acpi_table_len(void) -{ - u16 len; - - qemu_cfg_read((u8*)&len, sizeof(len)); - - return len; -} - -void* qemu_cfg_next_acpi_table_load(void *addr, u16 len) -{ - qemu_cfg_read(addr, len); - return addr; -} - -u16 qemu_cfg_smbios_entries(void) -{ - u16 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt)); - - return cnt; -} - -u32 qemu_cfg_e820_entries(void) -{ - u32 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_E820_TABLE, sizeof(cnt)); - return cnt; -} - -void* qemu_cfg_e820_load_next(void *addr) -{ - qemu_cfg_read(addr, sizeof(struct e820_reservation)); - return addr; -} - -struct smbios_header { - u16 length; - u8 type; -} PACKED; - -struct smbios_field { - struct smbios_header header; - u8 type; - u16 offset; - u8 data[]; -} PACKED; - -struct smbios_table { - struct smbios_header header; - u8 data[]; -} PACKED; - -#define SMBIOS_FIELD_ENTRY 0 -#define SMBIOS_TABLE_ENTRY 1 - -size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr) -{ - int i; - - for (i = qemu_cfg_smbios_entries(); i > 0; i--) { - struct smbios_field field; - - qemu_cfg_read((u8 *)&field, sizeof(struct smbios_header)); - field.header.length -= sizeof(struct smbios_header); - - if (field.header.type != SMBIOS_FIELD_ENTRY) { - qemu_cfg_skip(field.header.length); - continue; - } - - qemu_cfg_read((u8 *)&field.type, - sizeof(field) - sizeof(struct smbios_header)); - field.header.length -= sizeof(field) - sizeof(struct smbios_header); - - if (field.type != type || field.offset != offset) { - qemu_cfg_skip(field.header.length); - continue; - } - - qemu_cfg_read(addr, field.header.length); - return (size_t)field.header.length; - } - return 0; -} - -int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs, - unsigned *max_struct_size, char *end) -{ - static u64 used_bitmap[4] = { 0 }; - char *start = *p; - int i; - - /* Check if we've already reported these tables */ - if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f))) - return 1; - - /* Don't introduce spurious end markers */ - if (type == 127) - return 0; - - for (i = qemu_cfg_smbios_entries(); i > 0; i--) { - struct smbios_table table; - struct smbios_structure_header *header = (void *)*p; - int string; - - qemu_cfg_read((u8 *)&table, sizeof(struct smbios_header)); - table.header.length -= sizeof(struct smbios_header); - - if (table.header.type != SMBIOS_TABLE_ENTRY) { - qemu_cfg_skip(table.header.length); - continue; - } - - if (end - *p < sizeof(struct smbios_structure_header)) { - warn_noalloc(); - break; - } - - qemu_cfg_read((u8 *)*p, sizeof(struct smbios_structure_header)); - table.header.length -= sizeof(struct smbios_structure_header); - - if (header->type != type) { - qemu_cfg_skip(table.header.length); - continue; - } - - *p += sizeof(struct smbios_structure_header); - - /* Entries end with a double NULL char, if there's a string at - * the end (length is greater than formatted length), the string - * terminator provides the first NULL. */ - string = header->length < table.header.length + - sizeof(struct smbios_structure_header); - - /* Read the rest and terminate the entry */ - if (end - *p < table.header.length) { - warn_noalloc(); - *p -= sizeof(struct smbios_structure_header); - continue; - } - qemu_cfg_read((u8 *)*p, table.header.length); - *p += table.header.length; - *((u8*)*p) = 0; - (*p)++; - if (!string) { - *((u8*)*p) = 0; - (*p)++; - } - - (*nr_structs)++; - if (*p - (char *)header > *max_struct_size) - *max_struct_size = *p - (char *)header; - } - - if (start != *p) { - /* Mark that we've reported on this type */ - used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f)); - return 1; - } - - return 0; -} - -int qemu_cfg_get_numa_nodes(void) -{ - u64 cnt; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_NUMA, sizeof(cnt)); - - return (int)cnt; -} - -void qemu_cfg_get_numa_data(u64 *data, int n) -{ - int i; - - for (i = 0; i < n; i++) - qemu_cfg_read((u8*)(data + i), sizeof(u64)); -} - -u16 qemu_cfg_get_max_cpus(void) -{ - u16 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_MAX_CPUS, sizeof(cnt)); - - return cnt; -} - -int qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) -{ - if (file->size > maxlen) - return -1; - qemu_cfg_read_entry(dst, file->id, file->size); - return file->size; -} - -struct QemuCfgFile { - u32 size; /* file size */ - u16 select; /* write this to 0x510 to read it */ - u16 reserved; - char name[56]; -}; - -void qemu_cfg_romfile_setup(void) -{ - if (CONFIG_COREBOOT || !qemu_cfg_present) - return; - - u32 count; - qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count)); - count = ntohl(count); - u32 e; - for (e = 0; e < count; e++) { - struct QemuCfgFile qfile; - qemu_cfg_read((void*)&qfile, sizeof(qfile)); - struct romfile_s *file = malloc_tmp(sizeof(*file)); - if (!file) { - warn_noalloc(); - return; - } - memset(file, 0, sizeof(*file)); - strtcpy(file->name, qfile.name, sizeof(file->name)); - file->size = ntohl(qfile.size); - file->id = ntohs(qfile.select); - file->copy = qemu_cfg_read_file; - romfile_add(file); - dprintf(3, "Found fw_cfg file: %s (size=%d)\n", file->name, file->size); - } -} diff -Nru seabios-1.7.1/src/paravirt.h seabios-1.7.4/src/paravirt.h --- seabios-1.7.1/src/paravirt.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/paravirt.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -#ifndef __PV_H -#define __PV_H - -#include "config.h" // CONFIG_COREBOOT -#include "util.h" - -/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It - * should be used to determine that a VM is running under KVM. - */ -#define KVM_CPUID_SIGNATURE 0x40000000 - -static inline int kvm_para_available(void) -{ - if (CONFIG_COREBOOT) - return 0; - unsigned int eax, ebx, ecx, edx; - char signature[13]; - - cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx); - memcpy(signature + 0, &ebx, 4); - memcpy(signature + 4, &ecx, 4); - memcpy(signature + 8, &edx, 4); - signature[12] = 0; - - if (strcmp(signature, "KVMKVMKVM") == 0) - return 1; - - return 0; -} - -#define QEMU_CFG_SIGNATURE 0x00 -#define QEMU_CFG_ID 0x01 -#define QEMU_CFG_UUID 0x02 -#define QEMU_CFG_NUMA 0x0d -#define QEMU_CFG_BOOT_MENU 0x0e -#define QEMU_CFG_MAX_CPUS 0x0f -#define QEMU_CFG_FILE_DIR 0x19 -#define QEMU_CFG_ARCH_LOCAL 0x8000 -#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) -#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) -#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2) -#define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3) - -extern int qemu_cfg_present; - -void qemu_cfg_port_probe(void); -int qemu_cfg_show_boot_menu(void); -void qemu_cfg_get_uuid(u8 *uuid); -int qemu_cfg_irq0_override(void); -u16 qemu_cfg_acpi_additional_tables(void); -u16 qemu_cfg_next_acpi_table_len(void); -void *qemu_cfg_next_acpi_table_load(void *addr, u16 len); -u16 qemu_cfg_smbios_entries(void); -size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr); -int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs, - unsigned *max_struct_size, char *end); -int qemu_cfg_get_numa_nodes(void); -void qemu_cfg_get_numa_data(u64 *data, int n); -u16 qemu_cfg_get_max_cpus(void); -struct e820_reservation { - u64 address; - u64 length; - u32 type; -}; -u32 qemu_cfg_e820_entries(void); -void* qemu_cfg_e820_load_next(void *addr); -void qemu_cfg_romfile_setup(void); - -#endif diff -Nru seabios-1.7.1/src/pcibios.c seabios-1.7.4/src/pcibios.c --- seabios-1.7.1/src/pcibios.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pcibios.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,12 +5,14 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "types.h" // u32 -#include "util.h" // handle_1ab1 -#include "pci.h" // pci_config_readl -#include "bregs.h" // struct bregs #include "biosvar.h" // GET_GLOBAL -#include "pci_regs.h" // PCI_VENDOR_ID +#include "bregs.h" // struct bregs +#include "hw/pci.h" // pci_config_readl +#include "hw/pci_regs.h" // PCI_VENDOR_ID +#include "output.h" // dprintf +#include "std/pirtable.h" // struct pir_header +#include "string.h" // checksum +#include "util.h" // handle_1ab1 // romlayout.S extern void entry_bios32(void); @@ -201,19 +203,19 @@ } } +// Entry point for pci bios functions. +void VISIBLE16 VISIBLE32SEG +handle_pcibios(struct bregs *regs) +{ + debug_enter(regs, DEBUG_HDL_pcibios); + handle_1ab1(regs); +} + /**************************************************************** * 32bit interface ****************************************************************/ -// Entry point for 32bit pci bios functions. -void VISIBLE32SEG -handle_pcibios32(struct bregs *regs) -{ - debug_enter(regs, DEBUG_HDL_pcibios32); - handle_1ab1(regs); -} - struct bios32_s { u32 signature; u32 entry; @@ -223,13 +225,13 @@ u8 reserved[5]; } PACKED; -struct bios32_s BIOS32HEADER __aligned(16) VAR16EXPORT = { +struct bios32_s BIOS32HEADER __aligned(16) VARFSEG = { .signature = 0x5f32335f, // _32_ .length = sizeof(BIOS32HEADER) / 16, }; void -bios32_setup(void) +bios32_init(void) { dprintf(3, "init bios32\n"); diff -Nru seabios-1.7.1/src/pci.c seabios-1.7.4/src/pci.c --- seabios-1.7.1/src/pci.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pci.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,277 +0,0 @@ -// PCI config space access functions. -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "config.h" // CONFIG_* -#include "pci.h" // pci_config_writel -#include "ioport.h" // outl -#include "util.h" // dprintf -#include "farptr.h" // MAKE_FLATPTR -#include "pci_regs.h" // PCI_VENDOR_ID -#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA - -void pci_config_writel(u16 bdf, u32 addr, u32 val) -{ - outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); - outl(val, PORT_PCI_DATA); -} - -void pci_config_writew(u16 bdf, u32 addr, u16 val) -{ - outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); - outw(val, PORT_PCI_DATA + (addr & 2)); -} - -void pci_config_writeb(u16 bdf, u32 addr, u8 val) -{ - outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); - outb(val, PORT_PCI_DATA + (addr & 3)); -} - -u32 pci_config_readl(u16 bdf, u32 addr) -{ - outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); - return inl(PORT_PCI_DATA); -} - -u16 pci_config_readw(u16 bdf, u32 addr) -{ - outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); - return inw(PORT_PCI_DATA + (addr & 2)); -} - -u8 pci_config_readb(u16 bdf, u32 addr) -{ - outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD); - return inb(PORT_PCI_DATA + (addr & 3)); -} - -void -pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on) -{ - u16 val = pci_config_readw(bdf, addr); - val = (val & ~off) | on; - pci_config_writew(bdf, addr, val); -} - -// Helper function for foreachbdf() macro - return next device -int -pci_next(int bdf, int bus) -{ - if (pci_bdf_to_fn(bdf) == 0 - && (pci_config_readb(bdf, PCI_HEADER_TYPE) & 0x80) == 0) - // Last found device wasn't a multi-function device - skip to - // the next device. - bdf += 8; - else - bdf += 1; - - for (;;) { - if (pci_bdf_to_bus(bdf) != bus) - return -1; - - u16 v = pci_config_readw(bdf, PCI_VENDOR_ID); - if (v != 0x0000 && v != 0xffff) - // Device is present. - return bdf; - - if (pci_bdf_to_fn(bdf) == 0) - bdf += 8; - else - bdf += 1; - } -} - -struct pci_device *PCIDevices; -int MaxPCIBus VAR16VISIBLE; - -// Check if PCI is available at all -int -pci_probe_host(void) -{ - outl(0x80000000, PORT_PCI_CMD); - if (inl(PORT_PCI_CMD) != 0x80000000) { - dprintf(1, "Detected non-PCI system\n"); - return -1; - } - return 0; -} - -// Find all PCI devices and populate PCIDevices linked list. -void -pci_probe_devices(void) -{ - dprintf(3, "PCI probe\n"); - struct pci_device *busdevs[256]; - memset(busdevs, 0, sizeof(busdevs)); - struct pci_device **pprev = &PCIDevices; - int extraroots = romfile_loadint("etc/extra-pci-roots", 0); - int bus = -1, lastbus = 0, rootbuses = 0, count=0; - while (bus < 0xff && (bus < MaxPCIBus || rootbuses < extraroots)) { - bus++; - int bdf; - foreachbdf(bdf, bus) { - // Create new pci_device struct and add to list. - struct pci_device *dev = malloc_tmp(sizeof(*dev)); - if (!dev) { - warn_noalloc(); - return; - } - memset(dev, 0, sizeof(*dev)); - *pprev = dev; - pprev = &dev->next; - count++; - - // Find parent device. - int rootbus; - struct pci_device *parent = busdevs[bus]; - if (!parent) { - if (bus != lastbus) - rootbuses++; - lastbus = bus; - rootbus = rootbuses; - if (bus > MaxPCIBus) - MaxPCIBus = bus; - } else { - rootbus = parent->rootbus; - } - - // Populate pci_device info. - dev->bdf = bdf; - dev->parent = parent; - dev->rootbus = rootbus; - u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID); - dev->vendor = vendev & 0xffff; - dev->device = vendev >> 16; - u32 classrev = pci_config_readl(bdf, PCI_CLASS_REVISION); - dev->class = classrev >> 16; - dev->prog_if = classrev >> 8; - dev->revision = classrev & 0xff; - dev->header_type = pci_config_readb(bdf, PCI_HEADER_TYPE); - u8 v = dev->header_type & 0x7f; - if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) { - u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); - dev->secondary_bus = secbus; - if (secbus > bus && !busdevs[secbus]) - busdevs[secbus] = dev; - if (secbus > MaxPCIBus) - MaxPCIBus = secbus; - } - dprintf(4, "PCI device %02x:%02x.%x (vd=%04x:%04x c=%04x)\n" - , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) - , pci_bdf_to_fn(bdf) - , dev->vendor, dev->device, dev->class); - } - } - dprintf(1, "Found %d PCI devices (max PCI bus is %02x)\n", count, MaxPCIBus); -} - -// Search for a device with the specified vendor and device ids. -struct pci_device * -pci_find_device(u16 vendid, u16 devid) -{ - struct pci_device *pci; - foreachpci(pci) { - if (pci->vendor == vendid && pci->device == devid) - return pci; - } - return NULL; -} - -// Search for a device with the specified class id. -struct pci_device * -pci_find_class(u16 classid) -{ - struct pci_device *pci; - foreachpci(pci) { - if (pci->class == classid) - return pci; - } - return NULL; -} - -int pci_init_device(const struct pci_device_id *ids - , struct pci_device *pci, void *arg) -{ - while (ids->vendid || ids->class_mask) { - if ((ids->vendid == PCI_ANY_ID || ids->vendid == pci->vendor) && - (ids->devid == PCI_ANY_ID || ids->devid == pci->device) && - !((ids->class ^ pci->class) & ids->class_mask)) { - if (ids->func) - ids->func(pci, arg); - return 0; - } - ids++; - } - return -1; -} - -struct pci_device * -pci_find_init_device(const struct pci_device_id *ids, void *arg) -{ - struct pci_device *pci; - foreachpci(pci) { - if (pci_init_device(ids, pci, arg) == 0) - return pci; - } - return NULL; -} - -void -pci_reboot(void) -{ - u8 v = inb(PORT_PCI_REBOOT) & ~6; - outb(v|2, PORT_PCI_REBOOT); /* Request hard reset */ - udelay(50); - outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */ - udelay(50); -} - -// helper functions to access pci mmio bars from real mode - -u32 VISIBLE32FLAT -pci_readl_32(u32 addr) -{ - dprintf(9, "32: pci read : %x\n", addr); - return readl((void*)addr); -} - -u32 pci_readl(u32 addr) -{ - if (MODESEGMENT) { - dprintf(9, "16: pci read : %x\n", addr); - extern void _cfunc32flat_pci_readl_32(u32 addr); - return call32(_cfunc32flat_pci_readl_32, addr, -1); - } else { - return pci_readl_32(addr); - } -} - -struct reg32 { - u32 addr; - u32 data; -}; - -void VISIBLE32FLAT -pci_writel_32(struct reg32 *reg32) -{ - dprintf(9, "32: pci write: %x, %x (%p)\n", reg32->addr, reg32->data, reg32); - writel((void*)(reg32->addr), reg32->data); -} - -void pci_writel(u32 addr, u32 val) -{ - struct reg32 reg32 = { .addr = addr, .data = val }; - if (MODESEGMENT) { - dprintf(9, "16: pci write: %x, %x (%x:%p)\n", - reg32.addr, reg32.data, GET_SEG(SS), ®32); - void *flatptr = MAKE_FLATPTR(GET_SEG(SS), ®32); - extern void _cfunc32flat_pci_writel_32(struct reg32 *reg32); - call32(_cfunc32flat_pci_writel_32, (u32)flatptr, -1); - } else { - pci_writel_32(®32); - } -} diff -Nru seabios-1.7.1/src/pci.h seabios-1.7.4/src/pci.h --- seabios-1.7.1/src/pci.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pci.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -#ifndef __PCI_H -#define __PCI_H - -#include "types.h" // u32 - -#define PCI_ROM_SLOT 6 -#define PCI_NUM_REGIONS 7 -#define PCI_BRIDGE_NUM_REGIONS 2 - -static inline u8 pci_bdf_to_bus(u16 bdf) { - return bdf >> 8; -} -static inline u8 pci_bdf_to_devfn(u16 bdf) { - return bdf & 0xff; -} -static inline u16 pci_bdf_to_busdev(u16 bdf) { - return bdf & ~0x07; -} -static inline u8 pci_bdf_to_dev(u16 bdf) { - return (bdf >> 3) & 0x1f; -} -static inline u8 pci_bdf_to_fn(u16 bdf) { - return bdf & 0x07; -} -static inline u16 pci_to_bdf(int bus, int dev, int fn) { - return (bus<<8) | (dev<<3) | fn; -} -static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) { - return (bus << 8) | devfn; -} - -void pci_config_writel(u16 bdf, u32 addr, u32 val); -void pci_config_writew(u16 bdf, u32 addr, u16 val); -void pci_config_writeb(u16 bdf, u32 addr, u8 val); -u32 pci_config_readl(u16 bdf, u32 addr); -u16 pci_config_readw(u16 bdf, u32 addr); -u8 pci_config_readb(u16 bdf, u32 addr); -void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on); - -struct pci_device *pci_find_device(u16 vendid, u16 devid); -struct pci_device *pci_find_class(u16 classid); - -struct pci_device { - u16 bdf; - u8 rootbus; - struct pci_device *next; - struct pci_device *parent; - - // Configuration space device information - u16 vendor, device; - u16 class; - u8 prog_if, revision; - u8 header_type; - u8 secondary_bus; - - // Local information on device. - int have_driver; -}; -extern u64 pcimem_start, pcimem_end; -extern u64 pcimem64_start, pcimem64_end; -extern struct pci_device *PCIDevices; -extern int MaxPCIBus; -int pci_probe_host(void); -void pci_probe_devices(void); -static inline u32 pci_classprog(struct pci_device *pci) { - return (pci->class << 8) | pci->prog_if; -} - -#define foreachpci(PCI) \ - for (PCI=PCIDevices; PCI; PCI=PCI->next) - -int pci_next(int bdf, int bus); -#define foreachbdf(BDF, BUS) \ - for (BDF=pci_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS)) \ - ; BDF >= 0 \ - ; BDF=pci_next(BDF, (BUS))) - -#define PCI_ANY_ID (~0) -struct pci_device_id { - u32 vendid; - u32 devid; - u32 class; - u32 class_mask; - void (*func)(struct pci_device *pci, void *arg); -}; - -#define PCI_DEVICE(vendor_id, device_id, init_func) \ - { \ - .vendid = (vendor_id), \ - .devid = (device_id), \ - .class = PCI_ANY_ID, \ - .class_mask = 0, \ - .func = (init_func) \ - } - -#define PCI_DEVICE_CLASS(vendor_id, device_id, class_code, init_func) \ - { \ - .vendid = (vendor_id), \ - .devid = (device_id), \ - .class = (class_code), \ - .class_mask = ~0, \ - .func = (init_func) \ - } - -#define PCI_DEVICE_END \ - { \ - .vendid = 0, \ - } - -int pci_init_device(const struct pci_device_id *ids - , struct pci_device *pci, void *arg); -struct pci_device *pci_find_init_device(const struct pci_device_id *ids - , void *arg); -void pci_reboot(void); - -// helper functions to access pci mmio bars from real mode -u32 pci_readl(u32 addr); -void pci_writel(u32 addr, u32 val); - -// pirtable.c -void create_pirtable(void); - - -/**************************************************************** - * PIR table - ****************************************************************/ - -struct link_info { - u8 link; - u16 bitmap; -} PACKED; - -struct pir_slot { - u8 bus; - u8 dev; - struct link_info links[4]; - u8 slot_nr; - u8 reserved; -} PACKED; - -struct pir_header { - u32 signature; - u16 version; - u16 size; - u8 router_bus; - u8 router_devfunc; - u16 exclusive_irqs; - u32 compatible_devid; - u32 miniport_data; - u8 reserved[11]; - u8 checksum; - struct pir_slot slots[0]; -} PACKED; - -extern struct pir_header *PirAddr; - -#define PIR_SIGNATURE 0x52495024 // $PIR - - -#endif diff -Nru seabios-1.7.1/src/pci_ids.h seabios-1.7.4/src/pci_ids.h --- seabios-1.7.1/src/pci_ids.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pci_ids.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,2611 +0,0 @@ -/* - * PCI Class, Vendor and Device IDs - * - * Please keep sorted. - */ - -/* Device classes and subclasses */ - -#define PCI_CLASS_NOT_DEFINED 0x0000 -#define PCI_CLASS_NOT_DEFINED_VGA 0x0001 - -#define PCI_BASE_CLASS_STORAGE 0x01 -#define PCI_CLASS_STORAGE_SCSI 0x0100 -#define PCI_CLASS_STORAGE_IDE 0x0101 -#define PCI_CLASS_STORAGE_FLOPPY 0x0102 -#define PCI_CLASS_STORAGE_IPI 0x0103 -#define PCI_CLASS_STORAGE_RAID 0x0104 -#define PCI_CLASS_STORAGE_SATA 0x0106 -#define PCI_CLASS_STORAGE_SATA_AHCI 0x010601 -#define PCI_CLASS_STORAGE_SAS 0x0107 -#define PCI_CLASS_STORAGE_OTHER 0x0180 - -#define PCI_BASE_CLASS_NETWORK 0x02 -#define PCI_CLASS_NETWORK_ETHERNET 0x0200 -#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201 -#define PCI_CLASS_NETWORK_FDDI 0x0202 -#define PCI_CLASS_NETWORK_ATM 0x0203 -#define PCI_CLASS_NETWORK_OTHER 0x0280 - -#define PCI_BASE_CLASS_DISPLAY 0x03 -#define PCI_CLASS_DISPLAY_VGA 0x0300 -#define PCI_CLASS_DISPLAY_XGA 0x0301 -#define PCI_CLASS_DISPLAY_3D 0x0302 -#define PCI_CLASS_DISPLAY_OTHER 0x0380 - -#define PCI_BASE_CLASS_MULTIMEDIA 0x04 -#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400 -#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401 -#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402 -#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480 - -#define PCI_BASE_CLASS_MEMORY 0x05 -#define PCI_CLASS_MEMORY_RAM 0x0500 -#define PCI_CLASS_MEMORY_FLASH 0x0501 -#define PCI_CLASS_MEMORY_OTHER 0x0580 - -#define PCI_BASE_CLASS_BRIDGE 0x06 -#define PCI_CLASS_BRIDGE_HOST 0x0600 -#define PCI_CLASS_BRIDGE_ISA 0x0601 -#define PCI_CLASS_BRIDGE_EISA 0x0602 -#define PCI_CLASS_BRIDGE_MC 0x0603 -#define PCI_CLASS_BRIDGE_PCI 0x0604 -#define PCI_CLASS_BRIDGE_PCMCIA 0x0605 -#define PCI_CLASS_BRIDGE_NUBUS 0x0606 -#define PCI_CLASS_BRIDGE_CARDBUS 0x0607 -#define PCI_CLASS_BRIDGE_RACEWAY 0x0608 -#define PCI_CLASS_BRIDGE_OTHER 0x0680 - -#define PCI_BASE_CLASS_COMMUNICATION 0x07 -#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 -#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701 -#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702 -#define PCI_CLASS_COMMUNICATION_MODEM 0x0703 -#define PCI_CLASS_COMMUNICATION_OTHER 0x0780 - -#define PCI_BASE_CLASS_SYSTEM 0x08 -#define PCI_CLASS_SYSTEM_PIC 0x0800 -#define PCI_CLASS_SYSTEM_PIC_IOAPIC 0x080010 -#define PCI_CLASS_SYSTEM_PIC_IOXAPIC 0x080020 -#define PCI_CLASS_SYSTEM_DMA 0x0801 -#define PCI_CLASS_SYSTEM_TIMER 0x0802 -#define PCI_CLASS_SYSTEM_RTC 0x0803 -#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804 -#define PCI_CLASS_SYSTEM_SDHCI 0x0805 -#define PCI_CLASS_SYSTEM_OTHER 0x0880 - -#define PCI_BASE_CLASS_INPUT 0x09 -#define PCI_CLASS_INPUT_KEYBOARD 0x0900 -#define PCI_CLASS_INPUT_PEN 0x0901 -#define PCI_CLASS_INPUT_MOUSE 0x0902 -#define PCI_CLASS_INPUT_SCANNER 0x0903 -#define PCI_CLASS_INPUT_GAMEPORT 0x0904 -#define PCI_CLASS_INPUT_OTHER 0x0980 - -#define PCI_BASE_CLASS_DOCKING 0x0a -#define PCI_CLASS_DOCKING_GENERIC 0x0a00 -#define PCI_CLASS_DOCKING_OTHER 0x0a80 - -#define PCI_BASE_CLASS_PROCESSOR 0x0b -#define PCI_CLASS_PROCESSOR_386 0x0b00 -#define PCI_CLASS_PROCESSOR_486 0x0b01 -#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02 -#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10 -#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20 -#define PCI_CLASS_PROCESSOR_MIPS 0x0b30 -#define PCI_CLASS_PROCESSOR_CO 0x0b40 - -#define PCI_BASE_CLASS_SERIAL 0x0c -#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00 -#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010 -#define PCI_CLASS_SERIAL_ACCESS 0x0c01 -#define PCI_CLASS_SERIAL_SSA 0x0c02 -#define PCI_CLASS_SERIAL_USB 0x0c03 -#define PCI_CLASS_SERIAL_USB_UHCI 0x0c0300 -#define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310 -#define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320 -#define PCI_CLASS_SERIAL_FIBER 0x0c04 -#define PCI_CLASS_SERIAL_SMBUS 0x0c05 - -#define PCI_BASE_CLASS_WIRELESS 0x0d -#define PCI_CLASS_WIRELESS_RF_CONTROLLER 0x0d10 -#define PCI_CLASS_WIRELESS_WHCI 0x0d1010 - -#define PCI_BASE_CLASS_INTELLIGENT 0x0e -#define PCI_CLASS_INTELLIGENT_I2O 0x0e00 - -#define PCI_BASE_CLASS_SATELLITE 0x0f -#define PCI_CLASS_SATELLITE_TV 0x0f00 -#define PCI_CLASS_SATELLITE_AUDIO 0x0f01 -#define PCI_CLASS_SATELLITE_VOICE 0x0f03 -#define PCI_CLASS_SATELLITE_DATA 0x0f04 - -#define PCI_BASE_CLASS_CRYPT 0x10 -#define PCI_CLASS_CRYPT_NETWORK 0x1000 -#define PCI_CLASS_CRYPT_ENTERTAINMENT 0x1001 -#define PCI_CLASS_CRYPT_OTHER 0x1080 - -#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11 -#define PCI_CLASS_SP_DPIO 0x1100 -#define PCI_CLASS_SP_OTHER 0x1180 - -#define PCI_CLASS_OTHERS 0xff - -/* Vendors and devices. Sort key: vendor first, device next. */ - -#define PCI_VENDOR_ID_TTTECH 0x0357 -#define PCI_DEVICE_ID_TTTECH_MC322 0x000a - -#define PCI_VENDOR_ID_DYNALINK 0x0675 -#define PCI_DEVICE_ID_DYNALINK_IS64PH 0x1702 - -#define PCI_VENDOR_ID_BERKOM 0x0871 -#define PCI_DEVICE_ID_BERKOM_A1T 0xffa1 -#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xffa2 -#define PCI_DEVICE_ID_BERKOM_A4T 0xffa4 -#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO 0xffa8 - -#define PCI_VENDOR_ID_COMPAQ 0x0e11 -#define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508 -#define PCI_DEVICE_ID_COMPAQ_TACHYON 0xa0fc -#define PCI_DEVICE_ID_COMPAQ_SMART2P 0xae10 -#define PCI_DEVICE_ID_COMPAQ_NETEL100 0xae32 -#define PCI_DEVICE_ID_COMPAQ_NETEL10 0xae34 -#define PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE 0xae33 -#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I 0xae35 -#define PCI_DEVICE_ID_COMPAQ_NETEL100D 0xae40 -#define PCI_DEVICE_ID_COMPAQ_NETEL100PI 0xae43 -#define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011 -#define PCI_DEVICE_ID_COMPAQ_CISS 0xb060 -#define PCI_DEVICE_ID_COMPAQ_CISSB 0xb178 -#define PCI_DEVICE_ID_COMPAQ_CISSC 0x46 -#define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130 -#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150 - -#define PCI_VENDOR_ID_NCR 0x1000 -#define PCI_VENDOR_ID_LSI_LOGIC 0x1000 -#define PCI_DEVICE_ID_NCR_53C810 0x0001 -#define PCI_DEVICE_ID_NCR_53C820 0x0002 -#define PCI_DEVICE_ID_NCR_53C825 0x0003 -#define PCI_DEVICE_ID_NCR_53C815 0x0004 -#define PCI_DEVICE_ID_LSI_53C810AP 0x0005 -#define PCI_DEVICE_ID_NCR_53C860 0x0006 -#define PCI_DEVICE_ID_LSI_53C1510 0x000a -#define PCI_DEVICE_ID_NCR_53C896 0x000b -#define PCI_DEVICE_ID_NCR_53C895 0x000c -#define PCI_DEVICE_ID_NCR_53C885 0x000d -#define PCI_DEVICE_ID_NCR_53C875 0x000f -#define PCI_DEVICE_ID_NCR_53C1510 0x0010 -#define PCI_DEVICE_ID_LSI_53C895A 0x0012 -#define PCI_DEVICE_ID_LSI_53C875A 0x0013 -#define PCI_DEVICE_ID_LSI_53C1010_33 0x0020 -#define PCI_DEVICE_ID_LSI_53C1010_66 0x0021 -#define PCI_DEVICE_ID_LSI_53C1030 0x0030 -#define PCI_DEVICE_ID_LSI_1030_53C1035 0x0032 -#define PCI_DEVICE_ID_LSI_53C1035 0x0040 -#define PCI_DEVICE_ID_NCR_53C875J 0x008f -#define PCI_DEVICE_ID_LSI_FC909 0x0621 -#define PCI_DEVICE_ID_LSI_FC929 0x0622 -#define PCI_DEVICE_ID_LSI_FC929_LAN 0x0623 -#define PCI_DEVICE_ID_LSI_FC919 0x0624 -#define PCI_DEVICE_ID_LSI_FC919_LAN 0x0625 -#define PCI_DEVICE_ID_LSI_FC929X 0x0626 -#define PCI_DEVICE_ID_LSI_FC939X 0x0642 -#define PCI_DEVICE_ID_LSI_FC949X 0x0640 -#define PCI_DEVICE_ID_LSI_FC949ES 0x0646 -#define PCI_DEVICE_ID_LSI_FC919X 0x0628 -#define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701 -#define PCI_DEVICE_ID_LSI_61C102 0x0901 -#define PCI_DEVICE_ID_LSI_63C815 0x1000 -#define PCI_DEVICE_ID_LSI_SAS1064 0x0050 -#define PCI_DEVICE_ID_LSI_SAS1064R 0x0411 -#define PCI_DEVICE_ID_LSI_SAS1066 0x005E -#define PCI_DEVICE_ID_LSI_SAS1068 0x0054 -#define PCI_DEVICE_ID_LSI_SAS1064A 0x005C -#define PCI_DEVICE_ID_LSI_SAS1064E 0x0056 -#define PCI_DEVICE_ID_LSI_SAS1066E 0x005A -#define PCI_DEVICE_ID_LSI_SAS1068E 0x0058 -#define PCI_DEVICE_ID_LSI_SAS1078 0x0060 - -#define PCI_VENDOR_ID_ATI 0x1002 -/* Mach64 */ -#define PCI_DEVICE_ID_ATI_68800 0x4158 -#define PCI_DEVICE_ID_ATI_215CT222 0x4354 -#define PCI_DEVICE_ID_ATI_210888CX 0x4358 -#define PCI_DEVICE_ID_ATI_215ET222 0x4554 -/* Mach64 / Rage */ -#define PCI_DEVICE_ID_ATI_215GB 0x4742 -#define PCI_DEVICE_ID_ATI_215GD 0x4744 -#define PCI_DEVICE_ID_ATI_215GI 0x4749 -#define PCI_DEVICE_ID_ATI_215GP 0x4750 -#define PCI_DEVICE_ID_ATI_215GQ 0x4751 -#define PCI_DEVICE_ID_ATI_215XL 0x4752 -#define PCI_DEVICE_ID_ATI_215GT 0x4754 -#define PCI_DEVICE_ID_ATI_215GTB 0x4755 -#define PCI_DEVICE_ID_ATI_215_IV 0x4756 -#define PCI_DEVICE_ID_ATI_215_IW 0x4757 -#define PCI_DEVICE_ID_ATI_215_IZ 0x475A -#define PCI_DEVICE_ID_ATI_210888GX 0x4758 -#define PCI_DEVICE_ID_ATI_215_LB 0x4c42 -#define PCI_DEVICE_ID_ATI_215_LD 0x4c44 -#define PCI_DEVICE_ID_ATI_215_LG 0x4c47 -#define PCI_DEVICE_ID_ATI_215_LI 0x4c49 -#define PCI_DEVICE_ID_ATI_215_LM 0x4c4D -#define PCI_DEVICE_ID_ATI_215_LN 0x4c4E -#define PCI_DEVICE_ID_ATI_215_LR 0x4c52 -#define PCI_DEVICE_ID_ATI_215_LS 0x4c53 -#define PCI_DEVICE_ID_ATI_264_LT 0x4c54 -/* Mach64 VT */ -#define PCI_DEVICE_ID_ATI_264VT 0x5654 -#define PCI_DEVICE_ID_ATI_264VU 0x5655 -#define PCI_DEVICE_ID_ATI_264VV 0x5656 -/* Rage128 GL */ -#define PCI_DEVICE_ID_ATI_RAGE128_RE 0x5245 -#define PCI_DEVICE_ID_ATI_RAGE128_RF 0x5246 -#define PCI_DEVICE_ID_ATI_RAGE128_RG 0x5247 -/* Rage128 VR */ -#define PCI_DEVICE_ID_ATI_RAGE128_RK 0x524b -#define PCI_DEVICE_ID_ATI_RAGE128_RL 0x524c -#define PCI_DEVICE_ID_ATI_RAGE128_SE 0x5345 -#define PCI_DEVICE_ID_ATI_RAGE128_SF 0x5346 -#define PCI_DEVICE_ID_ATI_RAGE128_SG 0x5347 -#define PCI_DEVICE_ID_ATI_RAGE128_SH 0x5348 -#define PCI_DEVICE_ID_ATI_RAGE128_SK 0x534b -#define PCI_DEVICE_ID_ATI_RAGE128_SL 0x534c -#define PCI_DEVICE_ID_ATI_RAGE128_SM 0x534d -#define PCI_DEVICE_ID_ATI_RAGE128_SN 0x534e -/* Rage128 Ultra */ -#define PCI_DEVICE_ID_ATI_RAGE128_TF 0x5446 -#define PCI_DEVICE_ID_ATI_RAGE128_TL 0x544c -#define PCI_DEVICE_ID_ATI_RAGE128_TR 0x5452 -#define PCI_DEVICE_ID_ATI_RAGE128_TS 0x5453 -#define PCI_DEVICE_ID_ATI_RAGE128_TT 0x5454 -#define PCI_DEVICE_ID_ATI_RAGE128_TU 0x5455 -/* Rage128 M3 */ -#define PCI_DEVICE_ID_ATI_RAGE128_LE 0x4c45 -#define PCI_DEVICE_ID_ATI_RAGE128_LF 0x4c46 -/* Rage128 M4 */ -#define PCI_DEVICE_ID_ATI_RAGE128_MF 0x4d46 -#define PCI_DEVICE_ID_ATI_RAGE128_ML 0x4d4c -/* Rage128 Pro GL */ -#define PCI_DEVICE_ID_ATI_RAGE128_PA 0x5041 -#define PCI_DEVICE_ID_ATI_RAGE128_PB 0x5042 -#define PCI_DEVICE_ID_ATI_RAGE128_PC 0x5043 -#define PCI_DEVICE_ID_ATI_RAGE128_PD 0x5044 -#define PCI_DEVICE_ID_ATI_RAGE128_PE 0x5045 -#define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046 -/* Rage128 Pro VR */ -#define PCI_DEVICE_ID_ATI_RAGE128_PG 0x5047 -#define PCI_DEVICE_ID_ATI_RAGE128_PH 0x5048 -#define PCI_DEVICE_ID_ATI_RAGE128_PI 0x5049 -#define PCI_DEVICE_ID_ATI_RAGE128_PJ 0x504A -#define PCI_DEVICE_ID_ATI_RAGE128_PK 0x504B -#define PCI_DEVICE_ID_ATI_RAGE128_PL 0x504C -#define PCI_DEVICE_ID_ATI_RAGE128_PM 0x504D -#define PCI_DEVICE_ID_ATI_RAGE128_PN 0x504E -#define PCI_DEVICE_ID_ATI_RAGE128_PO 0x504F -#define PCI_DEVICE_ID_ATI_RAGE128_PP 0x5050 -#define PCI_DEVICE_ID_ATI_RAGE128_PQ 0x5051 -#define PCI_DEVICE_ID_ATI_RAGE128_PR 0x5052 -#define PCI_DEVICE_ID_ATI_RAGE128_PS 0x5053 -#define PCI_DEVICE_ID_ATI_RAGE128_PT 0x5054 -#define PCI_DEVICE_ID_ATI_RAGE128_PU 0x5055 -#define PCI_DEVICE_ID_ATI_RAGE128_PV 0x5056 -#define PCI_DEVICE_ID_ATI_RAGE128_PW 0x5057 -#define PCI_DEVICE_ID_ATI_RAGE128_PX 0x5058 -/* Rage128 M4 */ -/* Radeon R100 */ -#define PCI_DEVICE_ID_ATI_RADEON_QD 0x5144 -#define PCI_DEVICE_ID_ATI_RADEON_QE 0x5145 -#define PCI_DEVICE_ID_ATI_RADEON_QF 0x5146 -#define PCI_DEVICE_ID_ATI_RADEON_QG 0x5147 -/* Radeon RV100 (VE) */ -#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 -#define PCI_DEVICE_ID_ATI_RADEON_QZ 0x515a -/* Radeon R200 (8500) */ -#define PCI_DEVICE_ID_ATI_RADEON_QL 0x514c -#define PCI_DEVICE_ID_ATI_RADEON_QN 0x514e -#define PCI_DEVICE_ID_ATI_RADEON_QO 0x514f -#define PCI_DEVICE_ID_ATI_RADEON_Ql 0x516c -#define PCI_DEVICE_ID_ATI_RADEON_BB 0x4242 -/* Radeon R200 (9100) */ -#define PCI_DEVICE_ID_ATI_RADEON_QM 0x514d -/* Radeon RV200 (7500) */ -#define PCI_DEVICE_ID_ATI_RADEON_QW 0x5157 -#define PCI_DEVICE_ID_ATI_RADEON_QX 0x5158 -/* Radeon NV-100 */ -/* Radeon RV250 (9000) */ -#define PCI_DEVICE_ID_ATI_RADEON_Id 0x4964 -#define PCI_DEVICE_ID_ATI_RADEON_Ie 0x4965 -#define PCI_DEVICE_ID_ATI_RADEON_If 0x4966 -#define PCI_DEVICE_ID_ATI_RADEON_Ig 0x4967 -/* Radeon RV280 (9200) */ -#define PCI_DEVICE_ID_ATI_RADEON_Ya 0x5961 -#define PCI_DEVICE_ID_ATI_RADEON_Yd 0x5964 -/* Radeon R300 (9500) */ -/* Radeon R300 (9700) */ -#define PCI_DEVICE_ID_ATI_RADEON_ND 0x4e44 -#define PCI_DEVICE_ID_ATI_RADEON_NE 0x4e45 -#define PCI_DEVICE_ID_ATI_RADEON_NF 0x4e46 -#define PCI_DEVICE_ID_ATI_RADEON_NG 0x4e47 -/* Radeon R350 (9800) */ -/* Radeon RV350 (9600) */ -/* Radeon M6 */ -#define PCI_DEVICE_ID_ATI_RADEON_LY 0x4c59 -#define PCI_DEVICE_ID_ATI_RADEON_LZ 0x4c5a -/* Radeon M7 */ -#define PCI_DEVICE_ID_ATI_RADEON_LW 0x4c57 -#define PCI_DEVICE_ID_ATI_RADEON_LX 0x4c58 -/* Radeon M9 */ -#define PCI_DEVICE_ID_ATI_RADEON_Ld 0x4c64 -#define PCI_DEVICE_ID_ATI_RADEON_Le 0x4c65 -#define PCI_DEVICE_ID_ATI_RADEON_Lf 0x4c66 -#define PCI_DEVICE_ID_ATI_RADEON_Lg 0x4c67 -/* Radeon */ -/* RadeonIGP */ -#define PCI_DEVICE_ID_ATI_RS100 0xcab0 -#define PCI_DEVICE_ID_ATI_RS200 0xcab2 -#define PCI_DEVICE_ID_ATI_RS200_B 0xcbb2 -#define PCI_DEVICE_ID_ATI_RS250 0xcab3 -#define PCI_DEVICE_ID_ATI_RS300_100 0x5830 -#define PCI_DEVICE_ID_ATI_RS300_133 0x5831 -#define PCI_DEVICE_ID_ATI_RS300_166 0x5832 -#define PCI_DEVICE_ID_ATI_RS300_200 0x5833 -#define PCI_DEVICE_ID_ATI_RS350_100 0x7830 -#define PCI_DEVICE_ID_ATI_RS350_133 0x7831 -#define PCI_DEVICE_ID_ATI_RS350_166 0x7832 -#define PCI_DEVICE_ID_ATI_RS350_200 0x7833 -#define PCI_DEVICE_ID_ATI_RS400_100 0x5a30 -#define PCI_DEVICE_ID_ATI_RS400_133 0x5a31 -#define PCI_DEVICE_ID_ATI_RS400_166 0x5a32 -#define PCI_DEVICE_ID_ATI_RS400_200 0x5a33 -#define PCI_DEVICE_ID_ATI_RS480 0x5950 -/* ATI IXP Chipset */ -#define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349 -#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 -#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363 -#define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369 -#define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e -#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372 -#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376 -#define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379 -#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a -#define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380 -#define PCI_DEVICE_ID_ATI_SBX00_SMBUS 0x4385 -#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c -#define PCI_DEVICE_ID_ATI_IXP700_SATA 0x4390 -#define PCI_DEVICE_ID_ATI_IXP700_IDE 0x439c - -#define PCI_VENDOR_ID_VLSI 0x1004 -#define PCI_DEVICE_ID_VLSI_82C592 0x0005 -#define PCI_DEVICE_ID_VLSI_82C593 0x0006 -#define PCI_DEVICE_ID_VLSI_82C594 0x0007 -#define PCI_DEVICE_ID_VLSI_82C597 0x0009 -#define PCI_DEVICE_ID_VLSI_82C541 0x000c -#define PCI_DEVICE_ID_VLSI_82C543 0x000d -#define PCI_DEVICE_ID_VLSI_82C532 0x0101 -#define PCI_DEVICE_ID_VLSI_82C534 0x0102 -#define PCI_DEVICE_ID_VLSI_82C535 0x0104 -#define PCI_DEVICE_ID_VLSI_82C147 0x0105 -#define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 - -#define PCI_VENDOR_ID_ADL 0x1005 -#define PCI_DEVICE_ID_ADL_2301 0x2301 - -#define PCI_VENDOR_ID_NS 0x100b -#define PCI_DEVICE_ID_NS_87415 0x0002 -#define PCI_DEVICE_ID_NS_87560_LIO 0x000e -#define PCI_DEVICE_ID_NS_87560_USB 0x0012 -#define PCI_DEVICE_ID_NS_83815 0x0020 -#define PCI_DEVICE_ID_NS_83820 0x0022 -#define PCI_DEVICE_ID_NS_CS5535_ISA 0x002b -#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d -#define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e -#define PCI_DEVICE_ID_NS_CS5535_USB 0x002f -#define PCI_DEVICE_ID_NS_GX_VIDEO 0x0030 -#define PCI_DEVICE_ID_NS_SATURN 0x0035 -#define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500 -#define PCI_DEVICE_ID_NS_SCx200_SMI 0x0501 -#define PCI_DEVICE_ID_NS_SCx200_IDE 0x0502 -#define PCI_DEVICE_ID_NS_SCx200_AUDIO 0x0503 -#define PCI_DEVICE_ID_NS_SCx200_VIDEO 0x0504 -#define PCI_DEVICE_ID_NS_SCx200_XBUS 0x0505 -#define PCI_DEVICE_ID_NS_SC1100_BRIDGE 0x0510 -#define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 -#define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 -#define PCI_DEVICE_ID_NS_87410 0xd001 - -#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE 0x0028 - -#define PCI_VENDOR_ID_TSENG 0x100c -#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 -#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205 -#define PCI_DEVICE_ID_TSENG_W32P_c 0x3206 -#define PCI_DEVICE_ID_TSENG_W32P_d 0x3207 -#define PCI_DEVICE_ID_TSENG_ET6000 0x3208 - -#define PCI_VENDOR_ID_WEITEK 0x100e -#define PCI_DEVICE_ID_WEITEK_P9000 0x9001 -#define PCI_DEVICE_ID_WEITEK_P9100 0x9100 - -#define PCI_VENDOR_ID_DEC 0x1011 -#define PCI_DEVICE_ID_DEC_BRD 0x0001 -#define PCI_DEVICE_ID_DEC_TULIP 0x0002 -#define PCI_DEVICE_ID_DEC_TGA 0x0004 -#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 -#define PCI_DEVICE_ID_DEC_TGA2 0x000D -#define PCI_DEVICE_ID_DEC_FDDI 0x000F -#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 -#define PCI_DEVICE_ID_DEC_21142 0x0019 -#define PCI_DEVICE_ID_DEC_21052 0x0021 -#define PCI_DEVICE_ID_DEC_21150 0x0022 -#define PCI_DEVICE_ID_DEC_21152 0x0024 -#define PCI_DEVICE_ID_DEC_21153 0x0025 -#define PCI_DEVICE_ID_DEC_21154 0x0026 -#define PCI_DEVICE_ID_DEC_21285 0x1065 -#define PCI_DEVICE_ID_COMPAQ_42XX 0x0046 - -#define PCI_VENDOR_ID_CIRRUS 0x1013 -#define PCI_DEVICE_ID_CIRRUS_7548 0x0038 -#define PCI_DEVICE_ID_CIRRUS_5430 0x00a0 -#define PCI_DEVICE_ID_CIRRUS_5434_4 0x00a4 -#define PCI_DEVICE_ID_CIRRUS_5434_8 0x00a8 -#define PCI_DEVICE_ID_CIRRUS_5436 0x00ac -#define PCI_DEVICE_ID_CIRRUS_5446 0x00b8 -#define PCI_DEVICE_ID_CIRRUS_5480 0x00bc -#define PCI_DEVICE_ID_CIRRUS_5462 0x00d0 -#define PCI_DEVICE_ID_CIRRUS_5464 0x00d4 -#define PCI_DEVICE_ID_CIRRUS_5465 0x00d6 -#define PCI_DEVICE_ID_CIRRUS_6729 0x1100 -#define PCI_DEVICE_ID_CIRRUS_6832 0x1110 -#define PCI_DEVICE_ID_CIRRUS_7543 0x1202 -#define PCI_DEVICE_ID_CIRRUS_4610 0x6001 -#define PCI_DEVICE_ID_CIRRUS_4612 0x6003 -#define PCI_DEVICE_ID_CIRRUS_4615 0x6004 - -#define PCI_VENDOR_ID_IBM 0x1014 -#define PCI_DEVICE_ID_IBM_TR 0x0018 -#define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e -#define PCI_DEVICE_ID_IBM_CPC710_PCI64 0x00fc -#define PCI_DEVICE_ID_IBM_SNIPE 0x0180 -#define PCI_DEVICE_ID_IBM_CITRINE 0x028C -#define PCI_DEVICE_ID_IBM_GEMSTONE 0xB166 -#define PCI_DEVICE_ID_IBM_OBSIDIAN 0x02BD -#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1 0x0031 -#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2 0x0219 -#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX 0x021A -#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251 -#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361 -#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252 - -#define PCI_VENDOR_ID_UNISYS 0x1018 -#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C - -#define PCI_VENDOR_ID_COMPEX2 0x101a /* pci.ids says "AT&T GIS (NCR)" */ -#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005 - -#define PCI_VENDOR_ID_WD 0x101c -#define PCI_DEVICE_ID_WD_90C 0xc24a - -#define PCI_VENDOR_ID_AMI 0x101e -#define PCI_DEVICE_ID_AMI_MEGARAID3 0x1960 -#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010 -#define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 - -#define PCI_VENDOR_ID_AMD 0x1022 -#define PCI_DEVICE_ID_AMD_K8_NB 0x1100 -#define PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP 0x1101 -#define PCI_DEVICE_ID_AMD_K8_NB_MEMCTL 0x1102 -#define PCI_DEVICE_ID_AMD_K8_NB_MISC 0x1103 -#define PCI_DEVICE_ID_AMD_10H_NB_HT 0x1200 -#define PCI_DEVICE_ID_AMD_10H_NB_MAP 0x1201 -#define PCI_DEVICE_ID_AMD_10H_NB_DRAM 0x1202 -#define PCI_DEVICE_ID_AMD_10H_NB_MISC 0x1203 -#define PCI_DEVICE_ID_AMD_10H_NB_LINK 0x1204 -#define PCI_DEVICE_ID_AMD_11H_NB_HT 0x1300 -#define PCI_DEVICE_ID_AMD_11H_NB_MAP 0x1301 -#define PCI_DEVICE_ID_AMD_11H_NB_DRAM 0x1302 -#define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 -#define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 -#define PCI_DEVICE_ID_AMD_LANCE 0x2000 -#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 -#define PCI_DEVICE_ID_AMD_SCSI 0x2020 -#define PCI_DEVICE_ID_AMD_SERENADE 0x36c0 -#define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006 -#define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007 -#define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C -#define PCI_DEVICE_ID_AMD_FE_GATE_700E 0x700E -#define PCI_DEVICE_ID_AMD_COBRA_7401 0x7401 -#define PCI_DEVICE_ID_AMD_VIPER_7409 0x7409 -#define PCI_DEVICE_ID_AMD_VIPER_740B 0x740B -#define PCI_DEVICE_ID_AMD_VIPER_7410 0x7410 -#define PCI_DEVICE_ID_AMD_VIPER_7411 0x7411 -#define PCI_DEVICE_ID_AMD_VIPER_7413 0x7413 -#define PCI_DEVICE_ID_AMD_VIPER_7440 0x7440 -#define PCI_DEVICE_ID_AMD_OPUS_7441 0x7441 -#define PCI_DEVICE_ID_AMD_OPUS_7443 0x7443 -#define PCI_DEVICE_ID_AMD_VIPER_7443 0x7443 -#define PCI_DEVICE_ID_AMD_OPUS_7445 0x7445 -#define PCI_DEVICE_ID_AMD_8111_LPC 0x7468 -#define PCI_DEVICE_ID_AMD_8111_IDE 0x7469 -#define PCI_DEVICE_ID_AMD_8111_SMBUS2 0x746a -#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b -#define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d -#define PCI_DEVICE_ID_AMD_8151_0 0x7454 -#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450 -#define PCI_DEVICE_ID_AMD_8131_APIC 0x7451 -#define PCI_DEVICE_ID_AMD_8132_BRIDGE 0x7458 -#define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090 -#define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091 -#define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 -#define PCI_DEVICE_ID_AMD_CS5536_OHC 0x2094 -#define PCI_DEVICE_ID_AMD_CS5536_EHC 0x2095 -#define PCI_DEVICE_ID_AMD_CS5536_UDC 0x2096 -#define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097 -#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A - -#define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081 -#define PCI_DEVICE_ID_AMD_LX_AES 0x2082 - -#define PCI_VENDOR_ID_TRIDENT 0x1023 -#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 -#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 -#define PCI_DEVICE_ID_TRIDENT_9320 0x9320 -#define PCI_DEVICE_ID_TRIDENT_9388 0x9388 -#define PCI_DEVICE_ID_TRIDENT_9397 0x9397 -#define PCI_DEVICE_ID_TRIDENT_939A 0x939A -#define PCI_DEVICE_ID_TRIDENT_9520 0x9520 -#define PCI_DEVICE_ID_TRIDENT_9525 0x9525 -#define PCI_DEVICE_ID_TRIDENT_9420 0x9420 -#define PCI_DEVICE_ID_TRIDENT_9440 0x9440 -#define PCI_DEVICE_ID_TRIDENT_9660 0x9660 -#define PCI_DEVICE_ID_TRIDENT_9750 0x9750 -#define PCI_DEVICE_ID_TRIDENT_9850 0x9850 -#define PCI_DEVICE_ID_TRIDENT_9880 0x9880 -#define PCI_DEVICE_ID_TRIDENT_8400 0x8400 -#define PCI_DEVICE_ID_TRIDENT_8420 0x8420 -#define PCI_DEVICE_ID_TRIDENT_8500 0x8500 - -#define PCI_VENDOR_ID_AI 0x1025 -#define PCI_DEVICE_ID_AI_M1435 0x1435 - -#define PCI_VENDOR_ID_DELL 0x1028 -#define PCI_DEVICE_ID_DELL_RACIII 0x0008 -#define PCI_DEVICE_ID_DELL_RAC4 0x0012 -#define PCI_DEVICE_ID_DELL_PERC5 0x0015 - -#define PCI_VENDOR_ID_MATROX 0x102B -#define PCI_DEVICE_ID_MATROX_MGA_2 0x0518 -#define PCI_DEVICE_ID_MATROX_MIL 0x0519 -#define PCI_DEVICE_ID_MATROX_MYS 0x051A -#define PCI_DEVICE_ID_MATROX_MIL_2 0x051b -#define PCI_DEVICE_ID_MATROX_MYS_AGP 0x051e -#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f -#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 -#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 -#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001 -#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520 -#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521 -#define PCI_DEVICE_ID_MATROX_G400 0x0525 -#define PCI_DEVICE_ID_MATROX_G200EV_PCI 0x0530 -#define PCI_DEVICE_ID_MATROX_G550 0x2527 -#define PCI_DEVICE_ID_MATROX_VIA 0x4536 - -#define PCI_VENDOR_ID_CT 0x102c -#define PCI_DEVICE_ID_CT_69000 0x00c0 -#define PCI_DEVICE_ID_CT_65545 0x00d8 -#define PCI_DEVICE_ID_CT_65548 0x00dc -#define PCI_DEVICE_ID_CT_65550 0x00e0 -#define PCI_DEVICE_ID_CT_65554 0x00e4 -#define PCI_DEVICE_ID_CT_65555 0x00e5 - -#define PCI_VENDOR_ID_MIRO 0x1031 -#define PCI_DEVICE_ID_MIRO_36050 0x5601 -#define PCI_DEVICE_ID_MIRO_DC10PLUS 0x7efe -#define PCI_DEVICE_ID_MIRO_DC30PLUS 0xd801 - -#define PCI_VENDOR_ID_NEC 0x1033 -#define PCI_DEVICE_ID_NEC_CBUS_1 0x0001 /* PCI-Cbus Bridge */ -#define PCI_DEVICE_ID_NEC_LOCAL 0x0002 /* Local Bridge */ -#define PCI_DEVICE_ID_NEC_ATM 0x0003 /* ATM LAN Controller */ -#define PCI_DEVICE_ID_NEC_R4000 0x0004 /* R4000 Bridge */ -#define PCI_DEVICE_ID_NEC_486 0x0005 /* 486 Like Peripheral Bus Bridge */ -#define PCI_DEVICE_ID_NEC_ACCEL_1 0x0006 /* Graphic Accelerator */ -#define PCI_DEVICE_ID_NEC_UXBUS 0x0007 /* UX-Bus Bridge */ -#define PCI_DEVICE_ID_NEC_ACCEL_2 0x0008 /* Graphic Accelerator */ -#define PCI_DEVICE_ID_NEC_GRAPH 0x0009 /* PCI-CoreGraph Bridge */ -#define PCI_DEVICE_ID_NEC_VL 0x0016 /* PCI-VL Bridge */ -#define PCI_DEVICE_ID_NEC_STARALPHA2 0x002c /* STAR ALPHA2 */ -#define PCI_DEVICE_ID_NEC_CBUS_2 0x002d /* PCI-Cbus Bridge */ -#define PCI_DEVICE_ID_NEC_USB 0x0035 /* PCI-USB Host */ -#define PCI_DEVICE_ID_NEC_CBUS_3 0x003b -#define PCI_DEVICE_ID_NEC_NAPCCARD 0x003e -#define PCI_DEVICE_ID_NEC_PCX2 0x0046 /* PowerVR */ -#define PCI_DEVICE_ID_NEC_VRC5476 0x009b -#define PCI_DEVICE_ID_NEC_VRC4173 0x00a5 -#define PCI_DEVICE_ID_NEC_VRC5477_AC97 0x00a6 -#define PCI_DEVICE_ID_NEC_PC9821CS01 0x800c /* PC-9821-CS01 */ -#define PCI_DEVICE_ID_NEC_PC9821NRB06 0x800d /* PC-9821NR-B06 */ - -#define PCI_VENDOR_ID_FD 0x1036 -#define PCI_DEVICE_ID_FD_36C70 0x0000 - -#define PCI_VENDOR_ID_SI 0x1039 -#define PCI_DEVICE_ID_SI_5591_AGP 0x0001 -#define PCI_DEVICE_ID_SI_6202 0x0002 -#define PCI_DEVICE_ID_SI_503 0x0008 -#define PCI_DEVICE_ID_SI_ACPI 0x0009 -#define PCI_DEVICE_ID_SI_SMBUS 0x0016 -#define PCI_DEVICE_ID_SI_LPC 0x0018 -#define PCI_DEVICE_ID_SI_5597_VGA 0x0200 -#define PCI_DEVICE_ID_SI_6205 0x0205 -#define PCI_DEVICE_ID_SI_501 0x0406 -#define PCI_DEVICE_ID_SI_496 0x0496 -#define PCI_DEVICE_ID_SI_300 0x0300 -#define PCI_DEVICE_ID_SI_315H 0x0310 -#define PCI_DEVICE_ID_SI_315 0x0315 -#define PCI_DEVICE_ID_SI_315PRO 0x0325 -#define PCI_DEVICE_ID_SI_530 0x0530 -#define PCI_DEVICE_ID_SI_540 0x0540 -#define PCI_DEVICE_ID_SI_550 0x0550 -#define PCI_DEVICE_ID_SI_540_VGA 0x5300 -#define PCI_DEVICE_ID_SI_550_VGA 0x5315 -#define PCI_DEVICE_ID_SI_620 0x0620 -#define PCI_DEVICE_ID_SI_630 0x0630 -#define PCI_DEVICE_ID_SI_633 0x0633 -#define PCI_DEVICE_ID_SI_635 0x0635 -#define PCI_DEVICE_ID_SI_640 0x0640 -#define PCI_DEVICE_ID_SI_645 0x0645 -#define PCI_DEVICE_ID_SI_646 0x0646 -#define PCI_DEVICE_ID_SI_648 0x0648 -#define PCI_DEVICE_ID_SI_650 0x0650 -#define PCI_DEVICE_ID_SI_651 0x0651 -#define PCI_DEVICE_ID_SI_655 0x0655 -#define PCI_DEVICE_ID_SI_661 0x0661 -#define PCI_DEVICE_ID_SI_730 0x0730 -#define PCI_DEVICE_ID_SI_733 0x0733 -#define PCI_DEVICE_ID_SI_630_VGA 0x6300 -#define PCI_DEVICE_ID_SI_735 0x0735 -#define PCI_DEVICE_ID_SI_740 0x0740 -#define PCI_DEVICE_ID_SI_741 0x0741 -#define PCI_DEVICE_ID_SI_745 0x0745 -#define PCI_DEVICE_ID_SI_746 0x0746 -#define PCI_DEVICE_ID_SI_755 0x0755 -#define PCI_DEVICE_ID_SI_760 0x0760 -#define PCI_DEVICE_ID_SI_900 0x0900 -#define PCI_DEVICE_ID_SI_961 0x0961 -#define PCI_DEVICE_ID_SI_962 0x0962 -#define PCI_DEVICE_ID_SI_963 0x0963 -#define PCI_DEVICE_ID_SI_965 0x0965 -#define PCI_DEVICE_ID_SI_966 0x0966 -#define PCI_DEVICE_ID_SI_968 0x0968 -#define PCI_DEVICE_ID_SI_1180 0x1180 -#define PCI_DEVICE_ID_SI_5511 0x5511 -#define PCI_DEVICE_ID_SI_5513 0x5513 -#define PCI_DEVICE_ID_SI_5517 0x5517 -#define PCI_DEVICE_ID_SI_5518 0x5518 -#define PCI_DEVICE_ID_SI_5571 0x5571 -#define PCI_DEVICE_ID_SI_5581 0x5581 -#define PCI_DEVICE_ID_SI_5582 0x5582 -#define PCI_DEVICE_ID_SI_5591 0x5591 -#define PCI_DEVICE_ID_SI_5596 0x5596 -#define PCI_DEVICE_ID_SI_5597 0x5597 -#define PCI_DEVICE_ID_SI_5598 0x5598 -#define PCI_DEVICE_ID_SI_5600 0x5600 -#define PCI_DEVICE_ID_SI_7012 0x7012 -#define PCI_DEVICE_ID_SI_7013 0x7013 -#define PCI_DEVICE_ID_SI_7016 0x7016 -#define PCI_DEVICE_ID_SI_7018 0x7018 - -#define PCI_VENDOR_ID_HP 0x103c -#define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005 -#define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006 -#define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008 -#define PCI_DEVICE_ID_HP_VISUALIZE_FX2 0x100a -#define PCI_DEVICE_ID_HP_TACHYON 0x1028 -#define PCI_DEVICE_ID_HP_TACHLITE 0x1029 -#define PCI_DEVICE_ID_HP_J2585A 0x1030 -#define PCI_DEVICE_ID_HP_J2585B 0x1031 -#define PCI_DEVICE_ID_HP_J2973A 0x1040 -#define PCI_DEVICE_ID_HP_J2970A 0x1042 -#define PCI_DEVICE_ID_HP_DIVA 0x1048 -#define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 -#define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A -#define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B -#define PCI_DEVICE_ID_HP_REO_IOC 0x10f1 -#define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b -#define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 -#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 -#define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227 -#define PCI_DEVICE_ID_HP_ZX1_IOC 0x122a -#define PCI_DEVICE_ID_HP_PCIX_LBA 0x122e -#define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c -#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 -#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 -#define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301 -#define PCI_DEVICE_ID_HP_DIVA_HURRICANE 0x132a -#define PCI_DEVICE_ID_HP_CISSA 0x3220 -#define PCI_DEVICE_ID_HP_CISSC 0x3230 -#define PCI_DEVICE_ID_HP_CISSD 0x3238 -#define PCI_DEVICE_ID_HP_CISSE 0x323a -#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 - -#define PCI_VENDOR_ID_PCTECH 0x1042 -#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 -#define PCI_DEVICE_ID_PCTECH_RZ1001 0x1001 -#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020 - -#define PCI_VENDOR_ID_ASUSTEK 0x1043 -#define PCI_DEVICE_ID_ASUSTEK_0675 0x0675 - -#define PCI_VENDOR_ID_DPT 0x1044 -#define PCI_DEVICE_ID_DPT 0xa400 - -#define PCI_VENDOR_ID_OPTI 0x1045 -#define PCI_DEVICE_ID_OPTI_82C558 0xc558 -#define PCI_DEVICE_ID_OPTI_82C621 0xc621 -#define PCI_DEVICE_ID_OPTI_82C700 0xc700 -#define PCI_DEVICE_ID_OPTI_82C825 0xd568 - -#define PCI_VENDOR_ID_ELSA 0x1048 -#define PCI_DEVICE_ID_ELSA_MICROLINK 0x1000 -#define PCI_DEVICE_ID_ELSA_QS3000 0x3000 - -#define PCI_VENDOR_ID_BUSLOGIC 0x104B -#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140 -#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040 -#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130 - -#define PCI_VENDOR_ID_TI 0x104c -#define PCI_DEVICE_ID_TI_TVP4020 0x3d07 -#define PCI_DEVICE_ID_TI_4450 0x8011 -#define PCI_DEVICE_ID_TI_TSB43AB22 0x8023 -#define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 -#define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033 -#define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034 -#define PCI_DEVICE_ID_TI_X515 0x8036 -#define PCI_DEVICE_ID_TI_XX12 0x8039 -#define PCI_DEVICE_ID_TI_XX12_FM 0x803b -#define PCI_DEVICE_ID_TI_1130 0xac12 -#define PCI_DEVICE_ID_TI_1031 0xac13 -#define PCI_DEVICE_ID_TI_1131 0xac15 -#define PCI_DEVICE_ID_TI_1250 0xac16 -#define PCI_DEVICE_ID_TI_1220 0xac17 -#define PCI_DEVICE_ID_TI_1221 0xac19 -#define PCI_DEVICE_ID_TI_1210 0xac1a -#define PCI_DEVICE_ID_TI_1450 0xac1b -#define PCI_DEVICE_ID_TI_1225 0xac1c -#define PCI_DEVICE_ID_TI_1251A 0xac1d -#define PCI_DEVICE_ID_TI_1211 0xac1e -#define PCI_DEVICE_ID_TI_1251B 0xac1f -#define PCI_DEVICE_ID_TI_4410 0xac41 -#define PCI_DEVICE_ID_TI_4451 0xac42 -#define PCI_DEVICE_ID_TI_4510 0xac44 -#define PCI_DEVICE_ID_TI_4520 0xac46 -#define PCI_DEVICE_ID_TI_7510 0xac47 -#define PCI_DEVICE_ID_TI_7610 0xac48 -#define PCI_DEVICE_ID_TI_7410 0xac49 -#define PCI_DEVICE_ID_TI_1410 0xac50 -#define PCI_DEVICE_ID_TI_1420 0xac51 -#define PCI_DEVICE_ID_TI_1451A 0xac52 -#define PCI_DEVICE_ID_TI_1620 0xac54 -#define PCI_DEVICE_ID_TI_1520 0xac55 -#define PCI_DEVICE_ID_TI_1510 0xac56 -#define PCI_DEVICE_ID_TI_X620 0xac8d -#define PCI_DEVICE_ID_TI_X420 0xac8e -#define PCI_DEVICE_ID_TI_XX20_FM 0xac8f - -#define PCI_VENDOR_ID_SONY 0x104d - -/* Winbond have two vendor IDs! See 0x10ad as well */ -#define PCI_VENDOR_ID_WINBOND2 0x1050 -#define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a -#define PCI_DEVICE_ID_WINBOND2_6692 0x6692 - -#define PCI_VENDOR_ID_ANIGMA 0x1051 -#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100 - -#define PCI_VENDOR_ID_EFAR 0x1055 -#define PCI_DEVICE_ID_EFAR_SLC90E66_1 0x9130 -#define PCI_DEVICE_ID_EFAR_SLC90E66_3 0x9463 - -#define PCI_VENDOR_ID_MOTOROLA 0x1057 -#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001 -#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002 -#define PCI_DEVICE_ID_MOTOROLA_MPC107 0x0004 -#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801 -#define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802 -#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803 -#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b -#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803 -#define PCI_DEVICE_ID_MOTOROLA_MPC5200B 0x5809 - -#define PCI_VENDOR_ID_PROMISE 0x105a -#define PCI_DEVICE_ID_PROMISE_20265 0x0d30 -#define PCI_DEVICE_ID_PROMISE_20267 0x4d30 -#define PCI_DEVICE_ID_PROMISE_20246 0x4d33 -#define PCI_DEVICE_ID_PROMISE_20262 0x4d38 -#define PCI_DEVICE_ID_PROMISE_20263 0x0D38 -#define PCI_DEVICE_ID_PROMISE_20268 0x4d68 -#define PCI_DEVICE_ID_PROMISE_20269 0x4d69 -#define PCI_DEVICE_ID_PROMISE_20270 0x6268 -#define PCI_DEVICE_ID_PROMISE_20271 0x6269 -#define PCI_DEVICE_ID_PROMISE_20275 0x1275 -#define PCI_DEVICE_ID_PROMISE_20276 0x5275 -#define PCI_DEVICE_ID_PROMISE_20277 0x7275 - -#define PCI_VENDOR_ID_UMC 0x1060 -#define PCI_DEVICE_ID_UMC_UM8673F 0x0101 -#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a -#define PCI_DEVICE_ID_UMC_UM8886A 0x886a - -#define PCI_VENDOR_ID_PICOPOWER 0x1066 -#define PCI_DEVICE_ID_PICOPOWER_PT86C523 0x0002 -#define PCI_DEVICE_ID_PICOPOWER_PT86C523BBP 0x8002 - -#define PCI_VENDOR_ID_MYLEX 0x1069 -#define PCI_DEVICE_ID_MYLEX_DAC960_P 0x0001 -#define PCI_DEVICE_ID_MYLEX_DAC960_PD 0x0002 -#define PCI_DEVICE_ID_MYLEX_DAC960_PG 0x0010 -#define PCI_DEVICE_ID_MYLEX_DAC960_LA 0x0020 -#define PCI_DEVICE_ID_MYLEX_DAC960_LP 0x0050 -#define PCI_DEVICE_ID_MYLEX_DAC960_BA 0xBA56 -#define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166 - -#define PCI_VENDOR_ID_APPLE 0x106b -#define PCI_DEVICE_ID_APPLE_BANDIT 0x0001 -#define PCI_DEVICE_ID_APPLE_HYDRA 0x000e -#define PCI_DEVICE_ID_APPLE_UNI_N_FW 0x0018 -#define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020 -#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021 -#define PCI_DEVICE_ID_APPLE_UNI_N_GMACP 0x0024 -#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P 0x0027 -#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15 0x002d -#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15 0x002e -#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2 0x0032 -#define PCI_DEVICE_ID_APPLE_UNI_N_ATA 0x0033 -#define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034 -#define PCI_DEVICE_ID_APPLE_IPID_ATA100 0x003b -#define PCI_DEVICE_ID_APPLE_K2_ATA100 0x0043 -#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b -#define PCI_DEVICE_ID_APPLE_K2_GMAC 0x004c -#define PCI_DEVICE_ID_APPLE_SH_ATA 0x0050 -#define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051 -#define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058 -#define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059 -#define PCI_DEVICE_ID_APPLE_IPID2_AGP 0x0066 -#define PCI_DEVICE_ID_APPLE_IPID2_ATA 0x0069 -#define PCI_DEVICE_ID_APPLE_IPID2_FW 0x006a -#define PCI_DEVICE_ID_APPLE_IPID2_GMAC 0x006b -#define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 - -#define PCI_VENDOR_ID_YAMAHA 0x1073 -#define PCI_DEVICE_ID_YAMAHA_724 0x0004 -#define PCI_DEVICE_ID_YAMAHA_724F 0x000d -#define PCI_DEVICE_ID_YAMAHA_740 0x000a -#define PCI_DEVICE_ID_YAMAHA_740C 0x000c -#define PCI_DEVICE_ID_YAMAHA_744 0x0010 -#define PCI_DEVICE_ID_YAMAHA_754 0x0012 - -#define PCI_VENDOR_ID_QLOGIC 0x1077 -#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 -#define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020 -#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 -#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 -#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 -#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 -#define PCI_DEVICE_ID_QLOGIC_ISP2100 0x2100 -#define PCI_DEVICE_ID_QLOGIC_ISP2200 0x2200 -#define PCI_DEVICE_ID_QLOGIC_ISP2300 0x2300 -#define PCI_DEVICE_ID_QLOGIC_ISP2312 0x2312 -#define PCI_DEVICE_ID_QLOGIC_ISP2322 0x2322 -#define PCI_DEVICE_ID_QLOGIC_ISP6312 0x6312 -#define PCI_DEVICE_ID_QLOGIC_ISP6322 0x6322 -#define PCI_DEVICE_ID_QLOGIC_ISP2422 0x2422 -#define PCI_DEVICE_ID_QLOGIC_ISP2432 0x2432 -#define PCI_DEVICE_ID_QLOGIC_ISP2512 0x2512 -#define PCI_DEVICE_ID_QLOGIC_ISP2522 0x2522 -#define PCI_DEVICE_ID_QLOGIC_ISP5422 0x5422 -#define PCI_DEVICE_ID_QLOGIC_ISP5432 0x5432 - -#define PCI_VENDOR_ID_CYRIX 0x1078 -#define PCI_DEVICE_ID_CYRIX_5510 0x0000 -#define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001 -#define PCI_DEVICE_ID_CYRIX_5520 0x0002 -#define PCI_DEVICE_ID_CYRIX_5530_LEGACY 0x0100 -#define PCI_DEVICE_ID_CYRIX_5530_IDE 0x0102 -#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103 -#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104 - -#define PCI_VENDOR_ID_CONTAQ 0x1080 -#define PCI_DEVICE_ID_CONTAQ_82C693 0xc693 - -#define PCI_VENDOR_ID_OLICOM 0x108d -#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012 -#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013 -#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014 - -#define PCI_VENDOR_ID_SUN 0x108e -#define PCI_DEVICE_ID_SUN_EBUS 0x1000 -#define PCI_DEVICE_ID_SUN_HAPPYMEAL 0x1001 -#define PCI_DEVICE_ID_SUN_RIO_EBUS 0x1100 -#define PCI_DEVICE_ID_SUN_RIO_GEM 0x1101 -#define PCI_DEVICE_ID_SUN_RIO_1394 0x1102 -#define PCI_DEVICE_ID_SUN_RIO_USB 0x1103 -#define PCI_DEVICE_ID_SUN_GEM 0x2bad -#define PCI_DEVICE_ID_SUN_SIMBA 0x5000 -#define PCI_DEVICE_ID_SUN_PBM 0x8000 -#define PCI_DEVICE_ID_SUN_SCHIZO 0x8001 -#define PCI_DEVICE_ID_SUN_SABRE 0xa000 -#define PCI_DEVICE_ID_SUN_HUMMINGBIRD 0xa001 -#define PCI_DEVICE_ID_SUN_TOMATILLO 0xa801 -#define PCI_DEVICE_ID_SUN_CASSINI 0xabba - -#define PCI_VENDOR_ID_CMD 0x1095 -#define PCI_DEVICE_ID_CMD_643 0x0643 -#define PCI_DEVICE_ID_CMD_646 0x0646 -#define PCI_DEVICE_ID_CMD_648 0x0648 -#define PCI_DEVICE_ID_CMD_649 0x0649 - -#define PCI_DEVICE_ID_SII_680 0x0680 -#define PCI_DEVICE_ID_SII_3112 0x3112 -#define PCI_DEVICE_ID_SII_1210SA 0x0240 - -#define PCI_VENDOR_ID_BROOKTREE 0x109e -#define PCI_DEVICE_ID_BROOKTREE_878 0x0878 -#define PCI_DEVICE_ID_BROOKTREE_879 0x0879 - -#define PCI_VENDOR_ID_SGI 0x10a9 -#define PCI_DEVICE_ID_SGI_IOC3 0x0003 -#define PCI_DEVICE_ID_SGI_LITHIUM 0x1002 -#define PCI_DEVICE_ID_SGI_IOC4 0x100a - -#define PCI_VENDOR_ID_WINBOND 0x10ad -#define PCI_DEVICE_ID_WINBOND_82C105 0x0105 -#define PCI_DEVICE_ID_WINBOND_83C553 0x0565 - -#define PCI_VENDOR_ID_PLX 0x10b5 -#define PCI_DEVICE_ID_PLX_R685 0x1030 -#define PCI_DEVICE_ID_PLX_ROMULUS 0x106a -#define PCI_DEVICE_ID_PLX_SPCOM800 0x1076 -#define PCI_DEVICE_ID_PLX_1077 0x1077 -#define PCI_DEVICE_ID_PLX_SPCOM200 0x1103 -#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151 -#define PCI_DEVICE_ID_PLX_R753 0x1152 -#define PCI_DEVICE_ID_PLX_OLITEC 0x1187 -#define PCI_DEVICE_ID_PLX_PCI200SYN 0x3196 -#define PCI_DEVICE_ID_PLX_9030 0x9030 -#define PCI_DEVICE_ID_PLX_9050 0x9050 -#define PCI_DEVICE_ID_PLX_9080 0x9080 -#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001 - -#define PCI_VENDOR_ID_MADGE 0x10b6 -#define PCI_DEVICE_ID_MADGE_MK2 0x0002 - -#define PCI_VENDOR_ID_3COM 0x10b7 -#define PCI_DEVICE_ID_3COM_3C985 0x0001 -#define PCI_DEVICE_ID_3COM_3C940 0x1700 -#define PCI_DEVICE_ID_3COM_3C339 0x3390 -#define PCI_DEVICE_ID_3COM_3C359 0x3590 -#define PCI_DEVICE_ID_3COM_3C940B 0x80eb -#define PCI_DEVICE_ID_3COM_3CR990 0x9900 -#define PCI_DEVICE_ID_3COM_3CR990_TX_95 0x9902 -#define PCI_DEVICE_ID_3COM_3CR990_TX_97 0x9903 -#define PCI_DEVICE_ID_3COM_3CR990B 0x9904 -#define PCI_DEVICE_ID_3COM_3CR990_FX 0x9905 -#define PCI_DEVICE_ID_3COM_3CR990SVR95 0x9908 -#define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909 -#define PCI_DEVICE_ID_3COM_3CR990SVR 0x990a - -#define PCI_VENDOR_ID_AL 0x10b9 -#define PCI_DEVICE_ID_AL_M1533 0x1533 -#define PCI_DEVICE_ID_AL_M1535 0x1535 -#define PCI_DEVICE_ID_AL_M1541 0x1541 -#define PCI_DEVICE_ID_AL_M1563 0x1563 -#define PCI_DEVICE_ID_AL_M1621 0x1621 -#define PCI_DEVICE_ID_AL_M1631 0x1631 -#define PCI_DEVICE_ID_AL_M1632 0x1632 -#define PCI_DEVICE_ID_AL_M1641 0x1641 -#define PCI_DEVICE_ID_AL_M1644 0x1644 -#define PCI_DEVICE_ID_AL_M1647 0x1647 -#define PCI_DEVICE_ID_AL_M1651 0x1651 -#define PCI_DEVICE_ID_AL_M1671 0x1671 -#define PCI_DEVICE_ID_AL_M1681 0x1681 -#define PCI_DEVICE_ID_AL_M1683 0x1683 -#define PCI_DEVICE_ID_AL_M1689 0x1689 -#define PCI_DEVICE_ID_AL_M5219 0x5219 -#define PCI_DEVICE_ID_AL_M5228 0x5228 -#define PCI_DEVICE_ID_AL_M5229 0x5229 -#define PCI_DEVICE_ID_AL_M5451 0x5451 -#define PCI_DEVICE_ID_AL_M7101 0x7101 - -#define PCI_VENDOR_ID_NEOMAGIC 0x10c8 -#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005 -#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006 -#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016 - -#define PCI_VENDOR_ID_TCONRAD 0x10da -#define PCI_DEVICE_ID_TCONRAD_TOKENRING 0x0508 - -#define PCI_VENDOR_ID_NVIDIA 0x10de -#define PCI_DEVICE_ID_NVIDIA_TNT 0x0020 -#define PCI_DEVICE_ID_NVIDIA_TNT2 0x0028 -#define PCI_DEVICE_ID_NVIDIA_UTNT2 0x0029 -#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN 0x002a -#define PCI_DEVICE_ID_NVIDIA_VTNT2 0x002C -#define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS 0x0034 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE 0x0035 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036 -#define PCI_DEVICE_ID_NVIDIA_NVENET_10 0x0037 -#define PCI_DEVICE_ID_NVIDIA_NVENET_11 0x0038 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2 0x003e -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800 0x0041 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE 0x0042 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x0045 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000 0x004E -#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS 0x0052 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE 0x0053 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2 0x0055 -#define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056 -#define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057 -#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 -#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE 0x005d -#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 -#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 -#define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 -#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069 -#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a -#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084 -#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085 -#define PCI_DEVICE_ID_NVIDIA_NVENET_4 0x0086 -#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089 -#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a -#define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c -#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT 0x0090 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX 0x0091 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800 0x0098 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099 -#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 -#define PCI_DEVICE_ID_GEFORCE_6800A 0x00c1 -#define PCI_DEVICE_ID_GEFORCE_6800A_LE 0x00c2 -#define PCI_DEVICE_ID_GEFORCE_GO_6800 0x00c8 -#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA 0x00c9 -#define PCI_DEVICE_ID_QUADRO_FX_GO1400 0x00cc -#define PCI_DEVICE_ID_QUADRO_FX_1400 0x00ce -#define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1 -#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4 -#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5 -#define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6 -#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9 -#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da -#define PCI_DEVICE_ID_NVIDIA_NVENET_7 0x00df -#define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1 -#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA 0x00e3 -#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00e4 -#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5 -#define PCI_DEVICE_ID_NVIDIA_NVENET_6 0x00e6 -#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea -#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee -#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0 -#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1 -#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2 -#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3 -#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9 -#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280 0x00fd -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 -#define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX 0x0110 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2 0x0111 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO 0x0112 -#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR 0x0113 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT 0x0140 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600 0x0141 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL 0x0145 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540 0x014E -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200 0x014F -#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS 0x0150 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2 0x0151 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA 0x0152 -#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO 0x0153 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200 0x0164 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250 0x0166 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1 0x0167 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1 0x0168 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460 0x0170 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440 0x0171 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420 0x0172 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE 0x0173 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO 0x0174 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO 0x0175 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO 0x0177 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL 0x0178 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_200 0x017A -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL 0x017B -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL 0x017C -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000 0x0185 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO 0x0186 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO 0x0187 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL 0x0188 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC 0x0189 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS 0x018A -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL 0x018B -#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2 0x01a0 -#define PCI_DEVICE_ID_NVIDIA_NFORCE 0x01a4 -#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc -#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM 0x01c1 -#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3 -#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1 0x0201 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2 0x0202 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC 0x0203 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B 0x0211 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE 0x0212 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT 0x0215 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600 0x0250 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400 0x0251 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200 0x0253 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS 0x0264 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS 0x0368 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE 0x036E -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2 0x037F -#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268 -#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO 0x0286 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL 0x0288 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL 0x0289 -#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL 0x028C -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA 0x0301 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800 0x0302 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000 0x0308 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000 0x0309 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA 0x0311 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600 0x0312 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE 0x0314 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600 0x031A -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650 0x031B -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700 0x031C -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200 0x0320 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA 0x0321 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1 0x0322 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE 0x0323 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200 0x0324 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250 0x0325 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500 0x0326 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100 0x0327 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32 0x0328 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200 0x0329 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI 0x032A -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500 0x032B -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300 0x032C -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100 0x032D -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA 0x0330 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900 0x0331 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT 0x0332 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA 0x0333 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT 0x0334 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000 0x0338 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700 0x033F -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA 0x0341 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700 0x0342 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE 0x0343 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE 0x0344 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1 0x0347 -#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348 -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C -#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E -#define PCI_DEVICE_ID_NVIDIA_NVENET_14 0x0372 -#define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 -#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5 -#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS 0x03EB -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC -#define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE -#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS 0x0446 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448 -#define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450 -#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 -#define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452 -#define PCI_DEVICE_ID_NVIDIA_NVENET_23 0x0453 -#define PCI_DEVICE_ID_NVIDIA_NVENET_24 0x054C -#define PCI_DEVICE_ID_NVIDIA_NVENET_25 0x054D -#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E -#define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F -#define PCI_DEVICE_ID_NVIDIA_NVENET_28 0x07DC -#define PCI_DEVICE_ID_NVIDIA_NVENET_29 0x07DD -#define PCI_DEVICE_ID_NVIDIA_NVENET_30 0x07DE -#define PCI_DEVICE_ID_NVIDIA_NVENET_31 0x07DF -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 -#define PCI_DEVICE_ID_NVIDIA_NVENET_32 0x0760 -#define PCI_DEVICE_ID_NVIDIA_NVENET_33 0x0761 -#define PCI_DEVICE_ID_NVIDIA_NVENET_34 0x0762 -#define PCI_DEVICE_ID_NVIDIA_NVENET_35 0x0763 -#define PCI_DEVICE_ID_NVIDIA_NVENET_36 0x0AB0 -#define PCI_DEVICE_ID_NVIDIA_NVENET_37 0x0AB1 -#define PCI_DEVICE_ID_NVIDIA_NVENET_38 0x0AB2 -#define PCI_DEVICE_ID_NVIDIA_NVENET_39 0x0AB3 - -#define PCI_VENDOR_ID_IMS 0x10e0 -#define PCI_DEVICE_ID_IMS_TT128 0x9128 -#define PCI_DEVICE_ID_IMS_TT3D 0x9135 - -#define PCI_VENDOR_ID_INTERG 0x10ea -#define PCI_DEVICE_ID_INTERG_1682 0x1682 -#define PCI_DEVICE_ID_INTERG_2000 0x2000 -#define PCI_DEVICE_ID_INTERG_2010 0x2010 -#define PCI_DEVICE_ID_INTERG_5000 0x5000 -#define PCI_DEVICE_ID_INTERG_5050 0x5050 - -#define PCI_VENDOR_ID_REALTEK 0x10ec -#define PCI_DEVICE_ID_REALTEK_8139 0x8139 - -#define PCI_VENDOR_ID_XILINX 0x10ee -#define PCI_DEVICE_ID_RME_DIGI96 0x3fc0 -#define PCI_DEVICE_ID_RME_DIGI96_8 0x3fc1 -#define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2 -#define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3 -#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 -#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6 - -#define PCI_VENDOR_ID_INIT 0x1101 - -#define PCI_VENDOR_ID_CREATIVE 0x1102 /* duplicate: ECTIVA */ -#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002 - -#define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */ -#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938 - -#define PCI_VENDOR_ID_TTI 0x1103 -#define PCI_DEVICE_ID_TTI_HPT343 0x0003 -#define PCI_DEVICE_ID_TTI_HPT366 0x0004 -#define PCI_DEVICE_ID_TTI_HPT372 0x0005 -#define PCI_DEVICE_ID_TTI_HPT302 0x0006 -#define PCI_DEVICE_ID_TTI_HPT371 0x0007 -#define PCI_DEVICE_ID_TTI_HPT374 0x0008 -#define PCI_DEVICE_ID_TTI_HPT372N 0x0009 /* apparently a 372N variant? */ - -#define PCI_VENDOR_ID_VIA 0x1106 -#define PCI_DEVICE_ID_VIA_8763_0 0x0198 -#define PCI_DEVICE_ID_VIA_8380_0 0x0204 -#define PCI_DEVICE_ID_VIA_3238_0 0x0238 -#define PCI_DEVICE_ID_VIA_PT880 0x0258 -#define PCI_DEVICE_ID_VIA_PT880ULTRA 0x0308 -#define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259 -#define PCI_DEVICE_ID_VIA_3269_0 0x0269 -#define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282 -#define PCI_DEVICE_ID_VIA_3296_0 0x0296 -#define PCI_DEVICE_ID_VIA_8363_0 0x0305 -#define PCI_DEVICE_ID_VIA_P4M800CE 0x0314 -#define PCI_DEVICE_ID_VIA_P4M890 0x0327 -#define PCI_DEVICE_ID_VIA_VT3324 0x0324 -#define PCI_DEVICE_ID_VIA_VT3336 0x0336 -#define PCI_DEVICE_ID_VIA_VT3351 0x0351 -#define PCI_DEVICE_ID_VIA_VT3364 0x0364 -#define PCI_DEVICE_ID_VIA_8371_0 0x0391 -#define PCI_DEVICE_ID_VIA_8501_0 0x0501 -#define PCI_DEVICE_ID_VIA_82C561 0x0561 -#define PCI_DEVICE_ID_VIA_82C586_1 0x0571 -#define PCI_DEVICE_ID_VIA_82C576 0x0576 -#define PCI_DEVICE_ID_VIA_82C586_0 0x0586 -#define PCI_DEVICE_ID_VIA_82C596 0x0596 -#define PCI_DEVICE_ID_VIA_82C597_0 0x0597 -#define PCI_DEVICE_ID_VIA_82C598_0 0x0598 -#define PCI_DEVICE_ID_VIA_8601_0 0x0601 -#define PCI_DEVICE_ID_VIA_8605_0 0x0605 -#define PCI_DEVICE_ID_VIA_82C686 0x0686 -#define PCI_DEVICE_ID_VIA_82C691_0 0x0691 -#define PCI_DEVICE_ID_VIA_82C576_1 0x1571 -#define PCI_DEVICE_ID_VIA_82C586_2 0x3038 -#define PCI_DEVICE_ID_VIA_82C586_3 0x3040 -#define PCI_DEVICE_ID_VIA_82C596_3 0x3050 -#define PCI_DEVICE_ID_VIA_82C596B_3 0x3051 -#define PCI_DEVICE_ID_VIA_82C686_4 0x3057 -#define PCI_DEVICE_ID_VIA_82C686_5 0x3058 -#define PCI_DEVICE_ID_VIA_8233_5 0x3059 -#define PCI_DEVICE_ID_VIA_8233_0 0x3074 -#define PCI_DEVICE_ID_VIA_8633_0 0x3091 -#define PCI_DEVICE_ID_VIA_8367_0 0x3099 -#define PCI_DEVICE_ID_VIA_8653_0 0x3101 -#define PCI_DEVICE_ID_VIA_8622 0x3102 -#define PCI_DEVICE_ID_VIA_8235_USB_2 0x3104 -#define PCI_DEVICE_ID_VIA_8233C_0 0x3109 -#define PCI_DEVICE_ID_VIA_8361 0x3112 -#define PCI_DEVICE_ID_VIA_XM266 0x3116 -#define PCI_DEVICE_ID_VIA_612X 0x3119 -#define PCI_DEVICE_ID_VIA_862X_0 0x3123 -#define PCI_DEVICE_ID_VIA_8753_0 0x3128 -#define PCI_DEVICE_ID_VIA_8233A 0x3147 -#define PCI_DEVICE_ID_VIA_8703_51_0 0x3148 -#define PCI_DEVICE_ID_VIA_8237_SATA 0x3149 -#define PCI_DEVICE_ID_VIA_XN266 0x3156 -#define PCI_DEVICE_ID_VIA_6410 0x3164 -#define PCI_DEVICE_ID_VIA_8754C_0 0x3168 -#define PCI_DEVICE_ID_VIA_8235 0x3177 -#define PCI_DEVICE_ID_VIA_8385_0 0x3188 -#define PCI_DEVICE_ID_VIA_8377_0 0x3189 -#define PCI_DEVICE_ID_VIA_8378_0 0x3205 -#define PCI_DEVICE_ID_VIA_8783_0 0x3208 -#define PCI_DEVICE_ID_VIA_8237 0x3227 -#define PCI_DEVICE_ID_VIA_8251 0x3287 -#define PCI_DEVICE_ID_VIA_8237A 0x3337 -#define PCI_DEVICE_ID_VIA_8237S 0x3372 -#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x5324 -#define PCI_DEVICE_ID_VIA_8231 0x8231 -#define PCI_DEVICE_ID_VIA_8231_4 0x8235 -#define PCI_DEVICE_ID_VIA_8365_1 0x8305 -#define PCI_DEVICE_ID_VIA_CX700 0x8324 -#define PCI_DEVICE_ID_VIA_CX700_IDE 0x0581 -#define PCI_DEVICE_ID_VIA_VX800 0x8353 -#define PCI_DEVICE_ID_VIA_8371_1 0x8391 -#define PCI_DEVICE_ID_VIA_82C598_1 0x8598 -#define PCI_DEVICE_ID_VIA_838X_1 0xB188 -#define PCI_DEVICE_ID_VIA_83_87XX_1 0xB198 - -#define PCI_VENDOR_ID_SIEMENS 0x110A -#define PCI_DEVICE_ID_SIEMENS_DSCC4 0x2102 - -#define PCI_VENDOR_ID_VORTEX 0x1119 -#define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000 -#define PCI_DEVICE_ID_VORTEX_GDT6000B 0x0001 -#define PCI_DEVICE_ID_VORTEX_GDT6x10 0x0002 -#define PCI_DEVICE_ID_VORTEX_GDT6x20 0x0003 -#define PCI_DEVICE_ID_VORTEX_GDT6530 0x0004 -#define PCI_DEVICE_ID_VORTEX_GDT6550 0x0005 -#define PCI_DEVICE_ID_VORTEX_GDT6x17 0x0006 -#define PCI_DEVICE_ID_VORTEX_GDT6x27 0x0007 -#define PCI_DEVICE_ID_VORTEX_GDT6537 0x0008 -#define PCI_DEVICE_ID_VORTEX_GDT6557 0x0009 -#define PCI_DEVICE_ID_VORTEX_GDT6x15 0x000a -#define PCI_DEVICE_ID_VORTEX_GDT6x25 0x000b -#define PCI_DEVICE_ID_VORTEX_GDT6535 0x000c -#define PCI_DEVICE_ID_VORTEX_GDT6555 0x000d -#define PCI_DEVICE_ID_VORTEX_GDT6x17RP 0x0100 -#define PCI_DEVICE_ID_VORTEX_GDT6x27RP 0x0101 -#define PCI_DEVICE_ID_VORTEX_GDT6537RP 0x0102 -#define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103 -#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104 -#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105 - -#define PCI_VENDOR_ID_EF 0x111a -#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000 -#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002 -#define PCI_DEVICE_ID_EF_ATM_LANAI2 0x0003 -#define PCI_DEVICE_ID_EF_ATM_LANAIHB 0x0005 - -#define PCI_VENDOR_ID_IDT 0x111d -#define PCI_DEVICE_ID_IDT_IDT77201 0x0001 - -#define PCI_VENDOR_ID_FORE 0x1127 -#define PCI_DEVICE_ID_FORE_PCA200E 0x0300 - -#define PCI_VENDOR_ID_PHILIPS 0x1131 -#define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146 -#define PCI_DEVICE_ID_PHILIPS_SAA9730 0x9730 - -#define PCI_VENDOR_ID_EICON 0x1133 -#define PCI_DEVICE_ID_EICON_DIVA20 0xe002 -#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004 -#define PCI_DEVICE_ID_EICON_DIVA201 0xe005 -#define PCI_DEVICE_ID_EICON_DIVA202 0xe00b -#define PCI_DEVICE_ID_EICON_MAESTRA 0xe010 -#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012 -#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 -#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014 - -#define PCI_VENDOR_ID_CISCO 0x1137 - -#define PCI_VENDOR_ID_ZIATECH 0x1138 -#define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550 - - -#define PCI_VENDOR_ID_SYSKONNECT 0x1148 -#define PCI_DEVICE_ID_SYSKONNECT_TR 0x4200 -#define PCI_DEVICE_ID_SYSKONNECT_GE 0x4300 -#define PCI_DEVICE_ID_SYSKONNECT_YU 0x4320 -#define PCI_DEVICE_ID_SYSKONNECT_9DXX 0x4400 -#define PCI_DEVICE_ID_SYSKONNECT_9MXX 0x4500 - -#define PCI_VENDOR_ID_DIGI 0x114f -#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070 -#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071 -#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072 -#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073 -#define PCI_DEVICE_ID_NEO_2DB9 0x00C8 -#define PCI_DEVICE_ID_NEO_2DB9PRI 0x00C9 -#define PCI_DEVICE_ID_NEO_2RJ45 0x00CA -#define PCI_DEVICE_ID_NEO_2RJ45PRI 0x00CB -#define PCIE_DEVICE_ID_NEO_4_IBM 0x00F4 - -#define PCI_VENDOR_ID_XIRCOM 0x115d -#define PCI_DEVICE_ID_XIRCOM_RBM56G 0x0101 -#define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103 - -#define PCI_VENDOR_ID_SERVERWORKS 0x1166 -#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008 -#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 -#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017 -#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB 0x0036 -#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103 -#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132 -#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 -#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 -#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 -#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 -#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 -#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 -#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 -#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214 -#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217 -#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227 - -#define PCI_VENDOR_ID_SBE 0x1176 -#define PCI_DEVICE_ID_SBE_WANXL100 0x0301 -#define PCI_DEVICE_ID_SBE_WANXL200 0x0302 -#define PCI_DEVICE_ID_SBE_WANXL400 0x0104 - -#define PCI_VENDOR_ID_TOSHIBA 0x1179 -#define PCI_DEVICE_ID_TOSHIBA_PICCOLO 0x0102 -#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1 0x0103 -#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2 0x0105 -#define PCI_DEVICE_ID_TOSHIBA_TOPIC95 0x060a -#define PCI_DEVICE_ID_TOSHIBA_TOPIC97 0x060f -#define PCI_DEVICE_ID_TOSHIBA_TOPIC100 0x0617 - -#define PCI_VENDOR_ID_TOSHIBA_2 0x102f -#define PCI_DEVICE_ID_TOSHIBA_TC35815CF 0x0030 -#define PCI_DEVICE_ID_TOSHIBA_TC35815_NWU 0x0031 -#define PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939 0x0032 -#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE 0x0105 -#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 -#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 - -#define PCI_VENDOR_ID_ATTO 0x117c - -#define PCI_VENDOR_ID_RICOH 0x1180 -#define PCI_DEVICE_ID_RICOH_RL5C465 0x0465 -#define PCI_DEVICE_ID_RICOH_RL5C466 0x0466 -#define PCI_DEVICE_ID_RICOH_RL5C475 0x0475 -#define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 -#define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 -#define PCI_DEVICE_ID_RICOH_R5C822 0x0822 -#define PCI_DEVICE_ID_RICOH_R5C832 0x0832 -#define PCI_DEVICE_ID_RICOH_R5C843 0x0843 - -#define PCI_VENDOR_ID_DLINK 0x1186 -#define PCI_DEVICE_ID_DLINK_DGE510T 0x4c00 - -#define PCI_VENDOR_ID_ARTOP 0x1191 -#define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005 -#define PCI_DEVICE_ID_ARTOP_ATP860 0x0006 -#define PCI_DEVICE_ID_ARTOP_ATP860R 0x0007 -#define PCI_DEVICE_ID_ARTOP_ATP865 0x0008 -#define PCI_DEVICE_ID_ARTOP_ATP865R 0x0009 -#define PCI_DEVICE_ID_ARTOP_AEC7610 0x8002 -#define PCI_DEVICE_ID_ARTOP_AEC7612UW 0x8010 -#define PCI_DEVICE_ID_ARTOP_AEC7612U 0x8020 -#define PCI_DEVICE_ID_ARTOP_AEC7612S 0x8030 -#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040 -#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050 -#define PCI_DEVICE_ID_ARTOP_8060 0x8060 - -#define PCI_VENDOR_ID_ZEITNET 0x1193 -#define PCI_DEVICE_ID_ZEITNET_1221 0x0001 -#define PCI_DEVICE_ID_ZEITNET_1225 0x0002 - -#define PCI_VENDOR_ID_FUJITSU_ME 0x119e -#define PCI_DEVICE_ID_FUJITSU_FS155 0x0001 -#define PCI_DEVICE_ID_FUJITSU_FS50 0x0003 - -#define PCI_SUBVENDOR_ID_KEYSPAN 0x11a9 -#define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334 - -#define PCI_VENDOR_ID_MARVELL 0x11ab -#define PCI_DEVICE_ID_MARVELL_GT64111 0x4146 -#define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 -#define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 -#define PCI_DEVICE_ID_MARVELL_MV64460 0x6480 -#define PCI_DEVICE_ID_MARVELL_88ALP01_NAND 0x4100 -#define PCI_DEVICE_ID_MARVELL_88ALP01_SD 0x4101 -#define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC 0x4102 - -#define PCI_VENDOR_ID_V3 0x11b0 -#define PCI_DEVICE_ID_V3_V960 0x0001 -#define PCI_DEVICE_ID_V3_V351 0x0002 - -#define PCI_VENDOR_ID_ATT 0x11c1 -#define PCI_DEVICE_ID_ATT_VENUS_MODEM 0x480 - -#define PCI_VENDOR_ID_SPECIALIX 0x11cb -#define PCI_DEVICE_ID_SPECIALIX_IO8 0x2000 -#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000 -#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004 - -#define PCI_VENDOR_ID_ANALOG_DEVICES 0x11d4 -#define PCI_DEVICE_ID_AD1889JS 0x1889 - -#define PCI_DEVICE_ID_SEGA_BBA 0x1234 - -#define PCI_VENDOR_ID_ZORAN 0x11de -#define PCI_DEVICE_ID_ZORAN_36057 0x6057 -#define PCI_DEVICE_ID_ZORAN_36120 0x6120 - -#define PCI_VENDOR_ID_COMPEX 0x11f6 -#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112 - -#define PCI_VENDOR_ID_RP 0x11fe -#define PCI_DEVICE_ID_RP32INTF 0x0001 -#define PCI_DEVICE_ID_RP8INTF 0x0002 -#define PCI_DEVICE_ID_RP16INTF 0x0003 -#define PCI_DEVICE_ID_RP4QUAD 0x0004 -#define PCI_DEVICE_ID_RP8OCTA 0x0005 -#define PCI_DEVICE_ID_RP8J 0x0006 -#define PCI_DEVICE_ID_RP4J 0x0007 -#define PCI_DEVICE_ID_RP8SNI 0x0008 -#define PCI_DEVICE_ID_RP16SNI 0x0009 -#define PCI_DEVICE_ID_RPP4 0x000A -#define PCI_DEVICE_ID_RPP8 0x000B -#define PCI_DEVICE_ID_RP4M 0x000D -#define PCI_DEVICE_ID_RP2_232 0x000E -#define PCI_DEVICE_ID_RP2_422 0x000F -#define PCI_DEVICE_ID_URP32INTF 0x0801 -#define PCI_DEVICE_ID_URP8INTF 0x0802 -#define PCI_DEVICE_ID_URP16INTF 0x0803 -#define PCI_DEVICE_ID_URP8OCTA 0x0805 -#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C -#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D -#define PCI_DEVICE_ID_CRP16INTF 0x0903 - -#define PCI_VENDOR_ID_CYCLADES 0x120e -#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100 -#define PCI_DEVICE_ID_CYCLOM_Y_Hi 0x0101 -#define PCI_DEVICE_ID_CYCLOM_4Y_Lo 0x0102 -#define PCI_DEVICE_ID_CYCLOM_4Y_Hi 0x0103 -#define PCI_DEVICE_ID_CYCLOM_8Y_Lo 0x0104 -#define PCI_DEVICE_ID_CYCLOM_8Y_Hi 0x0105 -#define PCI_DEVICE_ID_CYCLOM_Z_Lo 0x0200 -#define PCI_DEVICE_ID_CYCLOM_Z_Hi 0x0201 -#define PCI_DEVICE_ID_PC300_RX_2 0x0300 -#define PCI_DEVICE_ID_PC300_RX_1 0x0301 -#define PCI_DEVICE_ID_PC300_TE_2 0x0310 -#define PCI_DEVICE_ID_PC300_TE_1 0x0311 -#define PCI_DEVICE_ID_PC300_TE_M_2 0x0320 -#define PCI_DEVICE_ID_PC300_TE_M_1 0x0321 - -#define PCI_VENDOR_ID_ESSENTIAL 0x120f -#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001 - -#define PCI_VENDOR_ID_O2 0x1217 -#define PCI_DEVICE_ID_O2_6729 0x6729 -#define PCI_DEVICE_ID_O2_6730 0x673a -#define PCI_DEVICE_ID_O2_6832 0x6832 -#define PCI_DEVICE_ID_O2_6836 0x6836 - -#define PCI_VENDOR_ID_3DFX 0x121a -#define PCI_DEVICE_ID_3DFX_VOODOO 0x0001 -#define PCI_DEVICE_ID_3DFX_VOODOO2 0x0002 -#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003 -#define PCI_DEVICE_ID_3DFX_VOODOO3 0x0005 -#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009 - -#define PCI_VENDOR_ID_AVM 0x1244 -#define PCI_DEVICE_ID_AVM_B1 0x0700 -#define PCI_DEVICE_ID_AVM_C4 0x0800 -#define PCI_DEVICE_ID_AVM_A1 0x0a00 -#define PCI_DEVICE_ID_AVM_A1_V2 0x0e00 -#define PCI_DEVICE_ID_AVM_C2 0x1100 -#define PCI_DEVICE_ID_AVM_T1 0x1200 - -#define PCI_VENDOR_ID_STALLION 0x124d - -/* Allied Telesyn */ -#define PCI_VENDOR_ID_AT 0x1259 -#define PCI_SUBDEVICE_ID_AT_2700FX 0x2701 -#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703 - -#define PCI_VENDOR_ID_ESS 0x125d -#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 -#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 -#define PCI_DEVICE_ID_ESS_ALLEGRO_1 0x1988 -#define PCI_DEVICE_ID_ESS_ALLEGRO 0x1989 -#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990 -#define PCI_DEVICE_ID_ESS_CANYON3D_2 0x1992 -#define PCI_DEVICE_ID_ESS_MAESTRO3 0x1998 -#define PCI_DEVICE_ID_ESS_MAESTRO3_1 0x1999 -#define PCI_DEVICE_ID_ESS_MAESTRO3_HW 0x199a -#define PCI_DEVICE_ID_ESS_MAESTRO3_2 0x199b - -#define PCI_VENDOR_ID_SATSAGEM 0x1267 -#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016 - -#define PCI_VENDOR_ID_ENSONIQ 0x1274 -#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880 -#define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000 -#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371 - -#define PCI_VENDOR_ID_TRANSMETA 0x1279 -#define PCI_DEVICE_ID_EFFICEON 0x0060 - -#define PCI_VENDOR_ID_ROCKWELL 0x127A - -#define PCI_VENDOR_ID_ITE 0x1283 -#define PCI_DEVICE_ID_ITE_8211 0x8211 -#define PCI_DEVICE_ID_ITE_8212 0x8212 -#define PCI_DEVICE_ID_ITE_8213 0x8213 -#define PCI_DEVICE_ID_ITE_8152 0x8152 -#define PCI_DEVICE_ID_ITE_8872 0x8872 -#define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886 - -/* formerly Platform Tech */ -#define PCI_DEVICE_ID_ESS_ESS0100 0x0100 - -#define PCI_VENDOR_ID_ALTEON 0x12ae - -#define PCI_SUBVENDOR_ID_CONNECT_TECH 0x12c4 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232 0x0001 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232 0x0002 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232 0x0003 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485 0x0004 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4 0x0005 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485 0x0006 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2 0x0007 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485 0x0008 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6 0x0009 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1 0x000A -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1 0x000B -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ 0x000C -#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_PTM 0x000D -#define PCI_SUBDEVICE_ID_CONNECT_TECH_NT960PCI 0x0100 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2 0x0201 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4 0x0202 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232 0x0300 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232 0x0301 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232 0x0302 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1 0x0310 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2 0x0311 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4 0x0312 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2 0x0320 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4 0x0321 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8 0x0322 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485 0x0330 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485 0x0331 -#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485 0x0332 - -#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2 -#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018 - -#define PCI_SUBVENDOR_ID_CHASE_PCIFAST 0x12E0 -#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4 0x0031 -#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8 0x0021 -#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16 0x0011 -#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC 0x0041 -#define PCI_SUBVENDOR_ID_CHASE_PCIRAS 0x124D -#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4 0xF001 -#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8 0xF010 - -#define PCI_VENDOR_ID_AUREAL 0x12eb -#define PCI_DEVICE_ID_AUREAL_VORTEX_1 0x0001 -#define PCI_DEVICE_ID_AUREAL_VORTEX_2 0x0002 -#define PCI_DEVICE_ID_AUREAL_ADVANTAGE 0x0003 - -#define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8 -#define PCI_DEVICE_ID_LML_33R10 0x8a02 - -#define PCI_VENDOR_ID_ESDGMBH 0x12fe -#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111 - -#define PCI_VENDOR_ID_SIIG 0x131f -#define PCI_SUBVENDOR_ID_SIIG 0x131f -#define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000 -#define PCI_DEVICE_ID_SIIG_1S_10x_650 0x1001 -#define PCI_DEVICE_ID_SIIG_1S_10x_850 0x1002 -#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010 -#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011 -#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012 -#define PCI_DEVICE_ID_SIIG_1P_10x 0x1020 -#define PCI_DEVICE_ID_SIIG_2P_10x 0x1021 -#define PCI_DEVICE_ID_SIIG_2S_10x_550 0x1030 -#define PCI_DEVICE_ID_SIIG_2S_10x_650 0x1031 -#define PCI_DEVICE_ID_SIIG_2S_10x_850 0x1032 -#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034 -#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035 -#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036 -#define PCI_DEVICE_ID_SIIG_4S_10x_550 0x1050 -#define PCI_DEVICE_ID_SIIG_4S_10x_650 0x1051 -#define PCI_DEVICE_ID_SIIG_4S_10x_850 0x1052 -#define PCI_DEVICE_ID_SIIG_1S_20x_550 0x2000 -#define PCI_DEVICE_ID_SIIG_1S_20x_650 0x2001 -#define PCI_DEVICE_ID_SIIG_1S_20x_850 0x2002 -#define PCI_DEVICE_ID_SIIG_1P_20x 0x2020 -#define PCI_DEVICE_ID_SIIG_2P_20x 0x2021 -#define PCI_DEVICE_ID_SIIG_2S_20x_550 0x2030 -#define PCI_DEVICE_ID_SIIG_2S_20x_650 0x2031 -#define PCI_DEVICE_ID_SIIG_2S_20x_850 0x2032 -#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040 -#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041 -#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042 -#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010 -#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011 -#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012 -#define PCI_DEVICE_ID_SIIG_4S_20x_550 0x2050 -#define PCI_DEVICE_ID_SIIG_4S_20x_650 0x2051 -#define PCI_DEVICE_ID_SIIG_4S_20x_850 0x2052 -#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060 -#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061 -#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062 -#define PCI_DEVICE_ID_SIIG_8S_20x_550 0x2080 -#define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 -#define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 -#define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 - -#define PCI_VENDOR_ID_RADISYS 0x1331 - -#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332 -#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415 -#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425 -#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155 - -#define PCI_VENDOR_ID_DOMEX 0x134a -#define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 - -#define PCI_VENDOR_ID_INTASHIELD 0x135a -#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80 -#define PCI_DEVICE_ID_INTASHIELD_IS400 0x0dc0 - -#define PCI_VENDOR_ID_QUATECH 0x135C -#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 -#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020 -#define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050 -#define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060 -#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278 - -#define PCI_VENDOR_ID_SEALEVEL 0x135e -#define PCI_DEVICE_ID_SEALEVEL_U530 0x7101 -#define PCI_DEVICE_ID_SEALEVEL_UCOMM2 0x7201 -#define PCI_DEVICE_ID_SEALEVEL_UCOMM422 0x7402 -#define PCI_DEVICE_ID_SEALEVEL_UCOMM232 0x7202 -#define PCI_DEVICE_ID_SEALEVEL_COMM4 0x7401 -#define PCI_DEVICE_ID_SEALEVEL_COMM8 0x7801 -#define PCI_DEVICE_ID_SEALEVEL_UCOMM8 0x7804 - -#define PCI_VENDOR_ID_HYPERCOPE 0x1365 -#define PCI_DEVICE_ID_HYPERCOPE_PLX 0x9050 -#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO 0x0104 -#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO 0x0106 -#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO 0x0107 -#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108 - -#define PCI_VENDOR_ID_KAWASAKI 0x136b -#define PCI_DEVICE_ID_MCHIP_KL5A72002 0xff01 - -#define PCI_VENDOR_ID_CNET 0x1371 -#define PCI_DEVICE_ID_CNET_GIGACARD 0x434e - -#define PCI_VENDOR_ID_LMC 0x1376 -#define PCI_DEVICE_ID_LMC_HSSI 0x0003 -#define PCI_DEVICE_ID_LMC_DS3 0x0004 -#define PCI_DEVICE_ID_LMC_SSI 0x0005 -#define PCI_DEVICE_ID_LMC_T1 0x0006 - -#define PCI_VENDOR_ID_NETGEAR 0x1385 -#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a - -#define PCI_VENDOR_ID_APPLICOM 0x1389 -#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001 -#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002 -#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 - -#define PCI_VENDOR_ID_MOXA 0x1393 -#define PCI_DEVICE_ID_MOXA_RC7000 0x0001 -#define PCI_DEVICE_ID_MOXA_CP102 0x1020 -#define PCI_DEVICE_ID_MOXA_CP102UL 0x1021 -#define PCI_DEVICE_ID_MOXA_CP102U 0x1022 -#define PCI_DEVICE_ID_MOXA_C104 0x1040 -#define PCI_DEVICE_ID_MOXA_CP104U 0x1041 -#define PCI_DEVICE_ID_MOXA_CP104JU 0x1042 -#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043 -#define PCI_DEVICE_ID_MOXA_CT114 0x1140 -#define PCI_DEVICE_ID_MOXA_CP114 0x1141 -#define PCI_DEVICE_ID_MOXA_CP118U 0x1180 -#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181 -#define PCI_DEVICE_ID_MOXA_CP132 0x1320 -#define PCI_DEVICE_ID_MOXA_CP132U 0x1321 -#define PCI_DEVICE_ID_MOXA_CP134U 0x1340 -#define PCI_DEVICE_ID_MOXA_C168 0x1680 -#define PCI_DEVICE_ID_MOXA_CP168U 0x1681 -#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682 -#define PCI_DEVICE_ID_MOXA_CP204J 0x2040 -#define PCI_DEVICE_ID_MOXA_C218 0x2180 -#define PCI_DEVICE_ID_MOXA_C320 0x3200 - -#define PCI_VENDOR_ID_CCD 0x1397 -#define PCI_DEVICE_ID_CCD_HFC4S 0x08B4 -#define PCI_SUBDEVICE_ID_CCD_PMX2S 0x1234 -#define PCI_DEVICE_ID_CCD_HFC8S 0x16B8 -#define PCI_DEVICE_ID_CCD_2BD0 0x2bd0 -#define PCI_DEVICE_ID_CCD_HFCE1 0x30B1 -#define PCI_SUBDEVICE_ID_CCD_SPD4S 0x3136 -#define PCI_SUBDEVICE_ID_CCD_SPDE1 0x3137 -#define PCI_DEVICE_ID_CCD_B000 0xb000 -#define PCI_DEVICE_ID_CCD_B006 0xb006 -#define PCI_DEVICE_ID_CCD_B007 0xb007 -#define PCI_DEVICE_ID_CCD_B008 0xb008 -#define PCI_DEVICE_ID_CCD_B009 0xb009 -#define PCI_DEVICE_ID_CCD_B00A 0xb00a -#define PCI_DEVICE_ID_CCD_B00B 0xb00b -#define PCI_DEVICE_ID_CCD_B00C 0xb00c -#define PCI_DEVICE_ID_CCD_B100 0xb100 -#define PCI_SUBDEVICE_ID_CCD_IOB4ST 0xB520 -#define PCI_SUBDEVICE_ID_CCD_IOB8STR 0xB521 -#define PCI_SUBDEVICE_ID_CCD_IOB8ST 0xB522 -#define PCI_SUBDEVICE_ID_CCD_IOB1E1 0xB523 -#define PCI_SUBDEVICE_ID_CCD_SWYX4S 0xB540 -#define PCI_SUBDEVICE_ID_CCD_JH4S20 0xB550 -#define PCI_SUBDEVICE_ID_CCD_IOB8ST_1 0xB552 -#define PCI_SUBDEVICE_ID_CCD_BN4S 0xB560 -#define PCI_SUBDEVICE_ID_CCD_BN8S 0xB562 -#define PCI_SUBDEVICE_ID_CCD_BNE1 0xB563 -#define PCI_SUBDEVICE_ID_CCD_BNE1D 0xB564 -#define PCI_SUBDEVICE_ID_CCD_BNE1DP 0xB565 -#define PCI_SUBDEVICE_ID_CCD_BN2S 0xB566 -#define PCI_SUBDEVICE_ID_CCD_BN1SM 0xB567 -#define PCI_SUBDEVICE_ID_CCD_BN4SM 0xB568 -#define PCI_SUBDEVICE_ID_CCD_BN2SM 0xB569 -#define PCI_SUBDEVICE_ID_CCD_BNE1M 0xB56A -#define PCI_SUBDEVICE_ID_CCD_BN8SP 0xB56B -#define PCI_SUBDEVICE_ID_CCD_HFC4S 0xB620 -#define PCI_SUBDEVICE_ID_CCD_HFC8S 0xB622 -#define PCI_DEVICE_ID_CCD_B700 0xb700 -#define PCI_DEVICE_ID_CCD_B701 0xb701 -#define PCI_SUBDEVICE_ID_CCD_HFCE1 0xC523 -#define PCI_SUBDEVICE_ID_CCD_OV2S 0xE884 -#define PCI_SUBDEVICE_ID_CCD_OV4S 0xE888 -#define PCI_SUBDEVICE_ID_CCD_OV8S 0xE998 - -#define PCI_VENDOR_ID_EXAR 0x13a8 -#define PCI_DEVICE_ID_EXAR_XR17C152 0x0152 -#define PCI_DEVICE_ID_EXAR_XR17C154 0x0154 -#define PCI_DEVICE_ID_EXAR_XR17C158 0x0158 - -#define PCI_VENDOR_ID_MICROGATE 0x13c0 -#define PCI_DEVICE_ID_MICROGATE_USC 0x0010 -#define PCI_DEVICE_ID_MICROGATE_SCA 0x0030 - -#define PCI_VENDOR_ID_3WARE 0x13C1 -#define PCI_DEVICE_ID_3WARE_1000 0x1000 -#define PCI_DEVICE_ID_3WARE_7000 0x1001 -#define PCI_DEVICE_ID_3WARE_9000 0x1002 - -#define PCI_VENDOR_ID_IOMEGA 0x13ca -#define PCI_DEVICE_ID_IOMEGA_BUZ 0x4231 - -#define PCI_VENDOR_ID_ABOCOM 0x13D1 -#define PCI_DEVICE_ID_ABOCOM_2BD1 0x2BD1 - -#define PCI_VENDOR_ID_SUNDANCE 0x13f0 - -#define PCI_VENDOR_ID_CMEDIA 0x13f6 -#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100 -#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101 -#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 -#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112 - -#define PCI_VENDOR_ID_LAVA 0x1407 -#define PCI_DEVICE_ID_LAVA_DSERIAL 0x0100 /* 2x 16550 */ -#define PCI_DEVICE_ID_LAVA_QUATRO_A 0x0101 /* 2x 16550, half of 4 port */ -#define PCI_DEVICE_ID_LAVA_QUATRO_B 0x0102 /* 2x 16550, half of 4 port */ -#define PCI_DEVICE_ID_LAVA_OCTO_A 0x0180 /* 4x 16550A, half of 8 port */ -#define PCI_DEVICE_ID_LAVA_OCTO_B 0x0181 /* 4x 16550A, half of 8 port */ -#define PCI_DEVICE_ID_LAVA_PORT_PLUS 0x0200 /* 2x 16650 */ -#define PCI_DEVICE_ID_LAVA_QUAD_A 0x0201 /* 2x 16650, half of 4 port */ -#define PCI_DEVICE_ID_LAVA_QUAD_B 0x0202 /* 2x 16650, half of 4 port */ -#define PCI_DEVICE_ID_LAVA_SSERIAL 0x0500 /* 1x 16550 */ -#define PCI_DEVICE_ID_LAVA_PORT_650 0x0600 /* 1x 16650 */ -#define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000 -#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8002 /* The Lava Dual Parallel is */ -#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8003 /* two PCI devices on a card */ -#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR 0x8800 - -#define PCI_VENDOR_ID_TIMEDIA 0x1409 -#define PCI_DEVICE_ID_TIMEDIA_1889 0x7168 - -#define PCI_VENDOR_ID_ICE 0x1412 -#define PCI_DEVICE_ID_ICE_1712 0x1712 -#define PCI_DEVICE_ID_VT1724 0x1724 - -#define PCI_VENDOR_ID_OXSEMI 0x1415 -#define PCI_DEVICE_ID_OXSEMI_12PCI840 0x8403 -#define PCI_DEVICE_ID_OXSEMI_PCIe840 0xC000 -#define PCI_DEVICE_ID_OXSEMI_PCIe840_G 0xC004 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_0 0xC100 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_0_G 0xC104 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1 0xC110 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_G 0xC114 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_U 0xC118 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU 0xC11C -#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501 -#define PCI_DEVICE_ID_OXSEMI_16PCI95N 0x9511 -#define PCI_DEVICE_ID_OXSEMI_16PCI954PP 0x9513 -#define PCI_DEVICE_ID_OXSEMI_16PCI952 0x9521 -#define PCI_DEVICE_ID_OXSEMI_16PCI952PP 0x9523 - -#define PCI_VENDOR_ID_CHELSIO 0x1425 - -#define PCI_VENDOR_ID_SAMSUNG 0x144d - -#define PCI_VENDOR_ID_MYRICOM 0x14c1 - -#define PCI_VENDOR_ID_TITAN 0x14D2 -#define PCI_DEVICE_ID_TITAN_010L 0x8001 -#define PCI_DEVICE_ID_TITAN_100L 0x8010 -#define PCI_DEVICE_ID_TITAN_110L 0x8011 -#define PCI_DEVICE_ID_TITAN_200L 0x8020 -#define PCI_DEVICE_ID_TITAN_210L 0x8021 -#define PCI_DEVICE_ID_TITAN_400L 0x8040 -#define PCI_DEVICE_ID_TITAN_800L 0x8080 -#define PCI_DEVICE_ID_TITAN_100 0xA001 -#define PCI_DEVICE_ID_TITAN_200 0xA005 -#define PCI_DEVICE_ID_TITAN_400 0xA003 -#define PCI_DEVICE_ID_TITAN_800B 0xA004 - -#define PCI_VENDOR_ID_PANACOM 0x14d4 -#define PCI_DEVICE_ID_PANACOM_QUADMODEM 0x0400 -#define PCI_DEVICE_ID_PANACOM_DUALMODEM 0x0402 - -#define PCI_VENDOR_ID_SIPACKETS 0x14d9 -#define PCI_DEVICE_ID_SP1011 0x0010 - -#define PCI_VENDOR_ID_AFAVLAB 0x14db -#define PCI_DEVICE_ID_AFAVLAB_P028 0x2180 -#define PCI_DEVICE_ID_AFAVLAB_P030 0x2182 -#define PCI_SUBDEVICE_ID_AFAVLAB_P061 0x2150 - -#define PCI_VENDOR_ID_BROADCOM 0x14e4 -#define PCI_DEVICE_ID_TIGON3_5752 0x1600 -#define PCI_DEVICE_ID_TIGON3_5752M 0x1601 -#define PCI_DEVICE_ID_NX2_5709 0x1639 -#define PCI_DEVICE_ID_NX2_5709S 0x163a -#define PCI_DEVICE_ID_TIGON3_5700 0x1644 -#define PCI_DEVICE_ID_TIGON3_5701 0x1645 -#define PCI_DEVICE_ID_TIGON3_5702 0x1646 -#define PCI_DEVICE_ID_TIGON3_5703 0x1647 -#define PCI_DEVICE_ID_TIGON3_5704 0x1648 -#define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 -#define PCI_DEVICE_ID_NX2_5706 0x164a -#define PCI_DEVICE_ID_NX2_5708 0x164c -#define PCI_DEVICE_ID_TIGON3_5702FE 0x164d -#define PCI_DEVICE_ID_NX2_57710 0x164e -#define PCI_DEVICE_ID_NX2_57711 0x164f -#define PCI_DEVICE_ID_NX2_57711E 0x1650 -#define PCI_DEVICE_ID_TIGON3_5705 0x1653 -#define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 -#define PCI_DEVICE_ID_TIGON3_5720 0x1658 -#define PCI_DEVICE_ID_TIGON3_5721 0x1659 -#define PCI_DEVICE_ID_TIGON3_5722 0x165a -#define PCI_DEVICE_ID_TIGON3_5723 0x165b -#define PCI_DEVICE_ID_TIGON3_5705M 0x165d -#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e -#define PCI_DEVICE_ID_TIGON3_5714 0x1668 -#define PCI_DEVICE_ID_TIGON3_5714S 0x1669 -#define PCI_DEVICE_ID_TIGON3_5780 0x166a -#define PCI_DEVICE_ID_TIGON3_5780S 0x166b -#define PCI_DEVICE_ID_TIGON3_5705F 0x166e -#define PCI_DEVICE_ID_TIGON3_5754M 0x1672 -#define PCI_DEVICE_ID_TIGON3_5755M 0x1673 -#define PCI_DEVICE_ID_TIGON3_5756 0x1674 -#define PCI_DEVICE_ID_TIGON3_5750 0x1676 -#define PCI_DEVICE_ID_TIGON3_5751 0x1677 -#define PCI_DEVICE_ID_TIGON3_5715 0x1678 -#define PCI_DEVICE_ID_TIGON3_5715S 0x1679 -#define PCI_DEVICE_ID_TIGON3_5754 0x167a -#define PCI_DEVICE_ID_TIGON3_5755 0x167b -#define PCI_DEVICE_ID_TIGON3_5750M 0x167c -#define PCI_DEVICE_ID_TIGON3_5751M 0x167d -#define PCI_DEVICE_ID_TIGON3_5751F 0x167e -#define PCI_DEVICE_ID_TIGON3_5787F 0x167f -#define PCI_DEVICE_ID_TIGON3_5761E 0x1680 -#define PCI_DEVICE_ID_TIGON3_5761 0x1681 -#define PCI_DEVICE_ID_TIGON3_5764 0x1684 -#define PCI_DEVICE_ID_TIGON3_5787M 0x1693 -#define PCI_DEVICE_ID_TIGON3_5782 0x1696 -#define PCI_DEVICE_ID_TIGON3_5784 0x1698 -#define PCI_DEVICE_ID_TIGON3_5785 0x1699 -#define PCI_DEVICE_ID_TIGON3_5786 0x169a -#define PCI_DEVICE_ID_TIGON3_5787 0x169b -#define PCI_DEVICE_ID_TIGON3_5788 0x169c -#define PCI_DEVICE_ID_TIGON3_5789 0x169d -#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 -#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 -#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 -#define PCI_DEVICE_ID_NX2_5706S 0x16aa -#define PCI_DEVICE_ID_NX2_5708S 0x16ac -#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 -#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 -#define PCI_DEVICE_ID_TIGON3_5781 0x16dd -#define PCI_DEVICE_ID_TIGON3_5753 0x16f7 -#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd -#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe -#define PCI_DEVICE_ID_TIGON3_5901 0x170d -#define PCI_DEVICE_ID_BCM4401B1 0x170c -#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e -#define PCI_DEVICE_ID_TIGON3_5906 0x1712 -#define PCI_DEVICE_ID_TIGON3_5906M 0x1713 -#define PCI_DEVICE_ID_BCM4401 0x4401 -#define PCI_DEVICE_ID_BCM4401B0 0x4402 - -#define PCI_VENDOR_ID_TOPIC 0x151f -#define PCI_DEVICE_ID_TOPIC_TP560 0x0000 - -#define PCI_VENDOR_ID_MAINPINE 0x1522 -#define PCI_DEVICE_ID_MAINPINE_PBRIDGE 0x0100 -#define PCI_VENDOR_ID_ENE 0x1524 -#define PCI_DEVICE_ID_ENE_CB712_SD 0x0550 -#define PCI_DEVICE_ID_ENE_CB712_SD_2 0x0551 -#define PCI_DEVICE_ID_ENE_CB714_SD 0x0750 -#define PCI_DEVICE_ID_ENE_CB714_SD_2 0x0751 -#define PCI_DEVICE_ID_ENE_1211 0x1211 -#define PCI_DEVICE_ID_ENE_1225 0x1225 -#define PCI_DEVICE_ID_ENE_1410 0x1410 -#define PCI_DEVICE_ID_ENE_710 0x1411 -#define PCI_DEVICE_ID_ENE_712 0x1412 -#define PCI_DEVICE_ID_ENE_1420 0x1420 -#define PCI_DEVICE_ID_ENE_720 0x1421 -#define PCI_DEVICE_ID_ENE_722 0x1422 - -#define PCI_SUBVENDOR_ID_PERLE 0x155f -#define PCI_SUBDEVICE_ID_PCI_RAS4 0xf001 -#define PCI_SUBDEVICE_ID_PCI_RAS8 0xf010 - -#define PCI_VENDOR_ID_SYBA 0x1592 -#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782 -#define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783 - -#define PCI_VENDOR_ID_MORETON 0x15aa -#define PCI_DEVICE_ID_RASTEL_2PORT 0x2000 - -#define PCI_VENDOR_ID_ZOLTRIX 0x15b0 -#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0 - -#define PCI_VENDOR_ID_MELLANOX 0x15b3 -#define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 -#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE 0x5a46 -#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 -#define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 -#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c -#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274 - -#define PCI_VENDOR_ID_QUICKNET 0x15e2 -#define PCI_DEVICE_ID_QUICKNET_XJ 0x0500 - -/* - * ADDI-DATA GmbH communication cards - */ -#define PCI_VENDOR_ID_ADDIDATA_OLD 0x10E8 -#define PCI_VENDOR_ID_ADDIDATA 0x15B8 -#define PCI_DEVICE_ID_ADDIDATA_APCI7500 0x7000 -#define PCI_DEVICE_ID_ADDIDATA_APCI7420 0x7001 -#define PCI_DEVICE_ID_ADDIDATA_APCI7300 0x7002 -#define PCI_DEVICE_ID_ADDIDATA_APCI7800 0x818E -#define PCI_DEVICE_ID_ADDIDATA_APCI7500_2 0x7009 -#define PCI_DEVICE_ID_ADDIDATA_APCI7420_2 0x700A -#define PCI_DEVICE_ID_ADDIDATA_APCI7300_2 0x700B -#define PCI_DEVICE_ID_ADDIDATA_APCI7500_3 0x700C -#define PCI_DEVICE_ID_ADDIDATA_APCI7420_3 0x700D -#define PCI_DEVICE_ID_ADDIDATA_APCI7300_3 0x700E -#define PCI_DEVICE_ID_ADDIDATA_APCI7800_3 0x700F - -#define PCI_VENDOR_ID_PDC 0x15e9 - -#define PCI_VENDOR_ID_FARSITE 0x1619 -#define PCI_DEVICE_ID_FARSITE_T2P 0x0400 -#define PCI_DEVICE_ID_FARSITE_T4P 0x0440 -#define PCI_DEVICE_ID_FARSITE_T1U 0x0610 -#define PCI_DEVICE_ID_FARSITE_T2U 0x0620 -#define PCI_DEVICE_ID_FARSITE_T4U 0x0640 -#define PCI_DEVICE_ID_FARSITE_TE1 0x1610 -#define PCI_DEVICE_ID_FARSITE_TE1C 0x1612 - -#define PCI_VENDOR_ID_ARIMA 0x161f - -#define PCI_VENDOR_ID_BROCADE 0x1657 - -#define PCI_VENDOR_ID_SIBYTE 0x166d -#define PCI_DEVICE_ID_BCM1250_PCI 0x0001 -#define PCI_DEVICE_ID_BCM1250_HT 0x0002 - -#define PCI_VENDOR_ID_ATHEROS 0x168c - -#define PCI_VENDOR_ID_NETCELL 0x169c -#define PCI_DEVICE_ID_REVOLUTION 0x0044 - -#define PCI_VENDOR_ID_CENATEK 0x16CA -#define PCI_DEVICE_ID_CENATEK_IDE 0x0001 - -#define PCI_VENDOR_ID_VITESSE 0x1725 -#define PCI_DEVICE_ID_VITESSE_VSC7174 0x7174 - -#define PCI_VENDOR_ID_LINKSYS 0x1737 -#define PCI_DEVICE_ID_LINKSYS_EG1064 0x1064 - -#define PCI_VENDOR_ID_ALTIMA 0x173b -#define PCI_DEVICE_ID_ALTIMA_AC1000 0x03e8 -#define PCI_DEVICE_ID_ALTIMA_AC1001 0x03e9 -#define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea -#define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb - -#define PCI_VENDOR_ID_BELKIN 0x1799 -#define PCI_DEVICE_ID_BELKIN_F5D7010V7 0x701f - -#define PCI_VENDOR_ID_RDC 0x17f3 -#define PCI_DEVICE_ID_RDC_R6020 0x6020 -#define PCI_DEVICE_ID_RDC_R6030 0x6030 -#define PCI_DEVICE_ID_RDC_R6040 0x6040 -#define PCI_DEVICE_ID_RDC_R6060 0x6060 -#define PCI_DEVICE_ID_RDC_R6061 0x6061 - -#define PCI_VENDOR_ID_LENOVO 0x17aa - -#define PCI_VENDOR_ID_ARECA 0x17d3 -#define PCI_DEVICE_ID_ARECA_1110 0x1110 -#define PCI_DEVICE_ID_ARECA_1120 0x1120 -#define PCI_DEVICE_ID_ARECA_1130 0x1130 -#define PCI_DEVICE_ID_ARECA_1160 0x1160 -#define PCI_DEVICE_ID_ARECA_1170 0x1170 -#define PCI_DEVICE_ID_ARECA_1200 0x1200 -#define PCI_DEVICE_ID_ARECA_1201 0x1201 -#define PCI_DEVICE_ID_ARECA_1202 0x1202 -#define PCI_DEVICE_ID_ARECA_1210 0x1210 -#define PCI_DEVICE_ID_ARECA_1220 0x1220 -#define PCI_DEVICE_ID_ARECA_1230 0x1230 -#define PCI_DEVICE_ID_ARECA_1260 0x1260 -#define PCI_DEVICE_ID_ARECA_1270 0x1270 -#define PCI_DEVICE_ID_ARECA_1280 0x1280 -#define PCI_DEVICE_ID_ARECA_1380 0x1380 -#define PCI_DEVICE_ID_ARECA_1381 0x1381 -#define PCI_DEVICE_ID_ARECA_1680 0x1680 -#define PCI_DEVICE_ID_ARECA_1681 0x1681 - -#define PCI_VENDOR_ID_S2IO 0x17d5 -#define PCI_DEVICE_ID_S2IO_WIN 0x5731 -#define PCI_DEVICE_ID_S2IO_UNI 0x5831 -#define PCI_DEVICE_ID_HERC_WIN 0x5732 -#define PCI_DEVICE_ID_HERC_UNI 0x5832 - -#define PCI_VENDOR_ID_SITECOM 0x182d -#define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 - -#define PCI_VENDOR_ID_TOPSPIN 0x1867 - -#define PCI_VENDOR_ID_TDI 0x192E -#define PCI_DEVICE_ID_TDI_EHCI 0x0101 - -#define PCI_VENDOR_ID_FREESCALE 0x1957 -#define PCI_DEVICE_ID_MPC8548E 0x0012 -#define PCI_DEVICE_ID_MPC8548 0x0013 -#define PCI_DEVICE_ID_MPC8543E 0x0014 -#define PCI_DEVICE_ID_MPC8543 0x0015 -#define PCI_DEVICE_ID_MPC8547E 0x0018 -#define PCI_DEVICE_ID_MPC8545E 0x0019 -#define PCI_DEVICE_ID_MPC8545 0x001a -#define PCI_DEVICE_ID_MPC8568E 0x0020 -#define PCI_DEVICE_ID_MPC8568 0x0021 -#define PCI_DEVICE_ID_MPC8567E 0x0022 -#define PCI_DEVICE_ID_MPC8567 0x0023 -#define PCI_DEVICE_ID_MPC8533E 0x0030 -#define PCI_DEVICE_ID_MPC8533 0x0031 -#define PCI_DEVICE_ID_MPC8544E 0x0032 -#define PCI_DEVICE_ID_MPC8544 0x0033 -#define PCI_DEVICE_ID_MPC8572E 0x0040 -#define PCI_DEVICE_ID_MPC8572 0x0041 -#define PCI_DEVICE_ID_MPC8536E 0x0050 -#define PCI_DEVICE_ID_MPC8536 0x0051 -#define PCI_DEVICE_ID_MPC8641 0x7010 -#define PCI_DEVICE_ID_MPC8641D 0x7011 -#define PCI_DEVICE_ID_MPC8610 0x7018 - -#define PCI_VENDOR_ID_PASEMI 0x1959 - -#define PCI_VENDOR_ID_ATTANSIC 0x1969 -#define PCI_DEVICE_ID_ATTANSIC_L1 0x1048 -#define PCI_DEVICE_ID_ATTANSIC_L2 0x2048 - -#define PCI_VENDOR_ID_JMICRON 0x197B -#define PCI_DEVICE_ID_JMICRON_JMB360 0x2360 -#define PCI_DEVICE_ID_JMICRON_JMB361 0x2361 -#define PCI_DEVICE_ID_JMICRON_JMB363 0x2363 -#define PCI_DEVICE_ID_JMICRON_JMB365 0x2365 -#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366 -#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368 -#define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381 -#define PCI_DEVICE_ID_JMICRON_JMB38X_MMC 0x2382 -#define PCI_DEVICE_ID_JMICRON_JMB38X_MS 0x2383 - -#define PCI_VENDOR_ID_KORENIX 0x1982 -#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 -#define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff - -#define PCI_VENDOR_ID_TEKRAM 0x1de1 -#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 - -#define PCI_VENDOR_ID_TEHUTI 0x1fc9 -#define PCI_DEVICE_ID_TEHUTI_3009 0x3009 -#define PCI_DEVICE_ID_TEHUTI_3010 0x3010 -#define PCI_DEVICE_ID_TEHUTI_3014 0x3014 - -#define PCI_VENDOR_ID_HINT 0x3388 -#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013 - -#define PCI_VENDOR_ID_3DLABS 0x3d3d -#define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007 -#define PCI_DEVICE_ID_3DLABS_PERMEDIA2V 0x0009 - -#define PCI_VENDOR_ID_NETXEN 0x4040 -#define PCI_DEVICE_ID_NX2031_10GXSR 0x0001 -#define PCI_DEVICE_ID_NX2031_10GCX4 0x0002 -#define PCI_DEVICE_ID_NX2031_4GCU 0x0003 -#define PCI_DEVICE_ID_NX2031_IMEZ 0x0004 -#define PCI_DEVICE_ID_NX2031_HMEZ 0x0005 -#define PCI_DEVICE_ID_NX2031_XG_MGMT 0x0024 -#define PCI_DEVICE_ID_NX2031_XG_MGMT2 0x0025 -#define PCI_DEVICE_ID_NX3031 0x0100 - -#define PCI_VENDOR_ID_AKS 0x416c -#define PCI_DEVICE_ID_AKS_ALADDINCARD 0x0100 - -#define PCI_VENDOR_ID_S3 0x5333 -#define PCI_DEVICE_ID_S3_TRIO 0x8811 -#define PCI_DEVICE_ID_S3_868 0x8880 -#define PCI_DEVICE_ID_S3_968 0x88f0 -#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25 -#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04 -#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00 - -#define PCI_VENDOR_ID_DUNORD 0x5544 -#define PCI_DEVICE_ID_DUNORD_I3000 0x0001 - -#define PCI_VENDOR_ID_DCI 0x6666 -#define PCI_DEVICE_ID_DCI_PCCOM4 0x0001 -#define PCI_DEVICE_ID_DCI_PCCOM8 0x0002 -#define PCI_DEVICE_ID_DCI_PCCOM2 0x0004 - -#define PCI_VENDOR_ID_INTEL 0x8086 -#define PCI_DEVICE_ID_INTEL_EESSC 0x0008 -#define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 -#define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321 -#define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 -#define PCI_DEVICE_ID_INTEL_PXH_1 0x032A -#define PCI_DEVICE_ID_INTEL_PXHV 0x032C -#define PCI_DEVICE_ID_INTEL_82375 0x0482 -#define PCI_DEVICE_ID_INTEL_82424 0x0483 -#define PCI_DEVICE_ID_INTEL_82378 0x0484 -#define PCI_DEVICE_ID_INTEL_I960 0x0960 -#define PCI_DEVICE_ID_INTEL_I960RM 0x0962 -#define PCI_DEVICE_ID_INTEL_82815_MC 0x1130 -#define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132 -#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 -#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 -#define PCI_DEVICE_ID_INTEL_7205_0 0x255d -#define PCI_DEVICE_ID_INTEL_82437 0x122d -#define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e -#define PCI_DEVICE_ID_INTEL_82371FB_1 0x1230 -#define PCI_DEVICE_ID_INTEL_82371MX 0x1234 -#define PCI_DEVICE_ID_INTEL_82441 0x1237 -#define PCI_DEVICE_ID_INTEL_82380FB 0x124b -#define PCI_DEVICE_ID_INTEL_82439 0x1250 -#define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 -#define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 -#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 -#define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 -#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 -#define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 -#define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 -#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415 -#define PCI_DEVICE_ID_INTEL_82801AA_6 0x2416 -#define PCI_DEVICE_ID_INTEL_82801AA_8 0x2418 -#define PCI_DEVICE_ID_INTEL_82801AB_0 0x2420 -#define PCI_DEVICE_ID_INTEL_82801AB_1 0x2421 -#define PCI_DEVICE_ID_INTEL_82801AB_3 0x2423 -#define PCI_DEVICE_ID_INTEL_82801AB_5 0x2425 -#define PCI_DEVICE_ID_INTEL_82801AB_6 0x2426 -#define PCI_DEVICE_ID_INTEL_82801AB_8 0x2428 -#define PCI_DEVICE_ID_INTEL_82801BA_0 0x2440 -#define PCI_DEVICE_ID_INTEL_82801BA_2 0x2443 -#define PCI_DEVICE_ID_INTEL_82801BA_4 0x2445 -#define PCI_DEVICE_ID_INTEL_82801BA_6 0x2448 -#define PCI_DEVICE_ID_INTEL_82801BA_8 0x244a -#define PCI_DEVICE_ID_INTEL_82801BA_9 0x244b -#define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c -#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e -#define PCI_DEVICE_ID_INTEL_82801E_0 0x2450 -#define PCI_DEVICE_ID_INTEL_82801E_11 0x245b -#define PCI_DEVICE_ID_INTEL_82801CA_0 0x2480 -#define PCI_DEVICE_ID_INTEL_82801CA_3 0x2483 -#define PCI_DEVICE_ID_INTEL_82801CA_5 0x2485 -#define PCI_DEVICE_ID_INTEL_82801CA_6 0x2486 -#define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a -#define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b -#define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c -#define PCI_DEVICE_ID_INTEL_82801DB_0 0x24c0 -#define PCI_DEVICE_ID_INTEL_82801DB_1 0x24c1 -#define PCI_DEVICE_ID_INTEL_82801DB_3 0x24c3 -#define PCI_DEVICE_ID_INTEL_82801DB_5 0x24c5 -#define PCI_DEVICE_ID_INTEL_82801DB_6 0x24c6 -#define PCI_DEVICE_ID_INTEL_82801DB_9 0x24c9 -#define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca -#define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb -#define PCI_DEVICE_ID_INTEL_82801DB_12 0x24cc -#define PCI_DEVICE_ID_INTEL_82801EB_0 0x24d0 -#define PCI_DEVICE_ID_INTEL_82801EB_1 0x24d1 -#define PCI_DEVICE_ID_INTEL_82801EB_3 0x24d3 -#define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 -#define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 -#define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db -#define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc -#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd -#define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 -#define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 -#define PCI_DEVICE_ID_INTEL_ESB_4 0x25a4 -#define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6 -#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab -#define PCI_DEVICE_ID_INTEL_82820_HB 0x2500 -#define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 -#define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 -#define PCI_DEVICE_ID_INTEL_82860_HB 0x2531 -#define PCI_DEVICE_ID_INTEL_E7501_MCH 0x254c -#define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560 -#define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 -#define PCI_DEVICE_ID_INTEL_82865_HB 0x2570 -#define PCI_DEVICE_ID_INTEL_82865_IG 0x2572 -#define PCI_DEVICE_ID_INTEL_82875_HB 0x2578 -#define PCI_DEVICE_ID_INTEL_82915G_HB 0x2580 -#define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582 -#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590 -#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 -#define PCI_DEVICE_ID_INTEL_5000_ERR 0x25F0 -#define PCI_DEVICE_ID_INTEL_5000_FBD0 0x25F5 -#define PCI_DEVICE_ID_INTEL_5000_FBD1 0x25F6 -#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 -#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 -#define PCI_DEVICE_ID_INTEL_3000_HB 0x2778 -#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0 -#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2 -#define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640 -#define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641 -#define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642 -#define PCI_DEVICE_ID_INTEL_ICH6_16 0x266a -#define PCI_DEVICE_ID_INTEL_ICH6_17 0x266d -#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e -#define PCI_DEVICE_ID_INTEL_ICH6_19 0x266f -#define PCI_DEVICE_ID_INTEL_ESB2_0 0x2670 -#define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698 -#define PCI_DEVICE_ID_INTEL_ESB2_17 0x269b -#define PCI_DEVICE_ID_INTEL_ESB2_18 0x269e -#define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8 -#define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9 -#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 -#define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd -#define PCI_DEVICE_ID_INTEL_ICH7_17 0x27da -#define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd -#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de -#define PCI_DEVICE_ID_INTEL_ICH7_21 0x27df -#define PCI_DEVICE_ID_INTEL_ICH8_0 0x2810 -#define PCI_DEVICE_ID_INTEL_ICH8_1 0x2811 -#define PCI_DEVICE_ID_INTEL_ICH8_2 0x2812 -#define PCI_DEVICE_ID_INTEL_ICH8_3 0x2814 -#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 -#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e -#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 -#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910 -#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917 -#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912 -#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913 -#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914 -#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919 -#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 -#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916 -#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918 -#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 -#define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 -#define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a -#define PCI_DEVICE_ID_INTEL_IOAT_TBG6 0x342b -#define PCI_DEVICE_ID_INTEL_IOAT_TBG7 0x342c -#define PCI_DEVICE_ID_INTEL_IOAT_TBG0 0x3430 -#define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431 -#define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432 -#define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433 -#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 -#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 -#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 -#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 -#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590 -#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592 -#define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595 -#define PCI_DEVICE_ID_INTEL_MCH_PA1 0x3596 -#define PCI_DEVICE_ID_INTEL_MCH_PB 0x3597 -#define PCI_DEVICE_ID_INTEL_MCH_PB1 0x3598 -#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599 -#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a -#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e -#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b -#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c -#define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14 -#define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16 -#define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18 -#define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a -#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 -#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 -#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN 0x3b00 -#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX 0x3b1f -#define PCI_DEVICE_ID_INTEL_PCH_SMBUS 0x3b30 -#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f -#define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 -#define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 -#define PCI_DEVICE_ID_INTEL_5100_22 0x65f6 -#define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 -#define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 -#define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 -#define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff -#define PCI_DEVICE_ID_INTEL_TOLAPAI_0 0x5031 -#define PCI_DEVICE_ID_INTEL_TOLAPAI_1 0x5032 -#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 -#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010 -#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020 -#define PCI_DEVICE_ID_INTEL_82437VX 0x7030 -#define PCI_DEVICE_ID_INTEL_82439TX 0x7100 -#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110 -#define PCI_DEVICE_ID_INTEL_82371AB 0x7111 -#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112 -#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113 -#define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120 -#define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121 -#define PCI_DEVICE_ID_INTEL_82810_MC3 0x7122 -#define PCI_DEVICE_ID_INTEL_82810_IG3 0x7123 -#define PCI_DEVICE_ID_INTEL_82810E_MC 0x7124 -#define PCI_DEVICE_ID_INTEL_82810E_IG 0x7125 -#define PCI_DEVICE_ID_INTEL_82443LX_0 0x7180 -#define PCI_DEVICE_ID_INTEL_82443LX_1 0x7181 -#define PCI_DEVICE_ID_INTEL_82443BX_0 0x7190 -#define PCI_DEVICE_ID_INTEL_82443BX_1 0x7191 -#define PCI_DEVICE_ID_INTEL_82443BX_2 0x7192 -#define PCI_DEVICE_ID_INTEL_440MX 0x7195 -#define PCI_DEVICE_ID_INTEL_440MX_6 0x7196 -#define PCI_DEVICE_ID_INTEL_82443MX_0 0x7198 -#define PCI_DEVICE_ID_INTEL_82443MX_1 0x7199 -#define PCI_DEVICE_ID_INTEL_82443MX_3 0x719b -#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0 -#define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2 -#define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 -#define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119 -#define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a -#define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 -#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5 -#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca -#define PCI_DEVICE_ID_INTEL_82454NX 0x84cb -#define PCI_DEVICE_ID_INTEL_84460GX 0x84ea -#define PCI_DEVICE_ID_INTEL_IXP4XX 0x8500 -#define PCI_DEVICE_ID_INTEL_IXP2800 0x9004 -#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 - -#define PCI_VENDOR_ID_SCALEMP 0x8686 -#define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010 - -#define PCI_VENDOR_ID_COMPUTONE 0x8e0e -#define PCI_DEVICE_ID_COMPUTONE_IP2EX 0x0291 -#define PCI_DEVICE_ID_COMPUTONE_PG 0x0302 -#define PCI_SUBVENDOR_ID_COMPUTONE 0x8e0e -#define PCI_SUBDEVICE_ID_COMPUTONE_PG4 0x0001 -#define PCI_SUBDEVICE_ID_COMPUTONE_PG8 0x0002 -#define PCI_SUBDEVICE_ID_COMPUTONE_PG6 0x0003 - -#define PCI_VENDOR_ID_KTI 0x8e2e - -#define PCI_VENDOR_ID_ADAPTEC 0x9004 -#define PCI_DEVICE_ID_ADAPTEC_7810 0x1078 -#define PCI_DEVICE_ID_ADAPTEC_7821 0x2178 -#define PCI_DEVICE_ID_ADAPTEC_38602 0x3860 -#define PCI_DEVICE_ID_ADAPTEC_7850 0x5078 -#define PCI_DEVICE_ID_ADAPTEC_7855 0x5578 -#define PCI_DEVICE_ID_ADAPTEC_3860 0x6038 -#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075 -#define PCI_DEVICE_ID_ADAPTEC_7860 0x6078 -#define PCI_DEVICE_ID_ADAPTEC_7861 0x6178 -#define PCI_DEVICE_ID_ADAPTEC_7870 0x7078 -#define PCI_DEVICE_ID_ADAPTEC_7871 0x7178 -#define PCI_DEVICE_ID_ADAPTEC_7872 0x7278 -#define PCI_DEVICE_ID_ADAPTEC_7873 0x7378 -#define PCI_DEVICE_ID_ADAPTEC_7874 0x7478 -#define PCI_DEVICE_ID_ADAPTEC_7895 0x7895 -#define PCI_DEVICE_ID_ADAPTEC_7880 0x8078 -#define PCI_DEVICE_ID_ADAPTEC_7881 0x8178 -#define PCI_DEVICE_ID_ADAPTEC_7882 0x8278 -#define PCI_DEVICE_ID_ADAPTEC_7883 0x8378 -#define PCI_DEVICE_ID_ADAPTEC_7884 0x8478 -#define PCI_DEVICE_ID_ADAPTEC_7885 0x8578 -#define PCI_DEVICE_ID_ADAPTEC_7886 0x8678 -#define PCI_DEVICE_ID_ADAPTEC_7887 0x8778 -#define PCI_DEVICE_ID_ADAPTEC_7888 0x8878 - -#define PCI_VENDOR_ID_ADAPTEC2 0x9005 -#define PCI_DEVICE_ID_ADAPTEC2_2940U2 0x0010 -#define PCI_DEVICE_ID_ADAPTEC2_2930U2 0x0011 -#define PCI_DEVICE_ID_ADAPTEC2_7890B 0x0013 -#define PCI_DEVICE_ID_ADAPTEC2_7890 0x001f -#define PCI_DEVICE_ID_ADAPTEC2_3940U2 0x0050 -#define PCI_DEVICE_ID_ADAPTEC2_3950U2D 0x0051 -#define PCI_DEVICE_ID_ADAPTEC2_7896 0x005f -#define PCI_DEVICE_ID_ADAPTEC2_7892A 0x0080 -#define PCI_DEVICE_ID_ADAPTEC2_7892B 0x0081 -#define PCI_DEVICE_ID_ADAPTEC2_7892D 0x0083 -#define PCI_DEVICE_ID_ADAPTEC2_7892P 0x008f -#define PCI_DEVICE_ID_ADAPTEC2_7899A 0x00c0 -#define PCI_DEVICE_ID_ADAPTEC2_7899B 0x00c1 -#define PCI_DEVICE_ID_ADAPTEC2_7899D 0x00c3 -#define PCI_DEVICE_ID_ADAPTEC2_7899P 0x00cf -#define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN 0x0500 -#define PCI_DEVICE_ID_ADAPTEC2_SCAMP 0x0503 - -#define PCI_VENDOR_ID_HOLTEK 0x9412 -#define PCI_DEVICE_ID_HOLTEK_6565 0x6565 - -#define PCI_VENDOR_ID_NETMOS 0x9710 -#define PCI_DEVICE_ID_NETMOS_9705 0x9705 -#define PCI_DEVICE_ID_NETMOS_9715 0x9715 -#define PCI_DEVICE_ID_NETMOS_9735 0x9735 -#define PCI_DEVICE_ID_NETMOS_9745 0x9745 -#define PCI_DEVICE_ID_NETMOS_9755 0x9755 -#define PCI_DEVICE_ID_NETMOS_9805 0x9805 -#define PCI_DEVICE_ID_NETMOS_9815 0x9815 -#define PCI_DEVICE_ID_NETMOS_9835 0x9835 -#define PCI_DEVICE_ID_NETMOS_9845 0x9845 -#define PCI_DEVICE_ID_NETMOS_9855 0x9855 - -#define PCI_VENDOR_ID_3COM_2 0xa727 - -#define PCI_VENDOR_ID_DIGIUM 0xd161 -#define PCI_DEVICE_ID_DIGIUM_HFC4S 0xb410 - -#define PCI_SUBVENDOR_ID_EXSYS 0xd84d -#define PCI_SUBDEVICE_ID_EXSYS_4014 0x4014 -#define PCI_SUBDEVICE_ID_EXSYS_4055 0x4055 - -#define PCI_VENDOR_ID_TIGERJET 0xe159 -#define PCI_DEVICE_ID_TIGERJET_300 0x0001 -#define PCI_DEVICE_ID_TIGERJET_100 0x0002 - -#define PCI_VENDOR_ID_XILINX_RME 0xea60 -#define PCI_DEVICE_ID_RME_DIGI32 0x9896 -#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897 -#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898 - -#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 -#define PCI_DEVICE_ID_VIRTIO_BLK 0x1001 -#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004 diff -Nru seabios-1.7.1/src/pciinit.c seabios-1.7.4/src/pciinit.c --- seabios-1.7.1/src/pciinit.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pciinit.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,675 +0,0 @@ -// Initialize PCI devices (on emulators) -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // pci_config_readl -#include "pci_ids.h" // PCI_VENDOR_ID_INTEL -#include "pci_regs.h" // PCI_COMMAND -#include "ioport.h" // PORT_ATA1_CMD_BASE -#include "config.h" // CONFIG_* -#include "xen.h" // usingXen - -#define PCI_DEVICE_MEM_MIN 0x1000 -#define PCI_BRIDGE_IO_MIN 0x1000 -#define PCI_BRIDGE_MEM_MIN 0x100000 - -enum pci_region_type { - PCI_REGION_TYPE_IO, - PCI_REGION_TYPE_MEM, - PCI_REGION_TYPE_PREFMEM, - PCI_REGION_TYPE_COUNT, -}; - -static const char *region_type_name[] = { - [ PCI_REGION_TYPE_IO ] = "io", - [ PCI_REGION_TYPE_MEM ] = "mem", - [ PCI_REGION_TYPE_PREFMEM ] = "prefmem", -}; - -u64 pcimem_start = BUILD_PCIMEM_START; -u64 pcimem_end = BUILD_PCIMEM_END; -u64 pcimem64_start = BUILD_PCIMEM64_START; -u64 pcimem64_end = BUILD_PCIMEM64_END; - -struct pci_region_entry { - struct pci_device *dev; - int bar; - u64 size; - u64 align; - int is64; - enum pci_region_type type; - struct pci_region_entry *next; -}; - -struct pci_region { - /* pci region assignments */ - u64 base; - struct pci_region_entry *list; -}; - -struct pci_bus { - struct pci_region r[PCI_REGION_TYPE_COUNT]; - struct pci_device *bus_dev; -}; - -static u32 pci_bar(struct pci_device *pci, int region_num) -{ - if (region_num != PCI_ROM_SLOT) { - return PCI_BASE_ADDRESS_0 + region_num * 4; - } - -#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80 - u8 type = pci->header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION; - return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS; -} - -static void -pci_set_io_region_addr(struct pci_device *pci, int bar, u64 addr, int is64) -{ - u32 ofs = pci_bar(pci, bar); - pci_config_writel(pci->bdf, ofs, addr); - if (is64) - pci_config_writel(pci->bdf, ofs + 4, addr >> 32); -} - - -/**************************************************************** - * Misc. device init - ****************************************************************/ - -/* host irqs corresponding to PCI irqs A-D */ -const u8 pci_irqs[4] = { - 10, 10, 11, 11 -}; - -// Return the global irq number corresponding to a host bus device irq pin. -static int pci_slot_get_irq(struct pci_device *pci, int pin) -{ - int slot_addend = 0; - - while (pci->parent != NULL) { - slot_addend += pci_bdf_to_dev(pci->bdf); - pci = pci->parent; - } - slot_addend += pci_bdf_to_dev(pci->bdf) - 1; - return pci_irqs[(pin - 1 + slot_addend) & 3]; -} - -/* PIIX3/PIIX4 PCI to ISA bridge */ -static void piix_isa_bridge_init(struct pci_device *pci, void *arg) -{ - int i, irq; - u8 elcr[2]; - - elcr[0] = 0x00; - elcr[1] = 0x00; - for (i = 0; i < 4; i++) { - irq = pci_irqs[i]; - /* set to trigger level */ - elcr[irq >> 3] |= (1 << (irq & 7)); - /* activate irq remapping in PIIX */ - pci_config_writeb(pci->bdf, 0x60 + i, irq); - } - outb(elcr[0], 0x4d0); - outb(elcr[1], 0x4d1); - dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]); -} - -static const struct pci_device_id pci_isa_bridge_tbl[] = { - /* PIIX3/PIIX4 PCI to ISA bridge */ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, - piix_isa_bridge_init), - PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, - piix_isa_bridge_init), - - PCI_DEVICE_END -}; - -static void storage_ide_init(struct pci_device *pci, void *arg) -{ - /* IDE: we map it as in ISA mode */ - pci_set_io_region_addr(pci, 0, PORT_ATA1_CMD_BASE, 0); - pci_set_io_region_addr(pci, 1, PORT_ATA1_CTRL_BASE, 0); - pci_set_io_region_addr(pci, 2, PORT_ATA2_CMD_BASE, 0); - pci_set_io_region_addr(pci, 3, PORT_ATA2_CTRL_BASE, 0); -} - -/* PIIX3/PIIX4 IDE */ -static void piix_ide_init(struct pci_device *pci, void *arg) -{ - u16 bdf = pci->bdf; - pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0 - pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1 -} - -static void pic_ibm_init(struct pci_device *pci, void *arg) -{ - /* PIC, IBM, MPIC & MPIC2 */ - pci_set_io_region_addr(pci, 0, 0x80800000 + 0x00040000, 0); -} - -static void apple_macio_init(struct pci_device *pci, void *arg) -{ - /* macio bridge */ - pci_set_io_region_addr(pci, 0, 0x80800000, 0); -} - -static const struct pci_device_id pci_class_tbl[] = { - /* STORAGE IDE */ - PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, - PCI_CLASS_STORAGE_IDE, piix_ide_init), - PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, - PCI_CLASS_STORAGE_IDE, piix_ide_init), - PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, - storage_ide_init), - - /* PIC, IBM, MIPC & MPIC2 */ - PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC, - pic_ibm_init), - PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC, - pic_ibm_init), - - /* 0xff00 */ - PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_init), - PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_init), - - PCI_DEVICE_END, -}; - -/* PIIX4 Power Management device (for ACPI) */ -static void piix4_pm_init(struct pci_device *pci, void *arg) -{ - u16 bdf = pci->bdf; - // acpi sci is hardwired to 9 - pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9); - - pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1); - pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */ - pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1); - pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */ -} - -static const struct pci_device_id pci_device_tbl[] = { - /* PIIX4 Power Management device (for ACPI) */ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, - piix4_pm_init), - - PCI_DEVICE_END, -}; - -static void pci_bios_init_device(struct pci_device *pci) -{ - u16 bdf = pci->bdf; - dprintf(1, "PCI: init bdf=%02x:%02x.%x id=%04x:%04x\n" - , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf) - , pci->vendor, pci->device); - - pci_init_device(pci_class_tbl, pci, NULL); - - /* enable memory mappings */ - pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - - /* map the interrupt */ - int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); - if (pin != 0) - pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin)); - - pci_init_device(pci_device_tbl, pci, NULL); -} - -static void pci_bios_init_devices(void) -{ - struct pci_device *pci; - foreachpci(pci) { - pci_bios_init_device(pci); - } - - foreachpci(pci) { - pci_init_device(pci_isa_bridge_tbl, pci, NULL); - } -} - - -/**************************************************************** - * Bus initialization - ****************************************************************/ - -static void -pci_bios_init_bus_rec(int bus, u8 *pci_bus) -{ - int bdf; - u16 class; - - dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus); - - /* prevent accidental access to unintended devices */ - foreachbdf(bdf, bus) { - class = pci_config_readw(bdf, PCI_CLASS_DEVICE); - if (class == PCI_CLASS_BRIDGE_PCI) { - pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255); - pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0); - } - } - - foreachbdf(bdf, bus) { - class = pci_config_readw(bdf, PCI_CLASS_DEVICE); - if (class != PCI_CLASS_BRIDGE_PCI) { - continue; - } - dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf); - - u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS); - if (pribus != bus) { - dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus); - pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus); - } else { - dprintf(1, "PCI: primary bus = 0x%x\n", pribus); - } - - u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); - (*pci_bus)++; - if (*pci_bus != secbus) { - dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n", - secbus, *pci_bus); - secbus = *pci_bus; - pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus); - } else { - dprintf(1, "PCI: secondary bus = 0x%x\n", secbus); - } - - /* set to max for access to all subordinate buses. - later set it to accurate value */ - u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS); - pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255); - - pci_bios_init_bus_rec(secbus, pci_bus); - - if (subbus != *pci_bus) { - dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n", - subbus, *pci_bus); - subbus = *pci_bus; - } else { - dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus); - } - pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus); - } -} - -static void -pci_bios_init_bus(void) -{ - u8 pci_bus = 0; - pci_bios_init_bus_rec(0 /* host bus */, &pci_bus); -} - - -/**************************************************************** - * Bus sizing - ****************************************************************/ - -static void -pci_bios_get_bar(struct pci_device *pci, int bar, - int *ptype, u64 *psize, int *pis64) -{ - u32 ofs = pci_bar(pci, bar); - u16 bdf = pci->bdf; - u32 old = pci_config_readl(bdf, ofs); - int is64 = 0, type = PCI_REGION_TYPE_MEM; - u64 mask; - - if (bar == PCI_ROM_SLOT) { - mask = PCI_ROM_ADDRESS_MASK; - pci_config_writel(bdf, ofs, mask); - } else { - if (old & PCI_BASE_ADDRESS_SPACE_IO) { - mask = PCI_BASE_ADDRESS_IO_MASK; - type = PCI_REGION_TYPE_IO; - } else { - mask = PCI_BASE_ADDRESS_MEM_MASK; - if (old & PCI_BASE_ADDRESS_MEM_PREFETCH) - type = PCI_REGION_TYPE_PREFMEM; - is64 = ((old & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64); - } - pci_config_writel(bdf, ofs, ~0); - } - u64 val = pci_config_readl(bdf, ofs); - pci_config_writel(bdf, ofs, old); - if (is64) { - u32 hold = pci_config_readl(bdf, ofs + 4); - pci_config_writel(bdf, ofs + 4, ~0); - u32 high = pci_config_readl(bdf, ofs + 4); - pci_config_writel(bdf, ofs + 4, hold); - val |= ((u64)high << 32); - mask |= ((u64)0xffffffff << 32); - *psize = (~(val & mask)) + 1; - } else { - *psize = ((~(val & mask)) + 1) & 0xffffffff; - } - *ptype = type; - *pis64 = is64; -} - -static int pci_bios_bridge_region_is64(struct pci_region *r, - struct pci_device *pci, int type) -{ - if (type != PCI_REGION_TYPE_PREFMEM) - return 0; - u32 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE); - if (!pmem) { - pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0); - pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE); - pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0); - } - if ((pmem & PCI_PREF_RANGE_TYPE_MASK) != PCI_PREF_RANGE_TYPE_64) - return 0; - struct pci_region_entry *entry = r->list; - while (entry) { - if (!entry->is64) - return 0; - entry = entry->next; - } - return 1; -} - -static u64 pci_region_align(struct pci_region *r) -{ - if (!r->list) - return 1; - // The first entry in the sorted list has the largest alignment - return r->list->align; -} - -static u64 pci_region_sum(struct pci_region *r) -{ - struct pci_region_entry *entry = r->list; - u64 sum = 0; - while (entry) { - sum += entry->size; - entry = entry->next; - } - return sum; -} - -static void pci_region_migrate_64bit_entries(struct pci_region *from, - struct pci_region *to) -{ - struct pci_region_entry **pprev = &from->list, **last = &to->list; - while (*pprev) { - struct pci_region_entry *entry = *pprev; - if (!entry->is64) { - pprev = &entry->next; - continue; - } - // Move from source list to destination list. - *pprev = entry->next; - entry->next = NULL; - *last = entry; - last = &entry->next; - } -} - -static struct pci_region_entry * -pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev, - int bar, u64 size, u64 align, int type, int is64) -{ - struct pci_region_entry *entry = malloc_tmp(sizeof(*entry)); - if (!entry) { - warn_noalloc(); - return NULL; - } - memset(entry, 0, sizeof(*entry)); - entry->dev = dev; - entry->bar = bar; - entry->size = size; - entry->align = align; - entry->is64 = is64; - entry->type = type; - // Insert into list in sorted order. - struct pci_region_entry **pprev; - for (pprev = &bus->r[type].list; *pprev; pprev = &(*pprev)->next) { - struct pci_region_entry *pos = *pprev; - if (pos->align < align || (pos->align == align && pos->size < size)) - break; - } - entry->next = *pprev; - *pprev = entry; - return entry; -} - -static int pci_bios_check_devices(struct pci_bus *busses) -{ - dprintf(1, "PCI: check devices\n"); - - // Calculate resources needed for regular (non-bus) devices. - struct pci_device *pci; - foreachpci(pci) { - if (pci->class == PCI_CLASS_BRIDGE_PCI) - busses[pci->secondary_bus].bus_dev = pci; - - struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)]; - int i; - for (i = 0; i < PCI_NUM_REGIONS; i++) { - if ((pci->class == PCI_CLASS_BRIDGE_PCI) && - (i >= PCI_BRIDGE_NUM_REGIONS && i < PCI_ROM_SLOT)) - continue; - int type, is64; - u64 size; - pci_bios_get_bar(pci, i, &type, &size, &is64); - if (size == 0) - continue; - - if (type != PCI_REGION_TYPE_IO && size < PCI_DEVICE_MEM_MIN) - size = PCI_DEVICE_MEM_MIN; - struct pci_region_entry *entry = pci_region_create_entry( - bus, pci, i, size, size, type, is64); - if (!entry) - return -1; - - if (is64) - i++; - } - } - - // Propagate required bus resources to parent busses. - int secondary_bus; - for (secondary_bus=MaxPCIBus; secondary_bus>0; secondary_bus--) { - struct pci_bus *s = &busses[secondary_bus]; - if (!s->bus_dev) - continue; - struct pci_bus *parent = &busses[pci_bdf_to_bus(s->bus_dev->bdf)]; - int type; - for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) { - u64 align = (type == PCI_REGION_TYPE_IO) ? - PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN; - if (pci_region_align(&s->r[type]) > align) - align = pci_region_align(&s->r[type]); - u64 sum = pci_region_sum(&s->r[type]); - u64 size = ALIGN(sum, align); - int is64 = pci_bios_bridge_region_is64(&s->r[type], - s->bus_dev, type); - // entry->bar is -1 if the entry represents a bridge region - struct pci_region_entry *entry = pci_region_create_entry( - parent, s->bus_dev, -1, size, align, type, is64); - if (!entry) - return -1; - dprintf(1, "PCI: secondary bus %d size %08llx type %s\n", - entry->dev->secondary_bus, size, - region_type_name[entry->type]); - } - } - return 0; -} - - -/**************************************************************** - * BAR assignment - ****************************************************************/ - -// Setup region bases (given the regions' size and alignment) -static int pci_bios_init_root_regions(struct pci_bus *bus) -{ - bus->r[PCI_REGION_TYPE_IO].base = 0xc000; - - struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM]; - struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM]; - - if (pci_region_align(r_start) < pci_region_align(r_end)) { - // Swap regions to improve alignment. - r_end = r_start; - r_start = &bus->r[PCI_REGION_TYPE_PREFMEM]; - } - u64 sum = pci_region_sum(r_end); - u64 align = pci_region_align(r_end); - r_end->base = ALIGN_DOWN((pcimem_end - sum), align); - sum = pci_region_sum(r_start); - align = pci_region_align(r_start); - r_start->base = ALIGN_DOWN((r_end->base - sum), align); - - if ((r_start->base < pcimem_start) || - (r_start->base > pcimem_end)) - // Memory range requested is larger than available. - return -1; - return 0; -} - -#define PCI_IO_SHIFT 8 -#define PCI_MEMORY_SHIFT 16 -#define PCI_PREF_MEMORY_SHIFT 16 - -static void -pci_region_map_one_entry(struct pci_region_entry *entry, u64 addr) -{ - u16 bdf = entry->dev->bdf; - if (entry->bar >= 0) { - dprintf(1, "PCI: map device bdf=%02x:%02x.%x" - " bar %d, addr %08llx, size %08llx [%s]\n", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), - entry->bar, addr, entry->size, region_type_name[entry->type]); - - pci_set_io_region_addr(entry->dev, entry->bar, addr, entry->is64); - return; - } - - u64 limit = addr + entry->size - 1; - if (entry->type == PCI_REGION_TYPE_IO) { - pci_config_writeb(bdf, PCI_IO_BASE, addr >> PCI_IO_SHIFT); - pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0); - pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT); - pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0); - } - if (entry->type == PCI_REGION_TYPE_MEM) { - pci_config_writew(bdf, PCI_MEMORY_BASE, addr >> PCI_MEMORY_SHIFT); - pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT); - } - if (entry->type == PCI_REGION_TYPE_PREFMEM) { - pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, addr >> PCI_PREF_MEMORY_SHIFT); - pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT); - pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, addr >> 32); - pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, limit >> 32); - } -} - -static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r) -{ - struct pci_region_entry *entry = r->list; - while (entry) { - u64 addr = r->base; - r->base += entry->size; - if (entry->bar == -1) - // Update bus base address if entry is a bridge region - busses[entry->dev->secondary_bus].r[entry->type].base = addr; - pci_region_map_one_entry(entry, addr); - struct pci_region_entry *next = entry->next; - free(entry); - entry = next; - } -} - -static void pci_bios_map_devices(struct pci_bus *busses) -{ - pcimem_start = RamSize; - - if (pci_bios_init_root_regions(busses)) { - struct pci_region r64_mem, r64_pref; - r64_mem.list = NULL; - r64_pref.list = NULL; - pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM], - &r64_mem); - pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM], - &r64_pref); - - if (pci_bios_init_root_regions(busses)) - panic("PCI: out of 32bit address space\n"); - - u64 sum_mem = pci_region_sum(&r64_mem); - u64 sum_pref = pci_region_sum(&r64_pref); - u64 align_mem = pci_region_align(&r64_mem); - u64 align_pref = pci_region_align(&r64_pref); - - r64_mem.base = ALIGN(0x100000000LL + RamSizeOver4G, align_mem); - r64_pref.base = ALIGN(r64_mem.base + sum_mem, align_pref); - pcimem64_start = r64_mem.base; - pcimem64_end = r64_pref.base + sum_pref; - - pci_region_map_entries(busses, &r64_mem); - pci_region_map_entries(busses, &r64_pref); - } else { - // no bars mapped high -> drop 64bit window (see dsdt) - pcimem64_start = 0; - } - // Map regions on each device. - int bus; - for (bus = 0; bus<=MaxPCIBus; bus++) { - int type; - for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) - pci_region_map_entries(busses, &busses[bus].r[type]); - } -} - - -/**************************************************************** - * Main setup code - ****************************************************************/ - -void -pci_setup(void) -{ - if (CONFIG_COREBOOT || usingXen()) { - // PCI setup already done by coreboot or Xen - just do probe. - pci_probe_devices(); - return; - } - - dprintf(3, "pci setup\n"); - - dprintf(1, "=== PCI bus & bridge init ===\n"); - if (pci_probe_host() != 0) { - return; - } - pci_bios_init_bus(); - - dprintf(1, "=== PCI device probing ===\n"); - pci_probe_devices(); - - dprintf(1, "=== PCI new allocation pass #1 ===\n"); - struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1)); - if (!busses) { - warn_noalloc(); - return; - } - memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1)); - if (pci_bios_check_devices(busses)) - return; - - dprintf(1, "=== PCI new allocation pass #2 ===\n"); - pci_bios_map_devices(busses); - - pci_bios_init_devices(); - - free(busses); -} diff -Nru seabios-1.7.1/src/pci_regs.h seabios-1.7.4/src/pci_regs.h --- seabios-1.7.1/src/pci_regs.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pci_regs.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,556 +0,0 @@ -/* - * pci_regs.h - * - * PCI standard defines - * Copyright 1994, Drew Eckhardt - * Copyright 1997--1999 Martin Mares - * - * For more information, please consult the following manuals (look at - * http://www.pcisig.com/ for how to get them): - * - * PCI BIOS Specification - * PCI Local Bus Specification - * PCI to PCI Bridge Specification - * PCI System Design Guide - * - * For hypertransport information, please consult the following manuals - * from http://www.hypertransport.org - * - * The Hypertransport I/O Link Specification - */ - -#ifndef LINUX_PCI_REGS_H -#define LINUX_PCI_REGS_H - -/* - * Under PCI, each device has 256 bytes of configuration address space, - * of which the first 64 bytes are standardized as follows: - */ -#define PCI_VENDOR_ID 0x00 /* 16 bits */ -#define PCI_DEVICE_ID 0x02 /* 16 bits */ -#define PCI_COMMAND 0x04 /* 16 bits */ -#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ -#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ -#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ -#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ -#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ -#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ -#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ -#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ -#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ -#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ -#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ - -#define PCI_STATUS 0x06 /* 16 bits */ -#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ -#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ -#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ -#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ -#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ -#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ -#define PCI_STATUS_DEVSEL_FAST 0x000 -#define PCI_STATUS_DEVSEL_MEDIUM 0x200 -#define PCI_STATUS_DEVSEL_SLOW 0x400 -#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ -#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ -#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ -#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ -#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ - -#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */ -#define PCI_REVISION_ID 0x08 /* Revision ID */ -#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ -#define PCI_CLASS_DEVICE 0x0a /* Device class */ - -#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ -#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ -#define PCI_HEADER_TYPE 0x0e /* 8 bits */ -#define PCI_HEADER_TYPE_NORMAL 0 -#define PCI_HEADER_TYPE_BRIDGE 1 -#define PCI_HEADER_TYPE_CARDBUS 2 - -#define PCI_BIST 0x0f /* 8 bits */ -#define PCI_BIST_CODE_MASK 0x0f /* Return result */ -#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ -#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ - -/* - * Base addresses specify locations in memory or I/O space. - * Decoded size can be determined by writing a value of - * 0xffffffff to the register, and reading it back. Only - * 1 bits are decoded. - */ -#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ -#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ -#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ -#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ -#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ -#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ -#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ -#define PCI_BASE_ADDRESS_SPACE_IO 0x01 -#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 -#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 -#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ -#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ -#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ -#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ -#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) -#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) -/* bit 1 is reserved if address_space = 1 */ - -/* Header type 0 (normal devices) */ -#define PCI_CARDBUS_CIS 0x28 -#define PCI_SUBSYSTEM_VENDOR_ID 0x2c -#define PCI_SUBSYSTEM_ID 0x2e -#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ -#define PCI_ROM_ADDRESS_ENABLE 0x01 -#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) - -#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ - -/* 0x35-0x3b are reserved */ -#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ -#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ -#define PCI_MIN_GNT 0x3e /* 8 bits */ -#define PCI_MAX_LAT 0x3f /* 8 bits */ - -/* Header type 1 (PCI-to-PCI bridges) */ -#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ -#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ -#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ -#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ -#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ -#define PCI_IO_LIMIT 0x1d -#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */ -#define PCI_IO_RANGE_TYPE_16 0x00 -#define PCI_IO_RANGE_TYPE_32 0x01 -#define PCI_IO_RANGE_MASK (~0x0fUL) -#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */ -#define PCI_MEMORY_BASE 0x20 /* Memory range behind */ -#define PCI_MEMORY_LIMIT 0x22 -#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL -#define PCI_MEMORY_RANGE_MASK (~0x0fUL) -#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ -#define PCI_PREF_MEMORY_LIMIT 0x26 -#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL -#define PCI_PREF_RANGE_TYPE_32 0x00 -#define PCI_PREF_RANGE_TYPE_64 0x01 -#define PCI_PREF_RANGE_MASK (~0x0fUL) -#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ -#define PCI_PREF_LIMIT_UPPER32 0x2c -#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */ -#define PCI_IO_LIMIT_UPPER16 0x32 -/* 0x34 same as for htype 0 */ -/* 0x35-0x3b is reserved */ -#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */ -/* 0x3c-0x3d are same as for htype 0 */ -#define PCI_BRIDGE_CONTROL 0x3e -#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */ -#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */ -#define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */ -#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */ -#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ -#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */ -#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */ - -/* Header type 2 (CardBus bridges) */ -#define PCI_CB_CAPABILITY_LIST 0x14 -/* 0x15 reserved */ -#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */ -#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */ -#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */ -#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */ -#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */ -#define PCI_CB_MEMORY_BASE_0 0x1c -#define PCI_CB_MEMORY_LIMIT_0 0x20 -#define PCI_CB_MEMORY_BASE_1 0x24 -#define PCI_CB_MEMORY_LIMIT_1 0x28 -#define PCI_CB_IO_BASE_0 0x2c -#define PCI_CB_IO_BASE_0_HI 0x2e -#define PCI_CB_IO_LIMIT_0 0x30 -#define PCI_CB_IO_LIMIT_0_HI 0x32 -#define PCI_CB_IO_BASE_1 0x34 -#define PCI_CB_IO_BASE_1_HI 0x36 -#define PCI_CB_IO_LIMIT_1 0x38 -#define PCI_CB_IO_LIMIT_1_HI 0x3a -#define PCI_CB_IO_RANGE_MASK (~0x03UL) -/* 0x3c-0x3d are same as for htype 0 */ -#define PCI_CB_BRIDGE_CONTROL 0x3e -#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */ -#define PCI_CB_BRIDGE_CTL_SERR 0x02 -#define PCI_CB_BRIDGE_CTL_ISA 0x04 -#define PCI_CB_BRIDGE_CTL_VGA 0x08 -#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20 -#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */ -#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */ -#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */ -#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200 -#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400 -#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40 -#define PCI_CB_SUBSYSTEM_ID 0x42 -#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */ -/* 0x48-0x7f reserved */ - -/* Capability lists */ - -#define PCI_CAP_LIST_ID 0 /* Capability ID */ -#define PCI_CAP_ID_PM 0x01 /* Power Management */ -#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */ -#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */ -#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ -#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ -#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ -#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ -#define PCI_CAP_ID_HT 0x08 /* HyperTransport */ -#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */ -#define PCI_CAP_ID_DBG 0x0A /* Debug port */ -#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */ -#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ -#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */ -#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */ -#define PCI_CAP_ID_EXP 0x10 /* PCI Express */ -#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ -#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ -#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ -#define PCI_CAP_SIZEOF 4 - -/* Power Management Registers */ - -#define PCI_PM_PMC 2 /* PM Capabilities Register */ -#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */ -#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ -#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */ -#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ -#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */ -#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ -#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ -#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ -#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */ -#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */ -#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */ -#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */ -#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */ -#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ -#define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */ -#define PCI_PM_CTRL 4 /* PM control and status register */ -#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ -#define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */ -#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ -#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ -#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ -#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */ -#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */ -#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */ -#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */ -#define PCI_PM_DATA_REGISTER 7 /* (??) */ -#define PCI_PM_SIZEOF 8 - -/* AGP registers */ - -#define PCI_AGP_VERSION 2 /* BCD version number */ -#define PCI_AGP_RFU 3 /* Rest of capability flags */ -#define PCI_AGP_STATUS 4 /* Status register */ -#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */ -#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */ -#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */ -#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */ -#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */ -#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */ -#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */ -#define PCI_AGP_COMMAND 8 /* Control register */ -#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ -#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */ -#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */ -#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */ -#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */ -#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */ -#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */ -#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */ -#define PCI_AGP_SIZEOF 12 - -/* Vital Product Data */ - -#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */ -#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */ -#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */ -#define PCI_VPD_DATA 4 /* 32-bits of data returned here */ - -/* Slot Identification */ - -#define PCI_SID_ESR 2 /* Expansion Slot Register */ -#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */ -#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */ -#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */ - -/* Message Signalled Interrupts registers */ - -#define PCI_MSI_FLAGS 2 /* Various flags */ -#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */ -#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ -#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ -#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ -#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */ -#define PCI_MSI_RFU 3 /* Rest of capability flags */ -#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ -#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ -#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ -#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ -#define PCI_MSI_MASK_BIT 16 /* Mask bits register */ - -/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */ -#define PCI_MSIX_FLAGS 2 -#define PCI_MSIX_FLAGS_QSIZE 0x7FF -#define PCI_MSIX_FLAGS_ENABLE (1 << 15) -#define PCI_MSIX_FLAGS_MASKALL (1 << 14) -#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) -#define PCI_MSIX_FLAGS_BITMASK (1 << 0) - -/* CompactPCI Hotswap Register */ - -#define PCI_CHSWP_CSR 2 /* Control and Status Register */ -#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */ -#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */ -#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */ -#define PCI_CHSWP_LOO 0x08 /* LED On / Off */ -#define PCI_CHSWP_PI 0x30 /* Programming Interface */ -#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */ -#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */ - -/* PCI-X registers */ - -#define PCI_X_CMD 2 /* Modes & Features */ -#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */ -#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */ -#define PCI_X_CMD_READ_512 0x0000 /* 512 byte maximum read byte count */ -#define PCI_X_CMD_READ_1K 0x0004 /* 1Kbyte maximum read byte count */ -#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */ -#define PCI_X_CMD_READ_4K 0x000c /* 4Kbyte maximum read byte count */ -#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */ - /* Max # of outstanding split transactions */ -#define PCI_X_CMD_SPLIT_1 0x0000 /* Max 1 */ -#define PCI_X_CMD_SPLIT_2 0x0010 /* Max 2 */ -#define PCI_X_CMD_SPLIT_3 0x0020 /* Max 3 */ -#define PCI_X_CMD_SPLIT_4 0x0030 /* Max 4 */ -#define PCI_X_CMD_SPLIT_8 0x0040 /* Max 8 */ -#define PCI_X_CMD_SPLIT_12 0x0050 /* Max 12 */ -#define PCI_X_CMD_SPLIT_16 0x0060 /* Max 16 */ -#define PCI_X_CMD_SPLIT_32 0x0070 /* Max 32 */ -#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */ -#define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */ -#define PCI_X_STATUS 4 /* PCI-X capabilities */ -#define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */ -#define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */ -#define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */ -#define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */ -#define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */ -#define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */ -#define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */ -#define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */ -#define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */ -#define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */ -#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */ -#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ -#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ - -/* PCI Express capability registers */ - -#define PCI_EXP_FLAGS 2 /* Capabilities register */ -#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */ -#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */ -#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */ -#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */ -#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */ -#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */ -#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ -#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ -#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ -#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ -#define PCI_EXP_DEVCAP 4 /* Device capabilities */ -#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */ -#define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */ -#define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */ -#define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */ -#define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */ -#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ -#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ -#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ -#define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */ -#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ -#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ -#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ -#define PCI_EXP_DEVCTL 8 /* Device Control */ -#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ -#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ -#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */ -#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ -#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ -#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ -#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ -#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ -#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ -#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ -#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ -#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */ -#define PCI_EXP_DEVSTA 10 /* Device Status */ -#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ -#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ -#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */ -#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */ -#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */ -#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ -#define PCI_EXP_LNKCAP 12 /* Link Capabilities */ -#define PCI_EXP_LNKCAP_ASPMS 0xc00 /* ASPM Support */ -#define PCI_EXP_LNKCAP_L0SEL 0x7000 /* L0s Exit Latency */ -#define PCI_EXP_LNKCAP_L1EL 0x38000 /* L1 Exit Latency */ -#define PCI_EXP_LNKCAP_CLKPM 0x40000 /* L1 Clock Power Management */ -#define PCI_EXP_LNKCTL 16 /* Link Control */ -#define PCI_EXP_LNKCTL_RL 0x20 /* Retrain Link */ -#define PCI_EXP_LNKCTL_CCC 0x40 /* Common Clock COnfiguration */ -#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ -#define PCI_EXP_LNKSTA 18 /* Link Status */ -#define PCI_EXP_LNKSTA_LT 0x800 /* Link Training */ -#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */ -#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ -#define PCI_EXP_SLTCTL 24 /* Slot Control */ -#define PCI_EXP_SLTSTA 26 /* Slot Status */ -#define PCI_EXP_RTCTL 28 /* Root Control */ -#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */ -#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */ -#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */ -#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */ -#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */ -#define PCI_EXP_RTCAP 30 /* Root Capabilities */ -#define PCI_EXP_RTSTA 32 /* Root Status */ -#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ -#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */ -#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ -#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */ - -/* Extended Capabilities (PCI-X 2.0 and Express) */ -#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) -#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) -#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) - -#define PCI_EXT_CAP_ID_ERR 1 -#define PCI_EXT_CAP_ID_VC 2 -#define PCI_EXT_CAP_ID_DSN 3 -#define PCI_EXT_CAP_ID_PWR 4 -#define PCI_EXT_CAP_ID_ARI 14 - -/* Advanced Error Reporting */ -#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ -#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */ -#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ -#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */ -#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */ -#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */ -#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */ -#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */ -#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */ -#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */ -#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */ -#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */ -#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ - /* Same bits as above */ -#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */ - /* Same bits as above */ -#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */ -#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */ -#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */ -#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ -#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */ -#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */ -#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */ - /* Same bits as above */ -#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */ -#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */ -#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */ -#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */ -#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */ -#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */ -#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */ -#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */ -/* Correctable Err Reporting Enable */ -#define PCI_ERR_ROOT_CMD_COR_EN 0x00000001 -/* Non-fatal Err Reporting Enable */ -#define PCI_ERR_ROOT_CMD_NONFATAL_EN 0x00000002 -/* Fatal Err Reporting Enable */ -#define PCI_ERR_ROOT_CMD_FATAL_EN 0x00000004 -#define PCI_ERR_ROOT_STATUS 48 -#define PCI_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */ -/* Multi ERR_COR Received */ -#define PCI_ERR_ROOT_MULTI_COR_RCV 0x00000002 -/* ERR_FATAL/NONFATAL Recevied */ -#define PCI_ERR_ROOT_UNCOR_RCV 0x00000004 -/* Multi ERR_FATAL/NONFATAL Recevied */ -#define PCI_ERR_ROOT_MULTI_UNCOR_RCV 0x00000008 -#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */ -#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */ -#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */ -#define PCI_ERR_ROOT_COR_SRC 52 -#define PCI_ERR_ROOT_SRC 54 - -/* Virtual Channel */ -#define PCI_VC_PORT_REG1 4 -#define PCI_VC_PORT_REG2 8 -#define PCI_VC_PORT_CTRL 12 -#define PCI_VC_PORT_STATUS 14 -#define PCI_VC_RES_CAP 16 -#define PCI_VC_RES_CTRL 20 -#define PCI_VC_RES_STATUS 26 - -/* Power Budgeting */ -#define PCI_PWR_DSR 4 /* Data Select Register */ -#define PCI_PWR_DATA 8 /* Data Register */ -#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ -#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ -#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ -#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ -#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ -#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ -#define PCI_PWR_CAP 12 /* Capability */ -#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ - -/* - * Hypertransport sub capability types - * - * Unfortunately there are both 3 bit and 5 bit capability types defined - * in the HT spec, catering for that is a little messy. You probably don't - * want to use these directly, just use pci_find_ht_capability() and it - * will do the right thing for you. - */ -#define HT_3BIT_CAP_MASK 0xE0 -#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */ -#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */ - -#define HT_5BIT_CAP_MASK 0xF8 -#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */ -#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */ -#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */ -#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */ -#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */ -#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */ -#define HT_MSI_FLAGS 0x02 /* Offset to flags */ -#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */ -#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */ -#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */ -#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */ -#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */ -#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */ -#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */ -#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */ -#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */ -#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */ -#define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */ - -/* Alternative Routing-ID Interpretation */ -#define PCI_ARI_CAP 0x04 /* ARI Capability Register */ -#define PCI_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */ -#define PCI_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */ -#define PCI_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) /* Next Function Number */ -#define PCI_ARI_CTRL 0x06 /* ARI Control Register */ -#define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */ -#define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */ -#define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */ - -#endif /* LINUX_PCI_REGS_H */ diff -Nru seabios-1.7.1/src/pic.c seabios-1.7.4/src/pic.c --- seabios-1.7.1/src/pic.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pic.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -// Helpers for working with i8259 interrupt controller. -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "pic.h" // get_pic1_isr -#include "util.h" // dprintf -#include "config.h" // CONFIG_* - -void -set_pics(u8 irq0, u8 irq8) -{ - // Send ICW1 (select OCW1 + will send ICW4) - outb(0x11, PORT_PIC1_CMD); - outb(0x11, PORT_PIC2_CMD); - // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15) - outb(irq0, PORT_PIC1_DATA); - outb(irq8, PORT_PIC2_DATA); - // Send ICW3 (cascaded pic ids) - outb(0x04, PORT_PIC1_DATA); - outb(0x02, PORT_PIC2_DATA); - // Send ICW4 (enable 8086 mode) - outb(0x01, PORT_PIC1_DATA); - outb(0x01, PORT_PIC2_DATA); - // Mask all irqs (except cascaded PIC2 irq) - outb(~PIC1_IRQ2, PORT_PIC1_DATA); - outb(~0, PORT_PIC2_DATA); -} - -void -pic_setup(void) -{ - dprintf(3, "init pic\n"); - set_pics(0x08, 0x70); -} - -// Handler for otherwise unused hardware irqs. -void VISIBLE16 -handle_hwpic1(struct bregs *regs) -{ - dprintf(DEBUG_ISR_hwpic1, "handle_hwpic1 irq=%x\n", get_pic1_isr()); - eoi_pic1(); -} - -void VISIBLE16 -handle_hwpic2(struct bregs *regs) -{ - dprintf(DEBUG_ISR_hwpic2, "handle_hwpic2 irq=%x\n", get_pic2_isr()); - eoi_pic2(); -} diff -Nru seabios-1.7.1/src/pic.h seabios-1.7.4/src/pic.h --- seabios-1.7.1/src/pic.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pic.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -// Helpers for working with i8259 interrupt controller. -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. -#ifndef __PIC_H -#define __PIC_H - -#include "ioport.h" // PORT_PIC* -#include "biosvar.h" // SET_IVT - -// PORT_PIC1 bitdefs -#define PIC1_IRQ0 (1<<0) -#define PIC1_IRQ1 (1<<1) -#define PIC1_IRQ2 (1<<2) -#define PIC1_IRQ5 (1<<5) -#define PIC1_IRQ6 (1<<6) -// PORT_PIC2 bitdefs -#define PIC2_IRQ8 (1<<0) -#define PIC2_IRQ12 (1<<4) -#define PIC2_IRQ13 (1<<5) -#define PIC2_IRQ14 (1<<6) - -static inline void -eoi_pic1(void) -{ - // Send eoi (select OCW2 + eoi) - outb(0x20, PORT_PIC1_CMD); -} - -static inline void -eoi_pic2(void) -{ - // Send eoi (select OCW2 + eoi) - outb(0x20, PORT_PIC2_CMD); - eoi_pic1(); -} - -static inline void -unmask_pic1(u8 irq) -{ - outb(inb(PORT_PIC1_DATA) & ~irq, PORT_PIC1_DATA); -} - -static inline void -unmask_pic2(u8 irq) -{ - outb(inb(PORT_PIC2_DATA) & ~irq, PORT_PIC2_DATA); -} - -static inline void -mask_pic1(u8 irq) -{ - outb(inb(PORT_PIC1_DATA) | irq, PORT_PIC1_DATA); -} - -static inline void -mask_pic2(u8 irq) -{ - outb(inb(PORT_PIC2_DATA) | irq, PORT_PIC2_DATA); -} - -static inline u8 -get_pic1_isr(void) -{ - // 0x0b == select OCW1 + read ISR - outb(0x0b, PORT_PIC1_CMD); - return inb(PORT_PIC1_CMD); -} - -static inline u8 -get_pic2_isr(void) -{ - // 0x0b == select OCW1 + read ISR - outb(0x0b, PORT_PIC2_CMD); - return inb(PORT_PIC2_CMD); -} - -static inline void -enable_hwirq(int hwirq, struct segoff_s func) -{ - int vector; - if (hwirq < 8) { - unmask_pic1(1 << hwirq); - vector = 0x08 + hwirq; - } else { - unmask_pic2(1 << (hwirq - 8)); - vector = 0x70 + hwirq - 8; - } - SET_IVT(vector, func); -} - -void set_pics(u8 irq0, u8 irq8); -void pic_setup(void); - -#endif // pic.h diff -Nru seabios-1.7.1/src/pirtable.c seabios-1.7.4/src/pirtable.c --- seabios-1.7.1/src/pirtable.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pirtable.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -// PIR table generation (for emulators) -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "pci.h" // struct pir_header -#include "config.h" // CONFIG_* -#include "util.h" // checksum - -struct pir_header *PirAddr VAR16VISIBLE; - -struct pir_table { - struct pir_header pir; - struct pir_slot slots[6]; -} PACKED; - -extern struct pir_table PIR_TABLE; -#if CONFIG_PIRTABLE && !CONFIG_COREBOOT -struct pir_table PIR_TABLE __aligned(16) VAR16EXPORT = { - .pir = { - .version = 0x0100, - .size = sizeof(struct pir_table), - .router_devfunc = 0x08, - .compatible_devid = 0x122e8086, - }, - .slots = { - { - // first slot entry PCI-to-ISA (embedded) - .dev = 1<<3, - .links = { - {.link = 0x60, .bitmap = 0xdef8}, // INTA# - {.link = 0x61, .bitmap = 0xdef8}, // INTB# - {.link = 0x62, .bitmap = 0xdef8}, // INTC# - {.link = 0x63, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 0, // embedded - }, { - // second slot entry: 1st PCI slot - .dev = 2<<3, - .links = { - {.link = 0x61, .bitmap = 0xdef8}, // INTA# - {.link = 0x62, .bitmap = 0xdef8}, // INTB# - {.link = 0x63, .bitmap = 0xdef8}, // INTC# - {.link = 0x60, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 1, - }, { - // third slot entry: 2nd PCI slot - .dev = 3<<3, - .links = { - {.link = 0x62, .bitmap = 0xdef8}, // INTA# - {.link = 0x63, .bitmap = 0xdef8}, // INTB# - {.link = 0x60, .bitmap = 0xdef8}, // INTC# - {.link = 0x61, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 2, - }, { - // 4th slot entry: 3rd PCI slot - .dev = 4<<3, - .links = { - {.link = 0x63, .bitmap = 0xdef8}, // INTA# - {.link = 0x60, .bitmap = 0xdef8}, // INTB# - {.link = 0x61, .bitmap = 0xdef8}, // INTC# - {.link = 0x62, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 3, - }, { - // 5th slot entry: 4rd PCI slot - .dev = 5<<3, - .links = { - {.link = 0x60, .bitmap = 0xdef8}, // INTA# - {.link = 0x61, .bitmap = 0xdef8}, // INTB# - {.link = 0x62, .bitmap = 0xdef8}, // INTC# - {.link = 0x63, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 4, - }, { - // 6th slot entry: 5rd PCI slot - .dev = 6<<3, - .links = { - {.link = 0x61, .bitmap = 0xdef8}, // INTA# - {.link = 0x62, .bitmap = 0xdef8}, // INTB# - {.link = 0x63, .bitmap = 0xdef8}, // INTC# - {.link = 0x60, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 5, - }, - } -}; -#endif // CONFIG_PIRTABLE && !CONFIG_COREBOOT - -void -create_pirtable(void) -{ - if (! CONFIG_PIRTABLE) - return; - - dprintf(3, "init PIR table\n"); - - PIR_TABLE.pir.signature = PIR_SIGNATURE; - PIR_TABLE.pir.checksum -= checksum(&PIR_TABLE, sizeof(PIR_TABLE)); - PirAddr = &PIR_TABLE.pir; -} diff -Nru seabios-1.7.1/src/pmm.c seabios-1.7.4/src/pmm.c --- seabios-1.7.1/src/pmm.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pmm.c 2013-12-23 15:40:06.000000000 +0000 @@ -1,440 +1,28 @@ // Post memory manager (PMM) calls // -// Copyright (C) 2009 Kevin O'Connor +// Copyright (C) 2009-2013 Kevin O'Connor // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "util.h" // checksum -#include "config.h" // BUILD_BIOS_ADDR -#include "memmap.h" // struct e820entry -#include "farptr.h" // GET_FARVAR -#include "biosvar.h" // GET_BDA -#include "optionroms.h" // OPTION_ROM_ALIGN - -// Information on a reserved area. -struct allocinfo_s { - struct allocinfo_s *next, **pprev; - void *data, *dataend, *allocend; -}; - -// Information on a tracked memory allocation. -struct allocdetail_s { - struct allocinfo_s detailinfo; - struct allocinfo_s datainfo; - u32 handle; -}; - -// The various memory zones. -struct zone_s { - struct allocinfo_s *info; -}; - -struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh; - -static struct zone_s *Zones[] = { - &ZoneTmpLow, &ZoneLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh -}; - - -/**************************************************************** - * low-level memory reservations - ****************************************************************/ - -// Find and reserve space from a given zone -static void * -allocSpace(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill) -{ - struct allocinfo_s *info; - for (info = zone->info; info; info = info->next) { - void *dataend = info->dataend; - void *allocend = info->allocend; - void *newallocend = (void*)ALIGN_DOWN((u32)allocend - size, align); - if (newallocend >= dataend && newallocend <= allocend) { - // Found space - now reserve it. - struct allocinfo_s **pprev = info->pprev; - if (!fill) - fill = newallocend; - fill->next = info; - fill->pprev = pprev; - fill->data = newallocend; - fill->dataend = newallocend + size; - fill->allocend = allocend; - - info->allocend = newallocend; - info->pprev = &fill->next; - *pprev = fill; - return newallocend; - } - } - return NULL; -} - -// Release space allocated with allocSpace() -static void -freeSpace(struct allocinfo_s *info) -{ - struct allocinfo_s *next = info->next; - struct allocinfo_s **pprev = info->pprev; - *pprev = next; - if (next) { - if (next->allocend == info->data) - next->allocend = info->allocend; - next->pprev = pprev; - } -} - -// Add new memory to a zone -static void -addSpace(struct zone_s *zone, void *start, void *end) -{ - // Find position to add space - struct allocinfo_s **pprev = &zone->info, *info; - for (;;) { - info = *pprev; - if (!info || info->data < start) - break; - pprev = &info->next; - } - - // Add space using temporary allocation info. - struct allocdetail_s tempdetail; - tempdetail.datainfo.next = info; - tempdetail.datainfo.pprev = pprev; - tempdetail.datainfo.data = tempdetail.datainfo.dataend = start; - tempdetail.datainfo.allocend = end; - *pprev = &tempdetail.datainfo; - if (info) - info->pprev = &tempdetail.datainfo.next; - - // Allocate final allocation info. - struct allocdetail_s *detail = allocSpace( - &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL); - if (!detail) { - detail = allocSpace(&ZoneTmpLow, sizeof(*detail) - , MALLOC_MIN_ALIGN, NULL); - if (!detail) { - *tempdetail.datainfo.pprev = tempdetail.datainfo.next; - if (tempdetail.datainfo.next) - tempdetail.datainfo.next->pprev = tempdetail.datainfo.pprev; - warn_noalloc(); - return; - } - } - - // Replace temp alloc space with final alloc space - memcpy(&detail->datainfo, &tempdetail.datainfo, sizeof(detail->datainfo)); - detail->handle = PMM_DEFAULT_HANDLE; - - *tempdetail.datainfo.pprev = &detail->datainfo; - if (tempdetail.datainfo.next) - tempdetail.datainfo.next->pprev = &detail->datainfo.next; -} - -// Search all zones for an allocation obtained from allocSpace() -static struct allocinfo_s * -findAlloc(void *data) -{ - int i; - for (i=0; iinfo; info; info = info->next) - if (info->data == data) - return info; - } - return NULL; -} - -// Return the last sentinal node of a zone -static struct allocinfo_s * -findLast(struct zone_s *zone) -{ - struct allocinfo_s *info = zone->info; - if (!info) - return NULL; - for (;;) { - struct allocinfo_s *next = info->next; - if (!next) - return info; - info = next; - } -} - - -/**************************************************************** - * 0xc0000-0xf0000 management - ****************************************************************/ - -static u32 RomEnd = BUILD_ROM_START; -static struct allocinfo_s *RomBase; - -#define OPROM_HEADER_RESERVE 16 - -// Return the memory position up to which roms may be located. -u32 -rom_get_top(void) -{ - return ALIGN_DOWN((u32)RomBase->allocend - OPROM_HEADER_RESERVE - , OPTION_ROM_ALIGN); -} - -// Return the end of the last deployed rom. -u32 -rom_get_last(void) -{ - return RomEnd; -} - -// Request space for an optionrom in 0xc0000-0xf0000 area. -struct rom_header * -rom_reserve(u32 size) -{ - u32 newend = ALIGN(RomEnd + size, OPTION_ROM_ALIGN) + OPROM_HEADER_RESERVE; - if (newend > (u32)RomBase->allocend) - return NULL; - if (newend < (u32)datalow_base + OPROM_HEADER_RESERVE) - newend = (u32)datalow_base + OPROM_HEADER_RESERVE; - RomBase->data = RomBase->dataend = (void*)newend; - return (void*)RomEnd; -} - -// Confirm space as in use by an optionrom. -int -rom_confirm(u32 size) -{ - void *new = rom_reserve(size); - if (!new) { - warn_noalloc(); - return -1; - } - RomEnd = ALIGN(RomEnd + size, OPTION_ROM_ALIGN); - return 0; -} - - -/**************************************************************** - * Setup - ****************************************************************/ - -void -malloc_setup(void) -{ - ASSERT32FLAT(); - dprintf(3, "malloc setup\n"); - - // Populate temp high ram - u32 highram = 0; - int i; - for (i=e820_count-1; i>=0; i--) { - struct e820entry *en = &e820_list[i]; - u64 end = en->start + en->size; - if (end < 1024*1024) - break; - if (en->type != E820_RAM || end > 0xffffffff) - continue; - u32 s = en->start, e = end; - if (!highram) { - u32 newe = ALIGN_DOWN(e - CONFIG_MAX_HIGHTABLE, MALLOC_MIN_ALIGN); - if (newe <= e && newe >= s) { - highram = newe; - e = newe; - } - } - addSpace(&ZoneTmpHigh, (void*)s, (void*)e); - } - - // Populate other regions - addSpace(&ZoneTmpLow, (void*)BUILD_STACK_ADDR, (void*)BUILD_EBDA_MINIMUM); - addSpace(&ZoneFSeg, BiosTableSpace, &BiosTableSpace[CONFIG_MAX_BIOSTABLE]); - extern u8 final_datalow_start[]; - addSpace(&ZoneLow, datalow_base + OPROM_HEADER_RESERVE, final_datalow_start); - RomBase = findLast(&ZoneLow); - if (highram) { - addSpace(&ZoneHigh, (void*)highram - , (void*)highram + CONFIG_MAX_HIGHTABLE); - add_e820(highram, CONFIG_MAX_HIGHTABLE, E820_RESERVED); - } -} - -// Update pointers after code relocation. -void -malloc_fixupreloc(void) -{ - ASSERT32FLAT(); - if (!CONFIG_RELOCATE_INIT) - return; - dprintf(3, "malloc fixup reloc\n"); - - int i; - for (i=0; iinfo) - zone->info->pprev = &zone->info; - } - - // Add space free'd during relocation in f-segment to ZoneFSeg - extern u8 code32init_end[]; - if ((u32)code32init_end > BUILD_BIOS_ADDR) { - memset((void*)BUILD_BIOS_ADDR, 0, (u32)code32init_end - BUILD_BIOS_ADDR); - addSpace(&ZoneFSeg, (void*)BUILD_BIOS_ADDR, code32init_end); - } -} - -void -malloc_finalize(void) -{ - ASSERT32FLAT(); - dprintf(3, "malloc finalize\n"); - - // Place an optionrom signature around used low mem area. - u32 base = rom_get_top(); - struct rom_header *dummyrom = (void*)base; - dummyrom->signature = OPTION_ROM_SIGNATURE; - int size = (BUILD_BIOS_ADDR - base) / 512; - dummyrom->size = (size > 255) ? 255 : size; - memset((void*)RomEnd, 0, base-RomEnd); - dprintf(1, "Space available for UMB: %08x-%08x\n", RomEnd, base); - - // Clear unused f-seg ram. - struct allocinfo_s *info = findLast(&ZoneFSeg); - memset(info->dataend, 0, info->allocend - info->dataend); - - // Give back unused high ram. - info = findLast(&ZoneHigh); - if (info) { - u32 giveback = ALIGN_DOWN(info->allocend - info->dataend, PAGE_SIZE); - add_e820((u32)info->dataend, giveback, E820_RAM); - dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback); - } -} - - -/**************************************************************** - * tracked memory allocations - ****************************************************************/ - -// Allocate memory from the given zone and track it as a PMM allocation -void * __malloc -pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align) -{ - ASSERT32FLAT(); - if (!size) - return NULL; - - // Find and reserve space for bookkeeping. - struct allocdetail_s *detail = allocSpace( - &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL); - if (!detail) { - detail = allocSpace(&ZoneTmpLow, sizeof(*detail) - , MALLOC_MIN_ALIGN, NULL); - if (!detail) - return NULL; - } - - // Find and reserve space for main allocation - void *data = allocSpace(zone, size, align, &detail->datainfo); - if (!data) { - freeSpace(&detail->detailinfo); - return NULL; - } - - dprintf(8, "pmm_malloc zone=%p handle=%x size=%d align=%x" - " ret=%p (detail=%p)\n" - , zone, handle, size, align - , data, detail); - detail->handle = handle; - - return data; -} - -// Free a data block allocated with pmm_malloc -int -pmm_free(void *data) -{ - ASSERT32FLAT(); - struct allocinfo_s *info = findAlloc(data); - if (!info || data == (void*)info || data == info->dataend) - return -1; - struct allocdetail_s *detail = container_of( - info, struct allocdetail_s, datainfo); - dprintf(8, "pmm_free %p (detail=%p)\n", data, detail); - freeSpace(info); - freeSpace(&detail->detailinfo); - return 0; -} - -// Find the amount of free space in a given zone. -static u32 -pmm_getspace(struct zone_s *zone) -{ - // XXX - doesn't account for ZoneLow being able to grow. - // XXX - results not reliable when CONFIG_THREAD_OPTIONROMS - u32 maxspace = 0; - struct allocinfo_s *info; - for (info = zone->info; info; info = info->next) { - u32 space = info->allocend - info->dataend; - if (space > maxspace) - maxspace = space; - } - - if (zone != &ZoneTmpHigh && zone != &ZoneTmpLow) - return maxspace; - // Account for space needed for PMM tracking. - u32 reserve = ALIGN(sizeof(struct allocdetail_s), MALLOC_MIN_ALIGN); - if (maxspace <= reserve) - return 0; - return maxspace - reserve; -} - -// Find the data block allocated with pmm_malloc with a given handle. -static void * -pmm_find(u32 handle) -{ - int i; - for (i=0; iinfo; info; info = info->next) { - if (info->data != (void*)info) - continue; - struct allocdetail_s *detail = container_of( - info, struct allocdetail_s, detailinfo); - if (detail->handle == handle) - return detail->datainfo.data; - } - } - return NULL; -} - - -/**************************************************************** - * pmm interface - ****************************************************************/ - -struct pmmheader { - u32 signature; - u8 version; - u8 length; - u8 checksum; - u16 entry_offset; - u16 entry_seg; - u8 reserved[5]; -} PACKED; +#include "biosvar.h" // FUNC16 +#include "config.h" // CONFIG_* +#include "malloc.h" // _malloc +#include "output.h" // dprintf +#include "std/pmm.h" // PMM_SIGNATURE +#include "string.h" // checksum +#include "util.h" // pmm_init +#include "x86.h" // __ffs extern struct pmmheader PMMHEADER; -#define PMM_SIGNATURE 0x4d4d5024 // $PMM - #if CONFIG_PMM -struct pmmheader PMMHEADER __aligned(16) VAR16EXPORT = { +struct pmmheader PMMHEADER __aligned(16) VARFSEG = { + .signature = PMM_SIGNATURE, .version = 0x01, .length = sizeof(PMMHEADER), - .entry_seg = SEG_BIOS, }; #endif -#define PMM_FUNCTION_NOT_SUPPORTED 0xffffffff - // PMM - allocate static u32 handle_pmm00(u16 *args) @@ -456,12 +44,12 @@ case 0: return 0; case 1: - return pmm_getspace(lowzone); + return malloc_getspace(lowzone); case 2: - return pmm_getspace(highzone); + return malloc_getspace(highzone); case 3: { - u32 spacelow = pmm_getspace(lowzone); - u32 spacehigh = pmm_getspace(highzone); + u32 spacelow = malloc_getspace(lowzone); + u32 spacehigh = malloc_getspace(highzone); if (spacelow > spacehigh) return spacelow; return spacehigh; @@ -482,14 +70,14 @@ case 0: return 0; case 1: - return (u32)pmm_malloc(lowzone, handle, size, align); + return (u32)_malloc(lowzone, handle, size, align); case 2: - return (u32)pmm_malloc(highzone, handle, size, align); + return (u32)_malloc(highzone, handle, size, align); case 3: { - void *data = pmm_malloc(lowzone, handle, size, align); + void *data = _malloc(lowzone, handle, size, align); if (data) return (u32)data; - return (u32)pmm_malloc(highzone, handle, size, align); + return (u32)_malloc(highzone, handle, size, align); } } } @@ -500,9 +88,9 @@ { u32 handle = *(u32*)&args[1]; dprintf(3, "pmm01: handle=%x\n", handle); - if (handle == PMM_DEFAULT_HANDLE) + if (handle == MALLOC_DEFAULT_HANDLE) return 0; - return (u32)pmm_find(handle); + return (u32)malloc_find(handle); } // PMM - deallocate @@ -511,7 +99,7 @@ { u32 buffer = *(u32*)&args[1]; dprintf(3, "pmm02: buffer=%x\n", buffer); - int ret = pmm_free((void*)buffer); + int ret = _free((void*)buffer); if (ret) // Error return 1; @@ -545,24 +133,20 @@ return ret; } -// romlayout.S -extern void entry_pmm(void); - void -pmm_setup(void) +pmm_init(void) { if (! CONFIG_PMM) return; dprintf(3, "init PMM\n"); - PMMHEADER.signature = PMM_SIGNATURE; - PMMHEADER.entry_offset = (u32)entry_pmm - BUILD_BIOS_ADDR; + PMMHEADER.entry = FUNC16(entry_pmm); PMMHEADER.checksum -= checksum(&PMMHEADER, sizeof(PMMHEADER)); } void -pmm_finalize(void) +pmm_prepboot(void) { if (! CONFIG_PMM) return; @@ -570,5 +154,5 @@ dprintf(3, "finalize PMM\n"); PMMHEADER.signature = 0; - PMMHEADER.entry_offset = 0; + PMMHEADER.entry.segoff = 0; } diff -Nru seabios-1.7.1/src/pnpbios.c seabios-1.7.4/src/pnpbios.c --- seabios-1.7.1/src/pnpbios.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/pnpbios.c 2013-12-23 15:40:06.000000000 +0000 @@ -4,31 +4,18 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "util.h" // checksum #include "config.h" // BUILD_BIOS_ADDR #include "farptr.h" // SET_FARVAR - -struct pnpheader { - u32 signature; - u8 version; - u8 length; - u16 control; - u8 checksum; - u32 eventloc; - u16 real_ip; - u16 real_cs; - u16 prot_ip; - u32 prot_base; - u32 oemid; - u16 real_ds; - u32 prot_database; -} PACKED; +#include "output.h" // dprintf +#include "std/pnpbios.h" // PNP_SIGNATURE +#include "string.h" // checksum +#include "util.h" // pnp_init extern struct pnpheader PNPHEADER; extern char pnp_string[]; #if CONFIG_PNPBIOS -struct pnpheader PNPHEADER __aligned(16) VAR16EXPORT = { +struct pnpheader PNPHEADER __aligned(16) VARFSEG = { .signature = PNP_SIGNATURE, .version = 0x10, .length = sizeof(PNPHEADER), @@ -41,11 +28,9 @@ // We need a copy of this string in the 0xf000 segment, but we are not // actually a PnP BIOS, so make sure it is *not* aligned, so OSes will // not see it if they scan. -char pnp_string[] __aligned(2) VAR16VISIBLE = " $PnP"; +char pnp_string[] __aligned(2) VARFSEG = " $PnP"; #endif -#define FUNCTION_NOT_SUPPORTED 0x82 - // BBS - Get Version and Installation Check static u16 handle_pnp60(u16 *args) @@ -90,7 +75,7 @@ extern void entry_pnp_prot(void); void -pnp_setup(void) +pnp_init(void) { if (! CONFIG_PNPBIOS) return; diff -Nru seabios-1.7.1/src/post.c seabios-1.7.4/src/post.c --- seabios-1.7.1/src/post.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/post.c 2013-12-23 15:40:06.000000000 +0000 @@ -1,54 +1,56 @@ // 32bit code to Power On Self Test (POST) a machine. // -// Copyright (C) 2008-2010 Kevin O'Connor +// Copyright (C) 2008-2013 Kevin O'Connor // Copyright (C) 2002 MandrakeSoft S.A. // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "ioport.h" // PORT_* +#include "biosvar.h" // SET_BDA +#include "bregs.h" // struct bregs #include "config.h" // CONFIG_* -#include "cmos.h" // CMOS_* -#include "util.h" // memset -#include "biosvar.h" // struct bios_data_area_s -#include "disk.h" // floppy_drive_setup -#include "ata.h" // ata_setup -#include "ahci.h" // ahci_setup +#include "fw/paravirt.h" // qemu_cfg_preinit +#include "fw/xen.h" // xen_preinit +#include "hw/ahci.h" // ahci_setup +#include "hw/ata.h" // ata_setup +#include "hw/esp-scsi.h" // esp_scsi_setup +#include "hw/lsi-scsi.h" // lsi_scsi_setup +#include "hw/megasas.h" // megasas_setup +#include "hw/pvscsi.h" // pvscsi_setup +#include "hw/pic.h" // pic_setup +#include "hw/ps2port.h" // ps2port_setup +#include "hw/rtc.h" // rtc_write +#include "hw/usb.h" // usb_setup +#include "hw/virtio-blk.h" // virtio_blk_setup +#include "hw/virtio-scsi.h" // virtio_scsi_setup +#include "malloc.h" // malloc_init #include "memmap.h" // add_e820 -#include "pic.h" // pic_setup -#include "pci.h" // create_pirtable -#include "acpi.h" // acpi_bios_init -#include "bregs.h" // struct bregs -#include "mptable.h" // mptable_init -#include "boot.h" // IPL -#include "usb.h" // usb_setup -#include "smbios.h" // smbios_init -#include "paravirt.h" // qemu_cfg_port_probe -#include "xen.h" // xen_probe_hvm_info -#include "ps2port.h" // ps2port_setup -#include "virtio-blk.h" // virtio_blk_setup -#include "virtio-scsi.h" // virtio_scsi_setup -#include "lsi-scsi.h" // lsi_scsi_setup -#include "esp-scsi.h" // esp_scsi_setup +#include "output.h" // dprintf +#include "string.h" // memset +#include "util.h" // kbd_init /**************************************************************** - * BIOS init + * BIOS initialization and hardware setup ****************************************************************/ static void -init_ivt(void) +ivt_init(void) { dprintf(3, "init ivt\n"); + // Setup reset-vector entry point (controls legacy reboots). + HaveRunPost = 1; + rtc_write(CMOS_RESET_CODE, 0); + // Initialize all vectors to the default handler. int i; for (i=0; i<256; i++) SET_IVT(i, FUNC16(entry_iret_official)); // Initialize all hw vectors to a default hw handler. - for (i=0x08; i<=0x0f; i++) + for (i=BIOS_HWIRQ0_VECTOR; isize = esize; - add_e820((u32)MAKE_FLATPTR(ebda_seg, 0), GET_EBDA(ebda_seg, size) * 1024 - , E820_RESERVED); + add_e820((u32)ebda, BUILD_LOWRAM_END-(u32)ebda, E820_RESERVED); // Init extra stack - StackPos = (void*)(&ExtraStack[BUILD_EXTRA_STACK_SIZE] - datalow_base); -} - -static void -ram_probe(void) -{ - dprintf(3, "Find memory size\n"); - if (CONFIG_COREBOOT) { - coreboot_setup(); - } else if (usingXen()) { - xen_setup(); - } else { - // On emulators, get memory size from nvram. - u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16) - | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24)); - if (rs) - rs += 16 * 1024 * 1024; - else - rs = (((inb_cmos(CMOS_MEM_EXTMEM_LOW) << 10) - | (inb_cmos(CMOS_MEM_EXTMEM_HIGH) << 18)) - + 1 * 1024 * 1024); - RamSize = rs; - add_e820(0, rs, E820_RAM); - - // Check for memory over 4Gig - u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16) - | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24) - | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32)); - RamSizeOver4G = high; - add_e820(0x100000000ull, high, E820_RAM); - - /* reserve 256KB BIOS area at the end of 4 GB */ - add_e820(0xfffc0000, 256*1024, E820_RESERVED); - } - - // Don't declare any memory between 0xa0000 and 0x100000 - add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE); - - // Mark known areas as reserved. - add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED); - - u32 count = qemu_cfg_e820_entries(); - if (count) { - struct e820_reservation entry; - int i; - - for (i = 0; i < count; i++) { - qemu_cfg_e820_load_next(&entry); - add_e820(entry.address, entry.length, entry.type); - } - } else if (kvm_para_available()) { - // Backwards compatibility - provide hard coded range. - // 4 pages before the bios, 3 pages for vmx tss pages, the - // other page for EPT real mode pagetable - add_e820(0xfffbc000, 4*4096, E820_RESERVED); - } - - dprintf(1, "Ram Size=0x%08x (0x%016llx high)\n", RamSize, RamSizeOver4G); + StackPos = (void*)(&ExtraStack[BUILD_EXTRA_STACK_SIZE] - zonelow_base); } -static void -init_bios_tables(void) +void +interface_init(void) { - if (CONFIG_COREBOOT) { - coreboot_copy_biostable(); - return; - } - if (usingXen()) { - xen_copy_biostables(); - return; - } - - create_pirtable(); + // Running at new code address - do code relocation fixups + malloc_init(); - mptable_init(); + // Setup romfile items. + qemu_cfg_init(); + coreboot_cbfs_init(); - smbios_init(); + // Setup ivt/bda/ebda + ivt_init(); + bda_init(); - acpi_bios_init(); + // Other interfaces + boot_init(); + bios32_init(); + pmm_init(); + pnp_init(); + kbd_init(); + mouse_init(); } // Initialize hardware devices -static void -init_hw(void) +void +device_hardware_setup(void) { usb_setup(); ps2port_setup(); @@ -198,6 +147,44 @@ virtio_scsi_setup(); lsi_scsi_setup(); esp_scsi_setup(); + megasas_setup(); + pvscsi_setup(); +} + +static void +platform_hardware_setup(void) +{ + // Enable CPU caching + setcr0(getcr0() & ~(CR0_CD|CR0_NW)); + + // Make sure legacy DMA isn't running. + dma_setup(); + + // Init base pc hardware. + pic_setup(); + mathcp_setup(); + timer_setup(); + clock_setup(); + + // Platform specific setup + qemu_platform_setup(); + coreboot_platform_setup(); +} + +void +prepareboot(void) +{ + // Run BCVs + bcv_prepboot(); + + // Finalize data structures before boot + cdrom_prepboot(); + pmm_prepboot(); + malloc_prepboot(); + memmap_prepboot(); + + // Setup bios checksum. + BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE); } // Begin the boot process by invoking an int0x19 in 16bit mode. @@ -218,70 +205,34 @@ static void maininit(void) { - // Setup romfile items. - qemu_cfg_romfile_setup(); - coreboot_cbfs_setup(); - - // Setup ivt/bda/ebda - init_ivt(); - init_bda(); - - // Init base pc hardware. - pic_setup(); - timer_setup(); - mathcp_setup(); - - // Initialize mtrr - mtrr_setup(); + // Initialize internal interfaces. + interface_init(); - // Initialize pci - pci_setup(); - smm_init(); - - // Setup Xen hypercalls - xen_init_hypercalls(); - - // Initialize internal tables - boot_setup(); + // Setup platform devices. + platform_hardware_setup(); // Start hardware initialization (if optionrom threading) - if (CONFIG_THREADS && CONFIG_THREAD_OPTIONROMS) - init_hw(); - - // Find and initialize other cpus - smp_probe(); - - // Setup interfaces that option roms may need - bios32_setup(); - pmm_setup(); - pnp_setup(); - kbd_setup(); - mouse_setup(); - init_bios_tables(); + if (CONFIG_THREAD_OPTIONROMS) + device_hardware_setup(); // Run vga option rom - vga_setup(); + vgarom_setup(); // Do hardware initialization (if running synchronously) - if (!CONFIG_THREADS || !CONFIG_THREAD_OPTIONROMS) { - init_hw(); + if (!CONFIG_THREAD_OPTIONROMS) { + device_hardware_setup(); wait_threads(); } // Run option roms optionrom_setup(); - // Run BCVs and show optional boot menu - boot_prep(); - - // Finalize data structures before boot - cdemu_setup(); - pmm_finalize(); - malloc_finalize(); - memmap_finalize(); + // Allow user to modify overall boot order. + interactive_bootmenu(); + wait_threads(); - // Setup bios checksum. - BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE); + // Prepare for boot. + prepareboot(); // Write protect bios memory. make_bios_readonly(); @@ -295,21 +246,6 @@ * POST entry and code relocation ****************************************************************/ -// Relocation fixup code that runs at new address after relocation complete. -static void -afterReloc(void) -{ - // Running at new code address - do code relocation fixups - malloc_fixupreloc(); - - // Move low-memory initial variable content to new location. - extern u8 datalow_start[], datalow_end[], final_datalow_start[]; - memmove(final_datalow_start, datalow_start, datalow_end - datalow_start); - - // Run main code - maininit(); -} - // Update given relocs for the code at 'dest' with a given 'delta' static void updateRelocs(void *dest, u32 *rstart, u32 *rend, u32 delta) @@ -319,14 +255,15 @@ *((u32*)(dest + *reloc)) += delta; } -// Relocate init code and then call maininit() at new address. -static void -reloc_init(void) -{ - if (!CONFIG_RELOCATE_INIT) { - maininit(); - return; - } +// Relocate init code and then call a function at its new address. +// The passed function should be in the "init" section and must not +// return. +void __noreturn +reloc_preinit(void *f, void *arg) +{ + void (*func)(void *) __noreturn = f; + if (!CONFIG_RELOCATE_INIT) + func(arg); // Symbols populated by the build. extern u8 code32flat_start[]; extern u8 _reloc_min_align; @@ -334,8 +271,6 @@ extern u32 _reloc_rel_start[], _reloc_rel_end[]; extern u32 _reloc_init_start[], _reloc_init_end[]; extern u8 code32init_start[], code32init_end[]; - extern u32 _reloc_datalow_start[], _reloc_datalow_end[]; - extern u8 datalow_start[], datalow_end[], final_datalow_start[]; // Allocate space for init code. u32 initsize = code32init_end - code32init_start; @@ -345,10 +280,6 @@ panic("No space for init relocation.\n"); // Copy code and update relocs (init absolute, init relative, and runtime) - dprintf(1, "Relocating low data from %p to %p (size %d)\n" - , datalow_start, final_datalow_start, datalow_end - datalow_start); - updateRelocs(code32flat_start, _reloc_datalow_start, _reloc_datalow_end - , final_datalow_start - datalow_start); dprintf(1, "Relocating init from %p to %p (size %d)\n" , code32init_start, codedest, initsize); s32 delta = codedest - (void*)code32init_start; @@ -356,26 +287,25 @@ updateRelocs(codedest, _reloc_abs_start, _reloc_abs_end, delta); updateRelocs(codedest, _reloc_rel_start, _reloc_rel_end, -delta); updateRelocs(code32flat_start, _reloc_init_start, _reloc_init_end, delta); + if (f >= (void*)code32init_start && f < (void*)code32init_end) + func = f + delta; - // Call maininit() in relocated code. - void (*func)(void) = (void*)afterReloc + delta; + // Call function in relocated code. barrier(); - func(); + func(arg); } -// Setup for code relocation and then call reloc_init +// Setup for code relocation and then relocate. void VISIBLE32INIT dopost(void) { - HaveRunPost = 1; - // Detect ram and setup internal malloc. - qemu_cfg_port_probe(); - ram_probe(); - malloc_setup(); + qemu_preinit(); + coreboot_preinit(); + malloc_preinit(); // Relocate initialization code and call maininit(). - reloc_init(); + reloc_preinit(maininit, NULL); } // Entry point for Power On Self Test (POST) - the BIOS initilization @@ -384,20 +314,14 @@ void VISIBLE32FLAT handle_post(void) { - debug_serial_setup(); - dprintf(1, "Start bios (version %s)\n", VERSION); - - // Enable CPU caching - setcr0(getcr0() & ~(CR0_CD|CR0_NW)); - - // Clear CMOS reboot flag. - outb_cmos(0, CMOS_RESET_CODE); + if (!CONFIG_QEMU && !CONFIG_COREBOOT) + return; - // Make sure legacy DMA isn't running. - init_dma(); + debug_preinit(); + dprintf(1, "Start bios (version %s)\n", VERSION); // Check if we are running under Xen. - xen_probe(); + xen_preinit(); // Allow writes to modify bios area (0xf0000) make_bios_writable(); diff -Nru seabios-1.7.1/src/ps2port.c seabios-1.7.4/src/ps2port.c --- seabios-1.7.1/src/ps2port.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ps2port.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,504 +0,0 @@ -// Support for handling the PS/2 mouse/keyboard ports. -// -// Copyright (C) 2008 Kevin O'Connor -// Several ideas taken from code Copyright (c) 1999-2004 Vojtech Pavlik -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "ioport.h" // inb -#include "util.h" // dprintf -#include "biosvar.h" // GET_LOW -#include "ps2port.h" // ps2_kbd_command -#include "pic.h" // eoi_pic1 - - -/**************************************************************** - * Low level i8042 commands. - ****************************************************************/ - -// Timeout value. -#define I8042_CTL_TIMEOUT 10000 - -#define I8042_BUFFER_SIZE 16 - -static int -i8042_wait_read(void) -{ - dprintf(7, "i8042_wait_read\n"); - int i; - for (i=0; i> 8) & 0xf; - int send = (command >> 12) & 0xf; - - // Send the command. - int ret = i8042_wait_write(); - if (ret) - return ret; - outb(command, PORT_PS2_STATUS); - - // Send parameters (if any). - int i; - for (i = 0; i < send; i++) { - ret = i8042_wait_write(); - if (ret) - return ret; - outb(param[i], PORT_PS2_DATA); - } - - // Receive parameters (if any). - for (i = 0; i < receive; i++) { - ret = i8042_wait_read(); - if (ret) - return ret; - param[i] = inb(PORT_PS2_DATA); - dprintf(7, "i8042 param=%x\n", param[i]); - } - - return 0; -} - -static int -i8042_command(int command, u8 *param) -{ - dprintf(7, "i8042_command cmd=%x\n", command); - int ret = __i8042_command(command, param); - if (ret) - dprintf(2, "i8042 command %x failed\n", command); - return ret; -} - -static int -i8042_kbd_write(u8 c) -{ - dprintf(7, "i8042_kbd_write c=%d\n", c); - int ret = i8042_wait_write(); - if (! ret) - outb(c, PORT_PS2_DATA); - return ret; -} - -static int -i8042_aux_write(u8 c) -{ - return i8042_command(I8042_CMD_AUX_SEND, &c); -} - -void -i8042_reboot(void) -{ - if (! CONFIG_PS2PORT) - return; - int i; - for (i=0; i<10; i++) { - i8042_wait_write(); - udelay(50); - outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */ - udelay(50); - } -} - - -/**************************************************************** - * Device commands. - ****************************************************************/ - -#define PS2_RET_ACK 0xfa -#define PS2_RET_NAK 0xfe - -static int -ps2_recvbyte(int aux, int needack, int timeout) -{ - u64 end = calc_future_tsc(timeout); - for (;;) { - u8 status = inb(PORT_PS2_STATUS); - if (status & I8042_STR_OBF) { - u8 data = inb(PORT_PS2_DATA); - dprintf(7, "ps2 read %x\n", data); - - if (!!(status & I8042_STR_AUXDATA) == aux) { - if (!needack) - return data; - if (data == PS2_RET_ACK) - return data; - if (data == PS2_RET_NAK) { - dprintf(1, "Got ps2 nak (status=%x)\n", status); - return data; - } - } - - // This data not part of command - just discard it. - dprintf(1, "Discarding ps2 data %02x (status=%02x)\n", data, status); - } - - if (check_tsc(end)) { - // Don't warn on second byte of a reset - if (timeout > 100) - warn_timeout(); - return -1; - } - yield(); - } -} - -static int -ps2_sendbyte(int aux, u8 command, int timeout) -{ - dprintf(7, "ps2_sendbyte aux=%d cmd=%x\n", aux, command); - int ret; - if (aux) - ret = i8042_aux_write(command); - else - ret = i8042_kbd_write(command); - if (ret) - return ret; - - // Read ack. - ret = ps2_recvbyte(aux, 1, timeout); - if (ret < 0) - return ret; - if (ret != PS2_RET_ACK) - return -1; - - return 0; -} - -u8 Ps2ctr VARLOW; - -static int -__ps2_command(int aux, int command, u8 *param) -{ - int ret2; - int receive = (command >> 8) & 0xf; - int send = (command >> 12) & 0xf; - - // Disable interrupts and keyboard/mouse. - u8 ps2ctr = GET_LOW(Ps2ctr); - u8 newctr = ((ps2ctr | I8042_CTR_AUXDIS | I8042_CTR_KBDDIS) - & ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT)); - dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr); - int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); - if (ret) - return ret; - - // Flush any interrupts already pending. - yield(); - - // Enable port command is being sent to. - if (aux) - newctr &= ~I8042_CTR_AUXDIS; - else - newctr &= ~I8042_CTR_KBDDIS; - ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); - if (ret) - goto fail; - - if (command == ATKBD_CMD_RESET_BAT) { - // Reset is special wrt timeouts and bytes received. - - // Send command. - ret = ps2_sendbyte(aux, command, 1000); - if (ret) - goto fail; - - // Receive parameters. - ret = ps2_recvbyte(aux, 0, 4000); - if (ret < 0) - goto fail; - param[0] = ret; - ret = ps2_recvbyte(aux, 0, 100); - if (ret < 0) - // Some devices only respond with one byte on reset. - ret = 0; - param[1] = ret; - } else if (command == ATKBD_CMD_GETID) { - // Getid is special wrt bytes received. - - // Send command. - ret = ps2_sendbyte(aux, command, 200); - if (ret) - goto fail; - - // Receive parameters. - ret = ps2_recvbyte(aux, 0, 500); - if (ret < 0) - goto fail; - param[0] = ret; - if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d - || ret == 0x60 || ret == 0x47) { - // These ids (keyboards) return two bytes. - ret = ps2_recvbyte(aux, 0, 500); - if (ret < 0) - goto fail; - param[1] = ret; - } else { - param[1] = 0; - } - } else { - // Send command. - ret = ps2_sendbyte(aux, command, 200); - if (ret) - goto fail; - - // Send parameters (if any). - int i; - for (i = 0; i < send; i++) { - ret = ps2_sendbyte(aux, param[i], 200); - if (ret) - goto fail; - } - - // Receive parameters (if any). - for (i = 0; i < receive; i++) { - ret = ps2_recvbyte(aux, 0, 500); - if (ret < 0) - goto fail; - param[i] = ret; - } - } - - ret = 0; - -fail: - // Restore interrupts and keyboard/mouse. - ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr); - if (ret2) - return ret2; - - return ret; -} - -static int -ps2_command(int aux, int command, u8 *param) -{ - dprintf(7, "ps2_command aux=%d cmd=%x\n", aux, command); - int ret = __ps2_command(aux, command, param); - if (ret) - dprintf(2, "ps2 command %x failed (aux=%d)\n", command, aux); - return ret; -} - -int -ps2_kbd_command(int command, u8 *param) -{ - if (! CONFIG_PS2PORT) - return -1; - return ps2_command(0, command, param); -} - -int -ps2_mouse_command(int command, u8 *param) -{ - if (! CONFIG_PS2PORT) - return -1; - - // Update ps2ctr for mouse enable/disable. - if (command == PSMOUSE_CMD_ENABLE || command == PSMOUSE_CMD_DISABLE) { - u8 ps2ctr = GET_LOW(Ps2ctr); - if (command == PSMOUSE_CMD_ENABLE) - ps2ctr = (ps2ctr | I8042_CTR_AUXINT) & ~I8042_CTR_AUXDIS; - else - ps2ctr = (ps2ctr | I8042_CTR_AUXDIS) & ~I8042_CTR_AUXINT; - SET_LOW(Ps2ctr, ps2ctr); - } - - return ps2_command(1, command, param); -} - - -/**************************************************************** - * IRQ handlers - ****************************************************************/ - -// INT74h : PS/2 mouse hardware interrupt -void VISIBLE16 -handle_74(void) -{ - if (! CONFIG_PS2PORT) - return; - - debug_isr(DEBUG_ISR_74); - - u8 v = inb(PORT_PS2_STATUS); - if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA)) - != (I8042_STR_OBF|I8042_STR_AUXDATA)) { - dprintf(1, "ps2 mouse irq but no mouse data.\n"); - goto done; - } - v = inb(PORT_PS2_DATA); - - if (!(GET_LOW(Ps2ctr) & I8042_CTR_AUXINT)) - // Interrupts not enabled. - goto done; - - process_mouse(v); - -done: - eoi_pic2(); -} - -// INT09h : Keyboard Hardware Service Entry Point -void VISIBLE16 -handle_09(void) -{ - if (! CONFIG_PS2PORT) - return; - - debug_isr(DEBUG_ISR_09); - - // read key from keyboard controller - u8 v = inb(PORT_PS2_STATUS); - if (v & I8042_STR_AUXDATA) { - dprintf(1, "ps2 keyboard irq but found mouse data?!\n"); - goto done; - } - v = inb(PORT_PS2_DATA); - - if (!(GET_LOW(Ps2ctr) & I8042_CTR_KBDINT)) - // Interrupts not enabled. - goto done; - - process_key(v); - - // Some old programs expect ISR to turn keyboard back on. - i8042_command(I8042_CMD_KBD_ENABLE, NULL); - -done: - eoi_pic1(); -} - - -/**************************************************************** - * Setup - ****************************************************************/ - -static void -keyboard_init(void *data) -{ - /* flush incoming keys */ - int ret = i8042_flush(); - if (ret) - return; - - // Controller self-test. - u8 param[2]; - ret = i8042_command(I8042_CMD_CTL_TEST, param); - if (ret) - return; - if (param[0] != 0x55) { - dprintf(1, "i8042 self test failed (got %x not 0x55)\n", param[0]); - return; - } - - // Controller keyboard test. - ret = i8042_command(I8042_CMD_KBD_TEST, param); - if (ret) - return; - if (param[0] != 0x00) { - dprintf(1, "i8042 keyboard test failed (got %x not 0x00)\n", param[0]); - return; - } - - // Disable keyboard and mouse events. - SET_LOW(Ps2ctr, I8042_CTR_KBDDIS | I8042_CTR_AUXDIS); - - - /* ------------------- keyboard side ------------------------*/ - /* reset keyboard and self test (keyboard side) */ - int spinupdelay = romfile_loadint("etc/ps2-keyboard-spinup", 0); - u64 end = calc_future_tsc(spinupdelay); - for (;;) { - ret = ps2_kbd_command(ATKBD_CMD_RESET_BAT, param); - if (!ret) - break; - if (check_tsc(end)) { - if (spinupdelay) - warn_timeout(); - return; - } - yield(); - } - if (param[0] != 0xaa) { - dprintf(1, "keyboard self test failed (got %x not 0xaa)\n", param[0]); - return; - } - - /* Disable keyboard */ - ret = ps2_kbd_command(ATKBD_CMD_RESET_DIS, NULL); - if (ret) - return; - - // Set scancode command (mode 2) - param[0] = 0x02; - ret = ps2_kbd_command(ATKBD_CMD_SSCANSET, param); - if (ret) - return; - - // Keyboard Mode: disable mouse, scan code convert, enable kbd IRQ - SET_LOW(Ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT); - - /* Enable keyboard */ - ret = ps2_kbd_command(ATKBD_CMD_ENABLE, NULL); - if (ret) - return; - - dprintf(1, "PS2 keyboard initialized\n"); -} - -void -ps2port_setup(void) -{ - ASSERT32FLAT(); - if (! CONFIG_PS2PORT) - return; - dprintf(3, "init ps2port\n"); - - enable_hwirq(1, FUNC16(entry_09)); - enable_hwirq(12, FUNC16(entry_74)); - - run_thread(keyboard_init, NULL); -} diff -Nru seabios-1.7.1/src/ps2port.h seabios-1.7.4/src/ps2port.h --- seabios-1.7.1/src/ps2port.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ps2port.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -// Basic ps2 port (keyboard/mouse) command handling. -#ifndef __PS2PORT_H -#define __PS2PORT_H - -#include "types.h" // u8 - -// Standard commands. -#define I8042_CMD_CTL_RCTR 0x0120 -#define I8042_CMD_CTL_WCTR 0x1060 -#define I8042_CMD_CTL_TEST 0x01aa - -#define I8042_CMD_KBD_TEST 0x01ab -#define I8042_CMD_KBD_DISABLE 0x00ad -#define I8042_CMD_KBD_ENABLE 0x00ae - -#define I8042_CMD_AUX_DISABLE 0x00a7 -#define I8042_CMD_AUX_ENABLE 0x00a8 -#define I8042_CMD_AUX_SEND 0x10d4 - -// Keyboard commands -#define ATKBD_CMD_SETLEDS 0x10ed -#define ATKBD_CMD_SSCANSET 0x10f0 -#define ATKBD_CMD_GETID 0x02f2 -#define ATKBD_CMD_ENABLE 0x00f4 -#define ATKBD_CMD_RESET_DIS 0x00f5 -#define ATKBD_CMD_RESET_BAT 0x02ff - -// Mouse commands -#define PSMOUSE_CMD_SETSCALE11 0x00e6 -#define PSMOUSE_CMD_SETSCALE21 0x00e7 -#define PSMOUSE_CMD_SETRES 0x10e8 -#define PSMOUSE_CMD_GETINFO 0x03e9 -#define PSMOUSE_CMD_GETID 0x02f2 -#define PSMOUSE_CMD_SETRATE 0x10f3 -#define PSMOUSE_CMD_ENABLE 0x00f4 -#define PSMOUSE_CMD_DISABLE 0x00f5 -#define PSMOUSE_CMD_RESET_BAT 0x02ff - -// Status register bits. -#define I8042_STR_PARITY 0x80 -#define I8042_STR_TIMEOUT 0x40 -#define I8042_STR_AUXDATA 0x20 -#define I8042_STR_KEYLOCK 0x10 -#define I8042_STR_CMDDAT 0x08 -#define I8042_STR_MUXERR 0x04 -#define I8042_STR_IBF 0x02 -#define I8042_STR_OBF 0x01 - -// Control register bits. -#define I8042_CTR_KBDINT 0x01 -#define I8042_CTR_AUXINT 0x02 -#define I8042_CTR_IGNKEYLOCK 0x08 -#define I8042_CTR_KBDDIS 0x10 -#define I8042_CTR_AUXDIS 0x20 -#define I8042_CTR_XLATE 0x40 - -// functions -void i8042_reboot(void); -int ps2_kbd_command(int command, u8 *param); -int ps2_mouse_command(int command, u8 *param); -void ps2port_setup(void); - -#endif // ps2port.h diff -Nru seabios-1.7.1/src/ramdisk.c seabios-1.7.4/src/ramdisk.c --- seabios-1.7.1/src/ramdisk.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ramdisk.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -// Code for emulating a drive via high-memory accesses. -// -// Copyright (C) 2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "disk.h" // process_ramdisk_op -#include "util.h" // dprintf -#include "memmap.h" // add_e820 -#include "biosvar.h" // GET_GLOBAL -#include "bregs.h" // struct bregs -#include "boot.h" // boot_add_floppy - -void -ramdisk_setup(void) -{ - if (!CONFIG_FLASH_FLOPPY) - return; - - // Find image. - struct romfile_s *file = romfile_findprefix("floppyimg/", NULL); - if (!file) - return; - const char *filename = file->name; - u32 size = file->size; - dprintf(3, "Found floppy file %s of size %d\n", filename, size); - int ftype = find_floppy_type(size); - if (ftype < 0) { - dprintf(3, "No floppy type found for ramdisk size\n"); - return; - } - - // Allocate ram for image. - void *pos = memalign_tmphigh(PAGE_SIZE, size); - if (!pos) { - warn_noalloc(); - return; - } - add_e820((u32)pos, size, E820_RESERVED); - - // Copy image into ram. - int ret = file->copy(file, pos, size); - if (ret < 0) - return; - - // Setup driver. - struct drive_s *drive_g = init_floppy((u32)pos, ftype); - if (!drive_g) - return; - drive_g->type = DTYPE_RAMDISK; - dprintf(1, "Mapping CBFS floppy %s to addr %p\n", filename, pos); - char *desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", &filename[10]); - boot_add_floppy(drive_g, desc, bootprio_find_named_rom(filename, 0)); -} - -static int -ramdisk_copy(struct disk_op_s *op, int iswrite) -{ - u32 offset = GET_GLOBAL(op->drive_g->cntl_id); - offset += (u32)op->lba * DISK_SECTOR_SIZE; - u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl); - u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset); - - u64 gdt[6]; - if (iswrite) { - gdt[2] = opd; - gdt[3] = ramd; - } else { - gdt[2] = ramd; - gdt[3] = opd; - } - - // Call int 1587 to copy data. - struct bregs br; - memset(&br, 0, sizeof(br)); - br.flags = F_CF|F_IF; - br.ah = 0x87; - br.es = GET_SEG(SS); - br.si = (u32)gdt; - br.cx = op->count * DISK_SECTOR_SIZE / 2; - call16_int(0x15, &br); - - if (br.flags & F_CF) - return DISK_RET_EBADTRACK; - return DISK_RET_SUCCESS; -} - -int -process_ramdisk_op(struct disk_op_s *op) -{ - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH || !CONFIG_FLASH_FLOPPY) - return 0; - - switch (op->command) { - case CMD_READ: - return ramdisk_copy(op, 0); - case CMD_WRITE: - return ramdisk_copy(op, 1); - case CMD_VERIFY: - case CMD_FORMAT: - case CMD_RESET: - return DISK_RET_SUCCESS; - default: - op->count = 0; - return DISK_RET_EPARAM; - } -} diff -Nru seabios-1.7.1/src/resume.c seabios-1.7.4/src/resume.c --- seabios-1.7.1/src/resume.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/resume.c 2013-12-23 15:40:06.000000000 +0000 @@ -4,43 +4,33 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "util.h" // dprintf -#include "ioport.h" // outb -#include "pic.h" // eoi_pic2 -#include "biosvar.h" // struct bios_data_area_s #include "bregs.h" // struct bregs -#include "acpi.h" // find_resume_vector -#include "ps2port.h" // i8042_reboot -#include "pci.h" // pci_reboot -#include "cmos.h" // inb_cmos +#include "config.h" // CONFIG_* +#include "farptr.h" // FLATPTR_TO_SEGOFF +#include "hw/pci.h" // pci_reboot +#include "hw/pic.h" // pic_eoi2 +#include "hw/ps2port.h" // i8042_reboot +#include "hw/rtc.h" // rtc_read +#include "output.h" // dprintf +#include "stacks.h" // farcall16big +#include "std/bda.h" // struct bios_data_area_s +#include "string.h" // memset +#include "util.h" // dma_setup // Indicator if POST phase has been run. -int HaveRunPost VAR16VISIBLE; - -// Reset DMA controller -void -init_dma(void) -{ - // first reset the DMA controllers - outb(0, PORT_DMA1_MASTER_CLEAR); - outb(0, PORT_DMA2_MASTER_CLEAR); - - // then initialize the DMA controllers - outb(0xc0, PORT_DMA2_MODE_REG); - outb(0x00, PORT_DMA2_MASK_REG); -} +int HaveRunPost VARFSEG; // Handler for post calls that look like a resume. void VISIBLE16 handle_resume(void) { ASSERT16(); - debug_serial_setup(); - int status = inb_cmos(CMOS_RESET_CODE); - outb_cmos(0, CMOS_RESET_CODE); + debug_preinit(); + int status = rtc_read(CMOS_RESET_CODE); + rtc_write(CMOS_RESET_CODE, 0); dprintf(1, "In resume (status=%d)\n", status); - init_dma(); + dma_setup(); switch (status) { case 0x01 ... 0x04: @@ -49,7 +39,7 @@ case 0x05: // flush keyboard (issue EOI) and jump via 40h:0067h - eoi_pic2(); + pic_eoi2(); // NO BREAK case 0x0a: #define BDA_JUMP (((struct bios_data_area_s *)0)->jump) @@ -109,9 +99,9 @@ } pic_setup(); - smm_init(); + smm_setup(); - s3_resume_vga_init(); + s3_resume_vga(); make_bios_readonly(); @@ -123,18 +113,26 @@ farcall16big(&br); } +u8 HaveAttemptedReboot VARLOW; + // Attempt to invoke a hard-reboot. static void tryReboot(void) { + if (HaveAttemptedReboot) { + // Hard reboot has failed - try to shutdown machine. + dprintf(1, "Unable to hard-reboot machine - attempting shutdown.\n"); + apm_shutdown(); + } + HaveAttemptedReboot = 1; + dprintf(1, "Attempting a hard reboot\n"); // Setup for reset on qemu. - if (! CONFIG_COREBOOT) { - qemu_prep_reset(); - if (HaveRunPost) - apm_shutdown(); - } + qemu_prep_reset(); + + // Reboot using ACPI RESET_REG + acpi_reboot(); // Try keyboard controller reboot. i8042_reboot(); diff -Nru seabios-1.7.1/src/romfile.c seabios-1.7.4/src/romfile.c --- seabios-1.7.1/src/romfile.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/romfile.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,13 +5,17 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "config.h" // CONFIG_* -#include "util.h" // dprintf +#include "malloc.h" // free +#include "output.h" // dprintf +#include "romfile.h" // struct romfile_s +#include "string.h" // memcmp -static struct romfile_s *RomfileRoot; +static struct romfile_s *RomfileRoot VARVERIFY32INIT; void romfile_add(struct romfile_s *file) { + dprintf(3, "Add romfile: %s (size=%d)\n", file->name, file->size); file->next = RomfileRoot; RomfileRoot = file; } diff -Nru seabios-1.7.1/src/romfile.h seabios-1.7.4/src/romfile.h --- seabios-1.7.1/src/romfile.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/romfile.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef __ROMFILE_H +#define __ROMFILE_H + +#include "types.h" // u32 + +// romfile.c +struct romfile_s { + struct romfile_s *next; + char name[128]; + u32 size; + int (*copy)(struct romfile_s *file, void *dest, u32 maxlen); +}; +void romfile_add(struct romfile_s *file); +struct romfile_s *romfile_findprefix(const char *prefix, struct romfile_s *prev); +struct romfile_s *romfile_find(const char *name); +void *romfile_loadfile(const char *name, int *psize); +u64 romfile_loadint(const char *name, u64 defval); + +#endif // romfile.h diff -Nru seabios-1.7.1/src/romlayout.S seabios-1.7.4/src/romlayout.S --- seabios-1.7.1/src/romlayout.S 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/romlayout.S 2013-12-23 15:40:06.000000000 +0000 @@ -5,16 +5,16 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "config.h" // CONFIG_* -#include "ioport.h" // PORT_A20 -#include "bregs.h" // CR0_* -#include "cmos.h" // CMOS_RESET_CODE #include "asm-offsets.h" // BREGS_* +#include "config.h" // CONFIG_* #include "entryfuncs.S" // ENTRY_* +#include "hw/ps2port.h" // PORT_A20 +#include "hw/rtc.h" // CMOS_RESET_CODE +#include "x86.h" // CR0_* /**************************************************************** - * Call trampolines + * 16bit / 32bit call trampolines ****************************************************************/ // Place CPU into 32bit mode from 16bit mode. @@ -127,32 +127,81 @@ movl %ecx, %eax jmpl *%edx +// Call a 16bit SeaBIOS function from SeaBIOS 32bit C code. +// %ecx = calling function +// Clobbers: %ecx, %edx, flags, segment registers, idt/gdt + DECLFUNC __call16 + .global __call16big + .code32 +__call16: + pushl %edx + pushl %ecx + movl $1f, %edx + jmp transition16 +__call16big: + pushl %edx + pushl %ecx + movl $1f, %edx + jmp transition16big + + // Make call. + .code16gcc +1: movl $_zonelow_seg, %edx // Adjust %ds, %ss, and %esp + movl %edx, %ds + movzwl StackSeg, %edx + movl %edx, %ecx + shll $4, %ecx + movl %edx, %ss + subl %ecx, %esp + movl %edx, %ds + + popl %ecx // Call function + popl %edx + calll *%ecx + + movl %ss, %edx // Readjust %esp + shll $4, %edx + addl %edx, %esp + + // Return via transition32 + movl $(2f + BUILD_BIOS_ADDR), %edx + jmp transition32 + .code32 +2: retl + + +/**************************************************************** + * External calling trampolines + ****************************************************************/ + // Far call a 16bit function from 16bit mode with a specified cpu register state -// %es:%eax = address of struct bregs -// Clobbers: %e[bcd]x, %e[ds]i, flags +// %eax = address of struct bregs, %edx = segment of struct bregs +// Clobbers: %e[bc]x, %e[ds]i, flags + .code16gcc DECLFUNC __farcall16 __farcall16: - // Save %eax, %ebp + // Save %edx/%eax, %ebp pushl %ebp pushl %eax - pushl %es + pushl %edx // Setup for iretw call + movl %edx, %ds pushw %cs pushw $1f // return point - pushw %es:BREGS_flags(%eax) // flags - pushl %es:BREGS_code(%eax) // CS:IP + pushw BREGS_flags(%eax) // flags + pushl BREGS_code(%eax) // CS:IP // Load calling registers. - movl %es:BREGS_edi(%eax), %edi - movl %es:BREGS_esi(%eax), %esi - movl %es:BREGS_ebp(%eax), %ebp - movl %es:BREGS_ebx(%eax), %ebx - movl %es:BREGS_edx(%eax), %edx - movl %es:BREGS_ecx(%eax), %ecx - movw %es:BREGS_ds(%eax), %ds - pushl %es:BREGS_eax(%eax) - movw %es:BREGS_es(%eax), %es + movl BREGS_edi(%eax), %edi + movl BREGS_esi(%eax), %esi + movl BREGS_ebp(%eax), %ebp + movl BREGS_ebx(%eax), %ebx + movl BREGS_edx(%eax), %edx + movl BREGS_ecx(%eax), %ecx + movw BREGS_es(%eax), %es + pushl BREGS_eax(%eax) + movw BREGS_ds(%eax), %ds popl %eax // Invoke call @@ -162,55 +211,32 @@ pushfw cli cld - pushw %es + pushw %ds pushl %eax - movw 0x08(%esp), %es + movw 0x08(%esp), %ds movl 0x0c(%esp), %eax - popl %es:BREGS_eax(%eax) - popw %es:BREGS_es(%eax) - popw %es:BREGS_flags(%eax) + popl BREGS_eax(%eax) + popw BREGS_es(%eax) + popw BREGS_flags(%eax) // Store remaining registers - movl %edi, %es:BREGS_edi(%eax) - movl %esi, %es:BREGS_esi(%eax) - movl %ebp, %es:BREGS_ebp(%eax) - movl %ebx, %es:BREGS_ebx(%eax) - movl %edx, %es:BREGS_edx(%eax) - movl %ecx, %es:BREGS_ecx(%eax) - movw %ds, %es:BREGS_ds(%eax) + movl %edi, BREGS_edi(%eax) + movl %esi, BREGS_esi(%eax) + movl %ebp, BREGS_ebp(%eax) + movl %ebx, BREGS_ebx(%eax) + movl %edx, BREGS_edx(%eax) + movl %ecx, BREGS_ecx(%eax) + movw %es, BREGS_ds(%eax) movw %ss, %cx movw %cx, %ds // Restore %ds == %ss - // Remove %es/%eax, restore %ebp - popl %eax + // Remove %edx/%eax, restore %ebp + popl %edx popl %eax popl %ebp retl -// Call a 16bit SeaBIOS function from SeaBIOS 32bit C code. -// %ebx = calling function -// Clobbers: %ecx, %edx, flags, segment registers, idt/gdt - DECLFUNC __call16 - .global __call16big - .code32 -__call16: - movl $1f, %edx - jmp transition16 -__call16big: - movl $1f, %edx - jmp transition16big - - // Make call. - .code16gcc -1: calll *%ebx - // Return via transition32 - movl $(2f + BUILD_BIOS_ADDR), %edx - jmp transition32 - .code32 -2: retl - - .code16gcc // IRQ trampolines .macro IRQ_TRAMPOLINE num DECLFUNC irq_trampoline_0x\num @@ -241,7 +267,7 @@ cli cld // Use the ExtraStack in low mem. - movl $_datalow_seg, %eax + movl $_zonelow_seg, %eax movw %ax, %ds movw %ax, %ss movl $ExtraStack + BUILD_EXTRA_STACK_SIZE, %esp @@ -334,20 +360,27 @@ popfl lretl -// PCI-BIOS 32bit entry point +// PCI-BIOS entry points DECLFUNC entry_pcibios32 entry_pcibios32: pushfl pushl %gs // Backup %gs and set %gs=%ds pushl %ds popl %gs - ENTRY_ARG_ESP _cfunc32seg_handle_pcibios32 + ENTRY_ARG_ESP _cfunc32seg_handle_pcibios popl %gs popfl lretl + .code16gcc + DECLFUNC entry_pcibios16 +entry_pcibios16: + ENTRY_ARG handle_pcibios + iretw + // BIOS32 support - EXPORTFUNC entry_bios32 + .code32 + DECLFUNC entry_bios32 entry_bios32: pushfl #if CONFIG_PCIBIOS @@ -384,6 +417,52 @@ .code16gcc +// UEFI Compatibility Support Module (CSM) entry point + EXPORTFUNC entry_csm +entry_csm: + // Backup register state + pushfw + cli + cld + pushl %eax // dummy + PUSHBREGS + + // Backup stack location and convert to a "flat pointer" + movl %ss, %eax + movw %ax, BREGS_code+2(%esp) // Store %ss in bregs->code.seg + shll $4, %eax + addl %esp, %eax + + // Change to BUILD_STACK_ADDR stack + xorl %ebx, %ebx + movw %bx, %ss + movl $BUILD_STACK_ADDR, %esp + + // Jump to 32bit mode and call handle_csm(bregs) + movl $_cfunc32flat_handle_csm, %edx + jmp transition32 + + DECLFUNC __csm_return + .code32 +__csm_return: + movl $1f, %edx + jmp transition16big + .code16gcc + + // Switch back to original stack +1: movzwl BREGS_code+2(%eax), %edx + movl %edx, %ecx + shll $4, %ecx + subl %ecx, %eax + movl %edx, %ss + movl %eax, %esp + + // Restore register state and return. + POPBREGS + addw $4, %sp // pop dummy + popfw + lretw + /**************************************************************** * Interrupt entry points @@ -396,7 +475,7 @@ cld pushw %ds // Set %ds:%eax to space on ExtraStack pushl %eax - movl $_datalow_seg, %eax + movl $_zonelow_seg, %eax movl %eax, %ds movl StackPos, %eax subl $24, %eax @@ -407,7 +486,6 @@ popl %ecx movl %edx, 12(%eax) movl %esp, 16(%eax) - movzwl %sp, %esp movw %ss, 20(%eax) movw %ds, %dx // Setup %ss/%esp and call function @@ -427,6 +505,57 @@ popw %ds iretw + // Main entry point for interrupts handled on extra stack + DECLFUNC irqentry_arg_extrastack +irqentry_arg_extrastack: + cli + cld + pushw %ds // Set %ds:%eax to space on ExtraStack + pushl %eax + movl $_zonelow_seg, %eax + movl %eax, %ds + movl StackPos, %eax + subl $BREGS_size+8, %eax + popl BREGS_eax(%eax) // Backup registers + popw BREGS_ds(%eax) + movl %edi, BREGS_edi(%eax) + movl %esi, BREGS_esi(%eax) + movl %ebp, BREGS_ebp(%eax) + movl %ebx, BREGS_ebx(%eax) + movl %edx, BREGS_edx(%eax) + movl %ecx, BREGS_ecx(%eax) + popl %ecx + movw %es, BREGS_es(%eax) + movl %esp, BREGS_size+0(%eax) + movw %ss, BREGS_size+4(%eax) + popl BREGS_code(%eax) + popw BREGS_flags(%eax) + + movw %ds, %dx // Setup %ss/%esp and call function + movw %dx, %ss + movl %eax, %esp + calll *%ecx + + movl %esp, %eax // Restore registers and return + movw BREGS_size+4(%eax), %ss + movl BREGS_size+0(%eax), %esp + popl %edx + popw %dx + pushw BREGS_flags(%eax) + pushl BREGS_code(%eax) + movl BREGS_edi(%eax), %edi + movl BREGS_esi(%eax), %esi + movl BREGS_ebp(%eax), %ebp + movl BREGS_ebx(%eax), %ebx + movl BREGS_edx(%eax), %edx + movl BREGS_ecx(%eax), %ecx + movw BREGS_es(%eax), %es + pushw BREGS_ds(%eax) + pushl BREGS_eax(%eax) + popl %eax + popw %ds + iretw + // Main entry point for interrupts with args DECLFUNC irqentryarg irqentryarg: @@ -451,7 +580,11 @@ .global entry_\num entry_\num : pushl $ handle_\num +#if CONFIG_ENTRY_EXTRASTACK + jmp irqentry_arg_extrastack +#else jmp irqentryarg +#endif .endm .macro DECL_IRQ_ENTRY_ARG num @@ -554,6 +687,10 @@ // 0xfa6e - vgafont8 in font.c ORG 0xfe6e + .global entry_1a_official +entry_1a_official: + cmpb $0xb1, %ah + je entry_pcibios16 // PCIBIOS calls can be in protected mode IRQ_ENTRY_ARG 1a ORG 0xfea5 diff -Nru seabios-1.7.1/src/serial.c seabios-1.7.4/src/serial.c --- seabios-1.7.1/src/serial.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/serial.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,8 +6,11 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "biosvar.h" // SET_BDA -#include "util.h" // debug_enter #include "bregs.h" // struct bregs +#include "hw/serialio.h" // SEROFF_IER +#include "output.h" // debug_enter +#include "stacks.h" // yield +#include "util.h" // serial_setup /**************************************************************** @@ -91,7 +94,7 @@ u16 addr = getComAddr(regs); if (!addr) return; - u32 end = calc_future_timer_ticks(GET_BDA(com_timeout[regs->dx])); + u32 end = irqtimer_calc_ticks(GET_BDA(com_timeout[regs->dx])); for (;;) { u8 lsr = inb(addr+SEROFF_LSR); if ((lsr & 0x60) == 0x60) { @@ -101,7 +104,7 @@ regs->ah = lsr; break; } - if (check_timer(end)) { + if (irqtimer_check(end)) { // Timed out - can't write data. regs->ah = lsr | 0x80; break; @@ -118,7 +121,7 @@ u16 addr = getComAddr(regs); if (!addr) return; - u32 end = calc_future_timer_ticks(GET_BDA(com_timeout[regs->dx])); + u32 end = irqtimer_calc_ticks(GET_BDA(com_timeout[regs->dx])); for (;;) { u8 lsr = inb(addr+SEROFF_LSR); if (lsr & 0x01) { @@ -127,7 +130,7 @@ regs->ah = lsr; break; } - if (check_timer(end)) { + if (irqtimer_check(end)) { // Timed out - can't read data. regs->ah = lsr | 0x80; break; @@ -234,7 +237,7 @@ if (!addr) return; - u32 end = calc_future_timer_ticks(GET_BDA(lpt_timeout[regs->dx])); + u32 end = irqtimer_calc_ticks(GET_BDA(lpt_timeout[regs->dx])); outb(regs->al, addr); u8 val8 = inb(addr+2); @@ -249,7 +252,7 @@ regs->ah = v ^ 0x48; break; } - if (check_timer(end)) { + if (irqtimer_check(end)) { // Timeout regs->ah = (v ^ 0x48) | 0x01; break; diff -Nru seabios-1.7.1/src/shadow.c seabios-1.7.4/src/shadow.c --- seabios-1.7.1/src/shadow.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/shadow.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ -// Support for enabling/disabling BIOS ram shadowing. -// -// Copyright (C) 2008-2010 Kevin O'Connor -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // memcpy -#include "pci.h" // pci_config_writeb -#include "config.h" // CONFIG_* -#include "pci_ids.h" // PCI_VENDOR_ID_INTEL -#include "pci_regs.h" // PCI_VENDOR_ID -#include "xen.h" // usingXen - -// On the emulators, the bios at 0xf0000 is also at 0xffff0000 -#define BIOS_SRC_OFFSET 0xfff00000 - -#define I440FX_PAM0 0x59 - -// Enable shadowing and copy bios. -static void -__make_bios_writable_intel(u16 bdf, u32 pam0) -{ - // Make ram from 0xc0000-0xf0000 writable - int clear = 0; - int i; - for (i=0; i<6; i++) { - u32 pam = pam0 + 1 + i; - int reg = pci_config_readb(bdf, pam); - if (CONFIG_OPTIONROMS_DEPLOYED && (reg & 0x11) != 0x11) { - // Need to copy optionroms to work around qemu implementation - void *mem = (void*)(BUILD_ROM_START + i * 32*1024); - memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024); - pci_config_writeb(bdf, pam, 0x33); - memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024); - clear = 1; - } else { - pci_config_writeb(bdf, pam, 0x33); - } - } - if (clear) - memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024); - - // Make ram from 0xf0000-0x100000 writable - int reg = pci_config_readb(bdf, pam0); - pci_config_writeb(bdf, pam0, 0x30); - if (reg & 0x10) - // Ram already present. - return; - - // Copy bios. - extern u8 code32flat_start[], code32flat_end[]; - memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET - , code32flat_end - code32flat_start); -} - -static void -make_bios_writable_intel(u16 bdf, u32 pam0) -{ - int reg = pci_config_readb(bdf, pam0); - if (!(reg & 0x10)) { - // QEMU doesn't fully implement the piix shadow capabilities - - // if ram isn't backing the bios segment when shadowing is - // disabled, the code itself wont be in memory. So, run the - // code from the high-memory flash location. - u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET; - void (*func)(u16 bdf, u32 pam0) = (void*)pos; - func(bdf, pam0); - return; - } - // Ram already present - just enable writes - __make_bios_writable_intel(bdf, pam0); -} - -static void -make_bios_readonly_intel(u16 bdf, u32 pam0) -{ - // Flush any pending writes before locking memory. - wbinvd(); - - // Write protect roms from 0xc0000-0xf0000 - u32 romend = rom_get_last(), romtop = rom_get_top(); - int i; - for (i=0; i<6; i++) { - u32 mem = BUILD_ROM_START + i * 32*1024; - u32 pam = pam0 + 1 + i; - if (romend <= mem + 16*1024 || romtop <= mem + 32*1024) { - if (romend > mem && romtop > mem + 16*1024) - pci_config_writeb(bdf, pam, 0x31); - break; - } - pci_config_writeb(bdf, pam, 0x11); - } - - // Write protect 0xf0000-0x100000 - pci_config_writeb(bdf, pam0, 0x10); -} - -static void i440fx_bios_make_readonly(struct pci_device *pci, void *arg) -{ - make_bios_readonly_intel(pci->bdf, I440FX_PAM0); -} - -static const struct pci_device_id dram_controller_make_readonly_tbl[] = { - PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, - i440fx_bios_make_readonly), - PCI_DEVICE_END -}; - -// Make the 0xc0000-0x100000 area read/writable. -void -make_bios_writable(void) -{ - if (CONFIG_COREBOOT || usingXen()) - return; - - dprintf(3, "enabling shadow ram\n"); - - // At this point, statically allocated variables can't be written, - // so do this search manually. - int bdf; - foreachbdf(bdf, 0) { - u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID); - u16 vendor = vendev & 0xffff, device = vendev >> 16; - if (vendor == PCI_VENDOR_ID_INTEL - && device == PCI_DEVICE_ID_INTEL_82441) { - make_bios_writable_intel(bdf, I440FX_PAM0); - return; - } - } - dprintf(1, "Unable to unlock ram - bridge not found\n"); -} - -// Make the BIOS code segment area (0xf0000) read-only. -void -make_bios_readonly(void) -{ - if (CONFIG_COREBOOT || usingXen()) - return; - - dprintf(3, "locking shadow ram\n"); - struct pci_device *pci = pci_find_init_device( - dram_controller_make_readonly_tbl, NULL); - if (!pci) - dprintf(1, "Unable to lock ram - bridge not found\n"); -} - -void -qemu_prep_reset(void) -{ - if (CONFIG_COREBOOT) - return; - // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a - // reset, so do that manually before invoking a hard reset. - make_bios_writable(); - extern u8 code32flat_start[], code32flat_end[]; - memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET - , code32flat_end - code32flat_start); -} diff -Nru seabios-1.7.1/src/smbios.c seabios-1.7.4/src/smbios.c --- seabios-1.7.1/src/smbios.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/smbios.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,523 +0,0 @@ -// smbios table generation (on emulators) -// -// Copyright (C) 2008,2009 Kevin O'Connor -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "paravirt.h" // qemu_cfg_smbios_load_field -#include "smbios.h" // struct smbios_entry_point - -struct smbios_entry_point *SMBiosAddr; - -static void -smbios_entry_point_init(u16 max_structure_size, - u16 structure_table_length, - void *structure_table_address, - u16 number_of_structures) -{ - struct smbios_entry_point *ep = malloc_fseg(sizeof(*ep)); - void *finaltable; - if (structure_table_length <= BUILD_MAX_SMBIOS_FSEG) - // Table is small enough for f-seg - allocate there. This - // works around a bug in JunOS (at least for small SMBIOS tables). - finaltable = malloc_fseg(structure_table_length); - else - finaltable = malloc_high(structure_table_length); - if (!ep || !finaltable) { - warn_noalloc(); - free(ep); - free(finaltable); - return; - } - memcpy(finaltable, structure_table_address, structure_table_length); - - memcpy(ep->anchor_string, "_SM_", 4); - ep->length = 0x1f; - ep->smbios_major_version = 2; - ep->smbios_minor_version = 4; - ep->max_structure_size = max_structure_size; - ep->entry_point_revision = 0; - memset(ep->formatted_area, 0, 5); - memcpy(ep->intermediate_anchor_string, "_DMI_", 5); - - ep->structure_table_length = structure_table_length; - ep->structure_table_address = (u32)finaltable; - ep->number_of_structures = number_of_structures; - ep->smbios_bcd_revision = 0x24; - - ep->checksum -= checksum(ep, 0x10); - - ep->intermediate_checksum -= checksum((void*)ep + 0x10, ep->length - 0x10); - - SMBiosAddr = ep; - dprintf(1, "SMBIOS ptr=%p table=%p size=%d\n" - , ep, finaltable, structure_table_length); -} - -#define load_str_field_with_default(type, field, def) \ - do { \ - size = qemu_cfg_smbios_load_field(type, \ - offsetof(struct smbios_type_##type, \ - field), end); \ - if (size > 0) { \ - end += size; \ - } else { \ - memcpy(end, def, sizeof(def)); \ - end += sizeof(def); \ - } \ - p->field = ++str_index; \ - } while (0) - -#define load_str_field_or_skip(type, field) \ - do { \ - size = qemu_cfg_smbios_load_field(type, \ - offsetof(struct smbios_type_##type, \ - field), end); \ - if (size > 0) { \ - end += size; \ - p->field = ++str_index; \ - } else { \ - p->field = 0; \ - } \ - } while (0) - -#define set_field_with_default(type, field, def) \ - do { \ - if (!qemu_cfg_smbios_load_field(type, \ - offsetof(struct smbios_type_##type, \ - field), &p->field)) { \ - p->field = def; \ - } \ - } while (0) - -/* Type 0 -- BIOS Information */ -#define RELEASE_DATE_STR "01/01/2011" -static void * -smbios_init_type_0(void *start) -{ - struct smbios_type_0 *p = (struct smbios_type_0 *)start; - char *end = (char *)start + sizeof(struct smbios_type_0); - size_t size; - int str_index = 0; - - p->header.type = 0; - p->header.length = sizeof(struct smbios_type_0); - p->header.handle = 0; - - load_str_field_with_default(0, vendor_str, CONFIG_APPNAME); - load_str_field_with_default(0, bios_version_str, CONFIG_APPNAME); - - p->bios_starting_address_segment = 0xe800; - - load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR); - - p->bios_rom_size = 0; /* FIXME */ - - if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0, - bios_characteristics), - &p->bios_characteristics)) { - memset(p->bios_characteristics, 0, 8); - /* BIOS characteristics not supported */ - p->bios_characteristics[0] = 0x08; - } - - if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0, - bios_characteristics_extension_bytes), - &p->bios_characteristics_extension_bytes)) { - p->bios_characteristics_extension_bytes[0] = 0; - /* Enable targeted content distribution. Needed for SVVP */ - p->bios_characteristics_extension_bytes[1] = 4; - } - - set_field_with_default(0, system_bios_major_release, 1); - set_field_with_default(0, system_bios_minor_release, 0); - set_field_with_default(0, embedded_controller_major_release, 0xff); - set_field_with_default(0, embedded_controller_minor_release, 0xff); - - *end = 0; - end++; - - return end; -} - -/* Type 1 -- System Information */ -static void * -smbios_init_type_1(void *start) -{ - struct smbios_type_1 *p = (struct smbios_type_1 *)start; - char *end = (char *)start + sizeof(struct smbios_type_1); - size_t size; - int str_index = 0; - - p->header.type = 1; - p->header.length = sizeof(struct smbios_type_1); - p->header.handle = 0x100; - - load_str_field_with_default(1, manufacturer_str, CONFIG_APPNAME); - load_str_field_with_default(1, product_name_str, CONFIG_APPNAME); - load_str_field_or_skip(1, version_str); - load_str_field_or_skip(1, serial_number_str); - - if (!qemu_cfg_smbios_load_field(1, offsetof(struct smbios_type_1, - uuid), &p->uuid)) { - memset(p->uuid, 0, 16); - } - - set_field_with_default(1, wake_up_type, 0x06); /* power switch */ - - load_str_field_or_skip(1, sku_number_str); - load_str_field_or_skip(1, family_str); - - *end = 0; - end++; - if (!str_index) { - *end = 0; - end++; - } - - return end; -} - -/* Type 3 -- System Enclosure */ -static void * -smbios_init_type_3(void *start) -{ - struct smbios_type_3 *p = (struct smbios_type_3 *)start; - char *end = (char *)start + sizeof(struct smbios_type_3); - size_t size; - int str_index = 0; - - p->header.type = 3; - p->header.length = sizeof(struct smbios_type_3); - p->header.handle = 0x300; - - load_str_field_with_default(3, manufacturer_str, CONFIG_APPNAME); - set_field_with_default(3, type, 0x01); /* other */ - - load_str_field_or_skip(3, version_str); - load_str_field_or_skip(3, serial_number_str); - load_str_field_or_skip(3, asset_tag_number_str); - - set_field_with_default(3, boot_up_state, 0x03); /* safe */ - set_field_with_default(3, power_supply_state, 0x03); /* safe */ - set_field_with_default(3, thermal_state, 0x03); /* safe */ - set_field_with_default(3, security_status, 0x02); /* unknown */ - - set_field_with_default(3, oem_defined, 0); - set_field_with_default(3, height, 0); - set_field_with_default(3, number_of_power_cords, 0); - set_field_with_default(3, contained_element_count, 0); - - *end = 0; - end++; - if (!str_index) { - *end = 0; - end++; - } - - return end; -} - -/* Type 4 -- Processor Information */ -static void * -smbios_init_type_4(void *start, unsigned int cpu_number) -{ - struct smbios_type_4 *p = (struct smbios_type_4 *)start; - char *end = (char *)start + sizeof(struct smbios_type_4); - size_t size; - int str_index = 0; - char name[1024]; - - p->header.type = 4; - p->header.length = sizeof(struct smbios_type_4); - p->header.handle = 0x400 + cpu_number; - - size = qemu_cfg_smbios_load_field(4, offsetof(struct smbios_type_4, - socket_designation_str), - name); - if (size) - snprintf(name + size - 1, sizeof(name) - size, "%2x", cpu_number); - else - snprintf(name, sizeof(name), "CPU%2x", cpu_number); - - memcpy(end, name, strlen(name) + 1); - end += strlen(name) + 1; - p->socket_designation_str = ++str_index; - - set_field_with_default(4, processor_type, 0x03); /* CPU */ - set_field_with_default(4, processor_family, 0x01); /* other */ - - load_str_field_with_default(4, processor_manufacturer_str, CONFIG_APPNAME); - - if (!qemu_cfg_smbios_load_field(4, offsetof(struct smbios_type_4, - processor_id), p->processor_id)) { - u32 cpuid_signature, ebx, ecx, cpuid_features; - cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features); - p->processor_id[0] = cpuid_signature; - p->processor_id[1] = cpuid_features; - } - - load_str_field_or_skip(4, processor_version_str); - set_field_with_default(4, voltage, 0); - set_field_with_default(4, external_clock, 0); - - set_field_with_default(4, max_speed, 2000); - set_field_with_default(4, current_speed, 2000); - - set_field_with_default(4, status, 0x41); /* socket populated, CPU enabled */ - set_field_with_default(4, processor_upgrade, 0x01); /* other */ - - /* cache information structure not provided */ - p->l1_cache_handle = 0xffff; - p->l2_cache_handle = 0xffff; - p->l3_cache_handle = 0xffff; - - *end = 0; - end++; - if (!str_index) { - *end = 0; - end++; - } - - return end; -} - -/* Type 16 -- Physical Memory Array */ -static void * -smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs) -{ - struct smbios_type_16 *p = (struct smbios_type_16*)start; - - p->header.type = 16; - p->header.length = sizeof(struct smbios_type_16); - p->header.handle = 0x1000; - - set_field_with_default(16, location, 0x01); /* other */ - set_field_with_default(16, use, 0x03); /* system memory */ - /* Multi-bit ECC to make Microsoft happy */ - set_field_with_default(16, error_correction, 0x06); - /* 0x80000000 = unknown, accept sizes < 2TB - TODO multiple arrays */ - p->maximum_capacity = memory_size_mb < 2 << 20 ? - memory_size_mb << 10 : 0x80000000; - p->memory_error_information_handle = 0xfffe; /* none provided */ - p->number_of_memory_devices = nr_mem_devs; - - start += sizeof(struct smbios_type_16); - *((u16 *)start) = 0; - - return start + 2; -} - -/* Type 17 -- Memory Device */ -static void * -smbios_init_type_17(void *start, u32 size_mb, int instance) -{ - struct smbios_type_17 *p = (struct smbios_type_17 *)start; - char *end = (char *)start + sizeof(struct smbios_type_17); - size_t size; - int str_index = 0; - char name[1024]; - - p->header.type = 17; - p->header.length = sizeof(struct smbios_type_17); - p->header.handle = 0x1100 + instance; - - p->physical_memory_array_handle = 0x1000; - set_field_with_default(17, total_width, 64); - set_field_with_default(17, data_width, 64); -/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */ - p->size = size_mb; - set_field_with_default(17, form_factor, 0x09); /* DIMM */ - p->device_set = 0; - - size = qemu_cfg_smbios_load_field(17, offsetof(struct smbios_type_17, - device_locator_str), - name); - if (size) - snprintf(name + size - 1, sizeof(name) - size, "%d", instance); - else - snprintf(name, sizeof(name), "DIMM %d", instance); - - memcpy(end, name, strlen(name) + 1); - end += strlen(name) + 1; - p->device_locator_str = ++str_index; - - load_str_field_or_skip(17, bank_locator_str); - set_field_with_default(17, memory_type, 0x07); /* RAM */ - set_field_with_default(17, type_detail, 0); - - *end = 0; - end++; - if (!str_index) { - *end = 0; - end++; - } - - return end; -} - -/* Type 19 -- Memory Array Mapped Address */ -static void * -smbios_init_type_19(void *start, u32 start_mb, u32 size_mb, int instance) -{ - struct smbios_type_19 *p = (struct smbios_type_19 *)start; - - p->header.type = 19; - p->header.length = sizeof(struct smbios_type_19); - p->header.handle = 0x1300 + instance; - - p->starting_address = start_mb << 10; - p->ending_address = p->starting_address + (size_mb << 10) - 1; - p->memory_array_handle = 0x1000; - p->partition_width = 1; - - start += sizeof(struct smbios_type_19); - *((u16 *)start) = 0; - - return start + 2; -} - -/* Type 20 -- Memory Device Mapped Address */ -static void * -smbios_init_type_20(void *start, u32 start_mb, u32 size_mb, int instance, - int dev_handle, int array_handle) -{ - struct smbios_type_20 *p = (struct smbios_type_20 *)start; - - p->header.type = 20; - p->header.length = sizeof(struct smbios_type_20); - p->header.handle = 0x1400 + instance; - - p->starting_address = start_mb << 10; - p->ending_address = p->starting_address + (size_mb << 10) - 1; - p->memory_device_handle = 0x1100 + dev_handle; - p->memory_array_mapped_address_handle = 0x1300 + array_handle; - p->partition_row_position = 1; - p->interleave_position = 0; - p->interleaved_data_depth = 0; - - start += sizeof(struct smbios_type_20); - - *((u16 *)start) = 0; - return start+2; -} - -/* Type 32 -- System Boot Information */ -static void * -smbios_init_type_32(void *start) -{ - struct smbios_type_32 *p = (struct smbios_type_32 *)start; - - p->header.type = 32; - p->header.length = sizeof(struct smbios_type_32); - p->header.handle = 0x2000; - memset(p->reserved, 0, 6); - set_field_with_default(32, boot_status, 0); /* no errors detected */ - - start += sizeof(struct smbios_type_32); - *((u16 *)start) = 0; - - return start+2; -} - -/* Type 127 -- End of Table */ -static void * -smbios_init_type_127(void *start) -{ - struct smbios_type_127 *p = (struct smbios_type_127 *)start; - - p->header.type = 127; - p->header.length = sizeof(struct smbios_type_127); - p->header.handle = 0x7f00; - - start += sizeof(struct smbios_type_127); - *((u16 *)start) = 0; - - return start + 2; -} - -#define TEMPSMBIOSSIZE (32 * 1024) - -void -smbios_init(void) -{ - if (! CONFIG_SMBIOS) - return; - - dprintf(3, "init SMBIOS tables\n"); - - char *start = malloc_tmphigh(TEMPSMBIOSSIZE); - if (! start) { - warn_noalloc(); - return; - } - - u32 nr_structs = 0, max_struct_size = 0; - char *q, *p = start; - char *end = start + TEMPSMBIOSSIZE - sizeof(struct smbios_type_127); - -#define add_struct(type, args...) \ - do { \ - if (!qemu_cfg_smbios_load_external(type, &p, &nr_structs, \ - &max_struct_size, end)) { \ - q = smbios_init_type_##type(args); \ - nr_structs++; \ - if ((q - p) > max_struct_size) \ - max_struct_size = q - p; \ - p = q; \ - } \ - } while (0) - - add_struct(0, p); - add_struct(1, p); - add_struct(3, p); - - int cpu_num; - for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++) - add_struct(4, p, cpu_num); - - int ram_mb = (RamSize + RamSizeOver4G) >> 20; - int nr_mem_devs = (ram_mb + 0x3fff) >> 14; - add_struct(16, p, ram_mb, nr_mem_devs); - - int i, j; - for (i = 0; i < nr_mem_devs; i++) { - u32 dev_mb = ((i == (nr_mem_devs - 1)) - ? (((ram_mb - 1) & 0x3fff) + 1) - : 16384); - add_struct(17, p, dev_mb, i); - } - - add_struct(19, p, 0, RamSize >> 20, 0); - if (RamSizeOver4G) - add_struct(19, p, 4096, RamSizeOver4G >> 20, 1); - - add_struct(20, p, 0, RamSize >> 20, 0, 0, 0); - if (RamSizeOver4G) { - u32 start_mb = 4096; - for (j = 1, i = 0; i < nr_mem_devs; i++, j++) { - u32 dev_mb = ((i == (nr_mem_devs - 1)) - ? (((ram_mb - 1) & 0x3fff) + 1) - : 16384); - if (i == 0) - dev_mb -= RamSize >> 20; - - add_struct(20, p, start_mb, dev_mb, j, i, 1); - start_mb += dev_mb; - } - } - - add_struct(32, p); - /* Add any remaining provided entries before the end marker */ - for (i = 0; i < 256; i++) - qemu_cfg_smbios_load_external(i, &p, &nr_structs, &max_struct_size, - end); - add_struct(127, p); - -#undef add_struct - - smbios_entry_point_init(max_struct_size, p - start, start, nr_structs); - free(start); -} diff -Nru seabios-1.7.1/src/smbios.h seabios-1.7.4/src/smbios.h --- seabios-1.7.1/src/smbios.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/smbios.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,168 +0,0 @@ -#ifndef __SMBIOS_H -#define __SMBIOS_H - -// smbios.c -void smbios_init(void); - -/* SMBIOS entry point -- must be written to a 16-bit aligned address - between 0xf0000 and 0xfffff. - */ -struct smbios_entry_point { - char anchor_string[4]; - u8 checksum; - u8 length; - u8 smbios_major_version; - u8 smbios_minor_version; - u16 max_structure_size; - u8 entry_point_revision; - u8 formatted_area[5]; - char intermediate_anchor_string[5]; - u8 intermediate_checksum; - u16 structure_table_length; - u32 structure_table_address; - u16 number_of_structures; - u8 smbios_bcd_revision; -} PACKED; - -extern struct smbios_entry_point *SMBiosAddr; - -/* This goes at the beginning of every SMBIOS structure. */ -struct smbios_structure_header { - u8 type; - u8 length; - u16 handle; -} PACKED; - -/* SMBIOS type 0 - BIOS Information */ -struct smbios_type_0 { - struct smbios_structure_header header; - u8 vendor_str; - u8 bios_version_str; - u16 bios_starting_address_segment; - u8 bios_release_date_str; - u8 bios_rom_size; - u8 bios_characteristics[8]; - u8 bios_characteristics_extension_bytes[2]; - u8 system_bios_major_release; - u8 system_bios_minor_release; - u8 embedded_controller_major_release; - u8 embedded_controller_minor_release; -} PACKED; - -/* SMBIOS type 1 - System Information */ -struct smbios_type_1 { - struct smbios_structure_header header; - u8 manufacturer_str; - u8 product_name_str; - u8 version_str; - u8 serial_number_str; - u8 uuid[16]; - u8 wake_up_type; - u8 sku_number_str; - u8 family_str; -} PACKED; - -/* SMBIOS type 3 - System Enclosure (v2.3) */ -struct smbios_type_3 { - struct smbios_structure_header header; - u8 manufacturer_str; - u8 type; - u8 version_str; - u8 serial_number_str; - u8 asset_tag_number_str; - u8 boot_up_state; - u8 power_supply_state; - u8 thermal_state; - u8 security_status; - u32 oem_defined; - u8 height; - u8 number_of_power_cords; - u8 contained_element_count; - // contained elements follow -} PACKED; - -/* SMBIOS type 4 - Processor Information (v2.0) */ -struct smbios_type_4 { - struct smbios_structure_header header; - u8 socket_designation_str; - u8 processor_type; - u8 processor_family; - u8 processor_manufacturer_str; - u32 processor_id[2]; - u8 processor_version_str; - u8 voltage; - u16 external_clock; - u16 max_speed; - u16 current_speed; - u8 status; - u8 processor_upgrade; - u16 l1_cache_handle; - u16 l2_cache_handle; - u16 l3_cache_handle; -} PACKED; - -/* SMBIOS type 16 - Physical Memory Array - * Associated with one type 17 (Memory Device). - */ -struct smbios_type_16 { - struct smbios_structure_header header; - u8 location; - u8 use; - u8 error_correction; - u32 maximum_capacity; - u16 memory_error_information_handle; - u16 number_of_memory_devices; -} PACKED; - -/* SMBIOS type 17 - Memory Device - * Associated with one type 19 - */ -struct smbios_type_17 { - struct smbios_structure_header header; - u16 physical_memory_array_handle; - u16 memory_error_information_handle; - u16 total_width; - u16 data_width; - u16 size; - u8 form_factor; - u8 device_set; - u8 device_locator_str; - u8 bank_locator_str; - u8 memory_type; - u16 type_detail; -} PACKED; - -/* SMBIOS type 19 - Memory Array Mapped Address */ -struct smbios_type_19 { - struct smbios_structure_header header; - u32 starting_address; - u32 ending_address; - u16 memory_array_handle; - u8 partition_width; -} PACKED; - -/* SMBIOS type 20 - Memory Device Mapped Address */ -struct smbios_type_20 { - struct smbios_structure_header header; - u32 starting_address; - u32 ending_address; - u16 memory_device_handle; - u16 memory_array_mapped_address_handle; - u8 partition_row_position; - u8 interleave_position; - u8 interleaved_data_depth; -} PACKED; - -/* SMBIOS type 32 - System Boot Information */ -struct smbios_type_32 { - struct smbios_structure_header header; - u8 reserved[6]; - u8 boot_status; -} PACKED; - -/* SMBIOS type 127 -- End-of-table */ -struct smbios_type_127 { - struct smbios_structure_header header; -} PACKED; - -#endif // smbios.h diff -Nru seabios-1.7.1/src/smm.c seabios-1.7.4/src/smm.c --- seabios-1.7.1/src/smm.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/smm.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -// System Management Mode support (on emulators) -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "pci.h" // pci_config_writel -#include "util.h" // wbinvd -#include "config.h" // CONFIG_* -#include "ioport.h" // outb -#include "pci_ids.h" // PCI_VENDOR_ID_INTEL -#include "xen.h" // usingXen - -ASM32FLAT( - ".global smm_relocation_start\n" - ".global smm_relocation_end\n" - ".global smm_code_start\n" - ".global smm_code_end\n" - " .code16\n" - - /* code to relocate SMBASE to 0xa0000 */ - "smm_relocation_start:\n" - " mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7efc, %ebx\n" - " addr32 mov (%ebx), %al\n" /* revision ID to see if x86_64 or x86 */ - " cmp $0x64, %al\n" - " je 1f\n" - " mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7ef8, %ebx\n" - " jmp 2f\n" - "1:\n" - " mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7f00, %ebx\n" - "2:\n" - " movl $" __stringify(BUILD_SMM_ADDR) " - 0x8000, %eax\n" - " addr32 movl %eax, (%ebx)\n" - /* indicate to the BIOS that the SMM code was executed */ - " mov $0x00, %al\n" - " movw $" __stringify(PORT_SMI_STATUS) ", %dx\n" - " outb %al, %dx\n" - " rsm\n" - "smm_relocation_end:\n" - - /* minimal SMM code to enable or disable ACPI */ - "smm_code_start:\n" - " movw $" __stringify(PORT_SMI_CMD) ", %dx\n" - " inb %dx, %al\n" - " cmp $0xf0, %al\n" - " jne 1f\n" - - /* ACPI disable */ - " mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */ - " inw %dx, %ax\n" - " andw $~1, %ax\n" - " outw %ax, %dx\n" - - " jmp 2f\n" - - "1:\n" - " cmp $0xf1, %al\n" - " jne 2f\n" - - /* ACPI enable */ - " mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */ - " inw %dx, %ax\n" - " orw $1, %ax\n" - " outw %ax, %dx\n" - - "2:\n" - " rsm\n" - "smm_code_end:\n" - " .code32\n" - ); - -extern u8 smm_relocation_start, smm_relocation_end; -extern u8 smm_code_start, smm_code_end; - -static void -smm_save_and_copy(void) -{ - /* save original memory content */ - memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE); - - /* copy the SMM relocation code */ - memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start, - &smm_relocation_end - &smm_relocation_start); -} - -static void -smm_relocate_and_restore(void) -{ - /* init APM status port */ - outb(0x01, PORT_SMI_STATUS); - - /* raise an SMI interrupt */ - outb(0x00, PORT_SMI_CMD); - - /* wait until SMM code executed */ - while (inb(PORT_SMI_STATUS) != 0x00) - ; - - /* restore original memory content */ - memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE); - - /* copy the SMM code */ - memcpy((void *)BUILD_SMM_ADDR, &smm_code_start - , &smm_code_end - &smm_code_start); - wbinvd(); -} - -#define I440FX_SMRAM 0x72 -#define PIIX_DEVACTB 0x58 -#define PIIX_APMC_EN (1 << 25) - -// This code is hardcoded for PIIX4 Power Management device. -static void piix4_apmc_smm_init(struct pci_device *pci, void *arg) -{ - struct pci_device *i440_pci = pci_find_device(PCI_VENDOR_ID_INTEL - , PCI_DEVICE_ID_INTEL_82441); - if (!i440_pci) - return; - - /* check if SMM init is already done */ - u32 value = pci_config_readl(pci->bdf, PIIX_DEVACTB); - if (value & PIIX_APMC_EN) - return; - - /* enable the SMM memory window */ - pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x48); - - smm_save_and_copy(); - - /* enable SMI generation when writing to the APMC register */ - pci_config_writel(pci->bdf, PIIX_DEVACTB, value | PIIX_APMC_EN); - - smm_relocate_and_restore(); - - /* close the SMM memory window and enable normal SMM */ - pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x08); -} - -static const struct pci_device_id smm_init_tbl[] = { - PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, - piix4_apmc_smm_init), - - PCI_DEVICE_END, -}; - -void -smm_init(void) -{ - if (CONFIG_COREBOOT) - // SMM only supported on emulators. - return; - if (!CONFIG_USE_SMM) - return; - if (usingXen()) - return; - - dprintf(3, "init smm\n"); - pci_find_init_device(smm_init_tbl, NULL); -} diff -Nru seabios-1.7.1/src/smp.c seabios-1.7.4/src/smp.c --- seabios-1.7.1/src/smp.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/smp.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -// CPU count detection -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2006 Fabrice Bellard -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "config.h" // CONFIG_* -#include "cmos.h" // CMOS_BIOS_SMP_COUNT -#include "paravirt.h" - -#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300) -#define APIC_SVR ((u8*)BUILD_APIC_ADDR + 0x0F0) -#define APIC_LINT0 ((u8*)BUILD_APIC_ADDR + 0x350) -#define APIC_LINT1 ((u8*)BUILD_APIC_ADDR + 0x360) - -#define APIC_ENABLED 0x0100 - -struct { u32 ecx, eax, edx; } smp_mtrr[32] VAR16VISIBLE; -u32 smp_mtrr_count VAR16VISIBLE; - -void -wrmsr_smp(u32 index, u64 val) -{ - wrmsr(index, val); - if (smp_mtrr_count >= ARRAY_SIZE(smp_mtrr)) { - warn_noalloc(); - return; - } - smp_mtrr[smp_mtrr_count].ecx = index; - smp_mtrr[smp_mtrr_count].eax = val; - smp_mtrr[smp_mtrr_count].edx = val >> 32; - smp_mtrr_count++; -} - -u32 CountCPUs VAR16VISIBLE; -u32 MaxCountCPUs VAR16VISIBLE; -// 256 bits for the found APIC IDs -u32 FoundAPICIDs[256/32] VAR16VISIBLE; -extern void smp_ap_boot_code(void); -ASM16( - " .global smp_ap_boot_code\n" - "smp_ap_boot_code:\n" - - // Setup data segment - " movw $" __stringify(SEG_BIOS) ", %ax\n" - " movw %ax, %ds\n" - - // MTRR setup - " movl $smp_mtrr, %esi\n" - " movl smp_mtrr_count, %ebx\n" - "1:testl %ebx, %ebx\n" - " jz 2f\n" - " movl 0(%esi), %ecx\n" - " movl 4(%esi), %eax\n" - " movl 8(%esi), %edx\n" - " wrmsr\n" - " addl $12, %esi\n" - " decl %ebx\n" - " jmp 1b\n" - "2:\n" - - // get apic ID on EBX, set bit on FoundAPICIDs - " movl $1, %eax\n" - " cpuid\n" - " shrl $24, %ebx\n" - " lock btsl %ebx, FoundAPICIDs\n" - - // Increment the cpu counter - " lock incl CountCPUs\n" - - // Halt the processor. - "1:hlt\n" - " jmp 1b\n" - ); - -int apic_id_is_present(u8 apic_id) -{ - return FoundAPICIDs[apic_id/32] & (1 << (apic_id % 32)); -} - -// find and initialize the CPUs by launching a SIPI to them -void -smp_probe(void) -{ - ASSERT32FLAT(); - u32 eax, ebx, ecx, cpuid_features; - cpuid(1, &eax, &ebx, &ecx, &cpuid_features); - if (eax < 1 || !(cpuid_features & CPUID_APIC)) { - // No apic - only the main cpu is present. - dprintf(1, "No apic - only the main cpu is present.\n"); - CountCPUs= 1; - MaxCountCPUs = 1; - return; - } - - // mark the BSP initial APIC ID as found, too: - u8 apic_id = ebx>>24; - FoundAPICIDs[apic_id/32] |= (1 << (apic_id % 32)); - - // Init the counter. - writel(&CountCPUs, 1); - - // Setup jump trampoline to counter code. - u64 old = *(u64*)BUILD_AP_BOOT_ADDR; - // ljmpw $SEG_BIOS, $(smp_ap_boot_code - BUILD_BIOS_ADDR) - u64 new = (0xea | ((u64)SEG_BIOS<<24) - | (((u32)smp_ap_boot_code - BUILD_BIOS_ADDR) << 8)); - *(u64*)BUILD_AP_BOOT_ADDR = new; - - // enable local APIC - u32 val = readl(APIC_SVR); - writel(APIC_SVR, val | APIC_ENABLED); - - if (! CONFIG_COREBOOT) { - /* Set LINT0 as Ext_INT, level triggered */ - writel(APIC_LINT0, 0x8700); - - /* Set LINT1 as NMI, level triggered */ - writel(APIC_LINT1, 0x8400); - } - - // broadcast SIPI - barrier(); - writel(APIC_ICR_LOW, 0x000C4500); - u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12; - writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector); - - // Wait for other CPUs to process the SIPI. - if (CONFIG_COREBOOT) { - msleep(10); - } else { - u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT); - while (cmos_smp_count + 1 != readl(&CountCPUs)) - yield(); - } - - // Restore memory. - *(u64*)BUILD_AP_BOOT_ADDR = old; - - MaxCountCPUs = qemu_cfg_get_max_cpus(); - if (!MaxCountCPUs || MaxCountCPUs < CountCPUs) - MaxCountCPUs = CountCPUs; - - dprintf(1, "Found %d cpu(s) max supported %d cpu(s)\n", readl(&CountCPUs), - MaxCountCPUs); -} diff -Nru seabios-1.7.1/src/ssdt-pcihp.dsl seabios-1.7.4/src/ssdt-pcihp.dsl --- seabios-1.7.1/src/ssdt-pcihp.dsl 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ssdt-pcihp.dsl 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml - -DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1) -{ - -/**************************************************************** - * PCI hotplug - ****************************************************************/ - - /* Objects supplied by DSDT */ - External (\_SB.PCI0, DeviceObj) - External (\_SB.PCI0.PCEJ, MethodObj) - - Scope(\_SB.PCI0) { - /* Bulk generated PCI hotplug devices */ - // Method _EJ0 can be patched by BIOS to EJ0_ - // at runtime, if the slot is detected to not support hotplug. - // Extract the offset of the address dword and the - // _EJ0 name to allow this patching. -#define hotplug_slot(slot) \ - Device (S##slot) { \ - ACPI_EXTRACT_NAME_DWORD_CONST aml_adr_dword \ - Name (_ADR, 0x##slot##0000) \ - ACPI_EXTRACT_METHOD_STRING aml_ej0_name \ - Method (_EJ0, 1) { Return(PCEJ(0x##slot)) } \ - Name (_SUN, 0x##slot) \ - } - - hotplug_slot(01) - hotplug_slot(02) - hotplug_slot(03) - hotplug_slot(04) - hotplug_slot(05) - hotplug_slot(06) - hotplug_slot(07) - hotplug_slot(08) - hotplug_slot(09) - hotplug_slot(0a) - hotplug_slot(0b) - hotplug_slot(0c) - hotplug_slot(0d) - hotplug_slot(0e) - hotplug_slot(0f) - hotplug_slot(10) - hotplug_slot(11) - hotplug_slot(12) - hotplug_slot(13) - hotplug_slot(14) - hotplug_slot(15) - hotplug_slot(16) - hotplug_slot(17) - hotplug_slot(18) - hotplug_slot(19) - hotplug_slot(1a) - hotplug_slot(1b) - hotplug_slot(1c) - hotplug_slot(1d) - hotplug_slot(1e) - hotplug_slot(1f) - -#define gen_pci_hotplug(slot) \ - If (LEqual(Arg0, 0x##slot)) { Notify(S##slot, Arg1) } - - Method(PCNT, 2) { - gen_pci_hotplug(01) - gen_pci_hotplug(02) - gen_pci_hotplug(03) - gen_pci_hotplug(04) - gen_pci_hotplug(05) - gen_pci_hotplug(06) - gen_pci_hotplug(07) - gen_pci_hotplug(08) - gen_pci_hotplug(09) - gen_pci_hotplug(0a) - gen_pci_hotplug(0b) - gen_pci_hotplug(0c) - gen_pci_hotplug(0d) - gen_pci_hotplug(0e) - gen_pci_hotplug(0f) - gen_pci_hotplug(10) - gen_pci_hotplug(11) - gen_pci_hotplug(12) - gen_pci_hotplug(13) - gen_pci_hotplug(14) - gen_pci_hotplug(15) - gen_pci_hotplug(16) - gen_pci_hotplug(17) - gen_pci_hotplug(18) - gen_pci_hotplug(19) - gen_pci_hotplug(1a) - gen_pci_hotplug(1b) - gen_pci_hotplug(1c) - gen_pci_hotplug(1d) - gen_pci_hotplug(1e) - gen_pci_hotplug(1f) - } - } - - Scope(\) { -/**************************************************************** - * Suspend - ****************************************************************/ - - /* - * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes: - * must match piix4 emulation. - */ - - ACPI_EXTRACT_NAME_STRING acpi_s3_name - Name (_S3, Package (0x04) - { - One, /* PM1a_CNT.SLP_TYP */ - One, /* PM1b_CNT.SLP_TYP */ - Zero, /* reserved */ - Zero /* reserved */ - }) - ACPI_EXTRACT_NAME_STRING acpi_s4_name - ACPI_EXTRACT_PKG_START acpi_s4_pkg - Name (_S4, Package (0x04) - { - 0x2, /* PM1a_CNT.SLP_TYP */ - 0x2, /* PM1b_CNT.SLP_TYP */ - Zero, /* reserved */ - Zero /* reserved */ - }) - Name (_S5, Package (0x04) - { - Zero, /* PM1a_CNT.SLP_TYP */ - Zero, /* PM1b_CNT.SLP_TYP */ - Zero, /* reserved */ - Zero /* reserved */ - }) - } -} diff -Nru seabios-1.7.1/src/ssdt-proc.dsl seabios-1.7.4/src/ssdt-proc.dsl --- seabios-1.7.1/src/ssdt-proc.dsl 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/ssdt-proc.dsl 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* This file is the basis for the ssdt table generated in src/acpi.c. - * It defines the contents of the per-cpu Processor() object. At - * runtime, a dynamically generated SSDT will contain one copy of this - * AML snippet for every possible cpu in the system. The objects will - * be placed in the \_SB_ namespace. - * - * In addition to the aml code generated from this file, the - * src/acpi.c file creates a NTFY method with an entry for each cpu: - * Method(NTFY, 2) { - * If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) } - * If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) } - * ... - * } - * and a CPON array with the list of active and inactive cpus: - * Name(CPON, Package() { One, One, ..., Zero, Zero, ... }) - */ - -ACPI_EXTRACT_ALL_CODE ssdp_proc_aml - -DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1) -{ - ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start - ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end - ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name - Processor (CPAA, 0xAA, 0x0000b010, 0x06) { - ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id - Name (ID, 0xAA) -/* - * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update - * CPAA and 0xAA with the appropriate CPU id (see - * SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without - * also updating the C code. - */ - Name (_HID, "ACPI0007") - External(CPMA, MethodObj) - External(CPST, MethodObj) - External(CPEJ, MethodObj) - Method(_MAT, 0) { - Return(CPMA(ID)) - } - Method (_STA, 0) { - Return(CPST(ID)) - } - Method (_EJ0, 1, NotSerialized) { - CPEJ(ID, Arg0) - } - } -} diff -Nru seabios-1.7.1/src/stacks.c seabios-1.7.4/src/stacks.c --- seabios-1.7.1/src/stacks.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/stacks.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,8 +5,15 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "biosvar.h" // GET_GLOBAL -#include "util.h" // dprintf #include "bregs.h" // CR0_PE +#include "hw/rtc.h" // rtc_use +#include "list.h" // hlist_node +#include "malloc.h" // free +#include "output.h" // dprintf +#include "stacks.h" // struct mutex_s +#include "util.h" // useRTC + +#define MAIN_STACK_MAX (1024*1024) /**************************************************************** @@ -95,12 +102,7 @@ * 16bit / 32bit calling ****************************************************************/ -static inline void sgdt(struct descloc_s *desc) { - asm("sgdtl %0" : "=m"(*desc)); -} -static inline void lgdt(struct descloc_s *desc) { - asm("lgdtl %0" : : "m"(*desc) : "memory"); -} +u16 StackSeg VARLOW; // Call a 32bit SeaBIOS function from a 16bit SeaBIOS function. u32 VISIBLE16 @@ -122,6 +124,8 @@ struct descloc_s gdt; sgdt(&gdt); + u16 oldstackseg = GET_LOW(StackSeg); + SET_LOW(StackSeg, GET_SEG(SS)); u32 bkup_ss, bkup_esp; asm volatile( // Backup ss/esp / set esp to flat stack location @@ -148,6 +152,8 @@ : "r" (func) : "ecx", "edx", "cc", "memory"); + SET_LOW(StackSeg, oldstackseg); + // Restore gdt and fs/gs lgdt(&gdt); SET_SEG(FS, fs); @@ -161,62 +167,62 @@ // Call a 16bit SeaBIOS function from a 32bit SeaBIOS function. static inline u32 -call16(u32 eax, void *func) +call16(u32 eax, u32 edx, void *func) { ASSERT32FLAT(); - if (getesp() > BUILD_STACK_ADDR) + if (getesp() > MAIN_STACK_MAX) panic("call16 with invalid stack\n"); - asm volatile( - "calll __call16" - : "+a" (eax) - : "b" ((u32)func - BUILD_BIOS_ADDR) - : "ecx", "edx", "cc", "memory"); - return eax; + extern u32 __call16(u32 eax, u32 edx, void *func); + return __call16(eax, edx, func - BUILD_BIOS_ADDR); } static inline u32 -call16big(u32 eax, void *func) +call16big(u32 eax, u32 edx, void *func) { ASSERT32FLAT(); - if (getesp() > BUILD_STACK_ADDR) + if (getesp() > MAIN_STACK_MAX) panic("call16big with invalid stack\n"); - asm volatile( - "calll __call16big" - : "+a" (eax) - : "b" ((u32)func - BUILD_BIOS_ADDR) - : "ecx", "edx", "cc", "memory"); - return eax; + extern u32 __call16big(u32 eax, u32 edx, void *func); + return __call16big(eax, edx, func - BUILD_BIOS_ADDR); } + +/**************************************************************** + * External 16bit interface calling + ****************************************************************/ + // Far call 16bit code with a specified register state. void VISIBLE16 -_farcall16(struct bregs *callregs) +_farcall16(struct bregs *callregs, u16 callregseg) { ASSERT16(); + if (on_extra_stack()) { + stack_hop_back((u32)callregs, callregseg, _farcall16); + return; + } asm volatile( "calll __farcall16\n" - : "+a" (callregs), "+m" (*callregs) - : "m" (__segment_ES) - : "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); + : "+a" (callregs), "+m" (*callregs), "+d" (callregseg) + : + : "ebx", "ecx", "esi", "edi", "cc", "memory"); } inline void farcall16(struct bregs *callregs) { if (MODE16) { - SET_SEG(ES, GET_SEG(SS)); - stack_hop_back((u32)callregs, 0, _farcall16); + _farcall16(callregs, GET_SEG(SS)); return; } extern void _cfunc16__farcall16(void); - call16((u32)callregs, _cfunc16__farcall16); + call16((u32)callregs - StackSeg * 16, StackSeg, _cfunc16__farcall16); } inline void farcall16big(struct bregs *callregs) { extern void _cfunc16__farcall16(void); - call16big((u32)callregs, _cfunc16__farcall16); + call16big((u32)callregs - StackSeg * 16, StackSeg, _cfunc16__farcall16); } // Invoke a 16bit software interrupt. @@ -239,21 +245,28 @@ // Thread info - stored at bottom of each thread stack - don't change // without also updating the inline assembler below. struct thread_info { - struct thread_info *next; void *stackpos; - struct thread_info **pprev; + struct hlist_node node; }; -struct thread_info VAR32FLATVISIBLE MainThread = { - &MainThread, NULL, &MainThread.next +struct thread_info MainThread VARFSEG = { + NULL, { &MainThread.node, &MainThread.node.next } }; #define THREADSTACKSIZE 4096 +// Check if any threads are running. +static int +have_threads(void) +{ + return (CONFIG_THREADS + && GET_FLATPTR(MainThread.node.next) != &MainThread.node); +} + // Return the 'struct thread_info' for the currently running thread. struct thread_info * getCurThread(void) { u32 esp = getesp(); - if (esp <= BUILD_STACK_ADDR) + if (esp <= MAIN_STACK_MAX) return &MainThread; return (void*)ALIGN_DOWN(esp, THREADSTACKSIZE); } @@ -262,15 +275,16 @@ static void switch_next(struct thread_info *cur) { - struct thread_info *next = cur->next; + struct thread_info *next = container_of( + cur->node.next, struct thread_info, node); if (cur == next) // Nothing to do. return; asm volatile( " pushl $1f\n" // store return pc " pushl %%ebp\n" // backup %ebp - " movl %%esp, 4(%%eax)\n" // cur->stackpos = %esp - " movl 4(%%ecx), %%esp\n" // %esp = next->stackpos + " movl %%esp, (%%eax)\n" // cur->stackpos = %esp + " movl (%%ecx), %%esp\n" // %esp = next->stackpos " popl %%ebp\n" // restore %ebp " retl\n" // restore pc "1:\n" @@ -279,67 +293,14 @@ : "ebx", "edx", "esi", "edi", "cc", "memory"); } -// Low-level irq enable. -void VISIBLE16 -check_irqs(void) -{ - asm volatile("sti ; nop ; rep ; nop ; cli ; cld" : : :"memory"); -} - -// Briefly permit irqs to occur. -void -yield(void) -{ - if (MODESEGMENT) { - stack_hop_back(0, 0, check_irqs); - return; - } - extern void _cfunc16_check_irqs(void); - if (!CONFIG_THREADS) { - call16big(0, _cfunc16_check_irqs); - return; - } - struct thread_info *cur = getCurThread(); - if (cur == &MainThread) - // Permit irqs to fire - call16big(0, _cfunc16_check_irqs); - - // Switch to the next thread - switch_next(cur); -} - -void VISIBLE16 -wait_irq(void) -{ - asm volatile("sti ; hlt ; cli ; cld": : :"memory"); -} - -// Wait for next irq to occur. -void -yield_toirq(void) -{ - if (MODESEGMENT) { - stack_hop_back(0, 0, wait_irq); - return; - } - if (CONFIG_THREADS && MainThread.next != &MainThread) { - // Threads still active - do a yield instead. - yield(); - return; - } - extern void _cfunc16_wait_irq(void); - call16big(0, _cfunc16_wait_irq); -} - // Last thing called from a thread (called on "next" stack). static void __end_thread(struct thread_info *old) { - old->next->pprev = old->pprev; - *old->pprev = old->next; + hlist_del(&old->node); free(old); dprintf(DEBUG_thread, "\\%08x/ End thread\n", (u32)old); - if (MainThread.next == &MainThread) + if (!have_threads()) dprintf(1, "All threads complete.\n"); } @@ -357,23 +318,20 @@ thread->stackpos = (void*)thread + THREADSTACKSIZE; struct thread_info *cur = getCurThread(); - thread->next = cur; - thread->pprev = cur->pprev; - cur->pprev = &thread->next; - *thread->pprev = thread; + hlist_add_after(&thread->node, &cur->node); dprintf(DEBUG_thread, "/%08x\\ Start thread\n", (u32)thread); asm volatile( // Start thread " pushl $1f\n" // store return pc " pushl %%ebp\n" // backup %ebp - " movl %%esp, 4(%%edx)\n" // cur->stackpos = %esp - " movl 4(%%ebx), %%esp\n" // %esp = thread->stackpos + " movl %%esp, (%%edx)\n" // cur->stackpos = %esp + " movl (%%ebx), %%esp\n" // %esp = thread->stackpos " calll *%%ecx\n" // Call func // End thread - " movl (%%ebx), %%ecx\n" // %ecx = thread->next - " movl 4(%%ecx), %%esp\n" // %esp = next->stackpos + " movl 4(%%ebx), %%ecx\n" // %ecx = thread->node.next + " movl -4(%%ecx), %%esp\n" // %esp = next->stackpos " movl %%ebx, %%eax\n" " calll %4\n" // call __end_thread(thread) " popl %%ebp\n" // restore %ebp @@ -388,14 +346,77 @@ func(data); } + +/**************************************************************** + * Thread helpers + ****************************************************************/ + +// Low-level irq enable. +void VISIBLE16 +check_irqs(void) +{ + if (on_extra_stack()) { + stack_hop_back(0, 0, check_irqs); + return; + } + asm volatile("sti ; nop ; rep ; nop ; cli ; cld" : : :"memory"); +} + +// Briefly permit irqs to occur. +void +yield(void) +{ + if (MODESEGMENT) { + check_irqs(); + return; + } + extern void _cfunc16_check_irqs(void); + if (!CONFIG_THREADS) { + call16big(0, 0, _cfunc16_check_irqs); + return; + } + struct thread_info *cur = getCurThread(); + if (cur == &MainThread) + // Permit irqs to fire + call16big(0, 0, _cfunc16_check_irqs); + + // Switch to the next thread + switch_next(cur); +} + +void VISIBLE16 +wait_irq(void) +{ + if (on_extra_stack()) { + stack_hop_back(0, 0, wait_irq); + return; + } + asm volatile("sti ; hlt ; cli ; cld": : :"memory"); +} + +// Wait for next irq to occur. +void +yield_toirq(void) +{ + if (MODESEGMENT) { + wait_irq(); + return; + } + if (have_threads()) { + // Threads still active - do a yield instead. + yield(); + return; + } + extern void _cfunc16_wait_irq(void); + call16big(0, 0, _cfunc16_wait_irq); +} + // Wait for all threads (other than the main thread) to complete. void wait_threads(void) { ASSERT32FLAT(); - if (! CONFIG_THREADS) - return; - while (MainThread.next != &MainThread) + while (have_threads()) yield(); } @@ -424,30 +445,30 @@ * Thread preemption ****************************************************************/ -int VAR16VISIBLE CanPreempt; +int CanPreempt VARFSEG; static u32 PreemptCount; // Turn on RTC irqs and arrange for them to check the 32bit threads. void start_preempt(void) { - if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS) + if (! CONFIG_THREAD_OPTIONROMS) return; CanPreempt = 1; PreemptCount = 0; - useRTC(); + rtc_use(); } // Turn off RTC irqs / stop checking for thread execution. void finish_preempt(void) { - if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS) { + if (! CONFIG_THREAD_OPTIONROMS) { yield(); return; } CanPreempt = 0; - releaseRTC(); + rtc_release(); dprintf(9, "Done preempt - %d checks\n", PreemptCount); yield(); } @@ -456,8 +477,8 @@ int wait_preempt(void) { - if (MODESEGMENT || !CONFIG_THREADS || !CONFIG_THREAD_OPTIONROMS - || !CanPreempt) + if (MODESEGMENT || !CONFIG_THREAD_OPTIONROMS || !CanPreempt + || getesp() < MAIN_STACK_MAX) return 0; while (CanPreempt) yield(); @@ -476,11 +497,7 @@ void check_preempt(void) { - if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS - || !GET_GLOBAL(CanPreempt) - || GET_FLATPTR(MainThread.next) == &MainThread) - return; - extern void _cfunc32flat_yield_preempt(void); - call32(_cfunc32flat_yield_preempt, 0, 0); + if (CONFIG_THREAD_OPTIONROMS && GET_GLOBAL(CanPreempt) && have_threads()) + call32(_cfunc32flat_yield_preempt, 0, 0); } diff -Nru seabios-1.7.1/src/stacks.h seabios-1.7.4/src/stacks.h --- seabios-1.7.1/src/stacks.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/stacks.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,34 @@ +// Misc function and variable declarations. +#ifndef __STACKS_H +#define __STACKS_H + +#include "types.h" // u32 + +// stacks.c +extern u8 ExtraStack[], *StackPos; +u32 stack_hop(u32 eax, u32 edx, void *func); +u32 stack_hop_back(u32 eax, u32 edx, void *func); +u32 call32(void *func, u32 eax, u32 errret); +struct bregs; +inline void farcall16(struct bregs *callregs); +inline void farcall16big(struct bregs *callregs); +inline void __call16_int(struct bregs *callregs, u16 offset); +#define call16_int(nr, callregs) do { \ + extern void irq_trampoline_ ##nr (); \ + __call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \ + } while (0) +extern struct thread_info MainThread; +struct thread_info *getCurThread(void); +void yield(void); +void yield_toirq(void); +void run_thread(void (*func)(void*), void *data); +void wait_threads(void); +struct mutex_s { u32 isLocked; }; +void mutex_lock(struct mutex_s *mutex); +void mutex_unlock(struct mutex_s *mutex); +void start_preempt(void); +void finish_preempt(void); +int wait_preempt(void); +void check_preempt(void); + +#endif // stacks.h diff -Nru seabios-1.7.1/src/std/acpi.h seabios-1.7.4/src/std/acpi.h --- seabios-1.7.1/src/std/acpi.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/acpi.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,272 @@ +#ifndef __ACPI_H +#define __ACPI_H + +#include "types.h" // u32 + +/* + * ACPI 2.0 Generic Address Space definition. + */ +struct acpi_20_generic_address { + u8 address_space_id; + u8 register_bit_width; + u8 register_bit_offset; + u8 reserved; + u64 address; +} PACKED; + +#define RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR " + +struct rsdp_descriptor { /* Root System Descriptor Pointer */ + u64 signature; /* ACPI signature, contains "RSD PTR " */ + u8 checksum; /* To make sum of struct == 0 */ + u8 oem_id [6]; /* OEM identification */ + u8 revision; /* Must be 0 for 1.0, 2 for 2.0 */ + u32 rsdt_physical_address; /* 32-bit physical address of RSDT */ + u32 length; /* XSDT Length in bytes including hdr */ + u64 xsdt_physical_address; /* 64-bit physical address of XSDT */ + u8 extended_checksum; /* Checksum of entire table */ + u8 reserved [3]; /* Reserved field must be 0 */ +}; + +/* Table structure from Linux kernel (the ACPI tables are under the + BSD license) */ + +#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ + u32 signature; /* ACPI signature (4 ASCII characters) */ \ + u32 length; /* Length of table, in bytes, including header */ \ + u8 revision; /* ACPI Specification minor version # */ \ + u8 checksum; /* To make sum of entire table == 0 */ \ + u8 oem_id [6]; /* OEM identification */ \ + u8 oem_table_id [8]; /* OEM table identification */ \ + u32 oem_revision; /* OEM revision number */ \ + u8 asl_compiler_id [4]; /* ASL compiler vendor ID */ \ + u32 asl_compiler_revision; /* ASL compiler revision number */ + + +/* + * ACPI 1.0 Fixed ACPI Description Table (FADT) + */ +#define FACP_SIGNATURE 0x50434146 // FACP +struct fadt_descriptor_rev1 +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 firmware_ctrl; /* Physical address of FACS */ + u32 dsdt; /* Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 reserved1; /* Reserved */ + u16 sci_int; /* System vector of SCI interrupt */ + u32 smi_cmd; /* Port address of SMI command port */ + u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ + u8 reserved2; /* Reserved - must be zero */ + u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ + u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ + u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ + u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ + u8 reserved3; /* Reserved */ + u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ + u16 flush_size; /* Size of area read to flush caches */ + u16 flush_stride; /* Stride used in flushing caches */ + u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */ + u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */ + u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* Index to century in RTC CMOS RAM */ + u8 reserved4; /* Reserved */ + u8 reserved4a; /* Reserved */ + u8 reserved4b; /* Reserved */ + u32 flags; +} PACKED; + +struct acpi_table_header /* ACPI common table header */ +{ + ACPI_TABLE_HEADER_DEF +} PACKED; + +/* + * ACPI 1.0 Root System Description Table (RSDT) + */ +#define RSDT_SIGNATURE 0x54445352 // RSDT +struct rsdt_descriptor_rev1 +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 table_offset_entry[0]; /* Array of pointers to other */ + /* ACPI tables */ +} PACKED; + +/* + * ACPI 1.0 Firmware ACPI Control Structure (FACS) + */ +#define FACS_SIGNATURE 0x53434146 // FACS +struct facs_descriptor_rev1 +{ + u32 signature; /* ACPI Signature */ + u32 length; /* Length of structure, in bytes */ + u32 hardware_signature; /* Hardware configuration signature */ + u32 firmware_waking_vector; /* ACPI OS waking vector */ + u32 global_lock; /* Global Lock */ + u32 flags; + u8 resverved3 [40]; /* Reserved - must be zero */ +} PACKED; + +/* + * Differentiated System Description Table (DSDT) + */ +#define DSDT_SIGNATURE 0x54445344 // DSDT + +/* + * MADT values and structures + */ + +/* Values for MADT PCATCompat */ + +#define DUAL_PIC 0 +#define MULTIPLE_APIC 1 + +/* Master MADT */ + +#define APIC_SIGNATURE 0x43495041 // APIC +struct multiple_apic_table +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 local_apic_address; /* Physical address of local APIC */ + u32 flags; +} PACKED; + +/* Values for Type in APIC sub-headers */ + +#define APIC_PROCESSOR 0 +#define APIC_IO 1 +#define APIC_XRUPT_OVERRIDE 2 +#define APIC_NMI 3 +#define APIC_LOCAL_NMI 4 +#define APIC_ADDRESS_OVERRIDE 5 +#define APIC_IO_SAPIC 6 +#define APIC_LOCAL_SAPIC 7 +#define APIC_XRUPT_SOURCE 8 +#define APIC_RESERVED 9 /* 9 and greater are reserved */ + +/* + * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) + */ +#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\ + u8 type; \ + u8 length; + +/* Sub-structures for MADT */ + +struct madt_processor_apic +{ + ACPI_SUB_HEADER_DEF + u8 processor_id; /* ACPI processor id */ + u8 local_apic_id; /* Processor's local APIC id */ + u32 flags; +} PACKED; + +struct madt_io_apic +{ + ACPI_SUB_HEADER_DEF + u8 io_apic_id; /* I/O APIC ID */ + u8 reserved; /* Reserved - must be zero */ + u32 address; /* APIC physical address */ + u32 interrupt; /* Global system interrupt where INTI + * lines start */ +} PACKED; + +struct madt_intsrcovr { + ACPI_SUB_HEADER_DEF + u8 bus; + u8 source; + u32 gsi; + u16 flags; +} PACKED; + +struct madt_local_nmi { + ACPI_SUB_HEADER_DEF + u8 processor_id; /* ACPI processor id */ + u16 flags; /* MPS INTI flags */ + u8 lint; /* Local APIC LINT# */ +} PACKED; + +/* + * HPET Description Table + */ +#define HPET_SIGNATURE 0x54455048 // HPET +struct acpi_20_hpet { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 timer_block_id; + struct acpi_20_generic_address addr; + u8 hpet_number; + u16 min_tick; + u8 page_protect; +} PACKED; + +/* + * SRAT (NUMA topology description) table + */ + +#define SRAT_SIGNATURE 0x54415253 // SRAT +struct system_resource_affinity_table +{ + ACPI_TABLE_HEADER_DEF + u32 reserved1; + u32 reserved2[2]; +} PACKED; + +#define SRAT_PROCESSOR 0 +#define SRAT_MEMORY 1 + +struct srat_processor_affinity +{ + ACPI_SUB_HEADER_DEF + u8 proximity_lo; + u8 local_apic_id; + u32 flags; + u8 local_sapic_eid; + u8 proximity_hi[3]; + u32 reserved; +} PACKED; + +struct srat_memory_affinity +{ + ACPI_SUB_HEADER_DEF + u8 proximity[4]; + u16 reserved1; + u64 base_addr; + u64 range_length; + u32 reserved2; + u32 flags; + u32 reserved3[2]; +} PACKED; + +/* PCI fw r3.0 MCFG table. */ +/* Subtable */ +struct acpi_mcfg_allocation { + u64 address; /* Base address, processor-relative */ + u16 pci_segment; /* PCI segment group number */ + u8 start_bus_number; /* Starting PCI Bus number */ + u8 end_bus_number; /* Final PCI Bus number */ + u32 reserved; +} PACKED; + +#define MCFG_SIGNATURE 0x4746434d // MCFG +struct acpi_table_mcfg { + ACPI_TABLE_HEADER_DEF; + u8 reserved[8]; + struct acpi_mcfg_allocation allocation[0]; +} PACKED; + +#endif // acpi.h diff -Nru seabios-1.7.1/src/std/bda.h seabios-1.7.4/src/std/bda.h --- seabios-1.7.1/src/std/bda.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/bda.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,159 @@ +// BIOS Data Area (and similar) definitions +#ifndef __BDA_H +#define __BDA_H + +#include "disk.h" // struct fdpt_s +#include "types.h" // u8 + + +/**************************************************************** + * Interupt vector table + ****************************************************************/ + +struct rmode_IVT { + struct segoff_s ivec[256]; +}; + + +/**************************************************************** + * Bios Data Area (BDA) + ****************************************************************/ + +struct bios_data_area_s { + // 40:00 + u16 port_com[4]; + u16 port_lpt[3]; + u16 ebda_seg; + // 40:10 + u16 equipment_list_flags; + u8 pad1; + u16 mem_size_kb; + u8 pad2; + u8 ps2_ctrl_flag; + u8 kbd_flag0; + u8 kbd_flag1; + u8 alt_keypad; + u16 kbd_buf_head; + u16 kbd_buf_tail; + // 40:1e + u8 kbd_buf[32]; + u8 floppy_recalibration_status; + u8 floppy_motor_status; + // 40:40 + u8 floppy_motor_counter; + u8 floppy_last_status; + u8 floppy_return_status[7]; + u8 video_mode; + u16 video_cols; + u16 video_pagesize; + u16 video_pagestart; + // 40:50 + u16 cursor_pos[8]; + // 40:60 + u16 cursor_type; + u8 video_page; + u16 crtc_address; + u8 video_msr; + u8 video_pal; + struct segoff_s jump; + u8 other_6b; + u32 timer_counter; + // 40:70 + u8 timer_rollover; + u8 break_flag; + u16 soft_reset_flag; + u8 disk_last_status; + u8 hdcount; + u8 disk_control_byte; + u8 port_disk; + u8 lpt_timeout[4]; + u8 com_timeout[4]; + // 40:80 + u16 kbd_buf_start_offset; + u16 kbd_buf_end_offset; + u8 video_rows; + u16 char_height; + u8 video_ctl; + u8 video_switches; + u8 modeset_ctl; + u8 dcc_index; + u8 floppy_last_data_rate; + u8 disk_status_controller; + u8 disk_error_controller; + u8 disk_interrupt_flag; + u8 floppy_harddisk_info; + // 40:90 + u8 floppy_media_state[4]; + u8 floppy_track[2]; + u8 kbd_flag2; + u8 kbd_led; + struct segoff_s user_wait_complete_flag; + u32 user_wait_timeout; + // 40:A0 + u8 rtc_wait_flag; + u8 other_a1[7]; + struct segoff_s video_savetable; + u8 other_ac[4]; + // 40:B0 + u8 other_b0[9]; + u8 vbe_flag; + u16 vbe_mode; + u8 other_bc[4]; + // 40:C0 + u8 other_c0[4*16]; +} PACKED; + +// BDA floppy_recalibration_status bitdefs +#define FRS_IRQ (1<<7) + +// BDA rtc_wait_flag bitdefs +#define RWS_WAIT_PENDING (1<<0) +#define RWS_WAIT_ELAPSED (1<<7) + +// BDA floppy_media_state bitdefs +#define FMS_DRIVE_STATE_MASK (0x07) +#define FMS_MEDIA_DRIVE_ESTABLISHED (1<<4) +#define FMS_DOUBLE_STEPPING (1<<5) +#define FMS_DATA_RATE_MASK (0xc0) + +// Limit of BDA timer_counter field +#define TICKS_PER_DAY 1573040 + + +/**************************************************************** + * Extended Bios Data Area (EBDA) + ****************************************************************/ + +struct extended_bios_data_area_s { + u8 size; + u8 reserved1[0x21]; + struct segoff_s far_call_pointer; + u8 mouse_flag1; + u8 mouse_flag2; + u8 mouse_data[0x08]; + // 0x30 + u8 other1[0x0d]; + + // 0x3d + struct fdpt_s fdpt[2]; + + // 0x5d + u8 other2[0xC4]; + + // 0x121 - Begin custom storage. +} PACKED; + + +/**************************************************************** + * Bios Config Table + ****************************************************************/ + +struct bios_config_table_s { + u16 size; + u8 model; + u8 submodel; + u8 biosrev; + u8 feature1, feature2, feature3, feature4, feature5; +} PACKED; + +#endif // bda.h diff -Nru seabios-1.7.1/src/std/disk.h seabios-1.7.4/src/std/disk.h --- seabios-1.7.1/src/std/disk.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/disk.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,177 @@ +// Standard disk BIOS definitions. +#ifndef __DISK_H +#define __DISK_H + +#include "types.h" // u8 + +#define DISK_RET_SUCCESS 0x00 +#define DISK_RET_EPARAM 0x01 +#define DISK_RET_EADDRNOTFOUND 0x02 +#define DISK_RET_EWRITEPROTECT 0x03 +#define DISK_RET_ECHANGED 0x06 +#define DISK_RET_EBOUNDARY 0x09 +#define DISK_RET_EBADTRACK 0x0c +#define DISK_RET_ECONTROLLER 0x20 +#define DISK_RET_ETIMEOUT 0x80 +#define DISK_RET_ENOTLOCKED 0xb0 +#define DISK_RET_ELOCKED 0xb1 +#define DISK_RET_ENOTREMOVABLE 0xb2 +#define DISK_RET_ETOOMANYLOCKS 0xb4 +#define DISK_RET_EMEDIA 0xC0 +#define DISK_RET_ENOTREADY 0xAA + + +/**************************************************************** + * Interface structs + ****************************************************************/ + +// Bios disk structures. +struct int13ext_s { + u8 size; + u8 reserved; + u16 count; + struct segoff_s data; + u64 lba; +} PACKED; + +// DPTE definition +struct dpte_s { + u16 iobase1; + u16 iobase2; + u8 prefix; + u8 unused; + u8 irq; + u8 blkcount; + u8 dma; + u8 pio; + u16 options; + u16 reserved; + u8 revision; + u8 checksum; +}; + +// Disk Physical Table definition +struct int13dpt_s { + u16 size; + u16 infos; + u32 cylinders; + u32 heads; + u32 spt; + u64 sector_count; + u16 blksize; + struct segoff_s dpte; + u16 key; + u8 dpi_length; + u8 reserved1; + u16 reserved2; + u8 host_bus[4]; + u8 iface_type[8]; + u64 iface_path; + union { + struct { + u64 device_path; + u8 reserved3; + u8 checksum; + } phoenix; + struct { + u64 device_path[2]; + u8 reserved3; + u8 checksum; + } t13; + }; +} PACKED; + +// Floppy info +struct fdpt_s { + u16 cylinders; + u8 heads; + u8 a0h_signature; + u8 phys_sectors; + u16 precompensation; + u8 reserved; + u8 drive_control_byte; + u16 phys_cylinders; + u8 phys_heads; + u16 landing_zone; + u8 sectors; + u8 checksum; +} PACKED; + +// Floppy "Disk Base Table" +struct floppy_dbt_s { + u8 specify1; + u8 specify2; + u8 shutoff_ticks; + u8 bps_code; + u8 sectors; + u8 interblock_len; + u8 data_len; + u8 gap_len; + u8 fill_byte; + u8 settle_time; + u8 startup_time; +} PACKED; + +struct floppy_ext_dbt_s { + struct floppy_dbt_s dbt; + // Extra fields + u8 max_track; + u8 data_rate; + u8 drive_type; +} PACKED; + + +/**************************************************************** + * Master boot record + ****************************************************************/ + +struct packed_chs_s { + u8 heads; + u8 sptcyl; + u8 cyllow; +}; + +struct partition_s { + u8 status; + struct packed_chs_s first; + u8 type; + struct packed_chs_s last; + u32 lba; + u32 count; +} PACKED; + +struct mbr_s { + u8 code[440]; + // 0x01b8 + u32 diskseg; + // 0x01bc + u16 null; + // 0x01be + struct partition_s partitions[4]; + // 0x01fe + u16 signature; +} PACKED; + +#define MBR_SIGNATURE 0xaa55 + + +/**************************************************************** + * ElTorito CDROM interface + ****************************************************************/ + +struct eltorito_s { + u8 size; + u8 media; + u8 emulated_drive; + u8 controller_index; + u32 ilba; + u16 device_spec; + u16 buffer_segment; + u16 load_segment; + u16 sector_count; + u8 cylinders; + u8 sectors; + u8 heads; +}; + +#endif // disk.h diff -Nru seabios-1.7.1/src/std/LegacyBios.h seabios-1.7.4/src/std/LegacyBios.h --- seabios-1.7.1/src/std/LegacyBios.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/LegacyBios.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,965 @@ +/** @file + The EFI Legacy BIOS Protocol is used to abstract legacy Option ROM usage + under EFI and Legacy OS boot. This file also includes all the related + COMPATIBILIY16 structures and defintions. + + Note: The names for EFI_IA32_REGISTER_SET elements were picked to follow + well known naming conventions. + + Thunk is the code that switches from 32-bit protected environment into the 16-bit real-mode + environment. Reverse thunk is the code that does the opposite. + +Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Module spec + Version 0.97. + +**/ + +#ifndef _EFI_LEGACY_BIOS_H_ +#define _EFI_LEGACY_BIOS_H_ + +/// +/// +/// +#pragma pack(1) + +typedef UINT8 SERIAL_MODE; +typedef UINT8 PARALLEL_MODE; + +#define EFI_COMPATIBILITY16_TABLE_SIGNATURE SIGNATURE_32 ('I', 'F', 'E', '$') + +/// +/// There is a table located within the traditional BIOS in either the 0xF000:xxxx or 0xE000:xxxx +/// physical address range. It is located on a 16-byte boundary and provides the physical address of the +/// entry point for the Compatibility16 functions. These functions provide the platform-specific +/// information that is required by the generic EfiCompatibility code. The functions are invoked via +/// thunking by using EFI_LEGACY_BIOS_PROTOCOL.FarCall86() with the 32-bit physical +/// entry point. +/// +typedef struct { + /// + /// The string "$EFI" denotes the start of the EfiCompatibility table. Byte 0 is "I," byte + /// 1 is "F," byte 2 is "E," and byte 3 is "$" and is normally accessed as a DWORD or UINT32. + /// + UINT32 Signature; + + /// + /// The value required such that byte checksum of TableLength equals zero. + /// + UINT8 TableChecksum; + + /// + /// The length of this table. + /// + UINT8 TableLength; + + /// + /// The major EFI revision for which this table was generated. + /// + UINT8 EfiMajorRevision; + + /// + /// The minor EFI revision for which this table was generated. + /// + UINT8 EfiMinorRevision; + + /// + /// The major revision of this table. + /// + UINT8 TableMajorRevision; + + /// + /// The minor revision of this table. + /// + UINT8 TableMinorRevision; + + /// + /// Reserved for future usage. + /// + UINT16 Reserved; + + /// + /// The segment of the entry point within the traditional BIOS for Compatibility16 functions. + /// + UINT16 Compatibility16CallSegment; + + /// + /// The offset of the entry point within the traditional BIOS for Compatibility16 functions. + /// + UINT16 Compatibility16CallOffset; + + /// + /// The segment of the entry point within the traditional BIOS for EfiCompatibility + /// to invoke the PnP installation check. + /// + UINT16 PnPInstallationCheckSegment; + + /// + /// The Offset of the entry point within the traditional BIOS for EfiCompatibility + /// to invoke the PnP installation check. + /// + UINT16 PnPInstallationCheckOffset; + + /// + /// EFI system resources table. Type EFI_SYSTEM_TABLE is defined in the IntelPlatform + ///Innovation Framework for EFI Driver Execution Environment Core Interface Specification (DXE CIS). + /// + UINT32 EfiSystemTable; + + /// + /// The address of an OEM-provided identifier string. The string is null terminated. + /// + UINT32 OemIdStringPointer; + + /// + /// The 32-bit physical address where ACPI RSD PTR is stored within the traditional + /// BIOS. The remained of the ACPI tables are located at their EFI addresses. The size + /// reserved is the maximum for ACPI 2.0. The EfiCompatibility will fill in the ACPI + /// RSD PTR with either the ACPI 1.0b or 2.0 values. + /// + UINT32 AcpiRsdPtrPointer; + + /// + /// The OEM revision number. Usage is undefined but provided for OEM module usage. + /// + UINT16 OemRevision; + + /// + /// The 32-bit physical address where INT15 E820 data is stored within the traditional + /// BIOS. The EfiCompatibility code will fill in the E820Pointer value and copy the + /// data to the indicated area. + /// + UINT32 E820Pointer; + + /// + /// The length of the E820 data and is filled in by the EfiCompatibility code. + /// + UINT32 E820Length; + + /// + /// The 32-bit physical address where the $PIR table is stored in the traditional BIOS. + /// The EfiCompatibility code will fill in the IrqRoutingTablePointer value and + /// copy the data to the indicated area. + /// + UINT32 IrqRoutingTablePointer; + + /// + /// The length of the $PIR table and is filled in by the EfiCompatibility code. + /// + UINT32 IrqRoutingTableLength; + + /// + /// The 32-bit physical address where the MP table is stored in the traditional BIOS. + /// The EfiCompatibility code will fill in the MpTablePtr value and copy the data + /// to the indicated area. + /// + UINT32 MpTablePtr; + + /// + /// The length of the MP table and is filled in by the EfiCompatibility code. + /// + UINT32 MpTableLength; + + /// + /// The segment of the OEM-specific INT table/code. + /// + UINT16 OemIntSegment; + + /// + /// The offset of the OEM-specific INT table/code. + /// + UINT16 OemIntOffset; + + /// + /// The segment of the OEM-specific 32-bit table/code. + /// + UINT16 Oem32Segment; + + /// + /// The offset of the OEM-specific 32-bit table/code. + /// + UINT16 Oem32Offset; + + /// + /// The segment of the OEM-specific 16-bit table/code. + /// + UINT16 Oem16Segment; + + /// + /// The offset of the OEM-specific 16-bit table/code. + /// + UINT16 Oem16Offset; + + /// + /// The segment of the TPM binary passed to 16-bit CSM. + /// + UINT16 TpmSegment; + + /// + /// The offset of the TPM binary passed to 16-bit CSM. + /// + UINT16 TpmOffset; + + /// + /// A pointer to a string identifying the independent BIOS vendor. + /// + UINT32 IbvPointer; + + /// + /// This field is NULL for all systems not supporting PCI Express. This field is the base + /// value of the start of the PCI Express memory-mapped configuration registers and + /// must be filled in prior to EfiCompatibility code issuing the Compatibility16 function + /// Compatibility16InitializeYourself(). + /// Compatibility16InitializeYourself() is defined in Compatability16 + /// Functions. + /// + UINT32 PciExpressBase; + + /// + /// Maximum PCI bus number assigned. + /// + UINT8 LastPciBus; +} EFI_COMPATIBILITY16_TABLE; + +/// +/// Functions provided by the CSM binary which communicate between the EfiCompatibility +/// and Compatability16 code. +/// +/// Inconsistent with the specification here: +/// The member's name started with "Compatibility16" [defined in Intel Framework +/// Compatibility Support Module Specification / 0.97 version] +/// has been changed to "Legacy16" since keeping backward compatible. +/// +typedef enum { + /// + /// Causes the Compatibility16 code to do any internal initialization required. + /// Input: + /// AX = Compatibility16InitializeYourself + /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_INIT_TABLE + /// Return: + /// AX = Return Status codes + /// + Legacy16InitializeYourself = 0x0000, + + /// + /// Causes the Compatibility16 BIOS to perform any drive number translations to match the boot sequence. + /// Input: + /// AX = Compatibility16UpdateBbs + /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE + /// Return: + /// AX = Returned status codes + /// + Legacy16UpdateBbs = 0x0001, + + /// + /// Allows the Compatibility16 code to perform any final actions before booting. The Compatibility16 + /// code is read/write. + /// Input: + /// AX = Compatibility16PrepareToBoot + /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure + /// Return: + /// AX = Returned status codes + /// + Legacy16PrepareToBoot = 0x0002, + + /// + /// Causes the Compatibility16 BIOS to boot. The Compatibility16 code is Read/Only. + /// Input: + /// AX = Compatibility16Boot + /// Output: + /// AX = Returned status codes + /// + Legacy16Boot = 0x0003, + + /// + /// Allows the Compatibility16 code to get the last device from which a boot was attempted. This is + /// stored in CMOS and is the priority number of the last attempted boot device. + /// Input: + /// AX = Compatibility16RetrieveLastBootDevice + /// Output: + /// AX = Returned status codes + /// BX = Priority number of the boot device. + /// + Legacy16RetrieveLastBootDevice = 0x0004, + + /// + /// Allows the Compatibility16 code rehook INT13, INT18, and/or INT19 after dispatching a legacy OpROM. + /// Input: + /// AX = Compatibility16DispatchOprom + /// ES:BX = Pointer to EFI_DISPATCH_OPROM_TABLE + /// Output: + /// AX = Returned status codes + /// BX = Number of non-BBS-compliant devices found. Equals 0 if BBS compliant. + /// + Legacy16DispatchOprom = 0x0005, + + /// + /// Finds a free area in the 0xFxxxx or 0xExxxx region of the specified length and returns the address + /// of that region. + /// Input: + /// AX = Compatibility16GetTableAddress + /// BX = Allocation region + /// 00 = Allocate from either 0xE0000 or 0xF0000 64 KB blocks. + /// Bit 0 = 1 Allocate from 0xF0000 64 KB block + /// Bit 1 = 1 Allocate from 0xE0000 64 KB block + /// CX = Requested length in bytes. + /// DX = Required address alignment. Bit mapped. First non-zero bit from the right is the alignment. + /// Output: + /// AX = Returned status codes + /// DS:BX = Address of the region + /// + Legacy16GetTableAddress = 0x0006, + + /// + /// Enables the EfiCompatibility module to do any nonstandard processing of keyboard LEDs or state. + /// Input: + /// AX = Compatibility16SetKeyboardLeds + /// CL = LED status. + /// Bit 0 Scroll Lock 0 = Off + /// Bit 1 NumLock + /// Bit 2 Caps Lock + /// Output: + /// AX = Returned status codes + /// + Legacy16SetKeyboardLeds = 0x0007, + + /// + /// Enables the EfiCompatibility module to install an interrupt handler for PCI mass media devices that + /// do not have an OpROM associated with them. An example is SATA. + /// Input: + /// AX = Compatibility16InstallPciHandler + /// ES:BX = Pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure + /// Output: + /// AX = Returned status codes + /// + Legacy16InstallPciHandler = 0x0008 +} EFI_COMPATIBILITY_FUNCTIONS; + + +/// +/// EFI_DISPATCH_OPROM_TABLE +/// +typedef struct { + UINT16 PnPInstallationCheckSegment; ///< A pointer to the PnpInstallationCheck data structure. + UINT16 PnPInstallationCheckOffset; ///< A pointer to the PnpInstallationCheck data structure. + UINT16 OpromSegment; ///< The segment where the OpROM was placed. Offset is assumed to be 3. + UINT8 PciBus; ///< The PCI bus. + UINT8 PciDeviceFunction; ///< The PCI device * 0x08 | PCI function. + UINT8 NumberBbsEntries; ///< The number of valid BBS table entries upon entry and exit. The IBV code may + ///< increase this number, if BBS-compliant devices also hook INTs in order to force the + ///< OpROM BIOS Setup to be executed. + UINT32 BbsTablePointer; ///< A pointer to the BBS table. + UINT16 RuntimeSegment; ///< The segment where the OpROM can be relocated to. If this value is 0x0000, this + ///< means that the relocation of this run time code is not supported. + ///< Inconsistent with specification here: + ///< The member's name "OpromDestinationSegment" [defined in Intel Framework Compatibility Support Module Specification / 0.97 version] + ///< has been changed to "RuntimeSegment" since keeping backward compatible. + +} EFI_DISPATCH_OPROM_TABLE; + +/// +/// EFI_TO_COMPATIBILITY16_INIT_TABLE +/// +typedef struct { + /// + /// Starting address of memory under 1 MB. The ending address is assumed to be 640 KB or 0x9FFFF. + /// + UINT32 BiosLessThan1MB; + + /// + /// The starting address of the high memory block. + /// + UINT32 HiPmmMemory; + + /// + /// The length of high memory block. + /// + UINT32 HiPmmMemorySizeInBytes; + + /// + /// The segment of the reverse thunk call code. + /// + UINT16 ReverseThunkCallSegment; + + /// + /// The offset of the reverse thunk call code. + /// + UINT16 ReverseThunkCallOffset; + + /// + /// The number of E820 entries copied to the Compatibility16 BIOS. + /// + UINT32 NumberE820Entries; + + /// + /// The amount of usable memory above 1 MB, e.g., E820 type 1 memory. + /// + UINT32 OsMemoryAbove1Mb; + + /// + /// The start of thunk code in main memory. Memory cannot be used by BIOS or PMM. + /// + UINT32 ThunkStart; + + /// + /// The size of the thunk code. + /// + UINT32 ThunkSizeInBytes; + + /// + /// Starting address of memory under 1 MB. + /// + UINT32 LowPmmMemory; + + /// + /// The length of low Memory block. + /// + UINT32 LowPmmMemorySizeInBytes; +} EFI_TO_COMPATIBILITY16_INIT_TABLE; + +/// +/// DEVICE_PRODUCER_SERIAL. +/// +typedef struct { + UINT16 Address; ///< I/O address assigned to the serial port. + UINT8 Irq; ///< IRQ assigned to the serial port. + SERIAL_MODE Mode; ///< Mode of serial port. Values are defined below. +} DEVICE_PRODUCER_SERIAL; + +/// +/// DEVICE_PRODUCER_SERIAL's modes. +///@{ +#define DEVICE_SERIAL_MODE_NORMAL 0x00 +#define DEVICE_SERIAL_MODE_IRDA 0x01 +#define DEVICE_SERIAL_MODE_ASK_IR 0x02 +#define DEVICE_SERIAL_MODE_DUPLEX_HALF 0x00 +#define DEVICE_SERIAL_MODE_DUPLEX_FULL 0x10 +///@) + +/// +/// DEVICE_PRODUCER_PARALLEL. +/// +typedef struct { + UINT16 Address; ///< I/O address assigned to the parallel port. + UINT8 Irq; ///< IRQ assigned to the parallel port. + UINT8 Dma; ///< DMA assigned to the parallel port. + PARALLEL_MODE Mode; ///< Mode of the parallel port. Values are defined below. +} DEVICE_PRODUCER_PARALLEL; + +/// +/// DEVICE_PRODUCER_PARALLEL's modes. +///@{ +#define DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY 0x00 +#define DEVICE_PARALLEL_MODE_MODE_BIDIRECTIONAL 0x01 +#define DEVICE_PARALLEL_MODE_MODE_EPP 0x02 +#define DEVICE_PARALLEL_MODE_MODE_ECP 0x03 +///@} + +/// +/// DEVICE_PRODUCER_FLOPPY +/// +typedef struct { + UINT16 Address; ///< I/O address assigned to the floppy. + UINT8 Irq; ///< IRQ assigned to the floppy. + UINT8 Dma; ///< DMA assigned to the floppy. + UINT8 NumberOfFloppy; ///< Number of floppies in the system. +} DEVICE_PRODUCER_FLOPPY; + +/// +/// LEGACY_DEVICE_FLAGS +/// +typedef struct { + UINT32 A20Kybd : 1; ///< A20 controller by keyboard controller. + UINT32 A20Port90 : 1; ///< A20 controlled by port 0x92. + UINT32 Reserved : 30; ///< Reserved for future usage. +} LEGACY_DEVICE_FLAGS; + +/// +/// DEVICE_PRODUCER_DATA_HEADER +/// +typedef struct { + DEVICE_PRODUCER_SERIAL Serial[4]; ///< Data for serial port x. Type DEVICE_PRODUCER_SERIAL is defined below. + DEVICE_PRODUCER_PARALLEL Parallel[3]; ///< Data for parallel port x. Type DEVICE_PRODUCER_PARALLEL is defined below. + DEVICE_PRODUCER_FLOPPY Floppy; ///< Data for floppy. Type DEVICE_PRODUCER_FLOPPY is defined below. + UINT8 MousePresent; ///< Flag to indicate if mouse is present. + LEGACY_DEVICE_FLAGS Flags; ///< Miscellaneous Boolean state information passed to CSM. +} DEVICE_PRODUCER_DATA_HEADER; + +/// +/// ATAPI_IDENTIFY +/// +typedef struct { + UINT16 Raw[256]; ///< Raw data from the IDE IdentifyDrive command. +} ATAPI_IDENTIFY; + +/// +/// HDD_INFO +/// +typedef struct { + /// + /// Status of IDE device. Values are defined below. There is one HDD_INFO structure + /// per IDE controller. The IdentifyDrive is per drive. Index 0 is master and index + /// 1 is slave. + /// + UINT16 Status; + + /// + /// PCI bus of IDE controller. + /// + UINT32 Bus; + + /// + /// PCI device of IDE controller. + /// + UINT32 Device; + + /// + /// PCI function of IDE controller. + /// + UINT32 Function; + + /// + /// Command ports base address. + /// + UINT16 CommandBaseAddress; + + /// + /// Control ports base address. + /// + UINT16 ControlBaseAddress; + + /// + /// Bus master address. + /// + UINT16 BusMasterAddress; + + UINT8 HddIrq; + + /// + /// Data that identifies the drive data; one per possible attached drive. + /// + ATAPI_IDENTIFY IdentifyDrive[2]; +} HDD_INFO; + +/// +/// HDD_INFO status bits +/// +#define HDD_PRIMARY 0x01 +#define HDD_SECONDARY 0x02 +#define HDD_MASTER_ATAPI_CDROM 0x04 +#define HDD_SLAVE_ATAPI_CDROM 0x08 +#define HDD_MASTER_IDE 0x20 +#define HDD_SLAVE_IDE 0x40 +#define HDD_MASTER_ATAPI_ZIPDISK 0x10 +#define HDD_SLAVE_ATAPI_ZIPDISK 0x80 + +/// +/// BBS_STATUS_FLAGS;\. +/// +typedef struct { + UINT16 OldPosition : 4; ///< Prior priority. + UINT16 Reserved1 : 4; ///< Reserved for future use. + UINT16 Enabled : 1; ///< If 0, ignore this entry. + UINT16 Failed : 1; ///< 0 = Not known if boot failure occurred. + ///< 1 = Boot attempted failed. + + /// + /// State of media present. + /// 00 = No bootable media is present in the device. + /// 01 = Unknown if a bootable media present. + /// 10 = Media is present and appears bootable. + /// 11 = Reserved. + /// + UINT16 MediaPresent : 2; + UINT16 Reserved2 : 4; ///< Reserved for future use. +} BBS_STATUS_FLAGS; + +/// +/// BBS_TABLE, device type values & boot priority values. +/// +typedef struct { + /// + /// The boot priority for this boot device. Values are defined below. + /// + UINT16 BootPriority; + + /// + /// The PCI bus for this boot device. + /// + UINT32 Bus; + + /// + /// The PCI device for this boot device. + /// + UINT32 Device; + + /// + /// The PCI function for the boot device. + /// + UINT32 Function; + + /// + /// The PCI class for this boot device. + /// + UINT8 Class; + + /// + /// The PCI Subclass for this boot device. + /// + UINT8 SubClass; + + /// + /// Segment:offset address of an ASCIIZ description string describing the manufacturer. + /// + UINT16 MfgStringOffset; + + /// + /// Segment:offset address of an ASCIIZ description string describing the manufacturer. + /// + UINT16 MfgStringSegment; + + /// + /// BBS device type. BBS device types are defined below. + /// + UINT16 DeviceType; + + /// + /// Status of this boot device. Type BBS_STATUS_FLAGS is defined below. + /// + BBS_STATUS_FLAGS StatusFlags; + + /// + /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for + /// BCV devices. + /// + UINT16 BootHandlerOffset; + + /// + /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for + /// BCV devices. + /// + UINT16 BootHandlerSegment; + + /// + /// Segment:offset address of an ASCIIZ description string describing this device. + /// + UINT16 DescStringOffset; + + /// + /// Segment:offset address of an ASCIIZ description string describing this device. + /// + UINT16 DescStringSegment; + + /// + /// Reserved. + /// + UINT32 InitPerReserved; + + /// + /// The use of these fields is IBV dependent. They can be used to flag that an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup + /// + UINT32 AdditionalIrq13Handler; + + /// + /// The use of these fields is IBV dependent. They can be used to flag that an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup + /// + UINT32 AdditionalIrq18Handler; + + /// + /// The use of these fields is IBV dependent. They can be used to flag that an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup + /// + UINT32 AdditionalIrq19Handler; + + /// + /// The use of these fields is IBV dependent. They can be used to flag that an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup + /// + UINT32 AdditionalIrq40Handler; + UINT8 AssignedDriveNumber; + UINT32 AdditionalIrq41Handler; + UINT32 AdditionalIrq46Handler; + UINT32 IBV1; + UINT32 IBV2; +} BBS_TABLE; + +/// +/// BBS device type values +///@{ +#define BBS_FLOPPY 0x01 +#define BBS_HARDDISK 0x02 +#define BBS_CDROM 0x03 +#define BBS_PCMCIA 0x04 +#define BBS_USB 0x05 +#define BBS_EMBED_NETWORK 0x06 +#define BBS_BEV_DEVICE 0x80 +#define BBS_UNKNOWN 0xff +///@} + +/// +/// BBS boot priority values +///@{ +#define BBS_DO_NOT_BOOT_FROM 0xFFFC +#define BBS_LOWEST_PRIORITY 0xFFFD +#define BBS_UNPRIORITIZED_ENTRY 0xFFFE +#define BBS_IGNORE_ENTRY 0xFFFF +///@} + +/// +/// SMM_ATTRIBUTES +/// +typedef struct { + /// + /// Access mechanism used to generate the soft SMI. Defined types are below. The other + /// values are reserved for future usage. + /// + UINT16 Type : 3; + + /// + /// The size of "port" in bits. Defined values are below. + /// + UINT16 PortGranularity : 3; + + /// + /// The size of data in bits. Defined values are below. + /// + UINT16 DataGranularity : 3; + + /// + /// Reserved for future use. + /// + UINT16 Reserved : 7; +} SMM_ATTRIBUTES; + +/// +/// SMM_ATTRIBUTES type values. +///@{ +#define STANDARD_IO 0x00 +#define STANDARD_MEMORY 0x01 +///@} + +/// +/// SMM_ATTRIBUTES port size constants. +///@{ +#define PORT_SIZE_8 0x00 +#define PORT_SIZE_16 0x01 +#define PORT_SIZE_32 0x02 +#define PORT_SIZE_64 0x03 +///@} + +/// +/// SMM_ATTRIBUTES data size constants. +///@{ +#define DATA_SIZE_8 0x00 +#define DATA_SIZE_16 0x01 +#define DATA_SIZE_32 0x02 +#define DATA_SIZE_64 0x03 +///@} + +/// +/// SMM_FUNCTION & relating constants. +/// +typedef struct { + UINT16 Function : 15; + UINT16 Owner : 1; +} SMM_FUNCTION; + +/// +/// SMM_FUNCTION Function constants. +///@{ +#define INT15_D042 0x0000 +#define GET_USB_BOOT_INFO 0x0001 +#define DMI_PNP_50_57 0x0002 +///@} + +/// +/// SMM_FUNCTION Owner constants. +///@{ +#define STANDARD_OWNER 0x0 +#define OEM_OWNER 0x1 +///@} + +/// +/// This structure assumes both port and data sizes are 1. SmmAttribute must be +/// properly to reflect that assumption. +/// +typedef struct { + /// + /// Describes the access mechanism, SmmPort, and SmmData sizes. Type + /// SMM_ATTRIBUTES is defined below. + /// + SMM_ATTRIBUTES SmmAttributes; + + /// + /// Function Soft SMI is to perform. Type SMM_FUNCTION is defined below. + /// + SMM_FUNCTION SmmFunction; + + /// + /// SmmPort size depends upon SmmAttributes and ranges from2 bytes to 16 bytes. + /// + UINT8 SmmPort; + + /// + /// SmmData size depends upon SmmAttributes and ranges from2 bytes to 16 bytes. + /// + UINT8 SmmData; +} SMM_ENTRY; + +/// +/// SMM_TABLE +/// +typedef struct { + UINT16 NumSmmEntries; ///< Number of entries represented by SmmEntry. + SMM_ENTRY SmmEntry; ///< One entry per function. Type SMM_ENTRY is defined below. +} SMM_TABLE; + +/// +/// UDC_ATTRIBUTES +/// +typedef struct { + /// + /// This bit set indicates that the ServiceAreaData is valid. + /// + UINT8 DirectoryServiceValidity : 1; + + /// + /// This bit set indicates to use the Reserve Area Boot Code Address (RACBA) only if + /// DirectoryServiceValidity is 0. + /// + UINT8 RabcaUsedFlag : 1; + + /// + /// This bit set indicates to execute hard disk diagnostics. + /// + UINT8 ExecuteHddDiagnosticsFlag : 1; + + /// + /// Reserved for future use. Set to 0. + /// + UINT8 Reserved : 5; +} UDC_ATTRIBUTES; + +/// +/// UD_TABLE +/// +typedef struct { + /// + /// This field contains the bit-mapped attributes of the PARTIES information. Type + /// UDC_ATTRIBUTES is defined below. + /// + UDC_ATTRIBUTES Attributes; + + /// + /// This field contains the zero-based device on which the selected + /// ServiceDataArea is present. It is 0 for master and 1 for the slave device. + /// + UINT8 DeviceNumber; + + /// + /// This field contains the zero-based index into the BbsTable for the parent device. + /// This index allows the user to reference the parent device information such as PCI + /// bus, device function. + /// + UINT8 BbsTableEntryNumberForParentDevice; + + /// + /// This field contains the zero-based index into the BbsTable for the boot entry. + /// + UINT8 BbsTableEntryNumberForBoot; + + /// + /// This field contains the zero-based index into the BbsTable for the HDD diagnostics entry. + /// + UINT8 BbsTableEntryNumberForHddDiag; + + /// + /// The raw Beer data. + /// + UINT8 BeerData[128]; + + /// + /// The raw data of selected service area. + /// + UINT8 ServiceAreaData[64]; +} UD_TABLE; + +#define EFI_TO_LEGACY_MAJOR_VERSION 0x02 +#define EFI_TO_LEGACY_MINOR_VERSION 0x00 +#define MAX_IDE_CONTROLLER 8 + +/// +/// EFI_TO_COMPATIBILITY16_BOOT_TABLE +/// +typedef struct { + UINT16 MajorVersion; ///< The EfiCompatibility major version number. + UINT16 MinorVersion; ///< The EfiCompatibility minor version number. + UINT32 AcpiTable; ///< The location of the RSDT ACPI table. < 4G range. + UINT32 SmbiosTable; ///< The location of the SMBIOS table in EFI memory. < 4G range. + UINT32 SmbiosTableLength; + // + // Legacy SIO state + // + DEVICE_PRODUCER_DATA_HEADER SioData; ///< Standard traditional device information. + UINT16 DevicePathType; ///< The default boot type. + UINT16 PciIrqMask; ///< Mask of which IRQs have been assigned to PCI. + UINT32 NumberE820Entries; ///< Number of E820 entries. The number can change from the + ///< Compatibility16InitializeYourself() function. + // + // Controller & Drive Identify[2] per controller information + // + HDD_INFO HddInfo[MAX_IDE_CONTROLLER]; ///< Hard disk drive information, including raw Identify Drive data. + UINT32 NumberBbsEntries; ///< Number of entries in the BBS table + UINT32 BbsTable; ///< A pointer to the BBS table. Type BBS_TABLE is defined below. + UINT32 SmmTable; ///< A pointer to the SMM table. Type SMM_TABLE is defined below. + UINT32 OsMemoryAbove1Mb; ///< The amount of usable memory above 1 MB, i.e. E820 type 1 memory. This value can + ///< differ from the value in EFI_TO_COMPATIBILITY16_INIT_TABLE as more + ///< memory may have been discovered. + UINT32 UnconventionalDeviceTable; ///< Information to boot off an unconventional device like a PARTIES partition. Type + ///< UD_TABLE is defined below. +} EFI_TO_COMPATIBILITY16_BOOT_TABLE; + +/// +/// EFI_LEGACY_INSTALL_PCI_HANDLER +/// +typedef struct { + UINT8 PciBus; ///< The PCI bus of the device. + UINT8 PciDeviceFun; ///< The PCI device in bits 7:3 and function in bits 2:0. + UINT8 PciSegment; ///< The PCI segment of the device. + UINT8 PciClass; ///< The PCI class code of the device. + UINT8 PciSubclass; ///< The PCI subclass code of the device. + UINT8 PciInterface; ///< The PCI interface code of the device. + // + // Primary section + // + UINT8 PrimaryIrq; ///< The primary device IRQ. + UINT8 PrimaryReserved; ///< Reserved. + UINT16 PrimaryControl; ///< The primary device control I/O base. + UINT16 PrimaryBase; ///< The primary device I/O base. + UINT16 PrimaryBusMaster; ///< The primary device bus master I/O base. + // + // Secondary Section + // + UINT8 SecondaryIrq; ///< The secondary device IRQ. + UINT8 SecondaryReserved; ///< Reserved. + UINT16 SecondaryControl; ///< The secondary device control I/O base. + UINT16 SecondaryBase; ///< The secondary device I/O base. + UINT16 SecondaryBusMaster; ///< The secondary device bus master I/O base. +} EFI_LEGACY_INSTALL_PCI_HANDLER; + +#endif diff -Nru seabios-1.7.1/src/std/mptable.h seabios-1.7.4/src/std/mptable.h --- seabios-1.7.1/src/std/mptable.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/mptable.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,77 @@ +#ifndef __MPTABLE_H +#define __MPTABLE_H + +#include "types.h" // u32 + +#define MPTABLE_SIGNATURE 0x5f504d5f // "_MP_" + +struct mptable_floating_s { + u32 signature; + u32 physaddr; + u8 length; + u8 spec_rev; + u8 checksum; + u8 feature1; + u8 feature2; + u8 reserved[3]; +}; + +#define MPCONFIG_SIGNATURE 0x504d4350 // "PCMP" + +struct mptable_config_s { + u32 signature; + u16 length; + u8 spec; + u8 checksum; + char oemid[8]; + char productid[12]; + u32 oemptr; + u16 oemsize; + u16 entrycount; + u32 lapic; + u16 exttable_length; + u8 exttable_checksum; + u8 reserved; +} PACKED; + +#define MPT_TYPE_CPU 0 +#define MPT_TYPE_BUS 1 +#define MPT_TYPE_IOAPIC 2 +#define MPT_TYPE_INTSRC 3 +#define MPT_TYPE_LOCAL_INT 4 + +struct mpt_cpu { + u8 type; + u8 apicid; + u8 apicver; + u8 cpuflag; + u32 cpusignature; + u32 featureflag; + u32 reserved[2]; +} PACKED; + +struct mpt_bus { + u8 type; + u8 busid; + char bustype[6]; +} PACKED; + +struct mpt_ioapic { + u8 type; + u8 apicid; + u8 apicver; + u8 flags; + u32 apicaddr; +} PACKED; + +struct mpt_intsrc { + u8 type; + u8 irqtype; + u16 irqflag; + u8 srcbus; + u8 srcbusirq; + u8 dstapic; + u8 dstirq; +} PACKED; + +#endif // mptable.h diff -Nru seabios-1.7.1/src/std/optionrom.h seabios-1.7.4/src/std/optionrom.h --- seabios-1.7.1/src/std/optionrom.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/optionrom.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,59 @@ +#ifndef __OPTIONROMS_H +#define __OPTIONROMS_H + +#include "types.h" // u32 + +#define OPTION_ROM_SIGNATURE 0xaa55 + +struct rom_header { + u16 signature; + u8 size; + u8 initVector[4]; + u8 reserved[17]; + u16 pcioffset; + u16 pnpoffset; +} PACKED; + +#define PCI_ROM_SIGNATURE 0x52494350 // "PCIR" + +struct pci_data { + u32 signature; + u16 vendor; + u16 device; + u16 vitaldata; + u16 dlen; + u8 drevision; + u8 class_lo; + u16 class_hi; + u16 ilen; + u16 irevision; + u8 type; + u8 indicator; + u16 reserved; +} PACKED; + +struct pnp_data { + u32 signature; + u8 revision; + u8 len; + u16 nextoffset; + u8 reserved_08; + u8 checksum; + u32 devid; + u16 manufacturer; + u16 productname; + u8 type_lo; + u16 type_hi; + u8 dev_flags; + u16 bcv; + u16 dv; + u16 bev; + u16 reserved_1c; + u16 staticresource; +} PACKED; + +#define OPTION_ROM_ALIGN 2048 +#define OPTION_ROM_INITVECTOR offsetof(struct rom_header, initVector[0]) +#define PCIROM_CODETYPE_X86 0 + +#endif diff -Nru seabios-1.7.1/src/std/pirtable.h seabios-1.7.4/src/std/pirtable.h --- seabios-1.7.1/src/std/pirtable.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/pirtable.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,35 @@ +#ifndef __PIRTABLE_H +#define __PIRTABLE_H + +#include "types.h" // u32 + +struct link_info { + u8 link; + u16 bitmap; +} PACKED; + +struct pir_slot { + u8 bus; + u8 dev; + struct link_info links[4]; + u8 slot_nr; + u8 reserved; +} PACKED; + +struct pir_header { + u32 signature; + u16 version; + u16 size; + u8 router_bus; + u8 router_devfunc; + u16 exclusive_irqs; + u32 compatible_devid; + u32 miniport_data; + u8 reserved[11]; + u8 checksum; + struct pir_slot slots[0]; +} PACKED; + +#define PIR_SIGNATURE 0x52495024 // $PIR + +#endif // pirtable.h diff -Nru seabios-1.7.1/src/std/pmm.h seabios-1.7.4/src/std/pmm.h --- seabios-1.7.1/src/std/pmm.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/pmm.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef __PMM_H +#define __PMM_H + +#include "types.h" // u32 + +#define PMM_SIGNATURE 0x4d4d5024 // $PMM + +struct pmmheader { + u32 signature; + u8 version; + u8 length; + u8 checksum; + struct segoff_s entry; + u8 reserved[5]; +} PACKED; + +#define PMM_FUNCTION_NOT_SUPPORTED 0xffffffff + +#endif // pmm.h diff -Nru seabios-1.7.1/src/std/pnpbios.h seabios-1.7.4/src/std/pnpbios.h --- seabios-1.7.1/src/std/pnpbios.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/pnpbios.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,24 @@ +#ifndef __PNPHEADER_H +#define __PNPHEADER_H + +#define PNP_SIGNATURE 0x506e5024 // $PnP + +struct pnpheader { + u32 signature; + u8 version; + u8 length; + u16 control; + u8 checksum; + u32 eventloc; + u16 real_ip; + u16 real_cs; + u16 prot_ip; + u32 prot_base; + u32 oemid; + u16 real_ds; + u32 prot_database; +} PACKED; + +#define FUNCTION_NOT_SUPPORTED 0x82 + +#endif // pnpheader.h diff -Nru seabios-1.7.1/src/std/smbios.h seabios-1.7.4/src/std/smbios.h --- seabios-1.7.1/src/std/smbios.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/smbios.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,165 @@ +#ifndef __SMBIOS_H +#define __SMBIOS_H + +#include "types.h" // u32 + +/* SMBIOS entry point -- must be written to a 16-bit aligned address + between 0xf0000 and 0xfffff. + */ +struct smbios_entry_point { + char anchor_string[4]; + u8 checksum; + u8 length; + u8 smbios_major_version; + u8 smbios_minor_version; + u16 max_structure_size; + u8 entry_point_revision; + u8 formatted_area[5]; + char intermediate_anchor_string[5]; + u8 intermediate_checksum; + u16 structure_table_length; + u32 structure_table_address; + u16 number_of_structures; + u8 smbios_bcd_revision; +} PACKED; + +/* This goes at the beginning of every SMBIOS structure. */ +struct smbios_structure_header { + u8 type; + u8 length; + u16 handle; +} PACKED; + +/* SMBIOS type 0 - BIOS Information */ +struct smbios_type_0 { + struct smbios_structure_header header; + u8 vendor_str; + u8 bios_version_str; + u16 bios_starting_address_segment; + u8 bios_release_date_str; + u8 bios_rom_size; + u8 bios_characteristics[8]; + u8 bios_characteristics_extension_bytes[2]; + u8 system_bios_major_release; + u8 system_bios_minor_release; + u8 embedded_controller_major_release; + u8 embedded_controller_minor_release; +} PACKED; + +/* SMBIOS type 1 - System Information */ +struct smbios_type_1 { + struct smbios_structure_header header; + u8 manufacturer_str; + u8 product_name_str; + u8 version_str; + u8 serial_number_str; + u8 uuid[16]; + u8 wake_up_type; + u8 sku_number_str; + u8 family_str; +} PACKED; + +/* SMBIOS type 3 - System Enclosure (v2.3) */ +struct smbios_type_3 { + struct smbios_structure_header header; + u8 manufacturer_str; + u8 type; + u8 version_str; + u8 serial_number_str; + u8 asset_tag_number_str; + u8 boot_up_state; + u8 power_supply_state; + u8 thermal_state; + u8 security_status; + u32 oem_defined; + u8 height; + u8 number_of_power_cords; + u8 contained_element_count; + // contained elements follow +} PACKED; + +/* SMBIOS type 4 - Processor Information (v2.0) */ +struct smbios_type_4 { + struct smbios_structure_header header; + u8 socket_designation_str; + u8 processor_type; + u8 processor_family; + u8 processor_manufacturer_str; + u32 processor_id[2]; + u8 processor_version_str; + u8 voltage; + u16 external_clock; + u16 max_speed; + u16 current_speed; + u8 status; + u8 processor_upgrade; + u16 l1_cache_handle; + u16 l2_cache_handle; + u16 l3_cache_handle; +} PACKED; + +/* SMBIOS type 16 - Physical Memory Array + * Associated with one type 17 (Memory Device). + */ +struct smbios_type_16 { + struct smbios_structure_header header; + u8 location; + u8 use; + u8 error_correction; + u32 maximum_capacity; + u16 memory_error_information_handle; + u16 number_of_memory_devices; +} PACKED; + +/* SMBIOS type 17 - Memory Device + * Associated with one type 19 + */ +struct smbios_type_17 { + struct smbios_structure_header header; + u16 physical_memory_array_handle; + u16 memory_error_information_handle; + u16 total_width; + u16 data_width; + u16 size; + u8 form_factor; + u8 device_set; + u8 device_locator_str; + u8 bank_locator_str; + u8 memory_type; + u16 type_detail; +} PACKED; + +/* SMBIOS type 19 - Memory Array Mapped Address */ +struct smbios_type_19 { + struct smbios_structure_header header; + u32 starting_address; + u32 ending_address; + u16 memory_array_handle; + u8 partition_width; +} PACKED; + +/* SMBIOS type 20 - Memory Device Mapped Address */ +struct smbios_type_20 { + struct smbios_structure_header header; + u32 starting_address; + u32 ending_address; + u16 memory_device_handle; + u16 memory_array_mapped_address_handle; + u8 partition_row_position; + u8 interleave_position; + u8 interleaved_data_depth; +} PACKED; + +/* SMBIOS type 32 - System Boot Information */ +struct smbios_type_32 { + struct smbios_structure_header header; + u8 reserved[6]; + u8 boot_status; +} PACKED; + +/* SMBIOS type 127 -- End-of-table */ +struct smbios_type_127 { + struct smbios_structure_header header; +} PACKED; + +#endif // smbios.h diff -Nru seabios-1.7.1/src/std/vbe.h seabios-1.7.4/src/std/vbe.h --- seabios-1.7.1/src/std/vbe.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/std/vbe.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,156 @@ +#ifndef __VBE_H +#define __VBE_H + +#include "types.h" // u8 + +#define VESA_SIGNATURE 0x41534556 // VESA +#define VBE2_SIGNATURE 0x32454256 // VBE2 + +struct vbe_info { + u32 signature; + u16 version; + struct segoff_s oem_string; + u32 capabilities; + struct segoff_s video_mode; + u16 total_memory; + u16 oem_revision; + struct segoff_s oem_vendor_string; + struct segoff_s oem_product_string; + struct segoff_s oem_revision_string; + u8 reserved[222]; +} PACKED; + +struct vbe_mode_info { + /* VBE */ + u16 mode_attributes; + u8 winA_attributes; + u8 winB_attributes; + u16 win_granularity; + u16 win_size; + u16 winA_seg; + u16 winB_seg; + struct segoff_s win_func_ptr; + u16 bytes_per_scanline; + /* VBE 1.2 */ + u16 xres; + u16 yres; + u8 xcharsize; + u8 ycharsize; + u8 planes; + u8 bits_per_pixel; + u8 banks; + u8 mem_model; + u8 bank_size; + u8 pages; + u8 reserved0; + /* Direct Color */ + u8 red_size; + u8 red_pos; + u8 green_size; + u8 green_pos; + u8 blue_size; + u8 blue_pos; + u8 alpha_size; + u8 alpha_pos; + u8 directcolor_info; + /* VBE 2.0 */ + u32 phys_base; + u32 reserved1; + u16 reserved2; + /* VBE 3.0 */ + u16 linear_bytes_per_scanline; + u8 bank_pages; + u8 linear_pages; + u8 linear_red_size; + u8 linear_red_pos; + u8 linear_green_size; + u8 linear_green_pos; + u8 linear_blue_size; + u8 linear_blue_pos; + u8 linear_alpha_size; + u8 linear_alpha_pos; + u32 pixclock_max; + u8 reserved[190]; +} PACKED; + +struct vbe_crtc_info { + u16 horiz_total; + u16 horiz_sync_start; + u16 horiz_sync_end; + u16 vert_total; + u16 vert_sync_start; + u16 vert_sync_end; + u8 flags; + u32 pixclock; + u16 refresh_rate; + u8 reserved[40]; +} PACKED; + +/* VBE Return Status Info */ +/* AL */ +#define VBE_RETURN_STATUS_SUPPORTED 0x4F +#define VBE_RETURN_STATUS_UNSUPPORTED 0x00 +/* AH */ +#define VBE_RETURN_STATUS_SUCCESSFULL 0x00 +#define VBE_RETURN_STATUS_FAILED 0x01 +#define VBE_RETURN_STATUS_NOT_SUPPORTED 0x02 +#define VBE_RETURN_STATUS_INVALID 0x03 + +/* VBE Mode Numbers */ + +#define VBE_MODE_VESA_DEFINED 0x0100 +#define VBE_MODE_REFRESH_RATE_USE_CRTC 0x0800 +#define VBE_MODE_LINEAR_FRAME_BUFFER 0x4000 +#define VBE_MODE_PRESERVE_DISPLAY_MEMORY 0x8000 + +#define VBE_VESA_MODE_END_OF_LIST 0xFFFF + +/* Capabilities */ + +#define VBE_CAPABILITY_8BIT_DAC 0x0001 +#define VBE_CAPABILITY_NOT_VGA_COMPATIBLE 0x0002 +#define VBE_CAPABILITY_RAMDAC_USE_BLANK_BIT 0x0004 +#define VBE_CAPABILITY_STEREOSCOPIC_SUPPORT 0x0008 +#define VBE_CAPABILITY_STEREO_VIA_VESA_EVC 0x0010 + +/* Mode Attributes */ + +#define VBE_MODE_ATTRIBUTE_SUPPORTED 0x0001 +#define VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE 0x0002 +#define VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT 0x0004 +#define VBE_MODE_ATTRIBUTE_COLOR_MODE 0x0008 +#define VBE_MODE_ATTRIBUTE_GRAPHICS_MODE 0x0010 +#define VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE 0x0020 +#define VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW 0x0040 +#define VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE 0x0080 +#define VBE_MODE_ATTRIBUTE_DOUBLE_SCAN_MODE 0x0100 +#define VBE_MODE_ATTRIBUTE_INTERLACE_MODE 0x0200 +#define VBE_MODE_ATTRIBUTE_HARDWARE_TRIPLE_BUFFER 0x0400 +#define VBE_MODE_ATTRIBUTE_HARDWARE_STEREOSCOPIC_DISPLAY 0x0800 +#define VBE_MODE_ATTRIBUTE_DUAL_DISPLAY_START_ADDRESS 0x1000 + +#define VBE_MODE_ATTTRIBUTE_LFB_ONLY ( VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW | VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE ) + +/* Window attributes */ + +#define VBE_WINDOW_ATTRIBUTE_RELOCATABLE 0x01 +#define VBE_WINDOW_ATTRIBUTE_READABLE 0x02 +#define VBE_WINDOW_ATTRIBUTE_WRITEABLE 0x04 + +/* Memory model */ + +#define VBE_MEMORYMODEL_TEXT_MODE 0x00 +#define VBE_MEMORYMODEL_CGA_GRAPHICS 0x01 +#define VBE_MEMORYMODEL_HERCULES_GRAPHICS 0x02 +#define VBE_MEMORYMODEL_PLANAR 0x03 +#define VBE_MEMORYMODEL_PACKED_PIXEL 0x04 +#define VBE_MEMORYMODEL_NON_CHAIN_4_256 0x05 +#define VBE_MEMORYMODEL_DIRECT_COLOR 0x06 +#define VBE_MEMORYMODEL_YUV 0x07 + +/* DirectColorModeInfo */ + +#define VBE_DIRECTCOLOR_COLOR_RAMP_PROGRAMMABLE 0x01 +#define VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE 0x02 + +#endif diff -Nru seabios-1.7.1/src/string.c seabios-1.7.4/src/string.c --- seabios-1.7.1/src/string.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/string.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,235 @@ +// String manipulation functions. +// +// Copyright (C) 2008-2013 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "stacks.h" // yield +#include "string.h" // memcpy +#include "farptr.h" // SET_SEG + + +/**************************************************************** + * String ops + ****************************************************************/ + +// Sum the bytes in the specified area. +u8 +checksum_far(u16 buf_seg, void *buf_far, u32 len) +{ + SET_SEG(ES, buf_seg); + u32 i; + u8 sum = 0; + for (i=0; i 3) { + u32 copylen = len; + if (copylen > 2048) + copylen = 2048; + copylen /= 4; + len -= copylen * 4; + asm volatile( + "rep movsl (%%esi),%%es:(%%edi)" + : "+c"(copylen), "+S"(s), "+D"(d) + : : "cc", "memory"); + yield(); + } + if (len) + // Copy any remaining bytes. + memcpy(d, s, len); +} + +void * +memmove(void *d, const void *s, size_t len) +{ + if (s >= d) + return memcpy(d, s, len); + + d += len-1; + s += len-1; + while (len--) { + *(char*)d = *(char*)s; + d--; + s--; + } + + return d; +} + +// Copy a string - truncating it if necessary. +char * +strtcpy(char *dest, const char *src, size_t len) +{ + char *d = dest; + while (--len && *src != '\0') + *d++ = *src++; + *d = '\0'; + return dest; +} + +// locate first occurance of character c in the string s +char * +strchr(const char *s, int c) +{ + for (; *s; s++) + if (*s == c) + return (char*)s; + return NULL; +} + +// Remove any trailing blank characters (spaces, new lines, carriage returns) +void +nullTrailingSpace(char *buf) +{ + int len = strlen(buf); + char *end = &buf[len-1]; + while (end >= buf && *end <= ' ') + *(end--) = '\0'; +} diff -Nru seabios-1.7.1/src/string.h seabios-1.7.4/src/string.h --- seabios-1.7.1/src/string.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/string.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,30 @@ +// String manipulation function defs. +#ifndef __STRING_H +#define __STRING_H + +#include "types.h" // u32 + +// string.c +u8 checksum_far(u16 buf_seg, void *buf_far, u32 len); +u8 checksum(void *buf, u32 len); +size_t strlen(const char *s); +int memcmp(const void *s1, const void *s2, size_t n); +int strcmp(const char *s1, const char *s2); +inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len); +inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len); +void *memset(void *s, int c, size_t n); +void memset_fl(void *ptr, u8 val, size_t size); +inline void memcpy_far(u16 d_seg, void *d_far + , u16 s_seg, const void *s_far, size_t len); +void memcpy_fl(void *d_fl, const void *s_fl, size_t len); +void *memcpy(void *d1, const void *s1, size_t len); +#if MODESEGMENT == 0 +#define memcpy __builtin_memcpy +#endif +void iomemcpy(void *d, const void *s, u32 len); +void *memmove(void *d, const void *s, size_t len); +char *strtcpy(char *dest, const char *src, size_t len); +char *strchr(const char *s, int c); +void nullTrailingSpace(char *buf); + +#endif // string.h diff -Nru seabios-1.7.1/src/system.c seabios-1.7.4/src/system.c --- seabios-1.7.1/src/system.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/system.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,12 +5,16 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "util.h" // memcpy_far -#include "biosvar.h" // BIOS_CONFIG_TABLE -#include "ioport.h" // inb -#include "memmap.h" // E820_RAM -#include "pic.h" // eoi_pic2 +#include "biosvar.h" // GET_GLOBAL #include "bregs.h" // struct bregs +#include "hw/pic.h" // pic_reset +#include "hw/ps2port.h" // PORT_A20 +#include "malloc.h" // LegacyRamSize +#include "memmap.h" // E820_RAM +#include "output.h" // debug_enter +#include "string.h" // memcpy_far +#include "util.h" // handle_1553 +#include "x86.h" // inb // Use PS2 System Control port A to set A20 enable static inline u8 @@ -174,7 +178,7 @@ static void handle_1588(struct bregs *regs) { - u32 rs = GET_GLOBAL(RamSize); + u32 rs = GET_GLOBAL(LegacyRamSize); // According to Ralf Brown's interrupt the limit should be 15M, // but real machines mostly return max. 63M. @@ -191,7 +195,7 @@ { set_a20(1); - set_pics(regs->bl, regs->bh); + pic_reset(regs->bl, regs->bh); u64 *gdt_far = (void*)(regs->si + 0); u16 gdt_seg = regs->es; @@ -270,7 +274,7 @@ // regs.u.r16.ax = 0; // regs.u.r16.bx = 0; - u32 rs = GET_GLOBAL(RamSize); + u32 rs = GET_GLOBAL(LegacyRamSize); // Get the amount of extended memory (above 1M) if (rs > 16*1024*1024) { @@ -290,10 +294,6 @@ set_success(regs); } -// Info on e820 map location and size. -struct e820entry e820_list[CONFIG_MAX_E820] VAR16VISIBLE; -int e820_count VAR16VISIBLE; - static void handle_15e820(struct bregs *regs) { @@ -349,6 +349,7 @@ case 0x52: handle_1552(regs); break; case 0x53: handle_1553(regs); break; case 0x5f: handle_155f(regs); break; + case 0x7f: handle_157f(regs); break; case 0x83: handle_1583(regs); break; case 0x86: handle_1586(regs); break; case 0x87: handle_1587(regs); break; diff -Nru seabios-1.7.1/src/types.h seabios-1.7.4/src/types.h --- seabios-1.7.1/src/types.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/types.h 2013-12-23 15:40:06.000000000 +0000 @@ -17,10 +17,21 @@ typedef u32 size_t; union u64_u32_u { - struct { u32 hi, lo; }; + struct { u32 lo, hi; }; u64 val; }; +// Definition for common 16bit segment/offset pointers. +struct segoff_s { + union { + struct { + u16 offset; + u16 seg; + }; + u32 segoff; + }; +}; + #ifdef MANUAL_NO_JUMP_TABLE # define default case 775324556: asm(""); default #endif @@ -51,18 +62,16 @@ # define VISIBLE32SEG // Designate a variable as (only) visible to 16bit code. # define VAR16 __section(".data16." UNIQSEC) -// Designate a variable as visible to 16bit, 32bit, and assembler code. -# define VAR16VISIBLE VAR16 __VISIBLE -// Designate a variable as externally visible (in addition to all internal code). -# define VAR16EXPORT __section(".data16.export." UNIQSEC) __VISIBLE // Designate a variable at a specific 16bit address # define VAR16FIXED(addr) __aligned(1) __VISIBLE __section(".fixedaddr." __stringify(addr)) // Designate a variable as (only) visible to 32bit segmented code. # define VAR32SEG __section(".discard.var32seg." UNIQSEC) -// Designate a 32bit variable also available in 16bit "big real" mode. -# define VAR32FLATVISIBLE __section(".discard.var32flat." UNIQSEC) __VISIBLE __weak // Designate a variable as visible and located in the e-segment. # define VARLOW __section(".discard.varlow." UNIQSEC) __VISIBLE __weak +// Designate a variable as visible and located in the f-segment. +# define VARFSEG __section(".discard.varfseg." UNIQSEC) __VISIBLE __weak +// Verify a variable is only accessable via 32bit "init" functions +# define VARVERIFY32INIT __section(".discard.varinit." UNIQSEC) // Designate top-level assembler as 16bit only. # define ASM16(code) __ASM(code) // Designate top-level assembler as 32bit flat only. @@ -77,12 +86,11 @@ # define VISIBLE32INIT # define VISIBLE32SEG __VISIBLE # define VAR16 __section(".discard.var16." UNIQSEC) -# define VAR16VISIBLE VAR16 __VISIBLE __weak -# define VAR16EXPORT VAR16VISIBLE -# define VAR16FIXED(addr) VAR16VISIBLE +# define VAR16FIXED(addr) VAR16 __VISIBLE __weak # define VAR32SEG __section(".data32seg." UNIQSEC) -# define VAR32FLATVISIBLE __section(".discard.var32flat." UNIQSEC) __VISIBLE __weak # define VARLOW __section(".discard.varlow." UNIQSEC) __VISIBLE __weak +# define VARFSEG __section(".discard.varfseg." UNIQSEC) __VISIBLE __weak +# define VARVERIFY32INIT __section(".discard.varinit." UNIQSEC) # define ASM16(code) # define ASM32FLAT(code) # define ASSERT16() __force_link_error__only_in_16bit() @@ -94,12 +102,11 @@ # define VISIBLE32INIT __section(".text.init." UNIQSEC) __VISIBLE # define VISIBLE32SEG # define VAR16 __section(".discard.var16." UNIQSEC) -# define VAR16VISIBLE VAR16 __VISIBLE __weak -# define VAR16EXPORT VAR16VISIBLE -# define VAR16FIXED(addr) VAR16VISIBLE +# define VAR16FIXED(addr) VAR16 __VISIBLE __weak # define VAR32SEG __section(".discard.var32seg." UNIQSEC) -# define VAR32FLATVISIBLE __section(".data.runtime." UNIQSEC) __VISIBLE -# define VARLOW __section(".datalow." UNIQSEC) __VISIBLE +# define VARLOW __section(".data.varlow." UNIQSEC) __VISIBLE __weak +# define VARFSEG __section(".data.varfseg." UNIQSEC) __VISIBLE +# define VARVERIFY32INIT __section(".data.varinit." UNIQSEC) # define ASM16(code) # define ASM32FLAT(code) __ASM(code) # define ASSERT16() __force_link_error__only_in_16bit() @@ -121,6 +128,9 @@ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) +#define container_of_or_null(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *___mptr = (ptr); \ + ___mptr ? container_of(___mptr, type, member) : NULL; }) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) diff -Nru seabios-1.7.1/src/usb.c seabios-1.7.4/src/usb.c --- seabios-1.7.1/src/usb.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,461 +0,0 @@ -// Main code for handling USB controllers and devices. -// -// Copyright (C) 2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // foreachpci -#include "config.h" // CONFIG_* -#include "pci_regs.h" // PCI_CLASS_REVISION -#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI -#include "usb-uhci.h" // uhci_init -#include "usb-ohci.h" // ohci_init -#include "usb-ehci.h" // ehci_init -#include "usb-hid.h" // usb_keyboard_setup -#include "usb-hub.h" // usb_hub_init -#include "usb-msc.h" // usb_msc_init -#include "usb-uas.h" // usb_uas_init -#include "usb.h" // struct usb_s -#include "biosvar.h" // GET_GLOBAL - - -/**************************************************************** - * Controller function wrappers - ****************************************************************/ - -// Allocate an async pipe (control or bulk). -struct usb_pipe * -usb_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - switch (usbdev->hub->cntl->type) { - default: - case USB_TYPE_UHCI: - return uhci_alloc_pipe(usbdev, epdesc); - case USB_TYPE_OHCI: - return ohci_alloc_pipe(usbdev, epdesc); - case USB_TYPE_EHCI: - return ehci_alloc_pipe(usbdev, epdesc); - } -} - -// Send a message on a control pipe using the default control descriptor. -static int -send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize - , void *data, int datasize) -{ - ASSERT32FLAT(); - switch (pipe->type) { - default: - case USB_TYPE_UHCI: - return uhci_control(pipe, dir, cmd, cmdsize, data, datasize); - case USB_TYPE_OHCI: - return ohci_control(pipe, dir, cmd, cmdsize, data, datasize); - case USB_TYPE_EHCI: - return ehci_control(pipe, dir, cmd, cmdsize, data, datasize); - } -} - -int -usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize) -{ - switch (GET_LOWFLAT(pipe_fl->type)) { - default: - case USB_TYPE_UHCI: - return uhci_send_bulk(pipe_fl, dir, data, datasize); - case USB_TYPE_OHCI: - return ohci_send_bulk(pipe_fl, dir, data, datasize); - case USB_TYPE_EHCI: - return ehci_send_bulk(pipe_fl, dir, data, datasize); - } -} - -int -usb_poll_intr(struct usb_pipe *pipe_fl, void *data) -{ - switch (GET_LOWFLAT(pipe_fl->type)) { - default: - case USB_TYPE_UHCI: - return uhci_poll_intr(pipe_fl, data); - case USB_TYPE_OHCI: - return ohci_poll_intr(pipe_fl, data); - case USB_TYPE_EHCI: - return ehci_poll_intr(pipe_fl, data); - } -} - - -/**************************************************************** - * Helper functions - ****************************************************************/ - -// Send a message to the default control pipe of a device. -int -send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req - , void *data) -{ - return send_control(pipe, req->bRequestType & USB_DIR_IN - , req, sizeof(*req), data, req->wLength); -} - -// Free an allocated control or bulk pipe. -void -free_pipe(struct usb_pipe *pipe) -{ - ASSERT32FLAT(); - if (!pipe) - return; - // Add to controller's free list. - struct usb_s *cntl = pipe->cntl; - pipe->freenext = cntl->freelist; - cntl->freelist = pipe; -} - -// Check for an available pipe on the freelist. -struct usb_pipe * -usb_getFreePipe(struct usb_s *cntl, u8 eptype) -{ - struct usb_pipe **pfree = &cntl->freelist; - for (;;) { - struct usb_pipe *pipe = *pfree; - if (!pipe) - return NULL; - if (pipe->eptype == eptype) { - *pfree = pipe->freenext; - return pipe; - } - pfree = &pipe->freenext; - } -} - -// Fill "pipe" endpoint info from an endpoint descriptor. -void -usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - pipe->cntl = usbdev->hub->cntl; - pipe->type = usbdev->hub->cntl->type; - pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - pipe->devaddr = usbdev->devaddr; - pipe->speed = usbdev->speed; - pipe->maxpacket = epdesc->wMaxPacketSize; - pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; -} - -// Find the exponential period of the requested interrupt end point. -int -usb_getFrameExp(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - int period = epdesc->bInterval; - if (usbdev->speed != USB_HIGHSPEED) - return (period <= 0) ? 0 : __fls(period); - return (period <= 4) ? 0 : period - 4; -} - -// Find the first endpoing of a given type in an interface description. -struct usb_endpoint_descriptor * -findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir) -{ - struct usb_endpoint_descriptor *epdesc = (void*)&usbdev->iface[1]; - for (;;) { - if ((void*)epdesc >= (void*)usbdev->iface + usbdev->imax - || epdesc->bDescriptorType == USB_DT_INTERFACE) { - return NULL; - } - if (epdesc->bDescriptorType == USB_DT_ENDPOINT - && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir - && (epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == type) - return epdesc; - epdesc = (void*)epdesc + epdesc->bLength; - } -} - -// Get the first 8 bytes of the device descriptor. -static int -get_device_info8(struct usb_pipe *pipe, struct usb_device_descriptor *dinfo) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; - req.bRequest = USB_REQ_GET_DESCRIPTOR; - req.wValue = USB_DT_DEVICE<<8; - req.wIndex = 0; - req.wLength = 8; - return send_default_control(pipe, &req, dinfo); -} - -static struct usb_config_descriptor * -get_device_config(struct usb_pipe *pipe) -{ - struct usb_config_descriptor cfg; - - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; - req.bRequest = USB_REQ_GET_DESCRIPTOR; - req.wValue = USB_DT_CONFIG<<8; - req.wIndex = 0; - req.wLength = sizeof(cfg); - int ret = send_default_control(pipe, &req, &cfg); - if (ret) - return NULL; - - void *config = malloc_tmphigh(cfg.wTotalLength); - if (!config) - return NULL; - req.wLength = cfg.wTotalLength; - ret = send_default_control(pipe, &req, config); - if (ret) - return NULL; - //hexdump(config, cfg.wTotalLength); - return config; -} - -static int -set_configuration(struct usb_pipe *pipe, u16 val) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; - req.bRequest = USB_REQ_SET_CONFIGURATION; - req.wValue = val; - req.wIndex = 0; - req.wLength = 0; - return send_default_control(pipe, &req, NULL); -} - - -/**************************************************************** - * Initialization and enumeration - ****************************************************************/ - -// Assign an address to a device in the default state on the given -// controller. -static int -usb_set_address(struct usbdevice_s *usbdev) -{ - ASSERT32FLAT(); - struct usb_s *cntl = usbdev->hub->cntl; - dprintf(3, "set_address %p\n", cntl); - if (cntl->maxaddr >= USB_MAXADDR) - return -1; - - // Create a pipe for the default address. - struct usb_endpoint_descriptor epdesc = { - .wMaxPacketSize = 8, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, - }; - usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); - if (!usbdev->defpipe) - return -1; - - msleep(USB_TIME_RSTRCY); - - // Send set_address command. - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; - req.bRequest = USB_REQ_SET_ADDRESS; - req.wValue = cntl->maxaddr + 1; - req.wIndex = 0; - req.wLength = 0; - int ret = send_default_control(usbdev->defpipe, &req, NULL); - free_pipe(usbdev->defpipe); - if (ret) - return -1; - - msleep(USB_TIME_SETADDR_RECOVERY); - - cntl->maxaddr++; - usbdev->devaddr = cntl->maxaddr; - usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); - if (!usbdev->defpipe) - return -1; - return 0; -} - -// Called for every found device - see if a driver is available for -// this device and do setup if so. -static int -configure_usb_device(struct usbdevice_s *usbdev) -{ - ASSERT32FLAT(); - dprintf(3, "config_usb: %p\n", usbdev->defpipe); - - // Set the max packet size for endpoint 0 of this device. - struct usb_device_descriptor dinfo; - int ret = get_device_info8(usbdev->defpipe, &dinfo); - if (ret) - return 0; - dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%02x\n" - , dinfo.bcdUSB, dinfo.bDeviceClass, dinfo.bDeviceSubClass - , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0); - if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64) - return 0; - free_pipe(usbdev->defpipe); - struct usb_endpoint_descriptor epdesc = { - .wMaxPacketSize = dinfo.bMaxPacketSize0, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, - }; - usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); - if (!usbdev->defpipe) - return -1; - - // Get configuration - struct usb_config_descriptor *config = get_device_config(usbdev->defpipe); - if (!config) - return 0; - - // Determine if a driver exists for this device - only look at the - // first interface of the first configuration. - struct usb_interface_descriptor *iface = (void*)(&config[1]); - if (iface->bInterfaceClass != USB_CLASS_HID - && iface->bInterfaceClass != USB_CLASS_MASS_STORAGE - && iface->bInterfaceClass != USB_CLASS_HUB) - // Not a supported device. - goto fail; - - // Set the configuration. - ret = set_configuration(usbdev->defpipe, config->bConfigurationValue); - if (ret) - goto fail; - - // Configure driver. - usbdev->config = config; - usbdev->iface = iface; - usbdev->imax = (void*)config + config->wTotalLength - (void*)iface; - if (iface->bInterfaceClass == USB_CLASS_HUB) - ret = usb_hub_init(usbdev); - else if (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE) { - if (iface->bInterfaceProtocol == US_PR_BULK) - ret = usb_msc_init(usbdev); - if (iface->bInterfaceProtocol == US_PR_UAS) - ret = usb_uas_init(usbdev); - } else - ret = usb_hid_init(usbdev); - if (ret) - goto fail; - - free(config); - return 1; -fail: - free(config); - return 0; -} - -static void -usb_init_hub_port(void *data) -{ - struct usbdevice_s *usbdev = data; - struct usbhub_s *hub = usbdev->hub; - u32 port = usbdev->port; - - // Detect if device present (and possibly start reset) - int ret = hub->op->detect(hub, port); - if (ret) - // No device present - goto done; - - // Reset port and determine device speed - mutex_lock(&hub->cntl->resetlock); - ret = hub->op->reset(hub, port); - if (ret < 0) - // Reset failed - goto resetfail; - usbdev->speed = ret; - - // Set address of port - ret = usb_set_address(usbdev); - if (ret) { - hub->op->disconnect(hub, port); - goto resetfail; - } - mutex_unlock(&hub->cntl->resetlock); - - // Configure the device - int count = configure_usb_device(usbdev); - free_pipe(usbdev->defpipe); - if (!count) - hub->op->disconnect(hub, port); - hub->devcount += count; -done: - hub->threads--; - free(usbdev); - return; - -resetfail: - mutex_unlock(&hub->cntl->resetlock); - goto done; -} - -void -usb_enumerate(struct usbhub_s *hub) -{ - u32 portcount = hub->portcount; - hub->threads = portcount; - - // Launch a thread for every port. - int i; - for (i=0; ihub = hub; - usbdev->port = i; - run_thread(usb_init_hub_port, usbdev); - } - - // Wait for threads to complete. - while (hub->threads) - yield(); -} - -void -usb_setup(void) -{ - ASSERT32FLAT(); - if (! CONFIG_USB) - return; - - dprintf(3, "init usb\n"); - - // Look for USB controllers - int count = 0; - struct pci_device *ehcipci = PCIDevices; - struct pci_device *pci; - foreachpci(pci) { - if (pci->class != PCI_CLASS_SERIAL_USB) - continue; - - if (pci->bdf >= ehcipci->bdf) { - // Check to see if this device has an ehci controller - int found = 0; - ehcipci = pci; - for (;;) { - if (pci_classprog(ehcipci) == PCI_CLASS_SERIAL_USB_EHCI) { - // Found an ehci controller. - int ret = ehci_init(ehcipci, count++, pci); - if (ret) - // Error - break; - count += found; - pci = ehcipci; - break; - } - if (ehcipci->class == PCI_CLASS_SERIAL_USB) - found++; - ehcipci = ehcipci->next; - if (!ehcipci || (pci_bdf_to_busdev(ehcipci->bdf) - != pci_bdf_to_busdev(pci->bdf))) - // No ehci controller found. - break; - } - } - - if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI) - uhci_init(pci, count++); - else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI) - ohci_init(pci, count++); - } -} diff -Nru seabios-1.7.1/src/usb-ehci.c seabios-1.7.4/src/usb-ehci.c --- seabios-1.7.1/src/usb-ehci.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-ehci.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,723 +0,0 @@ -// Code for handling EHCI USB controllers. -// -// Copyright (C) 2010 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // pci_bdf_to_bus -#include "config.h" // CONFIG_* -#include "ioport.h" // outw -#include "usb-ehci.h" // struct ehci_qh -#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI -#include "pci_regs.h" // PCI_BASE_ADDRESS_0 -#include "usb.h" // struct usb_s -#include "biosvar.h" // GET_LOWFLAT -#include "usb-uhci.h" // init_uhci -#include "usb-ohci.h" // init_ohci - -struct usb_ehci_s { - struct usb_s usb; - struct ehci_caps *caps; - struct ehci_regs *regs; - struct ehci_qh *async_qh; - struct pci_device *companion[8]; - int checkports; - int legacycount; -}; - -struct ehci_pipe { - struct ehci_qh qh; - struct ehci_qtd *next_td, *tds; - void *data; - struct usb_pipe pipe; -}; - - -/**************************************************************** - * Root hub - ****************************************************************/ - -#define EHCI_TIME_POSTPOWER 20 -#define EHCI_TIME_POSTRESET 2 - -// Check if need companion controllers for full/low speed devices -static void -ehci_note_port(struct usb_ehci_s *cntl) -{ - if (--cntl->checkports) - // Ports still being detected. - return; - if (! cntl->legacycount) - // No full/low speed devices found. - return; - // Start companion controllers. - int i; - for (i=0; icompanion); i++) { - struct pci_device *pci = cntl->companion[i]; - if (!pci) - break; - - // ohci/uhci_init call pci_config_XXX - don't run from irq handler. - wait_preempt(); - - if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI) - uhci_init(pci, cntl->usb.busid + i); - else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI) - ohci_init(pci, cntl->usb.busid + i); - } -} - -// Check if device attached to port -static int -ehci_hub_detect(struct usbhub_s *hub, u32 port) -{ - struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb); - u32 *portreg = &cntl->regs->portsc[port]; - u32 portsc = readl(portreg); - - // Power up port. - if (!(portsc & PORT_POWER)) { - portsc |= PORT_POWER; - writel(portreg, portsc); - msleep(EHCI_TIME_POSTPOWER); - } else { - // Port is already powered up, but we don't know how long it - // has been powered up, so wait the 20ms. - msleep(EHCI_TIME_POSTPOWER); - } - portsc = readl(portreg); - - if (!(portsc & PORT_CONNECT)) - // No device present - goto doneearly; - - if ((portsc & PORT_LINESTATUS_MASK) == PORT_LINESTATUS_KSTATE) { - // low speed device - cntl->legacycount++; - writel(portreg, portsc | PORT_OWNER); - goto doneearly; - } - - // XXX - if just powered up, need to wait for USB_TIME_ATTDB? - - // Begin reset on port - portsc = (portsc & ~PORT_PE) | PORT_RESET; - writel(portreg, portsc); - msleep(USB_TIME_DRSTR); - return 0; - -doneearly: - ehci_note_port(cntl); - return -1; -} - -// Reset device on port -static int -ehci_hub_reset(struct usbhub_s *hub, u32 port) -{ - struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb); - u32 *portreg = &cntl->regs->portsc[port]; - u32 portsc = readl(portreg); - - // Finish reset on port - portsc &= ~PORT_RESET; - writel(portreg, portsc); - msleep(EHCI_TIME_POSTRESET); - - int rv = -1; - portsc = readl(portreg); - if (!(portsc & PORT_CONNECT)) - // No longer connected - goto resetfail; - if (!(portsc & PORT_PE)) { - // full speed device - cntl->legacycount++; - writel(portreg, portsc | PORT_OWNER); - goto resetfail; - } - - rv = USB_HIGHSPEED; -resetfail: - ehci_note_port(cntl); - return rv; -} - -// Disable port -static void -ehci_hub_disconnect(struct usbhub_s *hub, u32 port) -{ - struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb); - u32 *portreg = &cntl->regs->portsc[port]; - u32 portsc = readl(portreg); - writel(portreg, portsc & ~PORT_PE); -} - -static struct usbhub_op_s ehci_HubOp = { - .detect = ehci_hub_detect, - .reset = ehci_hub_reset, - .disconnect = ehci_hub_disconnect, -}; - -// Find any devices connected to the root hub. -static int -check_ehci_ports(struct usb_ehci_s *cntl) -{ - ASSERT32FLAT(); - struct usbhub_s hub; - memset(&hub, 0, sizeof(hub)); - hub.cntl = &cntl->usb; - hub.portcount = cntl->checkports; - hub.op = &ehci_HubOp; - usb_enumerate(&hub); - return hub.devcount; -} - - -/**************************************************************** - * Setup - ****************************************************************/ - -// Wait for next USB async frame to start - for ensuring safe memory release. -static void -ehci_waittick(struct usb_ehci_s *cntl) -{ - if (MODE16) { - msleep(10); - return; - } - // Wait for access to "doorbell" - barrier(); - u32 cmd, sts; - u64 end = calc_future_tsc(100); - for (;;) { - sts = readl(&cntl->regs->usbsts); - if (!(sts & STS_IAA)) { - cmd = readl(&cntl->regs->usbcmd); - if (!(cmd & CMD_IAAD)) - break; - } - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } - // Ring "doorbell" - writel(&cntl->regs->usbcmd, cmd | CMD_IAAD); - // Wait for completion - for (;;) { - sts = readl(&cntl->regs->usbsts); - if (sts & STS_IAA) - break; - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } - // Ack completion - writel(&cntl->regs->usbsts, STS_IAA); -} - -static void -ehci_free_pipes(struct usb_ehci_s *cntl) -{ - dprintf(7, "ehci_free_pipes %p\n", cntl); - - struct ehci_qh *start = cntl->async_qh; - struct ehci_qh *pos = start; - for (;;) { - struct ehci_qh *next = (void*)(pos->next & ~EHCI_PTR_BITS); - if (next == start) - break; - struct ehci_pipe *pipe = container_of(next, struct ehci_pipe, qh); - if (pipe->pipe.cntl != &cntl->usb) - pos->next = next->next; - else - pos = next; - } - ehci_waittick(cntl); - for (;;) { - struct usb_pipe *usbpipe = cntl->usb.freelist; - if (!usbpipe) - break; - cntl->usb.freelist = usbpipe->freenext; - struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe); - free(pipe); - } -} - -static void -configure_ehci(void *data) -{ - struct usb_ehci_s *cntl = data; - - // Allocate ram for schedule storage - struct ehci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl)); - struct ehci_qh *intr_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*intr_qh)); - struct ehci_qh *async_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*async_qh)); - if (!fl || !intr_qh || !async_qh) { - warn_noalloc(); - goto fail; - } - - // XXX - check for halted? - - // Reset the HC - u32 cmd = readl(&cntl->regs->usbcmd); - writel(&cntl->regs->usbcmd, (cmd & ~(CMD_ASE | CMD_PSE)) | CMD_HCRESET); - u64 end = calc_future_tsc(250); - for (;;) { - cmd = readl(&cntl->regs->usbcmd); - if (!(cmd & CMD_HCRESET)) - break; - if (check_tsc(end)) { - warn_timeout(); - goto fail; - } - yield(); - } - - // Disable interrupts (just to be safe). - writel(&cntl->regs->usbintr, 0); - - // Set schedule to point to primary intr queue head - memset(intr_qh, 0, sizeof(*intr_qh)); - intr_qh->next = EHCI_PTR_TERM; - intr_qh->info2 = (0x01 << QH_SMASK_SHIFT); - intr_qh->token = QTD_STS_HALT; - intr_qh->qtd_next = intr_qh->alt_next = EHCI_PTR_TERM; - int i; - for (i=0; ilinks); i++) - fl->links[i] = (u32)intr_qh | EHCI_PTR_QH; - writel(&cntl->regs->periodiclistbase, (u32)fl); - - // Set async list to point to primary async queue head - memset(async_qh, 0, sizeof(*async_qh)); - async_qh->next = (u32)async_qh | EHCI_PTR_QH; - async_qh->info1 = QH_HEAD; - async_qh->token = QTD_STS_HALT; - async_qh->qtd_next = async_qh->alt_next = EHCI_PTR_TERM; - cntl->async_qh = async_qh; - writel(&cntl->regs->asynclistbase, (u32)async_qh); - - // Enable queues - writel(&cntl->regs->usbcmd, cmd | CMD_ASE | CMD_PSE | CMD_RUN); - - // Set default of high speed for root hub. - writel(&cntl->regs->configflag, 1); - cntl->checkports = readl(&cntl->caps->hcsparams) & HCS_N_PORTS_MASK; - - // Find devices - int count = check_ehci_ports(cntl); - ehci_free_pipes(cntl); - if (count) - // Success - return; - - // No devices found - shutdown and free controller. - writel(&cntl->regs->usbcmd, cmd & ~CMD_RUN); - msleep(4); // 2ms to stop reading memory - XXX -fail: - free(fl); - free(intr_qh); - free(async_qh); - free(cntl); -} - -int -ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci) -{ - if (! CONFIG_USB_EHCI) - return -1; - - u16 bdf = pci->bdf; - u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); - struct ehci_caps *caps = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); - u32 hcc_params = readl(&caps->hccparams); - - struct usb_ehci_s *cntl = malloc_tmphigh(sizeof(*cntl)); - if (!cntl) { - warn_noalloc(); - return -1; - } - memset(cntl, 0, sizeof(*cntl)); - cntl->usb.busid = busid; - cntl->usb.pci = pci; - cntl->usb.type = USB_TYPE_EHCI; - cntl->caps = caps; - if (hcc_params & HCC_64BIT_ADDR) - cntl->regs->ctrldssegment = 0; - cntl->regs = (void*)caps + readb(&caps->caplength); - - dprintf(1, "EHCI init on dev %02x:%02x.%x (regs=%p)\n" - , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) - , pci_bdf_to_fn(bdf), cntl->regs); - - pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); - - // XXX - check for and disable SMM control? - - // Find companion controllers. - int count = 0; - for (;;) { - if (!comppci || comppci == pci) - break; - if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_UHCI) - cntl->companion[count++] = comppci; - else if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_OHCI) - cntl->companion[count++] = comppci; - comppci = comppci->next; - } - - run_thread(configure_ehci, cntl); - return 0; -} - - -/**************************************************************** - * End point communication - ****************************************************************/ - -// Setup fields in qh -static void -ehci_desc2pipe(struct ehci_pipe *pipe, struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - - pipe->qh.info1 = ((pipe->pipe.maxpacket << QH_MAXPACKET_SHIFT) - | (pipe->pipe.speed << QH_SPEED_SHIFT) - | (pipe->pipe.ep << QH_EP_SHIFT) - | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); - - pipe->qh.info2 = (1 << QH_MULT_SHIFT); - struct usbdevice_s *hubdev = usbdev->hub->usbdev; - if (hubdev) { - struct ehci_pipe *hpipe = container_of( - hubdev->defpipe, struct ehci_pipe, pipe); - if (hpipe->pipe.speed == USB_HIGHSPEED) - pipe->qh.info2 |= ((usbdev->port << QH_HUBPORT_SHIFT) - | (hpipe->pipe.devaddr << QH_HUBADDR_SHIFT)); - else - pipe->qh.info2 = hpipe->qh.info2; - } - - u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (eptype == USB_ENDPOINT_XFER_CONTROL) - pipe->qh.info1 |= ((pipe->pipe.speed != USB_HIGHSPEED ? QH_CONTROL : 0) - | QH_TOGGLECONTROL); - else if (eptype == USB_ENDPOINT_XFER_INT) - pipe->qh.info2 |= (0x01 << QH_SMASK_SHIFT) | (0x1c << QH_CMASK_SHIFT); -} - -static struct usb_pipe * -ehci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - struct usb_ehci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_ehci_s, usb); - int frameexp = usb_getFrameExp(usbdev, epdesc); - dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); - - if (frameexp > 10) - frameexp = 10; - int maxpacket = epdesc->wMaxPacketSize; - // Determine number of entries needed for 2 timer ticks. - int ms = 1<next_td = pipe->tds = tds; - pipe->data = data; - pipe->qh.qtd_next = (u32)tds; - - int i; - for (i=0; iqtd_next = (i==count-1 ? (u32)tds : (u32)&td[1]); - td->alt_next = EHCI_PTR_TERM; - td->token = (ehci_explen(maxpacket) | QTD_STS_ACTIVE - | QTD_PID_IN | ehci_maxerr(3)); - td->buf[0] = (u32)data + maxpacket * i; - } - - // Add to interrupt schedule. - struct ehci_framelist *fl = (void*)readl(&cntl->regs->periodiclistbase); - if (frameexp == 0) { - // Add to existing interrupt entry. - struct ehci_qh *intr_qh = (void*)(fl->links[0] & ~EHCI_PTR_BITS); - pipe->qh.next = intr_qh->next; - barrier(); - intr_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; - } else { - int startpos = 1<<(frameexp-1); - pipe->qh.next = fl->links[startpos]; - barrier(); - for (i=startpos; ilinks); i+=ms) - fl->links[i] = (u32)&pipe->qh | EHCI_PTR_QH; - } - - return &pipe->pipe; -fail: - free(pipe); - free(tds); - free(data); - return NULL; -} - -struct usb_pipe * -ehci_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_EHCI) - return NULL; - u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (eptype == USB_ENDPOINT_XFER_INT) - return ehci_alloc_intr_pipe(usbdev, epdesc); - struct usb_ehci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_ehci_s, usb); - dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); - - struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); - if (usbpipe) { - // Use previously allocated pipe. - struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe); - ehci_desc2pipe(pipe, usbdev, epdesc); - return usbpipe; - } - - // Allocate a new queue head. - struct ehci_pipe *pipe; - if (eptype == USB_ENDPOINT_XFER_CONTROL) - pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe)); - else - pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); - if (!pipe) { - warn_noalloc(); - return NULL; - } - memset(pipe, 0, sizeof(*pipe)); - ehci_desc2pipe(pipe, usbdev, epdesc); - pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM; - - // Add queue head to controller list. - struct ehci_qh *async_qh = cntl->async_qh; - pipe->qh.next = async_qh->next; - barrier(); - async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; - return &pipe->pipe; -} - -static void -ehci_reset_pipe(struct ehci_pipe *pipe) -{ - SET_LOWFLAT(pipe->qh.qtd_next, EHCI_PTR_TERM); - SET_LOWFLAT(pipe->qh.alt_next, EHCI_PTR_TERM); - barrier(); - SET_LOWFLAT(pipe->qh.token, GET_LOWFLAT(pipe->qh.token) & QTD_TOGGLE); -} - -static int -ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) -{ - u64 end = calc_future_tsc(timeout); - u32 status; - for (;;) { - status = td->token; - if (!(status & QTD_STS_ACTIVE)) - break; - if (check_tsc(end)) { - u32 cur = GET_LOWFLAT(pipe->qh.current); - u32 tok = GET_LOWFLAT(pipe->qh.token); - u32 next = GET_LOWFLAT(pipe->qh.qtd_next); - warn_timeout(); - dprintf(1, "ehci pipe=%p cur=%08x tok=%08x next=%x td=%p status=%x\n" - , pipe, cur, tok, next, td, status); - ehci_reset_pipe(pipe); - struct usb_ehci_s *cntl = container_of( - GET_LOWFLAT(pipe->pipe.cntl), struct usb_ehci_s, usb); - ehci_waittick(cntl); - return -1; - } - yield(); - } - if (status & QTD_STS_HALT) { - dprintf(1, "ehci_wait_td error - status=%x\n", status); - ehci_reset_pipe(pipe); - return -2; - } - return 0; -} - -static int -fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes) -{ - u32 dest = (u32)buf; - u32 *pos = td->buf; - while (bytes) { - if (pos >= &td->buf[ARRAY_SIZE(td->buf)]) - // More data than can transfer in a single qtd - only use - // full packets to prevent a babble error. - return ALIGN_DOWN(dest - (u32)buf, maxpacket); - u32 count = bytes; - u32 max = 0x1000 - (dest & 0xfff); - if (count > max) - count = max; - *pos = dest; - bytes -= count; - dest += count; - pos++; - } - return dest - (u32)buf; -} - -int -ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize - , void *data, int datasize) -{ - ASSERT32FLAT(); - if (! CONFIG_USB_EHCI) - return -1; - dprintf(5, "ehci_control %p (dir=%d cmd=%d data=%d)\n" - , p, dir, cmdsize, datasize); - if (datasize > 4*4096 || cmdsize > 4*4096) { - // XXX - should support larger sizes. - warn_noalloc(); - return -1; - } - struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); - - // Setup transfer descriptors - struct ehci_qtd *tds = memalign_tmphigh(EHCI_QTD_ALIGN, sizeof(*tds) * 3); - if (!tds) { - warn_noalloc(); - return -1; - } - memset(tds, 0, sizeof(*tds) * 3); - struct ehci_qtd *td = tds; - - td->qtd_next = (u32)&td[1]; - td->alt_next = EHCI_PTR_TERM; - td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE - | QTD_PID_SETUP | ehci_maxerr(3)); - u16 maxpacket = pipe->pipe.maxpacket; - fillTDbuffer(td, maxpacket, cmd, cmdsize); - td++; - - if (datasize) { - td->qtd_next = (u32)&td[1]; - td->alt_next = EHCI_PTR_TERM; - td->token = (QTD_TOGGLE | ehci_explen(datasize) | QTD_STS_ACTIVE - | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3)); - fillTDbuffer(td, maxpacket, data, datasize); - td++; - } - - td->qtd_next = EHCI_PTR_TERM; - td->alt_next = EHCI_PTR_TERM; - td->token = (QTD_TOGGLE | QTD_STS_ACTIVE - | (dir ? QTD_PID_OUT : QTD_PID_IN) | ehci_maxerr(3)); - - // Transfer data - barrier(); - pipe->qh.qtd_next = (u32)tds; - int i, ret=0; - for (i=0; i<3; i++) { - struct ehci_qtd *td = &tds[i]; - ret = ehci_wait_td(pipe, td, 500); - if (ret) - break; - } - free(tds); - return ret; -} - -#define STACKQTDS 4 - -int -ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) -{ - if (! CONFIG_USB_EHCI) - return -1; - struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); - dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n" - , &pipe->qh, dir, data, datasize); - - // Allocate 4 tds on stack (with required alignment) - u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1]; - struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN); - memset(tds, 0, sizeof(*tds) * STACKQTDS); - barrier(); - SET_LOWFLAT(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds)); - - u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); - int tdpos = 0; - while (datasize) { - struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; - int ret = ehci_wait_td(pipe, td, 5000); - if (ret) - return -1; - - struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS) - , &tds[tdpos % STACKQTDS]); - - int transfer = fillTDbuffer(td, maxpacket, data, datasize); - td->qtd_next = (transfer==datasize ? EHCI_PTR_TERM : (u32)nexttd_fl); - td->alt_next = EHCI_PTR_TERM; - barrier(); - td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE - | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3)); - - data += transfer; - datasize -= transfer; - } - int i; - for (i=0; inext_td); - u32 token = GET_LOWFLAT(td->token); - if (token & QTD_STS_ACTIVE) - // No intrs found. - return -1; - // XXX - check for errors. - - // Copy data. - int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); - int pos = td - GET_LOWFLAT(pipe->tds); - void *tddata = GET_LOWFLAT(pipe->data) + maxpacket * pos; - memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata), maxpacket); - - // Reenable this td. - struct ehci_qtd *next = (void*)(GET_LOWFLAT(td->qtd_next) & ~EHCI_PTR_BITS); - SET_LOWFLAT(pipe->next_td, next); - SET_LOWFLAT(td->buf[0], (u32)tddata); - barrier(); - SET_LOWFLAT(td->token, (ehci_explen(maxpacket) | QTD_STS_ACTIVE - | QTD_PID_IN | ehci_maxerr(3))); - - return 0; -} diff -Nru seabios-1.7.1/src/usb-ehci.h seabios-1.7.4/src/usb-ehci.h --- seabios-1.7.1/src/usb-ehci.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-ehci.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,176 +0,0 @@ -#ifndef __USB_EHCI_H -#define __USB_EHCI_H - -// usb-ehci.c -int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci); -struct usbdevice_s; -struct usb_endpoint_descriptor; -struct usb_pipe *ehci_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); -struct usb_pipe; -int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize - , void *data, int datasize); -int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); -int ehci_poll_intr(struct usb_pipe *p, void *data); - - -/**************************************************************** - * ehci structs and flags - ****************************************************************/ - -struct ehci_caps { - u8 caplength; - u8 reserved_01; - u16 hciversion; - u32 hcsparams; - u32 hccparams; - u64 portroute; -} PACKED; - -#define HCC_64BIT_ADDR 1 - -#define HCS_N_PORTS_MASK 0xf - -struct ehci_regs { - u32 usbcmd; - u32 usbsts; - u32 usbintr; - u32 frindex; - u32 ctrldssegment; - u32 periodiclistbase; - u32 asynclistbase; - u32 reserved[9]; - u32 configflag; - u32 portsc[0]; -} PACKED; - -#define CMD_PARK (1<<11) -#define CMD_PARK_CNT(c) (((c)>>8)&3) -#define CMD_LRESET (1<<7) -#define CMD_IAAD (1<<6) -#define CMD_ASE (1<<5) -#define CMD_PSE (1<<4) -#define CMD_HCRESET (1<<1) -#define CMD_RUN (1<<0) - -#define STS_ASS (1<<15) -#define STS_PSS (1<<14) -#define STS_RECL (1<<13) -#define STS_HALT (1<<12) -#define STS_IAA (1<<5) -#define STS_FATAL (1<<4) -#define STS_FLR (1<<3) -#define STS_PCD (1<<2) -#define STS_ERR (1<<1) -#define STS_INT (1<<0) - -#define FLAG_CF (1<<0) - -#define PORT_WKOC_E (1<<22) -#define PORT_WKDISC_E (1<<21) -#define PORT_WKCONN_E (1<<20) -#define PORT_TEST_PKT (0x4<<16) -#define PORT_LED_OFF (0<<14) -#define PORT_LED_AMBER (1<<14) -#define PORT_LED_GREEN (2<<14) -#define PORT_LED_MASK (3<<14) -#define PORT_OWNER (1<<13) -#define PORT_POWER (1<<12) -#define PORT_LINESTATUS_MASK (3<<10) -#define PORT_LINESTATUS_KSTATE (1<<10) -#define PORT_RESET (1<<8) -#define PORT_SUSPEND (1<<7) -#define PORT_RESUME (1<<6) -#define PORT_OCC (1<<5) -#define PORT_OC (1<<4) -#define PORT_PEC (1<<3) -#define PORT_PE (1<<2) -#define PORT_CSC (1<<1) -#define PORT_CONNECT (1<<0) -#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) - - -#define EHCI_QH_ALIGN 128 // Can't span a 4K boundary, so increase from 32 - -struct ehci_qh { - u32 next; - u32 info1; - u32 info2; - u32 current; - - u32 qtd_next; - u32 alt_next; - u32 token; - u32 buf[5]; - u32 buf_hi[5]; -} PACKED; - -#define QH_CONTROL (1 << 27) -#define QH_MAXPACKET_SHIFT 16 -#define QH_MAXPACKET_MASK (0x7ff << QH_MAXPACKET_SHIFT) -#define QH_HEAD (1 << 15) -#define QH_TOGGLECONTROL (1 << 14) -#define QH_SPEED_SHIFT 12 -#define QH_SPEED_MASK (0x3 << QH_SPEED_SHIFT) -#define QH_EP_SHIFT 8 -#define QH_EP_MASK (0xf << QH_EP_SHIFT) -#define QH_DEVADDR_SHIFT 0 -#define QH_DEVADDR_MASK (0x7f << QH_DEVADDR_SHIFT) - -#define QH_SMASK_SHIFT 0 -#define QH_SMASK_MASK (0xff << QH_SMASK_SHIFT) -#define QH_CMASK_SHIFT 8 -#define QH_CMASK_MASK (0xff << QH_CMASK_SHIFT) -#define QH_HUBADDR_SHIFT 16 -#define QH_HUBADDR_MASK (0x7f << QH_HUBADDR_SHIFT) -#define QH_HUBPORT_SHIFT 23 -#define QH_HUBPORT_MASK (0x7f << QH_HUBPORT_SHIFT) -#define QH_MULT_SHIFT 30 -#define QH_MULT_MASK (0x3 << QH_MULT_SHIFT) - -#define EHCI_PTR_BITS 0x001F -#define EHCI_PTR_TERM 0x0001 -#define EHCI_PTR_QH 0x0002 - - -#define EHCI_QTD_ALIGN 64 // Can't span a 4K boundary, so increase from 32 - -struct ehci_qtd { - u32 qtd_next; - u32 alt_next; - u32 token; - u32 buf[5]; - u32 buf_hi[5]; - /* keep struct size a multiple of 64 bytes, as we're allocating - arrays. Without this padding, the second qtd could have the - wrong alignment. */ -} PACKED __aligned(EHCI_QTD_ALIGN); - -#define QTD_TOGGLE (1 << 31) -#define QTD_LENGTH_SHIFT 16 -#define QTD_LENGTH_MASK (0x7fff << QTD_LENGTH_SHIFT) -#define QTD_CERR_SHIFT 10 -#define QTD_CERR_MASK (0x3 << QTD_CERR_SHIFT) -#define QTD_IOC (1 << 15) -#define QTD_PID_OUT (0x0 << 8) -#define QTD_PID_IN (0x1 << 8) -#define QTD_PID_SETUP (0x2 << 8) -#define QTD_STS_ACTIVE (1 << 7) -#define QTD_STS_HALT (1 << 6) -#define QTD_STS_DBE (1 << 5) -#define QTD_STS_BABBLE (1 << 4) -#define QTD_STS_XACT (1 << 3) -#define QTD_STS_MMF (1 << 2) -#define QTD_STS_STS (1 << 1) -#define QTD_STS_PING (1 << 0) - -#define ehci_explen(len) (((len) << QTD_LENGTH_SHIFT) & QTD_LENGTH_MASK) - -#define ehci_maxerr(err) (((err) << QTD_CERR_SHIFT) & QTD_CERR_MASK) - - -struct ehci_framelist { - u32 links[1024]; -} PACKED; - -#endif // usb-ehci.h diff -Nru seabios-1.7.1/src/usb.h seabios-1.7.4/src/usb.h --- seabios-1.7.1/src/usb.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,241 +0,0 @@ -// USB functions and data. -#ifndef __USB_H -#define __USB_H - -#include "util.h" // struct mutex_s - -// Information on a USB end point. -struct usb_pipe { - union { - struct usb_s *cntl; - struct usb_pipe *freenext; - }; - u8 type; - u8 ep; - u8 devaddr; - u8 speed; - u16 maxpacket; - u8 eptype; -}; - -// Common information for usb devices. -struct usbdevice_s { - struct usbhub_s *hub; - struct usb_pipe *defpipe; - u32 port; - struct usb_config_descriptor *config; - struct usb_interface_descriptor *iface; - int imax; - u8 speed; - u8 devaddr; -}; - -// Common information for usb controllers. -struct usb_s { - struct usb_pipe *freelist; - struct mutex_s resetlock; - struct pci_device *pci; - int busid; - u8 type; - u8 maxaddr; -}; - -// Information for enumerating USB hubs -struct usbhub_s { - struct usbhub_op_s *op; - struct usbdevice_s *usbdev; - struct usb_s *cntl; - struct mutex_s lock; - u32 powerwait; - u32 port; - u32 threads; - u32 portcount; - u32 devcount; -}; - -// Hub callback (32bit) info -struct usbhub_op_s { - int (*detect)(struct usbhub_s *hub, u32 port); - int (*reset)(struct usbhub_s *hub, u32 port); - void (*disconnect)(struct usbhub_s *hub, u32 port); -}; - -#define USB_TYPE_UHCI 1 -#define USB_TYPE_OHCI 2 -#define USB_TYPE_EHCI 3 - -#define USB_FULLSPEED 0 -#define USB_LOWSPEED 1 -#define USB_HIGHSPEED 2 - -#define USB_MAXADDR 127 - - -/**************************************************************** - * usb structs and flags - ****************************************************************/ - -// USB mandated timings (in ms) -#define USB_TIME_SIGATT 100 -#define USB_TIME_ATTDB 100 -#define USB_TIME_DRST 10 -#define USB_TIME_DRSTR 50 -#define USB_TIME_RSTRCY 10 - -#define USB_TIME_SETADDR_RECOVERY 2 - -#define USB_PID_OUT 0xe1 -#define USB_PID_IN 0x69 -#define USB_PID_SETUP 0x2d - -#define USB_DIR_OUT 0 /* to device */ -#define USB_DIR_IN 0x80 /* to host */ - -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) - -#define USB_RECIP_MASK 0x1f -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 - -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -struct usb_ctrlrequest { - u8 bRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; -} PACKED; - -#define USB_DT_DEVICE 0x01 -#define USB_DT_CONFIG 0x02 -#define USB_DT_STRING 0x03 -#define USB_DT_INTERFACE 0x04 -#define USB_DT_ENDPOINT 0x05 -#define USB_DT_DEVICE_QUALIFIER 0x06 -#define USB_DT_OTHER_SPEED_CONFIG 0x07 - -struct usb_device_descriptor { - u8 bLength; - u8 bDescriptorType; - - u16 bcdUSB; - u8 bDeviceClass; - u8 bDeviceSubClass; - u8 bDeviceProtocol; - u8 bMaxPacketSize0; - u16 idVendor; - u16 idProduct; - u16 bcdDevice; - u8 iManufacturer; - u8 iProduct; - u8 iSerialNumber; - u8 bNumConfigurations; -} PACKED; - -#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ -#define USB_CLASS_AUDIO 1 -#define USB_CLASS_COMM 2 -#define USB_CLASS_HID 3 -#define USB_CLASS_PHYSICAL 5 -#define USB_CLASS_STILL_IMAGE 6 -#define USB_CLASS_PRINTER 7 -#define USB_CLASS_MASS_STORAGE 8 -#define USB_CLASS_HUB 9 - -struct usb_config_descriptor { - u8 bLength; - u8 bDescriptorType; - - u16 wTotalLength; - u8 bNumInterfaces; - u8 bConfigurationValue; - u8 iConfiguration; - u8 bmAttributes; - u8 bMaxPower; -} PACKED; - -struct usb_interface_descriptor { - u8 bLength; - u8 bDescriptorType; - - u8 bInterfaceNumber; - u8 bAlternateSetting; - u8 bNumEndpoints; - u8 bInterfaceClass; - u8 bInterfaceSubClass; - u8 bInterfaceProtocol; - u8 iInterface; -} PACKED; - -struct usb_endpoint_descriptor { - u8 bLength; - u8 bDescriptorType; - - u8 bEndpointAddress; - u8 bmAttributes; - u16 wMaxPacketSize; - u8 bInterval; -} PACKED; - -#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ -#define USB_ENDPOINT_DIR_MASK 0x80 - -#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 -#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 - - -/**************************************************************** - * usb mass storage flags - ****************************************************************/ - -#define US_SC_ATAPI_8020 0x02 -#define US_SC_ATAPI_8070 0x05 -#define US_SC_SCSI 0x06 - -#define US_PR_BULK 0x50 /* bulk-only transport */ -#define US_PR_UAS 0x62 /* usb attached scsi */ - -/**************************************************************** - * function defs - ****************************************************************/ - -// usb.c -struct usb_pipe *usb_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); -int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize); -int usb_poll_intr(struct usb_pipe *pipe, void *data); -int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req - , void *data); -void free_pipe(struct usb_pipe *pipe); -struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype); -void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); -int usb_getFrameExp(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); -struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev - , int type, int dir); -void usb_enumerate(struct usbhub_s *hub); -void usb_setup(void); - -#endif // usb.h diff -Nru seabios-1.7.1/src/usb-hid.c seabios-1.7.4/src/usb-hid.c --- seabios-1.7.1/src/usb-hid.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-hid.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,431 +0,0 @@ -// Code for handling USB Human Interface Devices (HID). -// -// Copyright (C) 2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "usb-hid.h" // usb_keyboard_setup -#include "config.h" // CONFIG_* -#include "usb.h" // usb_ctrlrequest -#include "biosvar.h" // GET_GLOBAL -#include "ps2port.h" // ATKBD_CMD_GETID - -struct usb_pipe *keyboard_pipe VAR16VISIBLE; -struct usb_pipe *mouse_pipe VAR16VISIBLE; - - -/**************************************************************** - * Setup - ****************************************************************/ - -// Send USB HID protocol message. -static int -set_protocol(struct usb_pipe *pipe, u16 val) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - req.bRequest = HID_REQ_SET_PROTOCOL; - req.wValue = val; - req.wIndex = 0; - req.wLength = 0; - return send_default_control(pipe, &req, NULL); -} - -// Send USB HID SetIdle request. -static int -set_idle(struct usb_pipe *pipe, int ms) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - req.bRequest = HID_REQ_SET_IDLE; - req.wValue = (ms/4)<<8; - req.wIndex = 0; - req.wLength = 0; - return send_default_control(pipe, &req, NULL); -} - -#define KEYREPEATWAITMS 500 -#define KEYREPEATMS 33 - -static int -usb_kbd_init(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_KEYBOARD) - return -1; - if (keyboard_pipe) - // XXX - this enables the first found keyboard (could be random) - return -1; - - if (epdesc->wMaxPacketSize != 8) - return -1; - - // Enable "boot" protocol. - int ret = set_protocol(usbdev->defpipe, 0); - if (ret) - return -1; - // Periodically send reports to enable key repeat. - ret = set_idle(usbdev->defpipe, KEYREPEATMS); - if (ret) - return -1; - - keyboard_pipe = usb_alloc_pipe(usbdev, epdesc); - if (!keyboard_pipe) - return -1; - - dprintf(1, "USB keyboard initialized\n"); - return 0; -} - -static int -usb_mouse_init(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_MOUSE) - return -1; - if (mouse_pipe) - // XXX - this enables the first found mouse (could be random) - return -1; - - if (epdesc->wMaxPacketSize < 3 || epdesc->wMaxPacketSize > 8) - return -1; - - // Enable "boot" protocol. - int ret = set_protocol(usbdev->defpipe, 0); - if (ret) - return -1; - - mouse_pipe = usb_alloc_pipe(usbdev, epdesc); - if (!mouse_pipe) - return -1; - - dprintf(1, "USB mouse initialized\n"); - return 0; -} - -// Initialize a found USB HID device (if applicable). -int -usb_hid_init(struct usbdevice_s *usbdev) -{ - if (! CONFIG_USB_KEYBOARD || ! CONFIG_USB_MOUSE) - return -1; - dprintf(2, "usb_hid_init %p\n", usbdev->defpipe); - - struct usb_interface_descriptor *iface = usbdev->iface; - if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT) - // Doesn't support boot protocol. - return -1; - - // Find intr in endpoint. - struct usb_endpoint_descriptor *epdesc = findEndPointDesc( - usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN); - if (!epdesc) { - dprintf(1, "No usb hid intr in?\n"); - return -1; - } - - if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD) - return usb_kbd_init(usbdev, epdesc); - if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) - return usb_mouse_init(usbdev, epdesc); - return -1; -} - - -/**************************************************************** - * Keyboard events - ****************************************************************/ - -// Mapping from USB key id to ps2 key sequence. -static u16 KeyToScanCode[] VAR16 = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020, - 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, - 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, - 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003, - 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, - 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a, - 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034, - 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, - 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046, - 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d, - 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e, - 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047, - 0x0048, 0x0049, 0x0052, 0x0053 -}; - -// Mapping from USB modifier id to ps2 key sequence. -static u16 ModifierToScanCode[] VAR16 = { - //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui - 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c -}; - -#define RELEASEBIT 0x80 - -// Format of USB keyboard event data -struct keyevent { - u8 modifiers; - u8 reserved; - u8 keys[6]; -}; - -// Translate data from KeyToScanCode[] to calls to process_key(). -static void -prockeys(u16 keys) -{ - if (keys > 0xff) { - u8 key = keys>>8; - if (key == 0xe1) { - // Pause key - process_key(0xe1); - process_key(0x1d | (keys & RELEASEBIT)); - process_key(0x45 | (keys & RELEASEBIT)); - return; - } - process_key(key); - } - process_key(keys); -} - -// Handle a USB key press/release event. -static void -procscankey(u8 key, u8 flags) -{ - if (key >= ARRAY_SIZE(KeyToScanCode)) - return; - u16 keys = GET_GLOBAL(KeyToScanCode[key]); - if (keys) - prockeys(keys | flags); -} - -// Handle a USB modifier press/release event. -static void -procmodkey(u8 mods, u8 flags) -{ - int i; - for (i=0; mods; i++) - if (mods & (1<modifiers, data->keys[0]); - - // Load old keys. - struct usbkeyinfo old; - old.data = GET_LOW(LastUSBkey.data); - - // Check for keys no longer pressed. - int addpos = 0; - int i; - for (i=0; i=ARRAY_SIZE(data->keys)) { - // Key released. - procscankey(key, RELEASEBIT); - if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1]) - // Last pressed key released - disable repeat. - old.repeatcount = 0xff; - break; - } - if (data->keys[j] == key) { - // Key still pressed. - data->keys[j] = 0; - old.keys[addpos++] = key; - break; - } - } - } - procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT); - - // Process new keys - procmodkey(data->modifiers & ~old.modifiers, 0); - old.modifiers = data->modifiers; - for (i=0; ikeys); i++) { - u8 key = data->keys[i]; - if (!key) - continue; - // New key pressed. - procscankey(key, 0); - old.keys[addpos++] = key; - old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1; - } - if (addpos < ARRAY_SIZE(old.keys)) - old.keys[addpos] = 0; - - // Check for key repeat event. - if (addpos) { - if (!old.repeatcount) - procscankey(old.keys[addpos-1], 0); - else if (old.repeatcount != 0xff) - old.repeatcount--; - } - - // Update old keys - SET_LOW(LastUSBkey.data, old.data); -} - -// Check if a USB keyboard event is pending and process it if so. -static void -usb_check_key(void) -{ - if (! CONFIG_USB_KEYBOARD) - return; - struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe); - if (!pipe) - return; - - for (;;) { - struct keyevent data; - int ret = usb_poll_intr(pipe, &data); - if (ret) - break; - handle_key(&data); - } -} - -// Test if USB keyboard is active. -inline int -usb_kbd_active(void) -{ - if (! CONFIG_USB_KEYBOARD) - return 0; - return GET_GLOBAL(keyboard_pipe) != NULL; -} - -// Handle a ps2 style keyboard command. -inline int -usb_kbd_command(int command, u8 *param) -{ - if (! CONFIG_USB_KEYBOARD) - return -1; - dprintf(9, "usb keyboard cmd=%x\n", command); - switch (command) { - case ATKBD_CMD_GETID: - // Return the id of a standard AT keyboard. - param[0] = 0xab; - param[1] = 0x83; - return 0; - default: - return -1; - } -} - - -/**************************************************************** - * Mouse events - ****************************************************************/ - -// Format of USB mouse event data -struct mouseevent { - u8 buttons; - u8 x, y; - u8 reserved[5]; -}; - -// Process USB mouse data. -static void -handle_mouse(struct mouseevent *data) -{ - dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y); - - s8 x = data->x, y = -data->y; - u8 flag = ((data->buttons & 0x7) | (1<<3) - | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0)); - process_mouse(flag); - process_mouse(x); - process_mouse(y); -} - -// Check if a USB mouse event is pending and process it if so. -static void -usb_check_mouse(void) -{ - if (! CONFIG_USB_MOUSE) - return; - struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe); - if (!pipe) - return; - - for (;;) { - struct mouseevent data; - int ret = usb_poll_intr(pipe, &data); - if (ret) - break; - handle_mouse(&data); - } -} - -// Test if USB mouse is active. -inline int -usb_mouse_active(void) -{ - if (! CONFIG_USB_MOUSE) - return 0; - return GET_GLOBAL(mouse_pipe) != NULL; -} - -// Handle a ps2 style mouse command. -inline int -usb_mouse_command(int command, u8 *param) -{ - if (! CONFIG_USB_MOUSE) - return -1; - dprintf(9, "usb mouse cmd=%x\n", command); - switch (command) { - case PSMOUSE_CMD_ENABLE: - case PSMOUSE_CMD_DISABLE: - case PSMOUSE_CMD_SETSCALE11: - return 0; - case PSMOUSE_CMD_SETSCALE21: - case PSMOUSE_CMD_SETRATE: - case PSMOUSE_CMD_SETRES: - // XXX - return 0; - case PSMOUSE_CMD_RESET_BAT: - case PSMOUSE_CMD_GETID: - // Return the id of a standard AT mouse. - param[0] = 0xaa; - param[1] = 0x00; - return 0; - - case PSMOUSE_CMD_GETINFO: - param[0] = 0x00; - param[1] = 4; - param[2] = 100; - return 0; - - default: - return -1; - } -} - -// Check for USB events pending - called periodically from timer interrupt. -void -usb_check_event(void) -{ - usb_check_key(); - usb_check_mouse(); -} diff -Nru seabios-1.7.1/src/usb-hid.h seabios-1.7.4/src/usb-hid.h --- seabios-1.7.1/src/usb-hid.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-hid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -#ifndef __USB_HID_H -#define __USB_HID_H - -// usb-hid.c -struct usbdevice_s; -int usb_hid_init(struct usbdevice_s *usbdev); -inline int usb_kbd_active(void); -inline int usb_kbd_command(int command, u8 *param); -inline int usb_mouse_active(void); -inline int usb_mouse_command(int command, u8 *param); -void usb_check_event(void); - - -/**************************************************************** - * hid flags - ****************************************************************/ - -#define USB_INTERFACE_SUBCLASS_BOOT 1 -#define USB_INTERFACE_PROTOCOL_KEYBOARD 1 -#define USB_INTERFACE_PROTOCOL_MOUSE 2 - -#define HID_REQ_GET_REPORT 0x01 -#define HID_REQ_GET_IDLE 0x02 -#define HID_REQ_GET_PROTOCOL 0x03 -#define HID_REQ_SET_REPORT 0x09 -#define HID_REQ_SET_IDLE 0x0A -#define HID_REQ_SET_PROTOCOL 0x0B - -#endif // ush-hid.h diff -Nru seabios-1.7.1/src/usb-hub.c seabios-1.7.4/src/usb-hub.c --- seabios-1.7.1/src/usb-hub.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-hub.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,185 +0,0 @@ -// Code for handling standard USB hubs. -// -// Copyright (C) 2010 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "config.h" // CONFIG_USB_HUB -#include "usb-hub.h" // struct usb_hub_descriptor -#include "usb.h" // struct usb_s - -static int -get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE; - req.bRequest = USB_REQ_GET_DESCRIPTOR; - req.wValue = USB_DT_HUB<<8; - req.wIndex = 0; - req.wLength = sizeof(*desc); - return send_default_control(pipe, &req, desc); -} - -static int -set_port_feature(struct usbhub_s *hub, int port, int feature) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER; - req.bRequest = USB_REQ_SET_FEATURE; - req.wValue = feature; - req.wIndex = port + 1; - req.wLength = 0; - mutex_lock(&hub->lock); - int ret = send_default_control(hub->usbdev->defpipe, &req, NULL); - mutex_unlock(&hub->lock); - return ret; -} - -static int -clear_port_feature(struct usbhub_s *hub, int port, int feature) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER; - req.bRequest = USB_REQ_CLEAR_FEATURE; - req.wValue = feature; - req.wIndex = port + 1; - req.wLength = 0; - mutex_lock(&hub->lock); - int ret = send_default_control(hub->usbdev->defpipe, &req, NULL); - mutex_unlock(&hub->lock); - return ret; -} - -static int -get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER; - req.bRequest = USB_REQ_GET_STATUS; - req.wValue = 0; - req.wIndex = port + 1; - req.wLength = sizeof(*sts); - mutex_lock(&hub->lock); - int ret = send_default_control(hub->usbdev->defpipe, &req, sts); - mutex_unlock(&hub->lock); - return ret; -} - -// Check if device attached to port -static int -usb_hub_detect(struct usbhub_s *hub, u32 port) -{ - // Turn on power to port. - int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER); - if (ret) - goto fail; - - // Wait for port power to stabilize. - msleep(hub->powerwait); - - // Check periodically for a device connect. - struct usb_port_status sts; - u64 end = calc_future_tsc(USB_TIME_SIGATT); - for (;;) { - ret = get_port_status(hub, port, &sts); - if (ret) - goto fail; - if (sts.wPortStatus & USB_PORT_STAT_CONNECTION) - // Device connected. - break; - if (check_tsc(end)) - // No device found. - return -1; - msleep(5); - } - - // XXX - wait USB_TIME_ATTDB time? - - return 0; - -fail: - dprintf(1, "Failure on hub port %d detect\n", port); - return -1; -} - -// Disable port -static void -usb_hub_disconnect(struct usbhub_s *hub, u32 port) -{ - int ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE); - if (ret) - dprintf(1, "Failure on hub port %d disconnect\n", port); -} - -// Reset device on port -static int -usb_hub_reset(struct usbhub_s *hub, u32 port) -{ - int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET); - if (ret) - goto fail; - - // Wait for reset to complete. - struct usb_port_status sts; - u64 end = calc_future_tsc(USB_TIME_DRST * 2); - for (;;) { - ret = get_port_status(hub, port, &sts); - if (ret) - goto fail; - if (!(sts.wPortStatus & USB_PORT_STAT_RESET)) - break; - if (check_tsc(end)) { - warn_timeout(); - goto fail; - } - msleep(5); - } - - // Reset complete. - if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION)) - // Device no longer present - return -1; - - return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK) - >> USB_PORT_STAT_SPEED_SHIFT); - -fail: - dprintf(1, "Failure on hub port %d reset\n", port); - usb_hub_disconnect(hub, port); - return -1; -} - -static struct usbhub_op_s HubOp = { - .detect = usb_hub_detect, - .reset = usb_hub_reset, - .disconnect = usb_hub_disconnect, -}; - -// Configure a usb hub and then find devices connected to it. -int -usb_hub_init(struct usbdevice_s *usbdev) -{ - ASSERT32FLAT(); - if (!CONFIG_USB_HUB) - return -1; - - struct usb_hub_descriptor desc; - int ret = get_hub_desc(usbdev->defpipe, &desc); - if (ret) - return ret; - - struct usbhub_s hub; - memset(&hub, 0, sizeof(hub)); - hub.usbdev = usbdev; - hub.cntl = usbdev->defpipe->cntl; - hub.powerwait = desc.bPwrOn2PwrGood * 2; - hub.portcount = desc.bNbrPorts; - hub.op = &HubOp; - usb_enumerate(&hub); - - dprintf(1, "Initialized USB HUB (%d ports used)\n", hub.devcount); - if (hub.devcount) - return 0; - return -1; -} diff -Nru seabios-1.7.1/src/usb-hub.h seabios-1.7.4/src/usb-hub.h --- seabios-1.7.1/src/usb-hub.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-hub.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -#ifndef __USB_HUB_H -#define __USB_HUB_H - -// usb-hub.c -struct usbdevice_s; -int usb_hub_init(struct usbdevice_s *usbdev); - - -/**************************************************************** - * hub flags - ****************************************************************/ - -#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) - -struct usb_hub_descriptor { - u8 bDescLength; - u8 bDescriptorType; - u8 bNbrPorts; - u16 wHubCharacteristics; - u8 bPwrOn2PwrGood; - u8 bHubContrCurrent; - // Variable length fields for DeviceRemovable[], PortPwrCtrlMask[] follow. -} PACKED; - -#define USB_PORT_FEAT_CONNECTION 0 -#define USB_PORT_FEAT_ENABLE 1 -#define USB_PORT_FEAT_SUSPEND 2 -#define USB_PORT_FEAT_OVER_CURRENT 3 -#define USB_PORT_FEAT_RESET 4 -#define USB_PORT_FEAT_POWER 8 -#define USB_PORT_FEAT_LOWSPEED 9 -#define USB_PORT_FEAT_C_CONNECTION 16 -#define USB_PORT_FEAT_C_ENABLE 17 -#define USB_PORT_FEAT_C_SUSPEND 18 -#define USB_PORT_FEAT_C_OVER_CURRENT 19 -#define USB_PORT_FEAT_C_RESET 20 -#define USB_PORT_FEAT_TEST 21 -#define USB_PORT_FEAT_INDICATOR 22 -#define USB_PORT_FEAT_C_PORT_L1 23 - -struct usb_port_status { - u16 wPortStatus; - u16 wPortChange; -} PACKED; - -#define USB_PORT_STAT_CONNECTION 0x0001 -#define USB_PORT_STAT_ENABLE 0x0002 -#define USB_PORT_STAT_SUSPEND 0x0004 -#define USB_PORT_STAT_OVERCURRENT 0x0008 -#define USB_PORT_STAT_RESET 0x0010 -#define USB_PORT_STAT_L1 0x0020 -#define USB_PORT_STAT_POWER 0x0100 -#define USB_PORT_STAT_SPEED_SHIFT 9 -#define USB_PORT_STAT_SPEED_MASK (0x3 << USB_PORT_STAT_SPEED_SHIFT) -#define USB_PORT_STAT_LOW_SPEED 0x0200 -#define USB_PORT_STAT_HIGH_SPEED 0x0400 -#define USB_PORT_STAT_TEST 0x0800 -#define USB_PORT_STAT_INDICATOR 0x1000 - -#endif // ush-hid.h diff -Nru seabios-1.7.1/src/usb-msc.c seabios-1.7.4/src/usb-msc.c --- seabios-1.7.1/src/usb-msc.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-msc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,215 +0,0 @@ -// Code for handling USB Mass Storage Controller devices. -// -// Copyright (C) 2010 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "config.h" // CONFIG_USB_MSC -#include "usb-msc.h" // usb_msc_init -#include "usb.h" // struct usb_s -#include "biosvar.h" // GET_GLOBAL -#include "blockcmd.h" // cdb_read -#include "disk.h" // DTYPE_USB -#include "boot.h" // bootprio_find_usb - -struct usbdrive_s { - struct drive_s drive; - struct usb_pipe *bulkin, *bulkout; - int lun; -}; - - -/**************************************************************** - * Bulk-only drive command processing - ****************************************************************/ - -#define USB_CDB_SIZE 12 - -#define CBW_SIGNATURE 0x43425355 // USBC - -struct cbw_s { - u32 dCBWSignature; - u32 dCBWTag; - u32 dCBWDataTransferLength; - u8 bmCBWFlags; - u8 bCBWLUN; - u8 bCBWCBLength; - u8 CBWCB[16]; -} PACKED; - -#define CSW_SIGNATURE 0x53425355 // USBS - -struct csw_s { - u32 dCSWSignature; - u32 dCSWTag; - u32 dCSWDataResidue; - u8 bCSWStatus; -} PACKED; - -static int -usb_msc_send(struct usbdrive_s *udrive_g, int dir, void *buf, u32 bytes) -{ - struct usb_pipe *pipe; - if (dir == USB_DIR_OUT) - pipe = GET_GLOBAL(udrive_g->bulkout); - else - pipe = GET_GLOBAL(udrive_g->bulkin); - return usb_send_bulk(pipe, dir, buf, bytes); -} - -// Low-level usb command transmit function. -int -usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - if (!CONFIG_USB_MSC) - return 0; - - dprintf(16, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n" - , op->drive_g, 0, op->count, blocksize, op->buf_fl); - struct usbdrive_s *udrive_g = container_of( - op->drive_g, struct usbdrive_s, drive); - - // Setup command block wrapper. - u32 bytes = blocksize * op->count; - struct cbw_s cbw; - memset(&cbw, 0, sizeof(cbw)); - memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE); - cbw.dCBWSignature = CBW_SIGNATURE; - cbw.dCBWTag = 999; // XXX - cbw.dCBWDataTransferLength = bytes; - cbw.bmCBWFlags = cdb_is_read(cdbcmd, blocksize) ? USB_DIR_IN : USB_DIR_OUT; - cbw.bCBWLUN = GET_GLOBAL(udrive_g->lun); - cbw.bCBWCBLength = USB_CDB_SIZE; - - // Transfer cbw to device. - int ret = usb_msc_send(udrive_g, USB_DIR_OUT - , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw)); - if (ret) - goto fail; - - // Transfer data to/from device. - if (bytes) { - ret = usb_msc_send(udrive_g, cbw.bmCBWFlags, op->buf_fl, bytes); - if (ret) - goto fail; - } - - // Transfer csw info. - struct csw_s csw; - ret = usb_msc_send(udrive_g, USB_DIR_IN - , MAKE_FLATPTR(GET_SEG(SS), &csw), sizeof(csw)); - if (ret) - goto fail; - - if (!csw.bCSWStatus) - return DISK_RET_SUCCESS; - if (csw.bCSWStatus == 2) - goto fail; - - if (blocksize) - op->count -= csw.dCSWDataResidue / blocksize; - return DISK_RET_EBADTRACK; - -fail: - // XXX - reset connection - dprintf(1, "USB transmission failed\n"); - op->count = 0; - return DISK_RET_EBADTRACK; -} - -static int -usb_msc_maxlun(struct usb_pipe *pipe) -{ - struct usb_ctrlrequest req; - req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - req.bRequest = 0xfe; - req.wValue = 0; - req.wIndex = 0; - req.wLength = 1; - unsigned char maxlun; - int ret = send_default_control(pipe, &req, &maxlun); - if (ret) - return 0; - return maxlun; -} - -static int -usb_msc_init_lun(struct usb_pipe *inpipe, struct usb_pipe *outpipe, - struct usbdevice_s *usbdev, int lun) -{ - // Allocate drive structure. - struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g)); - if (!udrive_g) { - warn_noalloc(); - return -1; - } - memset(udrive_g, 0, sizeof(*udrive_g)); - udrive_g->drive.type = DTYPE_USB; - udrive_g->bulkin = inpipe; - udrive_g->bulkout = outpipe; - udrive_g->lun = lun; - - int prio = bootprio_find_usb(usbdev, lun); - int ret = scsi_init_drive(&udrive_g->drive, "USB MSC", prio); - if (ret) { - dprintf(1, "Unable to configure USB MSC drive.\n"); - free(udrive_g); - return -1; - } - return 0; -} - -/**************************************************************** - * Setup - ****************************************************************/ - -// Configure a usb msc device. -int -usb_msc_init(struct usbdevice_s *usbdev) -{ - if (!CONFIG_USB_MSC) - return -1; - - // Verify right kind of device - struct usb_interface_descriptor *iface = usbdev->iface; - if ((iface->bInterfaceSubClass != US_SC_SCSI && - iface->bInterfaceSubClass != US_SC_ATAPI_8070 && - iface->bInterfaceSubClass != US_SC_ATAPI_8020) - || iface->bInterfaceProtocol != US_PR_BULK) { - dprintf(1, "Unsupported MSC USB device (subclass=%02x proto=%02x)\n" - , iface->bInterfaceSubClass, iface->bInterfaceProtocol); - return -1; - } - - // Find bulk in and bulk out endpoints. - struct usb_pipe *inpipe = NULL, *outpipe = NULL; - struct usb_endpoint_descriptor *indesc = findEndPointDesc( - usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_IN); - struct usb_endpoint_descriptor *outdesc = findEndPointDesc( - usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); - if (!indesc || !outdesc) - goto fail; - inpipe = usb_alloc_pipe(usbdev, indesc); - outpipe = usb_alloc_pipe(usbdev, outdesc); - if (!inpipe || !outpipe) - goto fail; - - int maxlun = usb_msc_maxlun(usbdev->defpipe); - int lun, pipesused = 0; - for (lun = 0; lun < maxlun + 1; lun++) { - int ret = usb_msc_init_lun(inpipe, outpipe, usbdev, lun); - if (!ret) - pipesused = 1; - } - - if (!pipesused) - goto fail; - - return 0; -fail: - dprintf(1, "Unable to configure USB MSC device.\n"); - free_pipe(inpipe); - free_pipe(outpipe); - return -1; -} diff -Nru seabios-1.7.1/src/usb-msc.h seabios-1.7.4/src/usb-msc.h --- seabios-1.7.1/src/usb-msc.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-msc.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#ifndef __USB_MSC_H -#define __USB_MSC_H - -// usb-msc.c -struct disk_op_s; -int usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); -struct usbdevice_s; -int usb_msc_init(struct usbdevice_s *usbdev); - -#endif // ush-msc.h diff -Nru seabios-1.7.1/src/usb-ohci.c seabios-1.7.4/src/usb-ohci.c --- seabios-1.7.1/src/usb-ohci.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-ohci.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,534 +0,0 @@ -// Code for handling OHCI USB controllers. -// -// Copyright (C) 2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // pci_bdf_to_bus -#include "config.h" // CONFIG_* -#include "usb-ohci.h" // struct ohci_hcca -#include "pci_regs.h" // PCI_BASE_ADDRESS_0 -#include "usb.h" // struct usb_s -#include "biosvar.h" // GET_LOWFLAT - -#define FIT (1 << 31) - -struct usb_ohci_s { - struct usb_s usb; - struct ohci_regs *regs; -}; - -struct ohci_pipe { - struct ohci_ed ed; - struct usb_pipe pipe; - void *data; - int count; - struct ohci_td *tds; -}; - - -/**************************************************************** - * Root hub - ****************************************************************/ - -// Check if device attached to port -static int -ohci_hub_detect(struct usbhub_s *hub, u32 port) -{ - struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb); - u32 sts = readl(&cntl->regs->roothub_portstatus[port]); - if (!(sts & RH_PS_CCS)) - // No device. - return -1; - - // XXX - need to wait for USB_TIME_ATTDB if just powered up? - - return 0; -} - -// Disable port -static void -ohci_hub_disconnect(struct usbhub_s *hub, u32 port) -{ - struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb); - writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA); -} - -// Reset device on port -static int -ohci_hub_reset(struct usbhub_s *hub, u32 port) -{ - struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb); - writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS); - u32 sts; - u64 end = calc_future_tsc(USB_TIME_DRSTR * 2); - for (;;) { - sts = readl(&cntl->regs->roothub_portstatus[port]); - if (!(sts & RH_PS_PRS)) - // XXX - need to ensure USB_TIME_DRSTR time in reset? - break; - if (check_tsc(end)) { - // Timeout. - warn_timeout(); - ohci_hub_disconnect(hub, port); - return -1; - } - yield(); - } - - if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES)) - // Device no longer present - return -1; - - return !!(sts & RH_PS_LSDA); -} - -static struct usbhub_op_s ohci_HubOp = { - .detect = ohci_hub_detect, - .reset = ohci_hub_reset, - .disconnect = ohci_hub_disconnect, -}; - -// Find any devices connected to the root hub. -static int -check_ohci_ports(struct usb_ohci_s *cntl) -{ - ASSERT32FLAT(); - // Turn on power for all devices on roothub. - u32 rha = readl(&cntl->regs->roothub_a); - rha &= ~(RH_A_PSM | RH_A_OCPM); - writel(&cntl->regs->roothub_status, RH_HS_LPSC); - writel(&cntl->regs->roothub_b, RH_B_PPCM); - msleep((rha >> 24) * 2); - // XXX - need to sleep for USB_TIME_SIGATT if just powered up? - - struct usbhub_s hub; - memset(&hub, 0, sizeof(hub)); - hub.cntl = &cntl->usb; - hub.portcount = rha & RH_A_NDP; - hub.op = &ohci_HubOp; - usb_enumerate(&hub); - return hub.devcount; -} - - -/**************************************************************** - * Setup - ****************************************************************/ - -// Wait for next USB frame to start - for ensuring safe memory release. -static void -ohci_waittick(struct usb_ohci_s *cntl) -{ - barrier(); - struct ohci_hcca *hcca = (void*)cntl->regs->hcca; - u32 startframe = hcca->frame_no; - u64 end = calc_future_tsc(1000 * 5); - for (;;) { - if (hcca->frame_no != startframe) - break; - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } -} - -static void -ohci_free_pipes(struct usb_ohci_s *cntl) -{ - dprintf(7, "ohci_free_pipes %p\n", cntl); - - u32 creg = readl(&cntl->regs->control); - if (creg & (OHCI_CTRL_CLE|OHCI_CTRL_BLE)) { - writel(&cntl->regs->control, creg & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE)); - ohci_waittick(cntl); - } - - u32 *pos = &cntl->regs->ed_controlhead; - for (;;) { - struct ohci_ed *next = (void*)*pos; - if (!next) - break; - struct ohci_pipe *pipe = container_of(next, struct ohci_pipe, ed); - if (pipe->pipe.cntl != &cntl->usb) { - *pos = next->hwNextED; - free(pipe); - } else { - pos = &next->hwNextED; - } - } - - writel(&cntl->regs->ed_controlcurrent, 0); - writel(&cntl->regs->ed_bulkcurrent, 0); - writel(&cntl->regs->control, creg); - cntl->usb.freelist = NULL; -} - -static int -start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca) -{ - u32 oldfminterval = readl(&cntl->regs->fminterval); - u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC; - - // XXX - check if already running? - - // Do reset - writel(&cntl->regs->control, OHCI_USB_RESET | oldrwc); - readl(&cntl->regs->control); // flush writes - msleep(USB_TIME_DRSTR); - - // Do software init (min 10us, max 2ms) - u64 end = calc_future_tsc_usec(10); - writel(&cntl->regs->cmdstatus, OHCI_HCR); - for (;;) { - u32 status = readl(&cntl->regs->cmdstatus); - if (! status & OHCI_HCR) - break; - if (check_tsc(end)) { - warn_timeout(); - return -1; - } - } - - // Init memory - writel(&cntl->regs->ed_controlhead, 0); - writel(&cntl->regs->ed_bulkhead, 0); - writel(&cntl->regs->hcca, (u32)hcca); - - // Init fminterval - u32 fi = oldfminterval & 0x3fff; - writel(&cntl->regs->fminterval - , (((oldfminterval & FIT) ^ FIT) - | fi | (((6 * (fi - 210)) / 7) << 16))); - writel(&cntl->regs->periodicstart, ((9 * fi) / 10) & 0x3fff); - readl(&cntl->regs->control); // flush writes - - // XXX - verify that fminterval was setup correctly. - - // Go into operational state - writel(&cntl->regs->control - , (OHCI_CTRL_CBSR | OHCI_CTRL_CLE | OHCI_CTRL_PLE - | OHCI_USB_OPER | oldrwc)); - readl(&cntl->regs->control); // flush writes - - return 0; -} - -static void -stop_ohci(struct usb_ohci_s *cntl) -{ - u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC; - writel(&cntl->regs->control, oldrwc); - readl(&cntl->regs->control); // flush writes -} - -static void -configure_ohci(void *data) -{ - struct usb_ohci_s *cntl = data; - - // Allocate memory - struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca)); - struct ohci_ed *intr_ed = malloc_high(sizeof(*intr_ed)); - if (!hcca || !intr_ed) { - warn_noalloc(); - goto free; - } - memset(hcca, 0, sizeof(*hcca)); - memset(intr_ed, 0, sizeof(*intr_ed)); - intr_ed->hwINFO = ED_SKIP; - int i; - for (i=0; iint_table); i++) - hcca->int_table[i] = (u32)intr_ed; - - int ret = start_ohci(cntl, hcca); - if (ret) - goto err; - - int count = check_ohci_ports(cntl); - ohci_free_pipes(cntl); - if (! count) - goto err; - return; - -err: - stop_ohci(cntl); -free: - free(hcca); - free(intr_ed); -} - -void -ohci_init(struct pci_device *pci, int busid) -{ - if (! CONFIG_USB_OHCI) - return; - struct usb_ohci_s *cntl = malloc_tmphigh(sizeof(*cntl)); - if (!cntl) { - warn_noalloc(); - return; - } - memset(cntl, 0, sizeof(*cntl)); - cntl->usb.busid = busid; - cntl->usb.pci = pci; - cntl->usb.type = USB_TYPE_OHCI; - - u16 bdf = pci->bdf; - u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); - cntl->regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); - - dprintf(1, "OHCI init on dev %02x:%02x.%x (regs=%p)\n" - , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) - , pci_bdf_to_fn(bdf), cntl->regs); - - // Enable bus mastering and memory access. - pci_config_maskw(bdf, PCI_COMMAND - , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY); - - // XXX - check for and disable SMM control? - - // Disable interrupts - writel(&cntl->regs->intrdisable, ~0); - writel(&cntl->regs->intrstatus, ~0); - - run_thread(configure_ohci, cntl); -} - - -/**************************************************************** - * End point communication - ****************************************************************/ - -// Setup fields in ed -static void -ohci_desc2pipe(struct ohci_pipe *pipe, struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - pipe->ed.hwINFO = (ED_SKIP | usbdev->devaddr | (pipe->pipe.ep << 7) - | (epdesc->wMaxPacketSize << 16) - | (usbdev->speed ? ED_LOWSPEED : 0)); -} - -static struct usb_pipe * -ohci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - struct usb_ohci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_ohci_s, usb); - int frameexp = usb_getFrameExp(usbdev, epdesc); - dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); - - if (frameexp > 5) - frameexp = 5; - int maxpacket = epdesc->wMaxPacketSize; - // Determine number of entries needed for 2 timer ticks. - int ms = 1<ed.hwINFO &= ~ED_SKIP; - pipe->data = data; - pipe->count = count; - pipe->tds = tds; - - struct ohci_ed *ed = &pipe->ed; - ed->hwHeadP = (u32)&tds[0]; - ed->hwTailP = (u32)&tds[count-1]; - - int i; - for (i=0; iregs->hcca; - if (frameexp == 0) { - // Add to existing interrupt entry. - struct ohci_ed *intr_ed = (void*)hcca->int_table[0]; - ed->hwNextED = intr_ed->hwNextED; - barrier(); - intr_ed->hwNextED = (u32)ed; - } else { - int startpos = 1<<(frameexp-1); - ed->hwNextED = hcca->int_table[startpos]; - barrier(); - for (i=startpos; iint_table); i+=ms) - hcca->int_table[i] = (u32)ed; - } - - return &pipe->pipe; - -err: - free(pipe); - free(tds); - free(data); - return NULL; -} - -struct usb_pipe * -ohci_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_OHCI) - return NULL; - u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (eptype == USB_ENDPOINT_XFER_INT) - return ohci_alloc_intr_pipe(usbdev, epdesc); - if (eptype != USB_ENDPOINT_XFER_CONTROL) { - dprintf(1, "OHCI Bulk transfers not supported.\n"); - return NULL; - } - struct usb_ohci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_ohci_s, usb); - dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb); - - struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); - if (usbpipe) { - // Use previously allocated pipe. - struct ohci_pipe *pipe = container_of(usbpipe, struct ohci_pipe, pipe); - ohci_desc2pipe(pipe, usbdev, epdesc); - return usbpipe; - } - - // Allocate a new queue head. - struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe)); - if (!pipe) { - warn_noalloc(); - return NULL; - } - memset(pipe, 0, sizeof(*pipe)); - ohci_desc2pipe(pipe, usbdev, epdesc); - - // Add queue head to controller list. - pipe->ed.hwNextED = cntl->regs->ed_controlhead; - barrier(); - cntl->regs->ed_controlhead = (u32)&pipe->ed; - return &pipe->pipe; -} - -static int -wait_ed(struct ohci_ed *ed) -{ - // XXX - 500ms just a guess - u64 end = calc_future_tsc(500); - for (;;) { - if (ed->hwHeadP == ed->hwTailP) - return 0; - if (check_tsc(end)) { - warn_timeout(); - return -1; - } - yield(); - } -} - -int -ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize - , void *data, int datasize) -{ - if (! CONFIG_USB_OHCI) - return -1; - dprintf(5, "ohci_control %p\n", p); - if (datasize > 4096) { - // XXX - should support larger sizes. - warn_noalloc(); - return -1; - } - struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); - struct usb_ohci_s *cntl = container_of( - pipe->pipe.cntl, struct usb_ohci_s, usb); - - // Setup transfer descriptors - struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3); - if (!tds) { - warn_noalloc(); - return -1; - } - struct ohci_td *td = tds; - td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC; - td->hwCBP = (u32)cmd; - td->hwNextTD = (u32)&td[1]; - td->hwBE = (u32)cmd + cmdsize - 1; - td++; - if (datasize) { - td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC; - td->hwCBP = (u32)data; - td->hwNextTD = (u32)&td[1]; - td->hwBE = (u32)data + datasize - 1; - td++; - } - td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC; - td->hwCBP = 0; - td->hwNextTD = (u32)&td[1]; - td->hwBE = 0; - td++; - - // Transfer data - pipe->ed.hwHeadP = (u32)tds; - pipe->ed.hwTailP = (u32)td; - barrier(); - pipe->ed.hwINFO &= ~ED_SKIP; - writel(&cntl->regs->cmdstatus, OHCI_CLF); - - int ret = wait_ed(&pipe->ed); - pipe->ed.hwINFO |= ED_SKIP; - if (ret) - ohci_waittick(cntl); - free(tds); - return ret; -} - -int -ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) -{ - return -1; -} - -int -ohci_poll_intr(struct usb_pipe *p, void *data) -{ - ASSERT16(); - if (! CONFIG_USB_OHCI) - return -1; - - struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); - struct ohci_td *tds = GET_LOWFLAT(pipe->tds); - struct ohci_td *head = (void*)(GET_LOWFLAT(pipe->ed.hwHeadP) & ~(ED_C|ED_H)); - struct ohci_td *tail = (void*)GET_LOWFLAT(pipe->ed.hwTailP); - int count = GET_LOWFLAT(pipe->count); - int pos = (tail - tds + 1) % count; - struct ohci_td *next = &tds[pos]; - if (head == next) - // No intrs found. - return -1; - // XXX - check for errors. - - // Copy data. - int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); - void *pipedata = GET_LOWFLAT((pipe->data)); - void *intrdata = pipedata + maxpacket * pos; - memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(intrdata), maxpacket); - - // Reenable this td. - SET_LOWFLAT(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC); - intrdata = pipedata + maxpacket * (tail-tds); - SET_LOWFLAT(tail->hwCBP, (u32)intrdata); - SET_LOWFLAT(tail->hwNextTD, (u32)next); - SET_LOWFLAT(tail->hwBE, (u32)intrdata + maxpacket - 1); - barrier(); - SET_LOWFLAT(pipe->ed.hwTailP, (u32)next); - - return 0; -} diff -Nru seabios-1.7.1/src/usb-ohci.h seabios-1.7.4/src/usb-ohci.h --- seabios-1.7.1/src/usb-ohci.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-ohci.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ -#ifndef __USB_OHCI_H -#define __USB_OHCI_H - -// usb-ohci.c -void ohci_init(struct pci_device *pci, int busid); -struct usbdevice_s; -struct usb_endpoint_descriptor; -struct usb_pipe *ohci_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); -struct usb_pipe; -int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize - , void *data, int datasize); -int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); -int ohci_poll_intr(struct usb_pipe *p, void *data); - - -/**************************************************************** - * ohci structs and flags - ****************************************************************/ - -struct ohci_ed { - u32 hwINFO; - u32 hwTailP; - u32 hwHeadP; - u32 hwNextED; -} PACKED; - -#define ED_ISO (1 << 15) -#define ED_SKIP (1 << 14) -#define ED_LOWSPEED (1 << 13) -#define ED_OUT (0x01 << 11) -#define ED_IN (0x02 << 11) - -#define ED_C (0x02) -#define ED_H (0x01) - -struct ohci_td { - u32 hwINFO; - u32 hwCBP; - u32 hwNextTD; - u32 hwBE; -} PACKED; - -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -#define TD_DI 0x00E00000 - -#define TD_DONE 0x00020000 -#define TD_ISO 0x00010000 - -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_R 0x00040000 - -struct ohci_hcca { - u32 int_table[32]; - u32 frame_no; - u32 done_head; - u8 reserved[120]; -} PACKED; - -struct ohci_regs { - u32 revision; - u32 control; - u32 cmdstatus; - u32 intrstatus; - u32 intrenable; - u32 intrdisable; - - u32 hcca; - u32 ed_periodcurrent; - u32 ed_controlhead; - u32 ed_controlcurrent; - u32 ed_bulkhead; - u32 ed_bulkcurrent; - u32 donehead; - - u32 fminterval; - u32 fmremaining; - u32 fmnumber; - u32 periodicstart; - u32 lsthresh; - - u32 roothub_a; - u32 roothub_b; - u32 roothub_status; - u32 roothub_portstatus[15]; -} PACKED; - -#define OHCI_CTRL_CBSR (3 << 0) -#define OHCI_CTRL_PLE (1 << 2) -#define OHCI_CTRL_CLE (1 << 4) -#define OHCI_CTRL_BLE (1 << 5) -#define OHCI_CTRL_HCFS (3 << 6) -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_OPER (2 << 6) -#define OHCI_CTRL_RWC (1 << 9) - -#define OHCI_HCR (1 << 0) -#define OHCI_CLF (1 << 1) - -#define OHCI_INTR_MIE (1 << 31) - -#define RH_PS_CCS 0x00000001 -#define RH_PS_PES 0x00000002 -#define RH_PS_PSS 0x00000004 -#define RH_PS_POCI 0x00000008 -#define RH_PS_PRS 0x00000010 -#define RH_PS_PPS 0x00000100 -#define RH_PS_LSDA 0x00000200 -#define RH_PS_CSC 0x00010000 -#define RH_PS_PESC 0x00020000 -#define RH_PS_PSSC 0x00040000 -#define RH_PS_OCIC 0x00080000 -#define RH_PS_PRSC 0x00100000 - -#define RH_HS_LPS 0x00000001 -#define RH_HS_OCI 0x00000002 -#define RH_HS_DRWE 0x00008000 -#define RH_HS_LPSC 0x00010000 -#define RH_HS_OCIC 0x00020000 -#define RH_HS_CRWE 0x80000000 - -#define RH_B_DR 0x0000ffff -#define RH_B_PPCM 0xffff0000 - -#define RH_A_NDP (0xff << 0) -#define RH_A_PSM (1 << 8) -#define RH_A_NPS (1 << 9) -#define RH_A_DT (1 << 10) -#define RH_A_OCPM (1 << 11) -#define RH_A_NOCP (1 << 12) -#define RH_A_POTPGT (0xff << 24) - -#endif // usb-ohci.h diff -Nru seabios-1.7.1/src/usb-uas.c seabios-1.7.4/src/usb-uas.c --- seabios-1.7.1/src/usb-uas.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-uas.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,264 +0,0 @@ -// Code for handling usb attached scsi devices. -// -// only usb 2.0 for now. -// -// once we have xhci driver with usb 3.0 support this must -// be updated to use usb3 streams so booting from usb3 -// devices actually works. -// -// Authors: -// Gerd Hoffmann -// -// based on usb-msc.c which is written by: -// Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "config.h" // CONFIG_USB_UAS -#include "usb.h" // struct usb_s -#include "biosvar.h" // GET_GLOBAL -#include "blockcmd.h" // cdb_read -#include "disk.h" // DTYPE_UAS -#include "boot.h" // bootprio_find_usb -#include "usb-uas.h" // usb_uas_init - -#define UAS_UI_COMMAND 0x01 -#define UAS_UI_SENSE 0x03 -#define UAS_UI_RESPONSE 0x04 -#define UAS_UI_TASK_MGMT 0x05 -#define UAS_UI_READ_READY 0x06 -#define UAS_UI_WRITE_READY 0x07 - -#define UAS_PIPE_ID_COMMAND 0x01 -#define UAS_PIPE_ID_STATUS 0x02 -#define UAS_PIPE_ID_DATA_IN 0x03 -#define UAS_PIPE_ID_DATA_OUT 0x04 - -typedef struct { - u8 id; - u8 reserved; - u16 tag; -} PACKED uas_ui_header; - -typedef struct { - u8 prio_taskattr; /* 6:3 priority, 2:0 task attribute */ - u8 reserved_1; - u8 add_cdb_length; /* 7:2 additional adb length (dwords) */ - u8 reserved_2; - u8 lun[8]; - u8 cdb[16]; - u8 add_cdb[]; -} PACKED uas_ui_command; - -typedef struct { - u16 status_qualifier; - u8 status; - u8 reserved[7]; - u16 sense_length; - u8 sense_data[18]; -} PACKED uas_ui_sense; - -typedef struct { - u16 add_response_info; - u8 response_code; -} PACKED uas_ui_response; - -typedef struct { - u8 function; - u8 reserved; - u16 task_tag; - u8 lun[8]; -} PACKED uas_ui_task_mgmt; - -typedef struct { - uas_ui_header hdr; - union { - uas_ui_command command; - uas_ui_sense sense; - uas_ui_task_mgmt task; - uas_ui_response response; - }; -} PACKED uas_ui; - -struct uasdrive_s { - struct drive_s drive; - struct usb_pipe *command, *status, *data_in, *data_out; - int lun; -}; - -int -uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - if (!CONFIG_USB_UAS) - return DISK_RET_EBADTRACK; - - struct uasdrive_s *drive = container_of( - op->drive_g, struct uasdrive_s, drive); - - uas_ui ui; - memset(&ui, 0, sizeof(ui)); - ui.hdr.id = UAS_UI_COMMAND; - ui.hdr.tag = 0xdead; - ui.command.lun[1] = drive->lun; - memcpy(ui.command.cdb, cdbcmd, sizeof(ui.command.cdb)); - int ret = usb_send_bulk(GET_GLOBAL(drive->command), - USB_DIR_OUT, MAKE_FLATPTR(GET_SEG(SS), &ui), - sizeof(ui.hdr) + sizeof(ui.command)); - if (ret) { - dprintf(1, "uas: command send fail"); - goto fail; - } - - memset(&ui, 0xff, sizeof(ui)); - ret = usb_send_bulk(GET_GLOBAL(drive->status), - USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui)); - if (ret) { - dprintf(1, "uas: status recv fail"); - goto fail; - } - - switch (ui.hdr.id) { - case UAS_UI_SENSE: - goto have_sense; - case UAS_UI_READ_READY: - ret = usb_send_bulk(GET_GLOBAL(drive->data_in), - USB_DIR_IN, op->buf_fl, op->count * blocksize); - if (ret) { - dprintf(1, "uas: data read fail"); - goto fail; - } - break; - case UAS_UI_WRITE_READY: - ret = usb_send_bulk(GET_GLOBAL(drive->data_out), - USB_DIR_OUT, op->buf_fl, op->count * blocksize); - if (ret) { - dprintf(1, "uas: data write fail"); - goto fail; - } - break; - default: - dprintf(1, "uas: unknown status ui id %d", ui.hdr.id); - goto fail; - } - - memset(&ui, 0xff, sizeof(ui)); - ret = usb_send_bulk(GET_GLOBAL(drive->status), - USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui)); - if (ret) { - dprintf(1, "uas: status recv fail"); - goto fail; - } - if (ui.hdr.id != UAS_UI_SENSE) { - dprintf(1, "uas: expected sense ui, got ui id %d", ui.hdr.id); - goto fail; - } - -have_sense: - if (ui.sense.status == 0) { - return DISK_RET_SUCCESS; - } - -fail: - return DISK_RET_EBADTRACK; -} - -static int -uas_init_lun(struct usbdevice_s *usbdev, - struct usb_pipe *command, struct usb_pipe *status, - struct usb_pipe *data_in, struct usb_pipe *data_out, - int lun) -{ - // Allocate drive structure. - struct uasdrive_s *drive = malloc_fseg(sizeof(*drive)); - if (!drive) { - warn_noalloc(); - return -1; - } - memset(drive, 0, sizeof(*drive)); - drive->drive.type = DTYPE_UAS; - drive->command = command; - drive->status = status; - drive->data_in = data_in; - drive->data_out = data_out; - drive->lun = lun; - - int prio = bootprio_find_usb(usbdev, lun); - int ret = scsi_init_drive(&drive->drive, "USB UAS", prio); - if (ret) { - free(drive); - return -1; - } - return 0; -} - -int -usb_uas_init(struct usbdevice_s *usbdev) -{ - if (!CONFIG_USB_UAS) - return -1; - - // Verify right kind of device - struct usb_interface_descriptor *iface = usbdev->iface; - if (iface->bInterfaceSubClass != US_SC_SCSI || - iface->bInterfaceProtocol != US_PR_UAS) { - dprintf(1, "Unsupported UAS device (subclass=%02x proto=%02x)\n" - , iface->bInterfaceSubClass, iface->bInterfaceProtocol); - return -1; - } - - /* find & allocate pipes */ - struct usb_endpoint_descriptor *ep = NULL; - struct usb_pipe *command = NULL; - struct usb_pipe *status = NULL; - struct usb_pipe *data_in = NULL; - struct usb_pipe *data_out = NULL; - u8 *desc = (u8*)iface; - while (desc) { - desc += desc[0]; - switch (desc[1]) { - case USB_DT_ENDPOINT: - ep = (void*)desc; - break; - case 0x24: - switch (desc[2]) { - case UAS_PIPE_ID_COMMAND: - command = usb_alloc_pipe(usbdev, ep); - break; - case UAS_PIPE_ID_STATUS: - status = usb_alloc_pipe(usbdev, ep); - break; - case UAS_PIPE_ID_DATA_IN: - data_in = usb_alloc_pipe(usbdev, ep); - break; - case UAS_PIPE_ID_DATA_OUT: - data_out = usb_alloc_pipe(usbdev, ep); - break; - default: - goto fail; - } - break; - default: - desc = NULL; - break; - } - } - if (!command || !status || !data_in || !data_out) - goto fail; - - /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ - int ret = uas_init_lun(usbdev, command, status, data_in, data_out, 0); - if (ret < 0) { - dprintf(1, "Unable to configure UAS drive.\n"); - goto fail; - } - - return 0; - -fail: - free_pipe(command); - free_pipe(status); - free_pipe(data_in); - free_pipe(data_out); - return -1; -} diff -Nru seabios-1.7.1/src/usb-uas.h seabios-1.7.4/src/usb-uas.h --- seabios-1.7.1/src/usb-uas.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-uas.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#ifndef __USB_UAS_H -#define __USB_UAS_H - -struct disk_op_s; -int uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); -struct usbdevice_s; -int usb_uas_init(struct usbdevice_s *usbdev); - -#endif /* __USB_UAS_H */ diff -Nru seabios-1.7.1/src/usb-uhci.c seabios-1.7.4/src/usb-uhci.c --- seabios-1.7.1/src/usb-uhci.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-uhci.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,578 +0,0 @@ -// Code for handling UHCI USB controllers. -// -// Copyright (C) 2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // pci_bdf_to_bus -#include "config.h" // CONFIG_* -#include "ioport.h" // outw -#include "usb-uhci.h" // USBLEGSUP -#include "pci_regs.h" // PCI_BASE_ADDRESS_4 -#include "usb.h" // struct usb_s -#include "biosvar.h" // GET_LOWFLAT - -struct usb_uhci_s { - struct usb_s usb; - u16 iobase; - struct uhci_qh *control_qh; - struct uhci_framelist *framelist; -}; - -struct uhci_pipe { - struct uhci_qh qh; - struct uhci_td *next_td; - struct usb_pipe pipe; - u16 iobase; - u8 toggle; -}; - - -/**************************************************************** - * Root hub - ****************************************************************/ - -// Check if device attached to a given port -static int -uhci_hub_detect(struct usbhub_s *hub, u32 port) -{ - struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); - u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; - - u16 status = inw(ioport); - if (!(status & USBPORTSC_CCS)) - // No device - return -1; - - // XXX - if just powered up, need to wait for USB_TIME_ATTDB? - - // Begin reset on port - outw(USBPORTSC_PR, ioport); - msleep(USB_TIME_DRSTR); - return 0; -} - -// Reset device on port -static int -uhci_hub_reset(struct usbhub_s *hub, u32 port) -{ - struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); - u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; - - // Finish reset on port - outw(0, ioport); - udelay(6); // 64 high-speed bit times - u16 status = inw(ioport); - if (!(status & USBPORTSC_CCS)) - // No longer connected - return -1; - outw(USBPORTSC_PE, ioport); - return !!(status & USBPORTSC_LSDA); -} - -// Disable port -static void -uhci_hub_disconnect(struct usbhub_s *hub, u32 port) -{ - struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); - u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; - outw(0, ioport); -} - -static struct usbhub_op_s uhci_HubOp = { - .detect = uhci_hub_detect, - .reset = uhci_hub_reset, - .disconnect = uhci_hub_disconnect, -}; - -// Find any devices connected to the root hub. -static int -check_uhci_ports(struct usb_uhci_s *cntl) -{ - ASSERT32FLAT(); - struct usbhub_s hub; - memset(&hub, 0, sizeof(hub)); - hub.cntl = &cntl->usb; - hub.portcount = 2; - hub.op = &uhci_HubOp; - usb_enumerate(&hub); - return hub.devcount; -} - - -/**************************************************************** - * Setup - ****************************************************************/ - -// Wait for next USB frame to start - for ensuring safe memory release. -static void -uhci_waittick(u16 iobase) -{ - barrier(); - u16 startframe = inw(iobase + USBFRNUM); - u64 end = calc_future_tsc(1000 * 5); - for (;;) { - if (inw(iobase + USBFRNUM) != startframe) - break; - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } -} - -static void -uhci_free_pipes(struct usb_uhci_s *cntl) -{ - dprintf(7, "uhci_free_pipes %p\n", cntl); - - struct uhci_qh *pos = (void*)(cntl->framelist->links[0] & ~UHCI_PTR_BITS); - for (;;) { - u32 link = pos->link; - if (link == UHCI_PTR_TERM) - break; - struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS); - struct uhci_pipe *pipe = container_of(next, struct uhci_pipe, qh); - if (pipe->pipe.cntl != &cntl->usb) - pos->link = next->link; - else - pos = next; - } - uhci_waittick(cntl->iobase); - for (;;) { - struct usb_pipe *usbpipe = cntl->usb.freelist; - if (!usbpipe) - break; - cntl->usb.freelist = usbpipe->freenext; - struct uhci_pipe *pipe = container_of(usbpipe, struct uhci_pipe, pipe); - free(pipe); - } -} - -static void -reset_uhci(struct usb_uhci_s *cntl, u16 bdf) -{ - // XXX - don't reset if not needed. - - // Reset PIRQ and SMI - pci_config_writew(bdf, USBLEGSUP, USBLEGSUP_RWC); - - // Reset the HC - outw(USBCMD_HCRESET, cntl->iobase + USBCMD); - udelay(5); - - // Disable interrupts and commands (just to be safe). - outw(0, cntl->iobase + USBINTR); - outw(0, cntl->iobase + USBCMD); -} - -static void -configure_uhci(void *data) -{ - struct usb_uhci_s *cntl = data; - - // Allocate ram for schedule storage - struct uhci_td *term_td = malloc_high(sizeof(*term_td)); - struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl)); - struct uhci_pipe *intr_pipe = malloc_high(sizeof(*intr_pipe)); - struct uhci_pipe *term_pipe = malloc_high(sizeof(*term_pipe)); - if (!term_td || !fl || !intr_pipe || !term_pipe) { - warn_noalloc(); - goto fail; - } - - // Work around for PIIX errata - memset(term_td, 0, sizeof(*term_td)); - term_td->link = UHCI_PTR_TERM; - term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT) - | USB_PID_IN); - memset(term_pipe, 0, sizeof(*term_pipe)); - term_pipe->qh.element = (u32)term_td; - term_pipe->qh.link = UHCI_PTR_TERM; - term_pipe->pipe.cntl = &cntl->usb; - - // Set schedule to point to primary intr queue head - memset(intr_pipe, 0, sizeof(*intr_pipe)); - intr_pipe->qh.element = UHCI_PTR_TERM; - intr_pipe->qh.link = (u32)&term_pipe->qh | UHCI_PTR_QH; - intr_pipe->pipe.cntl = &cntl->usb; - int i; - for (i=0; ilinks); i++) - fl->links[i] = (u32)&intr_pipe->qh | UHCI_PTR_QH; - cntl->framelist = fl; - cntl->control_qh = &intr_pipe->qh; - barrier(); - - // Set the frame length to the default: 1 ms exactly - outb(USBSOF_DEFAULT, cntl->iobase + USBSOF); - - // Store the frame list base address - outl((u32)fl->links, cntl->iobase + USBFLBASEADD); - - // Set the current frame number - outw(0, cntl->iobase + USBFRNUM); - - // Mark as configured and running with a 64-byte max packet. - outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->iobase + USBCMD); - - // Find devices - int count = check_uhci_ports(cntl); - uhci_free_pipes(cntl); - if (count) - // Success - return; - - // No devices found - shutdown and free controller. - outw(0, cntl->iobase + USBCMD); -fail: - free(term_td); - free(fl); - free(intr_pipe); - free(term_pipe); - free(cntl); -} - -void -uhci_init(struct pci_device *pci, int busid) -{ - if (! CONFIG_USB_UHCI) - return; - u16 bdf = pci->bdf; - struct usb_uhci_s *cntl = malloc_tmphigh(sizeof(*cntl)); - if (!cntl) { - warn_noalloc(); - return; - } - memset(cntl, 0, sizeof(*cntl)); - cntl->usb.busid = busid; - cntl->usb.pci = pci; - cntl->usb.type = USB_TYPE_UHCI; - cntl->iobase = (pci_config_readl(bdf, PCI_BASE_ADDRESS_4) - & PCI_BASE_ADDRESS_IO_MASK); - - dprintf(1, "UHCI init on dev %02x:%02x.%x (io=%x)\n" - , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) - , pci_bdf_to_fn(bdf), cntl->iobase); - - pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); - - reset_uhci(cntl, bdf); - - run_thread(configure_uhci, cntl); -} - - -/**************************************************************** - * End point communication - ****************************************************************/ - -static struct usb_pipe * -uhci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - struct usb_uhci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_uhci_s, usb); - int frameexp = usb_getFrameExp(usbdev, epdesc); - dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); - - if (frameexp > 10) - frameexp = 10; - int maxpacket = epdesc->wMaxPacketSize; - // Determine number of entries needed for 2 timer ticks. - int ms = 1<pipe, usbdev, epdesc); - int lowspeed = pipe->pipe.speed; - int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); - pipe->qh.element = (u32)tds; - pipe->next_td = &tds[0]; - pipe->iobase = cntl->iobase; - - int toggle = 0; - int i; - for (i=0; iframelist; - if (frameexp == 0) { - // Add to existing interrupt entry. - struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS); - pipe->qh.link = intr_qh->link; - barrier(); - intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; - if (cntl->control_qh == intr_qh) - cntl->control_qh = &pipe->qh; - } else { - int startpos = 1<<(frameexp-1); - pipe->qh.link = fl->links[startpos]; - barrier(); - for (i=startpos; ilinks); i+=ms) - fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH; - } - - return &pipe->pipe; -fail: - free(pipe); - free(tds); - free(data); - return NULL; -} - -struct usb_pipe * -uhci_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_UHCI) - return NULL; - u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (eptype == USB_ENDPOINT_XFER_INT) - return uhci_alloc_intr_pipe(usbdev, epdesc); - struct usb_uhci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_uhci_s, usb); - dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); - - struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); - if (usbpipe) { - // Use previously allocated pipe. - usb_desc2pipe(usbpipe, usbdev, epdesc); - return usbpipe; - } - - // Allocate a new queue head. - struct uhci_pipe *pipe; - if (eptype == USB_ENDPOINT_XFER_CONTROL) - pipe = malloc_tmphigh(sizeof(*pipe)); - else - pipe = malloc_low(sizeof(*pipe)); - if (!pipe) { - warn_noalloc(); - return NULL; - } - memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - pipe->qh.element = UHCI_PTR_TERM; - pipe->iobase = cntl->iobase; - - // Add queue head to controller list. - struct uhci_qh *control_qh = cntl->control_qh; - pipe->qh.link = control_qh->link; - barrier(); - control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; - if (eptype == USB_ENDPOINT_XFER_CONTROL) - cntl->control_qh = &pipe->qh; - return &pipe->pipe; -} - -static int -wait_pipe(struct uhci_pipe *pipe, int timeout) -{ - u64 end = calc_future_tsc(timeout); - for (;;) { - u32 el_link = GET_LOWFLAT(pipe->qh.element); - if (el_link & UHCI_PTR_TERM) - return 0; - if (check_tsc(end)) { - warn_timeout(); - u16 iobase = GET_LOWFLAT(pipe->iobase); - struct uhci_td *td = (void*)(el_link & ~UHCI_PTR_BITS); - dprintf(1, "Timeout on wait_pipe %p (td=%p s=%x c=%x/%x)\n" - , pipe, (void*)el_link, GET_LOWFLAT(td->status) - , inw(iobase + USBCMD) - , inw(iobase + USBSTS)); - SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM); - uhci_waittick(iobase); - return -1; - } - yield(); - } -} - -static int -wait_td(struct uhci_td *td) -{ - u64 end = calc_future_tsc(5000); // XXX - lookup real time. - u32 status; - for (;;) { - status = td->status; - if (!(status & TD_CTRL_ACTIVE)) - break; - if (check_tsc(end)) { - warn_timeout(); - return -1; - } - yield(); - } - if (status & TD_CTRL_ANY_ERROR) { - dprintf(1, "wait_td error - status=%x\n", status); - return -2; - } - return 0; -} - -int -uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize - , void *data, int datasize) -{ - ASSERT32FLAT(); - if (! CONFIG_USB_UHCI) - return -1; - dprintf(5, "uhci_control %p\n", p); - struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); - - int maxpacket = pipe->pipe.maxpacket; - int lowspeed = pipe->pipe.speed; - int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); - - // Setup transfer descriptors - int count = 2 + DIV_ROUND_UP(datasize, maxpacket); - struct uhci_td *tds = malloc_tmphigh(sizeof(*tds) * count); - if (!tds) { - warn_noalloc(); - return -1; - } - - tds[0].link = (u32)&tds[1] | UHCI_PTR_DEPTH; - tds[0].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) - | TD_CTRL_ACTIVE); - tds[0].token = (uhci_explen(cmdsize) | (devaddr << TD_TOKEN_DEVADDR_SHIFT) - | USB_PID_SETUP); - tds[0].buffer = (void*)cmd; - int toggle = TD_TOKEN_TOGGLE; - int i; - for (i=1; iqh.element = (u32)&tds[0]; - int ret = wait_pipe(pipe, 500); - free(tds); - return ret; -} - -#define STACKTDS 4 -#define TDALIGN 16 - -int -uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) -{ - if (! CONFIG_USB_UHCI) - return -1; - struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); - dprintf(7, "uhci_send_bulk qh=%p dir=%d data=%p size=%d\n" - , &pipe->qh, dir, data, datasize); - int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); - int lowspeed = GET_LOWFLAT(pipe->pipe.speed); - int devaddr = (GET_LOWFLAT(pipe->pipe.devaddr) - | (GET_LOWFLAT(pipe->pipe.ep) << 7)); - int toggle = GET_LOWFLAT(pipe->toggle) ? TD_TOKEN_TOGGLE : 0; - - // Allocate 4 tds on stack (16byte aligned) - u8 tdsbuf[sizeof(struct uhci_td) * STACKTDS + TDALIGN - 1]; - struct uhci_td *tds = (void*)ALIGN((u32)tdsbuf, TDALIGN); - memset(tds, 0, sizeof(*tds) * STACKTDS); - - // Enable tds - barrier(); - SET_LOWFLAT(pipe->qh.element, (u32)MAKE_FLATPTR(GET_SEG(SS), tds)); - - int tdpos = 0; - while (datasize) { - struct uhci_td *td = &tds[tdpos++ % STACKTDS]; - int ret = wait_td(td); - if (ret) - goto fail; - - int transfer = datasize; - if (transfer > maxpacket) - transfer = maxpacket; - struct uhci_td *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS) - , &tds[tdpos % STACKTDS]); - td->link = (transfer==datasize ? UHCI_PTR_TERM : (u32)nexttd_fl); - td->token = (uhci_explen(transfer) | toggle - | (devaddr << TD_TOKEN_DEVADDR_SHIFT) - | (dir ? USB_PID_IN : USB_PID_OUT)); - td->buffer = data; - barrier(); - td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) - | TD_CTRL_ACTIVE); - toggle ^= TD_TOKEN_TOGGLE; - - data += transfer; - datasize -= transfer; - } - SET_LOWFLAT(pipe->toggle, !!toggle); - return wait_pipe(pipe, 5000); -fail: - dprintf(1, "uhci_send_bulk failed\n"); - SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM); - uhci_waittick(GET_LOWFLAT(pipe->iobase)); - return -1; -} - -int -uhci_poll_intr(struct usb_pipe *p, void *data) -{ - ASSERT16(); - if (! CONFIG_USB_UHCI) - return -1; - - struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); - struct uhci_td *td = GET_LOWFLAT(pipe->next_td); - u32 status = GET_LOWFLAT(td->status); - u32 token = GET_LOWFLAT(td->token); - if (status & TD_CTRL_ACTIVE) - // No intrs found. - return -1; - // XXX - check for errors. - - // Copy data. - void *tddata = GET_LOWFLAT(td->buffer); - memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata) - , uhci_expected_length(token)); - - // Reenable this td. - struct uhci_td *next = (void*)(GET_LOWFLAT(td->link) & ~UHCI_PTR_BITS); - SET_LOWFLAT(pipe->next_td, next); - barrier(); - SET_LOWFLAT(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS) - | TD_CTRL_ACTIVE)); - - return 0; -} diff -Nru seabios-1.7.1/src/usb-uhci.h seabios-1.7.4/src/usb-uhci.h --- seabios-1.7.1/src/usb-uhci.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/usb-uhci.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -#ifndef __USB_UHCI_H -#define __USB_UHCI_H - -// usb-uhci.c -void uhci_init(struct pci_device *pci, int busid); -struct usbdevice_s; -struct usb_endpoint_descriptor; -struct usb_pipe *uhci_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); -struct usb_pipe; -int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize - , void *data, int datasize); -int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); -int uhci_poll_intr(struct usb_pipe *p, void *data); - - -/**************************************************************** - * uhci structs and flags - ****************************************************************/ - -/* USB port status and control registers */ -#define USBPORTSC1 16 -#define USBPORTSC2 18 -#define USBPORTSC_CCS 0x0001 /* Current Connect Status - * ("device present") */ -#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ -#define USBPORTSC_PE 0x0004 /* Port Enable */ -#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -#define USBPORTSC_DPLUS 0x0010 /* D+ high (line status) */ -#define USBPORTSC_DMINUS 0x0020 /* D- high (line status) */ -#define USBPORTSC_RD 0x0040 /* Resume Detect */ -#define USBPORTSC_RES1 0x0080 /* reserved, always 1 */ -#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ -#define USBPORTSC_PR 0x0200 /* Port Reset */ - -/* Legacy support register */ -#define USBLEGSUP 0xc0 -#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ - -/* Command register */ -#define USBCMD 0 -#define USBCMD_RS 0x0001 /* Run/Stop */ -#define USBCMD_HCRESET 0x0002 /* Host reset */ -#define USBCMD_GRESET 0x0004 /* Global reset */ -#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define USBCMD_FGR 0x0010 /* Force Global Resume */ -#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ -#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ -#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ - -/* Status register */ -#define USBSTS 2 -#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ -#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ -#define USBSTS_RD 0x0004 /* Resume Detect */ -#define USBSTS_HSE 0x0008 /* Host System Error: PCI problems */ -#define USBSTS_HCPE 0x0010 /* Host Controller Process Error: - * the schedule is buggy */ -#define USBSTS_HCH 0x0020 /* HC Halted */ - -/* Interrupt enable register */ -#define USBINTR 4 -#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ -#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ -#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ -#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ - -#define USBFRNUM 6 -#define USBFLBASEADD 8 -#define USBSOF 12 -#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */ - -struct uhci_framelist { - u32 links[1024]; -} PACKED; - -#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ -#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ -#define TD_CTRL_C_ERR_SHIFT 27 -#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ -#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ -#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ -#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ -#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ -#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ -#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ -#define TD_CTRL_NAK (1 << 19) /* NAK Received */ -#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ -#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ -#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ - -#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIMEO | \ - TD_CTRL_BITSTUFF) -#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) - -#define TD_TOKEN_DEVADDR_SHIFT 8 -#define TD_TOKEN_TOGGLE_SHIFT 19 -#define TD_TOKEN_TOGGLE (1 << 19) -#define TD_TOKEN_EXPLEN_SHIFT 21 -#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n-1 */ -#define TD_TOKEN_PID_MASK 0xFF - -#define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \ - TD_TOKEN_EXPLEN_SHIFT) - -#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \ - 1) & TD_TOKEN_EXPLEN_MASK) - -struct uhci_td { - u32 link; - u32 status; - u32 token; - void *buffer; -} PACKED; - -struct uhci_qh { - u32 link; - u32 element; -} PACKED; - -#define UHCI_PTR_BITS 0x000F -#define UHCI_PTR_TERM 0x0001 -#define UHCI_PTR_QH 0x0002 -#define UHCI_PTR_DEPTH 0x0004 -#define UHCI_PTR_BREADTH 0x0000 - -#endif // usb-uhci.h diff -Nru seabios-1.7.1/src/util.c seabios-1.7.4/src/util.c --- seabios-1.7.1/src/util.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/util.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,292 +0,0 @@ -// Misc utility functions. -// -// Copyright (C) 2008,2009 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // call16 -#include "bregs.h" // struct bregs -#include "config.h" // BUILD_STACK_ADDR - -void -cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) -{ - // Check for cpu id - u32 origflags = save_flags(); - restore_flags(origflags ^ F_ID); - u32 newflags = save_flags(); - restore_flags(origflags); - - if (((origflags ^ newflags) & F_ID) != F_ID) - // no cpuid - *eax = *ebx = *ecx = *edx = 0; - else - __cpuid(index, eax, ebx, ecx, edx); -} - - -/**************************************************************** - * String ops - ****************************************************************/ - -// Sum the bytes in the specified area. -u8 -checksum_far(u16 buf_seg, void *buf_far, u32 len) -{ - SET_SEG(ES, buf_seg); - u32 i; - u8 sum = 0; - for (i=0; i 3) { - u32 copylen = len; - if (copylen > 2048) - copylen = 2048; - copylen /= 4; - len -= copylen * 4; - asm volatile( - "rep movsl (%%esi),%%es:(%%edi)" - : "+c"(copylen), "+S"(s), "+D"(d) - : : "cc", "memory"); - yield(); - } - if (len) - // Copy any remaining bytes. - memcpy(d, s, len); -} - -void * -memmove(void *d, const void *s, size_t len) -{ - if (s >= d) - return memcpy(d, s, len); - - d += len-1; - s += len-1; - while (len--) { - *(char*)d = *(char*)s; - d--; - s--; - } - - return d; -} - -// Copy a string - truncating it if necessary. -char * -strtcpy(char *dest, const char *src, size_t len) -{ - char *d = dest; - while (--len && *src != '\0') - *d++ = *src++; - *d = '\0'; - return dest; -} - -// locate first occurance of character c in the string s -char * -strchr(const char *s, int c) -{ - for (; *s; s++) - if (*s == c) - return (char*)s; - return NULL; -} - -// Remove any trailing blank characters (spaces, new lines, carriage returns) -void -nullTrailingSpace(char *buf) -{ - int len = strlen(buf); - char *end = &buf[len-1]; - while (end >= buf && *end <= ' ') - *(end--) = '\0'; -} - -/**************************************************************** - * Keyboard calls - ****************************************************************/ - -// See if a keystroke is pending in the keyboard buffer. -static int -check_for_keystroke(void) -{ - struct bregs br; - memset(&br, 0, sizeof(br)); - br.flags = F_IF; - br.ah = 1; - call16_int(0x16, &br); - return !(br.flags & F_ZF); -} - -// Return a keystroke - waiting forever if necessary. -static int -get_raw_keystroke(void) -{ - struct bregs br; - memset(&br, 0, sizeof(br)); - br.flags = F_IF; - call16_int(0x16, &br); - return br.ah; -} - -// Read a keystroke - waiting up to 'msec' milliseconds. -int -get_keystroke(int msec) -{ - u32 end = calc_future_timer(msec); - for (;;) { - if (check_for_keystroke()) - return get_raw_keystroke(); - if (check_timer(end)) - return -1; - yield_toirq(); - } -} diff -Nru seabios-1.7.1/src/util.h seabios-1.7.4/src/util.h --- seabios-1.7.1/src/util.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/util.h 2013-12-23 15:40:06.000000000 +0000 @@ -1,486 +1,227 @@ -// Basic x86 asm functions and function defs. -// -// Copyright (C) 2008-2010 Kevin O'Connor -// -// This file may be distributed under the terms of the GNU LGPLv3 license. +// Misc function and variable declarations. #ifndef __UTIL_H #define __UTIL_H #include "types.h" // u32 -static inline void irq_disable(void) -{ - asm volatile("cli": : :"memory"); -} - -static inline void irq_enable(void) -{ - asm volatile("sti": : :"memory"); -} - -static inline u32 save_flags(void) -{ - u32 flags; - asm volatile("pushfl ; popl %0" : "=rm" (flags)); - return flags; -} - -static inline void restore_flags(u32 flags) -{ - asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc"); -} - -static inline void cpu_relax(void) -{ - asm volatile("rep ; nop": : :"memory"); -} - -static inline void nop(void) -{ - asm volatile("nop"); -} - -static inline void hlt(void) -{ - asm volatile("hlt": : :"memory"); -} - -static inline void wbinvd(void) -{ - asm volatile("wbinvd": : :"memory"); -} - -#define CPUID_TSC (1 << 4) -#define CPUID_MSR (1 << 5) -#define CPUID_APIC (1 << 9) -#define CPUID_MTRR (1 << 12) -static inline void __cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) -{ - asm("cpuid" - : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) - : "0" (index)); -} - -static inline u32 getcr0(void) { - u32 cr0; - asm("movl %%cr0, %0" : "=r"(cr0)); - return cr0; -} -static inline void setcr0(u32 cr0) { - asm("movl %0, %%cr0" : : "r"(cr0)); -} - -static inline u64 rdmsr(u32 index) -{ - u64 ret; - asm ("rdmsr" : "=A"(ret) : "c"(index)); - return ret; -} - -static inline void wrmsr(u32 index, u64 val) -{ - asm volatile ("wrmsr" : : "c"(index), "A"(val)); -} - -static inline u64 rdtscll(void) -{ - u64 val; - asm volatile("rdtsc" : "=A" (val)); - return val; -} - -static inline u32 __ffs(u32 word) -{ - asm("bsf %1,%0" - : "=r" (word) - : "rm" (word)); - return word; -} -static inline u32 __fls(u32 word) -{ - asm("bsr %1,%0" - : "=r" (word) - : "rm" (word)); - return word; -} - -static inline u16 __htons_constant(u16 val) { - return (val<<8) | (val>>8); -} -static inline u32 __htonl_constant(u32 val) { - return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24); -} -static inline u32 __htonl(u32 val) { - asm("bswapl %0" : "+r"(val)); - return val; -} -#define htonl(x) (__builtin_constant_p((u32)(x)) ? __htonl_constant(x) : __htonl(x)) -#define ntohl(x) htonl(x) -#define htons(x) __htons_constant(x) -#define ntohs(x) htons(x) - -static inline u16 cpu_to_le16(u16 x) -{ - return x; -} - -static inline u32 cpu_to_le32(u32 x) -{ - return x; -} - -static inline u32 le32_to_cpu(u32 x) -{ - return x; -} - -static inline u32 getesp(void) { - u32 esp; - asm("movl %%esp, %0" : "=rm"(esp)); - return esp; -} - -static inline void writel(void *addr, u32 val) { - *(volatile u32 *)addr = val; -} -static inline void writew(void *addr, u16 val) { - *(volatile u16 *)addr = val; -} -static inline void writeb(void *addr, u8 val) { - *(volatile u8 *)addr = val; -} -static inline u32 readl(const void *addr) { - return *(volatile const u32 *)addr; -} -static inline u16 readw(const void *addr) { - return *(volatile const u16 *)addr; -} -static inline u8 readb(const void *addr) { - return *(volatile const u8 *)addr; -} - -// GDT bits -#define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set -#define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set -#define GDT_B (0x1ULL << 54) // Big flag -#define GDT_G (0x1ULL << 55) // Granularity flag -// GDT bits for segment base -#define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \ - | (((u64)(v) & 0x00ffffff) << 16)) -// GDT bits for segment limit (0-1Meg) -#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \ - | (((u64)(v) & 0x0000ffff) << 0)) -// GDT bits for segment limit (0-4Gig in 4K chunks) -#define GDT_GRANLIMIT(v) (GDT_G | GDT_LIMIT((v) >> 12)) - -struct descloc_s { - u16 length; - u32 addr; -} PACKED; - -// util.c -void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); -u8 checksum_far(u16 buf_seg, void *buf_far, u32 len); -u8 checksum(void *buf, u32 len); -size_t strlen(const char *s); -int memcmp(const void *s1, const void *s2, size_t n); -int strcmp(const char *s1, const char *s2); -inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len); -inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len); -void *memset(void *s, int c, size_t n); -void memset_fl(void *ptr, u8 val, size_t size); -inline void memcpy_far(u16 d_seg, void *d_far - , u16 s_seg, const void *s_far, size_t len); -void memcpy_fl(void *d_fl, const void *s_fl, size_t len); -void *memcpy(void *d1, const void *s1, size_t len); -#if MODESEGMENT == 0 -#define memcpy __builtin_memcpy -#endif -void iomemcpy(void *d, const void *s, u32 len); -void *memmove(void *d, const void *s, size_t len); -char *strtcpy(char *dest, const char *src, size_t len); -char *strchr(const char *s, int c); -void nullTrailingSpace(char *buf); -int get_keystroke(int msec); - -// stacks.c -extern u8 ExtraStack[], *StackPos; -u32 stack_hop(u32 eax, u32 edx, void *func); -u32 stack_hop_back(u32 eax, u32 edx, void *func); -u32 call32(void *func, u32 eax, u32 errret); +// apm.c +void apm_shutdown(void); struct bregs; -inline void farcall16(struct bregs *callregs); -inline void farcall16big(struct bregs *callregs); -inline void __call16_int(struct bregs *callregs, u16 offset); -#define call16_int(nr, callregs) do { \ - extern void irq_trampoline_ ##nr (); \ - __call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \ - } while (0) -extern struct thread_info MainThread; -struct thread_info *getCurThread(void); -void yield(void); -void yield_toirq(void); -void run_thread(void (*func)(void*), void *data); -void wait_threads(void); -struct mutex_s { u32 isLocked; }; -void mutex_lock(struct mutex_s *mutex); -void mutex_unlock(struct mutex_s *mutex); -void start_preempt(void); -void finish_preempt(void); -int wait_preempt(void); -void check_preempt(void); - -// output.c -extern u16 DebugOutputPort; -void debug_serial_setup(void); -void panic(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))) __noreturn; -void printf(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); -int snprintf(char *str, size_t size, const char *fmt, ...) - __attribute__ ((format (printf, 3, 4))); -char * znprintf(size_t size, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); -void __dprintf(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); -void __debug_enter(struct bregs *regs, const char *fname); -void __debug_isr(const char *fname); -void __debug_stub(struct bregs *regs, int lineno, const char *fname); -void __warn_invalid(struct bregs *regs, int lineno, const char *fname); -void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname); -void __warn_internalerror(int lineno, const char *fname); -void __warn_noalloc(int lineno, const char *fname); -void __warn_timeout(int lineno, const char *fname); -void __set_invalid(struct bregs *regs, int lineno, const char *fname); -void __set_unimplemented(struct bregs *regs, int lineno, const char *fname); -void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname); -void __set_code_unimplemented(struct bregs *regs, u32 linecode - , const char *fname); -void hexdump(const void *d, int len); - -#define dprintf(lvl, fmt, args...) do { \ - if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL) \ - __dprintf((fmt) , ##args ); \ - } while (0) -#define debug_enter(regs, lvl) do { \ - if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ - __debug_enter((regs), __func__); \ - } while (0) -#define debug_isr(lvl) do { \ - if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ - __debug_isr(__func__); \ - } while (0) -#define debug_stub(regs) \ - __debug_stub((regs), __LINE__, __func__) -#define warn_invalid(regs) \ - __warn_invalid((regs), __LINE__, __func__) -#define warn_unimplemented(regs) \ - __warn_unimplemented((regs), __LINE__, __func__) -#define warn_internalerror() \ - __warn_internalerror(__LINE__, __func__) -#define warn_noalloc() \ - __warn_noalloc(__LINE__, __func__) -#define warn_timeout() \ - __warn_timeout(__LINE__, __func__) -#define set_invalid(regs) \ - __set_invalid((regs), __LINE__, __func__) -#define set_code_invalid(regs, code) \ - __set_code_invalid((regs), (code) | (__LINE__ << 8), __func__) -#define set_unimplemented(regs) \ - __set_unimplemented((regs), __LINE__, __func__) -#define set_code_unimplemented(regs, code) \ - __set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__) - -// kbd.c -void kbd_setup(void); -void handle_15c2(struct bregs *regs); -void process_key(u8 key); +void handle_1553(struct bregs *regs); -// mouse.c -void mouse_setup(void); -void process_mouse(u8 data); +// bmp.c +struct bmp_decdata *bmp_alloc(void); +int bmp_decode(struct bmp_decdata *bmp, unsigned char *data, int data_size); +void bmp_get_size(struct bmp_decdata *bmp, int *width, int *height); +int bmp_show(struct bmp_decdata *bmp, unsigned char *pic, int width + , int height, int depth, int bytes_per_line_dest); + +// boot.c +void boot_init(void); +void boot_add_bev(u16 seg, u16 bev, u16 desc, int prio); +void boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio); +struct drive_s; +void boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio); +void boot_add_hd(struct drive_s *drive_g, const char *desc, int prio); +void boot_add_cd(struct drive_s *drive_g, const char *desc, int prio); +void boot_add_cbfs(void *data, const char *desc, int prio); +void interactive_bootmenu(void); +void bcv_prepboot(void); +struct pci_device; +int bootprio_find_pci_device(struct pci_device *pci); +int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun); +int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave); +int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid); +int bootprio_find_pci_rom(struct pci_device *pci, int instance); +int bootprio_find_named_rom(const char *name, int instance); +struct usbdevice_s; +int bootprio_find_usb(struct usbdevice_s *usbdev, int lun); -// system.c -extern u32 RamSize; -extern u64 RamSizeOver4G; -void mathcp_setup(void); +// bootsplash.c +void enable_vga_console(void); +void enable_bootsplash(void); +void disable_bootsplash(void); -// serial.c -void serial_setup(void); -void lpt_setup(void); +// cdrom.c +extern u8 CDRom_locks[]; +extern struct cdemu_s CDEmu; +extern struct drive_s *cdemu_drive_gf; +struct disk_op_s; +int process_cdemu_op(struct disk_op_s *op); +void cdrom_prepboot(void); +void cdemu_134b(struct bregs *regs); +int cdrom_boot(struct drive_s *drive_g); // clock.c -#define PIT_TICK_RATE 1193180 // Underlying HZ of PIT -#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer -int check_tsc(u64 end); -void timer_setup(void); -void ndelay(u32 count); -void udelay(u32 count); -void mdelay(u32 count); -void nsleep(u32 count); -void usleep(u32 count); -void msleep(u32 count); -u64 calc_future_tsc(u32 msecs); -u64 calc_future_tsc_usec(u32 usecs); -u32 calc_future_timer_ticks(u32 count); -u32 calc_future_timer(u32 msecs); -int check_timer(u32 end); +void clock_setup(void); void handle_1583(struct bregs *regs); +u32 irqtimer_calc_ticks(u32 count); +u32 irqtimer_calc(u32 msecs); +int irqtimer_check(u32 end); void handle_1586(struct bregs *regs); -void useRTC(void); -void releaseRTC(void); -// apm.c -void apm_shutdown(void); -void handle_1553(struct bregs *regs); +// fw/acpi.c +extern struct rsdp_descriptor *RsdpAddr; +extern u32 acpi_pm1a_cnt; +void acpi_setup(void); +u32 find_resume_vector(void); +void find_acpi_features(void); +struct acpi_20_generic_address; +void acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val); +void acpi_reboot(void); -// pcibios.c -void handle_1ab1(struct bregs *regs); -void bios32_setup(void); +// fw/biostable.c +void copy_smbios(void *pos); +void copy_table(void *pos); +void *find_acpi_rsdp(void); -// shadow.c -void make_bios_writable(void); -void make_bios_readonly(void); -void qemu_prep_reset(void); +// fw/coreboot.c +extern const char *CBvendor, *CBpart; +struct cbfs_file; +void coreboot_debug_putc(char c); +void cbfs_run_payload(struct cbfs_file *file); +void coreboot_platform_setup(void); +void cbfs_payload_setup(void); +void coreboot_preinit(void); +void coreboot_cbfs_init(void); + +// fw/csm.c +int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid); +int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave); +int csm_bootprio_pci(struct pci_device *pci); + +// fw/mptable.c +void mptable_setup(void); -// pciinit.c +// fw/mtrr.c +void mtrr_setup(void); + +// fw/pciinit.c extern const u8 pci_irqs[4]; void pci_setup(void); -// smm.c -void smm_init(void); +// fw/pirtable.c +extern struct pir_header *PirAddr; +void pirtable_setup(void); + +// fw/shadow.c +void make_bios_writable(void); +void make_bios_readonly(void); +void qemu_prep_reset(void); -// smp.c +// fw/smbios.c +extern struct smbios_entry_point *SMBiosAddr; +void smbios_setup(void); +void display_uuid(void); + +// fw/smm.c +void smm_device_setup(void); +void smm_setup(void); + +// fw/smp.c extern u32 CountCPUs; extern u32 MaxCountCPUs; void wrmsr_smp(u32 index, u64 val); -void smp_probe(void); +void smp_setup(void); int apic_id_is_present(u8 apic_id); -// coreboot.c -extern const char *CBvendor, *CBpart; -struct cbfs_file; -void cbfs_run_payload(struct cbfs_file *file); -void coreboot_copy_biostable(void); -void cbfs_payload_setup(void); -void coreboot_setup(void); -void coreboot_cbfs_setup(void); +// hw/dma.c +int dma_floppy(u32 addr, int count, int isWrite); +void dma_setup(void); + +// hw/floppy.c +extern struct floppy_ext_dbt_s diskette_param_table2; +void floppy_setup(void); +struct drive_s *init_floppy(int floppyid, int ftype); +int find_floppy_type(u32 size); +int process_floppy_op(struct disk_op_s *op); +void floppy_tick(void); + +// hw/ramdisk.c +void ramdisk_setup(void); +int process_ramdisk_op(struct disk_op_s *op); -// biostable.c -void copy_table(void *pos); +// hw/timer.c +void timer_setup(void); +void pmtimer_setup(u16 ioport); +u32 timer_calc(u32 msecs); +u32 timer_calc_usec(u32 usecs); +int timer_check(u32 end); +void ndelay(u32 count); +void udelay(u32 count); +void mdelay(u32 count); +void nsleep(u32 count); +void usleep(u32 count); +void msleep(u32 count); +u32 ticks_to_ms(u32 ticks); +u32 ticks_from_ms(u32 ms); +void pit_setup(void); + +// jpeg.c +struct jpeg_decdata *jpeg_alloc(void); +int jpeg_decode(struct jpeg_decdata *jpeg, unsigned char *buf); +void jpeg_get_size(struct jpeg_decdata *jpeg, int *width, int *height); +int jpeg_show(struct jpeg_decdata *jpeg, unsigned char *pic, int width + , int height, int depth, int bytes_per_line_dest); -// vgahooks.c -void handle_155f(struct bregs *regs); -struct pci_device; -void vgahook_setup(struct pci_device *pci); +// kbd.c +void kbd_init(void); +void handle_15c2(struct bregs *regs); +void process_key(u8 key); + +// misc.c +extern struct bios_config_table_s BIOS_CONFIG_TABLE __aligned(1); +extern u8 BiosChecksum; +void mathcp_setup(void); + +// mouse.c +void mouse_init(void); +void process_mouse(u8 data); // optionroms.c +struct rom_header; +void callrom(struct rom_header *rom, u16 bdf); void call_bcv(u16 seg, u16 ip); +int is_pci_vga(struct pci_device *pci); void optionrom_setup(void); -void vga_setup(void); -void s3_resume_vga_init(void); +void vgarom_setup(void); +void s3_resume_vga(void); extern int ScreenAndDebug; -// bootsplash.c -void enable_vga_console(void); -void enable_bootsplash(void); -void disable_bootsplash(void); +// pcibios.c +void handle_1ab1(struct bregs *regs); +void bios32_init(void); -// resume.c -extern int HaveRunPost; -void init_dma(void); +// pmm.c +void pmm_init(void); +void pmm_prepboot(void); // pnpbios.c -#define PNP_SIGNATURE 0x506e5024 // $PnP u16 get_pnp_offset(void); -void pnp_setup(void); +void pnp_init(void); -// pmm.c -extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh; -u32 rom_get_top(void); -u32 rom_get_last(void); -struct rom_header *rom_reserve(u32 size); -int rom_confirm(u32 size); -void malloc_setup(void); -void malloc_fixupreloc(void); -void malloc_finalize(void); -void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align); -int pmm_free(void *data); -void pmm_setup(void); -void pmm_finalize(void); -#define PMM_DEFAULT_HANDLE 0xFFFFFFFF -// Minimum alignment of malloc'd memory -#define MALLOC_MIN_ALIGN 16 -// Helper functions for memory allocation. -static inline void *malloc_low(u32 size) { - return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); -} -static inline void *malloc_high(u32 size) { - return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); -} -static inline void *malloc_fseg(u32 size) { - return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); -} -static inline void *malloc_tmplow(u32 size) { - return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); -} -static inline void *malloc_tmphigh(u32 size) { - return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); -} -static inline void *malloc_tmp(u32 size) { - void *ret = malloc_tmphigh(size); - if (ret) - return ret; - return malloc_tmplow(size); -} -static inline void *memalign_low(u32 align, u32 size) { - return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align); -} -static inline void *memalign_high(u32 align, u32 size) { - return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align); -} -static inline void *memalign_tmplow(u32 align, u32 size) { - return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, align); -} -static inline void *memalign_tmphigh(u32 align, u32 size) { - return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align); -} -static inline void *memalign_tmp(u32 align, u32 size) { - void *ret = memalign_tmphigh(align, size); - if (ret) - return ret; - return memalign_tmplow(align, size); -} -static inline void free(void *data) { - pmm_free(data); -} - -// mtrr.c -void mtrr_setup(void); +// post.c +void interface_init(void); +void device_hardware_setup(void); +void prepareboot(void); +void startBoot(void); +void reloc_preinit(void *f, void *arg); -// romfile.c -struct romfile_s { - struct romfile_s *next; - char name[128]; - u32 size; - int (*copy)(struct romfile_s *file, void *dest, u32 maxlen); - - u32 id; - u32 rawsize; - u32 flags; - void *data; -}; -void romfile_add(struct romfile_s *file); -struct romfile_s *romfile_findprefix(const char *prefix, struct romfile_s *prev); -struct romfile_s *romfile_find(const char *name); -void *romfile_loadfile(const char *name, int *psize); -u64 romfile_loadint(const char *name, u64 defval); +// resume.c +extern int HaveRunPost; // romlayout.S void reset_vector(void) __noreturn; -// misc.c -extern u8 BiosChecksum; +// serial.c +void serial_setup(void); +void lpt_setup(void); + +// vgahooks.c +void handle_155f(struct bregs *regs); +void handle_157f(struct bregs *regs); +void vgahook_setup(struct pci_device *pci); + // version (auto generated file out/version.c) extern const char VERSION[]; diff -Nru seabios-1.7.1/src/vbe.h seabios-1.7.4/src/vbe.h --- seabios-1.7.1/src/vbe.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/vbe.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,157 +0,0 @@ -#ifndef __VBE_H -#define __VBE_H - -#include "types.h" // u8 -#include "farptr.h" // struct segoff_s - -#define VESA_SIGNATURE 0x41534556 // VESA -#define VBE2_SIGNATURE 0x32454256 // VBE2 - -struct vbe_info { - u32 signature; - u16 version; - struct segoff_s oem_string; - u32 capabilities; - struct segoff_s video_mode; - u16 total_memory; - u16 oem_revision; - struct segoff_s oem_vendor_string; - struct segoff_s oem_product_string; - struct segoff_s oem_revision_string; - u8 reserved[222]; -} PACKED; - -struct vbe_mode_info { - /* VBE */ - u16 mode_attributes; - u8 winA_attributes; - u8 winB_attributes; - u16 win_granularity; - u16 win_size; - u16 winA_seg; - u16 winB_seg; - struct segoff_s win_func_ptr; - u16 bytes_per_scanline; - /* VBE 1.2 */ - u16 xres; - u16 yres; - u8 xcharsize; - u8 ycharsize; - u8 planes; - u8 bits_per_pixel; - u8 banks; - u8 mem_model; - u8 bank_size; - u8 pages; - u8 reserved0; - /* Direct Color */ - u8 red_size; - u8 red_pos; - u8 green_size; - u8 green_pos; - u8 blue_size; - u8 blue_pos; - u8 alpha_size; - u8 alpha_pos; - u8 directcolor_info; - /* VBE 2.0 */ - u32 phys_base; - u32 reserved1; - u16 reserved2; - /* VBE 3.0 */ - u16 linear_bytes_per_scanline; - u8 bank_pages; - u8 linear_pages; - u8 linear_red_size; - u8 linear_red_pos; - u8 linear_green_size; - u8 linear_green_pos; - u8 linear_blue_size; - u8 linear_blue_pos; - u8 linear_alpha_size; - u8 linear_alpha_pos; - u32 pixclock_max; - u8 reserved[190]; -} PACKED; - -struct vbe_crtc_info { - u16 horiz_total; - u16 horiz_sync_start; - u16 horiz_sync_end; - u16 vert_total; - u16 vert_sync_start; - u16 vert_sync_end; - u8 flags; - u32 pixclock; - u16 refresh_rate; - u8 reserved[40]; -} PACKED; - -/* VBE Return Status Info */ -/* AL */ -#define VBE_RETURN_STATUS_SUPPORTED 0x4F -#define VBE_RETURN_STATUS_UNSUPPORTED 0x00 -/* AH */ -#define VBE_RETURN_STATUS_SUCCESSFULL 0x00 -#define VBE_RETURN_STATUS_FAILED 0x01 -#define VBE_RETURN_STATUS_NOT_SUPPORTED 0x02 -#define VBE_RETURN_STATUS_INVALID 0x03 - -/* VBE Mode Numbers */ - -#define VBE_MODE_VESA_DEFINED 0x0100 -#define VBE_MODE_REFRESH_RATE_USE_CRTC 0x0800 -#define VBE_MODE_LINEAR_FRAME_BUFFER 0x4000 -#define VBE_MODE_PRESERVE_DISPLAY_MEMORY 0x8000 - -#define VBE_VESA_MODE_END_OF_LIST 0xFFFF - -/* Capabilities */ - -#define VBE_CAPABILITY_8BIT_DAC 0x0001 -#define VBE_CAPABILITY_NOT_VGA_COMPATIBLE 0x0002 -#define VBE_CAPABILITY_RAMDAC_USE_BLANK_BIT 0x0004 -#define VBE_CAPABILITY_STEREOSCOPIC_SUPPORT 0x0008 -#define VBE_CAPABILITY_STEREO_VIA_VESA_EVC 0x0010 - -/* Mode Attributes */ - -#define VBE_MODE_ATTRIBUTE_SUPPORTED 0x0001 -#define VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE 0x0002 -#define VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT 0x0004 -#define VBE_MODE_ATTRIBUTE_COLOR_MODE 0x0008 -#define VBE_MODE_ATTRIBUTE_GRAPHICS_MODE 0x0010 -#define VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE 0x0020 -#define VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW 0x0040 -#define VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE 0x0080 -#define VBE_MODE_ATTRIBUTE_DOUBLE_SCAN_MODE 0x0100 -#define VBE_MODE_ATTRIBUTE_INTERLACE_MODE 0x0200 -#define VBE_MODE_ATTRIBUTE_HARDWARE_TRIPLE_BUFFER 0x0400 -#define VBE_MODE_ATTRIBUTE_HARDWARE_STEREOSCOPIC_DISPLAY 0x0800 -#define VBE_MODE_ATTRIBUTE_DUAL_DISPLAY_START_ADDRESS 0x1000 - -#define VBE_MODE_ATTTRIBUTE_LFB_ONLY ( VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW | VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE ) - -/* Window attributes */ - -#define VBE_WINDOW_ATTRIBUTE_RELOCATABLE 0x01 -#define VBE_WINDOW_ATTRIBUTE_READABLE 0x02 -#define VBE_WINDOW_ATTRIBUTE_WRITEABLE 0x04 - -/* Memory model */ - -#define VBE_MEMORYMODEL_TEXT_MODE 0x00 -#define VBE_MEMORYMODEL_CGA_GRAPHICS 0x01 -#define VBE_MEMORYMODEL_HERCULES_GRAPHICS 0x02 -#define VBE_MEMORYMODEL_PLANAR 0x03 -#define VBE_MEMORYMODEL_PACKED_PIXEL 0x04 -#define VBE_MEMORYMODEL_NON_CHAIN_4_256 0x05 -#define VBE_MEMORYMODEL_DIRECT_COLOR 0x06 -#define VBE_MEMORYMODEL_YUV 0x07 - -/* DirectColorModeInfo */ - -#define VBE_DIRECTCOLOR_COLOR_RAMP_PROGRAMMABLE 0x01 -#define VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE 0x02 - -#endif diff -Nru seabios-1.7.1/src/vgahooks.c seabios-1.7.4/src/vgahooks.c --- seabios-1.7.1/src/vgahooks.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/vgahooks.c 2013-12-23 15:40:06.000000000 +0000 @@ -4,18 +4,21 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "bregs.h" // set_code_invalid #include "biosvar.h" // GET_GLOBAL -#include "pci.h" // pci_find_device -#include "pci_regs.h" // PCI_VENDOR_ID -#include "pci_ids.h" // PCI_VENDOR_ID_VIA -#include "util.h" // handle_155f +#include "bregs.h" // set_code_invalid #include "config.h" // CONFIG_* +#include "hw/pci.h" // pci_find_device +#include "hw/pci_ids.h" // PCI_VENDOR_ID_VIA +#include "hw/pci_regs.h" // PCI_VENDOR_ID +#include "output.h" // dprintf +#include "string.h" // strcmp +#include "util.h" // handle_155f, handle_157f #define VH_VIA 1 #define VH_INTEL 2 +#define VH_SMI 3 -int VGAHookHandlerType VAR16VISIBLE; +int VGAHookHandlerType VARFSEG; static void handle_155fXX(struct bregs *regs) @@ -23,12 +26,17 @@ set_code_unimplemented(regs, RET_EUNSUPPORTED); } +static void +handle_157fXX(struct bregs *regs) +{ + set_code_unimplemented(regs, RET_EUNSUPPORTED); +} /**************************************************************** * Via hooks ****************************************************************/ -int ViaFBsize VAR16VISIBLE, ViaRamSpeed VAR16VISIBLE; +int ViaFBsize VARFSEG, ViaRamSpeed VARFSEG; static void via_155f01(struct bregs *regs) @@ -167,7 +175,7 @@ * Intel VGA hooks ****************************************************************/ -u8 IntelDisplayType VAR16VISIBLE, IntelDisplayId VAR16VISIBLE; +u8 IntelDisplayType VARFSEG, IntelDisplayId VARFSEG; static void intel_155f35(struct bregs *regs) @@ -246,6 +254,46 @@ { } +/**************************************************************** + * Silicon Motion hooks + ****************************************************************/ + +u8 SmiBootDisplay VARFSEG; // 1: LCD, 2: CRT, 3: Both */ + +static void +smi_157f02(struct bregs *regs) +{ + /* Boot Display Device Override */ + regs->ax = 0x007f; + regs->bl = GET_GLOBAL(SmiBootDisplay); + set_success(regs); +} + +static void +smi_157f14(struct bregs *regs) +{ + /* ReduceOn support default status */ + regs->ax = 0x007f; + regs->bl = 0x00; + set_success(regs); +} + +static void +smi_157f(struct bregs *regs) +{ + switch (regs->al) { + case 0x02: smi_157f02(regs); break; + case 0x14: smi_157f14(regs); break; + default: handle_157fXX(regs); break; + } +} + +static void +winent_mb6047_setup(struct pci_device *pci) +{ + VGAHookHandlerType = VH_SMI; + SmiBootDisplay = 0x02; +} /**************************************************************** * Entry and setup @@ -268,6 +316,22 @@ } } +// Main 16bit entry point +void +handle_157f(struct bregs *regs) +{ + if (!CONFIG_VGAHOOKS) { + handle_157fXX(regs); + return; + } + + int htype = GET_GLOBAL(VGAHookHandlerType); + switch (htype) { + case VH_SMI: smi_157f(regs); break; + default: handle_157fXX(regs); break; + } +} + // Setup void vgahook_setup(struct pci_device *pci) @@ -281,6 +345,8 @@ getac_setup(pci); else if (strcmp(CBvendor, "RODA") == 0 && strcmp(CBpart, "RK886EX") == 0) roda_setup(pci); + else if (strcmp(CBvendor, "Win Enterprise") == 0 && strcmp(CBpart, "MB6047") == 0) + winent_mb6047_setup(pci); else if (pci->vendor == PCI_VENDOR_ID_VIA) via_setup(pci); else if (pci->vendor == PCI_VENDOR_ID_INTEL) diff -Nru seabios-1.7.1/src/virtio-blk.c seabios-1.7.4/src/virtio-blk.c --- seabios-1.7.1/src/virtio-blk.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-blk.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,174 +0,0 @@ -// Virtio block boot support. -// -// Copyright (C) 2010 Red Hat Inc. -// -// Authors: -// Gleb Natapov -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // foreachpci -#include "config.h" // CONFIG_* -#include "biosvar.h" // GET_GLOBAL -#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK -#include "pci_regs.h" // PCI_VENDOR_ID -#include "boot.h" // boot_add_hd -#include "virtio-pci.h" -#include "virtio-ring.h" -#include "virtio-blk.h" -#include "disk.h" - -struct virtiodrive_s { - struct drive_s drive; - struct vring_virtqueue *vq; - u16 ioaddr; -}; - -static int -virtio_blk_op(struct disk_op_s *op, int write) -{ - struct virtiodrive_s *vdrive_g = - container_of(op->drive_g, struct virtiodrive_s, drive); - struct vring_virtqueue *vq = GET_GLOBAL(vdrive_g->vq); - struct virtio_blk_outhdr hdr = { - .type = write ? VIRTIO_BLK_T_OUT : VIRTIO_BLK_T_IN, - .ioprio = 0, - .sector = op->lba, - }; - u8 status = VIRTIO_BLK_S_UNSUPP; - struct vring_list sg[] = { - { - .addr = MAKE_FLATPTR(GET_SEG(SS), &hdr), - .length = sizeof(hdr), - }, - { - .addr = op->buf_fl, - .length = GET_GLOBAL(vdrive_g->drive.blksize) * op->count, - }, - { - .addr = MAKE_FLATPTR(GET_SEG(SS), &status), - .length = sizeof(status), - }, - }; - - /* Add to virtqueue and kick host */ - if (write) - vring_add_buf(vq, sg, 2, 1, 0, 0); - else - vring_add_buf(vq, sg, 1, 2, 0, 0); - vring_kick(GET_GLOBAL(vdrive_g->ioaddr), vq, 1); - - /* Wait for reply */ - while (!vring_more_used(vq)) - usleep(5); - - /* Reclaim virtqueue element */ - vring_get_buf(vq, NULL); - - /* Clear interrupt status register. Avoid leaving interrupts stuck if - * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised. - */ - vp_get_isr(GET_GLOBAL(vdrive_g->ioaddr)); - - return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK; -} - -int -process_virtio_blk_op(struct disk_op_s *op) -{ - if (! CONFIG_VIRTIO_BLK || CONFIG_COREBOOT) - return 0; - switch (op->command) { - case CMD_READ: - return virtio_blk_op(op, 0); - case CMD_WRITE: - return virtio_blk_op(op, 1); - case CMD_FORMAT: - case CMD_RESET: - case CMD_ISREADY: - case CMD_VERIFY: - case CMD_SEEK: - return DISK_RET_SUCCESS; - default: - op->count = 0; - return DISK_RET_EPARAM; - } -} - -static void -init_virtio_blk(struct pci_device *pci) -{ - u16 bdf = pci->bdf; - dprintf(1, "found virtio-blk at %x:%x\n", pci_bdf_to_bus(bdf), - pci_bdf_to_dev(bdf)); - struct virtiodrive_s *vdrive_g = malloc_fseg(sizeof(*vdrive_g)); - if (!vdrive_g) { - warn_noalloc(); - return; - } - memset(vdrive_g, 0, sizeof(*vdrive_g)); - vdrive_g->drive.type = DTYPE_VIRTIO_BLK; - vdrive_g->drive.cntl_id = bdf; - - u16 ioaddr = vp_init_simple(bdf); - vdrive_g->ioaddr = ioaddr; - if (vp_find_vq(ioaddr, 0, &vdrive_g->vq) < 0 ) { - dprintf(1, "fail to find vq for virtio-blk %x:%x\n", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); - goto fail; - } - - struct virtio_blk_config cfg; - vp_get(ioaddr, 0, &cfg, sizeof(cfg)); - - u32 f = vp_get_features(ioaddr); - vdrive_g->drive.blksize = (f & (1 << VIRTIO_BLK_F_BLK_SIZE)) ? - cfg.blk_size : DISK_SECTOR_SIZE; - - vdrive_g->drive.sectors = cfg.capacity; - dprintf(3, "virtio-blk %x:%x blksize=%d sectors=%u\n", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), - vdrive_g->drive.blksize, (u32)vdrive_g->drive.sectors); - - if (vdrive_g->drive.blksize != DISK_SECTOR_SIZE) { - dprintf(1, "virtio-blk %x:%x block size %d is unsupported\n", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), - vdrive_g->drive.blksize); - goto fail; - } - - vdrive_g->drive.pchs.cylinders = cfg.cylinders; - vdrive_g->drive.pchs.heads = cfg.heads; - vdrive_g->drive.pchs.spt = cfg.sectors; - char *desc = znprintf(MAXDESCSIZE, "Virtio disk PCI:%x:%x", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); - - boot_add_hd(&vdrive_g->drive, desc, bootprio_find_pci_device(pci)); - - vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | - VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK); - return; - -fail: - free(vdrive_g->vq); - free(vdrive_g); -} - -void -virtio_blk_setup(void) -{ - ASSERT32FLAT(); - if (! CONFIG_VIRTIO_BLK || CONFIG_COREBOOT) - return; - - dprintf(3, "init virtio-blk\n"); - - struct pci_device *pci; - foreachpci(pci) { - if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET - || pci->device != PCI_DEVICE_ID_VIRTIO_BLK) - continue; - init_virtio_blk(pci); - } -} diff -Nru seabios-1.7.1/src/virtio-blk.h seabios-1.7.4/src/virtio-blk.h --- seabios-1.7.1/src/virtio-blk.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-blk.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -#ifndef _VIRTIO_BLK_H -#define _VIRTIO_BLK_H - -struct virtio_blk_config -{ - u64 capacity; - u32 size_max; - u32 seg_max; - u16 cylinders; - u8 heads; - u8 sectors; - u32 blk_size; - u8 physical_block_exp; - u8 alignment_offset; - u16 min_io_size; - u32 opt_io_size; -} __attribute__((packed)); - -#define VIRTIO_BLK_F_BLK_SIZE 6 - -/* These two define direction. */ -#define VIRTIO_BLK_T_IN 0 -#define VIRTIO_BLK_T_OUT 1 - -/* This is the first element of the read scatter-gather list. */ -struct virtio_blk_outhdr { - /* VIRTIO_BLK_T* */ - u32 type; - /* io priority. */ - u32 ioprio; - /* Sector (ie. 512 byte offset) */ - u64 sector; -}; - -#define VIRTIO_BLK_S_OK 0 -#define VIRTIO_BLK_S_IOERR 1 -#define VIRTIO_BLK_S_UNSUPP 2 - -struct disk_op_s; -int process_virtio_blk_op(struct disk_op_s *op); -void virtio_blk_setup(void); - -#endif /* _VIRTIO_BLK_H */ diff -Nru seabios-1.7.1/src/virtio-pci.c seabios-1.7.4/src/virtio-pci.c --- seabios-1.7.1/src/virtio-pci.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-pci.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -/* virtio-pci.c - pci interface for virtio interface - * - * (c) Copyright 2008 Bull S.A.S. - * - * Author: Laurent Vivier - * - * some parts from Linux Virtio PCI driver - * - * Copyright IBM Corp. 2007 - * Authors: Anthony Liguori - * - * Adopted for Seabios: Gleb Natapov - * - * This work is licensed under the terms of the GNU LGPLv3 - * See the COPYING file in the top-level directory. - */ - -#include "virtio-ring.h" -#include "virtio-pci.h" -#include "config.h" // CONFIG_DEBUG_LEVEL -#include "util.h" // dprintf -#include "pci.h" // pci_config_readl -#include "pci_regs.h" // PCI_BASE_ADDRESS_0 - -int vp_find_vq(unsigned int ioaddr, int queue_index, - struct vring_virtqueue **p_vq) -{ - u16 num; - - ASSERT32FLAT(); - struct vring_virtqueue *vq = *p_vq = memalign_low(PAGE_SIZE, sizeof(*vq)); - if (!vq) { - warn_noalloc(); - goto fail; - } - memset(vq, 0, sizeof(*vq)); - - /* select the queue */ - - outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); - - /* check if the queue is available */ - - num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); - if (!num) { - dprintf(1, "ERROR: queue size is 0\n"); - goto fail; - } - - if (num > MAX_QUEUE_NUM) { - dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); - goto fail; - } - - /* check if the queue is already active */ - - if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { - dprintf(1, "ERROR: queue already active\n"); - goto fail; - } - - vq->queue_index = queue_index; - - /* initialize the queue */ - - struct vring * vr = &vq->vring; - vring_init(vr, num, (unsigned char*)&vq->queue); - - /* activate the queue - * - * NOTE: vr->desc is initialized by vring_init() - */ - - outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, - ioaddr + VIRTIO_PCI_QUEUE_PFN); - - return num; - -fail: - free(vq); - *p_vq = NULL; - return -1; -} - -u16 vp_init_simple(u16 bdf) -{ - u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & - PCI_BASE_ADDRESS_IO_MASK; - - vp_reset(ioaddr); - vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | - VIRTIO_CONFIG_S_DRIVER ); - return ioaddr; -} diff -Nru seabios-1.7.1/src/virtio-pci.h seabios-1.7.4/src/virtio-pci.h --- seabios-1.7.1/src/virtio-pci.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-pci.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -#ifndef _VIRTIO_PCI_H -#define _VIRTIO_PCI_H - -#include "ioport.h" // inl - -/* A 32-bit r/o bitmask of the features supported by the host */ -#define VIRTIO_PCI_HOST_FEATURES 0 - -/* A 32-bit r/w bitmask of features activated by the guest */ -#define VIRTIO_PCI_GUEST_FEATURES 4 - -/* A 32-bit r/w PFN for the currently selected queue */ -#define VIRTIO_PCI_QUEUE_PFN 8 - -/* A 16-bit r/o queue size for the currently selected queue */ -#define VIRTIO_PCI_QUEUE_NUM 12 - -/* A 16-bit r/w queue selector */ -#define VIRTIO_PCI_QUEUE_SEL 14 - -/* A 16-bit r/w queue notifier */ -#define VIRTIO_PCI_QUEUE_NOTIFY 16 - -/* An 8-bit device status register. */ -#define VIRTIO_PCI_STATUS 18 - -/* An 8-bit r/o interrupt status register. Reading the value will return the - * current contents of the ISR and will also clear it. This is effectively - * a read-and-acknowledge. */ -#define VIRTIO_PCI_ISR 19 - -/* The bit of the ISR which indicates a device configuration change. */ -#define VIRTIO_PCI_ISR_CONFIG 0x2 - -/* The remaining space is defined by each driver as the per-driver - * configuration space */ -#define VIRTIO_PCI_CONFIG 20 - -/* Virtio ABI version, this must match exactly */ -#define VIRTIO_PCI_ABI_VERSION 0 - -static inline u32 vp_get_features(unsigned int ioaddr) -{ - return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES); -} - -static inline void vp_set_features(unsigned int ioaddr, u32 features) -{ - outl(features, ioaddr + VIRTIO_PCI_GUEST_FEATURES); -} - -static inline void vp_get(unsigned int ioaddr, unsigned offset, - void *buf, unsigned len) -{ - u8 *ptr = buf; - unsigned i; - - for (i = 0; i < len; i++) - ptr[i] = inb(ioaddr + VIRTIO_PCI_CONFIG + offset + i); -} - -static inline u8 vp_get_status(unsigned int ioaddr) -{ - return inb(ioaddr + VIRTIO_PCI_STATUS); -} - -static inline void vp_set_status(unsigned int ioaddr, u8 status) -{ - if (status == 0) /* reset */ - return; - outb(status, ioaddr + VIRTIO_PCI_STATUS); -} - -static inline u8 vp_get_isr(unsigned int ioaddr) -{ - return inb(ioaddr + VIRTIO_PCI_ISR); -} - -static inline void vp_reset(unsigned int ioaddr) -{ - outb(0, ioaddr + VIRTIO_PCI_STATUS); - (void)inb(ioaddr + VIRTIO_PCI_ISR); -} - -static inline void vp_notify(unsigned int ioaddr, int queue_index) -{ - outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); -} - -static inline void vp_del_vq(unsigned int ioaddr, int queue_index) -{ - /* select the queue */ - - outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); - - /* deactivate the queue */ - - outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN); -} - -struct vring_virtqueue; -u16 vp_init_simple(u16 bdf); -int vp_find_vq(unsigned int ioaddr, int queue_index, - struct vring_virtqueue **p_vq); -#endif /* _VIRTIO_PCI_H_ */ diff -Nru seabios-1.7.1/src/virtio-ring.c seabios-1.7.4/src/virtio-ring.c --- seabios-1.7.1/src/virtio-ring.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-ring.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -/* virtio-pci.c - virtio ring management - * - * (c) Copyright 2008 Bull S.A.S. - * - * Author: Laurent Vivier - * - * some parts from Linux Virtio Ring - * - * Copyright Rusty Russell IBM Corporation 2007 - * - * Adopted for Seabios: Gleb Natapov - * - * This work is licensed under the terms of the GNU LGPLv3 - * See the COPYING file in the top-level directory. - * - * - */ - -#include "virtio-ring.h" -#include "virtio-pci.h" -#include "biosvar.h" // GET_GLOBAL -#include "util.h" // dprintf - -#define BUG() do { \ - dprintf(1, "BUG: failure at %s:%d/%s()!\n", \ - __FILE__, __LINE__, __func__); \ - while(1); \ - } while (0) -#define BUG_ON(condition) do { if (condition) BUG(); } while (0) - -/* - * vring_more_used - * - * is there some used buffers ? - * - */ - -int vring_more_used(struct vring_virtqueue *vq) -{ - struct vring_used *used = GET_LOWFLAT(vq->vring.used); - int more = GET_LOWFLAT(vq->last_used_idx) != GET_LOWFLAT(used->idx); - /* Make sure ring reads are done after idx read above. */ - smp_rmb(); - return more; -} - -/* - * vring_free - * - * put at the begin of the free list the current desc[head] - */ - -void vring_detach(struct vring_virtqueue *vq, unsigned int head) -{ - struct vring *vr = &vq->vring; - struct vring_desc *desc = GET_LOWFLAT(vr->desc); - unsigned int i; - - /* find end of given descriptor */ - - i = head; - while (GET_LOWFLAT(desc[i].flags) & VRING_DESC_F_NEXT) - i = GET_LOWFLAT(desc[i].next); - - /* link it with free list and point to it */ - - SET_LOWFLAT(desc[i].next, GET_LOWFLAT(vq->free_head)); - SET_LOWFLAT(vq->free_head, head); -} - -/* - * vring_get_buf - * - * get a buffer from the used list - * - */ - -int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len) -{ - struct vring *vr = &vq->vring; - struct vring_used_elem *elem; - struct vring_used *used = GET_LOWFLAT(vq->vring.used); - u32 id; - int ret; - -// BUG_ON(!vring_more_used(vq)); - - elem = &used->ring[GET_LOWFLAT(vq->last_used_idx) % GET_LOWFLAT(vr->num)]; - id = GET_LOWFLAT(elem->id); - if (len != NULL) - *len = GET_LOWFLAT(elem->len); - - ret = GET_LOWFLAT(vq->vdata[id]); - - vring_detach(vq, id); - - SET_LOWFLAT(vq->last_used_idx, GET_LOWFLAT(vq->last_used_idx) + 1); - - return ret; -} - -void vring_add_buf(struct vring_virtqueue *vq, - struct vring_list list[], - unsigned int out, unsigned int in, - int index, int num_added) -{ - struct vring *vr = &vq->vring; - int i, av, head, prev; - struct vring_desc *desc = GET_LOWFLAT(vr->desc); - struct vring_avail *avail = GET_LOWFLAT(vr->avail); - - BUG_ON(out + in == 0); - - prev = 0; - head = GET_LOWFLAT(vq->free_head); - for (i = head; out; i = GET_LOWFLAT(desc[i].next), out--) { - SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT); - SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr)); - SET_LOWFLAT(desc[i].len, list->length); - prev = i; - list++; - } - for ( ; in; i = GET_LOWFLAT(desc[i].next), in--) { - SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT|VRING_DESC_F_WRITE); - SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr)); - SET_LOWFLAT(desc[i].len, list->length); - prev = i; - list++; - } - SET_LOWFLAT(desc[prev].flags, - GET_LOWFLAT(desc[prev].flags) & ~VRING_DESC_F_NEXT); - - SET_LOWFLAT(vq->free_head, i); - - SET_LOWFLAT(vq->vdata[head], index); - - av = (GET_LOWFLAT(avail->idx) + num_added) % GET_LOWFLAT(vr->num); - SET_LOWFLAT(avail->ring[av], head); -} - -void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) -{ - struct vring *vr = &vq->vring; - struct vring_avail *avail = GET_LOWFLAT(vr->avail); - - /* Make sure idx update is done after ring write. */ - smp_wmb(); - SET_LOWFLAT(avail->idx, GET_LOWFLAT(avail->idx) + num_added); - - vp_notify(ioaddr, GET_LOWFLAT(vq->queue_index)); -} diff -Nru seabios-1.7.1/src/virtio-ring.h seabios-1.7.4/src/virtio-ring.h --- seabios-1.7.1/src/virtio-ring.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-ring.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,131 +0,0 @@ -#ifndef _VIRTIO_RING_H -#define _VIRTIO_RING_H - -#include "types.h" // u64 -#include "memmap.h" // PAGE_SIZE - -#define PAGE_SHIFT 12 -#define PAGE_MASK (PAGE_SIZE-1) - -#define virt_to_phys(v) (unsigned long)(v) -#define phys_to_virt(p) (void*)(p) -/* Compiler barrier is enough as an x86 CPU does not reorder reads or writes */ -#define smp_rmb() barrier() -#define smp_wmb() barrier() - -/* Status byte for guest to report progress, and synchronize features. */ -/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ -#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 -/* We have found a driver for the device. */ -#define VIRTIO_CONFIG_S_DRIVER 2 -/* Driver has used its parts of the config, and is happy */ -#define VIRTIO_CONFIG_S_DRIVER_OK 4 -/* We've given up on this device. */ -#define VIRTIO_CONFIG_S_FAILED 0x80 - -#define MAX_QUEUE_NUM (128) - -#define VRING_DESC_F_NEXT 1 -#define VRING_DESC_F_WRITE 2 - -#define VRING_AVAIL_F_NO_INTERRUPT 1 - -#define VRING_USED_F_NO_NOTIFY 1 - -struct vring_desc -{ - u64 addr; - u32 len; - u16 flags; - u16 next; -}; - -struct vring_avail -{ - u16 flags; - u16 idx; - u16 ring[0]; -}; - -struct vring_used_elem -{ - u32 id; - u32 len; -}; - -struct vring_used -{ - u16 flags; - u16 idx; - struct vring_used_elem ring[]; -}; - -struct vring { - unsigned int num; - struct vring_desc *desc; - struct vring_avail *avail; - struct vring_used *used; -}; - -#define vring_size(num) \ - (((((sizeof(struct vring_desc) * num) + \ - (sizeof(struct vring_avail) + sizeof(u16) * num)) \ - + PAGE_MASK) & ~PAGE_MASK) + \ - (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num)) - -typedef unsigned char virtio_queue_t[vring_size(MAX_QUEUE_NUM)]; - -struct vring_virtqueue { - virtio_queue_t queue; - struct vring vring; - u16 free_head; - u16 last_used_idx; - u16 vdata[MAX_QUEUE_NUM]; - /* PCI */ - int queue_index; -}; - -struct vring_list { - char *addr; - unsigned int length; -}; - -static inline void vring_init(struct vring *vr, - unsigned int num, unsigned char *queue) -{ - unsigned int i; - unsigned long pa; - - ASSERT32FLAT(); - vr->num = num; - - /* physical address of desc must be page aligned */ - - pa = virt_to_phys(queue); - pa = (pa + PAGE_MASK) & ~PAGE_MASK; - vr->desc = phys_to_virt(pa); - - vr->avail = (struct vring_avail *)&vr->desc[num]; - /* disable interrupts */ - vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; - - /* physical address of used must be page aligned */ - - pa = virt_to_phys(&vr->avail->ring[num]); - pa = (pa + PAGE_MASK) & ~PAGE_MASK; - vr->used = phys_to_virt(pa); - - for (i = 0; i < num - 1; i++) - vr->desc[i].next = i + 1; - vr->desc[i].next = 0; -} - -int vring_more_used(struct vring_virtqueue *vq); -void vring_detach(struct vring_virtqueue *vq, unsigned int head); -int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len); -void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[], - unsigned int out, unsigned int in, - int index, int num_added); -void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added); - -#endif /* _VIRTIO_RING_H_ */ diff -Nru seabios-1.7.1/src/virtio-scsi.c seabios-1.7.4/src/virtio-scsi.c --- seabios-1.7.1/src/virtio-scsi.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-scsi.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ -// Virtio SCSI boot support. -// -// Copyright (C) 2012 Red Hat Inc. -// -// Authors: -// Paolo Bonzini -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "util.h" // dprintf -#include "pci.h" // foreachpci -#include "config.h" // CONFIG_* -#include "biosvar.h" // GET_GLOBAL -#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK -#include "pci_regs.h" // PCI_VENDOR_ID -#include "boot.h" // bootprio_find_scsi_device -#include "blockcmd.h" // scsi_init_drive -#include "virtio-pci.h" -#include "virtio-ring.h" -#include "virtio-scsi.h" -#include "disk.h" - -struct virtio_lun_s { - struct drive_s drive; - struct pci_device *pci; - struct vring_virtqueue *vq; - u16 ioaddr; - u16 target; - u16 lun; -}; - -static int -virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op, - void *cdbcmd, u16 target, u16 lun, u16 blocksize) -{ - struct virtio_scsi_req_cmd req; - struct virtio_scsi_resp_cmd resp; - struct vring_list sg[3]; - - memset(&req, 0, sizeof(req)); - req.lun[0] = 1; - req.lun[1] = target; - req.lun[2] = (lun >> 8) | 0x40; - req.lun[3] = (lun & 0xff); - memcpy(req.cdb, cdbcmd, 16); - - u32 len = op->count * blocksize; - int datain = cdb_is_read(cdbcmd, blocksize); - int in_num = (datain ? 2 : 1); - int out_num = (len ? 3 : 2) - in_num; - - sg[0].addr = MAKE_FLATPTR(GET_SEG(SS), &req); - sg[0].length = sizeof(req); - - sg[out_num].addr = MAKE_FLATPTR(GET_SEG(SS), &resp); - sg[out_num].length = sizeof(resp); - - if (len) { - int data_idx = (datain ? 2 : 1); - sg[data_idx].addr = op->buf_fl; - sg[data_idx].length = len; - } - - /* Add to virtqueue and kick host */ - vring_add_buf(vq, sg, out_num, in_num, 0, 0); - vring_kick(ioaddr, vq, 1); - - /* Wait for reply */ - while (!vring_more_used(vq)) - usleep(5); - - /* Reclaim virtqueue element */ - vring_get_buf(vq, NULL); - - /* Clear interrupt status register. Avoid leaving interrupts stuck if - * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised. - */ - vp_get_isr(ioaddr); - - if (resp.response == VIRTIO_SCSI_S_OK && resp.status == 0) { - return DISK_RET_SUCCESS; - } - return DISK_RET_EBADTRACK; -} - -int -virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) -{ - struct virtio_lun_s *vlun = - container_of(op->drive_g, struct virtio_lun_s, drive); - - return virtio_scsi_cmd(GET_GLOBAL(vlun->ioaddr), - GET_GLOBAL(vlun->vq), op, cdbcmd, - GET_GLOBAL(vlun->target), GET_GLOBAL(vlun->lun), - blocksize); -} - -static int -virtio_scsi_add_lun(struct pci_device *pci, u16 ioaddr, - struct vring_virtqueue *vq, u16 target, u16 lun) -{ - struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun)); - if (!vlun) { - warn_noalloc(); - return -1; - } - memset(vlun, 0, sizeof(*vlun)); - vlun->drive.type = DTYPE_VIRTIO_SCSI; - vlun->drive.cntl_id = pci->bdf; - vlun->pci = pci; - vlun->ioaddr = ioaddr; - vlun->vq = vq; - vlun->target = target; - vlun->lun = lun; - - int prio = bootprio_find_scsi_device(pci, target, lun); - int ret = scsi_init_drive(&vlun->drive, "virtio-scsi", prio); - if (ret) - goto fail; - return 0; - -fail: - free(vlun); - return -1; -} - -static int -virtio_scsi_scan_target(struct pci_device *pci, u16 ioaddr, - struct vring_virtqueue *vq, u16 target) -{ - /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ - int ret = virtio_scsi_add_lun(pci, ioaddr, vq, target, 0); - return ret < 0 ? 0 : 1; -} - -static void -init_virtio_scsi(struct pci_device *pci) -{ - u16 bdf = pci->bdf; - dprintf(1, "found virtio-scsi at %x:%x\n", pci_bdf_to_bus(bdf), - pci_bdf_to_dev(bdf)); - struct vring_virtqueue *vq = NULL; - u16 ioaddr = vp_init_simple(bdf); - if (vp_find_vq(ioaddr, 2, &vq) < 0 ) { - dprintf(1, "fail to find vq for virtio-scsi %x:%x\n", - pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); - goto fail; - } - - int i, tot; - for (tot = 0, i = 0; i < 256; i++) - tot += virtio_scsi_scan_target(pci, ioaddr, vq, i); - - if (!tot) - goto fail; - - vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | - VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK); - return; - -fail: - free(vq); -} - -void -virtio_scsi_setup(void) -{ - ASSERT32FLAT(); - if (! CONFIG_VIRTIO_SCSI || CONFIG_COREBOOT) - return; - - dprintf(3, "init virtio-scsi\n"); - - struct pci_device *pci; - foreachpci(pci) { - if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET - || pci->device != PCI_DEVICE_ID_VIRTIO_SCSI) - continue; - init_virtio_scsi(pci); - } -} diff -Nru seabios-1.7.1/src/virtio-scsi.h seabios-1.7.4/src/virtio-scsi.h --- seabios-1.7.1/src/virtio-scsi.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/virtio-scsi.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -#ifndef _VIRTIO_SCSI_H -#define _VIRTIO_SCSI_H - -#define VIRTIO_SCSI_CDB_SIZE 32 -#define VIRTIO_SCSI_SENSE_SIZE 96 - -struct virtio_scsi_config -{ - u32 num_queues; - u32 seg_max; - u32 max_sectors; - u32 cmd_per_lun; - u32 event_info_size; - u32 sense_size; - u32 cdb_size; - u16 max_channel; - u16 max_target; - u32 max_lun; -} __attribute__((packed)); - -/* This is the first element of the "out" scatter-gather list. */ -struct virtio_scsi_req_cmd { - u8 lun[8]; - u64 id; - u8 task_attr; - u8 prio; - u8 crn; - char cdb[VIRTIO_SCSI_CDB_SIZE]; -}; - -/* This is the first element of the "in" scatter-gather list. */ -struct virtio_scsi_resp_cmd { - u32 sense_len; - u32 residual; - u16 status_qualifier; - u8 status; - u8 response; - u8 sense[VIRTIO_SCSI_SENSE_SIZE]; -}; - -#define VIRTIO_SCSI_S_OK 0 - -struct disk_op_s; -int virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); -void virtio_scsi_setup(void); - -#endif /* _VIRTIO_SCSI_H */ diff -Nru seabios-1.7.1/src/x86.c seabios-1.7.4/src/x86.c --- seabios-1.7.1/src/x86.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/x86.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,23 @@ +// X86 utility functions. +// +// Copyright (C) 2013 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "x86.h" // __cpuid + +void +cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ + // Check for cpu id + u32 origflags = save_flags(); + restore_flags(origflags ^ F_ID); + u32 newflags = save_flags(); + restore_flags(origflags); + + if (((origflags ^ newflags) & F_ID) != F_ID) + // no cpuid + *eax = *ebx = *ecx = *edx = 0; + else + __cpuid(index, eax, ebx, ecx, edx); +} diff -Nru seabios-1.7.1/src/x86.h seabios-1.7.4/src/x86.h --- seabios-1.7.1/src/x86.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/src/x86.h 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,225 @@ +// Basic x86 asm functions. +#ifndef __X86_H +#define __X86_H + +// CPU flag bitdefs +#define F_CF (1<<0) +#define F_ZF (1<<6) +#define F_IF (1<<9) +#define F_ID (1<<21) + +// CR0 flags +#define CR0_PG (1<<31) // Paging +#define CR0_CD (1<<30) // Cache disable +#define CR0_NW (1<<29) // Not Write-through +#define CR0_PE (1<<0) // Protection enable + +#ifndef __ASSEMBLY__ + +#include "types.h" // u32 + +static inline void irq_disable(void) +{ + asm volatile("cli": : :"memory"); +} + +static inline void irq_enable(void) +{ + asm volatile("sti": : :"memory"); +} + +static inline u32 save_flags(void) +{ + u32 flags; + asm volatile("pushfl ; popl %0" : "=rm" (flags)); + return flags; +} + +static inline void restore_flags(u32 flags) +{ + asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc"); +} + +static inline void cpu_relax(void) +{ + asm volatile("rep ; nop": : :"memory"); +} + +static inline void nop(void) +{ + asm volatile("nop"); +} + +static inline void hlt(void) +{ + asm volatile("hlt": : :"memory"); +} + +static inline void wbinvd(void) +{ + asm volatile("wbinvd": : :"memory"); +} + +#define CPUID_TSC (1 << 4) +#define CPUID_MSR (1 << 5) +#define CPUID_APIC (1 << 9) +#define CPUID_MTRR (1 << 12) +static inline void __cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ + asm("cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (index)); +} + +static inline u32 getcr0(void) { + u32 cr0; + asm("movl %%cr0, %0" : "=r"(cr0)); + return cr0; +} +static inline void setcr0(u32 cr0) { + asm("movl %0, %%cr0" : : "r"(cr0)); +} + +static inline u64 rdmsr(u32 index) +{ + u64 ret; + asm ("rdmsr" : "=A"(ret) : "c"(index)); + return ret; +} + +static inline void wrmsr(u32 index, u64 val) +{ + asm volatile ("wrmsr" : : "c"(index), "A"(val)); +} + +static inline u64 rdtscll(void) +{ + u64 val; + asm volatile("rdtsc" : "=A" (val)); + return val; +} + +static inline u32 __ffs(u32 word) +{ + asm("bsf %1,%0" + : "=r" (word) + : "rm" (word)); + return word; +} +static inline u32 __fls(u32 word) +{ + asm("bsr %1,%0" + : "=r" (word) + : "rm" (word)); + return word; +} + +static inline u32 getesp(void) { + u32 esp; + asm("movl %%esp, %0" : "=rm"(esp)); + return esp; +} + +static inline void outb(u8 value, u16 port) { + __asm__ __volatile__("outb %b0, %w1" : : "a"(value), "Nd"(port)); +} +static inline void outw(u16 value, u16 port) { + __asm__ __volatile__("outw %w0, %w1" : : "a"(value), "Nd"(port)); +} +static inline void outl(u32 value, u16 port) { + __asm__ __volatile__("outl %0, %w1" : : "a"(value), "Nd"(port)); +} +static inline u8 inb(u16 port) { + u8 value; + __asm__ __volatile__("inb %w1, %b0" : "=a"(value) : "Nd"(port)); + return value; +} +static inline u16 inw(u16 port) { + u16 value; + __asm__ __volatile__("inw %w1, %w0" : "=a"(value) : "Nd"(port)); + return value; +} +static inline u32 inl(u16 port) { + u32 value; + __asm__ __volatile__("inl %w1, %0" : "=a"(value) : "Nd"(port)); + return value; +} + +static inline void insb(u16 port, u8 *data, u32 count) { + asm volatile("rep insb (%%dx), %%es:(%%edi)" + : "+c"(count), "+D"(data) : "d"(port) : "memory"); +} +static inline void insw(u16 port, u16 *data, u32 count) { + asm volatile("rep insw (%%dx), %%es:(%%edi)" + : "+c"(count), "+D"(data) : "d"(port) : "memory"); +} +static inline void insl(u16 port, u32 *data, u32 count) { + asm volatile("rep insl (%%dx), %%es:(%%edi)" + : "+c"(count), "+D"(data) : "d"(port) : "memory"); +} +// XXX - outs not limited to es segment +static inline void outsb(u16 port, u8 *data, u32 count) { + asm volatile("rep outsb %%es:(%%esi), (%%dx)" + : "+c"(count), "+S"(data) : "d"(port) : "memory"); +} +static inline void outsw(u16 port, u16 *data, u32 count) { + asm volatile("rep outsw %%es:(%%esi), (%%dx)" + : "+c"(count), "+S"(data) : "d"(port) : "memory"); +} +static inline void outsl(u16 port, u32 *data, u32 count) { + asm volatile("rep outsl %%es:(%%esi), (%%dx)" + : "+c"(count), "+S"(data) : "d"(port) : "memory"); +} + +static inline void writel(void *addr, u32 val) { + *(volatile u32 *)addr = val; +} +static inline void writew(void *addr, u16 val) { + *(volatile u16 *)addr = val; +} +static inline void writeb(void *addr, u8 val) { + *(volatile u8 *)addr = val; +} +static inline u32 readl(const void *addr) { + return *(volatile const u32 *)addr; +} +static inline u16 readw(const void *addr) { + return *(volatile const u16 *)addr; +} +static inline u8 readb(const void *addr) { + return *(volatile const u8 *)addr; +} + +// GDT bits +#define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set +#define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set +#define GDT_B (0x1ULL << 54) // Big flag +#define GDT_G (0x1ULL << 55) // Granularity flag +// GDT bits for segment base +#define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \ + | (((u64)(v) & 0x00ffffff) << 16)) +// GDT bits for segment limit (0-1Meg) +#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \ + | (((u64)(v) & 0x0000ffff) << 0)) +// GDT bits for segment limit (0-4Gig in 4K chunks) +#define GDT_GRANLIMIT(v) (GDT_G | GDT_LIMIT((v) >> 12)) + +struct descloc_s { + u16 length; + u32 addr; +} PACKED; + +static inline void sgdt(struct descloc_s *desc) { + asm("sgdtl %0" : "=m"(*desc)); +} +static inline void lgdt(struct descloc_s *desc) { + asm("lgdtl %0" : : "m"(*desc) : "memory"); +} + +// x86.c +void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); + + +#endif // !__ASSEMBLY__ + +#endif // x86.h diff -Nru seabios-1.7.1/src/xen.c seabios-1.7.4/src/xen.c --- seabios-1.7.1/src/xen.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/xen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -// Xen HVM support -// -// Copyright (C) 2011 Citrix Systems. -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "config.h" -#include "xen.h" - -#include "memmap.h" // add_e820 -#include "types.h" // ASM32FLAT -#include "util.h" // copy_acpi_rsdp - -#define INFO_PHYSICAL_ADDRESS 0x00001000 - -u32 xen_cpuid_base = 0; -unsigned long xen_hypercall_page = 0; - -struct xen_seabios_info { - char signature[14]; /* XenHVMSeaBIOS\0 */ - u8 length; /* Length of this struct */ - u8 checksum; /* Set such that the sum over bytes 0..length == 0 */ - /* - * Physical address of an array of tables_nr elements. - * - * Each element is a 32 bit value contianing the physical address - * of a BIOS table. - */ - u32 tables; - u32 tables_nr; - /* - * Physical address of the e820 table, contains e820_nr entries. - */ - u32 e820; - u32 e820_nr; -} PACKED; - -static void validate_info(struct xen_seabios_info *t) -{ - if ( memcmp(t->signature, "XenHVMSeaBIOS", 14) ) - panic("Bad Xen info signature\n"); - - if ( t->length < sizeof(struct xen_seabios_info) ) - panic("Bad Xen info length\n"); - - if (checksum(t, t->length) != 0) - panic("Bad Xen info checksum\n"); -} - -void xen_probe(void) -{ - u32 base, eax, ebx, ecx, edx; - char signature[13]; - - if (!CONFIG_XEN) - return; - - for (base = 0x40000000; base < 0x40010000; base += 0x100) { - cpuid(base, &eax, &ebx, &ecx, &edx); - memcpy(signature + 0, &ebx, 4); - memcpy(signature + 4, &ecx, 4); - memcpy(signature + 8, &edx, 4); - signature[12] = 0; - - dprintf(9, "Found hypervisor signature \"%s\" at %x\n", - signature, base); - if (strcmp(signature, "XenVMMXenVMM") == 0) { - /* Set debug_io_port first, so the following messages work. */ - DebugOutputPort = 0xe9; - dprintf(1, "SeaBIOS (version %s)\n\n", VERSION); - dprintf(1, "Found Xen hypervisor signature at %x\n", base); - if ((eax - base) < 2) - panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n", - eax, base); - xen_cpuid_base = base; - break; - } - } - if (!xen_cpuid_base) - dprintf(1, "No Xen hypervisor found.\n"); -} - -static int hypercall_xen_version( int cmd, void *arg) -{ - return _hypercall2(int, xen_version, cmd, arg); -} - -/* Fill in hypercall transfer pages. */ -void xen_init_hypercalls(void) -{ - u32 eax, ebx, ecx, edx; - xen_extraversion_t extraversion; - unsigned long i; - - if (!usingXen()) - return; - - cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx); - - xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE); - if (!xen_hypercall_page) - panic("unable to allocate Xen hypercall page\n"); - - dprintf(1, "Allocated Xen hypercall page at %lx\n", xen_hypercall_page); - for ( i = 0; i < eax; i++ ) - wrmsr(ebx, xen_hypercall_page + (i << 12) + i); - - /* Print version information. */ - cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx); - hypercall_xen_version(XENVER_extraversion, extraversion); - dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion); -} - -void xen_copy_biostables(void) -{ - struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS; - void **tables = (void*)info->tables; - int i; - - dprintf(1, "xen: copy BIOS tables...\n"); - for (i=0; itables_nr; i++) - copy_table(tables[i]); -} - -void xen_setup(void) -{ - u64 maxram = 0, maxram_over4G = 0; - int i; - struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS; - struct e820entry *e820 = (struct e820entry *)info->e820; - validate_info(info); - - dprintf(1, "xen: copy e820...\n"); - - for (i = 0; i < info->e820_nr; i++) { - struct e820entry *e = &e820[i]; - if (e->type == E820_ACPI || e->type == E820_RAM) { - u64 end = e->start + e->size; - if (end > 0x100000000ull) { - end -= 0x100000000ull; - if (end > maxram_over4G) - maxram_over4G = end; - } else if (end > maxram) - maxram = end; - } - add_e820(e->start, e->size, e->type); - } - - RamSize = maxram; - RamSizeOver4G = maxram_over4G; -} diff -Nru seabios-1.7.1/src/xen.h seabios-1.7.4/src/xen.h --- seabios-1.7.1/src/xen.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/src/xen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -#ifndef __XEN_H -#define __XEN_H - -#include "config.h" // CONFIG_* -#include "types.h" // u32 - -extern u32 xen_cpuid_base; - -void xen_probe(void); -void xen_setup(void); -void xen_init_hypercalls(void); -void xen_copy_biostables(void); - -static inline int usingXen(void) { - if (!CONFIG_XEN) - return 0; - return (xen_cpuid_base != 0); -} - -extern unsigned long xen_hypercall_page; - -#define _hypercall0(type, name) \ -({ \ - unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ - long __res; \ - asm volatile ( \ - "call *%%eax" \ - : "=a" (__res) \ - : "0" (__hentry) \ - : "memory" ); \ - (type)__res; \ -}) - -#define _hypercall1(type, name, a1) \ -({ \ - unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ - long __res, __ign1; \ - asm volatile ( \ - "call *%%eax" \ - : "=a" (__res), "=b" (__ign1) \ - : "0" (__hentry), "1" ((long)(a1)) \ - : "memory" ); \ - (type)__res; \ -}) - -#define _hypercall2(type, name, a1, a2) \ -({ \ - unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ - long __res, __ign1, __ign2; \ - asm volatile ( \ - "call *%%eax" \ - : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ - : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)) \ - : "memory" ); \ - (type)__res; \ -}) - -#define _hypercall3(type, name, a1, a2, a3) \ -({ \ - unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ - long __res, __ign1, __ign2, __ign3; \ - asm volatile ( \ - "call *%%eax" \ - : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ - "=d" (__ign3) \ - : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \ - "3" ((long)(a3)) \ - : "memory" ); \ - (type)__res; \ -}) - -#define _hypercall4(type, name, a1, a2, a3, a4) \ -({ \ - unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ - long __res, __ign1, __ign2, __ign3, __ign4; \ - asm volatile ( \ - "call *%%eax" \ - : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ - "=d" (__ign3), "=S" (__ign4) \ - : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \ - "3" ((long)(a3)), "4" ((long)(a4)) \ - : "memory" ); \ - (type)__res; \ -}) - -#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ -({ \ - unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \ - long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \ - asm volatile ( \ - "call *%%eax" \ - : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ - "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \ - : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \ - "3" ((long)(a3)), "4" ((long)(a4)), \ - "5" ((long)(a5)) \ - : "memory" ); \ - (type)__res; \ -}) - -/****************************************************************************** - * - * The following interface definitions are taken from Xen and have the - * following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* xen.h */ - -#define __HYPERVISOR_xen_version 17 - -/* version.h */ - -/* arg == xen_extraversion_t. */ -#define XENVER_extraversion 1 -typedef char xen_extraversion_t[16]; -#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t)) - -#endif diff -Nru seabios-1.7.1/tools/acpi_extract_preprocess.py seabios-1.7.4/tools/acpi_extract_preprocess.py --- seabios-1.7.1/tools/acpi_extract_preprocess.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/acpi_extract_preprocess.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -# Read a preprocessed ASL listing and put each ACPI_EXTRACT -# directive in a comment, to make iasl skip it. -# We also put each directive on a new line, the machinery -# in tools/acpi_extract.py requires this. - -import re; -import sys; -import fileinput; - -def die(diag): - sys.stderr.write("Error: %s\n" % (diag)) - sys.exit(1) - -# Note: () around pattern make split return matched string as part of list -psplit = re.compile(r''' ( - \b # At word boundary - ACPI_EXTRACT_\w+ # directive - \s+ # some whitespace - \w+ # array name - )''', re.VERBOSE); - -lineno = 0 -for line in fileinput.input(): - # line number and debug string to output in case of errors - lineno = lineno + 1 - debug = "input line %d: %s" % (lineno, line.rstrip()) - - s = psplit.split(line); - # The way split works, each odd item is the matching ACPI_EXTRACT directive. - # Put each in a comment, and on a line by itself. - for i in range(len(s)): - if (i % 2): - sys.stdout.write("\n/* %s */\n" % s[i]) - else: - sys.stdout.write(s[i]) - diff -Nru seabios-1.7.1/tools/acpi_extract.py seabios-1.7.4/tools/acpi_extract.py --- seabios-1.7.1/tools/acpi_extract.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/acpi_extract.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,308 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -# Process mixed ASL/AML listing (.lst file) produced by iasl -l -# Locate and execute ACPI_EXTRACT directives, output offset info -# -# Documentation of ACPI_EXTRACT_* directive tags: -# -# These directive tags output offset information from AML for BIOS runtime -# table generation. -# Each directive is of the form: -# ACPI_EXTRACT_ (...) -# and causes the extractor to create an array -# named with offset, in the generated AML, -# of an object of a given type in the following . -# -# A directive must fit on a single code line. -# -# Object type in AML is verified, a mismatch causes a build failure. -# -# Directives and operators currently supported are: -# ACPI_EXTRACT_NAME_DWORD_CONST - extract a Dword Const object from Name() -# ACPI_EXTRACT_NAME_WORD_CONST - extract a Word Const object from Name() -# ACPI_EXTRACT_NAME_BYTE_CONST - extract a Byte Const object from Name() -# ACPI_EXTRACT_METHOD_STRING - extract a NameString from Method() -# ACPI_EXTRACT_NAME_STRING - extract a NameString from Name() -# ACPI_EXTRACT_PROCESSOR_START - start of Processor() block -# ACPI_EXTRACT_PROCESSOR_STRING - extract a NameString from Processor() -# ACPI_EXTRACT_PROCESSOR_END - offset at last byte of Processor() + 1 -# ACPI_EXTRACT_PKG_START - start of Package block -# -# ACPI_EXTRACT_ALL_CODE - create an array storing the generated AML bytecode -# -# ACPI_EXTRACT is not allowed anywhere else in code, except in comments. - -import re; -import sys; -import fileinput; - -aml = [] -asl = [] -output = {} -debug = "" - -class asl_line: - line = None - lineno = None - aml_offset = None - -def die(diag): - sys.stderr.write("Error: %s; %s\n" % (diag, debug)) - sys.exit(1) - -#Store an ASL command, matching AML offset, and input line (for debugging) -def add_asl(lineno, line): - l = asl_line() - l.line = line - l.lineno = lineno - l.aml_offset = len(aml) - asl.append(l) - -#Store an AML byte sequence -#Verify that offset output by iasl matches # of bytes so far -def add_aml(offset, line): - o = int(offset, 16); - # Sanity check: offset must match size of code so far - if (o != len(aml)): - die("Offset 0x%x != 0x%x" % (o, len(aml))) - # Strip any trailing dots and ASCII dump after " - line = re.sub(r'\s*\.*\s*".*$',"", line) - # Strip traling whitespace - line = re.sub(r'\s+$',"", line) - # Strip leading whitespace - line = re.sub(r'^\s+',"", line) - # Split on whitespace - code = re.split(r'\s+', line) - for c in code: - # Require a legal hex number, two digits - if (not(re.search(r'^[0-9A-Fa-f][0-9A-Fa-f]$', c))): - die("Unexpected octet %s" % c); - aml.append(int(c, 16)); - -# Process aml bytecode array, decoding AML -def aml_pkglen_bytes(offset): - # PkgLength can be multibyte. Bits 8-7 give the # of extra bytes. - pkglenbytes = aml[offset] >> 6; - return pkglenbytes + 1 - -def aml_pkglen(offset): - pkgstart = offset - pkglenbytes = aml_pkglen_bytes(offset) - pkglen = aml[offset] & 0x3F - # If multibyte, first nibble only uses bits 0-3 - if ((pkglenbytes > 0) and (pkglen & 0x30)): - die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" % - (pkglen, pkglen)) - offset += 1 - pkglenbytes -= 1 - for i in range(pkglenbytes): - pkglen |= aml[offset + i] << (i * 8 + 4) - if (len(aml) < pkgstart + pkglen): - die("PckgLen 0x%x at offset 0x%x exceeds AML size 0x%x" % - (pkglen, offset, len(aml))) - return pkglen - -# Given method offset, find its NameString offset -def aml_method_string(offset): - #0x14 MethodOp PkgLength NameString MethodFlags TermList - if (aml[offset] != 0x14): - die( "Method offset 0x%x: expected 0x14 actual 0x%x" % - (offset, aml[offset])); - offset += 1; - pkglenbytes = aml_pkglen_bytes(offset) - offset += pkglenbytes; - return offset; - -# Given name offset, find its NameString offset -def aml_name_string(offset): - #0x08 NameOp NameString DataRef - if (aml[offset] != 0x08): - die( "Name offset 0x%x: expected 0x08 actual 0x%x" % - (offset, aml[offset])); - offset += 1 - # Block Name Modifier. Skip it. - if (aml[offset] == 0x5c or aml[offset] == 0x5e): - offset += 1 - return offset; - -# Given data offset, find dword const offset -def aml_data_dword_const(offset): - #0x08 NameOp NameString DataRef - if (aml[offset] != 0x0C): - die( "Name offset 0x%x: expected 0x0C actual 0x%x" % - (offset, aml[offset])); - return offset + 1; - -# Given data offset, find word const offset -def aml_data_word_const(offset): - #0x08 NameOp NameString DataRef - if (aml[offset] != 0x0B): - die( "Name offset 0x%x: expected 0x0B actual 0x%x" % - (offset, aml[offset])); - return offset + 1; - -# Given data offset, find byte const offset -def aml_data_byte_const(offset): - #0x08 NameOp NameString DataRef - if (aml[offset] != 0x0A): - die( "Name offset 0x%x: expected 0x0A actual 0x%x" % - (offset, aml[offset])); - return offset + 1; - -# Given name offset, find dword const offset -def aml_name_dword_const(offset): - return aml_data_dword_const(aml_name_string(offset) + 4) - -# Given name offset, find word const offset -def aml_name_word_const(offset): - return aml_data_word_const(aml_name_string(offset) + 4) - -# Given name offset, find byte const offset -def aml_name_byte_const(offset): - return aml_data_byte_const(aml_name_string(offset) + 4) - -def aml_processor_start(offset): - #0x5B 0x83 ProcessorOp PkgLength NameString ProcID - if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)): - die( "Name offset 0x%x: expected 0x5B 0x83 actual 0x%x 0x%x" % - (offset, aml[offset], aml[offset + 1])); - return offset - -def aml_processor_string(offset): - #0x5B 0x83 ProcessorOp PkgLength NameString ProcID - start = aml_processor_start(offset) - offset += 2 - pkglenbytes = aml_pkglen_bytes(offset) - offset += pkglenbytes - return offset - -def aml_processor_end(offset): - start = aml_processor_start(offset) - offset += 2 - pkglenbytes = aml_pkglen_bytes(offset) - pkglen = aml_pkglen(offset) - return offset + pkglen - -def aml_package_start(offset): - offset = aml_name_string(offset) + 4 - # 0x12 PkgLength NumElements PackageElementList - if (aml[offset] != 0x12): - die( "Name offset 0x%x: expected 0x12 actual 0x%x" % - (offset, aml[offset])); - offset += 1 - return offset + aml_pkglen_bytes(offset) + 1 - -lineno = 0 -for line in fileinput.input(): - # Strip trailing newline - line = line.rstrip(); - # line number and debug string to output in case of errors - lineno = lineno + 1 - debug = "input line %d: %s" % (lineno, line) - #ASL listing: space, then line#, then ...., then code - pasl = re.compile('^\s+([0-9]+)\.\.\.\.\s*') - m = pasl.search(line) - if (m): - add_asl(lineno, pasl.sub("", line)); - # AML listing: offset in hex, then ...., then code - paml = re.compile('^([0-9A-Fa-f]+)\.\.\.\.\s*') - m = paml.search(line) - if (m): - add_aml(m.group(1), paml.sub("", line)) - -# Now go over code -# Track AML offset of a previous non-empty ASL command -prev_aml_offset = -1 -for i in range(len(asl)): - debug = "input line %d: %s" % (asl[i].lineno, asl[i].line) - - l = asl[i].line - - # skip if not an extract directive - a = len(re.findall(r'ACPI_EXTRACT', l)) - if (not a): - # If not empty, store AML offset. Will be used for sanity checks - # IASL seems to put {}. at random places in the listing. - # Ignore any non-words for the purpose of this test. - m = re.search(r'\w+', l) - if (m): - prev_aml_offset = asl[i].aml_offset - continue - - if (a > 1): - die("Expected at most one ACPI_EXTRACT per line, actual %d" % a) - - mext = re.search(r''' - ^\s* # leading whitespace - /\*\s* # start C comment - (ACPI_EXTRACT_\w+) # directive: group(1) - \s+ # whitspace separates directive from array name - (\w+) # array name: group(2) - \s*\*/ # end of C comment - \s*$ # trailing whitespace - ''', l, re.VERBOSE) - if (not mext): - die("Stray ACPI_EXTRACT in input") - - # previous command must have produced some AML, - # otherwise we are in a middle of a block - if (prev_aml_offset == asl[i].aml_offset): - die("ACPI_EXTRACT directive in the middle of a block") - - directive = mext.group(1) - array = mext.group(2) - offset = asl[i].aml_offset - - if (directive == "ACPI_EXTRACT_ALL_CODE"): - if array in output: - die("%s directive used more than once" % directive) - output[array] = aml - continue - if (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"): - offset = aml_name_dword_const(offset) - elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"): - offset = aml_name_word_const(offset) - elif (directive == "ACPI_EXTRACT_NAME_BYTE_CONST"): - offset = aml_name_byte_const(offset) - elif (directive == "ACPI_EXTRACT_NAME_STRING"): - offset = aml_name_string(offset) - elif (directive == "ACPI_EXTRACT_METHOD_STRING"): - offset = aml_method_string(offset) - elif (directive == "ACPI_EXTRACT_PROCESSOR_START"): - offset = aml_processor_start(offset) - elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"): - offset = aml_processor_string(offset) - elif (directive == "ACPI_EXTRACT_PROCESSOR_END"): - offset = aml_processor_end(offset) - elif (directive == "ACPI_EXTRACT_PKG_START"): - offset = aml_package_start(offset) - else: - die("Unsupported directive %s" % directive) - - if array not in output: - output[array] = [] - output[array].append(offset) - -debug = "at end of file" - -def get_value_type(maxvalue): - #Use type large enough to fit the table - if (maxvalue >= 0x10000): - return "int" - elif (maxvalue >= 0x100): - return "short" - else: - return "char" - -# Pretty print output -for array in output.keys(): - otype = get_value_type(max(output[array])) - odata = [] - for value in output[array]: - odata.append("0x%x" % value) - sys.stdout.write("static unsigned %s %s[] = {\n" % (otype, array)) - sys.stdout.write(",\n".join(odata)) - sys.stdout.write('\n};\n'); diff -Nru seabios-1.7.1/tools/buildrom.py seabios-1.7.4/tools/buildrom.py --- seabios-1.7.1/tools/buildrom.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/buildrom.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# Fill in checksum/size of an option rom, and pad it to proper length. -# -# Copyright (C) 2009 Kevin O'Connor -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -import sys - -def alignpos(pos, alignbytes): - mask = alignbytes - 1 - return (pos + mask) & ~mask - -def checksum(data): - ords = map(ord, data) - return sum(ords) - -def main(): - inname = sys.argv[1] - outname = sys.argv[2] - - # Read data in - f = open(inname, 'rb') - data = f.read() - count = len(data) - - # Pad to a 512 byte boundary - data += "\0" * (alignpos(count, 512) - count) - count = len(data) - - # Check if a pci header is present - pcidata = ord(data[24:25]) + (ord(data[25:26]) << 8) - if pcidata != 0: - data = data[:pcidata + 16] + chr(count/512) + chr(0) + data[pcidata + 18:] - - # Fill in size field; clear checksum field - data = data[:2] + chr(count/512) + data[3:6] + "\0" + data[7:] - - # Checksum rom - newsum = (256 - checksum(data)) & 0xff - data = data[:6] + chr(newsum) + data[7:] - - # Write new rom - f = open(outname, 'wb') - f.write(data) - -if __name__ == '__main__': - main() diff -Nru seabios-1.7.1/tools/buildversion.sh seabios-1.7.4/tools/buildversion.sh --- seabios-1.7.1/tools/buildversion.sh 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/buildversion.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#!/bin/sh -# Script to generate a C file with version information. -OUTFILE="$1" -VAR16MODE="$2" - -# Extract version info -if [ -d .git ]; then - VERSION="`git describe --tags --long --dirty`" -elif [ -f .version ]; then - VERSION="`cat .version`" -else - VERSION="?" -fi -VERSION="${VERSION}-`date +"%Y%m%d_%H%M%S"`-`hostname`" -echo "Version: ${VERSION}" - -# Build header file -if [ "$VAR16MODE" = "VAR16" ]; then - cat > ${OUTFILE} < ${OUTFILE} < -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -import sys -import layoutrom - -def main(): - # Get args - objinfo, rawfile, outfile = sys.argv[1:] - - # Read in symbols - objinfofile = open(objinfo, 'rb') - symbols = layoutrom.parseObjDump(objinfofile, 'in')[1] - - # Read in raw file - f = open(rawfile, 'rb') - rawdata = f.read() - f.close() - datasize = len(rawdata) - finalsize = 64*1024 - if datasize > 64*1024: - finalsize = 128*1024 - if datasize > 128*1024: - finalsize = 256*1024 - - # Sanity checks - start = symbols['code32flat_start'].offset - end = symbols['code32flat_end'].offset - expend = layoutrom.BUILD_BIOS_ADDR + layoutrom.BUILD_BIOS_SIZE - if end != expend: - print "Error! Code does not end at 0x%x (got 0x%x)" % ( - expend, end) - sys.exit(1) - if datasize > finalsize: - print "Error! Code is too big (0x%x vs 0x%x)" % ( - datasize, finalsize) - sys.exit(1) - expdatasize = end - start - if datasize != expdatasize: - print "Error! Unknown extra data (0x%x vs 0x%x)" % ( - datasize, expdatasize) - sys.exit(1) - - # Print statistics - runtimesize = datasize - if '_reloc_abs_start' in symbols: - runtimesize = end - symbols['code32init_end'].offset - print "Total size: %d Fixed: %d Free: %d (used %.1f%% of %dKiB rom)" % ( - datasize, runtimesize, finalsize - datasize - , (datasize / float(finalsize)) * 100.0 - , finalsize / 1024) - - # Write final file - f = open(outfile, 'wb') - f.write(("\0" * (finalsize - datasize)) + rawdata) - f.close() - -if __name__ == '__main__': - main() diff -Nru seabios-1.7.1/tools/checkstack.py seabios-1.7.4/tools/checkstack.py --- seabios-1.7.1/tools/checkstack.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/checkstack.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,225 +0,0 @@ -#!/usr/bin/env python -# Script that tries to find how much stack space each function in an -# object is using. -# -# Copyright (C) 2008 Kevin O'Connor -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -# Usage: -# objdump -m i386 -M i8086 -M suffix -d out/rom16.o | tools/checkstack.py - -import sys -import re - -# Functions that change stacks -STACKHOP = ['stack_hop', 'stack_hop_back'] -# List of functions we can assume are never called. -#IGNORE = ['panic', '__dprintf'] -IGNORE = ['panic'] - -OUTPUTDESC = """ -#funcname1[preamble_stack_usage,max_usage_with_callers]: -# insn_addr:called_function [usage_at_call_point+caller_preamble,total_usage] -# -#funcname2[p,m,max_usage_to_yield_point]: -# insn_addr:called_function [u+c,t,usage_to_yield_point] -""" - -# Find out maximum stack usage for a function -def calcmaxstack(funcs, funcaddr): - info = funcs[funcaddr] - # Find max of all nested calls. - maxusage = info[1] - maxyieldusage = doesyield = 0 - if info[3] is not None: - maxyieldusage = info[3] - doesyield = 1 - info[2] = maxusage - info[4] = info[3] - seenbefore = {} - totcalls = 0 - for insnaddr, calladdr, usage in info[6]: - callinfo = funcs.get(calladdr) - if callinfo is None: - continue - if callinfo[2] is None: - calcmaxstack(funcs, calladdr) - if callinfo[0] not in seenbefore: - seenbefore[callinfo[0]] = 1 - totcalls += 1 + callinfo[5] - funcnameroot = callinfo[0].split('.')[0] - if funcnameroot in IGNORE: - # This called function is ignored - don't contribute it to - # the max stack. - continue - if funcnameroot in STACKHOP: - if usage > maxusage: - maxusage = usage - if callinfo[4] is not None: - doesyield = 1 - if usage > maxyieldusage: - maxyieldusage = usage - continue - totusage = usage + callinfo[2] - if totusage > maxusage: - maxusage = totusage - if callinfo[4] is not None: - doesyield = 1 - totyieldusage = usage + callinfo[4] - if totyieldusage > maxyieldusage: - maxyieldusage = totyieldusage - info[2] = maxusage - if doesyield: - info[4] = maxyieldusage - info[5] = totcalls - -# Try to arrange output so that functions that call each other are -# near each other. -def orderfuncs(funcaddrs, availfuncs): - l = [(availfuncs[funcaddr][5], availfuncs[funcaddr][0], funcaddr) - for funcaddr in funcaddrs if funcaddr in availfuncs] - l.sort() - l.reverse() - out = [] - while l: - count, name, funcaddr = l.pop(0) - if funcaddr not in availfuncs: - continue - calladdrs = [calls[1] for calls in availfuncs[funcaddr][6]] - del availfuncs[funcaddr] - out = out + orderfuncs(calladdrs, availfuncs) + [funcaddr] - return out - -# Update function info with a found "yield" point. -def noteYield(info, stackusage): - prevyield = info[3] - if prevyield is None or prevyield < stackusage: - info[3] = stackusage - -# Update function info with a found "call" point. -def noteCall(info, subfuncs, insnaddr, calladdr, stackusage): - if (calladdr, stackusage) in subfuncs: - # Already noted a nearly identical call - ignore this one. - return - info[6].append((insnaddr, calladdr, stackusage)) - subfuncs[(calladdr, stackusage)] = 1 - -hex_s = r'[0-9a-f]+' -re_func = re.compile(r'^(?P' + hex_s + r') <(?P.*)>:$') -re_asm = re.compile( - r'^[ ]*(?P' + hex_s - + r'):\t.*\t(addr32 )?(?P.+?)[ ]*((?P' + hex_s - + r') <(?P.*)>)?$') -re_usestack = re.compile( - r'^(push[f]?[lw])|(sub.* [$](?P0x' + hex_s + r'),%esp)$') - -def calc(): - # funcs[funcaddr] = [funcname, basicstackusage, maxstackusage - # , yieldusage, maxyieldusage, totalcalls - # , [(insnaddr, calladdr, stackusage), ...]] - funcs = {-1: ['', 0, 0, None, None, 0, []]} - cur = None - atstart = 0 - stackusage = 0 - - # Parse input lines - for line in sys.stdin.readlines(): - m = re_func.match(line) - if m is not None: - # Found function - funcaddr = int(m.group('funcaddr'), 16) - funcs[funcaddr] = cur = [m.group('func'), 0, None, None, None, 0, []] - stackusage = 0 - atstart = 1 - subfuncs = {} - continue - m = re_asm.match(line) - if m is not None: - insn = m.group('insn') - - im = re_usestack.match(insn) - if im is not None: - if insn.startswith('pushl') or insn.startswith('pushfl'): - stackusage += 4 - continue - elif insn.startswith('pushw') or insn.startswith('pushfw'): - stackusage += 2 - continue - stackusage += int(im.group('num'), 16) - - if atstart: - if '%esp' in insn or insn.startswith('leal'): - # Still part of initial header - continue - cur[1] = stackusage - atstart = 0 - - insnaddr = m.group('insnaddr') - calladdr = m.group('calladdr') - if calladdr is None: - if insn.startswith('lcallw'): - noteCall(cur, subfuncs, insnaddr, -1, stackusage + 4) - noteYield(cur, stackusage + 4) - elif insn.startswith('int'): - noteCall(cur, subfuncs, insnaddr, -1, stackusage + 6) - noteYield(cur, stackusage + 6) - elif insn.startswith('sti'): - noteYield(cur, stackusage) - else: - # misc instruction - continue - else: - # Jump or call insn - calladdr = int(calladdr, 16) - ref = m.group('ref') - if '+' in ref: - # Inter-function jump. - pass - elif insn.startswith('j'): - # Tail call - noteCall(cur, subfuncs, insnaddr, calladdr, 0) - elif insn.startswith('calll'): - noteCall(cur, subfuncs, insnaddr, calladdr, stackusage + 4) - else: - print "unknown call", ref - noteCall(cur, subfuncs, insnaddr, calladdr, stackusage) - # Reset stack usage to preamble usage - stackusage = cur[1] - - #print "other", repr(line) - - # Calculate maxstackusage - for funcaddr, info in funcs.items(): - if info[2] is not None: - continue - calcmaxstack(funcs, funcaddr) - - # Sort functions for output - funcaddrs = orderfuncs(funcs.keys(), funcs.copy()) - - # Show all functions - print OUTPUTDESC - for funcaddr in funcaddrs: - name, basicusage, maxusage, yieldusage, maxyieldusage, count, calls = \ - funcs[funcaddr] - if maxusage == 0 and maxyieldusage is None: - continue - yieldstr = "" - if maxyieldusage is not None: - yieldstr = ",%d" % maxyieldusage - print "\n%s[%d,%d%s]:" % (name, basicusage, maxusage, yieldstr) - for insnaddr, calladdr, stackusage in calls: - callinfo = funcs.get(calladdr, ("", 0, 0, 0, None)) - yieldstr = "" - if callinfo[4] is not None: - yieldstr = ",%d" % (stackusage + callinfo[4]) - print " %04s:%-40s [%d+%d,%d%s]" % ( - insnaddr, callinfo[0], stackusage, callinfo[1] - , stackusage+callinfo[2], yieldstr) - -def main(): - calc() - -if __name__ == '__main__': - main() diff -Nru seabios-1.7.1/tools/checksum.py seabios-1.7.4/tools/checksum.py --- seabios-1.7.1/tools/checksum.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/checksum.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#!/usr/bin/env python -# Script to report the checksum of a file. -# -# Copyright (C) 2009 Kevin O'Connor -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -import sys - -def main(): - data = sys.stdin.read() - ords = map(ord, data) - print "sum=%x\n" % sum(ords) - -if __name__ == '__main__': - main() diff -Nru seabios-1.7.1/tools/encodeint.py seabios-1.7.4/tools/encodeint.py --- seabios-1.7.1/tools/encodeint.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/encodeint.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#!/usr/bin/env python -# Encode an integer in little endian format in a file. -# -# Copyright (C) 2011 Kevin O'Connor -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -import sys -import struct - -def main(): - filename = sys.argv[1] - value = int(sys.argv[2]) - - outval = struct.pack(' "$OUTFILE" </{s:->#\(.*\):/* \1 */:; \ - s:^->\([^ ]*\) [\$\#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:->::; p;}" < "$INFILE" >> "$OUTFILE" -cat >> "$OUTFILE" < /dev/null 2>&1 << EOF -#include -int main() -{ - gettext(""); - return 0; -} -EOF -if [ ! "$?" -eq "0" ]; then - echo -DKBUILD_NO_NLS; -fi - diff -Nru seabios-1.7.1/tools/kconfig/conf.c seabios-1.7.4/tools/kconfig/conf.c --- seabios-1.7.1/tools/kconfig/conf.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/conf.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,654 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -static void conf(struct menu *menu); -static void check_conf(struct menu *menu); - -enum input_mode { - oldaskconfig, - silentoldconfig, - oldconfig, - allnoconfig, - allyesconfig, - allmodconfig, - alldefconfig, - randconfig, - defconfig, - savedefconfig, - listnewconfig, - oldnoconfig, -} input_mode = oldaskconfig; - -char *defconfig_file; - -static int indent = 1; -static int valid_stdin = 1; -static int sync_kconfig; -static int conf_cnt; -static char line[128]; -static struct menu *rootEntry; - -static void print_help(struct menu *menu) -{ - struct gstr help = str_new(); - - menu_get_ext_help(menu, &help); - - printf("\n%s\n", str_get(&help)); - str_free(&help); -} - -static void strip(char *str) -{ - char *p = str; - int l; - - while ((isspace(*p))) - p++; - l = strlen(p); - if (p != str) - memmove(str, p, l + 1); - if (!l) - return; - p = str + l - 1; - while ((isspace(*p))) - *p-- = 0; -} - -static void check_stdin(void) -{ - if (!valid_stdin) { - printf(_("aborted!\n\n")); - printf(_("Console input/output is redirected. ")); - printf(_("Run 'make oldconfig' to update configuration.\n\n")); - exit(1); - } -} - -static int conf_askvalue(struct symbol *sym, const char *def) -{ - enum symbol_type type = sym_get_type(sym); - - if (!sym_has_value(sym)) - printf(_("(NEW) ")); - - line[0] = '\n'; - line[1] = 0; - - if (!sym_is_changable(sym)) { - printf("%s\n", def); - line[0] = '\n'; - line[1] = 0; - return 0; - } - - switch (input_mode) { - case oldconfig: - case silentoldconfig: - if (sym_has_value(sym)) { - printf("%s\n", def); - return 0; - } - check_stdin(); - case oldaskconfig: - fflush(stdout); - xfgets(line, 128, stdin); - return 1; - default: - break; - } - - switch (type) { - case S_INT: - case S_HEX: - case S_STRING: - printf("%s\n", def); - return 1; - default: - ; - } - printf("%s", line); - return 1; -} - -static int conf_string(struct menu *menu) -{ - struct symbol *sym = menu->sym; - const char *def; - - while (1) { - printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); - printf("(%s) ", sym->name); - def = sym_get_string_value(sym); - if (sym_get_string_value(sym)) - printf("[%s] ", def); - if (!conf_askvalue(sym, def)) - return 0; - switch (line[0]) { - case '\n': - break; - case '?': - /* print help */ - if (line[1] == '\n') { - print_help(menu); - def = NULL; - break; - } - default: - line[strlen(line)-1] = 0; - def = line; - } - if (def && sym_set_string_value(sym, def)) - return 0; - } -} - -static int conf_sym(struct menu *menu) -{ - struct symbol *sym = menu->sym; - tristate oldval, newval; - - while (1) { - printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); - if (sym->name) - printf("(%s) ", sym->name); - putchar('['); - oldval = sym_get_tristate_value(sym); - switch (oldval) { - case no: - putchar('N'); - break; - case mod: - putchar('M'); - break; - case yes: - putchar('Y'); - break; - } - if (oldval != no && sym_tristate_within_range(sym, no)) - printf("/n"); - if (oldval != mod && sym_tristate_within_range(sym, mod)) - printf("/m"); - if (oldval != yes && sym_tristate_within_range(sym, yes)) - printf("/y"); - if (menu_has_help(menu)) - printf("/?"); - printf("] "); - if (!conf_askvalue(sym, sym_get_string_value(sym))) - return 0; - strip(line); - - switch (line[0]) { - case 'n': - case 'N': - newval = no; - if (!line[1] || !strcmp(&line[1], "o")) - break; - continue; - case 'm': - case 'M': - newval = mod; - if (!line[1]) - break; - continue; - case 'y': - case 'Y': - newval = yes; - if (!line[1] || !strcmp(&line[1], "es")) - break; - continue; - case 0: - newval = oldval; - break; - case '?': - goto help; - default: - continue; - } - if (sym_set_tristate_value(sym, newval)) - return 0; -help: - print_help(menu); - } -} - -static int conf_choice(struct menu *menu) -{ - struct symbol *sym, *def_sym; - struct menu *child; - bool is_new; - - sym = menu->sym; - is_new = !sym_has_value(sym); - if (sym_is_changable(sym)) { - conf_sym(menu); - sym_calc_value(sym); - switch (sym_get_tristate_value(sym)) { - case no: - return 1; - case mod: - return 0; - case yes: - break; - } - } else { - switch (sym_get_tristate_value(sym)) { - case no: - return 1; - case mod: - printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); - return 0; - case yes: - break; - } - } - - while (1) { - int cnt, def; - - printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); - def_sym = sym_get_choice_value(sym); - cnt = def = 0; - line[0] = 0; - for (child = menu->list; child; child = child->next) { - if (!menu_is_visible(child)) - continue; - if (!child->sym) { - printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); - continue; - } - cnt++; - if (child->sym == def_sym) { - def = cnt; - printf("%*c", indent, '>'); - } else - printf("%*c", indent, ' '); - printf(" %d. %s", cnt, _(menu_get_prompt(child))); - if (child->sym->name) - printf(" (%s)", child->sym->name); - if (!sym_has_value(child->sym)) - printf(_(" (NEW)")); - printf("\n"); - } - printf(_("%*schoice"), indent - 1, ""); - if (cnt == 1) { - printf("[1]: 1\n"); - goto conf_childs; - } - printf("[1-%d", cnt); - if (menu_has_help(menu)) - printf("?"); - printf("]: "); - switch (input_mode) { - case oldconfig: - case silentoldconfig: - if (!is_new) { - cnt = def; - printf("%d\n", cnt); - break; - } - check_stdin(); - case oldaskconfig: - fflush(stdout); - xfgets(line, 128, stdin); - strip(line); - if (line[0] == '?') { - print_help(menu); - continue; - } - if (!line[0]) - cnt = def; - else if (isdigit(line[0])) - cnt = atoi(line); - else - continue; - break; - default: - break; - } - - conf_childs: - for (child = menu->list; child; child = child->next) { - if (!child->sym || !menu_is_visible(child)) - continue; - if (!--cnt) - break; - } - if (!child) - continue; - if (line[strlen(line) - 1] == '?') { - print_help(child); - continue; - } - sym_set_choice_value(sym, child->sym); - for (child = child->list; child; child = child->next) { - indent += 2; - conf(child); - indent -= 2; - } - return 1; - } -} - -static void conf(struct menu *menu) -{ - struct symbol *sym; - struct property *prop; - struct menu *child; - - if (!menu_is_visible(menu)) - return; - - sym = menu->sym; - prop = menu->prompt; - if (prop) { - const char *prompt; - - switch (prop->type) { - case P_MENU: - if ((input_mode == silentoldconfig || - input_mode == listnewconfig || - input_mode == oldnoconfig) && - rootEntry != menu) { - check_conf(menu); - return; - } - case P_COMMENT: - prompt = menu_get_prompt(menu); - if (prompt) - printf("%*c\n%*c %s\n%*c\n", - indent, '*', - indent, '*', _(prompt), - indent, '*'); - default: - ; - } - } - - if (!sym) - goto conf_childs; - - if (sym_is_choice(sym)) { - conf_choice(menu); - if (sym->curr.tri != mod) - return; - goto conf_childs; - } - - switch (sym->type) { - case S_INT: - case S_HEX: - case S_STRING: - conf_string(menu); - break; - default: - conf_sym(menu); - break; - } - -conf_childs: - if (sym) - indent += 2; - for (child = menu->list; child; child = child->next) - conf(child); - if (sym) - indent -= 2; -} - -static void check_conf(struct menu *menu) -{ - struct symbol *sym; - struct menu *child; - - if (!menu_is_visible(menu)) - return; - - sym = menu->sym; - if (sym && !sym_has_value(sym)) { - if (sym_is_changable(sym) || - (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { - if (input_mode == listnewconfig) { - if (sym->name && !sym_is_choice_value(sym)) { - printf("%s%s\n", CONFIG_, sym->name); - } - } else if (input_mode != oldnoconfig) { - if (!conf_cnt++) - printf(_("*\n* Restart config...\n*\n")); - rootEntry = menu_get_parent_menu(menu); - conf(rootEntry); - } - } - } - - for (child = menu->list; child; child = child->next) - check_conf(child); -} - -static struct option long_opts[] = { - {"oldaskconfig", no_argument, NULL, oldaskconfig}, - {"oldconfig", no_argument, NULL, oldconfig}, - {"silentoldconfig", no_argument, NULL, silentoldconfig}, - {"defconfig", optional_argument, NULL, defconfig}, - {"savedefconfig", required_argument, NULL, savedefconfig}, - {"allnoconfig", no_argument, NULL, allnoconfig}, - {"allyesconfig", no_argument, NULL, allyesconfig}, - {"allmodconfig", no_argument, NULL, allmodconfig}, - {"alldefconfig", no_argument, NULL, alldefconfig}, - {"randconfig", no_argument, NULL, randconfig}, - {"listnewconfig", no_argument, NULL, listnewconfig}, - {"oldnoconfig", no_argument, NULL, oldnoconfig}, - {NULL, 0, NULL, 0} -}; - -int main(int ac, char **av) -{ - int opt; - const char *name; - struct stat tmpstat; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { - input_mode = (enum input_mode)opt; - switch (opt) { - case silentoldconfig: - sync_kconfig = 1; - break; - case defconfig: - case savedefconfig: - defconfig_file = optarg; - break; - case randconfig: - { - struct timeval now; - unsigned int seed; - - /* - * Use microseconds derived seed, - * compensate for systems where it may be zero - */ - gettimeofday(&now, NULL); - - seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); - srand(seed); - break; - } - case '?': - fprintf(stderr, _("See README for usage info\n")); - exit(1); - break; - } - } - if (ac == optind) { - printf(_("%s: Kconfig file missing\n"), av[0]); - exit(1); - } - name = av[optind]; - conf_parse(name); - //zconfdump(stdout); - if (sync_kconfig) { - name = conf_get_configname(); - if (stat(name, &tmpstat)) { - fprintf(stderr, _("***\n" - "*** Configuration file \"%s\" not found!\n" - "***\n" - "*** Please run some configurator (e.g. \"make oldconfig\" or\n" - "*** \"make menuconfig\" or \"make xconfig\").\n" - "***\n"), name); - exit(1); - } - } - - switch (input_mode) { - case defconfig: - if (!defconfig_file) - defconfig_file = conf_get_default_confname(); - if (conf_read(defconfig_file)) { - printf(_("***\n" - "*** Can't find default configuration \"%s\"!\n" - "***\n"), defconfig_file); - exit(1); - } - break; - case savedefconfig: - case silentoldconfig: - case oldaskconfig: - case oldconfig: - case listnewconfig: - case oldnoconfig: - conf_read(NULL); - break; - case allnoconfig: - case allyesconfig: - case allmodconfig: - case alldefconfig: - case randconfig: - name = getenv("KCONFIG_ALLCONFIG"); - if (name && !stat(name, &tmpstat)) { - conf_read_simple(name, S_DEF_USER); - break; - } - switch (input_mode) { - case allnoconfig: name = "allno.config"; break; - case allyesconfig: name = "allyes.config"; break; - case allmodconfig: name = "allmod.config"; break; - case alldefconfig: name = "alldef.config"; break; - case randconfig: name = "allrandom.config"; break; - default: break; - } - if (!stat(name, &tmpstat)) - conf_read_simple(name, S_DEF_USER); - else if (!stat("all.config", &tmpstat)) - conf_read_simple("all.config", S_DEF_USER); - break; - default: - break; - } - - if (sync_kconfig) { - if (conf_get_changed()) { - name = getenv("KCONFIG_NOSILENTUPDATE"); - if (name && *name) { - fprintf(stderr, - _("\n*** The configuration requires explicit update.\n\n")); - return 1; - } - } - valid_stdin = isatty(0) && isatty(1) && isatty(2); - } - - switch (input_mode) { - case allnoconfig: - conf_set_all_new_symbols(def_no); - break; - case allyesconfig: - conf_set_all_new_symbols(def_yes); - break; - case allmodconfig: - conf_set_all_new_symbols(def_mod); - break; - case alldefconfig: - conf_set_all_new_symbols(def_default); - break; - case randconfig: - conf_set_all_new_symbols(def_random); - break; - case defconfig: - conf_set_all_new_symbols(def_default); - break; - case savedefconfig: - break; - case oldaskconfig: - rootEntry = &rootmenu; - conf(&rootmenu); - input_mode = silentoldconfig; - /* fall through */ - case oldconfig: - case listnewconfig: - case oldnoconfig: - case silentoldconfig: - /* Update until a loop caused no more changes */ - do { - conf_cnt = 0; - check_conf(&rootmenu); - } while (conf_cnt && - (input_mode != listnewconfig && - input_mode != oldnoconfig)); - break; - } - - if (sync_kconfig) { - /* silentoldconfig is used during the build so we shall update autoconf. - * All other commands are only used to generate a config. - */ - if (conf_get_changed() && conf_write(NULL)) { - fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); - exit(1); - } - if (conf_write_autoconf()) { - fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); - return 1; - } - } else if (input_mode == savedefconfig) { - if (conf_write_defconfig(defconfig_file)) { - fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), - defconfig_file); - return 1; - } - } else if (input_mode != listnewconfig) { - if (conf_write(NULL)) { - fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); - exit(1); - } - } - return 0; -} -/* - * Helper function to facilitate fgets() by Jean Sacren. - */ -void xfgets(str, size, in) - char *str; - int size; - FILE *in; -{ - if (fgets(str, size, in) == NULL) - fprintf(stderr, "\nError in reading or end of file.\n"); -} diff -Nru seabios-1.7.1/tools/kconfig/confdata.c seabios-1.7.4/tools/kconfig/confdata.c --- seabios-1.7.1/tools/kconfig/confdata.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/confdata.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1062 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -static void conf_warning(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -static void conf_message(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -static const char *conf_filename; -static int conf_lineno, conf_warnings, conf_unsaved; - -const char conf_defname[] = "arch/$ARCH/defconfig"; - -static void conf_warning(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - conf_warnings++; -} - -static void conf_default_message_callback(const char *fmt, va_list ap) -{ - printf("#\n# "); - vprintf(fmt, ap); - printf("\n#\n"); -} - -static void (*conf_message_callback) (const char *fmt, va_list ap) = - conf_default_message_callback; -void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) -{ - conf_message_callback = fn; -} - -static void conf_message(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (conf_message_callback) - conf_message_callback(fmt, ap); -} - -const char *conf_get_configname(void) -{ - char *name = getenv("KCONFIG_CONFIG"); - - return name ? name : ".config"; -} - -const char *conf_get_autoconfig_name(void) -{ - char *name = getenv("KCONFIG_AUTOCONFIG"); - - return name ? name : "include/config/auto.conf"; -} - -static char *conf_expand_value(const char *in) -{ - struct symbol *sym; - const char *src; - static char res_value[SYMBOL_MAXLENGTH]; - char *dst, name[SYMBOL_MAXLENGTH]; - - res_value[0] = 0; - dst = name; - while ((src = strchr(in, '$'))) { - strncat(res_value, in, src - in); - src++; - dst = name; - while (isalnum(*src) || *src == '_') - *dst++ = *src++; - *dst = 0; - sym = sym_lookup(name, 0); - sym_calc_value(sym); - strcat(res_value, sym_get_string_value(sym)); - in = src; - } - strcat(res_value, in); - - return res_value; -} - -char *conf_get_default_confname(void) -{ - struct stat buf; - static char fullname[PATH_MAX+1]; - char *env, *name; - - name = conf_expand_value(conf_defname); - env = getenv(SRCTREE); - if (env) { - sprintf(fullname, "%s/%s", env, name); - if (!stat(fullname, &buf)) - return fullname; - } - return name; -} - -static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) -{ - char *p2; - - switch (sym->type) { - case S_TRISTATE: - if (p[0] == 'm') { - sym->def[def].tri = mod; - sym->flags |= def_flags; - break; - } - case S_BOOLEAN: - if (p[0] == 'y') { - sym->def[def].tri = yes; - sym->flags |= def_flags; - break; - } - if (p[0] == 'n') { - sym->def[def].tri = no; - sym->flags |= def_flags; - break; - } - conf_warning("symbol value '%s' invalid for %s", p, sym->name); - break; - case S_OTHER: - if (*p != '"') { - for (p2 = p; *p2 && !isspace(*p2); p2++) - ; - sym->type = S_STRING; - goto done; - } - case S_STRING: - if (*p++ != '"') - break; - for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { - if (*p2 == '"') { - *p2 = 0; - break; - } - memmove(p2, p2 + 1, strlen(p2)); - } - if (!p2) { - conf_warning("invalid string found"); - return 1; - } - case S_INT: - case S_HEX: - done: - if (sym_string_valid(sym, p)) { - sym->def[def].val = strdup(p); - sym->flags |= def_flags; - } else { - conf_warning("symbol value '%s' invalid for %s", p, sym->name); - return 1; - } - break; - default: - ; - } - return 0; -} - -int conf_read_simple(const char *name, int def) -{ - FILE *in = NULL; - char line[1024]; - char *p, *p2; - struct symbol *sym; - int i, def_flags; - - if (name) { - in = zconf_fopen(name); - } else { - struct property *prop; - - name = conf_get_configname(); - in = zconf_fopen(name); - if (in) - goto load; - sym_add_change_count(1); - if (!sym_defconfig_list) { - if (modules_sym) - sym_calc_value(modules_sym); - return 1; - } - - for_all_defaults(sym_defconfig_list, prop) { - if (expr_calc_value(prop->visible.expr) == no || - prop->expr->type != E_SYMBOL) - continue; - name = conf_expand_value(prop->expr->left.sym->name); - in = zconf_fopen(name); - if (in) { - conf_message(_("using defaults found in %s"), - name); - goto load; - } - } - } - if (!in) - return 1; - -load: - conf_filename = name; - conf_lineno = 0; - conf_warnings = 0; - conf_unsaved = 0; - - def_flags = SYMBOL_DEF << def; - for_all_symbols(i, sym) { - sym->flags |= SYMBOL_CHANGED; - sym->flags &= ~(def_flags|SYMBOL_VALID); - if (sym_is_choice(sym)) - sym->flags |= def_flags; - switch (sym->type) { - case S_INT: - case S_HEX: - case S_STRING: - if (sym->def[def].val) - free(sym->def[def].val); - default: - sym->def[def].val = NULL; - sym->def[def].tri = no; - } - } - - while (fgets(line, sizeof(line), in)) { - conf_lineno++; - sym = NULL; - if (line[0] == '#') { - if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) - continue; - p = strchr(line + 2 + strlen(CONFIG_), ' '); - if (!p) - continue; - *p++ = 0; - if (strncmp(p, "is not set", 10)) - continue; - if (def == S_DEF_USER) { - sym = sym_find(line + 2 + strlen(CONFIG_)); - if (!sym) { - sym_add_change_count(1); - goto setsym; - } - } else { - sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); - if (sym->type == S_UNKNOWN) - sym->type = S_BOOLEAN; - } - if (sym->flags & def_flags) { - conf_warning("override: reassigning to symbol %s", sym->name); - } - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - sym->def[def].tri = no; - sym->flags |= def_flags; - break; - default: - ; - } - } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { - p = strchr(line + strlen(CONFIG_), '='); - if (!p) - continue; - *p++ = 0; - p2 = strchr(p, '\n'); - if (p2) { - *p2-- = 0; - if (*p2 == '\r') - *p2 = 0; - } - if (def == S_DEF_USER) { - sym = sym_find(line + strlen(CONFIG_)); - if (!sym) { - sym_add_change_count(1); - goto setsym; - } - } else { - sym = sym_lookup(line + strlen(CONFIG_), 0); - if (sym->type == S_UNKNOWN) - sym->type = S_OTHER; - } - if (sym->flags & def_flags) { - conf_warning("override: reassigning to symbol %s", sym->name); - } - if (conf_set_sym_val(sym, def, def_flags, p)) - continue; - } else { - if (line[0] != '\r' && line[0] != '\n') - conf_warning("unexpected data"); - continue; - } -setsym: - if (sym && sym_is_choice_value(sym)) { - struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); - switch (sym->def[def].tri) { - case no: - break; - case mod: - if (cs->def[def].tri == yes) { - conf_warning("%s creates inconsistent choice state", sym->name); - cs->flags &= ~def_flags; - } - break; - case yes: - if (cs->def[def].tri != no) - conf_warning("override: %s changes choice state", sym->name); - cs->def[def].val = sym; - break; - } - cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); - } - } - fclose(in); - - if (modules_sym) - sym_calc_value(modules_sym); - return 0; -} - -int conf_read(const char *name) -{ - struct symbol *sym, *choice_sym; - struct property *prop; - struct expr *e; - int i, flags; - - sym_set_change_count(0); - - if (conf_read_simple(name, S_DEF_USER)) - return 1; - - for_all_symbols(i, sym) { - sym_calc_value(sym); - if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) - goto sym_ok; - if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { - /* check that calculated value agrees with saved value */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) - break; - if (!sym_is_choice(sym)) - goto sym_ok; - default: - if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) - goto sym_ok; - break; - } - } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) - /* no previous value and not saved */ - goto sym_ok; - conf_unsaved++; - /* maybe print value in verbose mode... */ - sym_ok: - if (!sym_is_choice(sym)) - continue; - /* The choice symbol only has a set value (and thus is not new) - * if all its visible childs have values. - */ - prop = sym_get_choice_prop(sym); - flags = sym->flags; - expr_list_for_each_sym(prop->expr, e, choice_sym) - if (choice_sym->visible != no) - flags &= choice_sym->flags; - sym->flags &= flags | ~SYMBOL_DEF_USER; - } - - for_all_symbols(i, sym) { - if (sym_has_value(sym) && !sym_is_choice_value(sym)) { - /* Reset values of generates values, so they'll appear - * as new, if they should become visible, but that - * doesn't quite work if the Kconfig and the saved - * configuration disagree. - */ - if (sym->visible == no && !conf_unsaved) - sym->flags &= ~SYMBOL_DEF_USER; - switch (sym->type) { - case S_STRING: - case S_INT: - case S_HEX: - /* Reset a string value if it's out of range */ - if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) - break; - sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); - conf_unsaved++; - break; - default: - break; - } - } - } - - sym_add_change_count(conf_warnings || conf_unsaved); - - return 0; -} - -/* Write a S_STRING */ -static void conf_write_string(bool headerfile, const char *name, - const char *str, FILE *out) -{ - int l; - if (headerfile) - fprintf(out, "#define %s%s \"", CONFIG_, name); - else - fprintf(out, "%s%s=\"", CONFIG_, name); - - while (1) { - l = strcspn(str, "\"\\"); - if (l) { - xfwrite(str, l, 1, out); - str += l; - } - if (!*str) - break; - fprintf(out, "\\%c", *str++); - } - fputs("\"\n", out); -} - -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) -{ - const char *str; - - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - if (write_no) - fprintf(out, "# %s%s is not set\n", - CONFIG_, sym->name); - break; - case mod: - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); - break; - case yes: - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); - break; - } - break; - case S_STRING: - conf_write_string(false, sym->name, sym_get_string_value(sym), out); - break; - case S_HEX: - case S_INT: - str = sym_get_string_value(sym); - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); - break; - case S_OTHER: - case S_UNKNOWN: - break; - } -} - -/* - * Write out a minimal config. - * All values that has default values are skipped as this is redundant. - */ -int conf_write_defconfig(const char *filename) -{ - struct symbol *sym; - struct menu *menu; - FILE *out; - - out = fopen(filename, "w"); - if (!out) - return 1; - - sym_clear_all_valid(); - - /* Traverse all menus to find all relevant symbols */ - menu = rootmenu.list; - - while (menu != NULL) - { - sym = menu->sym; - if (sym == NULL) { - if (!menu_is_visible(menu)) - goto next_menu; - } else if (!sym_is_choice(sym)) { - sym_calc_value(sym); - if (!(sym->flags & SYMBOL_WRITE)) - goto next_menu; - sym->flags &= ~SYMBOL_WRITE; - /* If we cannot change the symbol - skip */ - if (!sym_is_changable(sym)) - goto next_menu; - /* If symbol equals to default value - skip */ - if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) - goto next_menu; - - /* - * If symbol is a choice value and equals to the - * default for a choice - skip. - * But only if value is bool and equal to "y" and - * choice is not "optional". - * (If choice is "optional" then all values can be "n") - */ - if (sym_is_choice_value(sym)) { - struct symbol *cs; - struct symbol *ds; - - cs = prop_get_symbol(sym_get_choice_prop(sym)); - ds = sym_choice_default(cs); - if (!sym_is_optional(cs) && sym == ds) { - if ((sym->type == S_BOOLEAN) && - sym_get_tristate_value(sym) == yes) - goto next_menu; - } - } - conf_write_symbol(sym, out, true); - } -next_menu: - if (menu->list != NULL) { - menu = menu->list; - } - else if (menu->next != NULL) { - menu = menu->next; - } else { - while ((menu = menu->parent)) { - if (menu->next != NULL) { - menu = menu->next; - break; - } - } - } - } - fclose(out); - return 0; -} - -int conf_write(const char *name) -{ - FILE *out; - struct symbol *sym; - struct menu *menu; - const char *basename; - const char *str; - char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; - time_t now; - int use_timestamp = 1; - char *env; - - dirname[0] = 0; - if (name && name[0]) { - struct stat st; - char *slash; - - if (!stat(name, &st) && S_ISDIR(st.st_mode)) { - strcpy(dirname, name); - strcat(dirname, "/"); - basename = conf_get_configname(); - } else if ((slash = strrchr(name, '/'))) { - int size = slash - name + 1; - memcpy(dirname, name, size); - dirname[size] = 0; - if (slash[1]) - basename = slash + 1; - else - basename = conf_get_configname(); - } else - basename = name; - } else - basename = conf_get_configname(); - - sprintf(newname, "%s%s", dirname, basename); - env = getenv("KCONFIG_OVERWRITECONFIG"); - if (!env || !*env) { - sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); - out = fopen(tmpname, "w"); - } else { - *tmpname = 0; - out = fopen(newname, "w"); - } - if (!out) - return 1; - - time(&now); - env = getenv("KCONFIG_NOTIMESTAMP"); - if (env && *env) - use_timestamp = 0; - - fprintf(out, _("#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "%s%s" - "#\n"), - rootmenu.prompt->text, - use_timestamp ? "# " : "", - use_timestamp ? ctime(&now) : ""); - - if (!conf_get_changed()) - sym_clear_all_valid(); - - menu = rootmenu.list; - while (menu) { - sym = menu->sym; - if (!sym) { - if (!menu_is_visible(menu)) - goto next; - str = menu_get_prompt(menu); - fprintf(out, "\n" - "#\n" - "# %s\n" - "#\n", str); - } else if (!(sym->flags & SYMBOL_CHOICE)) { - sym_calc_value(sym); - if (!(sym->flags & SYMBOL_WRITE)) - goto next; - sym->flags &= ~SYMBOL_WRITE; - /* Write config symbol to file */ - conf_write_symbol(sym, out, true); - } - -next: - if (menu->list) { - menu = menu->list; - continue; - } - if (menu->next) - menu = menu->next; - else while ((menu = menu->parent)) { - if (menu->next) { - menu = menu->next; - break; - } - } - } - fclose(out); - - if (*tmpname) { - strcat(dirname, basename); - strcat(dirname, ".old"); - rename(newname, dirname); - if (rename(tmpname, newname)) - return 1; - } - - conf_message(_("configuration written to %s"), newname); - - sym_set_change_count(0); - - return 0; -} - -static int conf_split_config(void) -{ - const char *name; - char path[PATH_MAX+1]; - char *s, *d, c; - struct symbol *sym; - struct stat sb; - int res, i, fd; - - name = conf_get_autoconfig_name(); - conf_read_simple(name, S_DEF_AUTO); - - if (chdir("include/config")) - return 1; - - res = 0; - for_all_symbols(i, sym) { - sym_calc_value(sym); - if ((sym->flags & SYMBOL_AUTO) || !sym->name) - continue; - if (sym->flags & SYMBOL_WRITE) { - if (sym->flags & SYMBOL_DEF_AUTO) { - /* - * symbol has old and new value, - * so compare them... - */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - if (sym_get_tristate_value(sym) == - sym->def[S_DEF_AUTO].tri) - continue; - break; - case S_STRING: - case S_HEX: - case S_INT: - if (!strcmp(sym_get_string_value(sym), - sym->def[S_DEF_AUTO].val)) - continue; - break; - default: - break; - } - } else { - /* - * If there is no old value, only 'no' (unset) - * is allowed as new value. - */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - if (sym_get_tristate_value(sym) == no) - continue; - break; - default: - break; - } - } - } else if (!(sym->flags & SYMBOL_DEF_AUTO)) - /* There is neither an old nor a new value. */ - continue; - /* else - * There is an old value, but no new value ('no' (unset) - * isn't saved in auto.conf, so the old value is always - * different from 'no'). - */ - - /* Replace all '_' and append ".h" */ - s = sym->name; - d = path; - while ((c = *s++)) { - c = tolower(c); - *d++ = (c == '_') ? '/' : c; - } - strcpy(d, ".h"); - - /* Assume directory path already exists. */ - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - if (errno != ENOENT) { - res = 1; - break; - } - /* - * Create directory components, - * unless they exist already. - */ - d = path; - while ((d = strchr(d, '/'))) { - *d = 0; - if (stat(path, &sb) && mkdir(path, 0755)) { - res = 1; - goto out; - } - *d++ = '/'; - } - /* Try it again. */ - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - res = 1; - break; - } - } - close(fd); - } -out: - if (chdir("../..")) - return 1; - - return res; -} - -int conf_write_autoconf(void) -{ - struct symbol *sym; - const char *str; - const char *name; - FILE *out, *tristate, *out_h; - time_t now; - int i; - - sym_clear_all_valid(); - - file_write_dep("include/config/auto.conf.cmd"); - - if (conf_split_config()) - return 1; - - out = fopen(".tmpconfig", "w"); - if (!out) - return 1; - - tristate = fopen(".tmpconfig_tristate", "w"); - if (!tristate) { - fclose(out); - return 1; - } - - out_h = fopen(".tmpconfig.h", "w"); - if (!out_h) { - fclose(out); - fclose(tristate); - return 1; - } - - time(&now); - fprintf(out, "#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "# %s" - "#\n", - rootmenu.prompt->text, ctime(&now)); - fprintf(tristate, "#\n" - "# Automatically generated - do not edit\n" - "\n"); - fprintf(out_h, "/*\n" - " * Automatically generated C config: don't edit\n" - " * %s\n" - " * %s" - " */\n", - rootmenu.prompt->text, ctime(&now)); - - for_all_symbols(i, sym) { - sym_calc_value(sym); - if (!sym->name) - continue; - if (!(sym->flags & SYMBOL_WRITE)) { - if (sym->type == S_BOOLEAN || sym->type == S_HEX - || sym->type == S_INT) - fprintf(out_h, "#define %s%s 0\n", - CONFIG_, sym->name); - continue; - } - - /* write symbol to config file */ - conf_write_symbol(sym, out, false); - - /* update autoconf and tristate files */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - fprintf(out_h, "#define %s%s 0\n", - CONFIG_, sym->name); - break; - case mod: - fprintf(tristate, "%s%s=M\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s_MODULE 1\n", - CONFIG_, sym->name); - break; - case yes: - if (sym->type == S_TRISTATE) - fprintf(tristate,"%s%s=Y\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s 1\n", - CONFIG_, sym->name); - break; - } - break; - case S_STRING: - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); - break; - case S_HEX: - str = sym_get_string_value(sym); - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out_h, "#define %s%s 0x%s\n", - CONFIG_, sym->name, str); - break; - } - case S_INT: - str = sym_get_string_value(sym); - fprintf(out_h, "#define %s%s %s\n", - CONFIG_, sym->name, str); - break; - default: - break; - } - } - fclose(out); - fclose(tristate); - fclose(out_h); - - name = getenv("KCONFIG_AUTOHEADER"); - if (!name) - name = "include/generated/autoconf.h"; - if (rename(".tmpconfig.h", name)) - return 1; - name = getenv("KCONFIG_TRISTATE"); - if (!name) - name = "include/config/tristate.conf"; - if (rename(".tmpconfig_tristate", name)) - return 1; - name = conf_get_autoconfig_name(); - /* - * This must be the last step, kbuild has a dependency on auto.conf - * and this marks the successful completion of the previous steps. - */ - if (rename(".tmpconfig", name)) - return 1; - - return 0; -} - -static int sym_change_count; -static void (*conf_changed_callback)(void); - -void sym_set_change_count(int count) -{ - int _sym_change_count = sym_change_count; - sym_change_count = count; - if (conf_changed_callback && - (bool)_sym_change_count != (bool)count) - conf_changed_callback(); -} - -void sym_add_change_count(int count) -{ - sym_set_change_count(count + sym_change_count); -} - -bool conf_get_changed(void) -{ - return sym_change_count; -} - -void conf_set_changed_callback(void (*fn)(void)) -{ - conf_changed_callback = fn; -} - -static void randomize_choice_values(struct symbol *csym) -{ - struct property *prop; - struct symbol *sym; - struct expr *e; - int cnt, def; - - /* - * If choice is mod then we may have more items selected - * and if no then no-one. - * In both cases stop. - */ - if (csym->curr.tri != yes) - return; - - prop = sym_get_choice_prop(csym); - - /* count entries in choice block */ - cnt = 0; - expr_list_for_each_sym(prop->expr, e, sym) - cnt++; - - /* - * find a random value and set it to yes, - * set the rest to no so we have only one set - */ - def = (rand() % cnt); - - cnt = 0; - expr_list_for_each_sym(prop->expr, e, sym) { - if (def == cnt++) { - sym->def[S_DEF_USER].tri = yes; - csym->def[S_DEF_USER].val = sym; - } - else { - sym->def[S_DEF_USER].tri = no; - } - } - csym->flags |= SYMBOL_DEF_USER; - /* clear VALID to get value calculated */ - csym->flags &= ~(SYMBOL_VALID); -} - -static void set_all_choice_values(struct symbol *csym) -{ - struct property *prop; - struct symbol *sym; - struct expr *e; - - prop = sym_get_choice_prop(csym); - - /* - * Set all non-assinged choice values to no - */ - expr_list_for_each_sym(prop->expr, e, sym) { - if (!sym_has_value(sym)) - sym->def[S_DEF_USER].tri = no; - } - csym->flags |= SYMBOL_DEF_USER; - /* clear VALID to get value calculated */ - csym->flags &= ~(SYMBOL_VALID); -} - -void conf_set_all_new_symbols(enum conf_def_mode mode) -{ - struct symbol *sym, *csym; - int i, cnt; - - for_all_symbols(i, sym) { - if (sym_has_value(sym)) - continue; - switch (sym_get_type(sym)) { - case S_BOOLEAN: - case S_TRISTATE: - switch (mode) { - case def_yes: - sym->def[S_DEF_USER].tri = yes; - break; - case def_mod: - sym->def[S_DEF_USER].tri = mod; - break; - case def_no: - sym->def[S_DEF_USER].tri = no; - break; - case def_random: - cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; - sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); - break; - default: - continue; - } - if (!(sym_is_choice(sym) && mode == def_random)) - sym->flags |= SYMBOL_DEF_USER; - break; - default: - break; - } - - } - - sym_clear_all_valid(); - - /* - * We have different type of choice blocks. - * If curr.tri equals to mod then we can select several - * choice symbols in one block. - * In this case we do nothing. - * If curr.tri equals yes then only one symbol can be - * selected in a choice block and we set it to yes, - * and the rest to no. - */ - for_all_symbols(i, csym) { - if (sym_has_value(csym) || !sym_is_choice(csym)) - continue; - - sym_calc_value(csym); - if (mode == def_random) - randomize_choice_values(csym); - else - set_all_choice_values(csym); - } -} diff -Nru seabios-1.7.1/tools/kconfig/expr.c seabios-1.7.4/tools/kconfig/expr.c --- seabios-1.7.1/tools/kconfig/expr.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/expr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1173 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -#define DEBUG_EXPR 0 - -struct expr *expr_alloc_symbol(struct symbol *sym) -{ - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); - e->type = E_SYMBOL; - e->left.sym = sym; - return e; -} - -struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) -{ - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); - e->type = type; - e->left.expr = ce; - return e; -} - -struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) -{ - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); - e->type = type; - e->left.expr = e1; - e->right.expr = e2; - return e; -} - -struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) -{ - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); - e->type = type; - e->left.sym = s1; - e->right.sym = s2; - return e; -} - -struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) -{ - if (!e1) - return e2; - return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; -} - -struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) -{ - if (!e1) - return e2; - return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; -} - -struct expr *expr_copy(const struct expr *org) -{ - struct expr *e; - - if (!org) - return NULL; - - e = malloc(sizeof(*org)); - memcpy(e, org, sizeof(*org)); - switch (org->type) { - case E_SYMBOL: - e->left = org->left; - break; - case E_NOT: - e->left.expr = expr_copy(org->left.expr); - break; - case E_EQUAL: - case E_UNEQUAL: - e->left.sym = org->left.sym; - e->right.sym = org->right.sym; - break; - case E_AND: - case E_OR: - case E_LIST: - e->left.expr = expr_copy(org->left.expr); - e->right.expr = expr_copy(org->right.expr); - break; - default: - printf("can't copy type %d\n", e->type); - free(e); - e = NULL; - break; - } - - return e; -} - -void expr_free(struct expr *e) -{ - if (!e) - return; - - switch (e->type) { - case E_SYMBOL: - break; - case E_NOT: - expr_free(e->left.expr); - return; - case E_EQUAL: - case E_UNEQUAL: - break; - case E_OR: - case E_AND: - expr_free(e->left.expr); - expr_free(e->right.expr); - break; - default: - printf("how to free type %d?\n", e->type); - break; - } - free(e); -} - -static int trans_count; - -#define e1 (*ep1) -#define e2 (*ep2) - -static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) -{ - if (e1->type == type) { - __expr_eliminate_eq(type, &e1->left.expr, &e2); - __expr_eliminate_eq(type, &e1->right.expr, &e2); - return; - } - if (e2->type == type) { - __expr_eliminate_eq(type, &e1, &e2->left.expr); - __expr_eliminate_eq(type, &e1, &e2->right.expr); - return; - } - if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && - e1->left.sym == e2->left.sym && - (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) - return; - if (!expr_eq(e1, e2)) - return; - trans_count++; - expr_free(e1); expr_free(e2); - switch (type) { - case E_OR: - e1 = expr_alloc_symbol(&symbol_no); - e2 = expr_alloc_symbol(&symbol_no); - break; - case E_AND: - e1 = expr_alloc_symbol(&symbol_yes); - e2 = expr_alloc_symbol(&symbol_yes); - break; - default: - ; - } -} - -void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) -{ - if (!e1 || !e2) - return; - switch (e1->type) { - case E_OR: - case E_AND: - __expr_eliminate_eq(e1->type, ep1, ep2); - default: - ; - } - if (e1->type != e2->type) switch (e2->type) { - case E_OR: - case E_AND: - __expr_eliminate_eq(e2->type, ep1, ep2); - default: - ; - } - e1 = expr_eliminate_yn(e1); - e2 = expr_eliminate_yn(e2); -} - -#undef e1 -#undef e2 - -int expr_eq(struct expr *e1, struct expr *e2) -{ - int res, old_count; - - if (e1->type != e2->type) - return 0; - switch (e1->type) { - case E_EQUAL: - case E_UNEQUAL: - return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; - case E_SYMBOL: - return e1->left.sym == e2->left.sym; - case E_NOT: - return expr_eq(e1->left.expr, e2->left.expr); - case E_AND: - case E_OR: - e1 = expr_copy(e1); - e2 = expr_copy(e2); - old_count = trans_count; - expr_eliminate_eq(&e1, &e2); - res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && - e1->left.sym == e2->left.sym); - expr_free(e1); - expr_free(e2); - trans_count = old_count; - return res; - case E_LIST: - case E_RANGE: - case E_NONE: - /* panic */; - } - - if (DEBUG_EXPR) { - expr_fprint(e1, stdout); - printf(" = "); - expr_fprint(e2, stdout); - printf(" ?\n"); - } - - return 0; -} - -struct expr *expr_eliminate_yn(struct expr *e) -{ - struct expr *tmp; - - if (e) switch (e->type) { - case E_AND: - e->left.expr = expr_eliminate_yn(e->left.expr); - e->right.expr = expr_eliminate_yn(e->right.expr); - if (e->left.expr->type == E_SYMBOL) { - if (e->left.expr->left.sym == &symbol_no) { - expr_free(e->left.expr); - expr_free(e->right.expr); - e->type = E_SYMBOL; - e->left.sym = &symbol_no; - e->right.expr = NULL; - return e; - } else if (e->left.expr->left.sym == &symbol_yes) { - free(e->left.expr); - tmp = e->right.expr; - *e = *(e->right.expr); - free(tmp); - return e; - } - } - if (e->right.expr->type == E_SYMBOL) { - if (e->right.expr->left.sym == &symbol_no) { - expr_free(e->left.expr); - expr_free(e->right.expr); - e->type = E_SYMBOL; - e->left.sym = &symbol_no; - e->right.expr = NULL; - return e; - } else if (e->right.expr->left.sym == &symbol_yes) { - free(e->right.expr); - tmp = e->left.expr; - *e = *(e->left.expr); - free(tmp); - return e; - } - } - break; - case E_OR: - e->left.expr = expr_eliminate_yn(e->left.expr); - e->right.expr = expr_eliminate_yn(e->right.expr); - if (e->left.expr->type == E_SYMBOL) { - if (e->left.expr->left.sym == &symbol_no) { - free(e->left.expr); - tmp = e->right.expr; - *e = *(e->right.expr); - free(tmp); - return e; - } else if (e->left.expr->left.sym == &symbol_yes) { - expr_free(e->left.expr); - expr_free(e->right.expr); - e->type = E_SYMBOL; - e->left.sym = &symbol_yes; - e->right.expr = NULL; - return e; - } - } - if (e->right.expr->type == E_SYMBOL) { - if (e->right.expr->left.sym == &symbol_no) { - free(e->right.expr); - tmp = e->left.expr; - *e = *(e->left.expr); - free(tmp); - return e; - } else if (e->right.expr->left.sym == &symbol_yes) { - expr_free(e->left.expr); - expr_free(e->right.expr); - e->type = E_SYMBOL; - e->left.sym = &symbol_yes; - e->right.expr = NULL; - return e; - } - } - break; - default: - ; - } - return e; -} - -/* - * bool FOO!=n => FOO - */ -struct expr *expr_trans_bool(struct expr *e) -{ - if (!e) - return NULL; - switch (e->type) { - case E_AND: - case E_OR: - case E_NOT: - e->left.expr = expr_trans_bool(e->left.expr); - e->right.expr = expr_trans_bool(e->right.expr); - break; - case E_UNEQUAL: - // FOO!=n -> FOO - if (e->left.sym->type == S_TRISTATE) { - if (e->right.sym == &symbol_no) { - e->type = E_SYMBOL; - e->right.sym = NULL; - } - } - break; - default: - ; - } - return e; -} - -/* - * e1 || e2 -> ? - */ -static struct expr *expr_join_or(struct expr *e1, struct expr *e2) -{ - struct expr *tmp; - struct symbol *sym1, *sym2; - - if (expr_eq(e1, e2)) - return expr_copy(e1); - if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) - return NULL; - if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) - return NULL; - if (e1->type == E_NOT) { - tmp = e1->left.expr; - if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) - return NULL; - sym1 = tmp->left.sym; - } else - sym1 = e1->left.sym; - if (e2->type == E_NOT) { - if (e2->left.expr->type != E_SYMBOL) - return NULL; - sym2 = e2->left.expr->left.sym; - } else - sym2 = e2->left.sym; - if (sym1 != sym2) - return NULL; - if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) - return NULL; - if (sym1->type == S_TRISTATE) { - if (e1->type == E_EQUAL && e2->type == E_EQUAL && - ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || - (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { - // (a='y') || (a='m') -> (a!='n') - return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); - } - if (e1->type == E_EQUAL && e2->type == E_EQUAL && - ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || - (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { - // (a='y') || (a='n') -> (a!='m') - return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); - } - if (e1->type == E_EQUAL && e2->type == E_EQUAL && - ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || - (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { - // (a='m') || (a='n') -> (a!='y') - return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); - } - } - if (sym1->type == S_BOOLEAN && sym1 == sym2) { - if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || - (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) - return expr_alloc_symbol(&symbol_yes); - } - - if (DEBUG_EXPR) { - printf("optimize ("); - expr_fprint(e1, stdout); - printf(") || ("); - expr_fprint(e2, stdout); - printf(")?\n"); - } - return NULL; -} - -static struct expr *expr_join_and(struct expr *e1, struct expr *e2) -{ - struct expr *tmp; - struct symbol *sym1, *sym2; - - if (expr_eq(e1, e2)) - return expr_copy(e1); - if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) - return NULL; - if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) - return NULL; - if (e1->type == E_NOT) { - tmp = e1->left.expr; - if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) - return NULL; - sym1 = tmp->left.sym; - } else - sym1 = e1->left.sym; - if (e2->type == E_NOT) { - if (e2->left.expr->type != E_SYMBOL) - return NULL; - sym2 = e2->left.expr->left.sym; - } else - sym2 = e2->left.sym; - if (sym1 != sym2) - return NULL; - if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) - return NULL; - - if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || - (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) - // (a) && (a='y') -> (a='y') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); - - if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || - (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) - // (a) && (a!='n') -> (a) - return expr_alloc_symbol(sym1); - - if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || - (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) - // (a) && (a!='m') -> (a='y') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); - - if (sym1->type == S_TRISTATE) { - if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { - // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' - sym2 = e1->right.sym; - if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) - return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) - : expr_alloc_symbol(&symbol_no); - } - if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { - // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' - sym2 = e2->right.sym; - if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) - return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) - : expr_alloc_symbol(&symbol_no); - } - if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && - ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || - (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) - // (a!='y') && (a!='n') -> (a='m') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); - - if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && - ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || - (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) - // (a!='y') && (a!='m') -> (a='n') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); - - if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && - ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || - (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) - // (a!='m') && (a!='n') -> (a='m') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); - - if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || - (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || - (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || - (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) - return NULL; - } - - if (DEBUG_EXPR) { - printf("optimize ("); - expr_fprint(e1, stdout); - printf(") && ("); - expr_fprint(e2, stdout); - printf(")?\n"); - } - return NULL; -} - -static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) -{ -#define e1 (*ep1) -#define e2 (*ep2) - struct expr *tmp; - - if (e1->type == type) { - expr_eliminate_dups1(type, &e1->left.expr, &e2); - expr_eliminate_dups1(type, &e1->right.expr, &e2); - return; - } - if (e2->type == type) { - expr_eliminate_dups1(type, &e1, &e2->left.expr); - expr_eliminate_dups1(type, &e1, &e2->right.expr); - return; - } - if (e1 == e2) - return; - - switch (e1->type) { - case E_OR: case E_AND: - expr_eliminate_dups1(e1->type, &e1, &e1); - default: - ; - } - - switch (type) { - case E_OR: - tmp = expr_join_or(e1, e2); - if (tmp) { - expr_free(e1); expr_free(e2); - e1 = expr_alloc_symbol(&symbol_no); - e2 = tmp; - trans_count++; - } - break; - case E_AND: - tmp = expr_join_and(e1, e2); - if (tmp) { - expr_free(e1); expr_free(e2); - e1 = expr_alloc_symbol(&symbol_yes); - e2 = tmp; - trans_count++; - } - break; - default: - ; - } -#undef e1 -#undef e2 -} - -static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) -{ -#define e1 (*ep1) -#define e2 (*ep2) - struct expr *tmp, *tmp1, *tmp2; - - if (e1->type == type) { - expr_eliminate_dups2(type, &e1->left.expr, &e2); - expr_eliminate_dups2(type, &e1->right.expr, &e2); - return; - } - if (e2->type == type) { - expr_eliminate_dups2(type, &e1, &e2->left.expr); - expr_eliminate_dups2(type, &e1, &e2->right.expr); - } - if (e1 == e2) - return; - - switch (e1->type) { - case E_OR: - expr_eliminate_dups2(e1->type, &e1, &e1); - // (FOO || BAR) && (!FOO && !BAR) -> n - tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); - tmp2 = expr_copy(e2); - tmp = expr_extract_eq_and(&tmp1, &tmp2); - if (expr_is_yes(tmp1)) { - expr_free(e1); - e1 = expr_alloc_symbol(&symbol_no); - trans_count++; - } - expr_free(tmp2); - expr_free(tmp1); - expr_free(tmp); - break; - case E_AND: - expr_eliminate_dups2(e1->type, &e1, &e1); - // (FOO && BAR) || (!FOO || !BAR) -> y - tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); - tmp2 = expr_copy(e2); - tmp = expr_extract_eq_or(&tmp1, &tmp2); - if (expr_is_no(tmp1)) { - expr_free(e1); - e1 = expr_alloc_symbol(&symbol_yes); - trans_count++; - } - expr_free(tmp2); - expr_free(tmp1); - expr_free(tmp); - break; - default: - ; - } -#undef e1 -#undef e2 -} - -struct expr *expr_eliminate_dups(struct expr *e) -{ - int oldcount; - if (!e) - return e; - - oldcount = trans_count; - while (1) { - trans_count = 0; - switch (e->type) { - case E_OR: case E_AND: - expr_eliminate_dups1(e->type, &e, &e); - expr_eliminate_dups2(e->type, &e, &e); - default: - ; - } - if (!trans_count) - break; - e = expr_eliminate_yn(e); - } - trans_count = oldcount; - return e; -} - -struct expr *expr_transform(struct expr *e) -{ - struct expr *tmp; - - if (!e) - return NULL; - switch (e->type) { - case E_EQUAL: - case E_UNEQUAL: - case E_SYMBOL: - case E_LIST: - break; - default: - e->left.expr = expr_transform(e->left.expr); - e->right.expr = expr_transform(e->right.expr); - } - - switch (e->type) { - case E_EQUAL: - if (e->left.sym->type != S_BOOLEAN) - break; - if (e->right.sym == &symbol_no) { - e->type = E_NOT; - e->left.expr = expr_alloc_symbol(e->left.sym); - e->right.sym = NULL; - break; - } - if (e->right.sym == &symbol_mod) { - printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); - e->type = E_SYMBOL; - e->left.sym = &symbol_no; - e->right.sym = NULL; - break; - } - if (e->right.sym == &symbol_yes) { - e->type = E_SYMBOL; - e->right.sym = NULL; - break; - } - break; - case E_UNEQUAL: - if (e->left.sym->type != S_BOOLEAN) - break; - if (e->right.sym == &symbol_no) { - e->type = E_SYMBOL; - e->right.sym = NULL; - break; - } - if (e->right.sym == &symbol_mod) { - printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); - e->type = E_SYMBOL; - e->left.sym = &symbol_yes; - e->right.sym = NULL; - break; - } - if (e->right.sym == &symbol_yes) { - e->type = E_NOT; - e->left.expr = expr_alloc_symbol(e->left.sym); - e->right.sym = NULL; - break; - } - break; - case E_NOT: - switch (e->left.expr->type) { - case E_NOT: - // !!a -> a - tmp = e->left.expr->left.expr; - free(e->left.expr); - free(e); - e = tmp; - e = expr_transform(e); - break; - case E_EQUAL: - case E_UNEQUAL: - // !a='x' -> a!='x' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; - break; - case E_OR: - // !(a || b) -> !a && !b - tmp = e->left.expr; - e->type = E_AND; - e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); - tmp->type = E_NOT; - tmp->right.expr = NULL; - e = expr_transform(e); - break; - case E_AND: - // !(a && b) -> !a || !b - tmp = e->left.expr; - e->type = E_OR; - e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); - tmp->type = E_NOT; - tmp->right.expr = NULL; - e = expr_transform(e); - break; - case E_SYMBOL: - if (e->left.expr->left.sym == &symbol_yes) { - // !'y' -> 'n' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = E_SYMBOL; - e->left.sym = &symbol_no; - break; - } - if (e->left.expr->left.sym == &symbol_mod) { - // !'m' -> 'm' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = E_SYMBOL; - e->left.sym = &symbol_mod; - break; - } - if (e->left.expr->left.sym == &symbol_no) { - // !'n' -> 'y' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = E_SYMBOL; - e->left.sym = &symbol_yes; - break; - } - break; - default: - ; - } - break; - default: - ; - } - return e; -} - -int expr_contains_symbol(struct expr *dep, struct symbol *sym) -{ - if (!dep) - return 0; - - switch (dep->type) { - case E_AND: - case E_OR: - return expr_contains_symbol(dep->left.expr, sym) || - expr_contains_symbol(dep->right.expr, sym); - case E_SYMBOL: - return dep->left.sym == sym; - case E_EQUAL: - case E_UNEQUAL: - return dep->left.sym == sym || - dep->right.sym == sym; - case E_NOT: - return expr_contains_symbol(dep->left.expr, sym); - default: - ; - } - return 0; -} - -bool expr_depends_symbol(struct expr *dep, struct symbol *sym) -{ - if (!dep) - return false; - - switch (dep->type) { - case E_AND: - return expr_depends_symbol(dep->left.expr, sym) || - expr_depends_symbol(dep->right.expr, sym); - case E_SYMBOL: - return dep->left.sym == sym; - case E_EQUAL: - if (dep->left.sym == sym) { - if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) - return true; - } - break; - case E_UNEQUAL: - if (dep->left.sym == sym) { - if (dep->right.sym == &symbol_no) - return true; - } - break; - default: - ; - } - return false; -} - -struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) -{ - struct expr *tmp = NULL; - expr_extract_eq(E_AND, &tmp, ep1, ep2); - if (tmp) { - *ep1 = expr_eliminate_yn(*ep1); - *ep2 = expr_eliminate_yn(*ep2); - } - return tmp; -} - -struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) -{ - struct expr *tmp = NULL; - expr_extract_eq(E_OR, &tmp, ep1, ep2); - if (tmp) { - *ep1 = expr_eliminate_yn(*ep1); - *ep2 = expr_eliminate_yn(*ep2); - } - return tmp; -} - -void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) -{ -#define e1 (*ep1) -#define e2 (*ep2) - if (e1->type == type) { - expr_extract_eq(type, ep, &e1->left.expr, &e2); - expr_extract_eq(type, ep, &e1->right.expr, &e2); - return; - } - if (e2->type == type) { - expr_extract_eq(type, ep, ep1, &e2->left.expr); - expr_extract_eq(type, ep, ep1, &e2->right.expr); - return; - } - if (expr_eq(e1, e2)) { - *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; - expr_free(e2); - if (type == E_AND) { - e1 = expr_alloc_symbol(&symbol_yes); - e2 = expr_alloc_symbol(&symbol_yes); - } else if (type == E_OR) { - e1 = expr_alloc_symbol(&symbol_no); - e2 = expr_alloc_symbol(&symbol_no); - } - } -#undef e1 -#undef e2 -} - -struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) -{ - struct expr *e1, *e2; - - if (!e) { - e = expr_alloc_symbol(sym); - if (type == E_UNEQUAL) - e = expr_alloc_one(E_NOT, e); - return e; - } - switch (e->type) { - case E_AND: - e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); - e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); - if (sym == &symbol_yes) - e = expr_alloc_two(E_AND, e1, e2); - if (sym == &symbol_no) - e = expr_alloc_two(E_OR, e1, e2); - if (type == E_UNEQUAL) - e = expr_alloc_one(E_NOT, e); - return e; - case E_OR: - e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); - e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); - if (sym == &symbol_yes) - e = expr_alloc_two(E_OR, e1, e2); - if (sym == &symbol_no) - e = expr_alloc_two(E_AND, e1, e2); - if (type == E_UNEQUAL) - e = expr_alloc_one(E_NOT, e); - return e; - case E_NOT: - return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); - case E_UNEQUAL: - case E_EQUAL: - if (type == E_EQUAL) { - if (sym == &symbol_yes) - return expr_copy(e); - if (sym == &symbol_mod) - return expr_alloc_symbol(&symbol_no); - if (sym == &symbol_no) - return expr_alloc_one(E_NOT, expr_copy(e)); - } else { - if (sym == &symbol_yes) - return expr_alloc_one(E_NOT, expr_copy(e)); - if (sym == &symbol_mod) - return expr_alloc_symbol(&symbol_yes); - if (sym == &symbol_no) - return expr_copy(e); - } - break; - case E_SYMBOL: - return expr_alloc_comp(type, e->left.sym, sym); - case E_LIST: - case E_RANGE: - case E_NONE: - /* panic */; - } - return NULL; -} - -tristate expr_calc_value(struct expr *e) -{ - tristate val1, val2; - const char *str1, *str2; - - if (!e) - return yes; - - switch (e->type) { - case E_SYMBOL: - sym_calc_value(e->left.sym); - return e->left.sym->curr.tri; - case E_AND: - val1 = expr_calc_value(e->left.expr); - val2 = expr_calc_value(e->right.expr); - return EXPR_AND(val1, val2); - case E_OR: - val1 = expr_calc_value(e->left.expr); - val2 = expr_calc_value(e->right.expr); - return EXPR_OR(val1, val2); - case E_NOT: - val1 = expr_calc_value(e->left.expr); - return EXPR_NOT(val1); - case E_EQUAL: - sym_calc_value(e->left.sym); - sym_calc_value(e->right.sym); - str1 = sym_get_string_value(e->left.sym); - str2 = sym_get_string_value(e->right.sym); - return !strcmp(str1, str2) ? yes : no; - case E_UNEQUAL: - sym_calc_value(e->left.sym); - sym_calc_value(e->right.sym); - str1 = sym_get_string_value(e->left.sym); - str2 = sym_get_string_value(e->right.sym); - return !strcmp(str1, str2) ? no : yes; - default: - printf("expr_calc_value: %d?\n", e->type); - return no; - } -} - -int expr_compare_type(enum expr_type t1, enum expr_type t2) -{ -#if 0 - return 1; -#else - if (t1 == t2) - return 0; - switch (t1) { - case E_EQUAL: - case E_UNEQUAL: - if (t2 == E_NOT) - return 1; - case E_NOT: - if (t2 == E_AND) - return 1; - case E_AND: - if (t2 == E_OR) - return 1; - case E_OR: - if (t2 == E_LIST) - return 1; - case E_LIST: - if (t2 == 0) - return 1; - default: - return -1; - } - printf("[%dgt%d?]", t1, t2); - return 0; -#endif -} - -static inline struct expr * -expr_get_leftmost_symbol(const struct expr *e) -{ - - if (e == NULL) - return NULL; - - while (e->type != E_SYMBOL) - e = e->left.expr; - - return expr_copy(e); -} - -/* - * Given expression `e1' and `e2', returns the leaf of the longest - * sub-expression of `e1' not containing 'e2. - */ -struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) -{ - struct expr *ret; - - switch (e1->type) { - case E_OR: - return expr_alloc_and( - expr_simplify_unmet_dep(e1->left.expr, e2), - expr_simplify_unmet_dep(e1->right.expr, e2)); - case E_AND: { - struct expr *e; - e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); - e = expr_eliminate_dups(e); - ret = (!expr_eq(e, e1)) ? e1 : NULL; - expr_free(e); - break; - } - default: - ret = e1; - break; - } - - return expr_get_leftmost_symbol(ret); -} - -void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) -{ - if (!e) { - fn(data, NULL, "y"); - return; - } - - if (expr_compare_type(prevtoken, e->type) > 0) - fn(data, NULL, "("); - switch (e->type) { - case E_SYMBOL: - if (e->left.sym->name) - fn(data, e->left.sym, e->left.sym->name); - else - fn(data, NULL, ""); - break; - case E_NOT: - fn(data, NULL, "!"); - expr_print(e->left.expr, fn, data, E_NOT); - break; - case E_EQUAL: - if (e->left.sym->name) - fn(data, e->left.sym, e->left.sym->name); - else - fn(data, NULL, ""); - fn(data, NULL, "="); - fn(data, e->right.sym, e->right.sym->name); - break; - case E_UNEQUAL: - if (e->left.sym->name) - fn(data, e->left.sym, e->left.sym->name); - else - fn(data, NULL, ""); - fn(data, NULL, "!="); - fn(data, e->right.sym, e->right.sym->name); - break; - case E_OR: - expr_print(e->left.expr, fn, data, E_OR); - fn(data, NULL, " || "); - expr_print(e->right.expr, fn, data, E_OR); - break; - case E_AND: - expr_print(e->left.expr, fn, data, E_AND); - fn(data, NULL, " && "); - expr_print(e->right.expr, fn, data, E_AND); - break; - case E_LIST: - fn(data, e->right.sym, e->right.sym->name); - if (e->left.expr) { - fn(data, NULL, " ^ "); - expr_print(e->left.expr, fn, data, E_LIST); - } - break; - case E_RANGE: - fn(data, NULL, "["); - fn(data, e->left.sym, e->left.sym->name); - fn(data, NULL, " "); - fn(data, e->right.sym, e->right.sym->name); - fn(data, NULL, "]"); - break; - default: - { - char buf[32]; - sprintf(buf, "", e->type); - fn(data, NULL, buf); - break; - } - } - if (expr_compare_type(prevtoken, e->type) > 0) - fn(data, NULL, ")"); -} - -static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) -{ - xfwrite(str, strlen(str), 1, data); -} - -void expr_fprint(struct expr *e, FILE *out) -{ - expr_print(e, expr_print_file_helper, out, E_NONE); -} - -static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) -{ - struct gstr *gs = (struct gstr*)data; - const char *sym_str = NULL; - - if (sym) - sym_str = sym_get_string_value(sym); - - if (gs->max_width) { - unsigned extra_length = strlen(str); - const char *last_cr = strrchr(gs->s, '\n'); - unsigned last_line_length; - - if (sym_str) - extra_length += 4 + strlen(sym_str); - - if (!last_cr) - last_cr = gs->s; - - last_line_length = strlen(gs->s) - (last_cr - gs->s); - - if ((last_line_length + extra_length) > gs->max_width) - str_append(gs, "\\\n"); - } - - str_append(gs, str); - if (sym && sym->type != S_UNKNOWN) - str_printf(gs, " [=%s]", sym_str); -} - -void expr_gstr_print(struct expr *e, struct gstr *gs) -{ - expr_print(e, expr_print_gstr_helper, gs, E_NONE); -} diff -Nru seabios-1.7.1/tools/kconfig/expr.h seabios-1.7.4/tools/kconfig/expr.h --- seabios-1.7.1/tools/kconfig/expr.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/expr.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#ifndef EXPR_H -#define EXPR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#ifndef __cplusplus -#include -#endif - -struct file { - struct file *next; - struct file *parent; - const char *name; - int lineno; - int flags; -}; - -#define FILE_BUSY 0x0001 -#define FILE_SCANNED 0x0002 - -typedef enum tristate { - no, mod, yes -} tristate; - -enum expr_type { - E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE -}; - -union expr_data { - struct expr *expr; - struct symbol *sym; -}; - -struct expr { - enum expr_type type; - union expr_data left, right; -}; - -#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) -#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) -#define EXPR_NOT(dep) (2-(dep)) - -#define expr_list_for_each_sym(l, e, s) \ - for (e = (l); e && (s = e->right.sym); e = e->left.expr) - -struct expr_value { - struct expr *expr; - tristate tri; -}; - -struct symbol_value { - void *val; - tristate tri; -}; - -enum symbol_type { - S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER -}; - -/* enum values are used as index to symbol.def[] */ -enum { - S_DEF_USER, /* main user value */ - S_DEF_AUTO, /* values read from auto.conf */ - S_DEF_DEF3, /* Reserved for UI usage */ - S_DEF_DEF4, /* Reserved for UI usage */ - S_DEF_COUNT -}; - -struct symbol { - struct symbol *next; - char *name; - enum symbol_type type; - struct symbol_value curr; - struct symbol_value def[S_DEF_COUNT]; - tristate visible; - int flags; - struct property *prop; - struct expr_value dir_dep; - struct expr_value rev_dep; -}; - -#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) - -#define SYMBOL_CONST 0x0001 /* symbol is const */ -#define SYMBOL_CHECK 0x0008 /* used during dependency checking */ -#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ -#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ -#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ -#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ -#define SYMBOL_WRITE 0x0200 /* ? */ -#define SYMBOL_CHANGED 0x0400 /* ? */ -#define SYMBOL_AUTO 0x1000 /* value from environment variable */ -#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ -#define SYMBOL_WARNED 0x8000 /* warning has been issued */ - -/* Set when symbol.def[] is used */ -#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ -#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ -#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ -#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ -#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ - -#define SYMBOL_MAXLENGTH 256 -#define SYMBOL_HASHSIZE 9973 - -/* A property represent the config options that can be associated - * with a config "symbol". - * Sample: - * config FOO - * default y - * prompt "foo prompt" - * select BAR - * config BAZ - * int "BAZ Value" - * range 1..255 - */ -enum prop_type { - P_UNKNOWN, - P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ - P_COMMENT, /* text associated with a comment */ - P_MENU, /* prompt associated with a menuconfig option */ - P_DEFAULT, /* default y */ - P_CHOICE, /* choice value */ - P_SELECT, /* select BAR */ - P_RANGE, /* range 7..100 (for a symbol) */ - P_ENV, /* value from environment variable */ - P_SYMBOL, /* where a symbol is defined */ -}; - -struct property { - struct property *next; /* next property - null if last */ - struct symbol *sym; /* the symbol for which the property is associated */ - enum prop_type type; /* type of property */ - const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ - struct expr_value visible; - struct expr *expr; /* the optional conditional part of the property */ - struct menu *menu; /* the menu the property are associated with - * valid for: P_SELECT, P_RANGE, P_CHOICE, - * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ - struct file *file; /* what file was this property defined */ - int lineno; /* what lineno was this property defined */ -}; - -#define for_all_properties(sym, st, tok) \ - for (st = sym->prop; st; st = st->next) \ - if (st->type == (tok)) -#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) -#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) -#define for_all_prompts(sym, st) \ - for (st = sym->prop; st; st = st->next) \ - if (st->text) - -struct menu { - struct menu *next; - struct menu *parent; - struct menu *list; - struct symbol *sym; - struct property *prompt; - struct expr *visibility; - struct expr *dep; - unsigned int flags; - char *help; - struct file *file; - int lineno; - void *data; -}; - -#define MENU_CHANGED 0x0001 -#define MENU_ROOT 0x0002 - -#ifndef SWIG - -extern struct file *file_list; -extern struct file *current_file; -struct file *lookup_file(const char *name); - -extern struct symbol symbol_yes, symbol_no, symbol_mod; -extern struct symbol *modules_sym; -extern struct symbol *sym_defconfig_list; -extern int cdebug; -struct expr *expr_alloc_symbol(struct symbol *sym); -struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); -struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); -struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); -struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); -struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); -struct expr *expr_copy(const struct expr *org); -void expr_free(struct expr *e); -int expr_eq(struct expr *e1, struct expr *e2); -void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); -tristate expr_calc_value(struct expr *e); -struct expr *expr_eliminate_yn(struct expr *e); -struct expr *expr_trans_bool(struct expr *e); -struct expr *expr_eliminate_dups(struct expr *e); -struct expr *expr_transform(struct expr *e); -int expr_contains_symbol(struct expr *dep, struct symbol *sym); -bool expr_depends_symbol(struct expr *dep, struct symbol *sym); -struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); -struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); -void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); -struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); -struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); - -void expr_fprint(struct expr *e, FILE *out); -struct gstr; /* forward */ -void expr_gstr_print(struct expr *e, struct gstr *gs); - -static inline int expr_is_yes(struct expr *e) -{ - return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); -} - -static inline int expr_is_no(struct expr *e) -{ - return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); -} -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* EXPR_H */ diff -Nru seabios-1.7.1/tools/kconfig/gconf.c seabios-1.7.4/tools/kconfig/gconf.c --- seabios-1.7.1/tools/kconfig/gconf.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/gconf.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1577 +0,0 @@ -/* Hey EMACS -*- linux-c -*- */ -/* - * - * Copyright (C) 2002-2003 Romain Lievin - * Released under the terms of the GNU GPL v2.0. - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "lkc.h" -#include "images.c" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -//#define DEBUG - -enum { - SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW -}; - -enum { - OPT_NORMAL, OPT_ALL, OPT_PROMPT -}; - -static gint view_mode = FULL_VIEW; -static gboolean show_name = TRUE; -static gboolean show_range = TRUE; -static gboolean show_value = TRUE; -static gboolean resizeable = FALSE; -static int opt_mode = OPT_NORMAL; - -GtkWidget *main_wnd = NULL; -GtkWidget *tree1_w = NULL; // left frame -GtkWidget *tree2_w = NULL; // right frame -GtkWidget *text_w = NULL; -GtkWidget *hpaned = NULL; -GtkWidget *vpaned = NULL; -GtkWidget *back_btn = NULL; -GtkWidget *save_btn = NULL; -GtkWidget *save_menu_item = NULL; - -GtkTextTag *tag1, *tag2; -GdkColor color; - -GtkTreeStore *tree1, *tree2, *tree; -GtkTreeModel *model1, *model2; -static GtkTreeIter *parents[256]; -static gint indent; - -static struct menu *current; // current node for SINGLE view -static struct menu *browsed; // browsed node for SPLIT view - -enum { - COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, - COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, - COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, - COL_NUMBER -}; - -static void display_list(void); -static void display_tree(struct menu *menu); -static void display_tree_part(void); -static void update_tree(struct menu *src, GtkTreeIter * dst); -static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); -static gchar **fill_row(struct menu *menu); -static void conf_changed(void); - -/* Helping/Debugging Functions */ - -const char *dbg_sym_flags(int val) -{ - static char buf[256]; - - bzero(buf, 256); - - if (val & SYMBOL_CONST) - strcat(buf, "const/"); - if (val & SYMBOL_CHECK) - strcat(buf, "check/"); - if (val & SYMBOL_CHOICE) - strcat(buf, "choice/"); - if (val & SYMBOL_CHOICEVAL) - strcat(buf, "choiceval/"); - if (val & SYMBOL_VALID) - strcat(buf, "valid/"); - if (val & SYMBOL_OPTIONAL) - strcat(buf, "optional/"); - if (val & SYMBOL_WRITE) - strcat(buf, "write/"); - if (val & SYMBOL_CHANGED) - strcat(buf, "changed/"); - if (val & SYMBOL_AUTO) - strcat(buf, "auto/"); - - buf[strlen(buf) - 1] = '\0'; - - return buf; -} - -void replace_button_icon(GladeXML * xml, GdkDrawable * window, - GtkStyle * style, gchar * btn_name, gchar ** xpm) -{ - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkToolButton *button; - GtkWidget *image; - - pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, - &style->bg[GTK_STATE_NORMAL], - xpm); - - button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); - image = gtk_image_new_from_pixmap(pixmap, mask); - gtk_widget_show(image); - gtk_tool_button_set_icon_widget(button, image); -} - -/* Main Window Initialization */ -void init_main_window(const gchar * glade_file) -{ - GladeXML *xml; - GtkWidget *widget; - GtkTextBuffer *txtbuf; - GtkStyle *style; - - xml = glade_xml_new(glade_file, "window1", NULL); - if (!xml) - g_error(_("GUI loading failed !\n")); - glade_xml_signal_autoconnect(xml); - - main_wnd = glade_xml_get_widget(xml, "window1"); - hpaned = glade_xml_get_widget(xml, "hpaned1"); - vpaned = glade_xml_get_widget(xml, "vpaned1"); - tree1_w = glade_xml_get_widget(xml, "treeview1"); - tree2_w = glade_xml_get_widget(xml, "treeview2"); - text_w = glade_xml_get_widget(xml, "textview3"); - - back_btn = glade_xml_get_widget(xml, "button1"); - gtk_widget_set_sensitive(back_btn, FALSE); - - widget = glade_xml_get_widget(xml, "show_name1"); - gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, - show_name); - - widget = glade_xml_get_widget(xml, "show_range1"); - gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, - show_range); - - widget = glade_xml_get_widget(xml, "show_data1"); - gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, - show_value); - - save_btn = glade_xml_get_widget(xml, "button3"); - save_menu_item = glade_xml_get_widget(xml, "save1"); - conf_set_changed_callback(conf_changed); - - style = gtk_widget_get_style(main_wnd); - widget = glade_xml_get_widget(xml, "toolbar1"); - -#if 0 /* Use stock Gtk icons instead */ - replace_button_icon(xml, main_wnd->window, style, - "button1", (gchar **) xpm_back); - replace_button_icon(xml, main_wnd->window, style, - "button2", (gchar **) xpm_load); - replace_button_icon(xml, main_wnd->window, style, - "button3", (gchar **) xpm_save); -#endif - replace_button_icon(xml, main_wnd->window, style, - "button4", (gchar **) xpm_single_view); - replace_button_icon(xml, main_wnd->window, style, - "button5", (gchar **) xpm_split_view); - replace_button_icon(xml, main_wnd->window, style, - "button6", (gchar **) xpm_tree_view); - -#if 0 - switch (view_mode) { - case SINGLE_VIEW: - widget = glade_xml_get_widget(xml, "button4"); - g_signal_emit_by_name(widget, "clicked"); - break; - case SPLIT_VIEW: - widget = glade_xml_get_widget(xml, "button5"); - g_signal_emit_by_name(widget, "clicked"); - break; - case FULL_VIEW: - widget = glade_xml_get_widget(xml, "button6"); - g_signal_emit_by_name(widget, "clicked"); - break; - } -#endif - txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); - tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", - "foreground", "red", - "weight", PANGO_WEIGHT_BOLD, - NULL); - tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", - /*"style", PANGO_STYLE_OBLIQUE, */ - NULL); - - gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text); - - gtk_widget_show(main_wnd); -} - -void init_tree_model(void) -{ - gint i; - - tree = tree2 = gtk_tree_store_new(COL_NUMBER, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_POINTER, GDK_TYPE_COLOR, - G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN); - model2 = GTK_TREE_MODEL(tree2); - - for (parents[0] = NULL, i = 1; i < 256; i++) - parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); - - tree1 = gtk_tree_store_new(COL_NUMBER, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_POINTER, GDK_TYPE_COLOR, - G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN); - model1 = GTK_TREE_MODEL(tree1); -} - -void init_left_tree(void) -{ - GtkTreeView *view = GTK_TREE_VIEW(tree1_w); - GtkCellRenderer *renderer; - GtkTreeSelection *sel; - GtkTreeViewColumn *column; - - gtk_tree_view_set_model(view, model1); - gtk_tree_view_set_headers_visible(view, TRUE); - gtk_tree_view_set_rules_hint(view, FALSE); - - column = gtk_tree_view_column_new(); - gtk_tree_view_append_column(view, column); - gtk_tree_view_column_set_title(column, _("Options")); - - renderer = gtk_cell_renderer_toggle_new(); - gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), - renderer, FALSE); - gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), - renderer, - "active", COL_BTNACT, - "inconsistent", COL_BTNINC, - "visible", COL_BTNVIS, - "radio", COL_BTNRAD, NULL); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), - renderer, FALSE); - gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), - renderer, - "text", COL_OPTION, - "foreground-gdk", - COL_COLOR, NULL); - - sel = gtk_tree_view_get_selection(view); - gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); - gtk_widget_realize(tree1_w); -} - -static void renderer_edited(GtkCellRendererText * cell, - const gchar * path_string, - const gchar * new_text, gpointer user_data); -static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, - gchar * arg1, gpointer user_data); - -void init_right_tree(void) -{ - GtkTreeView *view = GTK_TREE_VIEW(tree2_w); - GtkCellRenderer *renderer; - GtkTreeSelection *sel; - GtkTreeViewColumn *column; - gint i; - - gtk_tree_view_set_model(view, model2); - gtk_tree_view_set_headers_visible(view, TRUE); - gtk_tree_view_set_rules_hint(view, FALSE); - - column = gtk_tree_view_column_new(); - gtk_tree_view_append_column(view, column); - gtk_tree_view_column_set_title(column, _("Options")); - - renderer = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), - renderer, FALSE); - gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), - renderer, - "pixbuf", COL_PIXBUF, - "visible", COL_PIXVIS, NULL); - renderer = gtk_cell_renderer_toggle_new(); - gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), - renderer, FALSE); - gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), - renderer, - "active", COL_BTNACT, - "inconsistent", COL_BTNINC, - "visible", COL_BTNVIS, - "radio", COL_BTNRAD, NULL); - /*g_signal_connect(G_OBJECT(renderer), "toggled", - G_CALLBACK(renderer_toggled), NULL); */ - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), - renderer, FALSE); - gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), - renderer, - "text", COL_OPTION, - "foreground-gdk", - COL_COLOR, NULL); - - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(view, -1, - _("Name"), renderer, - "text", COL_NAME, - "foreground-gdk", - COL_COLOR, NULL); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(view, -1, - "N", renderer, - "text", COL_NO, - "foreground-gdk", - COL_COLOR, NULL); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(view, -1, - "M", renderer, - "text", COL_MOD, - "foreground-gdk", - COL_COLOR, NULL); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(view, -1, - "Y", renderer, - "text", COL_YES, - "foreground-gdk", - COL_COLOR, NULL); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(view, -1, - _("Value"), renderer, - "text", COL_VALUE, - "editable", - COL_EDIT, - "foreground-gdk", - COL_COLOR, NULL); - g_signal_connect(G_OBJECT(renderer), "edited", - G_CALLBACK(renderer_edited), NULL); - - column = gtk_tree_view_get_column(view, COL_NAME); - gtk_tree_view_column_set_visible(column, show_name); - column = gtk_tree_view_get_column(view, COL_NO); - gtk_tree_view_column_set_visible(column, show_range); - column = gtk_tree_view_get_column(view, COL_MOD); - gtk_tree_view_column_set_visible(column, show_range); - column = gtk_tree_view_get_column(view, COL_YES); - gtk_tree_view_column_set_visible(column, show_range); - column = gtk_tree_view_get_column(view, COL_VALUE); - gtk_tree_view_column_set_visible(column, show_value); - - if (resizeable) { - for (i = 0; i < COL_VALUE; i++) { - column = gtk_tree_view_get_column(view, i); - gtk_tree_view_column_set_resizable(column, TRUE); - } - } - - sel = gtk_tree_view_get_selection(view); - gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); -} - - -/* Utility Functions */ - - -static void text_insert_help(struct menu *menu) -{ - GtkTextBuffer *buffer; - GtkTextIter start, end; - const char *prompt = _(menu_get_prompt(menu)); - struct gstr help = str_new(); - - menu_get_ext_help(menu, &help); - - buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); - gtk_text_buffer_get_bounds(buffer, &start, &end); - gtk_text_buffer_delete(buffer, &start, &end); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); - - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, - NULL); - gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2, - NULL); - str_free(&help); -} - - -static void text_insert_msg(const char *title, const char *message) -{ - GtkTextBuffer *buffer; - GtkTextIter start, end; - const char *msg = message; - - buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); - gtk_text_buffer_get_bounds(buffer, &start, &end); - gtk_text_buffer_delete(buffer, &start, &end); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); - - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, - NULL); - gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, - NULL); -} - - -/* Main Windows Callbacks */ - -void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); -gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, - gpointer user_data) -{ - GtkWidget *dialog, *label; - gint result; - - if (!conf_get_changed()) - return FALSE; - - dialog = gtk_dialog_new_with_buttons(_("Warning !"), - GTK_WINDOW(main_wnd), - (GtkDialogFlags) - (GTK_DIALOG_MODAL | - GTK_DIALOG_DESTROY_WITH_PARENT), - GTK_STOCK_OK, - GTK_RESPONSE_YES, - GTK_STOCK_NO, - GTK_RESPONSE_NO, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, NULL); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), - GTK_RESPONSE_CANCEL); - - label = gtk_label_new(_("\nSave configuration ?\n")); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); - gtk_widget_show(label); - - result = gtk_dialog_run(GTK_DIALOG(dialog)); - switch (result) { - case GTK_RESPONSE_YES: - on_save_activate(NULL, NULL); - return FALSE; - case GTK_RESPONSE_NO: - return FALSE; - case GTK_RESPONSE_CANCEL: - case GTK_RESPONSE_DELETE_EVENT: - default: - gtk_widget_destroy(dialog); - return TRUE; - } - - return FALSE; -} - - -void on_window1_destroy(GtkObject * object, gpointer user_data) -{ - gtk_main_quit(); -} - - -void -on_window1_size_request(GtkWidget * widget, - GtkRequisition * requisition, gpointer user_data) -{ - static gint old_h; - gint w, h; - - if (widget->window == NULL) - gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); - else - gdk_window_get_size(widget->window, &w, &h); - - if (h == old_h) - return; - old_h = h; - - gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); -} - - -/* Menu & Toolbar Callbacks */ - - -static void -load_filename(GtkFileSelection * file_selector, gpointer user_data) -{ - const gchar *fn; - - fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION - (user_data)); - - if (conf_read(fn)) - text_insert_msg(_("Error"), _("Unable to load configuration !")); - else - display_tree(&rootmenu); -} - -void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkWidget *fs; - - fs = gtk_file_selection_new(_("Load file...")); - g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), - "clicked", - G_CALLBACK(load_filename), (gpointer) fs); - g_signal_connect_swapped(GTK_OBJECT - (GTK_FILE_SELECTION(fs)->ok_button), - "clicked", G_CALLBACK(gtk_widget_destroy), - (gpointer) fs); - g_signal_connect_swapped(GTK_OBJECT - (GTK_FILE_SELECTION(fs)->cancel_button), - "clicked", G_CALLBACK(gtk_widget_destroy), - (gpointer) fs); - gtk_widget_show(fs); -} - - -void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - if (conf_write(NULL)) - text_insert_msg(_("Error"), _("Unable to save configuration !")); -} - - -static void -store_filename(GtkFileSelection * file_selector, gpointer user_data) -{ - const gchar *fn; - - fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION - (user_data)); - - if (conf_write(fn)) - text_insert_msg(_("Error"), _("Unable to save configuration !")); - - gtk_widget_destroy(GTK_WIDGET(user_data)); -} - -void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkWidget *fs; - - fs = gtk_file_selection_new(_("Save file as...")); - g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), - "clicked", - G_CALLBACK(store_filename), (gpointer) fs); - g_signal_connect_swapped(GTK_OBJECT - (GTK_FILE_SELECTION(fs)->ok_button), - "clicked", G_CALLBACK(gtk_widget_destroy), - (gpointer) fs); - g_signal_connect_swapped(GTK_OBJECT - (GTK_FILE_SELECTION(fs)->cancel_button), - "clicked", G_CALLBACK(gtk_widget_destroy), - (gpointer) fs); - gtk_widget_show(fs); -} - - -void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - if (!on_window1_delete_event(NULL, NULL, NULL)) - gtk_widget_destroy(GTK_WIDGET(main_wnd)); -} - - -void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkTreeViewColumn *col; - - show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; - col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); - if (col) - gtk_tree_view_column_set_visible(col, show_name); -} - - -void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkTreeViewColumn *col; - - show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; - col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); - if (col) - gtk_tree_view_column_set_visible(col, show_range); - col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); - if (col) - gtk_tree_view_column_set_visible(col, show_range); - col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); - if (col) - gtk_tree_view_column_set_visible(col, show_range); - -} - - -void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkTreeViewColumn *col; - - show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; - col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); - if (col) - gtk_tree_view_column_set_visible(col, show_value); -} - - -void -on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data) -{ - opt_mode = OPT_NORMAL; - gtk_tree_store_clear(tree2); - display_tree(&rootmenu); /* instead of update_tree to speed-up */ -} - - -void -on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data) -{ - opt_mode = OPT_ALL; - gtk_tree_store_clear(tree2); - display_tree(&rootmenu); /* instead of update_tree to speed-up */ -} - - -void -on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data) -{ - opt_mode = OPT_PROMPT; - gtk_tree_store_clear(tree2); - display_tree(&rootmenu); /* instead of update_tree to speed-up */ -} - - -void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkWidget *dialog; - const gchar *intro_text = _( - "Welcome to gkc, the GTK+ graphical configuration tool\n" - "For each option, a blank box indicates the feature is disabled, a\n" - "check indicates it is enabled, and a dot indicates that it is to\n" - "be compiled as a module. Clicking on the box will cycle through the three states.\n" - "\n" - "If you do not see an option (e.g., a device driver) that you\n" - "believe should be present, try turning on Show All Options\n" - "under the Options menu.\n" - "Although there is no cross reference yet to help you figure out\n" - "what other options must be enabled to support the option you\n" - "are interested in, you can still view the help of a grayed-out\n" - "option.\n" - "\n" - "Toggling Show Debug Info under the Options menu will show \n" - "the dependencies, which you can then match by examining other options."); - - dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, intro_text); - g_signal_connect_swapped(GTK_OBJECT(dialog), "response", - G_CALLBACK(gtk_widget_destroy), - GTK_OBJECT(dialog)); - gtk_widget_show_all(dialog); -} - - -void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkWidget *dialog; - const gchar *about_text = - _("gkc is copyright (c) 2002 Romain Lievin .\n" - "Based on the source code from Roman Zippel.\n"); - - dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, about_text); - g_signal_connect_swapped(GTK_OBJECT(dialog), "response", - G_CALLBACK(gtk_widget_destroy), - GTK_OBJECT(dialog)); - gtk_widget_show_all(dialog); -} - - -void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) -{ - GtkWidget *dialog; - const gchar *license_text = - _("gkc is released under the terms of the GNU GPL v2.\n" - "For more information, please see the source code or\n" - "visit http://www.fsf.org/licenses/licenses.html\n"); - - dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, license_text); - g_signal_connect_swapped(GTK_OBJECT(dialog), "response", - G_CALLBACK(gtk_widget_destroy), - GTK_OBJECT(dialog)); - gtk_widget_show_all(dialog); -} - - -void on_back_clicked(GtkButton * button, gpointer user_data) -{ - enum prop_type ptype; - - current = current->parent; - ptype = current->prompt ? current->prompt->type : P_UNKNOWN; - if (ptype != P_MENU) - current = current->parent; - display_tree_part(); - - if (current == &rootmenu) - gtk_widget_set_sensitive(back_btn, FALSE); -} - - -void on_load_clicked(GtkButton * button, gpointer user_data) -{ - on_load1_activate(NULL, user_data); -} - - -void on_single_clicked(GtkButton * button, gpointer user_data) -{ - view_mode = SINGLE_VIEW; - gtk_paned_set_position(GTK_PANED(hpaned), 0); - gtk_widget_hide(tree1_w); - current = &rootmenu; - display_tree_part(); -} - - -void on_split_clicked(GtkButton * button, gpointer user_data) -{ - gint w, h; - view_mode = SPLIT_VIEW; - gtk_widget_show(tree1_w); - gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); - gtk_paned_set_position(GTK_PANED(hpaned), w / 2); - if (tree2) - gtk_tree_store_clear(tree2); - display_list(); - - /* Disable back btn, like in full mode. */ - gtk_widget_set_sensitive(back_btn, FALSE); -} - - -void on_full_clicked(GtkButton * button, gpointer user_data) -{ - view_mode = FULL_VIEW; - gtk_paned_set_position(GTK_PANED(hpaned), 0); - gtk_widget_hide(tree1_w); - if (tree2) - gtk_tree_store_clear(tree2); - display_tree(&rootmenu); - gtk_widget_set_sensitive(back_btn, FALSE); -} - - -void on_collapse_clicked(GtkButton * button, gpointer user_data) -{ - gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); -} - - -void on_expand_clicked(GtkButton * button, gpointer user_data) -{ - gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); -} - - -/* CTree Callbacks */ - -/* Change hex/int/string value in the cell */ -static void renderer_edited(GtkCellRendererText * cell, - const gchar * path_string, - const gchar * new_text, gpointer user_data) -{ - GtkTreePath *path = gtk_tree_path_new_from_string(path_string); - GtkTreeIter iter; - const char *old_def, *new_def; - struct menu *menu; - struct symbol *sym; - - if (!gtk_tree_model_get_iter(model2, &iter, path)) - return; - - gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); - sym = menu->sym; - - gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); - new_def = new_text; - - sym_set_string_value(sym, new_def); - - update_tree(&rootmenu, NULL); - - gtk_tree_path_free(path); -} - -/* Change the value of a symbol and update the tree */ -static void change_sym_value(struct menu *menu, gint col) -{ - struct symbol *sym = menu->sym; - tristate oldval, newval; - - if (!sym) - return; - - if (col == COL_NO) - newval = no; - else if (col == COL_MOD) - newval = mod; - else if (col == COL_YES) - newval = yes; - else - return; - - switch (sym_get_type(sym)) { - case S_BOOLEAN: - case S_TRISTATE: - oldval = sym_get_tristate_value(sym); - if (!sym_tristate_within_range(sym, newval)) - newval = yes; - sym_set_tristate_value(sym, newval); - if (view_mode == FULL_VIEW) - update_tree(&rootmenu, NULL); - else if (view_mode == SPLIT_VIEW) { - update_tree(browsed, NULL); - display_list(); - } - else if (view_mode == SINGLE_VIEW) - display_tree_part(); //fixme: keep exp/coll - break; - case S_INT: - case S_HEX: - case S_STRING: - default: - break; - } -} - -static void toggle_sym_value(struct menu *menu) -{ - if (!menu->sym) - return; - - sym_toggle_tristate_value(menu->sym); - if (view_mode == FULL_VIEW) - update_tree(&rootmenu, NULL); - else if (view_mode == SPLIT_VIEW) { - update_tree(browsed, NULL); - display_list(); - } - else if (view_mode == SINGLE_VIEW) - display_tree_part(); //fixme: keep exp/coll -} - -static void renderer_toggled(GtkCellRendererToggle * cell, - gchar * path_string, gpointer user_data) -{ - GtkTreePath *path, *sel_path = NULL; - GtkTreeIter iter, sel_iter; - GtkTreeSelection *sel; - struct menu *menu; - - path = gtk_tree_path_new_from_string(path_string); - if (!gtk_tree_model_get_iter(model2, &iter, path)) - return; - - sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); - if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) - sel_path = gtk_tree_model_get_path(model2, &sel_iter); - if (!sel_path) - goto out1; - if (gtk_tree_path_compare(path, sel_path)) - goto out2; - - gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); - toggle_sym_value(menu); - - out2: - gtk_tree_path_free(sel_path); - out1: - gtk_tree_path_free(path); -} - -static gint column2index(GtkTreeViewColumn * column) -{ - gint i; - - for (i = 0; i < COL_NUMBER; i++) { - GtkTreeViewColumn *col; - - col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); - if (col == column) - return i; - } - - return -1; -} - - -/* User click: update choice (full) or goes down (single) */ -gboolean -on_treeview2_button_press_event(GtkWidget * widget, - GdkEventButton * event, gpointer user_data) -{ - GtkTreeView *view = GTK_TREE_VIEW(widget); - GtkTreePath *path; - GtkTreeViewColumn *column; - GtkTreeIter iter; - struct menu *menu; - gint col; - -#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK - gint tx = (gint) event->x; - gint ty = (gint) event->y; - gint cx, cy; - - gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, - &cy); -#else - gtk_tree_view_get_cursor(view, &path, &column); -#endif - if (path == NULL) - return FALSE; - - if (!gtk_tree_model_get_iter(model2, &iter, path)) - return FALSE; - gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); - - col = column2index(column); - if (event->type == GDK_2BUTTON_PRESS) { - enum prop_type ptype; - ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; - - if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { - // goes down into menu - current = menu; - display_tree_part(); - gtk_widget_set_sensitive(back_btn, TRUE); - } else if ((col == COL_OPTION)) { - toggle_sym_value(menu); - gtk_tree_view_expand_row(view, path, TRUE); - } - } else { - if (col == COL_VALUE) { - toggle_sym_value(menu); - gtk_tree_view_expand_row(view, path, TRUE); - } else if (col == COL_NO || col == COL_MOD - || col == COL_YES) { - change_sym_value(menu, col); - gtk_tree_view_expand_row(view, path, TRUE); - } - } - - return FALSE; -} - -/* Key pressed: update choice */ -gboolean -on_treeview2_key_press_event(GtkWidget * widget, - GdkEventKey * event, gpointer user_data) -{ - GtkTreeView *view = GTK_TREE_VIEW(widget); - GtkTreePath *path; - GtkTreeViewColumn *column; - GtkTreeIter iter; - struct menu *menu; - gint col; - - gtk_tree_view_get_cursor(view, &path, &column); - if (path == NULL) - return FALSE; - - if (event->keyval == GDK_space) { - if (gtk_tree_view_row_expanded(view, path)) - gtk_tree_view_collapse_row(view, path); - else - gtk_tree_view_expand_row(view, path, FALSE); - return TRUE; - } - if (event->keyval == GDK_KP_Enter) { - } - if (widget == tree1_w) - return FALSE; - - gtk_tree_model_get_iter(model2, &iter, path); - gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); - - if (!strcasecmp(event->string, "n")) - col = COL_NO; - else if (!strcasecmp(event->string, "m")) - col = COL_MOD; - else if (!strcasecmp(event->string, "y")) - col = COL_YES; - else - col = -1; - change_sym_value(menu, col); - - return FALSE; -} - - -/* Row selection changed: update help */ -void -on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) -{ - GtkTreeSelection *selection; - GtkTreeIter iter; - struct menu *menu; - - selection = gtk_tree_view_get_selection(treeview); - if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { - gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); - text_insert_help(menu); - } -} - - -/* User click: display sub-tree in the right frame. */ -gboolean -on_treeview1_button_press_event(GtkWidget * widget, - GdkEventButton * event, gpointer user_data) -{ - GtkTreeView *view = GTK_TREE_VIEW(widget); - GtkTreePath *path; - GtkTreeViewColumn *column; - GtkTreeIter iter; - struct menu *menu; - - gint tx = (gint) event->x; - gint ty = (gint) event->y; - gint cx, cy; - - gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, - &cy); - if (path == NULL) - return FALSE; - - gtk_tree_model_get_iter(model1, &iter, path); - gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); - - if (event->type == GDK_2BUTTON_PRESS) { - toggle_sym_value(menu); - current = menu; - display_tree_part(); - } else { - browsed = menu; - display_tree_part(); - } - - gtk_widget_realize(tree2_w); - gtk_tree_view_set_cursor(view, path, NULL, FALSE); - gtk_widget_grab_focus(tree2_w); - - return FALSE; -} - - -/* Fill a row of strings */ -static gchar **fill_row(struct menu *menu) -{ - static gchar *row[COL_NUMBER]; - struct symbol *sym = menu->sym; - const char *def; - int stype; - tristate val; - enum prop_type ptype; - int i; - - for (i = COL_OPTION; i <= COL_COLOR; i++) - g_free(row[i]); - bzero(row, sizeof(row)); - - row[COL_OPTION] = - g_strdup_printf("%s %s", _(menu_get_prompt(menu)), - sym && !sym_has_value(sym) ? "(NEW)" : ""); - - if (opt_mode == OPT_ALL && !menu_is_visible(menu)) - row[COL_COLOR] = g_strdup("DarkGray"); - else if (opt_mode == OPT_PROMPT && - menu_has_prompt(menu) && !menu_is_visible(menu)) - row[COL_COLOR] = g_strdup("DarkGray"); - else - row[COL_COLOR] = g_strdup("Black"); - - ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; - switch (ptype) { - case P_MENU: - row[COL_PIXBUF] = (gchar *) xpm_menu; - if (view_mode == SINGLE_VIEW) - row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); - row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); - break; - case P_COMMENT: - row[COL_PIXBUF] = (gchar *) xpm_void; - row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); - row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); - break; - default: - row[COL_PIXBUF] = (gchar *) xpm_void; - row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); - row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); - break; - } - - if (!sym) - return row; - row[COL_NAME] = g_strdup(sym->name); - - sym_calc_value(sym); - sym->flags &= ~SYMBOL_CHANGED; - - if (sym_is_choice(sym)) { // parse childs for getting final value - struct menu *child; - struct symbol *def_sym = sym_get_choice_value(sym); - struct menu *def_menu = NULL; - - row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); - - for (child = menu->list; child; child = child->next) { - if (menu_is_visible(child) - && child->sym == def_sym) - def_menu = child; - } - - if (def_menu) - row[COL_VALUE] = - g_strdup(_(menu_get_prompt(def_menu))); - } - if (sym->flags & SYMBOL_CHOICEVAL) - row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); - - stype = sym_get_type(sym); - switch (stype) { - case S_BOOLEAN: - if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) - row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); - if (sym_is_choice(sym)) - break; - case S_TRISTATE: - val = sym_get_tristate_value(sym); - switch (val) { - case no: - row[COL_NO] = g_strdup("N"); - row[COL_VALUE] = g_strdup("N"); - row[COL_BTNACT] = GINT_TO_POINTER(FALSE); - row[COL_BTNINC] = GINT_TO_POINTER(FALSE); - break; - case mod: - row[COL_MOD] = g_strdup("M"); - row[COL_VALUE] = g_strdup("M"); - row[COL_BTNINC] = GINT_TO_POINTER(TRUE); - break; - case yes: - row[COL_YES] = g_strdup("Y"); - row[COL_VALUE] = g_strdup("Y"); - row[COL_BTNACT] = GINT_TO_POINTER(TRUE); - row[COL_BTNINC] = GINT_TO_POINTER(FALSE); - break; - } - - if (val != no && sym_tristate_within_range(sym, no)) - row[COL_NO] = g_strdup("_"); - if (val != mod && sym_tristate_within_range(sym, mod)) - row[COL_MOD] = g_strdup("_"); - if (val != yes && sym_tristate_within_range(sym, yes)) - row[COL_YES] = g_strdup("_"); - break; - case S_INT: - case S_HEX: - case S_STRING: - def = sym_get_string_value(sym); - row[COL_VALUE] = g_strdup(def); - row[COL_EDIT] = GINT_TO_POINTER(TRUE); - row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); - break; - } - - return row; -} - - -/* Set the node content with a row of strings */ -static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) -{ - GdkColor color; - gboolean success; - GdkPixbuf *pix; - - pix = gdk_pixbuf_new_from_xpm_data((const char **) - row[COL_PIXBUF]); - - gdk_color_parse(row[COL_COLOR], &color); - gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, - FALSE, FALSE, &success); - - gtk_tree_store_set(tree, node, - COL_OPTION, row[COL_OPTION], - COL_NAME, row[COL_NAME], - COL_NO, row[COL_NO], - COL_MOD, row[COL_MOD], - COL_YES, row[COL_YES], - COL_VALUE, row[COL_VALUE], - COL_MENU, (gpointer) menu, - COL_COLOR, &color, - COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), - COL_PIXBUF, pix, - COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), - COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), - COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), - COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), - COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), - -1); - - g_object_unref(pix); -} - - -/* Add a node to the tree */ -static void place_node(struct menu *menu, char **row) -{ - GtkTreeIter *parent = parents[indent - 1]; - GtkTreeIter *node = parents[indent]; - - gtk_tree_store_append(tree, node, parent); - set_node(node, menu, row); -} - - -/* Find a node in the GTK+ tree */ -static GtkTreeIter found; - -/* - * Find a menu in the GtkTree starting at parent. - */ -GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, - struct menu *tofind) -{ - GtkTreeIter iter; - GtkTreeIter *child = &iter; - gboolean valid; - GtkTreeIter *ret; - - valid = gtk_tree_model_iter_children(model2, child, parent); - while (valid) { - struct menu *menu; - - gtk_tree_model_get(model2, child, 6, &menu, -1); - - if (menu == tofind) { - memcpy(&found, child, sizeof(GtkTreeIter)); - return &found; - } - - ret = gtktree_iter_find_node(child, tofind); - if (ret) - return ret; - - valid = gtk_tree_model_iter_next(model2, child); - } - - return NULL; -} - - -/* - * Update the tree by adding/removing entries - * Does not change other nodes - */ -static void update_tree(struct menu *src, GtkTreeIter * dst) -{ - struct menu *child1; - GtkTreeIter iter, tmp; - GtkTreeIter *child2 = &iter; - gboolean valid; - GtkTreeIter *sibling; - struct symbol *sym; - struct property *prop; - struct menu *menu1, *menu2; - - if (src == &rootmenu) - indent = 1; - - valid = gtk_tree_model_iter_children(model2, child2, dst); - for (child1 = src->list; child1; child1 = child1->next) { - - prop = child1->prompt; - sym = child1->sym; - - reparse: - menu1 = child1; - if (valid) - gtk_tree_model_get(model2, child2, COL_MENU, - &menu2, -1); - else - menu2 = NULL; // force adding of a first child - -#ifdef DEBUG - printf("%*c%s | %s\n", indent, ' ', - menu1 ? menu_get_prompt(menu1) : "nil", - menu2 ? menu_get_prompt(menu2) : "nil"); -#endif - - if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || - (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) || - (opt_mode == OPT_ALL && !menu_get_prompt(child1))) { - - /* remove node */ - if (gtktree_iter_find_node(dst, menu1) != NULL) { - memcpy(&tmp, child2, sizeof(GtkTreeIter)); - valid = gtk_tree_model_iter_next(model2, - child2); - gtk_tree_store_remove(tree2, &tmp); - if (!valid) - return; /* next parent */ - else - goto reparse; /* next child */ - } else - continue; - } - - if (menu1 != menu2) { - if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node - if (!valid && !menu2) - sibling = NULL; - else - sibling = child2; - gtk_tree_store_insert_before(tree2, - child2, - dst, sibling); - set_node(child2, menu1, fill_row(menu1)); - if (menu2 == NULL) - valid = TRUE; - } else { // remove node - memcpy(&tmp, child2, sizeof(GtkTreeIter)); - valid = gtk_tree_model_iter_next(model2, - child2); - gtk_tree_store_remove(tree2, &tmp); - if (!valid) - return; // next parent - else - goto reparse; // next child - } - } else if (sym && (sym->flags & SYMBOL_CHANGED)) { - set_node(child2, menu1, fill_row(menu1)); - } - - indent++; - update_tree(child1, child2); - indent--; - - valid = gtk_tree_model_iter_next(model2, child2); - } -} - - -/* Display the whole tree (single/split/full view) */ -static void display_tree(struct menu *menu) -{ - struct symbol *sym; - struct property *prop; - struct menu *child; - enum prop_type ptype; - - if (menu == &rootmenu) { - indent = 1; - current = &rootmenu; - } - - for (child = menu->list; child; child = child->next) { - prop = child->prompt; - sym = child->sym; - ptype = prop ? prop->type : P_UNKNOWN; - - if (sym) - sym->flags &= ~SYMBOL_CHANGED; - - if ((view_mode == SPLIT_VIEW) - && !(child->flags & MENU_ROOT) && (tree == tree1)) - continue; - - if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) - && (tree == tree2)) - continue; - - if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || - (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || - (opt_mode == OPT_ALL && menu_get_prompt(child))) - place_node(child, fill_row(child)); -#ifdef DEBUG - printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); - printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); - printf("%s", prop_get_type_name(ptype)); - printf(" | "); - if (sym) { - printf("%s", sym_type_name(sym->type)); - printf(" | "); - printf("%s", dbg_sym_flags(sym->flags)); - printf("\n"); - } else - printf("\n"); -#endif - if ((view_mode != FULL_VIEW) && (ptype == P_MENU) - && (tree == tree2)) - continue; -/* - if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) - || (view_mode == FULL_VIEW) - || (view_mode == SPLIT_VIEW))*/ - if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) - || (view_mode == FULL_VIEW) - || (view_mode == SPLIT_VIEW)) { - indent++; - display_tree(child); - indent--; - } - } -} - -/* Display a part of the tree starting at current node (single/split view) */ -static void display_tree_part(void) -{ - if (tree2) - gtk_tree_store_clear(tree2); - if (view_mode == SINGLE_VIEW) - display_tree(current); - else if (view_mode == SPLIT_VIEW) - display_tree(browsed); - gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); -} - -/* Display the list in the left frame (split view) */ -static void display_list(void) -{ - if (tree1) - gtk_tree_store_clear(tree1); - - tree = tree1; - display_tree(&rootmenu); - gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); - tree = tree2; -} - -void fixup_rootmenu(struct menu *menu) -{ - struct menu *child; - static int menu_cnt = 0; - - menu->flags |= MENU_ROOT; - for (child = menu->list; child; child = child->next) { - if (child->prompt && child->prompt->type == P_MENU) { - menu_cnt++; - fixup_rootmenu(child); - menu_cnt--; - } else if (!menu_cnt) - fixup_rootmenu(child); - } -} - - -/* Main */ -int main(int ac, char *av[]) -{ - const char *name; - char *env; - gchar *glade_file; - -#ifndef LKC_DIRECT_LINK - kconfig_load(); -#endif - - bindtextdomain(PACKAGE, LOCALEDIR); - bind_textdomain_codeset(PACKAGE, "UTF-8"); - textdomain(PACKAGE); - - /* GTK stuffs */ - gtk_set_locale(); - gtk_init(&ac, &av); - glade_init(); - - //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); - //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); - - /* Determine GUI path */ - env = getenv(SRCTREE); - if (env) - glade_file = g_strconcat(env, "/tools/kconfig/gconf.glade", NULL); - else if (av[0][0] == '/') - glade_file = g_strconcat(av[0], ".glade", NULL); - else - glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); - - /* Conf stuffs */ - if (ac > 1 && av[1][0] == '-') { - switch (av[1][1]) { - case 'a': - //showAll = 1; - break; - case 'h': - case '?': - printf("%s \n", av[0]); - exit(0); - } - name = av[2]; - } else - name = av[1]; - - conf_parse(name); - fixup_rootmenu(&rootmenu); - conf_read(NULL); - - /* Load the interface and connect signals */ - init_main_window(glade_file); - init_tree_model(); - init_left_tree(); - init_right_tree(); - - switch (view_mode) { - case SINGLE_VIEW: - display_tree_part(); - break; - case SPLIT_VIEW: - display_list(); - break; - case FULL_VIEW: - display_tree(&rootmenu); - break; - } - - gtk_main(); - - return 0; -} - -static void conf_changed(void) -{ - bool changed = conf_get_changed(); - gtk_widget_set_sensitive(save_btn, changed); - gtk_widget_set_sensitive(save_menu_item, changed); -} diff -Nru seabios-1.7.1/tools/kconfig/gconf.glade seabios-1.7.4/tools/kconfig/gconf.glade --- seabios-1.7.1/tools/kconfig/gconf.glade 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/gconf.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,661 +0,0 @@ - - - - - - True - Gtk Kernel Configurator - GTK_WINDOW_TOPLEVEL - GTK_WIN_POS_NONE - False - 640 - 480 - True - False - True - False - False - GDK_WINDOW_TYPE_HINT_NORMAL - GDK_GRAVITY_NORTH_WEST - - - - - - - True - False - 0 - - - - True - - - - True - _File - True - - - - - - - True - Load a config file - _Load - True - - - - - - True - gtk-open - 1 - 0.5 - 0.5 - 0 - 0 - - - - - - - - True - Save the config in .config - _Save - True - - - - - - True - gtk-save - 1 - 0.5 - 0.5 - 0 - 0 - - - - - - - - True - Save the config in a file - Save _as - True - - - - - True - gtk-save-as - 1 - 0.5 - 0.5 - 0 - 0 - - - - - - - - True - - - - - - True - _Quit - True - - - - - - True - gtk-quit - 1 - 0.5 - 0.5 - 0 - 0 - - - - - - - - - - - - True - _Options - True - - - - - - - True - Show name - Show _name - True - False - - - - - - - True - Show range (Y/M/N) - Show _range - True - False - - - - - - - True - Show value of the option - Show _data - True - False - - - - - - - True - - - - - - True - Show normal options - Show normal options - True - True - - - - - - - True - Show all options - Show all _options - True - False - set_option_mode1 - - - - - - - True - Show all options with prompts - Show all prompt options - True - False - set_option_mode1 - - - - - - - - - - - - True - _Help - True - - - - - - - True - _Introduction - True - - - - - - True - gtk-dialog-question - 1 - 0.5 - 0.5 - 0 - 0 - - - - - - - - True - _About - True - - - - - - True - gtk-properties - 1 - 0.5 - 0.5 - 0 - 0 - - - - - - - - True - _License - True - - - - - True - gtk-justify-fill - 1 - 0.5 - 0.5 - 0 - 0 - - - - - - - - - - - 0 - False - False - - - - - - True - GTK_SHADOW_OUT - GTK_POS_LEFT - GTK_POS_TOP - - - - True - GTK_ORIENTATION_HORIZONTAL - GTK_TOOLBAR_BOTH - True - True - - - - True - Goes up of one level (single view) - Back - True - gtk-undo - True - True - False - - - - False - True - - - - - - True - True - True - False - - - - True - - - - - False - False - - - - - - True - Load a config file - Load - True - gtk-open - True - True - False - - - - False - True - - - - - - True - Save a config file - Save - True - gtk-save - True - True - False - - - - False - True - - - - - - True - True - True - False - - - - True - - - - - False - False - - - - - - True - Single view - Single - True - gtk-missing-image - True - True - False - - - - False - True - - - - - - True - Split view - Split - True - gtk-missing-image - True - True - False - - - - False - True - - - - - - True - Full view - Full - True - gtk-missing-image - True - True - False - - - - False - True - - - - - - True - True - True - False - - - - True - - - - - False - False - - - - - - True - Collapse the whole tree in the right frame - Collapse - True - gtk-remove - True - True - False - - - - False - True - - - - - - True - Expand the whole tree in the right frame - Expand - True - gtk-add - True - True - False - - - - False - True - - - - - - - 0 - False - False - - - - - - 1 - True - True - 0 - - - - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT - - - - True - True - True - False - False - False - - - - - - - - True - False - - - - - - True - True - 0 - - - - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT - - - - True - True - True - True - False - False - False - - - - - - - - True - False - - - - - - True - GTK_POLICY_NEVER - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT - - - - True - True - False - False - True - GTK_JUSTIFY_LEFT - GTK_WRAP_WORD - True - 0 - 0 - 0 - 0 - 0 - 0 - Sorry, no help available for this option yet. - - - - - True - True - - - - - True - True - - - - - 0 - True - True - - - - - - - diff -Nru seabios-1.7.1/tools/kconfig/.gitignore seabios-1.7.4/tools/kconfig/.gitignore --- seabios-1.7.1/tools/kconfig/.gitignore 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -# -# Generated files -# -config* -lex.*.c -*.tab.c -*.tab.h -zconf.hash.c -*.moc -lkc_defs.h -gconf.glade.h -*.pot -*.mo - -# -# configuration programs -# -conf -mconf -nconf -qconf -gconf -kxgettext diff -Nru seabios-1.7.1/tools/kconfig/images.c seabios-1.7.4/tools/kconfig/images.c --- seabios-1.7.1/tools/kconfig/images.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/images.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,326 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -static const char *xpm_load[] = { -"22 22 5 1", -". c None", -"# c #000000", -"c c #838100", -"a c #ffff00", -"b c #ffffff", -"......................", -"......................", -"......................", -"............####....#.", -"...........#....##.##.", -"..................###.", -".................####.", -".####...........#####.", -"#abab##########.......", -"#babababababab#.......", -"#ababababababa#.......", -"#babababababab#.......", -"#ababab###############", -"#babab##cccccccccccc##", -"#abab##cccccccccccc##.", -"#bab##cccccccccccc##..", -"#ab##cccccccccccc##...", -"#b##cccccccccccc##....", -"###cccccccccccc##.....", -"##cccccccccccc##......", -"###############.......", -"......................"}; - -static const char *xpm_save[] = { -"22 22 5 1", -". c None", -"# c #000000", -"a c #838100", -"b c #c5c2c5", -"c c #cdb6d5", -"......................", -".####################.", -".#aa#bbbbbbbbbbbb#bb#.", -".#aa#bbbbbbbbbbbb#bb#.", -".#aa#bbbbbbbbbcbb####.", -".#aa#bbbccbbbbbbb#aa#.", -".#aa#bbbccbbbbbbb#aa#.", -".#aa#bbbbbbbbbbbb#aa#.", -".#aa#bbbbbbbbbbbb#aa#.", -".#aa#bbbbbbbbbbbb#aa#.", -".#aa#bbbbbbbbbbbb#aa#.", -".#aaa############aaa#.", -".#aaaaaaaaaaaaaaaaaa#.", -".#aaaaaaaaaaaaaaaaaa#.", -".#aaa#############aa#.", -".#aaa#########bbb#aa#.", -".#aaa#########bbb#aa#.", -".#aaa#########bbb#aa#.", -".#aaa#########bbb#aa#.", -".#aaa#########bbb#aa#.", -"..##################..", -"......................"}; - -static const char *xpm_back[] = { -"22 22 3 1", -". c None", -"# c #000083", -"a c #838183", -"......................", -"......................", -"......................", -"......................", -"......................", -"...........######a....", -"..#......##########...", -"..##...####......##a..", -"..###.###.........##..", -"..######..........##..", -"..#####...........##..", -"..######..........##..", -"..#######.........##..", -"..########.......##a..", -"...............a###...", -"...............###....", -"......................", -"......................", -"......................", -"......................", -"......................", -"......................"}; - -static const char *xpm_tree_view[] = { -"22 22 2 1", -". c None", -"# c #000000", -"......................", -"......................", -"......#...............", -"......#...............", -"......#...............", -"......#...............", -"......#...............", -"......########........", -"......#...............", -"......#...............", -"......#...............", -"......#...............", -"......#...............", -"......########........", -"......#...............", -"......#...............", -"......#...............", -"......#...............", -"......#...............", -"......########........", -"......................", -"......................"}; - -static const char *xpm_single_view[] = { -"22 22 2 1", -". c None", -"# c #000000", -"......................", -"......................", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"..........#...........", -"......................", -"......................"}; - -static const char *xpm_split_view[] = { -"22 22 2 1", -". c None", -"# c #000000", -"......................", -"......................", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......#......#........", -"......................", -"......................"}; - -static const char *xpm_symbol_no[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .......... ", -" . . ", -" . . ", -" . . ", -" . . ", -" . . ", -" . . ", -" . . ", -" . . ", -" .......... ", -" "}; - -static const char *xpm_symbol_mod[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .......... ", -" . . ", -" . . ", -" . .. . ", -" . .... . ", -" . .... . ", -" . .. . ", -" . . ", -" . . ", -" .......... ", -" "}; - -static const char *xpm_symbol_yes[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .......... ", -" . . ", -" . . ", -" . . . ", -" . .. . ", -" . . .. . ", -" . .... . ", -" . .. . ", -" . . ", -" .......... ", -" "}; - -static const char *xpm_choice_no[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .... ", -" .. .. ", -" . . ", -" . . ", -" . . ", -" . . ", -" . . ", -" . . ", -" .. .. ", -" .... ", -" "}; - -static const char *xpm_choice_yes[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .... ", -" .. .. ", -" . . ", -" . .. . ", -" . .... . ", -" . .... . ", -" . .. . ", -" . . ", -" .. .. ", -" .... ", -" "}; - -static const char *xpm_menu[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .......... ", -" . . ", -" . .. . ", -" . .... . ", -" . ...... . ", -" . ...... . ", -" . .... . ", -" . .. . ", -" . . ", -" .......... ", -" "}; - -static const char *xpm_menu_inv[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .......... ", -" .......... ", -" .. ...... ", -" .. .... ", -" .. .. ", -" .. .. ", -" .. .... ", -" .. ...... ", -" .......... ", -" .......... ", -" "}; - -static const char *xpm_menuback[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" .......... ", -" . . ", -" . .. . ", -" . .... . ", -" . ...... . ", -" . ...... . ", -" . .... . ", -" . .. . ", -" . . ", -" .......... ", -" "}; - -static const char *xpm_void[] = { -"12 12 2 1", -" c white", -". c black", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; diff -Nru seabios-1.7.1/tools/kconfig/kconfig_load.c seabios-1.7.4/tools/kconfig/kconfig_load.c --- seabios-1.7.1/tools/kconfig/kconfig_load.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/kconfig_load.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -#include -#include -#include - -#include "lkc.h" - -#define P(name,type,arg) type (*name ## _p) arg -#include "lkc_proto.h" -#undef P - -void kconfig_load(void) -{ - void *handle; - char *error; - - handle = dlopen("./libkconfig.so", RTLD_LAZY); - if (!handle) { - handle = dlopen("./tools/kconfig/libkconfig.so", RTLD_LAZY); - if (!handle) { - fprintf(stderr, "%s\n", dlerror()); - exit(1); - } - } - -#define P(name,type,arg) \ -{ \ - name ## _p = dlsym(handle, #name); \ - if ((error = dlerror())) { \ - fprintf(stderr, "%s\n", error); \ - exit(1); \ - } \ -} -#include "lkc_proto.h" -#undef P -} diff -Nru seabios-1.7.1/tools/kconfig/kxgettext.c seabios-1.7.4/tools/kconfig/kxgettext.c --- seabios-1.7.1/tools/kconfig/kxgettext.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/kxgettext.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,236 +0,0 @@ -/* - * Arnaldo Carvalho de Melo , 2005 - * - * Released under the terms of the GNU GPL v2.0 - */ - -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -static char *escape(const char* text, char *bf, int len) -{ - char *bfp = bf; - int multiline = strchr(text, '\n') != NULL; - int eol = 0; - int textlen = strlen(text); - - if ((textlen > 0) && (text[textlen-1] == '\n')) - eol = 1; - - *bfp++ = '"'; - --len; - - if (multiline) { - *bfp++ = '"'; - *bfp++ = '\n'; - *bfp++ = '"'; - len -= 3; - } - - while (*text != '\0' && len > 1) { - if (*text == '"') - *bfp++ = '\\'; - else if (*text == '\n') { - *bfp++ = '\\'; - *bfp++ = 'n'; - *bfp++ = '"'; - *bfp++ = '\n'; - *bfp++ = '"'; - len -= 5; - ++text; - goto next; - } - else if (*text == '\\') { - *bfp++ = '\\'; - len--; - } - *bfp++ = *text++; -next: - --len; - } - - if (multiline && eol) - bfp -= 3; - - *bfp++ = '"'; - *bfp = '\0'; - - return bf; -} - -struct file_line { - struct file_line *next; - const char *file; - int lineno; -}; - -static struct file_line *file_line__new(const char *file, int lineno) -{ - struct file_line *self = malloc(sizeof(*self)); - - if (self == NULL) - goto out; - - self->file = file; - self->lineno = lineno; - self->next = NULL; -out: - return self; -} - -struct message { - const char *msg; - const char *option; - struct message *next; - struct file_line *files; -}; - -static struct message *message__list; - -static struct message *message__new(const char *msg, char *option, - const char *file, int lineno) -{ - struct message *self = malloc(sizeof(*self)); - - if (self == NULL) - goto out; - - self->files = file_line__new(file, lineno); - if (self->files == NULL) - goto out_fail; - - self->msg = strdup(msg); - if (self->msg == NULL) - goto out_fail_msg; - - self->option = option; - self->next = NULL; -out: - return self; -out_fail_msg: - free(self->files); -out_fail: - free(self); - self = NULL; - goto out; -} - -static struct message *mesage__find(const char *msg) -{ - struct message *m = message__list; - - while (m != NULL) { - if (strcmp(m->msg, msg) == 0) - break; - m = m->next; - } - - return m; -} - -static int message__add_file_line(struct message *self, const char *file, - int lineno) -{ - int rc = -1; - struct file_line *fl = file_line__new(file, lineno); - - if (fl == NULL) - goto out; - - fl->next = self->files; - self->files = fl; - rc = 0; -out: - return rc; -} - -static int message__add(const char *msg, char *option, const char *file, - int lineno) -{ - int rc = 0; - char bf[16384]; - char *escaped = escape(msg, bf, sizeof(bf)); - struct message *m = mesage__find(escaped); - - if (m != NULL) - rc = message__add_file_line(m, file, lineno); - else { - m = message__new(escaped, option, file, lineno); - - if (m != NULL) { - m->next = message__list; - message__list = m; - } else - rc = -1; - } - return rc; -} - -static void menu_build_message_list(struct menu *menu) -{ - struct menu *child; - - message__add(menu_get_prompt(menu), NULL, - menu->file == NULL ? "Root Menu" : menu->file->name, - menu->lineno); - - if (menu->sym != NULL && menu_has_help(menu)) - message__add(menu_get_help(menu), menu->sym->name, - menu->file == NULL ? "Root Menu" : menu->file->name, - menu->lineno); - - for (child = menu->list; child != NULL; child = child->next) - if (child->prompt != NULL) - menu_build_message_list(child); -} - -static void message__print_file_lineno(struct message *self) -{ - struct file_line *fl = self->files; - - putchar('\n'); - if (self->option != NULL) - printf("# %s:00000\n", self->option); - - printf("#: %s:%d", fl->file, fl->lineno); - fl = fl->next; - - while (fl != NULL) { - printf(", %s:%d", fl->file, fl->lineno); - fl = fl->next; - } - - putchar('\n'); -} - -static void message__print_gettext_msgid_msgstr(struct message *self) -{ - message__print_file_lineno(self); - - printf("msgid %s\n" - "msgstr \"\"\n", self->msg); -} - -static void menu__xgettext(void) -{ - struct message *m = message__list; - - while (m != NULL) { - /* skip empty lines ("") */ - if (strlen(m->msg) > sizeof("\"\"")) - message__print_gettext_msgid_msgstr(m); - m = m->next; - } -} - -int main(int ac, char **av) -{ - conf_parse(av[1]); - - menu_build_message_list(menu_get_root_menu(NULL)); - menu__xgettext(); - return 0; -} diff -Nru seabios-1.7.1/tools/kconfig/lex.zconf.c_shipped seabios-1.7.4/tools/kconfig/lex.zconf.c_shipped --- seabios-1.7.1/tools/kconfig/lex.zconf.c_shipped 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lex.zconf.c_shipped 1970-01-01 00:00:00.000000000 +0000 @@ -1,2430 +0,0 @@ - -#line 3 "scripts/kconfig/lex.zconf.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define yy_create_buffer zconf_create_buffer -#define yy_delete_buffer zconf_delete_buffer -#define yy_flex_debug zconf_flex_debug -#define yy_init_buffer zconf_init_buffer -#define yy_flush_buffer zconf_flush_buffer -#define yy_load_buffer_state zconf_load_buffer_state -#define yy_switch_to_buffer zconf_switch_to_buffer -#define yyin zconfin -#define yyleng zconfleng -#define yylex zconflex -#define yylineno zconflineno -#define yyout zconfout -#define yyrestart zconfrestart -#define yytext zconftext -#define yywrap zconfwrap -#define yyalloc zconfalloc -#define yyrealloc zconfrealloc -#define yyfree zconffree - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE zconfrestart(zconfin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -extern int zconfleng; - -extern FILE *zconfin, *zconfout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up zconftext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via zconfrestart()), so that the user can continue scanning by - * just pointing zconfin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when zconftext is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int zconfleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow zconfwrap()'s to do buffer switches - * instead of setting up a fresh zconfin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void zconfrestart (FILE *input_file ); -void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); -void zconf_delete_buffer (YY_BUFFER_STATE b ); -void zconf_flush_buffer (YY_BUFFER_STATE b ); -void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); -void zconfpop_buffer_state (void ); - -static void zconfensure_buffer_stack (void ); -static void zconf_load_buffer_state (void ); -static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); - -#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); - -void *zconfalloc (yy_size_t ); -void *zconfrealloc (void *,yy_size_t ); -void zconffree (void * ); - -#define yy_new_buffer zconf_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - zconfensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - zconfensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ - -#define zconfwrap(n) 1 -#define YY_SKIP_YYWRAP - -typedef unsigned char YY_CHAR; - -FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; - -typedef int yy_state_type; - -extern int zconflineno; - -int zconflineno = 1; - -extern char *zconftext; -#define yytext_ptr zconftext -static yyconst flex_int16_t yy_nxt[][17] = - { - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 - }, - - { - 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12 - }, - - { - 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12 - }, - - { - 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 18, 16, 16, 16 - }, - - { - 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 18, 16, 16, 16 - - }, - - { - 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19 - }, - - { - 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19 - }, - - { - 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, - 22, 22, 22, 22, 22, 25, 22 - }, - - { - 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, - 22, 22, 22, 22, 22, 25, 22 - }, - - { - 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, - 33, 34, 35, 35, 36, 37, 38 - - }, - - { - 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, - 33, 34, 35, 35, 36, 37, 38 - }, - - { - -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, -11, -11, -11, -11 - }, - - { - 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, - -12, -12, -12, -12, -12, -12, -12 - }, - - { - 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, - -13, -13, -13, -13, -13, -13, -13 - }, - - { - 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, -14, -14, -14, -14 - - }, - - { - 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42 - }, - - { - 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16 - }, - - { - 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, - -17, -17, -17, -17, -17, -17, -17 - }, - - { - 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, - -18, -18, -18, 44, -18, -18, -18 - }, - - { - 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45 - - }, - - { - 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, - -20, -20, -20, -20, -20, -20, -20 - }, - - { - 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48 - }, - - { - 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, - 49, 49, 49, 49, 49, -22, 49 - }, - - { - 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, - -23, -23, -23, -23, -23, -23, -23 - }, - - { - 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, - -24, -24, -24, -24, -24, -24, -24 - - }, - - { - 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51 - }, - - { - 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, - -26, -26, -26, -26, -26, -26, -26 - }, - - { - 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, - -27, -27, -27, -27, -27, -27, -27 - }, - - { - 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, - -28, -28, -28, -28, 53, -28, -28 - }, - - { - 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, - -29, -29, -29, -29, -29, -29, -29 - - }, - - { - 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54 - }, - - { - 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, - -31, -31, -31, -31, -31, -31, -31 - }, - - { - 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, - -32, -32, -32, -32, -32, -32, -32 - }, - - { - 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, - -33, -33, -33, -33, -33, -33, -33 - }, - - { - 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, - -34, 56, 57, 57, -34, -34, -34 - - }, - - { - 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, 57, 57, 57, -35, -35, -35 - }, - - { - 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, -36, -36, -36, -36 - }, - - { - 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37 - }, - - { - 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, - -38, -38, -38, -38, -38, -38, 59 - }, - - { - 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39 - - }, - - { - 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, - -40, -40, -40, -40, -40, -40, -40 - }, - - { - 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42 - }, - - { - 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42 - }, - - { - 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43 - }, - - { - 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, - -44, -44, -44, 44, -44, -44, -44 - - }, - - { - 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45 - }, - - { - 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, - -46, -46, -46, -46, -46, -46, -46 - }, - - { - 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48 - }, - - { - 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48 - }, - - { - 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, - 49, 49, 49, 49, 49, -49, 49 - - }, - - { - 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, - -50, -50, -50, -50, -50, -50, -50 - }, - - { - 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, - -51, -51, -51, -51, -51, -51, -51 - }, - - { - 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, - -52, -52, -52, -52, -52, -52, -52 - }, - - { - 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, - -53, -53, -53, -53, -53, -53, -53 - }, - - { - 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54 - - }, - - { - 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, - -55, -55, -55, -55, -55, -55, -55 - }, - - { - 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, - -56, 60, 57, 57, -56, -56, -56 - }, - - { - 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, - -57, 57, 57, 57, -57, -57, -57 - }, - - { - 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, - -58, -58, -58, -58, -58, -58, -58 - }, - - { - 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, - -59, -59, -59, -59, -59, -59, -59 - - }, - - { - 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, - -60, 57, 57, 57, -60, -60, -60 - }, - - } ; - -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up zconftext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - zconfleng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; - -#define YY_NUM_RULES 33 -#define YY_END_OF_BUFFER 34 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[61] = - { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, - 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, - 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, - 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, - 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 - } ; - -static yyconst flex_int32_t yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, - 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, - 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, - - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -extern int zconf_flex_debug; -int zconf_flex_debug = 0; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *zconftext; -#define YY_NO_INPUT 1 - -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -#define START_STRSIZE 16 - -static struct { - struct file *file; - int lineno; -} current_pos; - -static char *text; -static int text_size, text_asize; - -struct buffer { - struct buffer *parent; - YY_BUFFER_STATE state; -}; - -struct buffer *current_buf; - -static int last_ts, first_ts; - -static void zconf_endhelp(void); -static void zconf_endfile(void); - -static void new_string(void) -{ - text = malloc(START_STRSIZE); - text_asize = START_STRSIZE; - text_size = 0; - *text = 0; -} - -static void append_string(const char *str, int size) -{ - int new_size = text_size + size + 1; - if (new_size > text_asize) { - new_size += START_STRSIZE - 1; - new_size &= -START_STRSIZE; - text = realloc(text, new_size); - text_asize = new_size; - } - memcpy(text + text_size, str, size); - text_size += size; - text[text_size] = 0; -} - -static void alloc_string(const char *str, int size) -{ - text = malloc(size + 1); - memcpy(text, str, size); - text[size] = 0; -} - -#define INITIAL 0 -#define COMMAND 1 -#define HELP 2 -#define STRING 3 -#define PARAM 4 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int zconflex_destroy (void ); - -int zconfget_debug (void ); - -void zconfset_debug (int debug_flag ); - -YY_EXTRA_TYPE zconfget_extra (void ); - -void zconfset_extra (YY_EXTRA_TYPE user_defined ); - -FILE *zconfget_in (void ); - -void zconfset_in (FILE * in_str ); - -FILE *zconfget_out (void ); - -void zconfset_out (FILE * out_str ); - -int zconfget_leng (void ); - -char *zconfget_text (void ); - -int zconfget_lineno (void ); - -void zconfset_lineno (int line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int zconfwrap (void ); -#else -extern int zconfwrap (void ); -#endif -#endif - - static void yyunput (int c,char *buf_ptr ); - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (void ); -#else -static int input (void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - errno=0; \ - while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(zconfin); \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int zconflex (void); - -#define YY_DECL int zconflex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after zconftext and zconfleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - - int str = 0; - int ts, i; - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! zconfin ) - zconfin = stdin; - - if ( ! zconfout ) - zconfout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - zconfensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - zconf_create_buffer(zconfin,YY_BUF_SIZE ); - } - - zconf_load_buffer_state( ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = (yy_c_buf_p); - - /* Support of zconftext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); -yy_match: - while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) - ++yy_cp; - - yy_current_state = -yy_current_state; - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - - YY_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ -case 1: -/* rule 1 can match eol */ -case 2: -/* rule 2 can match eol */ -YY_RULE_SETUP -{ - current_file->lineno++; - return T_EOL; -} - YY_BREAK -case 3: -YY_RULE_SETUP - - YY_BREAK -case 4: -YY_RULE_SETUP -{ - BEGIN(COMMAND); -} - YY_BREAK -case 5: -YY_RULE_SETUP -{ - unput(zconftext[0]); - BEGIN(COMMAND); -} - YY_BREAK - -case 6: -YY_RULE_SETUP -{ - struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); - BEGIN(PARAM); - current_pos.file = current_file; - current_pos.lineno = current_file->lineno; - if (id && id->flags & TF_COMMAND) { - zconflval.id = id; - return id->token; - } - alloc_string(zconftext, zconfleng); - zconflval.string = text; - return T_WORD; - } - YY_BREAK -case 7: -YY_RULE_SETUP - - YY_BREAK -case 8: -/* rule 8 can match eol */ -YY_RULE_SETUP -{ - BEGIN(INITIAL); - current_file->lineno++; - return T_EOL; - } - YY_BREAK - -case 9: -YY_RULE_SETUP -return T_AND; - YY_BREAK -case 10: -YY_RULE_SETUP -return T_OR; - YY_BREAK -case 11: -YY_RULE_SETUP -return T_OPEN_PAREN; - YY_BREAK -case 12: -YY_RULE_SETUP -return T_CLOSE_PAREN; - YY_BREAK -case 13: -YY_RULE_SETUP -return T_NOT; - YY_BREAK -case 14: -YY_RULE_SETUP -return T_EQUAL; - YY_BREAK -case 15: -YY_RULE_SETUP -return T_UNEQUAL; - YY_BREAK -case 16: -YY_RULE_SETUP -{ - str = zconftext[0]; - new_string(); - BEGIN(STRING); - } - YY_BREAK -case 17: -/* rule 17 can match eol */ -YY_RULE_SETUP -BEGIN(INITIAL); current_file->lineno++; return T_EOL; - YY_BREAK -case 18: -YY_RULE_SETUP -/* ignore */ - YY_BREAK -case 19: -YY_RULE_SETUP -{ - struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); - if (id && id->flags & TF_PARAM) { - zconflval.id = id; - return id->token; - } - alloc_string(zconftext, zconfleng); - zconflval.string = text; - return T_WORD; - } - YY_BREAK -case 20: -YY_RULE_SETUP -/* comment */ - YY_BREAK -case 21: -/* rule 21 can match eol */ -YY_RULE_SETUP -current_file->lineno++; - YY_BREAK -case 22: -YY_RULE_SETUP - - YY_BREAK -case YY_STATE_EOF(PARAM): -{ - BEGIN(INITIAL); - } - YY_BREAK - -case 23: -/* rule 23 can match eol */ -*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ -(yy_c_buf_p) = yy_cp -= 1; -YY_DO_BEFORE_ACTION; /* set up zconftext again */ -YY_RULE_SETUP -{ - append_string(zconftext, zconfleng); - zconflval.string = text; - return T_WORD_QUOTE; - } - YY_BREAK -case 24: -YY_RULE_SETUP -{ - append_string(zconftext, zconfleng); - } - YY_BREAK -case 25: -/* rule 25 can match eol */ -*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ -(yy_c_buf_p) = yy_cp -= 1; -YY_DO_BEFORE_ACTION; /* set up zconftext again */ -YY_RULE_SETUP -{ - append_string(zconftext + 1, zconfleng - 1); - zconflval.string = text; - return T_WORD_QUOTE; - } - YY_BREAK -case 26: -YY_RULE_SETUP -{ - append_string(zconftext + 1, zconfleng - 1); - } - YY_BREAK -case 27: -YY_RULE_SETUP -{ - if (str == zconftext[0]) { - BEGIN(PARAM); - zconflval.string = text; - return T_WORD_QUOTE; - } else - append_string(zconftext, 1); - } - YY_BREAK -case 28: -/* rule 28 can match eol */ -YY_RULE_SETUP -{ - printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); - current_file->lineno++; - BEGIN(INITIAL); - return T_EOL; - } - YY_BREAK -case YY_STATE_EOF(STRING): -{ - BEGIN(INITIAL); - } - YY_BREAK - -case 29: -YY_RULE_SETUP -{ - ts = 0; - for (i = 0; i < zconfleng; i++) { - if (zconftext[i] == '\t') - ts = (ts & ~7) + 8; - else - ts++; - } - last_ts = ts; - if (first_ts) { - if (ts < first_ts) { - zconf_endhelp(); - return T_HELPTEXT; - } - ts -= first_ts; - while (ts > 8) { - append_string(" ", 8); - ts -= 8; - } - append_string(" ", ts); - } - } - YY_BREAK -case 30: -/* rule 30 can match eol */ -*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ -(yy_c_buf_p) = yy_cp -= 1; -YY_DO_BEFORE_ACTION; /* set up zconftext again */ -YY_RULE_SETUP -{ - current_file->lineno++; - zconf_endhelp(); - return T_HELPTEXT; - } - YY_BREAK -case 31: -/* rule 31 can match eol */ -YY_RULE_SETUP -{ - current_file->lineno++; - append_string("\n", 1); - } - YY_BREAK -case 32: -YY_RULE_SETUP -{ - while (zconfleng) { - if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) - break; - zconfleng--; - } - append_string(zconftext, zconfleng); - if (!first_ts) - first_ts = last_ts; - } - YY_BREAK -case YY_STATE_EOF(HELP): -{ - zconf_endhelp(); - return T_HELPTEXT; - } - YY_BREAK - -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(COMMAND): -{ - if (current_file) { - zconf_endfile(); - return T_EOL; - } - fclose(zconfin); - yyterminate(); -} - YY_BREAK -case 33: -YY_RULE_SETUP -YY_FATAL_ERROR( "flex scanner jammed" ); - YY_BREAK - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed zconfin at a new source and called - * zconflex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( zconfwrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * zconftext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of zconflex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); - register int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - zconfrestart(zconfin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = (yy_start); - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - register int yy_is_jam; - - yy_current_state = yy_nxt[yy_current_state][1]; - yy_is_jam = (yy_current_state <= 0); - - return yy_is_jam ? 0 : yy_current_state; -} - - static void yyunput (int c, register char * yy_bp ) -{ - register char *yy_cp; - - yy_cp = (yy_c_buf_p); - - /* undo effects of setting up zconftext */ - *yy_cp = (yy_hold_char); - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - register char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - zconfrestart(zconfin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( zconfwrap( ) ) - return EOF; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve zconftext */ - (yy_hold_char) = *++(yy_c_buf_p); - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void zconfrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - zconfensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - zconf_create_buffer(zconfin,YY_BUF_SIZE ); - } - - zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); - zconf_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * zconfpop_buffer_state(); - * zconfpush_buffer_state(new_buffer); - */ - zconfensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - zconf_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (zconfwrap()) processing, but the only time this flag - * is looked at is after zconfwrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void zconf_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - zconf_init_buffer(b,file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with zconf_create_buffer() - * - */ - void zconf_delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - zconffree((void *) b->yy_ch_buf ); - - zconffree((void *) b ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a zconfrestart() or at EOF. - */ - static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - zconf_flush_buffer(b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then zconf_init_buffer was _probably_ - * called from zconfrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void zconf_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - zconf_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - zconfensure_buffer_stack(); - - /* This block is copied from zconf_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from zconf_switch_to_buffer. */ - zconf_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void zconfpop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - zconf_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - zconf_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void zconfensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - zconf_switch_to_buffer(b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to zconflex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * zconf_scan_bytes() instead. - */ -YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) -{ - - return zconf_scan_bytes(yystr,strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) zconfalloc(n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = zconf_scan_buffer(buf,n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up zconftext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - zconftext[zconfleng] = (yy_hold_char); \ - (yy_c_buf_p) = zconftext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - zconfleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int zconfget_lineno (void) -{ - - return zconflineno; -} - -/** Get the input stream. - * - */ -FILE *zconfget_in (void) -{ - return zconfin; -} - -/** Get the output stream. - * - */ -FILE *zconfget_out (void) -{ - return zconfout; -} - -/** Get the length of the current token. - * - */ -int zconfget_leng (void) -{ - return zconfleng; -} - -/** Get the current token. - * - */ - -char *zconfget_text (void) -{ - return zconftext; -} - -/** Set the current line number. - * @param line_number - * - */ -void zconfset_lineno (int line_number ) -{ - - zconflineno = line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see zconf_switch_to_buffer - */ -void zconfset_in (FILE * in_str ) -{ - zconfin = in_str ; -} - -void zconfset_out (FILE * out_str ) -{ - zconfout = out_str ; -} - -int zconfget_debug (void) -{ - return zconf_flex_debug; -} - -void zconfset_debug (int bdebug ) -{ - zconf_flex_debug = bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from zconflex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - zconfin = stdin; - zconfout = stdout; -#else - zconfin = (FILE *) 0; - zconfout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * zconflex_init() - */ - return 0; -} - -/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ -int zconflex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - zconf_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - zconfpop_buffer_state(); - } - - /* Destroy the stack itself. */ - zconffree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * zconflex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *zconfalloc (yy_size_t size ) -{ - return (void *) malloc( size ); -} - -void *zconfrealloc (void * ptr, yy_size_t size ) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} - -void zconffree (void * ptr ) -{ - free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -void zconf_starthelp(void) -{ - new_string(); - last_ts = first_ts = 0; - BEGIN(HELP); -} - -static void zconf_endhelp(void) -{ - zconflval.string = text; - BEGIN(INITIAL); -} - -/* - * Try to open specified file with following names: - * ./name - * $(srctree)/name - * The latter is used when srctree is separate from objtree - * when compiling the kernel. - * Return NULL if file is not found. - */ -FILE *zconf_fopen(const char *name) -{ - char *env, fullname[PATH_MAX+1]; - FILE *f; - - f = fopen(name, "r"); - if (!f && name != NULL && name[0] != '/') { - env = getenv(SRCTREE); - if (env) { - sprintf(fullname, "%s/%s", env, name); - f = fopen(fullname, "r"); - } - } - return f; -} - -void zconf_initscan(const char *name) -{ - zconfin = zconf_fopen(name); - if (!zconfin) { - printf("can't find file %s\n", name); - exit(1); - } - - current_buf = malloc(sizeof(*current_buf)); - memset(current_buf, 0, sizeof(*current_buf)); - - current_file = file_lookup(name); - current_file->lineno = 1; - current_file->flags = FILE_BUSY; -} - -void zconf_nextfile(const char *name) -{ - struct file *file = file_lookup(name); - struct buffer *buf = malloc(sizeof(*buf)); - memset(buf, 0, sizeof(*buf)); - - current_buf->state = YY_CURRENT_BUFFER; - zconfin = zconf_fopen(file->name); - if (!zconfin) { - printf("%s:%d: can't open file \"%s\"\n", - zconf_curname(), zconf_lineno(), file->name); - exit(1); - } - zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); - buf->parent = current_buf; - current_buf = buf; - - if (file->flags & FILE_BUSY) { - printf("%s:%d: do not source '%s' from itself\n", - zconf_curname(), zconf_lineno(), name); - exit(1); - } - if (file->flags & FILE_SCANNED) { - printf("%s:%d: file '%s' is already sourced from '%s'\n", - zconf_curname(), zconf_lineno(), name, - file->parent->name); - exit(1); - } - file->flags |= FILE_BUSY; - file->lineno = 1; - file->parent = current_file; - current_file = file; -} - -static void zconf_endfile(void) -{ - struct buffer *parent; - - current_file->flags |= FILE_SCANNED; - current_file->flags &= ~FILE_BUSY; - current_file = current_file->parent; - - parent = current_buf->parent; - if (parent) { - fclose(zconfin); - zconf_delete_buffer(YY_CURRENT_BUFFER); - zconf_switch_to_buffer(parent->state); - } - free(current_buf); - current_buf = parent; -} - -int zconf_lineno(void) -{ - return current_pos.lineno; -} - -const char *zconf_curname(void) -{ - return current_pos.file ? current_pos.file->name : ""; -} - diff -Nru seabios-1.7.1/tools/kconfig/lkc.h seabios-1.7.4/tools/kconfig/lkc.h --- seabios-1.7.1/tools/kconfig/lkc.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lkc.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#ifndef LKC_H -#define LKC_H - -#include "expr.h" - -#ifndef KBUILD_NO_NLS -# include -#else -static inline const char *gettext(const char *txt) { return txt; } -static inline void textdomain(const char *domainname) {} -static inline void bindtextdomain(const char *name, const char *dir) {} -static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef LKC_DIRECT_LINK -#define P(name,type,arg) extern type name arg -#else -#include "lkc_defs.h" -#define P(name,type,arg) extern type (*name ## _p) arg -#endif -#include "lkc_proto.h" -#undef P - -#define SRCTREE "srctree" - -#ifndef PACKAGE -#define PACKAGE "linux" -#endif - -#define LOCALEDIR "/usr/share/locale" - -#define _(text) gettext(text) -#define N_(text) (text) - -#ifndef CONFIG_ -#define CONFIG_ "CONFIG_" -#endif - -#define TF_COMMAND 0x0001 -#define TF_PARAM 0x0002 -#define TF_OPTION 0x0004 - -enum conf_def_mode { - def_default, - def_yes, - def_mod, - def_no, - def_random -}; - -#define T_OPT_MODULES 1 -#define T_OPT_DEFCONFIG_LIST 2 -#define T_OPT_ENV 3 - -struct kconf_id { - int name; - int token; - unsigned int flags; - enum symbol_type stype; -}; - -#ifdef YYDEBUG -extern int zconfdebug; -#endif - -int zconfparse(void); -void zconfdump(FILE *out); -void zconf_starthelp(void); -FILE *zconf_fopen(const char *name); -void zconf_initscan(const char *name); -void zconf_nextfile(const char *name); -int zconf_lineno(void); -const char *zconf_curname(void); - -/* conf.c */ -void xfgets(char *str, int size, FILE *in); - -/* confdata.c */ -const char *conf_get_configname(void); -const char *conf_get_autoconfig_name(void); -char *conf_get_default_confname(void); -void sym_set_change_count(int count); -void sym_add_change_count(int count); -void conf_set_all_new_symbols(enum conf_def_mode mode); - -/* confdata.c and expr.c */ -static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) -{ - if (fwrite(str, len, count, out) < count) - fprintf(stderr, "\nError in writing or end of file.\n"); -} - -/* kconfig_load.c */ -void kconfig_load(void); - -/* menu.c */ -void _menu_init(void); -void menu_warn(struct menu *menu, const char *fmt, ...); -struct menu *menu_add_menu(void); -void menu_end_menu(void); -void menu_add_entry(struct symbol *sym); -void menu_end_entry(void); -void menu_add_dep(struct expr *dep); -void menu_add_visibility(struct expr *dep); -struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); -struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); -void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); -void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); -void menu_add_option(int token, char *arg); -void menu_finalize(struct menu *parent); -void menu_set_type(int type); - -/* util.c */ -struct file *file_lookup(const char *name); -int file_write_dep(const char *name); - -struct gstr { - size_t len; - char *s; - /* - * when max_width is not zero long lines in string s (if any) get - * wrapped not to exceed the max_width value - */ - int max_width; -}; -struct gstr str_new(void); -struct gstr str_assign(const char *s); -void str_free(struct gstr *gs); -void str_append(struct gstr *gs, const char *s); -void str_printf(struct gstr *gs, const char *fmt, ...); -const char *str_get(struct gstr *gs); - -/* symbol.c */ -extern struct expr *sym_env_list; - -void sym_init(void); -void sym_clear_all_valid(void); -void sym_set_all_changed(void); -void sym_set_changed(struct symbol *sym); -struct symbol *sym_choice_default(struct symbol *sym); -const char *sym_get_string_default(struct symbol *sym); -struct symbol *sym_check_deps(struct symbol *sym); -struct property *prop_alloc(enum prop_type type, struct symbol *sym); -struct symbol *prop_get_symbol(struct property *prop); -struct property *sym_get_env_prop(struct symbol *sym); - -static inline tristate sym_get_tristate_value(struct symbol *sym) -{ - return sym->curr.tri; -} - - -static inline struct symbol *sym_get_choice_value(struct symbol *sym) -{ - return (struct symbol *)sym->curr.val; -} - -static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) -{ - return sym_set_tristate_value(chval, yes); -} - -static inline bool sym_is_choice(struct symbol *sym) -{ - return sym->flags & SYMBOL_CHOICE ? true : false; -} - -static inline bool sym_is_choice_value(struct symbol *sym) -{ - return sym->flags & SYMBOL_CHOICEVAL ? true : false; -} - -static inline bool sym_is_optional(struct symbol *sym) -{ - return sym->flags & SYMBOL_OPTIONAL ? true : false; -} - -static inline bool sym_has_value(struct symbol *sym) -{ - return sym->flags & SYMBOL_DEF_USER ? true : false; -} - -#ifdef __cplusplus -} -#endif - -#endif /* LKC_H */ diff -Nru seabios-1.7.1/tools/kconfig/lkc_proto.h seabios-1.7.4/tools/kconfig/lkc_proto.h --- seabios-1.7.1/tools/kconfig/lkc_proto.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lkc_proto.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -#include - -/* confdata.c */ -P(conf_parse,void,(const char *name)); -P(conf_read,int,(const char *name)); -P(conf_read_simple,int,(const char *name, int)); -P(conf_write_defconfig,int,(const char *name)); -P(conf_write,int,(const char *name)); -P(conf_write_autoconf,int,(void)); -P(conf_get_changed,bool,(void)); -P(conf_set_changed_callback, void,(void (*fn)(void))); -P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); - -/* menu.c */ -P(rootmenu,struct menu,); - -P(menu_is_visible, bool, (struct menu *menu)); -P(menu_has_prompt, bool, (struct menu *menu)); -P(menu_get_prompt,const char *,(struct menu *menu)); -P(menu_get_root_menu,struct menu *,(struct menu *menu)); -P(menu_get_parent_menu,struct menu *,(struct menu *menu)); -P(menu_has_help,bool,(struct menu *menu)); -P(menu_get_help,const char *,(struct menu *menu)); -P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); -P(get_relations_str, struct gstr, (struct symbol **sym_arr)); -P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); - -/* symbol.c */ -P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); - -P(sym_lookup,struct symbol *,(const char *name, int flags)); -P(sym_find,struct symbol *,(const char *name)); -P(sym_expand_string_value,const char *,(const char *in)); -P(sym_re_search,struct symbol **,(const char *pattern)); -P(sym_type_name,const char *,(enum symbol_type type)); -P(sym_calc_value,void,(struct symbol *sym)); -P(sym_get_type,enum symbol_type,(struct symbol *sym)); -P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); -P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); -P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); -P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); -P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); -P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); -P(sym_is_changable,bool,(struct symbol *sym)); -P(sym_get_choice_prop,struct property *,(struct symbol *sym)); -P(sym_get_default_prop,struct property *,(struct symbol *sym)); -P(sym_get_string_value,const char *,(struct symbol *sym)); - -P(prop_get_type_name,const char *,(enum prop_type type)); - -/* expr.c */ -P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); -P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/BIG.FAT.WARNING seabios-1.7.4/tools/kconfig/lxdialog/BIG.FAT.WARNING --- seabios-1.7.1/tools/kconfig/lxdialog/BIG.FAT.WARNING 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/BIG.FAT.WARNING 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -This is NOT the official version of dialog. This version has been -significantly modified from the original. It is for use by the Linux -kernel configuration script. Please do not bother Savio Lam with -questions about this program. diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/checklist.c seabios-1.7.4/tools/kconfig/lxdialog/checklist.c --- seabios-1.7.1/tools/kconfig/lxdialog/checklist.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/checklist.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,332 +0,0 @@ -/* - * checklist.c -- implements the checklist box - * - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension - * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; 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. - */ - -#include "dialog.h" - -static int list_width, check_x, item_x; - -/* - * Print list item - */ -static void print_item(WINDOW * win, int choice, int selected) -{ - int i; - char *list_item = malloc(list_width + 1); - - strncpy(list_item, item_str(), list_width - item_x); - list_item[list_width - item_x] = '\0'; - - /* Clear 'residue' of last item */ - wattrset(win, dlg.menubox.atr); - wmove(win, choice, 0); - for (i = 0; i < list_width; i++) - waddch(win, ' '); - - wmove(win, choice, check_x); - wattrset(win, selected ? dlg.check_selected.atr - : dlg.check.atr); - if (!item_is_tag(':')) - wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); - - wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); - mvwaddch(win, choice, item_x, list_item[0]); - wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); - waddstr(win, list_item + 1); - if (selected) { - wmove(win, choice, check_x + 1); - wrefresh(win); - } - free(list_item); -} - -/* - * Print the scroll indicators. - */ -static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, - int y, int x, int height) -{ - wmove(win, y, x); - - if (scroll > 0) { - wattrset(win, dlg.uarrow.atr); - waddch(win, ACS_UARROW); - waddstr(win, "(-)"); - } else { - wattrset(win, dlg.menubox.atr); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - } - - y = y + height + 1; - wmove(win, y, x); - - if ((height < item_no) && (scroll + choice < item_no - 1)) { - wattrset(win, dlg.darrow.atr); - waddch(win, ACS_DARROW); - waddstr(win, "(+)"); - } else { - wattrset(win, dlg.menubox_border.atr); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - } -} - -/* - * Display the termination buttons - */ -static void print_buttons(WINDOW * dialog, int height, int width, int selected) -{ - int x = width / 2 - 11; - int y = height - 2; - - print_button(dialog, gettext("Select"), y, x, selected == 0); - print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); - - wmove(dialog, y, x + 1 + 14 * selected); - wrefresh(dialog); -} - -/* - * Display a dialog box with a list of options that can be turned on or off - * in the style of radiolist (only one option turned on at a time). - */ -int dialog_checklist(const char *title, const char *prompt, int height, - int width, int list_height) -{ - int i, x, y, box_x, box_y; - int key = 0, button = 0, choice = 0, scroll = 0, max_choice; - WINDOW *dialog, *list; - - /* which item to highlight */ - item_foreach() { - if (item_is_tag('X')) - choice = item_n(); - if (item_is_selected()) { - choice = item_n(); - break; - } - } - -do_resize: - if (getmaxy(stdscr) < (height + 6)) - return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) < (width + 6)) - return -ERRDISPLAYTOOSMALL; - - max_choice = MIN(list_height, item_count()); - - /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; - - draw_shadow(stdscr, y, x, height, width); - - dialog = newwin(height, width, y, x); - keypad(dialog, TRUE); - - draw_box(dialog, 0, 0, height, width, - dlg.dialog.atr, dlg.border.atr); - wattrset(dialog, dlg.border.atr); - mvwaddch(dialog, height - 3, 0, ACS_LTEE); - for (i = 0; i < width - 2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dlg.dialog.atr); - waddch(dialog, ACS_RTEE); - - print_title(dialog, title, width); - - wattrset(dialog, dlg.dialog.atr); - print_autowrap(dialog, prompt, width - 2, 1, 3); - - list_width = width - 6; - box_y = height - list_height - 5; - box_x = (width - list_width) / 2 - 1; - - /* create new window for the list */ - list = subwin(dialog, list_height, list_width, y + box_y + 1, - x + box_x + 1); - - keypad(list, TRUE); - - /* draw a box around the list items */ - draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, - dlg.menubox_border.atr, dlg.menubox.atr); - - /* Find length of longest item in order to center checklist */ - check_x = 0; - item_foreach() - check_x = MAX(check_x, strlen(item_str()) + 4); - check_x = MIN(check_x, list_width); - - check_x = (list_width - check_x) / 2; - item_x = check_x + 4; - - if (choice >= list_height) { - scroll = choice - list_height + 1; - choice -= scroll; - } - - /* Print the list */ - for (i = 0; i < max_choice; i++) { - item_set(scroll + i); - print_item(list, i, i == choice); - } - - print_arrows(dialog, choice, item_count(), scroll, - box_y, box_x + check_x + 5, list_height); - - print_buttons(dialog, height, width, 0); - - wnoutrefresh(dialog); - wnoutrefresh(list); - doupdate(); - - while (key != KEY_ESC) { - key = wgetch(dialog); - - for (i = 0; i < max_choice; i++) { - item_set(i + scroll); - if (toupper(key) == toupper(item_str()[0])) - break; - } - - if (i < max_choice || key == KEY_UP || key == KEY_DOWN || - key == '+' || key == '-') { - if (key == KEY_UP || key == '-') { - if (!choice) { - if (!scroll) - continue; - /* Scroll list down */ - if (list_height > 1) { - /* De-highlight current first item */ - item_set(scroll); - print_item(list, 0, FALSE); - scrollok(list, TRUE); - wscrl(list, -1); - scrollok(list, FALSE); - } - scroll--; - item_set(scroll); - print_item(list, 0, TRUE); - print_arrows(dialog, choice, item_count(), - scroll, box_y, box_x + check_x + 5, list_height); - - wnoutrefresh(dialog); - wrefresh(list); - - continue; /* wait for another key press */ - } else - i = choice - 1; - } else if (key == KEY_DOWN || key == '+') { - if (choice == max_choice - 1) { - if (scroll + choice >= item_count() - 1) - continue; - /* Scroll list up */ - if (list_height > 1) { - /* De-highlight current last item before scrolling up */ - item_set(scroll + max_choice - 1); - print_item(list, - max_choice - 1, - FALSE); - scrollok(list, TRUE); - wscrl(list, 1); - scrollok(list, FALSE); - } - scroll++; - item_set(scroll + max_choice - 1); - print_item(list, max_choice - 1, TRUE); - - print_arrows(dialog, choice, item_count(), - scroll, box_y, box_x + check_x + 5, list_height); - - wnoutrefresh(dialog); - wrefresh(list); - - continue; /* wait for another key press */ - } else - i = choice + 1; - } - if (i != choice) { - /* De-highlight current item */ - item_set(scroll + choice); - print_item(list, choice, FALSE); - /* Highlight new item */ - choice = i; - item_set(scroll + choice); - print_item(list, choice, TRUE); - wnoutrefresh(dialog); - wrefresh(list); - } - continue; /* wait for another key press */ - } - switch (key) { - case 'H': - case 'h': - case '?': - button = 1; - /* fall-through */ - case 'S': - case 's': - case ' ': - case '\n': - item_foreach() - item_set_selected(0); - item_set(scroll + choice); - item_set_selected(1); - delwin(list); - delwin(dialog); - return button; - case TAB: - case KEY_LEFT: - case KEY_RIGHT: - button = ((key == KEY_LEFT ? --button : ++button) < 0) - ? 1 : (button > 1 ? 0 : button); - - print_buttons(dialog, height, width, button); - wrefresh(dialog); - break; - case 'X': - case 'x': - key = KEY_ESC; - break; - case KEY_ESC: - key = on_key_esc(dialog); - break; - case KEY_RESIZE: - delwin(list); - delwin(dialog); - on_key_resize(); - goto do_resize; - } - - /* Now, update everything... */ - doupdate(); - } - delwin(list); - delwin(dialog); - return key; /* ESC pressed */ -} diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/check-lxdialog.sh seabios-1.7.4/tools/kconfig/lxdialog/check-lxdialog.sh --- seabios-1.7.1/tools/kconfig/lxdialog/check-lxdialog.sh 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/check-lxdialog.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -#!/bin/sh -# Check ncurses compatibility - -# What library to link -ldflags() -{ - for ext in so a dylib ; do - for lib in ncursesw ncurses curses ; do - $cc -print-file-name=lib${lib}.${ext} | grep -q / - if [ $? -eq 0 ]; then - echo "-l${lib}" - exit - fi - done - done - exit 1 -} - -# Where is ncurses.h? -ccflags() -{ - if [ -f /usr/include/ncurses/ncurses.h ]; then - echo '-I/usr/include/ncurses -DCURSES_LOC=""' - elif [ -f /usr/include/ncurses/curses.h ]; then - echo '-I/usr/include/ncurses -DCURSES_LOC=""' - elif [ -f /usr/include/ncursesw/curses.h ]; then - echo '-I/usr/include/ncursesw -DCURSES_LOC=""' - elif [ -f /usr/include/ncurses.h ]; then - echo '-DCURSES_LOC=""' - else - echo '-DCURSES_LOC=""' - fi -} - -# Temp file, try to clean up after us -tmp=.lxdialog.tmp -trap "rm -f $tmp" 0 1 2 3 15 - -# Check if we can link to ncurses -check() { - $cc -xc - -o $tmp 2>/dev/null <<'EOF' -#include CURSES_LOC -main() {} -EOF - if [ $? != 0 ]; then - echo " *** Unable to find the ncurses libraries or the" 1>&2 - echo " *** required header files." 1>&2 - echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 - echo " *** " 1>&2 - echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 - echo " *** " 1>&2 - exit 1 - fi -} - -usage() { - printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" -} - -if [ $# -eq 0 ]; then - usage - exit 1 -fi - -cc="" -case "$1" in - "-check") - shift - cc="$@" - check - ;; - "-ccflags") - ccflags - ;; - "-ldflags") - shift - cc="$@" - ldflags - ;; - "*") - usage - exit 1 - ;; -esac diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/dialog.h seabios-1.7.4/tools/kconfig/lxdialog/dialog.h --- seabios-1.7.1/tools/kconfig/lxdialog/dialog.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/dialog.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,230 +0,0 @@ -/* - * dialog.h -- common declarations for all dialog modules - * - * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef KBUILD_NO_NLS -# include -#else -# define gettext(Msgid) ((const char *) (Msgid)) -#endif - -#ifdef __sun__ -#define CURS_MACROS -#endif -#include CURSES_LOC - -/* - * Colors in ncurses 1.9.9e do not work properly since foreground and - * background colors are OR'd rather than separately masked. This version - * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible - * with standard curses. The simplest fix (to make this work with standard - * curses) uses the wbkgdset() function, not used in the original hack. - * Turn it off if we're building with 1.9.9e, since it just confuses things. - */ -#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) -#define OLD_NCURSES 1 -#undef wbkgdset -#define wbkgdset(w,p) /*nothing */ -#else -#define OLD_NCURSES 0 -#endif - -#define TR(params) _tracef params - -#define KEY_ESC 27 -#define TAB 9 -#define MAX_LEN 2048 -#define BUF_SIZE (10*1024) -#define MIN(x,y) (x < y ? x : y) -#define MAX(x,y) (x > y ? x : y) - -#ifndef ACS_ULCORNER -#define ACS_ULCORNER '+' -#endif -#ifndef ACS_LLCORNER -#define ACS_LLCORNER '+' -#endif -#ifndef ACS_URCORNER -#define ACS_URCORNER '+' -#endif -#ifndef ACS_LRCORNER -#define ACS_LRCORNER '+' -#endif -#ifndef ACS_HLINE -#define ACS_HLINE '-' -#endif -#ifndef ACS_VLINE -#define ACS_VLINE '|' -#endif -#ifndef ACS_LTEE -#define ACS_LTEE '+' -#endif -#ifndef ACS_RTEE -#define ACS_RTEE '+' -#endif -#ifndef ACS_UARROW -#define ACS_UARROW '^' -#endif -#ifndef ACS_DARROW -#define ACS_DARROW 'v' -#endif - -/* error return codes */ -#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) - -/* - * Color definitions - */ -struct dialog_color { - chtype atr; /* Color attribute */ - int fg; /* foreground */ - int bg; /* background */ - int hl; /* highlight this item */ -}; - -struct dialog_info { - const char *backtitle; - struct dialog_color screen; - struct dialog_color shadow; - struct dialog_color dialog; - struct dialog_color title; - struct dialog_color border; - struct dialog_color button_active; - struct dialog_color button_inactive; - struct dialog_color button_key_active; - struct dialog_color button_key_inactive; - struct dialog_color button_label_active; - struct dialog_color button_label_inactive; - struct dialog_color inputbox; - struct dialog_color inputbox_border; - struct dialog_color searchbox; - struct dialog_color searchbox_title; - struct dialog_color searchbox_border; - struct dialog_color position_indicator; - struct dialog_color menubox; - struct dialog_color menubox_border; - struct dialog_color item; - struct dialog_color item_selected; - struct dialog_color tag; - struct dialog_color tag_selected; - struct dialog_color tag_key; - struct dialog_color tag_key_selected; - struct dialog_color check; - struct dialog_color check_selected; - struct dialog_color uarrow; - struct dialog_color darrow; -}; - -/* - * Global variables - */ -extern struct dialog_info dlg; -extern char dialog_input_result[]; - -/* - * Function prototypes - */ - -/* item list as used by checklist and menubox */ -void item_reset(void); -void item_make(const char *fmt, ...); -void item_add_str(const char *fmt, ...); -void item_set_tag(char tag); -void item_set_data(void *p); -void item_set_selected(int val); -int item_activate_selected(void); -void *item_data(void); -char item_tag(void); - -/* item list manipulation for lxdialog use */ -#define MAXITEMSTR 200 -struct dialog_item { - char str[MAXITEMSTR]; /* promtp displayed */ - char tag; - void *data; /* pointer to menu item - used by menubox+checklist */ - int selected; /* Set to 1 by dialog_*() function if selected. */ -}; - -/* list of lialog_items */ -struct dialog_list { - struct dialog_item node; - struct dialog_list *next; -}; - -extern struct dialog_list *item_cur; -extern struct dialog_list item_nil; -extern struct dialog_list *item_head; - -int item_count(void); -void item_set(int n); -int item_n(void); -const char *item_str(void); -int item_is_selected(void); -int item_is_tag(char tag); -#define item_foreach() \ - for (item_cur = item_head ? item_head: item_cur; \ - item_cur && (item_cur != &item_nil); item_cur = item_cur->next) - -/* generic key handlers */ -int on_key_esc(WINDOW *win); -int on_key_resize(void); - -int init_dialog(const char *backtitle); -void set_dialog_backtitle(const char *backtitle); -void end_dialog(int x, int y); -void attr_clear(WINDOW * win, int height, int width, chtype attr); -void dialog_clear(void); -void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); -void print_button(WINDOW * win, const char *label, int y, int x, int selected); -void print_title(WINDOW *dialog, const char *title, int width); -void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, - chtype border); -void draw_shadow(WINDOW * win, int y, int x, int height, int width); - -int first_alpha(const char *string, const char *exempt); -int dialog_yesno(const char *title, const char *prompt, int height, int width); -int dialog_msgbox(const char *title, const char *prompt, int height, - int width, int pause); -int dialog_textbox(const char *title, const char *file, int height, int width); -int dialog_menu(const char *title, const char *prompt, - const void *selected, int *s_scroll); -int dialog_checklist(const char *title, const char *prompt, int height, - int width, int list_height); -extern char dialog_input_result[]; -int dialog_inputbox(const char *title, const char *prompt, int height, - int width, const char *init); - -/* - * This is the base for fictitious keys, which activate - * the buttons. - * - * Mouse-generated keys are the following: - * -- the first 32 are used as numbers, in addition to '0'-'9' - * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') - * -- uppercase chars are used to invoke the button (M_EVENT + 'O') - */ -#define M_EVENT (KEY_MAX+1) diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/.gitignore seabios-1.7.4/tools/kconfig/lxdialog/.gitignore --- seabios-1.7.1/tools/kconfig/lxdialog/.gitignore 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -# -# Generated files -# -lxdialog diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/inputbox.c seabios-1.7.4/tools/kconfig/lxdialog/inputbox.c --- seabios-1.7.1/tools/kconfig/lxdialog/inputbox.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/inputbox.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,238 +0,0 @@ -/* - * inputbox.c -- implements the input box - * - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; 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. - */ - -#include "dialog.h" - -char dialog_input_result[MAX_LEN + 1]; - -/* - * Print the termination buttons - */ -static void print_buttons(WINDOW * dialog, int height, int width, int selected) -{ - int x = width / 2 - 11; - int y = height - 2; - - print_button(dialog, gettext(" Ok "), y, x, selected == 0); - print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); - - wmove(dialog, y, x + 1 + 14 * selected); - wrefresh(dialog); -} - -/* - * Display a dialog box for inputing a string - */ -int dialog_inputbox(const char *title, const char *prompt, int height, int width, - const char *init) -{ - int i, x, y, box_y, box_x, box_width; - int input_x = 0, scroll = 0, key = 0, button = -1; - char *instr = dialog_input_result; - WINDOW *dialog; - - if (!init) - instr[0] = '\0'; - else - strcpy(instr, init); - -do_resize: - if (getmaxy(stdscr) <= (height - 2)) - return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) <= (width - 2)) - return -ERRDISPLAYTOOSMALL; - - /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; - - draw_shadow(stdscr, y, x, height, width); - - dialog = newwin(height, width, y, x); - keypad(dialog, TRUE); - - draw_box(dialog, 0, 0, height, width, - dlg.dialog.atr, dlg.border.atr); - wattrset(dialog, dlg.border.atr); - mvwaddch(dialog, height - 3, 0, ACS_LTEE); - for (i = 0; i < width - 2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dlg.dialog.atr); - waddch(dialog, ACS_RTEE); - - print_title(dialog, title, width); - - wattrset(dialog, dlg.dialog.atr); - print_autowrap(dialog, prompt, width - 2, 1, 3); - - /* Draw the input field box */ - box_width = width - 6; - getyx(dialog, y, x); - box_y = y + 2; - box_x = (width - box_width) / 2; - draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, - dlg.dialog.atr, dlg.border.atr); - - print_buttons(dialog, height, width, 0); - - /* Set up the initial value */ - wmove(dialog, box_y, box_x); - wattrset(dialog, dlg.inputbox.atr); - - input_x = strlen(instr); - - if (input_x >= box_width) { - scroll = input_x - box_width + 1; - input_x = box_width - 1; - for (i = 0; i < box_width - 1; i++) - waddch(dialog, instr[scroll + i]); - } else { - waddstr(dialog, instr); - } - - wmove(dialog, box_y, box_x + input_x); - - wrefresh(dialog); - - while (key != KEY_ESC) { - key = wgetch(dialog); - - if (button == -1) { /* Input box selected */ - switch (key) { - case TAB: - case KEY_UP: - case KEY_DOWN: - break; - case KEY_LEFT: - continue; - case KEY_RIGHT: - continue; - case KEY_BACKSPACE: - case 127: - if (input_x || scroll) { - wattrset(dialog, dlg.inputbox.atr); - if (!input_x) { - scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width; i++) - waddch(dialog, - instr[scroll + input_x + i] ? - instr[scroll + input_x + i] : ' '); - input_x = strlen(instr) - scroll; - } else - input_x--; - instr[scroll + input_x] = '\0'; - mvwaddch(dialog, box_y, input_x + box_x, ' '); - wmove(dialog, box_y, input_x + box_x); - wrefresh(dialog); - } - continue; - default: - if (key < 0x100 && isprint(key)) { - if (scroll + input_x < MAX_LEN) { - wattrset(dialog, dlg.inputbox.atr); - instr[scroll + input_x] = key; - instr[scroll + input_x + 1] = '\0'; - if (input_x == box_width - 1) { - scroll++; - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width - 1; i++) - waddch(dialog, instr [scroll + i]); - } else { - wmove(dialog, box_y, input_x++ + box_x); - waddch(dialog, key); - } - wrefresh(dialog); - } else - flash(); /* Alarm user about overflow */ - continue; - } - } - } - switch (key) { - case 'O': - case 'o': - delwin(dialog); - return 0; - case 'H': - case 'h': - delwin(dialog); - return 1; - case KEY_UP: - case KEY_LEFT: - switch (button) { - case -1: - button = 1; /* Indicates "Help" button is selected */ - print_buttons(dialog, height, width, 1); - break; - case 0: - button = -1; /* Indicates input box is selected */ - print_buttons(dialog, height, width, 0); - wmove(dialog, box_y, box_x + input_x); - wrefresh(dialog); - break; - case 1: - button = 0; /* Indicates "OK" button is selected */ - print_buttons(dialog, height, width, 0); - break; - } - break; - case TAB: - case KEY_DOWN: - case KEY_RIGHT: - switch (button) { - case -1: - button = 0; /* Indicates "OK" button is selected */ - print_buttons(dialog, height, width, 0); - break; - case 0: - button = 1; /* Indicates "Help" button is selected */ - print_buttons(dialog, height, width, 1); - break; - case 1: - button = -1; /* Indicates input box is selected */ - print_buttons(dialog, height, width, 0); - wmove(dialog, box_y, box_x + input_x); - wrefresh(dialog); - break; - } - break; - case ' ': - case '\n': - delwin(dialog); - return (button == -1 ? 0 : button); - case 'X': - case 'x': - key = KEY_ESC; - break; - case KEY_ESC: - key = on_key_esc(dialog); - break; - case KEY_RESIZE: - delwin(dialog); - on_key_resize(); - goto do_resize; - } - } - - delwin(dialog); - return KEY_ESC; /* ESC pressed */ -} diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/menubox.c seabios-1.7.4/tools/kconfig/lxdialog/menubox.c --- seabios-1.7.1/tools/kconfig/lxdialog/menubox.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/menubox.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,434 +0,0 @@ -/* - * menubox.c -- implements the menu box - * - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; 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. - */ - -/* - * Changes by Clifford Wolf (god@clifford.at) - * - * [ 1998-06-13 ] - * - * *) A bugfix for the Page-Down problem - * - * *) Formerly when I used Page Down and Page Up, the cursor would be set - * to the first position in the menu box. Now lxdialog is a bit - * smarter and works more like other menu systems (just have a look at - * it). - * - * *) Formerly if I selected something my scrolling would be broken because - * lxdialog is re-invoked by the Menuconfig shell script, can't - * remember the last scrolling position, and just sets it so that the - * cursor is at the bottom of the box. Now it writes the temporary file - * lxdialog.scrltmp which contains this information. The file is - * deleted by lxdialog if the user leaves a submenu or enters a new - * one, but it would be nice if Menuconfig could make another "rm -f" - * just to be sure. Just try it out - you will recognise a difference! - * - * [ 1998-06-14 ] - * - * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files - * and menus change their size on the fly. - * - * *) If for some reason the last scrolling position is not saved by - * lxdialog, it sets the scrolling so that the selected item is in the - * middle of the menu box, not at the bottom. - * - * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) - * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. - * This fixes a bug in Menuconfig where using ' ' to descend into menus - * would leave mis-synchronized lxdialog.scrltmp files lying around, - * fscanf would read in 'scroll', and eventually that value would get used. - */ - -#include "dialog.h" - -static int menu_width, item_x; - -/* - * Print menu item - */ -static void do_print_item(WINDOW * win, const char *item, int line_y, - int selected, int hotkey) -{ - int j; - char *menu_item = malloc(menu_width + 1); - - strncpy(menu_item, item, menu_width - item_x); - menu_item[menu_width - item_x] = '\0'; - j = first_alpha(menu_item, "YyNnMmHh"); - - /* Clear 'residue' of last item */ - wattrset(win, dlg.menubox.atr); - wmove(win, line_y, 0); -#if OLD_NCURSES - { - int i; - for (i = 0; i < menu_width; i++) - waddch(win, ' '); - } -#else - wclrtoeol(win); -#endif - wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); - mvwaddstr(win, line_y, item_x, menu_item); - if (hotkey) { - wattrset(win, selected ? dlg.tag_key_selected.atr - : dlg.tag_key.atr); - mvwaddch(win, line_y, item_x + j, menu_item[j]); - } - if (selected) { - wmove(win, line_y, item_x + 1); - } - free(menu_item); - wrefresh(win); -} - -#define print_item(index, choice, selected) \ -do { \ - item_set(index); \ - do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ -} while (0) - -/* - * Print the scroll indicators. - */ -static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, - int height) -{ - int cur_y, cur_x; - - getyx(win, cur_y, cur_x); - - wmove(win, y, x); - - if (scroll > 0) { - wattrset(win, dlg.uarrow.atr); - waddch(win, ACS_UARROW); - waddstr(win, "(-)"); - } else { - wattrset(win, dlg.menubox.atr); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - } - - y = y + height + 1; - wmove(win, y, x); - wrefresh(win); - - if ((height < item_no) && (scroll + height < item_no)) { - wattrset(win, dlg.darrow.atr); - waddch(win, ACS_DARROW); - waddstr(win, "(+)"); - } else { - wattrset(win, dlg.menubox_border.atr); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - waddch(win, ACS_HLINE); - } - - wmove(win, cur_y, cur_x); - wrefresh(win); -} - -/* - * Display the termination buttons. - */ -static void print_buttons(WINDOW * win, int height, int width, int selected) -{ - int x = width / 2 - 16; - int y = height - 2; - - print_button(win, gettext("Select"), y, x, selected == 0); - print_button(win, gettext(" Exit "), y, x + 12, selected == 1); - print_button(win, gettext(" Help "), y, x + 24, selected == 2); - - wmove(win, y, x + 1 + 12 * selected); - wrefresh(win); -} - -/* scroll up n lines (n may be negative) */ -static void do_scroll(WINDOW *win, int *scroll, int n) -{ - /* Scroll menu up */ - scrollok(win, TRUE); - wscrl(win, n); - scrollok(win, FALSE); - *scroll = *scroll + n; - wrefresh(win); -} - -/* - * Display a menu for choosing among a number of options - */ -int dialog_menu(const char *title, const char *prompt, - const void *selected, int *s_scroll) -{ - int i, j, x, y, box_x, box_y; - int height, width, menu_height; - int key = 0, button = 0, scroll = 0, choice = 0; - int first_item = 0, max_choice; - WINDOW *dialog, *menu; - -do_resize: - height = getmaxy(stdscr); - width = getmaxx(stdscr); - if (height < 15 || width < 65) - return -ERRDISPLAYTOOSMALL; - - height -= 4; - width -= 5; - menu_height = height - 10; - - max_choice = MIN(menu_height, item_count()); - - /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; - - draw_shadow(stdscr, y, x, height, width); - - dialog = newwin(height, width, y, x); - keypad(dialog, TRUE); - - draw_box(dialog, 0, 0, height, width, - dlg.dialog.atr, dlg.border.atr); - wattrset(dialog, dlg.border.atr); - mvwaddch(dialog, height - 3, 0, ACS_LTEE); - for (i = 0; i < width - 2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dlg.dialog.atr); - wbkgdset(dialog, dlg.dialog.atr & A_COLOR); - waddch(dialog, ACS_RTEE); - - print_title(dialog, title, width); - - wattrset(dialog, dlg.dialog.atr); - print_autowrap(dialog, prompt, width - 2, 1, 3); - - menu_width = width - 6; - box_y = height - menu_height - 5; - box_x = (width - menu_width) / 2 - 1; - - /* create new window for the menu */ - menu = subwin(dialog, menu_height, menu_width, - y + box_y + 1, x + box_x + 1); - keypad(menu, TRUE); - - /* draw a box around the menu items */ - draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, - dlg.menubox_border.atr, dlg.menubox.atr); - - if (menu_width >= 80) - item_x = (menu_width - 70) / 2; - else - item_x = 4; - - /* Set choice to default item */ - item_foreach() - if (selected && (selected == item_data())) - choice = item_n(); - /* get the saved scroll info */ - scroll = *s_scroll; - if ((scroll <= choice) && (scroll + max_choice > choice) && - (scroll >= 0) && (scroll + max_choice <= item_count())) { - first_item = scroll; - choice = choice - scroll; - } else { - scroll = 0; - } - if ((choice >= max_choice)) { - if (choice >= item_count() - max_choice / 2) - scroll = first_item = item_count() - max_choice; - else - scroll = first_item = choice - max_choice / 2; - choice = choice - scroll; - } - - /* Print the menu */ - for (i = 0; i < max_choice; i++) { - print_item(first_item + i, i, i == choice); - } - - wnoutrefresh(menu); - - print_arrows(dialog, item_count(), scroll, - box_y, box_x + item_x + 1, menu_height); - - print_buttons(dialog, height, width, 0); - wmove(menu, choice, item_x + 1); - wrefresh(menu); - - while (key != KEY_ESC) { - key = wgetch(menu); - - if (key < 256 && isalpha(key)) - key = tolower(key); - - if (strchr("ynmh", key)) - i = max_choice; - else { - for (i = choice + 1; i < max_choice; i++) { - item_set(scroll + i); - j = first_alpha(item_str(), "YyNnMmHh"); - if (key == tolower(item_str()[j])) - break; - } - if (i == max_choice) - for (i = 0; i < max_choice; i++) { - item_set(scroll + i); - j = first_alpha(item_str(), "YyNnMmHh"); - if (key == tolower(item_str()[j])) - break; - } - } - - if (i < max_choice || - key == KEY_UP || key == KEY_DOWN || - key == '-' || key == '+' || - key == KEY_PPAGE || key == KEY_NPAGE) { - /* Remove highligt of current item */ - print_item(scroll + choice, choice, FALSE); - - if (key == KEY_UP || key == '-') { - if (choice < 2 && scroll) { - /* Scroll menu down */ - do_scroll(menu, &scroll, -1); - - print_item(scroll, 0, FALSE); - } else - choice = MAX(choice - 1, 0); - - } else if (key == KEY_DOWN || key == '+') { - print_item(scroll+choice, choice, FALSE); - - if ((choice > max_choice - 3) && - (scroll + max_choice < item_count())) { - /* Scroll menu up */ - do_scroll(menu, &scroll, 1); - - print_item(scroll+max_choice - 1, - max_choice - 1, FALSE); - } else - choice = MIN(choice + 1, max_choice - 1); - - } else if (key == KEY_PPAGE) { - scrollok(menu, TRUE); - for (i = 0; (i < max_choice); i++) { - if (scroll > 0) { - do_scroll(menu, &scroll, -1); - print_item(scroll, 0, FALSE); - } else { - if (choice > 0) - choice--; - } - } - - } else if (key == KEY_NPAGE) { - for (i = 0; (i < max_choice); i++) { - if (scroll + max_choice < item_count()) { - do_scroll(menu, &scroll, 1); - print_item(scroll+max_choice-1, - max_choice - 1, FALSE); - } else { - if (choice + 1 < max_choice) - choice++; - } - } - } else - choice = i; - - print_item(scroll + choice, choice, TRUE); - - print_arrows(dialog, item_count(), scroll, - box_y, box_x + item_x + 1, menu_height); - - wnoutrefresh(dialog); - wrefresh(menu); - - continue; /* wait for another key press */ - } - - switch (key) { - case KEY_LEFT: - case TAB: - case KEY_RIGHT: - button = ((key == KEY_LEFT ? --button : ++button) < 0) - ? 2 : (button > 2 ? 0 : button); - - print_buttons(dialog, height, width, button); - wrefresh(menu); - break; - case ' ': - case 's': - case 'y': - case 'n': - case 'm': - case '/': - case 'h': - case '?': - case 'z': - case '\n': - /* save scroll info */ - *s_scroll = scroll; - delwin(menu); - delwin(dialog); - item_set(scroll + choice); - item_set_selected(1); - switch (key) { - case 'h': - case '?': - return 2; - case 's': - case 'y': - return 3; - case 'n': - return 4; - case 'm': - return 5; - case ' ': - return 6; - case '/': - return 7; - case 'z': - return 8; - case '\n': - return button; - } - return 0; - case 'e': - case 'x': - key = KEY_ESC; - break; - case KEY_ESC: - key = on_key_esc(menu); - break; - case KEY_RESIZE: - on_key_resize(); - delwin(menu); - delwin(dialog); - goto do_resize; - } - } - delwin(menu); - delwin(dialog); - return key; /* ESC pressed */ -} diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/textbox.c seabios-1.7.4/tools/kconfig/lxdialog/textbox.c --- seabios-1.7.1/tools/kconfig/lxdialog/textbox.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/textbox.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,391 +0,0 @@ -/* - * textbox.c -- implements the text box - * - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; 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. - */ - -#include "dialog.h" - -static void back_lines(int n); -static void print_page(WINDOW * win, int height, int width); -static void print_line(WINDOW * win, int row, int width); -static char *get_line(void); -static void print_position(WINDOW * win); - -static int hscroll; -static int begin_reached, end_reached, page_length; -static const char *buf; -static const char *page; - -/* - * refresh window content - */ -static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, - int cur_y, int cur_x) -{ - print_page(box, boxh, boxw); - print_position(dialog); - wmove(dialog, cur_y, cur_x); /* Restore cursor position */ - wrefresh(dialog); -} - - -/* - * Display text from a file in a dialog box. - */ -int dialog_textbox(const char *title, const char *tbuf, - int initial_height, int initial_width) -{ - int i, x, y, cur_x, cur_y, key = 0; - int height, width, boxh, boxw; - int passed_end; - WINDOW *dialog, *box; - - begin_reached = 1; - end_reached = 0; - page_length = 0; - hscroll = 0; - buf = tbuf; - page = buf; /* page is pointer to start of page to be displayed */ - -do_resize: - getmaxyx(stdscr, height, width); - if (height < 8 || width < 8) - return -ERRDISPLAYTOOSMALL; - if (initial_height != 0) - height = initial_height; - else - if (height > 4) - height -= 4; - else - height = 0; - if (initial_width != 0) - width = initial_width; - else - if (width > 5) - width -= 5; - else - width = 0; - - /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; - - draw_shadow(stdscr, y, x, height, width); - - dialog = newwin(height, width, y, x); - keypad(dialog, TRUE); - - /* Create window for box region, used for scrolling text */ - boxh = height - 4; - boxw = width - 2; - box = subwin(dialog, boxh, boxw, y + 1, x + 1); - wattrset(box, dlg.dialog.atr); - wbkgdset(box, dlg.dialog.atr & A_COLOR); - - keypad(box, TRUE); - - /* register the new window, along with its borders */ - draw_box(dialog, 0, 0, height, width, - dlg.dialog.atr, dlg.border.atr); - - wattrset(dialog, dlg.border.atr); - mvwaddch(dialog, height - 3, 0, ACS_LTEE); - for (i = 0; i < width - 2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dlg.dialog.atr); - wbkgdset(dialog, dlg.dialog.atr & A_COLOR); - waddch(dialog, ACS_RTEE); - - print_title(dialog, title, width); - - print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); - wnoutrefresh(dialog); - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - - /* Print first page of text */ - attr_clear(box, boxh, boxw, dlg.dialog.atr); - refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); - - while ((key != KEY_ESC) && (key != '\n')) { - key = wgetch(dialog); - switch (key) { - case 'E': /* Exit */ - case 'e': - case 'X': - case 'x': - delwin(box); - delwin(dialog); - return 0; - case 'g': /* First page */ - case KEY_HOME: - if (!begin_reached) { - begin_reached = 1; - page = buf; - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); - } - break; - case 'G': /* Last page */ - case KEY_END: - - end_reached = 1; - /* point to last char in buf */ - page = buf + strlen(buf); - back_lines(boxh); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); - break; - case 'K': /* Previous line */ - case 'k': - case KEY_UP: - if (!begin_reached) { - back_lines(page_length + 1); - - /* We don't call print_page() here but use - * scrolling to ensure faster screen update. - * However, 'end_reached' and 'page_length' - * should still be updated, and 'page' should - * point to start of next page. This is done - * by calling get_line() in the following - * 'for' loop. */ - scrollok(box, TRUE); - wscrl(box, -1); /* Scroll box region down one line */ - scrollok(box, FALSE); - page_length = 0; - passed_end = 0; - for (i = 0; i < boxh; i++) { - if (!i) { - /* print first line of page */ - print_line(box, 0, boxw); - wnoutrefresh(box); - } else - /* Called to update 'end_reached' and 'page' */ - get_line(); - if (!passed_end) - page_length++; - if (end_reached && !passed_end) - passed_end = 1; - } - - print_position(dialog); - wmove(dialog, cur_y, cur_x); /* Restore cursor position */ - wrefresh(dialog); - } - break; - case 'B': /* Previous page */ - case 'b': - case KEY_PPAGE: - if (begin_reached) - break; - back_lines(page_length + boxh); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); - break; - case 'J': /* Next line */ - case 'j': - case KEY_DOWN: - if (!end_reached) { - begin_reached = 0; - scrollok(box, TRUE); - scroll(box); /* Scroll box region up one line */ - scrollok(box, FALSE); - print_line(box, boxh - 1, boxw); - wnoutrefresh(box); - print_position(dialog); - wmove(dialog, cur_y, cur_x); /* Restore cursor position */ - wrefresh(dialog); - } - break; - case KEY_NPAGE: /* Next page */ - case ' ': - if (end_reached) - break; - - begin_reached = 0; - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); - break; - case '0': /* Beginning of line */ - case 'H': /* Scroll left */ - case 'h': - case KEY_LEFT: - if (hscroll <= 0) - break; - - if (key == '0') - hscroll = 0; - else - hscroll--; - /* Reprint current page to scroll horizontally */ - back_lines(page_length); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); - break; - case 'L': /* Scroll right */ - case 'l': - case KEY_RIGHT: - if (hscroll >= MAX_LEN) - break; - hscroll++; - /* Reprint current page to scroll horizontally */ - back_lines(page_length); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); - break; - case KEY_ESC: - key = on_key_esc(dialog); - break; - case KEY_RESIZE: - back_lines(height); - delwin(box); - delwin(dialog); - on_key_resize(); - goto do_resize; - } - } - delwin(box); - delwin(dialog); - return key; /* ESC pressed */ -} - -/* - * Go back 'n' lines in text. Called by dialog_textbox(). - * 'page' will be updated to point to the desired line in 'buf'. - */ -static void back_lines(int n) -{ - int i; - - begin_reached = 0; - /* Go back 'n' lines */ - for (i = 0; i < n; i++) { - if (*page == '\0') { - if (end_reached) { - end_reached = 0; - continue; - } - } - if (page == buf) { - begin_reached = 1; - return; - } - page--; - do { - if (page == buf) { - begin_reached = 1; - return; - } - page--; - } while (*page != '\n'); - page++; - } -} - -/* - * Print a new page of text. Called by dialog_textbox(). - */ -static void print_page(WINDOW * win, int height, int width) -{ - int i, passed_end = 0; - - page_length = 0; - for (i = 0; i < height; i++) { - print_line(win, i, width); - if (!passed_end) - page_length++; - if (end_reached && !passed_end) - passed_end = 1; - } - wnoutrefresh(win); -} - -/* - * Print a new line of text. Called by dialog_textbox() and print_page(). - */ -static void print_line(WINDOW * win, int row, int width) -{ - int y, x; - char *line; - - line = get_line(); - line += MIN(strlen(line), hscroll); /* Scroll horizontally */ - wmove(win, row, 0); /* move cursor to correct line */ - waddch(win, ' '); - waddnstr(win, line, MIN(strlen(line), width - 2)); - - getyx(win, y, x); - /* Clear 'residue' of previous line */ -#if OLD_NCURSES - { - int i; - for (i = 0; i < width - x; i++) - waddch(win, ' '); - } -#else - wclrtoeol(win); -#endif -} - -/* - * Return current line of text. Called by dialog_textbox() and print_line(). - * 'page' should point to start of current line before calling, and will be - * updated to point to start of next line. - */ -static char *get_line(void) -{ - int i = 0; - static char line[MAX_LEN + 1]; - - end_reached = 0; - while (*page != '\n') { - if (*page == '\0') { - if (!end_reached) { - end_reached = 1; - break; - } - } else if (i < MAX_LEN) - line[i++] = *(page++); - else { - /* Truncate lines longer than MAX_LEN characters */ - if (i == MAX_LEN) - line[i++] = '\0'; - page++; - } - } - if (i <= MAX_LEN) - line[i] = '\0'; - if (!end_reached) - page++; /* move pass '\n' */ - - return line; -} - -/* - * Print current position - */ -static void print_position(WINDOW * win) -{ - int percent; - - wattrset(win, dlg.position_indicator.atr); - wbkgdset(win, dlg.position_indicator.atr & A_COLOR); - percent = (page - buf) * 100 / strlen(buf); - wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); - wprintw(win, "(%3d%%)", percent); -} diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/util.c seabios-1.7.4/tools/kconfig/lxdialog/util.c --- seabios-1.7.1/tools/kconfig/lxdialog/util.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/util.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,657 +0,0 @@ -/* - * util.c - * - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; 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. - */ - -#include - -#include "dialog.h" - -struct dialog_info dlg; - -static void set_mono_theme(void) -{ - dlg.screen.atr = A_NORMAL; - dlg.shadow.atr = A_NORMAL; - dlg.dialog.atr = A_NORMAL; - dlg.title.atr = A_BOLD; - dlg.border.atr = A_NORMAL; - dlg.button_active.atr = A_REVERSE; - dlg.button_inactive.atr = A_DIM; - dlg.button_key_active.atr = A_REVERSE; - dlg.button_key_inactive.atr = A_BOLD; - dlg.button_label_active.atr = A_REVERSE; - dlg.button_label_inactive.atr = A_NORMAL; - dlg.inputbox.atr = A_NORMAL; - dlg.inputbox_border.atr = A_NORMAL; - dlg.searchbox.atr = A_NORMAL; - dlg.searchbox_title.atr = A_BOLD; - dlg.searchbox_border.atr = A_NORMAL; - dlg.position_indicator.atr = A_BOLD; - dlg.menubox.atr = A_NORMAL; - dlg.menubox_border.atr = A_NORMAL; - dlg.item.atr = A_NORMAL; - dlg.item_selected.atr = A_REVERSE; - dlg.tag.atr = A_BOLD; - dlg.tag_selected.atr = A_REVERSE; - dlg.tag_key.atr = A_BOLD; - dlg.tag_key_selected.atr = A_REVERSE; - dlg.check.atr = A_BOLD; - dlg.check_selected.atr = A_REVERSE; - dlg.uarrow.atr = A_BOLD; - dlg.darrow.atr = A_BOLD; -} - -#define DLG_COLOR(dialog, f, b, h) \ -do { \ - dlg.dialog.fg = (f); \ - dlg.dialog.bg = (b); \ - dlg.dialog.hl = (h); \ -} while (0) - -static void set_classic_theme(void) -{ - DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); - DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); - DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); - DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); - DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); - DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); - DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); - DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); - DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); - DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); - DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); - DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); - DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); - DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); - DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); - DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); - DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); - DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); - DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); - DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); - DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); - DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); -} - -static void set_blackbg_theme(void) -{ - DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); - DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); - DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); - DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); - DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); - - DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); - DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); - DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); - DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); - DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); - DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); - - DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); - DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); - - DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); - DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); - DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); - - DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); - - DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); - DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); - - DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); - DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); - - DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); - DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); - DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); - DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); - - DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); - DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); - - DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); - DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); -} - -static void set_bluetitle_theme(void) -{ - set_classic_theme(); - DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); - DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); - DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); - DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); - DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); - DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); - DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); - -} - -/* - * Select color theme - */ -static int set_theme(const char *theme) -{ - int use_color = 1; - if (!theme) - set_bluetitle_theme(); - else if (strcmp(theme, "classic") == 0) - set_classic_theme(); - else if (strcmp(theme, "bluetitle") == 0) - set_bluetitle_theme(); - else if (strcmp(theme, "blackbg") == 0) - set_blackbg_theme(); - else if (strcmp(theme, "mono") == 0) - use_color = 0; - - return use_color; -} - -static void init_one_color(struct dialog_color *color) -{ - static int pair = 0; - - pair++; - init_pair(pair, color->fg, color->bg); - if (color->hl) - color->atr = A_BOLD | COLOR_PAIR(pair); - else - color->atr = COLOR_PAIR(pair); -} - -static void init_dialog_colors(void) -{ - init_one_color(&dlg.screen); - init_one_color(&dlg.shadow); - init_one_color(&dlg.dialog); - init_one_color(&dlg.title); - init_one_color(&dlg.border); - init_one_color(&dlg.button_active); - init_one_color(&dlg.button_inactive); - init_one_color(&dlg.button_key_active); - init_one_color(&dlg.button_key_inactive); - init_one_color(&dlg.button_label_active); - init_one_color(&dlg.button_label_inactive); - init_one_color(&dlg.inputbox); - init_one_color(&dlg.inputbox_border); - init_one_color(&dlg.searchbox); - init_one_color(&dlg.searchbox_title); - init_one_color(&dlg.searchbox_border); - init_one_color(&dlg.position_indicator); - init_one_color(&dlg.menubox); - init_one_color(&dlg.menubox_border); - init_one_color(&dlg.item); - init_one_color(&dlg.item_selected); - init_one_color(&dlg.tag); - init_one_color(&dlg.tag_selected); - init_one_color(&dlg.tag_key); - init_one_color(&dlg.tag_key_selected); - init_one_color(&dlg.check); - init_one_color(&dlg.check_selected); - init_one_color(&dlg.uarrow); - init_one_color(&dlg.darrow); -} - -/* - * Setup for color display - */ -static void color_setup(const char *theme) -{ - int use_color; - - use_color = set_theme(theme); - if (use_color && has_colors()) { - start_color(); - init_dialog_colors(); - } else - set_mono_theme(); -} - -/* - * Set window to attribute 'attr' - */ -void attr_clear(WINDOW * win, int height, int width, chtype attr) -{ - int i, j; - - wattrset(win, attr); - for (i = 0; i < height; i++) { - wmove(win, i, 0); - for (j = 0; j < width; j++) - waddch(win, ' '); - } - touchwin(win); -} - -void dialog_clear(void) -{ - attr_clear(stdscr, LINES, COLS, dlg.screen.atr); - /* Display background title if it exists ... - SLH */ - if (dlg.backtitle != NULL) { - int i; - - wattrset(stdscr, dlg.screen.atr); - mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); - wmove(stdscr, 1, 1); - for (i = 1; i < COLS - 1; i++) - waddch(stdscr, ACS_HLINE); - } - wnoutrefresh(stdscr); -} - -/* - * Do some initialization for dialog - */ -int init_dialog(const char *backtitle) -{ - int height, width; - - initscr(); /* Init curses */ - getmaxyx(stdscr, height, width); - if (height < 19 || width < 80) { - endwin(); - return -ERRDISPLAYTOOSMALL; - } - - dlg.backtitle = backtitle; - color_setup(getenv("MENUCONFIG_COLOR")); - - keypad(stdscr, TRUE); - cbreak(); - noecho(); - dialog_clear(); - - return 0; -} - -void set_dialog_backtitle(const char *backtitle) -{ - dlg.backtitle = backtitle; -} - -/* - * End using dialog functions. - */ -void end_dialog(int x, int y) -{ - /* move cursor back to original position */ - move(y, x); - refresh(); - endwin(); -} - -/* Print the title of the dialog. Center the title and truncate - * tile if wider than dialog (- 2 chars). - **/ -void print_title(WINDOW *dialog, const char *title, int width) -{ - if (title) { - int tlen = MIN(width - 2, strlen(title)); - wattrset(dialog, dlg.title.atr); - mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); - mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); - waddch(dialog, ' '); - } -} - -/* - * Print a string of text in a window, automatically wrap around to the - * next line if the string is too long to fit on one line. Newline - * characters '\n' are replaced by spaces. We start on a new line - * if there is no room for at least 4 nonblanks following a double-space. - */ -void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) -{ - int newl, cur_x, cur_y; - int i, prompt_len, room, wlen; - char tempstr[MAX_LEN + 1], *word, *sp, *sp2; - - strcpy(tempstr, prompt); - - prompt_len = strlen(tempstr); - - /* - * Remove newlines - */ - for (i = 0; i < prompt_len; i++) { - if (tempstr[i] == '\n') - tempstr[i] = ' '; - } - - if (prompt_len <= width - x * 2) { /* If prompt is short */ - wmove(win, y, (width - prompt_len) / 2); - waddstr(win, tempstr); - } else { - cur_x = x; - cur_y = y; - newl = 1; - word = tempstr; - while (word && *word) { - sp = strchr(word, ' '); - if (sp) - *sp++ = 0; - - /* Wrap to next line if either the word does not fit, - or it is the first word of a new sentence, and it is - short, and the next word does not fit. */ - room = width - cur_x; - wlen = strlen(word); - if (wlen > room || - (newl && wlen < 4 && sp - && wlen + 1 + strlen(sp) > room - && (!(sp2 = strchr(sp, ' ')) - || wlen + 1 + (sp2 - sp) > room))) { - cur_y++; - cur_x = x; - } - wmove(win, cur_y, cur_x); - waddstr(win, word); - getyx(win, cur_y, cur_x); - cur_x++; - if (sp && *sp == ' ') { - cur_x++; /* double space */ - while (*++sp == ' ') ; - newl = 1; - } else - newl = 0; - word = sp; - } - } -} - -/* - * Print a button - */ -void print_button(WINDOW * win, const char *label, int y, int x, int selected) -{ - int i, temp; - - wmove(win, y, x); - wattrset(win, selected ? dlg.button_active.atr - : dlg.button_inactive.atr); - waddstr(win, "<"); - temp = strspn(label, " "); - label += temp; - wattrset(win, selected ? dlg.button_label_active.atr - : dlg.button_label_inactive.atr); - for (i = 0; i < temp; i++) - waddch(win, ' '); - wattrset(win, selected ? dlg.button_key_active.atr - : dlg.button_key_inactive.atr); - waddch(win, label[0]); - wattrset(win, selected ? dlg.button_label_active.atr - : dlg.button_label_inactive.atr); - waddstr(win, (char *)label + 1); - wattrset(win, selected ? dlg.button_active.atr - : dlg.button_inactive.atr); - waddstr(win, ">"); - wmove(win, y, x + temp + 1); -} - -/* - * Draw a rectangular box with line drawing characters - */ -void -draw_box(WINDOW * win, int y, int x, int height, int width, - chtype box, chtype border) -{ - int i, j; - - wattrset(win, 0); - for (i = 0; i < height; i++) { - wmove(win, y + i, x); - for (j = 0; j < width; j++) - if (!i && !j) - waddch(win, border | ACS_ULCORNER); - else if (i == height - 1 && !j) - waddch(win, border | ACS_LLCORNER); - else if (!i && j == width - 1) - waddch(win, box | ACS_URCORNER); - else if (i == height - 1 && j == width - 1) - waddch(win, box | ACS_LRCORNER); - else if (!i) - waddch(win, border | ACS_HLINE); - else if (i == height - 1) - waddch(win, box | ACS_HLINE); - else if (!j) - waddch(win, border | ACS_VLINE); - else if (j == width - 1) - waddch(win, box | ACS_VLINE); - else - waddch(win, box | ' '); - } -} - -/* - * Draw shadows along the right and bottom edge to give a more 3D look - * to the boxes - */ -void draw_shadow(WINDOW * win, int y, int x, int height, int width) -{ - int i; - - if (has_colors()) { /* Whether terminal supports color? */ - wattrset(win, dlg.shadow.atr); - wmove(win, y + height, x + 2); - for (i = 0; i < width; i++) - waddch(win, winch(win) & A_CHARTEXT); - for (i = y + 1; i < y + height + 1; i++) { - wmove(win, i, x + width); - waddch(win, winch(win) & A_CHARTEXT); - waddch(win, winch(win) & A_CHARTEXT); - } - wnoutrefresh(win); - } -} - -/* - * Return the position of the first alphabetic character in a string. - */ -int first_alpha(const char *string, const char *exempt) -{ - int i, in_paren = 0, c; - - for (i = 0; i < strlen(string); i++) { - c = tolower(string[i]); - - if (strchr("<[(", c)) - ++in_paren; - if (strchr(">])", c) && in_paren > 0) - --in_paren; - - if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) - return i; - } - - return 0; -} - -/* - * ncurses uses ESC to detect escaped char sequences. This resutl in - * a small timeout before ESC is actually delivered to the application. - * lxdialog suggest which is correctly translated to two - * times esc. But then we need to ignore the second esc to avoid stepping - * out one menu too much. Filter away all escaped key sequences since - * keypad(FALSE) turn off ncurses support for escape sequences - and thats - * needed to make notimeout() do as expected. - */ -int on_key_esc(WINDOW *win) -{ - int key; - int key2; - int key3; - - nodelay(win, TRUE); - keypad(win, FALSE); - key = wgetch(win); - key2 = wgetch(win); - do { - key3 = wgetch(win); - } while (key3 != ERR); - nodelay(win, FALSE); - keypad(win, TRUE); - if (key == KEY_ESC && key2 == ERR) - return KEY_ESC; - else if (key != ERR && key != KEY_ESC && key2 == ERR) - ungetch(key); - - return -1; -} - -/* redraw screen in new size */ -int on_key_resize(void) -{ - dialog_clear(); - return KEY_RESIZE; -} - -struct dialog_list *item_cur; -struct dialog_list item_nil; -struct dialog_list *item_head; - -void item_reset(void) -{ - struct dialog_list *p, *next; - - for (p = item_head; p; p = next) { - next = p->next; - free(p); - } - item_head = NULL; - item_cur = &item_nil; -} - -void item_make(const char *fmt, ...) -{ - va_list ap; - struct dialog_list *p = malloc(sizeof(*p)); - - if (item_head) - item_cur->next = p; - else - item_head = p; - item_cur = p; - memset(p, 0, sizeof(*p)); - - va_start(ap, fmt); - vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); - va_end(ap); -} - -void item_add_str(const char *fmt, ...) -{ - va_list ap; - size_t avail; - - avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); - - va_start(ap, fmt); - vsnprintf(item_cur->node.str + strlen(item_cur->node.str), - avail, fmt, ap); - item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; - va_end(ap); -} - -void item_set_tag(char tag) -{ - item_cur->node.tag = tag; -} -void item_set_data(void *ptr) -{ - item_cur->node.data = ptr; -} - -void item_set_selected(int val) -{ - item_cur->node.selected = val; -} - -int item_activate_selected(void) -{ - item_foreach() - if (item_is_selected()) - return 1; - return 0; -} - -void *item_data(void) -{ - return item_cur->node.data; -} - -char item_tag(void) -{ - return item_cur->node.tag; -} - -int item_count(void) -{ - int n = 0; - struct dialog_list *p; - - for (p = item_head; p; p = p->next) - n++; - return n; -} - -void item_set(int n) -{ - int i = 0; - item_foreach() - if (i++ == n) - return; -} - -int item_n(void) -{ - int n = 0; - struct dialog_list *p; - - for (p = item_head; p; p = p->next) { - if (p == item_cur) - return n; - n++; - } - return 0; -} - -const char *item_str(void) -{ - return item_cur->node.str; -} - -int item_is_selected(void) -{ - return (item_cur->node.selected != 0); -} - -int item_is_tag(char tag) -{ - return (item_cur->node.tag == tag); -} diff -Nru seabios-1.7.1/tools/kconfig/lxdialog/yesno.c seabios-1.7.4/tools/kconfig/lxdialog/yesno.c --- seabios-1.7.1/tools/kconfig/lxdialog/yesno.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/lxdialog/yesno.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -/* - * yesno.c -- implements the yes/no box - * - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; 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. - */ - -#include "dialog.h" - -/* - * Display termination buttons - */ -static void print_buttons(WINDOW * dialog, int height, int width, int selected) -{ - int x = width / 2 - 10; - int y = height - 2; - - print_button(dialog, gettext(" Yes "), y, x, selected == 0); - print_button(dialog, gettext(" No "), y, x + 13, selected == 1); - - wmove(dialog, y, x + 1 + 13 * selected); - wrefresh(dialog); -} - -/* - * Display a dialog box with two buttons - Yes and No - */ -int dialog_yesno(const char *title, const char *prompt, int height, int width) -{ - int i, x, y, key = 0, button = 0; - WINDOW *dialog; - -do_resize: - if (getmaxy(stdscr) < (height + 4)) - return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) < (width + 4)) - return -ERRDISPLAYTOOSMALL; - - /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; - - draw_shadow(stdscr, y, x, height, width); - - dialog = newwin(height, width, y, x); - keypad(dialog, TRUE); - - draw_box(dialog, 0, 0, height, width, - dlg.dialog.atr, dlg.border.atr); - wattrset(dialog, dlg.border.atr); - mvwaddch(dialog, height - 3, 0, ACS_LTEE); - for (i = 0; i < width - 2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dlg.dialog.atr); - waddch(dialog, ACS_RTEE); - - print_title(dialog, title, width); - - wattrset(dialog, dlg.dialog.atr); - print_autowrap(dialog, prompt, width - 2, 1, 3); - - print_buttons(dialog, height, width, 0); - - while (key != KEY_ESC) { - key = wgetch(dialog); - switch (key) { - case 'Y': - case 'y': - delwin(dialog); - return 0; - case 'N': - case 'n': - delwin(dialog); - return 1; - - case TAB: - case KEY_LEFT: - case KEY_RIGHT: - button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); - - print_buttons(dialog, height, width, button); - wrefresh(dialog); - break; - case ' ': - case '\n': - delwin(dialog); - return button; - case KEY_ESC: - key = on_key_esc(dialog); - break; - case KEY_RESIZE: - delwin(dialog); - on_key_resize(); - goto do_resize; - } - } - - delwin(dialog); - return key; /* ESC pressed */ -} diff -Nru seabios-1.7.1/tools/kconfig/Makefile seabios-1.7.4/tools/kconfig/Makefile --- seabios-1.7.1/tools/kconfig/Makefile 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,361 +0,0 @@ -# =========================================================================== -# Kernel configuration targets -# These targets are used from top-level makefile - -PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \ - localmodconfig localyesconfig - -ifdef KBUILD_KCONFIG -Kconfig := $(KBUILD_KCONFIG) -else -Kconfig := Kconfig -endif - -xconfig: $(obj)/qconf - $< $(Kconfig) - -gconfig: $(obj)/gconf - $< $(Kconfig) - -menuconfig: $(obj)/mconf - $< $(Kconfig) - -config: $(obj)/conf - $< --oldaskconfig $(Kconfig) - -nconfig: $(obj)/nconf - $< $(Kconfig) - -oldconfig: $(obj)/conf - $< --$@ $(Kconfig) - -silentoldconfig: $(obj)/conf - @echo " Build Kconfig config file" - $(Q)mkdir -p include/generated - $(Q)$< --$@ $(Kconfig) - -# if no path is given, then use src directory to find file -ifdef LSMOD -LSMOD_F := $(LSMOD) -ifeq ($(findstring /,$(LSMOD)),) - LSMOD_F := $(objtree)/$(LSMOD) -endif -endif - -localmodconfig: $(obj)/streamline_config.pl $(obj)/conf - $(Q)mkdir -p include/generated - $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config - $(Q)if [ -f .config ]; then \ - cmp -s .tmp.config .config || \ - (mv -f .config .config.old.1; \ - mv -f .tmp.config .config; \ - $(obj)/conf --silentoldconfig $(Kconfig); \ - mv -f .config.old.1 .config.old) \ - else \ - mv -f .tmp.config .config; \ - $(obj)/conf --silentoldconfig $(Kconfig); \ - fi - $(Q)rm -f .tmp.config - -localyesconfig: $(obj)/streamline_config.pl $(obj)/conf - $(Q)mkdir -p include/generated - $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config - $(Q)sed -i s/=m/=y/ .tmp.config - $(Q)if [ -f .config ]; then \ - cmp -s .tmp.config .config || \ - (mv -f .config .config.old.1; \ - mv -f .tmp.config .config; \ - $(obj)/conf --silentoldconfig $(Kconfig); \ - mv -f .config.old.1 .config.old) \ - else \ - mv -f .tmp.config .config; \ - $(obj)/conf --silentoldconfig $(Kconfig); \ - fi - $(Q)rm -f .tmp.config - -# Create new linux.pot file -# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files -# The symlink is used to repair a deficiency in arch/um -update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h - $(Q)echo " GEN config" - $(Q)xgettext --default-domain=linux \ - --add-comments --keyword=_ --keyword=N_ \ - --from-code=UTF-8 \ - --files-from=tools/kconfig/POTFILES.in \ - --output $(obj)/config.pot - $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot - $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch - $(Q)(for i in `ls arch/*/Kconfig`; \ - do \ - echo " GEN $$i"; \ - $(obj)/kxgettext $$i \ - >> $(obj)/config.pot; \ - done ) - $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ - --output $(obj)/linux.pot - $(Q)rm -f arch/um/Kconfig.arch - $(Q)rm -f $(obj)/config.pot - -PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig - -allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf - $< --$@ $(Kconfig) - -PHONY += listnewconfig oldnoconfig savedefconfig defconfig - -listnewconfig oldnoconfig: $(obj)/conf - $< --$@ $(Kconfig) - -savedefconfig: $(obj)/conf - $< --$@=defconfig $(Kconfig) - -defconfig: $(obj)/conf - @echo " Build default config" - $(Q)$< --defconfig=/dev/null $(Kconfig) - -# Help text used by make help -help: - @echo ' config - Update current config utilising a line-oriented program' - @echo ' nconfig - Update current config utilising a ncurses menu based program' - @echo ' menuconfig - Update current config utilising a menu based program' - @echo ' xconfig - Update current config utilising a QT based front-end' - @echo ' gconfig - Update current config utilising a GTK based front-end' - @echo ' oldconfig - Update current config utilising a provided .config as base' - @echo ' localmodconfig - Update current config disabling modules not loaded' - @echo ' localyesconfig - Update current config converting local mods to core' - @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps' - @echo ' defconfig - New config with default from ARCH supplied defconfig' - @echo ' savedefconfig - Save current config as ./defconfig (minimal config)' - @echo ' allnoconfig - New config where all options are answered with no' - @echo ' allyesconfig - New config where all options are accepted with yes' - @echo ' allmodconfig - New config selecting modules when possible' - @echo ' alldefconfig - New config with all symbols set to default' - @echo ' randconfig - New config with random answer to all options' - @echo ' listnewconfig - List new options' - @echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)' - -# lxdialog stuff -check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh - -# Use recursively expanded variables so we do not call gcc unless -# we really need to do so. (Do not call gcc as part of make mrproper) -HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ - -DLOCALE - -# =========================================================================== -# Shared Makefile for the various kconfig executables: -# conf: Used for defconfig, oldconfig and related targets -# nconf: Used for the nconfig target. -# Utilizes ncurses -# mconf: Used for the menuconfig target -# Utilizes the lxdialog package -# qconf: Used for the xconfig target -# Based on QT which needs to be installed to compile it -# gconf: Used for the gconfig target -# Based on GTK which needs to be installed to compile it -# object files used by all kconfig flavours - -lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o -lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o - -conf-objs := conf.o zconf.tab.o -mconf-objs := mconf.o zconf.tab.o $(lxdialog) -nconf-objs := nconf.o zconf.tab.o nconf.gui.o -kxgettext-objs := kxgettext.o zconf.tab.o - -hostprogs-y := conf qconf gconf kxgettext - -ifeq ($(MAKECMDGOALS),nconfig) - hostprogs-y += nconf -endif - -ifeq ($(MAKECMDGOALS),menuconfig) - hostprogs-y += mconf -endif - -ifeq ($(MAKECMDGOALS),xconfig) - qconf-target := 1 -endif -ifeq ($(MAKECMDGOALS),gconfig) - gconf-target := 1 -endif - - -ifeq ($(qconf-target),1) -qconf-cxxobjs := qconf.o -qconf-objs := kconfig_load.o zconf.tab.o -endif - -ifeq ($(gconf-target),1) -gconf-objs := gconf.o kconfig_load.o zconf.tab.o -endif - -clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ - .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h -clean-files += mconf qconf gconf nconf -clean-files += config.pot linux.pot - -# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) -PHONY += $(obj)/dochecklxdialog -$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog -$(obj)/dochecklxdialog: - $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf) - -always := dochecklxdialog - -# Add environment specific flags -HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) - -# generated files seem to need this to find local include files -HOSTCFLAGS_lex.zconf.o := -I$(src) -HOSTCFLAGS_zconf.tab.o := -I$(src) - -HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl -HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK - -HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl -HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ - -D LKC_DIRECT_LINK - -HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) - -HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses -$(obj)/qconf.o: $(obj)/.tmp_qtcheck - -ifeq ($(qconf-target),1) -$(obj)/.tmp_qtcheck: $(src)/Makefile --include $(obj)/.tmp_qtcheck - -# QT needs some extra effort... -$(obj)/.tmp_qtcheck: - @set -e; echo " CHECK qt"; dir=""; pkg=""; \ - if ! pkg-config --exists QtCore 2> /dev/null; then \ - echo "* Unable to find the QT4 tool qmake. Trying to use QT3"; \ - pkg-config --exists qt 2> /dev/null && pkg=qt; \ - pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \ - if [ -n "$$pkg" ]; then \ - cflags="\$$(shell pkg-config $$pkg --cflags)"; \ - libs="\$$(shell pkg-config $$pkg --libs)"; \ - moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \ - dir="$$(pkg-config $$pkg --variable=prefix)"; \ - else \ - for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ - if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ - done; \ - if [ -z "$$dir" ]; then \ - echo "*"; \ - echo "* Unable to find any QT installation. Please make sure that"; \ - echo "* the QT4 or QT3 development package is correctly installed and"; \ - echo "* either qmake can be found or install pkg-config or set"; \ - echo "* the QTDIR environment variable to the correct location."; \ - echo "*"; \ - false; \ - fi; \ - libpath=$$dir/lib; lib=qt; osdir=""; \ - $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ - osdir=x$$($(HOSTCXX) -print-multi-os-directory); \ - test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \ - test -f $$libpath/libqt-mt.so && lib=qt-mt; \ - cflags="-I$$dir/include"; \ - libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \ - moc="$$dir/bin/moc"; \ - fi; \ - if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \ - echo "*"; \ - echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \ - echo "*"; \ - moc="/usr/bin/moc"; \ - fi; \ - else \ - cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \ - libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \ - binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \ - moc="$$binpath/bin/moc"; \ - fi; \ - echo "KC_QT_CFLAGS=$$cflags" > $@; \ - echo "KC_QT_LIBS=$$libs" >> $@; \ - echo "KC_QT_MOC=$$moc" >> $@ -endif - -$(obj)/gconf.o: $(obj)/.tmp_gtkcheck - -ifeq ($(gconf-target),1) --include $(obj)/.tmp_gtkcheck - -# GTK needs some extra effort, too... -$(obj)/.tmp_gtkcheck: - @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \ - if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ - touch $@; \ - else \ - echo "*"; \ - echo "* GTK+ is present but version >= 2.0.0 is required."; \ - echo "*"; \ - false; \ - fi \ - else \ - echo "*"; \ - echo "* Unable to find the GTK+ installation. Please make sure that"; \ - echo "* the GTK+ 2.0 development package is correctly installed..."; \ - echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ - echo "*"; \ - false; \ - fi -endif - -$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c - -$(obj)/kconfig_load.o: $(obj)/lkc_defs.h - -$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h - -$(obj)/gconf.o: $(obj)/lkc_defs.h - -$(obj)/%.moc: $(src)/%.h - $(KC_QT_MOC) -i $< -o $@ - -$(obj)/lkc_defs.h: $(src)/lkc_proto.h - sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' - -# Extract gconf menu items for I18N support -$(obj)/gconf.glade.h: $(obj)/gconf.glade - intltool-extract --type=gettext/glade $(obj)/gconf.glade - -### -# The following requires flex/bison/gperf -# By default we use the _shipped versions, uncomment the following line if -# you are modifying the flex/bison src. -# LKC_GENPARSER := 1 - -ifdef LKC_GENPARSER - -$(obj)/zconf.tab.c: $(src)/zconf.y -$(obj)/lex.zconf.c: $(src)/zconf.l -$(obj)/zconf.hash.c: $(src)/zconf.gperf - -%.tab.c: %.y - bison -l -b $* -p $(notdir $*) $< - cp $@ $@_shipped - -lex.%.c: %.l - flex -L -P$(notdir $*) -o$@ $< - cp $@ $@_shipped - -%.hash.c: %.gperf - gperf < $< > $@ - cp $@ $@_shipped - -endif - -VPATH := $(srctree) - -$(obj)/%:: $(src)/%_shipped - $(Q)cat $< > $@ - -host-cobjs := $(sort $(foreach m,$(hostprogs-y),$($(m)-objs))) -host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) -hostprogs-y := $(addprefix $(obj)/,$(hostprogs-y)) -$(host-cobjs) : $(obj)/%.o : $(src)/%.c - $(Q)$(HOSTCC) -I$(obj) -I$(srctree)/$(src) $(HOSTCFLAGS) $(HOSTCFLAGS_$(@F)) $(HOST_EXTRACFLAGS) -c -o $@ $< -$(hostprogs-y) : $(obj)/% : $(host-cobjs) - $(Q)$(HOSTCC) $(HOSTLDFLAGS) -o $@ $(addprefix $(obj)/,$($(@F)-objs)) $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) diff -Nru seabios-1.7.1/tools/kconfig/mconf.c seabios-1.7.4/tools/kconfig/mconf.c --- seabios-1.7.1/tools/kconfig/mconf.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/mconf.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,862 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - * - * Introduced single menu mode (show all sub-menus in one large tree). - * 2002-11-06 Petr Baudis - * - * i18n, 2005, Arnaldo Carvalho de Melo - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" -#include "lxdialog/dialog.h" - -static const char mconf_readme[] = N_( -"Overview\n" -"--------\n" -"This interface let you select features and parameters for the build.\n" -"Features can either be built-in, modularized, or ignored. Parameters\n" -"must be entered in as decimal or hexadecimal numbers or text.\n" -"\n" -"Menu items beginning with following braces represent features that\n" -" [ ] can be built in or removed\n" -" < > can be built in, modularized or removed\n" -" { } can be built in or modularized (selected by other feature)\n" -" - - are selected by other feature,\n" -"while *, M or whitespace inside braces means to build in, build as\n" -"a module or to exclude the feature respectively.\n" -"\n" -"To change any of these features, highlight it with the cursor\n" -"keys and press to build it in, to make it a module or\n" -" to removed it. You may also press the to cycle\n" -"through the available options (ie. Y->N->M->Y).\n" -"\n" -"Some additional keyboard hints:\n" -"\n" -"Menus\n" -"----------\n" -"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" -" you wish to change or submenu wish to select and press .\n" -" Submenus are designated by \"--->\".\n" -"\n" -" Shortcut: Press the option's highlighted letter (hotkey).\n" -" Pressing a hotkey more than once will sequence\n" -" through all visible items which use that hotkey.\n" -"\n" -" You may also use the and keys to scroll\n" -" unseen options into view.\n" -"\n" -"o To exit a menu use the cursor keys to highlight the button\n" -" and press .\n" -"\n" -" Shortcut: Press or or if there is no hotkey\n" -" using those letters. You may press a single , but\n" -" there is a delayed response which you may find annoying.\n" -"\n" -" Also, the and cursor keys will cycle between and\n" -" \n" -"\n" -"\n" -"Data Entry\n" -"-----------\n" -"o Enter the requested information and press \n" -" If you are entering hexadecimal values, it is not necessary to\n" -" add the '0x' prefix to the entry.\n" -"\n" -"o For help, use the or cursor keys to highlight the help option\n" -" and press . You can try as well.\n" -"\n" -"\n" -"Text Box (Help Window)\n" -"--------\n" -"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" -" keys h,j,k,l function here as do and for those\n" -" who are familiar with less and lynx.\n" -"\n" -"o Press , , or to exit.\n" -"\n" -"\n" -"Alternate Configuration Files\n" -"-----------------------------\n" -"Menuconfig supports the use of alternate configuration files for\n" -"those who, for various reasons, find it necessary to switch\n" -"between different configurations.\n" -"\n" -"At the end of the main menu you will find two options. One is\n" -"for saving the current configuration to a file of your choosing.\n" -"The other option is for loading a previously saved alternate\n" -"configuration.\n" -"\n" -"Even if you don't use alternate configuration files, but you\n" -"find during a Menuconfig session that you have completely messed\n" -"up your settings, you may use the \"Load Alternate...\" option to\n" -"restore your previously saved settings from \".config\" without\n" -"restarting Menuconfig.\n" -"\n" -"Other information\n" -"-----------------\n" -"If you use Menuconfig in an XTERM window make sure you have your\n" -"$TERM variable set to point to a xterm definition which supports color.\n" -"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" -"display correctly in a RXVT window because rxvt displays only one\n" -"intensity of color, bright.\n" -"\n" -"Menuconfig will display larger menus on screens or xterms which are\n" -"set to display more than the standard 25 row by 80 column geometry.\n" -"In order for this to work, the \"stty size\" command must be able to\n" -"display the screen's current row and column geometry. I STRONGLY\n" -"RECOMMEND that you make sure you do NOT have the shell variables\n" -"LINES and COLUMNS exported into your environment. Some distributions\n" -"export those variables via /etc/profile. Some ncurses programs can\n" -"become confused when those variables (LINES & COLUMNS) don't reflect\n" -"the true screen size.\n" -"\n" -"Optional personality available\n" -"------------------------------\n" -"If you prefer to have all of the options listed in a single menu, rather\n" -"than the default multimenu hierarchy, run the menuconfig with\n" -"MENUCONFIG_MODE environment variable set to single_menu. Example:\n" -"\n" -"make MENUCONFIG_MODE=single_menu menuconfig\n" -"\n" -" will then unroll the appropriate category, or enfold it if it\n" -"is already unrolled.\n" -"\n" -"Note that this mode can eventually be a little more CPU expensive\n" -"(especially with a larger number of unrolled categories) than the\n" -"default mode.\n" -"\n" -"Different color themes available\n" -"--------------------------------\n" -"It is possible to select different color themes using the variable\n" -"MENUCONFIG_COLOR. To select a theme use:\n" -"\n" -"make MENUCONFIG_COLOR= menuconfig\n" -"\n" -"Available themes are\n" -" mono => selects colors suitable for monochrome displays\n" -" blackbg => selects a color scheme with black background\n" -" classic => theme with blue background. The classic look\n" -" bluetitle => a LCD friendly version of classic. (default)\n" -"\n"), -menu_instructions[] = N_( - "Arrow keys navigate the menu. " - " selects submenus --->. " - "Highlighted letters are hotkeys. " - "Pressing includes, excludes, modularizes features. " - "Press to exit, for Help, for Search. " - "Legend: [*] built-in [ ] excluded module < > module capable"), -radiolist_instructions[] = N_( - "Use the arrow keys to navigate this window or " - "press the hotkey of the item you wish to select " - "followed by the . " - "Press for additional information about this option."), -inputbox_instructions_int[] = N_( - "Please enter a decimal value. " - "Fractions will not be accepted. " - "Use the key to move from the input field to the buttons below it."), -inputbox_instructions_hex[] = N_( - "Please enter a hexadecimal value. " - "Use the key to move from the input field to the buttons below it."), -inputbox_instructions_string[] = N_( - "Please enter a string value. " - "Use the key to move from the input field to the buttons below it."), -setmod_text[] = N_( - "This feature depends on another which has been configured as a module.\n" - "As a result, this feature will be built as a module."), -load_config_text[] = N_( - "Enter the name of the configuration file you wish to load. " - "Accept the name shown to restore the configuration you " - "last retrieved. Leave blank to abort."), -load_config_help[] = N_( - "\n" - "For various reasons, one may wish to keep several different\n" - "configurations available on a single machine.\n" - "\n" - "If you have saved a previous configuration in a file other than the\n" - "default one, entering its name here will allow you to modify that\n" - "configuration.\n" - "\n" - "If you are uncertain, then you have probably never used alternate\n" - "configuration files. You should therefore leave this blank to abort.\n"), -save_config_text[] = N_( - "Enter a filename to which this configuration should be saved " - "as an alternate. Leave blank to abort."), -save_config_help[] = N_( - "\n" - "For various reasons, one may wish to keep different configurations\n" - "available on a single machine.\n" - "\n" - "Entering a file name here will allow you to later retrieve, modify\n" - "and use the current configuration as an alternate to whatever\n" - "configuration options you have selected at that time.\n" - "\n" - "If you are uncertain what all this means then you should probably\n" - "leave this blank.\n"), -search_help[] = N_( - "\n" - "Search for symbols and display their relations.\n" - "Regular expressions are allowed.\n" - "Example: search for \"^FOO\"\n" - "Result:\n" - "-----------------------------------------------------------------\n" - "Symbol: FOO [=m]\n" - "Prompt: Foo bus is used to drive the bar HW\n" - "Defined at drivers/pci/Kconfig:47\n" - "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" - "Location:\n" - " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" - " -> PCI support (PCI [=y])\n" - " -> PCI access mode ( [=y])\n" - "Selects: LIBCRC32\n" - "Selected by: BAR\n" - "-----------------------------------------------------------------\n" - "o The line 'Prompt:' shows the text used in the menu structure for\n" - " this symbol\n" - "o The 'Defined at' line tell at what file / line number the symbol\n" - " is defined\n" - "o The 'Depends on:' line tell what symbols needs to be defined for\n" - " this symbol to be visible in the menu (selectable)\n" - "o The 'Location:' lines tell where in the menu structure this symbol\n" - " is located\n" - " A location followed by a [=y] indicate that this is a selectable\n" - " menu item - and current value is displayed inside brackets.\n" - "o The 'Selects:' line tell what symbol will be automatically\n" - " selected if this symbol is selected (y or m)\n" - "o The 'Selected by' line tell what symbol has selected this symbol\n" - "\n" - "Only relevant lines are shown.\n" - "\n\n" - "Search examples:\n" - "Examples: USB => find all symbols containing USB\n" - " ^USB => find all symbols starting with USB\n" - " USB$ => find all symbols ending with USB\n" - "\n"); - -static int indent; -static struct menu *current_menu; -static int child_count; -static int single_menu_mode; -static int show_all_options; - -static void conf(struct menu *menu); -static void conf_choice(struct menu *menu); -static void conf_string(struct menu *menu); -static void conf_load(void); -static void conf_save(void); -static void show_textbox(const char *title, const char *text, int r, int c); -static void show_helptext(const char *title, const char *text); -static void show_help(struct menu *menu); - -static char filename[PATH_MAX+1]; -static void set_config_filename(const char *config_filename) -{ - static char menu_backtitle[PATH_MAX+128]; - int size; - - size = snprintf(menu_backtitle, sizeof(menu_backtitle), - "%s - %s", config_filename, rootmenu.prompt->text); - if (size >= sizeof(menu_backtitle)) - menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; - set_dialog_backtitle(menu_backtitle); - - size = snprintf(filename, sizeof(filename), "%s", config_filename); - if (size >= sizeof(filename)) - filename[sizeof(filename)-1] = '\0'; -} - - -static void search_conf(void) -{ - struct symbol **sym_arr; - struct gstr res; - char *dialog_input; - int dres; -again: - dialog_clear(); - dres = dialog_inputbox(_("Search Configuration Parameter"), - _("Enter " CONFIG_ " (sub)string to search for " - "(with or without \"" CONFIG_ "\")"), - 10, 75, ""); - switch (dres) { - case 0: - break; - case 1: - show_helptext(_("Search Configuration"), search_help); - goto again; - default: - return; - } - - /* strip the prefix if necessary */ - dialog_input = dialog_input_result; - if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) - dialog_input += strlen(CONFIG_); - - sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr); - free(sym_arr); - show_textbox(_("Search Results"), str_get(&res), 0, 0); - str_free(&res); -} - -static void build_conf(struct menu *menu) -{ - struct symbol *sym; - struct property *prop; - struct menu *child; - int type, tmp, doint = 2; - tristate val; - char ch; - bool visible; - - /* - * note: menu_is_visible() has side effect that it will - * recalc the value of the symbol. - */ - visible = menu_is_visible(menu); - if (show_all_options && !menu_has_prompt(menu)) - return; - else if (!show_all_options && !visible) - return; - - sym = menu->sym; - prop = menu->prompt; - if (!sym) { - if (prop && menu != current_menu) { - const char *prompt = menu_get_prompt(menu); - switch (prop->type) { - case P_MENU: - child_count++; - prompt = _(prompt); - if (single_menu_mode) { - item_make("%s%*c%s", - menu->data ? "-->" : "++>", - indent + 1, ' ', prompt); - } else - item_make(" %*c%s --->", indent + 1, ' ', prompt); - - item_set_tag('m'); - item_set_data(menu); - if (single_menu_mode && menu->data) - goto conf_childs; - return; - case P_COMMENT: - if (prompt) { - child_count++; - item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); - item_set_tag(':'); - item_set_data(menu); - } - break; - default: - if (prompt) { - child_count++; - item_make("---%*c%s", indent + 1, ' ', _(prompt)); - item_set_tag(':'); - item_set_data(menu); - } - } - } else - doint = 0; - goto conf_childs; - } - - type = sym_get_type(sym); - if (sym_is_choice(sym)) { - struct symbol *def_sym = sym_get_choice_value(sym); - struct menu *def_menu = NULL; - - child_count++; - for (child = menu->list; child; child = child->next) { - if (menu_is_visible(child) && child->sym == def_sym) - def_menu = child; - } - - val = sym_get_tristate_value(sym); - if (sym_is_changable(sym)) { - switch (type) { - case S_BOOLEAN: - item_make("[%c]", val == no ? ' ' : '*'); - break; - case S_TRISTATE: - switch (val) { - case yes: ch = '*'; break; - case mod: ch = 'M'; break; - default: ch = ' '; break; - } - item_make("<%c>", ch); - break; - } - item_set_tag('t'); - item_set_data(menu); - } else { - item_make(" "); - item_set_tag(def_menu ? 't' : ':'); - item_set_data(menu); - } - - item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); - if (val == yes) { - if (def_menu) { - item_add_str(" (%s)", _(menu_get_prompt(def_menu))); - item_add_str(" --->"); - if (def_menu->list) { - indent += 2; - build_conf(def_menu); - indent -= 2; - } - } - return; - } - } else { - if (menu == current_menu) { - item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); - item_set_tag(':'); - item_set_data(menu); - goto conf_childs; - } - child_count++; - val = sym_get_tristate_value(sym); - if (sym_is_choice_value(sym) && val == yes) { - item_make(" "); - item_set_tag(':'); - item_set_data(menu); - } else { - switch (type) { - case S_BOOLEAN: - if (sym_is_changable(sym)) - item_make("[%c]", val == no ? ' ' : '*'); - else - item_make("-%c-", val == no ? ' ' : '*'); - item_set_tag('t'); - item_set_data(menu); - break; - case S_TRISTATE: - switch (val) { - case yes: ch = '*'; break; - case mod: ch = 'M'; break; - default: ch = ' '; break; - } - if (sym_is_changable(sym)) { - if (sym->rev_dep.tri == mod) - item_make("{%c}", ch); - else - item_make("<%c>", ch); - } else - item_make("-%c-", ch); - item_set_tag('t'); - item_set_data(menu); - break; - default: - tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ - item_make("(%s)", sym_get_string_value(sym)); - tmp = indent - tmp + 4; - if (tmp < 0) - tmp = 0; - item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), - (sym_has_value(sym) || !sym_is_changable(sym)) ? - "" : _(" (NEW)")); - item_set_tag('s'); - item_set_data(menu); - goto conf_childs; - } - } - item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), - (sym_has_value(sym) || !sym_is_changable(sym)) ? - "" : _(" (NEW)")); - if (menu->prompt->type == P_MENU) { - item_add_str(" --->"); - return; - } - } - -conf_childs: - indent += doint; - for (child = menu->list; child; child = child->next) - build_conf(child); - indent -= doint; -} - -static void conf(struct menu *menu) -{ - struct menu *submenu; - const char *prompt = menu_get_prompt(menu); - struct symbol *sym; - struct menu *active_menu = NULL; - int res; - int s_scroll = 0; - - while (1) { - item_reset(); - current_menu = menu; - build_conf(menu); - if (!child_count) - break; - if (menu == &rootmenu) { - item_make("--- "); - item_set_tag(':'); - item_make(_(" Load an Alternate Configuration File")); - item_set_tag('L'); - item_make(_(" Save an Alternate Configuration File")); - item_set_tag('S'); - } - dialog_clear(); - res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), - _(menu_instructions), - active_menu, &s_scroll); - if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) - break; - if (!item_activate_selected()) - continue; - if (!item_tag()) - continue; - - submenu = item_data(); - active_menu = item_data(); - if (submenu) - sym = submenu->sym; - else - sym = NULL; - - switch (res) { - case 0: - switch (item_tag()) { - case 'm': - if (single_menu_mode) - submenu->data = (void *) (long) !submenu->data; - else - conf(submenu); - break; - case 't': - if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) - conf_choice(submenu); - else if (submenu->prompt->type == P_MENU) - conf(submenu); - break; - case 's': - conf_string(submenu); - break; - case 'L': - conf_load(); - break; - case 'S': - conf_save(); - break; - } - break; - case 2: - if (sym) - show_help(submenu); - else - show_helptext(_("README"), _(mconf_readme)); - break; - case 3: - if (item_is_tag('t')) { - if (sym_set_tristate_value(sym, yes)) - break; - if (sym_set_tristate_value(sym, mod)) - show_textbox(NULL, setmod_text, 6, 74); - } - break; - case 4: - if (item_is_tag('t')) - sym_set_tristate_value(sym, no); - break; - case 5: - if (item_is_tag('t')) - sym_set_tristate_value(sym, mod); - break; - case 6: - if (item_is_tag('t')) - sym_toggle_tristate_value(sym); - else if (item_is_tag('m')) - conf(submenu); - break; - case 7: - search_conf(); - break; - case 8: - show_all_options = !show_all_options; - break; - } - } -} - -static void show_textbox(const char *title, const char *text, int r, int c) -{ - dialog_clear(); - dialog_textbox(title, text, r, c); -} - -static void show_helptext(const char *title, const char *text) -{ - show_textbox(title, text, 0, 0); -} - -static void show_help(struct menu *menu) -{ - struct gstr help = str_new(); - - help.max_width = getmaxx(stdscr) - 10; - menu_get_ext_help(menu, &help); - - show_helptext(_(menu_get_prompt(menu)), str_get(&help)); - str_free(&help); -} - -static void conf_choice(struct menu *menu) -{ - const char *prompt = _(menu_get_prompt(menu)); - struct menu *child; - struct symbol *active; - - active = sym_get_choice_value(menu->sym); - while (1) { - int res; - int selected; - item_reset(); - - current_menu = menu; - for (child = menu->list; child; child = child->next) { - if (!menu_is_visible(child)) - continue; - if (child->sym) - item_make("%s", _(menu_get_prompt(child))); - else { - item_make("*** %s ***", _(menu_get_prompt(child))); - item_set_tag(':'); - } - item_set_data(child); - if (child->sym == active) - item_set_selected(1); - if (child->sym == sym_get_choice_value(menu->sym)) - item_set_tag('X'); - } - dialog_clear(); - res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), - _(radiolist_instructions), - 15, 70, 6); - selected = item_activate_selected(); - switch (res) { - case 0: - if (selected) { - child = item_data(); - if (!child->sym) - break; - - sym_set_tristate_value(child->sym, yes); - } - return; - case 1: - if (selected) { - child = item_data(); - show_help(child); - active = child->sym; - } else - show_help(menu); - break; - case KEY_ESC: - return; - case -ERRDISPLAYTOOSMALL: - return; - } - } -} - -static void conf_string(struct menu *menu) -{ - const char *prompt = menu_get_prompt(menu); - - while (1) { - int res; - const char *heading; - - switch (sym_get_type(menu->sym)) { - case S_INT: - heading = _(inputbox_instructions_int); - break; - case S_HEX: - heading = _(inputbox_instructions_hex); - break; - case S_STRING: - heading = _(inputbox_instructions_string); - break; - default: - heading = _("Internal mconf error!"); - } - dialog_clear(); - res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), - heading, 10, 75, - sym_get_string_value(menu->sym)); - switch (res) { - case 0: - if (sym_set_string_value(menu->sym, dialog_input_result)) - return; - show_textbox(NULL, _("You have made an invalid entry."), 5, 43); - break; - case 1: - show_help(menu); - break; - case KEY_ESC: - return; - } - } -} - -static void conf_load(void) -{ - - while (1) { - int res; - dialog_clear(); - res = dialog_inputbox(NULL, load_config_text, - 11, 55, filename); - switch(res) { - case 0: - if (!dialog_input_result[0]) - return; - if (!conf_read(dialog_input_result)) { - set_config_filename(dialog_input_result); - sym_set_change_count(1); - return; - } - show_textbox(NULL, _("File does not exist!"), 5, 38); - break; - case 1: - show_helptext(_("Load Alternate Configuration"), load_config_help); - break; - case KEY_ESC: - return; - } - } -} - -static void conf_save(void) -{ - while (1) { - int res; - dialog_clear(); - res = dialog_inputbox(NULL, save_config_text, - 11, 55, filename); - switch(res) { - case 0: - if (!dialog_input_result[0]) - return; - if (!conf_write(dialog_input_result)) { - set_config_filename(dialog_input_result); - return; - } - show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); - break; - case 1: - show_helptext(_("Save Alternate Configuration"), save_config_help); - break; - case KEY_ESC: - return; - } - } -} - -int main(int ac, char **av) -{ - int saved_x, saved_y; - char *mode; - int res; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - conf_parse(av[1]); - conf_read(NULL); - - mode = getenv("MENUCONFIG_MODE"); - if (mode) { - if (!strcasecmp(mode, "single_menu")) - single_menu_mode = 1; - } - - initscr(); - - getyx(stdscr, saved_y, saved_x); - if (init_dialog(NULL)) { - fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); - fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); - return 1; - } - - set_config_filename(conf_get_configname()); - do { - conf(&rootmenu); - dialog_clear(); - if (conf_get_changed()) - res = dialog_yesno(NULL, - _("Do you wish to save your " - "new configuration?\n" - " to continue."), - 6, 60); - else - res = -1; - } while (res == KEY_ESC); - end_dialog(saved_x, saved_y); - - switch (res) { - case 0: - if (conf_write(filename)) { - fprintf(stderr, _("\n\n" - "Error while writing of the configuration.\n" - "Your configuration changes were NOT saved." - "\n\n")); - return 1; - } - case -1: - printf(_("\n\n" - "*** End of the configuration.\n" - "*** Execute 'make' to start the build or try 'make help'." - "\n\n")); - break; - default: - fprintf(stderr, _("\n\n" - "Your configuration changes were NOT saved." - "\n\n")); - } - - return 0; -} - diff -Nru seabios-1.7.1/tools/kconfig/menu.c seabios-1.7.4/tools/kconfig/menu.c --- seabios-1.7.1/tools/kconfig/menu.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/menu.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,609 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -static const char nohelp_text[] = N_( - "There is no help available for this option.\n"); - -struct menu rootmenu; -static struct menu **last_entry_ptr; - -struct file *file_list; -struct file *current_file; - -void menu_warn(struct menu *menu, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); -} - -static void prop_warn(struct property *prop, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); -} - -void _menu_init(void) -{ - current_entry = current_menu = &rootmenu; - last_entry_ptr = &rootmenu.list; -} - -void menu_add_entry(struct symbol *sym) -{ - struct menu *menu; - - menu = malloc(sizeof(*menu)); - memset(menu, 0, sizeof(*menu)); - menu->sym = sym; - menu->parent = current_menu; - menu->file = current_file; - menu->lineno = zconf_lineno(); - - *last_entry_ptr = menu; - last_entry_ptr = &menu->next; - current_entry = menu; - if (sym) - menu_add_symbol(P_SYMBOL, sym, NULL); -} - -void menu_end_entry(void) -{ -} - -struct menu *menu_add_menu(void) -{ - menu_end_entry(); - last_entry_ptr = ¤t_entry->list; - return current_menu = current_entry; -} - -void menu_end_menu(void) -{ - last_entry_ptr = ¤t_menu->next; - current_menu = current_menu->parent; -} - -static struct expr *menu_check_dep(struct expr *e) -{ - if (!e) - return e; - - switch (e->type) { - case E_NOT: - e->left.expr = menu_check_dep(e->left.expr); - break; - case E_OR: - case E_AND: - e->left.expr = menu_check_dep(e->left.expr); - e->right.expr = menu_check_dep(e->right.expr); - break; - case E_SYMBOL: - /* change 'm' into 'm' && MODULES */ - if (e->left.sym == &symbol_mod) - return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); - break; - default: - break; - } - return e; -} - -void menu_add_dep(struct expr *dep) -{ - current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); -} - -void menu_set_type(int type) -{ - struct symbol *sym = current_entry->sym; - - if (sym->type == type) - return; - if (sym->type == S_UNKNOWN) { - sym->type = type; - return; - } - menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", - sym->name ? sym->name : "", - sym_type_name(sym->type), sym_type_name(type)); -} - -struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) -{ - struct property *prop = prop_alloc(type, current_entry->sym); - - prop->menu = current_entry; - prop->expr = expr; - prop->visible.expr = menu_check_dep(dep); - - if (prompt) { - if (isspace(*prompt)) { - prop_warn(prop, "leading whitespace ignored"); - while (isspace(*prompt)) - prompt++; - } - if (current_entry->prompt && current_entry != &rootmenu) - prop_warn(prop, "prompt redefined"); - - /* Apply all upper menus' visibilities to actual prompts. */ - if(type == P_PROMPT) { - struct menu *menu = current_entry; - - while ((menu = menu->parent) != NULL) { - if (!menu->visibility) - continue; - prop->visible.expr - = expr_alloc_and(prop->visible.expr, - menu->visibility); - } - } - - current_entry->prompt = prop; - } - prop->text = prompt; - - return prop; -} - -struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) -{ - return menu_add_prop(type, prompt, NULL, dep); -} - -void menu_add_visibility(struct expr *expr) -{ - current_entry->visibility = expr_alloc_and(current_entry->visibility, - expr); -} - -void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) -{ - menu_add_prop(type, NULL, expr, dep); -} - -void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) -{ - menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); -} - -void menu_add_option(int token, char *arg) -{ - struct property *prop; - - switch (token) { - case T_OPT_MODULES: - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(current_entry->sym); - break; - case T_OPT_DEFCONFIG_LIST: - if (!sym_defconfig_list) - sym_defconfig_list = current_entry->sym; - else if (sym_defconfig_list != current_entry->sym) - zconf_error("trying to redefine defconfig symbol"); - break; - case T_OPT_ENV: - prop_add_env(arg); - break; - } -} - -static int menu_validate_number(struct symbol *sym, struct symbol *sym2) -{ - return sym2->type == S_INT || sym2->type == S_HEX || - (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); -} - -static void sym_check_prop(struct symbol *sym) -{ - struct property *prop; - struct symbol *sym2; - for (prop = sym->prop; prop; prop = prop->next) { - switch (prop->type) { - case P_DEFAULT: - if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && - prop->expr->type != E_SYMBOL) - prop_warn(prop, - "default for config symbol '%s'" - " must be a single symbol", sym->name); - if (prop->expr->type != E_SYMBOL) - break; - sym2 = prop_get_symbol(prop); - if (sym->type == S_HEX || sym->type == S_INT) { - if (!menu_validate_number(sym, sym2)) - prop_warn(prop, - "'%s': number is invalid", - sym->name); - } - break; - case P_SELECT: - sym2 = prop_get_symbol(prop); - if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) - prop_warn(prop, - "config symbol '%s' uses select, but is " - "not boolean or tristate", sym->name); - else if (sym2->type != S_UNKNOWN && - sym2->type != S_BOOLEAN && - sym2->type != S_TRISTATE) - prop_warn(prop, - "'%s' has wrong type. 'select' only " - "accept arguments of boolean and " - "tristate type", sym2->name); - break; - case P_RANGE: - if (sym->type != S_INT && sym->type != S_HEX) - prop_warn(prop, "range is only allowed " - "for int or hex symbols"); - if (!menu_validate_number(sym, prop->expr->left.sym) || - !menu_validate_number(sym, prop->expr->right.sym)) - prop_warn(prop, "range is invalid"); - break; - default: - ; - } - } -} - -void menu_finalize(struct menu *parent) -{ - struct menu *menu, *last_menu; - struct symbol *sym; - struct property *prop; - struct expr *parentdep, *basedep, *dep, *dep2, **ep; - - sym = parent->sym; - if (parent->list) { - if (sym && sym_is_choice(sym)) { - if (sym->type == S_UNKNOWN) { - /* find the first choice value to find out choice type */ - current_entry = parent; - for (menu = parent->list; menu; menu = menu->next) { - if (menu->sym && menu->sym->type != S_UNKNOWN) { - menu_set_type(menu->sym->type); - break; - } - } - } - /* set the type of the remaining choice values */ - for (menu = parent->list; menu; menu = menu->next) { - current_entry = menu; - if (menu->sym && menu->sym->type == S_UNKNOWN) - menu_set_type(sym->type); - } - parentdep = expr_alloc_symbol(sym); - } else if (parent->prompt) - parentdep = parent->prompt->visible.expr; - else - parentdep = parent->dep; - - for (menu = parent->list; menu; menu = menu->next) { - basedep = expr_transform(menu->dep); - basedep = expr_alloc_and(expr_copy(parentdep), basedep); - basedep = expr_eliminate_dups(basedep); - menu->dep = basedep; - if (menu->sym) - prop = menu->sym->prop; - else - prop = menu->prompt; - for (; prop; prop = prop->next) { - if (prop->menu != menu) - continue; - dep = expr_transform(prop->visible.expr); - dep = expr_alloc_and(expr_copy(basedep), dep); - dep = expr_eliminate_dups(dep); - if (menu->sym && menu->sym->type != S_TRISTATE) - dep = expr_trans_bool(dep); - prop->visible.expr = dep; - if (prop->type == P_SELECT) { - struct symbol *es = prop_get_symbol(prop); - es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, - expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); - } - } - } - for (menu = parent->list; menu; menu = menu->next) - menu_finalize(menu); - } else if (sym) { - basedep = parent->prompt ? parent->prompt->visible.expr : NULL; - basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); - basedep = expr_eliminate_dups(expr_transform(basedep)); - last_menu = NULL; - for (menu = parent->next; menu; menu = menu->next) { - dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; - if (!expr_contains_symbol(dep, sym)) - break; - if (expr_depends_symbol(dep, sym)) - goto next; - dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); - dep = expr_eliminate_dups(expr_transform(dep)); - dep2 = expr_copy(basedep); - expr_eliminate_eq(&dep, &dep2); - expr_free(dep); - if (!expr_is_yes(dep2)) { - expr_free(dep2); - break; - } - expr_free(dep2); - next: - menu_finalize(menu); - menu->parent = parent; - last_menu = menu; - } - if (last_menu) { - parent->list = parent->next; - parent->next = last_menu->next; - last_menu->next = NULL; - } - - sym->dir_dep.expr = parent->dep; - } - for (menu = parent->list; menu; menu = menu->next) { - if (sym && sym_is_choice(sym) && - menu->sym && !sym_is_choice_value(menu->sym)) { - current_entry = menu; - menu->sym->flags |= SYMBOL_CHOICEVAL; - if (!menu->prompt) - menu_warn(menu, "choice value must have a prompt"); - for (prop = menu->sym->prop; prop; prop = prop->next) { - if (prop->type == P_DEFAULT) - prop_warn(prop, "defaults for choice " - "values not supported"); - if (prop->menu == menu) - continue; - if (prop->type == P_PROMPT && - prop->menu->parent->sym != sym) - prop_warn(prop, "choice value used outside its choice group"); - } - /* Non-tristate choice values of tristate choices must - * depend on the choice being set to Y. The choice - * values' dependencies were propagated to their - * properties above, so the change here must be re- - * propagated. - */ - if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { - basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); - menu->dep = expr_alloc_and(basedep, menu->dep); - for (prop = menu->sym->prop; prop; prop = prop->next) { - if (prop->menu != menu) - continue; - prop->visible.expr = expr_alloc_and(expr_copy(basedep), - prop->visible.expr); - } - } - menu_add_symbol(P_CHOICE, sym, NULL); - prop = sym_get_choice_prop(sym); - for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) - ; - *ep = expr_alloc_one(E_LIST, NULL); - (*ep)->right.sym = menu->sym; - } - if (menu->list && (!menu->prompt || !menu->prompt->text)) { - for (last_menu = menu->list; ; last_menu = last_menu->next) { - last_menu->parent = parent; - if (!last_menu->next) - break; - } - last_menu->next = menu->next; - menu->next = menu->list; - menu->list = NULL; - } - } - - if (sym && !(sym->flags & SYMBOL_WARNED)) { - if (sym->type == S_UNKNOWN) - menu_warn(parent, "config symbol defined without type"); - - if (sym_is_choice(sym) && !parent->prompt) - menu_warn(parent, "choice must have a prompt"); - - /* Check properties connected to this symbol */ - sym_check_prop(sym); - sym->flags |= SYMBOL_WARNED; - } - - if (sym && !sym_is_optional(sym) && parent->prompt) { - sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, - expr_alloc_and(parent->prompt->visible.expr, - expr_alloc_symbol(&symbol_mod))); - } -} - -bool menu_has_prompt(struct menu *menu) -{ - if (!menu->prompt) - return false; - return true; -} - -bool menu_is_visible(struct menu *menu) -{ - struct menu *child; - struct symbol *sym; - tristate visible; - - if (!menu->prompt) - return false; - - if (menu->visibility) { - if (expr_calc_value(menu->visibility) == no) - return no; - } - - sym = menu->sym; - if (sym) { - sym_calc_value(sym); - visible = menu->prompt->visible.tri; - } else - visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); - - if (visible != no) - return true; - - if (!sym || sym_get_tristate_value(menu->sym) == no) - return false; - - for (child = menu->list; child; child = child->next) { - if (menu_is_visible(child)) { - if (sym) - sym->flags |= SYMBOL_DEF_USER; - return true; - } - } - - return false; -} - -const char *menu_get_prompt(struct menu *menu) -{ - if (menu->prompt) - return menu->prompt->text; - else if (menu->sym) - return menu->sym->name; - return NULL; -} - -struct menu *menu_get_root_menu(struct menu *menu) -{ - return &rootmenu; -} - -struct menu *menu_get_parent_menu(struct menu *menu) -{ - enum prop_type type; - - for (; menu != &rootmenu; menu = menu->parent) { - type = menu->prompt ? menu->prompt->type : 0; - if (type == P_MENU) - break; - } - return menu; -} - -bool menu_has_help(struct menu *menu) -{ - return menu->help != NULL; -} - -const char *menu_get_help(struct menu *menu) -{ - if (menu->help) - return menu->help; - else - return ""; -} - -static void get_prompt_str(struct gstr *r, struct property *prop) -{ - int i, j; - struct menu *submenu[8], *menu; - - str_printf(r, _("Prompt: %s\n"), _(prop->text)); - str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, - prop->menu->lineno); - if (!expr_is_yes(prop->visible.expr)) { - str_append(r, _(" Depends on: ")); - expr_gstr_print(prop->visible.expr, r); - str_append(r, "\n"); - } - menu = prop->menu->parent; - for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) - submenu[i++] = menu; - if (i > 0) { - str_printf(r, _(" Location:\n")); - for (j = 4; --i >= 0; j += 2) { - menu = submenu[i]; - str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); - if (menu->sym) { - str_printf(r, " (%s [=%s])", menu->sym->name ? - menu->sym->name : _(""), - sym_get_string_value(menu->sym)); - } - str_append(r, "\n"); - } - } -} - -void get_symbol_str(struct gstr *r, struct symbol *sym) -{ - bool hit; - struct property *prop; - - if (sym && sym->name) { - str_printf(r, "Symbol: %s [=%s]\n", sym->name, - sym_get_string_value(sym)); - str_printf(r, "Type : %s\n", sym_type_name(sym->type)); - if (sym->type == S_INT || sym->type == S_HEX) { - prop = sym_get_range_prop(sym); - if (prop) { - str_printf(r, "Range : "); - expr_gstr_print(prop->expr, r); - str_append(r, "\n"); - } - } - } - for_all_prompts(sym, prop) - get_prompt_str(r, prop); - hit = false; - for_all_properties(sym, prop, P_SELECT) { - if (!hit) { - str_append(r, " Selects: "); - hit = true; - } else - str_printf(r, " && "); - expr_gstr_print(prop->expr, r); - } - if (hit) - str_append(r, "\n"); - if (sym->rev_dep.expr) { - str_append(r, _(" Selected by: ")); - expr_gstr_print(sym->rev_dep.expr, r); - str_append(r, "\n"); - } - str_append(r, "\n\n"); -} - -struct gstr get_relations_str(struct symbol **sym_arr) -{ - struct symbol *sym; - struct gstr res = str_new(); - int i; - - for (i = 0; sym_arr && (sym = sym_arr[i]); i++) - get_symbol_str(&res, sym); - if (!i) - str_append(&res, _("No matches found.\n")); - return res; -} - - -void menu_get_ext_help(struct menu *menu, struct gstr *help) -{ - struct symbol *sym = menu->sym; - - if (menu_has_help(menu)) { - if (sym->name) { - str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); - str_append(help, _(menu_get_help(menu))); - str_append(help, "\n"); - } - } else { - str_append(help, nohelp_text); - } - if (sym) - get_symbol_str(help, sym); -} diff -Nru seabios-1.7.1/tools/kconfig/nconf.c seabios-1.7.4/tools/kconfig/nconf.c --- seabios-1.7.1/tools/kconfig/nconf.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/nconf.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1561 +0,0 @@ -/* - * Copyright (C) 2008 Nir Tzachar -#define LKC_DIRECT_LINK -#include "lkc.h" -#include "nconf.h" -#include - -static const char nconf_readme[] = N_( -"Overview\n" -"--------\n" -"This interface let you select features and parameters for the build.\n" -"Features can either be built-in, modularized, or ignored. Parameters\n" -"must be entered in as decimal or hexadecimal numbers or text.\n" -"\n" -"Menu items beginning with following braces represent features that\n" -" [ ] can be built in or removed\n" -" < > can be built in, modularized or removed\n" -" { } can be built in or modularized (selected by other feature)\n" -" - - are selected by other feature,\n" -" XXX cannot be selected. Use Symbol Info to find out why,\n" -"while *, M or whitespace inside braces means to build in, build as\n" -"a module or to exclude the feature respectively.\n" -"\n" -"To change any of these features, highlight it with the cursor\n" -"keys and press to build it in, to make it a module or\n" -" to removed it. You may also press the to cycle\n" -"through the available options (ie. Y->N->M->Y).\n" -"\n" -"Some additional keyboard hints:\n" -"\n" -"Menus\n" -"----------\n" -"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" -" you wish to change use or . Goto submenu by \n" -" pressing of . Use or to go back.\n" -" Submenus are designated by \"--->\".\n" -"\n" -" Searching: pressing '/' triggers interactive search mode.\n" -" nconfig performs a case insensitive search for the string\n" -" in the menu prompts (no regex support).\n" -" Pressing the up/down keys highlights the previous/next\n" -" matching item. Backspace removes one character from the\n" -" match string. Pressing either '/' again or ESC exits\n" -" search mode. All other keys behave normally.\n" -"\n" -" You may also use the and keys to scroll\n" -" unseen options into view.\n" -"\n" -"o To exit a menu use the just press or .\n" -"\n" -"o To get help with an item, press \n" -" Shortcut: Press or .\n" -"\n" -"\n" -"Radiolists (Choice lists)\n" -"-----------\n" -"o Use the cursor keys to select the option you wish to set and press\n" -" or the .\n" -"\n" -" Shortcut: Press the first letter of the option you wish to set then\n" -" press or .\n" -"\n" -"o To see available help for the item, press \n" -" Shortcut: Press or .\n" -"\n" -"\n" -"Data Entry\n" -"-----------\n" -"o Enter the requested information and press \n" -" If you are entering hexadecimal values, it is not necessary to\n" -" add the '0x' prefix to the entry.\n" -"\n" -"o For help, press .\n" -"\n" -"\n" -"Text Box (Help Window)\n" -"--------\n" -"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" -" keys h,j,k,l function here as do for those\n" -" who are familiar with less and lynx.\n" -"\n" -"o Press , , , or to exit.\n" -"\n" -"\n" -"Alternate Configuration Files\n" -"-----------------------------\n" -"nconfig supports the use of alternate configuration files for\n" -"those who, for various reasons, find it necessary to switch\n" -"between different configurations.\n" -"\n" -"At the end of the main menu you will find two options. One is\n" -"for saving the current configuration to a file of your choosing.\n" -"The other option is for loading a previously saved alternate\n" -"configuration.\n" -"\n" -"Even if you don't use alternate configuration files, but you\n" -"find during a nconfig session that you have completely messed\n" -"up your settings, you may use the \"Load Alternate...\" option to\n" -"restore your previously saved settings from \".config\" without\n" -"restarting nconfig.\n" -"\n" -"Other information\n" -"-----------------\n" -"If you use nconfig in an XTERM window make sure you have your\n" -"$TERM variable set to point to a xterm definition which supports color.\n" -"Otherwise, nconfig will look rather bad. nconfig will not\n" -"display correctly in a RXVT window because rxvt displays only one\n" -"intensity of color, bright.\n" -"\n" -"nconfig will display larger menus on screens or xterms which are\n" -"set to display more than the standard 25 row by 80 column geometry.\n" -"In order for this to work, the \"stty size\" command must be able to\n" -"display the screen's current row and column geometry. I STRONGLY\n" -"RECOMMEND that you make sure you do NOT have the shell variables\n" -"LINES and COLUMNS exported into your environment. Some distributions\n" -"export those variables via /etc/profile. Some ncurses programs can\n" -"become confused when those variables (LINES & COLUMNS) don't reflect\n" -"the true screen size.\n" -"\n" -"Optional personality available\n" -"------------------------------\n" -"If you prefer to have all of the options listed in a single menu, rather\n" -"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n" -"environment variable set to single_menu. Example:\n" -"\n" -"make NCONFIG_MODE=single_menu nconfig\n" -"\n" -" will then unroll the appropriate category, or enfold it if it\n" -"is already unrolled.\n" -"\n" -"Note that this mode can eventually be a little more CPU expensive\n" -"(especially with a larger number of unrolled categories) than the\n" -"default mode.\n" -"\n"), -menu_no_f_instructions[] = N_( -" You do not have function keys support. Please follow the\n" -" following instructions:\n" -" Arrow keys navigate the menu.\n" -" or selects submenus --->.\n" -" Capital Letters are hotkeys.\n" -" Pressing includes, excludes, modularizes features.\n" -" Pressing SpaceBar toggles between the above options.\n" -" Press or to go back one menu,\n" -" or for Help, for Search.\n" -" <1> is interchangeable with , <2> with , etc.\n" -" Legend: [*] built-in [ ] excluded module < > module capable.\n" -" always leaves the current window.\n"), -menu_instructions[] = N_( -" Arrow keys navigate the menu.\n" -" or selects submenus --->.\n" -" Capital Letters are hotkeys.\n" -" Pressing includes, excludes, modularizes features.\n" -" Pressing SpaceBar toggles between the above options\n" -" Press , or to go back one menu,\n" -" , or for Help, for Search.\n" -" <1> is interchangeable with , <2> with , etc.\n" -" Legend: [*] built-in [ ] excluded module < > module capable.\n" -" always leaves the current window\n"), -radiolist_instructions[] = N_( -" Use the arrow keys to navigate this window or\n" -" press the hotkey of the item you wish to select\n" -" followed by the .\n" -" Press , or for additional information about this option.\n"), -inputbox_instructions_int[] = N_( -"Please enter a decimal value.\n" -"Fractions will not be accepted.\n" -"Press to accept, to cancel."), -inputbox_instructions_hex[] = N_( -"Please enter a hexadecimal value.\n" -"Press to accept, to cancel."), -inputbox_instructions_string[] = N_( -"Please enter a string value.\n" -"Press to accept, to cancel."), -setmod_text[] = N_( -"This feature depends on another which\n" -"has been configured as a module.\n" -"As a result, this feature will be built as a module."), -nohelp_text[] = N_( -"There is no help available for this option.\n"), -load_config_text[] = N_( -"Enter the name of the configuration file you wish to load.\n" -"Accept the name shown to restore the configuration you\n" -"last retrieved. Leave blank to abort."), -load_config_help[] = N_( -"\n" -"For various reasons, one may wish to keep several different\n" -"configurations available on a single machine.\n" -"\n" -"If you have saved a previous configuration in a file other than the\n" -"default one, entering its name here will allow you to modify that\n" -"configuration.\n" -"\n" -"If you are uncertain, then you have probably never used alternate\n" -"configuration files. You should therefor leave this blank to abort.\n"), -save_config_text[] = N_( -"Enter a filename to which this configuration should be saved\n" -"as an alternate. Leave blank to abort."), -save_config_help[] = N_( -"\n" -"For various reasons, one may wish to keep different configurations\n" -"available on a single machine.\n" -"\n" -"Entering a file name here will allow you to later retrieve, modify\n" -"and use the current configuration as an alternate to whatever\n" -"configuration options you have selected at that time.\n" -"\n" -"If you are uncertain what all this means then you should probably\n" -"leave this blank.\n"), -search_help[] = N_( -"\n" -"Search for symbols and display their relations. Regular expressions\n" -"are allowed.\n" -"Example: search for \"^FOO\"\n" -"Result:\n" -"-----------------------------------------------------------------\n" -"Symbol: FOO [ = m]\n" -"Prompt: Foo bus is used to drive the bar HW\n" -"Defined at drivers/pci/Kconfig:47\n" -"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" -"Location:\n" -" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" -" -> PCI support (PCI [ = y])\n" -" -> PCI access mode ( [ = y])\n" -"Selects: LIBCRC32\n" -"Selected by: BAR\n" -"-----------------------------------------------------------------\n" -"o The line 'Prompt:' shows the text used in the menu structure for\n" -" this symbol\n" -"o The 'Defined at' line tell at what file / line number the symbol\n" -" is defined\n" -"o The 'Depends on:' line tell what symbols needs to be defined for\n" -" this symbol to be visible in the menu (selectable)\n" -"o The 'Location:' lines tell where in the menu structure this symbol\n" -" is located\n" -" A location followed by a [ = y] indicate that this is a selectable\n" -" menu item - and current value is displayed inside brackets.\n" -"o The 'Selects:' line tell what symbol will be automatically\n" -" selected if this symbol is selected (y or m)\n" -"o The 'Selected by' line tell what symbol has selected this symbol\n" -"\n" -"Only relevant lines are shown.\n" -"\n\n" -"Search examples:\n" -"Examples: USB => find all symbols containing USB\n" -" ^USB => find all symbols starting with USB\n" -" USB$ => find all symbols ending with USB\n" -"\n"); - -struct mitem { - char str[256]; - char tag; - void *usrptr; - int is_visible; -}; - -#define MAX_MENU_ITEMS 4096 -static int show_all_items; -static int indent; -static struct menu *current_menu; -static int child_count; -static int single_menu_mode; -/* the window in which all information appears */ -static WINDOW *main_window; -/* the largest size of the menu window */ -static int mwin_max_lines; -static int mwin_max_cols; -/* the window in which we show option buttons */ -static MENU *curses_menu; -static ITEM *curses_menu_items[MAX_MENU_ITEMS]; -static struct mitem k_menu_items[MAX_MENU_ITEMS]; -static int items_num; -static int global_exit; -/* the currently selected button */ -const char *current_instructions = menu_instructions; - -static void conf(struct menu *menu); -static void conf_choice(struct menu *menu); -static void conf_string(struct menu *menu); -static void conf_load(void); -static void conf_save(void); -static void show_help(struct menu *menu); -static int do_exit(void); -static void setup_windows(void); -static void search_conf(void); - -typedef void (*function_key_handler_t)(int *key, struct menu *menu); -static void handle_f1(int *key, struct menu *current_item); -static void handle_f2(int *key, struct menu *current_item); -static void handle_f3(int *key, struct menu *current_item); -static void handle_f4(int *key, struct menu *current_item); -static void handle_f5(int *key, struct menu *current_item); -static void handle_f6(int *key, struct menu *current_item); -static void handle_f7(int *key, struct menu *current_item); -static void handle_f8(int *key, struct menu *current_item); -static void handle_f9(int *key, struct menu *current_item); - -struct function_keys { - const char *key_str; - const char *func; - function_key key; - function_key_handler_t handler; -}; - -static const int function_keys_num = 9; -struct function_keys function_keys[] = { - { - .key_str = "F1", - .func = "Help", - .key = F_HELP, - .handler = handle_f1, - }, - { - .key_str = "F2", - .func = "Sym Info", - .key = F_SYMBOL, - .handler = handle_f2, - }, - { - .key_str = "F3", - .func = "Insts", - .key = F_INSTS, - .handler = handle_f3, - }, - { - .key_str = "F4", - .func = "Config", - .key = F_CONF, - .handler = handle_f4, - }, - { - .key_str = "F5", - .func = "Back", - .key = F_BACK, - .handler = handle_f5, - }, - { - .key_str = "F6", - .func = "Save", - .key = F_SAVE, - .handler = handle_f6, - }, - { - .key_str = "F7", - .func = "Load", - .key = F_LOAD, - .handler = handle_f7, - }, - { - .key_str = "F8", - .func = "Sym Search", - .key = F_SEARCH, - .handler = handle_f8, - }, - { - .key_str = "F9", - .func = "Exit", - .key = F_EXIT, - .handler = handle_f9, - }, -}; - -static void print_function_line(void) -{ - int i; - int offset = 1; - const int skip = 1; - - for (i = 0; i < function_keys_num; i++) { - wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); - mvwprintw(main_window, LINES-3, offset, - "%s", - function_keys[i].key_str); - wattrset(main_window, attributes[FUNCTION_TEXT]); - offset += strlen(function_keys[i].key_str); - mvwprintw(main_window, LINES-3, - offset, "%s", - function_keys[i].func); - offset += strlen(function_keys[i].func) + skip; - } - wattrset(main_window, attributes[NORMAL]); -} - -/* help */ -static void handle_f1(int *key, struct menu *current_item) -{ - show_scroll_win(main_window, - _("README"), _(nconf_readme)); - return; -} - -/* symbole help */ -static void handle_f2(int *key, struct menu *current_item) -{ - show_help(current_item); - return; -} - -/* instructions */ -static void handle_f3(int *key, struct menu *current_item) -{ - show_scroll_win(main_window, - _("Instructions"), - _(current_instructions)); - return; -} - -/* config */ -static void handle_f4(int *key, struct menu *current_item) -{ - int res = btn_dialog(main_window, - _("Show all symbols?"), - 2, - " ", - ""); - if (res == 0) - show_all_items = 1; - else if (res == 1) - show_all_items = 0; - - return; -} - -/* back */ -static void handle_f5(int *key, struct menu *current_item) -{ - *key = KEY_LEFT; - return; -} - -/* save */ -static void handle_f6(int *key, struct menu *current_item) -{ - conf_save(); - return; -} - -/* load */ -static void handle_f7(int *key, struct menu *current_item) -{ - conf_load(); - return; -} - -/* search */ -static void handle_f8(int *key, struct menu *current_item) -{ - search_conf(); - return; -} - -/* exit */ -static void handle_f9(int *key, struct menu *current_item) -{ - do_exit(); - return; -} - -/* return != 0 to indicate the key was handles */ -static int process_special_keys(int *key, struct menu *menu) -{ - int i; - - if (*key == KEY_RESIZE) { - setup_windows(); - return 1; - } - - for (i = 0; i < function_keys_num; i++) { - if (*key == KEY_F(function_keys[i].key) || - *key == '0' + function_keys[i].key){ - function_keys[i].handler(key, menu); - return 1; - } - } - - return 0; -} - -static void clean_items(void) -{ - int i; - for (i = 0; curses_menu_items[i]; i++) - free_item(curses_menu_items[i]); - bzero(curses_menu_items, sizeof(curses_menu_items)); - bzero(k_menu_items, sizeof(k_menu_items)); - items_num = 0; -} - -typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN, - FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f; - -/* return the index of the matched item, or -1 if no such item exists */ -static int get_mext_match(const char *match_str, match_f flag) -{ - int match_start = item_index(current_item(curses_menu)); - int index; - - if (flag == FIND_NEXT_MATCH_DOWN) - ++match_start; - else if (flag == FIND_NEXT_MATCH_UP) - --match_start; - - index = match_start; - index = (index + items_num) % items_num; - while (true) { - char *str = k_menu_items[index].str; - if (strcasestr(str, match_str) != 0) - return index; - if (flag == FIND_NEXT_MATCH_UP || - flag == MATCH_TINKER_PATTERN_UP) - --index; - else - ++index; - index = (index + items_num) % items_num; - if (index == match_start) - return -1; - } -} - -/* Make a new item. */ -static void item_make(struct menu *menu, char tag, const char *fmt, ...) -{ - va_list ap; - - if (items_num > MAX_MENU_ITEMS-1) - return; - - bzero(&k_menu_items[items_num], sizeof(k_menu_items[0])); - k_menu_items[items_num].tag = tag; - k_menu_items[items_num].usrptr = menu; - if (menu != NULL) - k_menu_items[items_num].is_visible = - menu_is_visible(menu); - else - k_menu_items[items_num].is_visible = 1; - - va_start(ap, fmt); - vsnprintf(k_menu_items[items_num].str, - sizeof(k_menu_items[items_num].str), - fmt, ap); - va_end(ap); - - if (!k_menu_items[items_num].is_visible) - memcpy(k_menu_items[items_num].str, "XXX", 3); - - curses_menu_items[items_num] = new_item( - k_menu_items[items_num].str, - k_menu_items[items_num].str); - set_item_userptr(curses_menu_items[items_num], - &k_menu_items[items_num]); - /* - if (!k_menu_items[items_num].is_visible) - item_opts_off(curses_menu_items[items_num], O_SELECTABLE); - */ - - items_num++; - curses_menu_items[items_num] = NULL; -} - -/* very hackish. adds a string to the last item added */ -static void item_add_str(const char *fmt, ...) -{ - va_list ap; - int index = items_num-1; - char new_str[256]; - char tmp_str[256]; - - if (index < 0) - return; - - va_start(ap, fmt); - vsnprintf(new_str, sizeof(new_str), fmt, ap); - va_end(ap); - snprintf(tmp_str, sizeof(tmp_str), "%s%s", - k_menu_items[index].str, new_str); - strncpy(k_menu_items[index].str, - tmp_str, - sizeof(k_menu_items[index].str)); - - free_item(curses_menu_items[index]); - curses_menu_items[index] = new_item( - k_menu_items[index].str, - k_menu_items[index].str); - set_item_userptr(curses_menu_items[index], - &k_menu_items[index]); -} - -/* get the tag of the currently selected item */ -static char item_tag(void) -{ - ITEM *cur; - struct mitem *mcur; - - cur = current_item(curses_menu); - if (cur == NULL) - return 0; - mcur = (struct mitem *) item_userptr(cur); - return mcur->tag; -} - -static int curses_item_index(void) -{ - return item_index(current_item(curses_menu)); -} - -static void *item_data(void) -{ - ITEM *cur; - struct mitem *mcur; - - cur = current_item(curses_menu); - if (!cur) - return NULL; - mcur = (struct mitem *) item_userptr(cur); - return mcur->usrptr; - -} - -static int item_is_tag(char tag) -{ - return item_tag() == tag; -} - -static char filename[PATH_MAX+1]; -static char menu_backtitle[PATH_MAX+128]; -static const char *set_config_filename(const char *config_filename) -{ - int size; - - size = snprintf(menu_backtitle, sizeof(menu_backtitle), - "%s - %s", config_filename, rootmenu.prompt->text); - if (size >= sizeof(menu_backtitle)) - menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; - - size = snprintf(filename, sizeof(filename), "%s", config_filename); - if (size >= sizeof(filename)) - filename[sizeof(filename)-1] = '\0'; - return menu_backtitle; -} - -/* return = 0 means we are successful. - * -1 means go on doing what you were doing - */ -static int do_exit(void) -{ - int res; - if (!conf_get_changed()) { - global_exit = 1; - return 0; - } - res = btn_dialog(main_window, - _("Do you wish to save your new configuration?\n" - " to cancel and resume nconfig."), - 2, - " ", - ""); - if (res == KEY_EXIT) { - global_exit = 0; - return -1; - } - - /* if we got here, the user really wants to exit */ - switch (res) { - case 0: - res = conf_write(filename); - if (res) - btn_dialog( - main_window, - _("Error during writing of configuration.\n" - "Your configuration changes were NOT saved."), - 1, - ""); - break; - default: - btn_dialog( - main_window, - _("Your configuration changes were NOT saved."), - 1, - ""); - break; - } - global_exit = 1; - return 0; -} - - -static void search_conf(void) -{ - struct symbol **sym_arr; - struct gstr res; - char dialog_input_result[100]; - char *dialog_input; - int dres; -again: - dres = dialog_inputbox(main_window, - _("Search Configuration Parameter"), - _("Enter " CONFIG_ " (sub)string to search for " - "(with or without \"" CONFIG_ "\")"), - "", dialog_input_result, 99); - switch (dres) { - case 0: - break; - case 1: - show_scroll_win(main_window, - _("Search Configuration"), search_help); - goto again; - default: - return; - } - - /* strip the prefix if necessary */ - dialog_input = dialog_input_result; - if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) - dialog_input += strlen(CONFIG_); - - sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr); - free(sym_arr); - show_scroll_win(main_window, - _("Search Results"), str_get(&res)); - str_free(&res); -} - - -static void build_conf(struct menu *menu) -{ - struct symbol *sym; - struct property *prop; - struct menu *child; - int type, tmp, doint = 2; - tristate val; - char ch; - - if (!menu || (!show_all_items && !menu_is_visible(menu))) - return; - - sym = menu->sym; - prop = menu->prompt; - if (!sym) { - if (prop && menu != current_menu) { - const char *prompt = menu_get_prompt(menu); - enum prop_type ptype; - ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; - switch (ptype) { - case P_MENU: - child_count++; - prompt = _(prompt); - if (single_menu_mode) { - item_make(menu, 'm', - "%s%*c%s", - menu->data ? "-->" : "++>", - indent + 1, ' ', prompt); - } else - item_make(menu, 'm', - " %*c%s --->", - indent + 1, - ' ', prompt); - - if (single_menu_mode && menu->data) - goto conf_childs; - return; - case P_COMMENT: - if (prompt) { - child_count++; - item_make(menu, ':', - " %*c*** %s ***", - indent + 1, ' ', - _(prompt)); - } - break; - default: - if (prompt) { - child_count++; - item_make(menu, ':', "---%*c%s", - indent + 1, ' ', - _(prompt)); - } - } - } else - doint = 0; - goto conf_childs; - } - - type = sym_get_type(sym); - if (sym_is_choice(sym)) { - struct symbol *def_sym = sym_get_choice_value(sym); - struct menu *def_menu = NULL; - - child_count++; - for (child = menu->list; child; child = child->next) { - if (menu_is_visible(child) && child->sym == def_sym) - def_menu = child; - } - - val = sym_get_tristate_value(sym); - if (sym_is_changable(sym)) { - switch (type) { - case S_BOOLEAN: - item_make(menu, 't', "[%c]", - val == no ? ' ' : '*'); - break; - case S_TRISTATE: - switch (val) { - case yes: - ch = '*'; - break; - case mod: - ch = 'M'; - break; - default: - ch = ' '; - break; - } - item_make(menu, 't', "<%c>", ch); - break; - } - } else { - item_make(menu, def_menu ? 't' : ':', " "); - } - - item_add_str("%*c%s", indent + 1, - ' ', _(menu_get_prompt(menu))); - if (val == yes) { - if (def_menu) { - item_add_str(" (%s)", - _(menu_get_prompt(def_menu))); - item_add_str(" --->"); - if (def_menu->list) { - indent += 2; - build_conf(def_menu); - indent -= 2; - } - } - return; - } - } else { - if (menu == current_menu) { - item_make(menu, ':', - "---%*c%s", indent + 1, - ' ', _(menu_get_prompt(menu))); - goto conf_childs; - } - child_count++; - val = sym_get_tristate_value(sym); - if (sym_is_choice_value(sym) && val == yes) { - item_make(menu, ':', " "); - } else { - switch (type) { - case S_BOOLEAN: - if (sym_is_changable(sym)) - item_make(menu, 't', "[%c]", - val == no ? ' ' : '*'); - else - item_make(menu, 't', "-%c-", - val == no ? ' ' : '*'); - break; - case S_TRISTATE: - switch (val) { - case yes: - ch = '*'; - break; - case mod: - ch = 'M'; - break; - default: - ch = ' '; - break; - } - if (sym_is_changable(sym)) { - if (sym->rev_dep.tri == mod) - item_make(menu, - 't', "{%c}", ch); - else - item_make(menu, - 't', "<%c>", ch); - } else - item_make(menu, 't', "-%c-", ch); - break; - default: - tmp = 2 + strlen(sym_get_string_value(sym)); - item_make(menu, 's', " (%s)", - sym_get_string_value(sym)); - tmp = indent - tmp + 4; - if (tmp < 0) - tmp = 0; - item_add_str("%*c%s%s", tmp, ' ', - _(menu_get_prompt(menu)), - (sym_has_value(sym) || - !sym_is_changable(sym)) ? "" : - _(" (NEW)")); - goto conf_childs; - } - } - item_add_str("%*c%s%s", indent + 1, ' ', - _(menu_get_prompt(menu)), - (sym_has_value(sym) || !sym_is_changable(sym)) ? - "" : _(" (NEW)")); - if (menu->prompt && menu->prompt->type == P_MENU) { - item_add_str(" --->"); - return; - } - } - -conf_childs: - indent += doint; - for (child = menu->list; child; child = child->next) - build_conf(child); - indent -= doint; -} - -static void reset_menu(void) -{ - unpost_menu(curses_menu); - clean_items(); -} - -/* adjust the menu to show this item. - * prefer not to scroll the menu if possible*/ -static void center_item(int selected_index, int *last_top_row) -{ - int toprow; - - set_top_row(curses_menu, *last_top_row); - toprow = top_row(curses_menu); - if (selected_index < toprow || - selected_index >= toprow+mwin_max_lines) { - toprow = max(selected_index-mwin_max_lines/2, 0); - if (toprow >= item_count(curses_menu)-mwin_max_lines) - toprow = item_count(curses_menu)-mwin_max_lines; - set_top_row(curses_menu, toprow); - } - set_current_item(curses_menu, - curses_menu_items[selected_index]); - *last_top_row = toprow; - post_menu(curses_menu); - refresh_all_windows(main_window); -} - -/* this function assumes reset_menu has been called before */ -static void show_menu(const char *prompt, const char *instructions, - int selected_index, int *last_top_row) -{ - int maxx, maxy; - WINDOW *menu_window; - - current_instructions = instructions; - - clear(); - wattrset(main_window, attributes[NORMAL]); - print_in_middle(stdscr, 1, 0, COLS, - menu_backtitle, - attributes[MAIN_HEADING]); - - wattrset(main_window, attributes[MAIN_MENU_BOX]); - box(main_window, 0, 0); - wattrset(main_window, attributes[MAIN_MENU_HEADING]); - mvwprintw(main_window, 0, 3, " %s ", prompt); - wattrset(main_window, attributes[NORMAL]); - - set_menu_items(curses_menu, curses_menu_items); - - /* position the menu at the middle of the screen */ - scale_menu(curses_menu, &maxy, &maxx); - maxx = min(maxx, mwin_max_cols-2); - maxy = mwin_max_lines; - menu_window = derwin(main_window, - maxy, - maxx, - 2, - (mwin_max_cols-maxx)/2); - keypad(menu_window, TRUE); - set_menu_win(curses_menu, menu_window); - set_menu_sub(curses_menu, menu_window); - - /* must reassert this after changing items, otherwise returns to a - * default of 16 - */ - set_menu_format(curses_menu, maxy, 1); - center_item(selected_index, last_top_row); - set_menu_format(curses_menu, maxy, 1); - - print_function_line(); - - /* Post the menu */ - post_menu(curses_menu); - refresh_all_windows(main_window); -} - -static void adj_match_dir(match_f *match_direction) -{ - if (*match_direction == FIND_NEXT_MATCH_DOWN) - *match_direction = - MATCH_TINKER_PATTERN_DOWN; - else if (*match_direction == FIND_NEXT_MATCH_UP) - *match_direction = - MATCH_TINKER_PATTERN_UP; - /* else, do no change.. */ -} - -struct match_state -{ - int in_search; - match_f match_direction; - char pattern[256]; -}; - -/* Return 0 means I have handled the key. In such a case, ans should hold the - * item to center, or -1 otherwise. - * Else return -1 . - */ -static int do_match(int key, struct match_state *state, int *ans) -{ - char c = (char) key; - int terminate_search = 0; - *ans = -1; - if (key == '/' || (state->in_search && key == 27)) { - move(0, 0); - refresh(); - clrtoeol(); - state->in_search = 1-state->in_search; - bzero(state->pattern, sizeof(state->pattern)); - state->match_direction = MATCH_TINKER_PATTERN_DOWN; - return 0; - } else if (!state->in_search) - return 1; - - if (isalnum(c) || isgraph(c) || c == ' ') { - state->pattern[strlen(state->pattern)] = c; - state->pattern[strlen(state->pattern)] = '\0'; - adj_match_dir(&state->match_direction); - *ans = get_mext_match(state->pattern, - state->match_direction); - } else if (key == KEY_DOWN) { - state->match_direction = FIND_NEXT_MATCH_DOWN; - *ans = get_mext_match(state->pattern, - state->match_direction); - } else if (key == KEY_UP) { - state->match_direction = FIND_NEXT_MATCH_UP; - *ans = get_mext_match(state->pattern, - state->match_direction); - } else if (key == KEY_BACKSPACE || key == 127) { - state->pattern[strlen(state->pattern)-1] = '\0'; - adj_match_dir(&state->match_direction); - } else - terminate_search = 1; - - if (terminate_search) { - state->in_search = 0; - bzero(state->pattern, sizeof(state->pattern)); - move(0, 0); - refresh(); - clrtoeol(); - return -1; - } - return 0; -} - -static void conf(struct menu *menu) -{ - struct menu *submenu = 0; - const char *prompt = menu_get_prompt(menu); - struct symbol *sym; - struct menu *active_menu = NULL; - int res; - int current_index = 0; - int last_top_row = 0; - struct match_state match_state = { - .in_search = 0, - .match_direction = MATCH_TINKER_PATTERN_DOWN, - .pattern = "", - }; - - while (!global_exit) { - reset_menu(); - current_menu = menu; - build_conf(menu); - if (!child_count) - break; - - show_menu(prompt ? _(prompt) : _("Main Menu"), - _(menu_instructions), - current_index, &last_top_row); - keypad((menu_win(curses_menu)), TRUE); - while (!global_exit) { - if (match_state.in_search) { - mvprintw(0, 0, - "searching: %s", match_state.pattern); - clrtoeol(); - } - refresh_all_windows(main_window); - res = wgetch(menu_win(curses_menu)); - if (!res) - break; - if (do_match(res, &match_state, ¤t_index) == 0) { - if (current_index != -1) - center_item(current_index, - &last_top_row); - continue; - } - if (process_special_keys(&res, - (struct menu *) item_data())) - break; - switch (res) { - case KEY_DOWN: - menu_driver(curses_menu, REQ_DOWN_ITEM); - break; - case KEY_UP: - menu_driver(curses_menu, REQ_UP_ITEM); - break; - case KEY_NPAGE: - menu_driver(curses_menu, REQ_SCR_DPAGE); - break; - case KEY_PPAGE: - menu_driver(curses_menu, REQ_SCR_UPAGE); - break; - case KEY_HOME: - menu_driver(curses_menu, REQ_FIRST_ITEM); - break; - case KEY_END: - menu_driver(curses_menu, REQ_LAST_ITEM); - break; - case 'h': - case '?': - show_help((struct menu *) item_data()); - break; - } - if (res == 10 || res == 27 || - res == 32 || res == 'n' || res == 'y' || - res == KEY_LEFT || res == KEY_RIGHT || - res == 'm') - break; - refresh_all_windows(main_window); - } - - refresh_all_windows(main_window); - /* if ESC or left*/ - if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) - break; - - /* remember location in the menu */ - last_top_row = top_row(curses_menu); - current_index = curses_item_index(); - - if (!item_tag()) - continue; - - submenu = (struct menu *) item_data(); - active_menu = (struct menu *)item_data(); - if (!submenu || !menu_is_visible(submenu)) - continue; - if (submenu) - sym = submenu->sym; - else - sym = NULL; - - switch (res) { - case ' ': - if (item_is_tag('t')) - sym_toggle_tristate_value(sym); - else if (item_is_tag('m')) - conf(submenu); - break; - case KEY_RIGHT: - case 10: /* ENTER WAS PRESSED */ - switch (item_tag()) { - case 'm': - if (single_menu_mode) - submenu->data = - (void *) (long) !submenu->data; - else - conf(submenu); - break; - case 't': - if (sym_is_choice(sym) && - sym_get_tristate_value(sym) == yes) - conf_choice(submenu); - else if (submenu->prompt && - submenu->prompt->type == P_MENU) - conf(submenu); - else if (res == 10) - sym_toggle_tristate_value(sym); - break; - case 's': - conf_string(submenu); - break; - } - break; - case 'y': - if (item_is_tag('t')) { - if (sym_set_tristate_value(sym, yes)) - break; - if (sym_set_tristate_value(sym, mod)) - btn_dialog(main_window, setmod_text, 0); - } - break; - case 'n': - if (item_is_tag('t')) - sym_set_tristate_value(sym, no); - break; - case 'm': - if (item_is_tag('t')) - sym_set_tristate_value(sym, mod); - break; - } - } -} - -static void conf_message_callback(const char *fmt, va_list ap) -{ - char buf[1024]; - - vsnprintf(buf, sizeof(buf), fmt, ap); - btn_dialog(main_window, buf, 1, ""); -} - -static void show_help(struct menu *menu) -{ - struct gstr help = str_new(); - - if (menu && menu->sym && menu_has_help(menu)) { - if (menu->sym->name) { - str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name); - str_append(&help, _(menu_get_help(menu))); - str_append(&help, "\n"); - get_symbol_str(&help, menu->sym); - } else { - str_append(&help, _(menu_get_help(menu))); - } - } else { - str_append(&help, nohelp_text); - } - show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); - str_free(&help); -} - -static void conf_choice(struct menu *menu) -{ - const char *prompt = _(menu_get_prompt(menu)); - struct menu *child = 0; - struct symbol *active; - int selected_index = 0; - int last_top_row = 0; - int res, i = 0; - struct match_state match_state = { - .in_search = 0, - .match_direction = MATCH_TINKER_PATTERN_DOWN, - .pattern = "", - }; - - active = sym_get_choice_value(menu->sym); - /* this is mostly duplicated from the conf() function. */ - while (!global_exit) { - reset_menu(); - - for (i = 0, child = menu->list; child; child = child->next) { - if (!show_all_items && !menu_is_visible(child)) - continue; - - if (child->sym == sym_get_choice_value(menu->sym)) - item_make(child, ':', " %s", - _(menu_get_prompt(child))); - else if (child->sym) - item_make(child, ':', " %s", - _(menu_get_prompt(child))); - else - item_make(child, ':', "*** %s ***", - _(menu_get_prompt(child))); - - if (child->sym == active){ - last_top_row = top_row(curses_menu); - selected_index = i; - } - i++; - } - show_menu(prompt ? _(prompt) : _("Choice Menu"), - _(radiolist_instructions), - selected_index, - &last_top_row); - while (!global_exit) { - if (match_state.in_search) { - mvprintw(0, 0, "searching: %s", - match_state.pattern); - clrtoeol(); - } - refresh_all_windows(main_window); - res = wgetch(menu_win(curses_menu)); - if (!res) - break; - if (do_match(res, &match_state, &selected_index) == 0) { - if (selected_index != -1) - center_item(selected_index, - &last_top_row); - continue; - } - if (process_special_keys( - &res, - (struct menu *) item_data())) - break; - switch (res) { - case KEY_DOWN: - menu_driver(curses_menu, REQ_DOWN_ITEM); - break; - case KEY_UP: - menu_driver(curses_menu, REQ_UP_ITEM); - break; - case KEY_NPAGE: - menu_driver(curses_menu, REQ_SCR_DPAGE); - break; - case KEY_PPAGE: - menu_driver(curses_menu, REQ_SCR_UPAGE); - break; - case KEY_HOME: - menu_driver(curses_menu, REQ_FIRST_ITEM); - break; - case KEY_END: - menu_driver(curses_menu, REQ_LAST_ITEM); - break; - case 'h': - case '?': - show_help((struct menu *) item_data()); - break; - } - if (res == 10 || res == 27 || res == ' ' || - res == KEY_LEFT){ - break; - } - refresh_all_windows(main_window); - } - /* if ESC or left */ - if (res == 27 || res == KEY_LEFT) - break; - - child = item_data(); - if (!child || !menu_is_visible(child) || !child->sym) - continue; - switch (res) { - case ' ': - case 10: - case KEY_RIGHT: - sym_set_tristate_value(child->sym, yes); - return; - case 'h': - case '?': - show_help(child); - active = child->sym; - break; - case KEY_EXIT: - return; - } - } -} - -static void conf_string(struct menu *menu) -{ - const char *prompt = menu_get_prompt(menu); - char dialog_input_result[256]; - - while (1) { - int res; - const char *heading; - - switch (sym_get_type(menu->sym)) { - case S_INT: - heading = _(inputbox_instructions_int); - break; - case S_HEX: - heading = _(inputbox_instructions_hex); - break; - case S_STRING: - heading = _(inputbox_instructions_string); - break; - default: - heading = _("Internal nconf error!"); - } - res = dialog_inputbox(main_window, - prompt ? _(prompt) : _("Main Menu"), - heading, - sym_get_string_value(menu->sym), - dialog_input_result, - sizeof(dialog_input_result)); - switch (res) { - case 0: - if (sym_set_string_value(menu->sym, - dialog_input_result)) - return; - btn_dialog(main_window, - _("You have made an invalid entry."), 0); - break; - case 1: - show_help(menu); - break; - case KEY_EXIT: - return; - } - } -} - -static void conf_load(void) -{ - char dialog_input_result[256]; - while (1) { - int res; - res = dialog_inputbox(main_window, - NULL, load_config_text, - filename, - dialog_input_result, - sizeof(dialog_input_result)); - switch (res) { - case 0: - if (!dialog_input_result[0]) - return; - if (!conf_read(dialog_input_result)) { - set_config_filename(dialog_input_result); - sym_set_change_count(1); - return; - } - btn_dialog(main_window, _("File does not exist!"), 0); - break; - case 1: - show_scroll_win(main_window, - _("Load Alternate Configuration"), - load_config_help); - break; - case KEY_EXIT: - return; - } - } -} - -static void conf_save(void) -{ - char dialog_input_result[256]; - while (1) { - int res; - res = dialog_inputbox(main_window, - NULL, save_config_text, - filename, - dialog_input_result, - sizeof(dialog_input_result)); - switch (res) { - case 0: - if (!dialog_input_result[0]) - return; - res = conf_write(dialog_input_result); - if (!res) { - set_config_filename(dialog_input_result); - return; - } - btn_dialog(main_window, _("Can't create file! " - "Probably a nonexistent directory."), - 1, ""); - break; - case 1: - show_scroll_win(main_window, - _("Save Alternate Configuration"), - save_config_help); - break; - case KEY_EXIT: - return; - } - } -} - -void setup_windows(void) -{ - if (main_window != NULL) - delwin(main_window); - - /* set up the menu and menu window */ - main_window = newwin(LINES-2, COLS-2, 2, 1); - keypad(main_window, TRUE); - mwin_max_lines = LINES-7; - mwin_max_cols = COLS-6; - - /* panels order is from bottom to top */ - new_panel(main_window); -} - -int main(int ac, char **av) -{ - char *mode; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - conf_parse(av[1]); - conf_read(NULL); - - mode = getenv("NCONFIG_MODE"); - if (mode) { - if (!strcasecmp(mode, "single_menu")) - single_menu_mode = 1; - } - - /* Initialize curses */ - initscr(); - /* set color theme */ - set_colors(); - - cbreak(); - noecho(); - keypad(stdscr, TRUE); - curs_set(0); - - if (COLS < 75 || LINES < 20) { - endwin(); - printf("Your terminal should have at " - "least 20 lines and 75 columns\n"); - return 1; - } - - notimeout(stdscr, FALSE); - ESCDELAY = 1; - - /* set btns menu */ - curses_menu = new_menu(curses_menu_items); - menu_opts_off(curses_menu, O_SHOWDESC); - menu_opts_on(curses_menu, O_SHOWMATCH); - menu_opts_on(curses_menu, O_ONEVALUE); - menu_opts_on(curses_menu, O_NONCYCLIC); - menu_opts_on(curses_menu, O_IGNORECASE); - set_menu_mark(curses_menu, " "); - set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); - set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); - set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]); - - set_config_filename(conf_get_configname()); - setup_windows(); - - /* check for KEY_FUNC(1) */ - if (has_key(KEY_F(1)) == FALSE) { - show_scroll_win(main_window, - _("Instructions"), - _(menu_no_f_instructions)); - } - - conf_set_message_callback(conf_message_callback); - /* do the work */ - while (!global_exit) { - conf(&rootmenu); - if (!global_exit && do_exit() == 0) - break; - } - /* ok, we are done */ - unpost_menu(curses_menu); - free_menu(curses_menu); - delwin(main_window); - clear(); - refresh(); - endwin(); - return 0; -} - diff -Nru seabios-1.7.1/tools/kconfig/nconf.gui.c seabios-1.7.4/tools/kconfig/nconf.gui.c --- seabios-1.7.1/tools/kconfig/nconf.gui.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/nconf.gui.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,617 +0,0 @@ -/* - * Copyright (C) 2008 Nir Tzachar 0) - win_rows = msg_lines+4; - else - win_rows = msg_lines+2; - - win = newwin(win_rows, total_width+4, y, x); - keypad(win, TRUE); - menu_win = derwin(win, 1, btns_width, win_rows-2, - 1+(total_width+2-btns_width)/2); - menu = new_menu(btns); - msg_win = derwin(win, win_rows-2, msg_width, 1, - 1+(total_width+2-msg_width)/2); - - set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); - set_menu_back(menu, attributes[DIALOG_MENU_BACK]); - - (void) wattrset(win, attributes[DIALOG_BOX]); - box(win, 0, 0); - - /* print message */ - (void) wattrset(msg_win, attributes[DIALOG_TEXT]); - fill_window(msg_win, msg); - - set_menu_win(menu, win); - set_menu_sub(menu, menu_win); - set_menu_format(menu, 1, btn_num); - menu_opts_off(menu, O_SHOWDESC); - menu_opts_off(menu, O_SHOWMATCH); - menu_opts_on(menu, O_ONEVALUE); - menu_opts_on(menu, O_NONCYCLIC); - set_menu_mark(menu, ""); - post_menu(menu); - - - touchwin(win); - refresh_all_windows(main_window); - while ((res = wgetch(win))) { - switch (res) { - case KEY_LEFT: - menu_driver(menu, REQ_LEFT_ITEM); - break; - case KEY_RIGHT: - menu_driver(menu, REQ_RIGHT_ITEM); - break; - case 10: /* ENTER */ - case 27: /* ESCAPE */ - case ' ': - case KEY_F(F_BACK): - case KEY_F(F_EXIT): - break; - } - touchwin(win); - refresh_all_windows(main_window); - - if (res == 10 || res == ' ') { - res = item_index(current_item(menu)); - break; - } else if (res == 27 || res == KEY_F(F_BACK) || - res == KEY_F(F_EXIT)) { - res = KEY_EXIT; - break; - } - } - - unpost_menu(menu); - free_menu(menu); - for (i = 0; i < btn_num; i++) - free_item(btns[i]); - - delwin(win); - return res; -} - -int dialog_inputbox(WINDOW *main_window, - const char *title, const char *prompt, - const char *init, char *result, int result_len) -{ - int prompt_lines = 0; - int prompt_width = 0; - WINDOW *win; - WINDOW *prompt_win; - WINDOW *form_win; - PANEL *panel; - int i, x, y; - int res = -1; - int cursor_position = strlen(init); - - - /* find the widest line of msg: */ - prompt_lines = get_line_no(prompt); - for (i = 0; i < prompt_lines; i++) { - const char *line = get_line(prompt, i); - int len = get_line_length(line); - prompt_width = max(prompt_width, len); - } - - if (title) - prompt_width = max(prompt_width, strlen(title)); - - /* place dialog in middle of screen */ - y = (LINES-(prompt_lines+4))/2; - x = (COLS-(prompt_width+4))/2; - - strncpy(result, init, result_len); - - /* create the windows */ - win = newwin(prompt_lines+6, prompt_width+7, y, x); - prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); - form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); - keypad(form_win, TRUE); - - (void) wattrset(form_win, attributes[INPUT_FIELD]); - - (void) wattrset(win, attributes[INPUT_BOX]); - box(win, 0, 0); - (void) wattrset(win, attributes[INPUT_HEADING]); - if (title) - mvwprintw(win, 0, 3, "%s", title); - - /* print message */ - (void) wattrset(prompt_win, attributes[INPUT_TEXT]); - fill_window(prompt_win, prompt); - - mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); - mvwprintw(form_win, 0, 0, "%s", result); - - /* create panels */ - panel = new_panel(win); - - /* show the cursor */ - curs_set(1); - - touchwin(win); - refresh_all_windows(main_window); - while ((res = wgetch(form_win))) { - int len = strlen(result); - switch (res) { - case 10: /* ENTER */ - case 27: /* ESCAPE */ - case KEY_F(F_HELP): - case KEY_F(F_EXIT): - case KEY_F(F_BACK): - break; - case 127: - case KEY_BACKSPACE: - if (cursor_position > 0) { - memmove(&result[cursor_position-1], - &result[cursor_position], - len-cursor_position+1); - cursor_position--; - } - break; - case KEY_DC: - if (cursor_position >= 0 && cursor_position < len) { - memmove(&result[cursor_position], - &result[cursor_position+1], - len-cursor_position+1); - } - break; - case KEY_UP: - case KEY_RIGHT: - if (cursor_position < len && - cursor_position < min(result_len, prompt_width)) - cursor_position++; - break; - case KEY_DOWN: - case KEY_LEFT: - if (cursor_position > 0) - cursor_position--; - break; - default: - if ((isgraph(res) || isspace(res)) && - len-2 < result_len) { - /* insert the char at the proper position */ - memmove(&result[cursor_position+1], - &result[cursor_position], - len+1); - result[cursor_position] = res; - cursor_position++; - } else { - mvprintw(0, 0, "unknow key: %d\n", res); - } - break; - } - wmove(form_win, 0, 0); - wclrtoeol(form_win); - mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); - mvwprintw(form_win, 0, 0, "%s", result); - wmove(form_win, 0, cursor_position); - touchwin(win); - refresh_all_windows(main_window); - - if (res == 10) { - res = 0; - break; - } else if (res == 27 || res == KEY_F(F_BACK) || - res == KEY_F(F_EXIT)) { - res = KEY_EXIT; - break; - } else if (res == KEY_F(F_HELP)) { - res = 1; - break; - } - } - - /* hide the cursor */ - curs_set(0); - del_panel(panel); - delwin(prompt_win); - delwin(form_win); - delwin(win); - return res; -} - -/* refresh all windows in the correct order */ -void refresh_all_windows(WINDOW *main_window) -{ - update_panels(); - touchwin(main_window); - refresh(); -} - -/* layman's scrollable window... */ -void show_scroll_win(WINDOW *main_window, - const char *title, - const char *text) -{ - int res; - int total_lines = get_line_no(text); - int x, y; - int start_x = 0, start_y = 0; - int text_lines = 0, text_cols = 0; - int total_cols = 0; - int win_cols = 0; - int win_lines = 0; - int i = 0; - WINDOW *win; - WINDOW *pad; - PANEL *panel; - - /* find the widest line of msg: */ - total_lines = get_line_no(text); - for (i = 0; i < total_lines; i++) { - const char *line = get_line(text, i); - int len = get_line_length(line); - total_cols = max(total_cols, len+2); - } - - /* create the pad */ - pad = newpad(total_lines+10, total_cols+10); - (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); - fill_window(pad, text); - - win_lines = min(total_lines+4, LINES-2); - win_cols = min(total_cols+2, COLS-2); - text_lines = max(win_lines-4, 0); - text_cols = max(win_cols-2, 0); - - /* place window in middle of screen */ - y = (LINES-win_lines)/2; - x = (COLS-win_cols)/2; - - win = newwin(win_lines, win_cols, y, x); - keypad(win, TRUE); - /* show the help in the help window, and show the help panel */ - (void) wattrset(win, attributes[SCROLLWIN_BOX]); - box(win, 0, 0); - (void) wattrset(win, attributes[SCROLLWIN_HEADING]); - mvwprintw(win, 0, 3, " %s ", title); - panel = new_panel(win); - - /* handle scrolling */ - do { - - copywin(pad, win, start_y, start_x, 2, 2, text_lines, - text_cols, 0); - print_in_middle(win, - text_lines+2, - 0, - text_cols, - "", - attributes[DIALOG_MENU_FORE]); - wrefresh(win); - - res = wgetch(win); - switch (res) { - case KEY_NPAGE: - case ' ': - start_y += text_lines-2; - break; - case KEY_PPAGE: - start_y -= text_lines+2; - break; - case KEY_HOME: - start_y = 0; - break; - case KEY_END: - start_y = total_lines-text_lines; - break; - case KEY_DOWN: - case 'j': - start_y++; - break; - case KEY_UP: - case 'k': - start_y--; - break; - case KEY_LEFT: - case 'h': - start_x--; - break; - case KEY_RIGHT: - case 'l': - start_x++; - break; - } - if (res == 10 || res == 27 || res == 'q' - || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) { - break; - } - if (start_y < 0) - start_y = 0; - if (start_y >= total_lines-text_lines) - start_y = total_lines-text_lines; - if (start_x < 0) - start_x = 0; - if (start_x >= total_cols-text_cols) - start_x = total_cols-text_cols; - } while (res); - - del_panel(panel); - delwin(win); - refresh_all_windows(main_window); -} diff -Nru seabios-1.7.1/tools/kconfig/nconf.h seabios-1.7.4/tools/kconfig/nconf.h --- seabios-1.7.1/tools/kconfig/nconf.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/nconf.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 Nir Tzachar -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ncurses.h" - -#define max(a, b) ({\ - typeof(a) _a = a;\ - typeof(b) _b = b;\ - _a > _b ? _a : _b; }) - -#define min(a, b) ({\ - typeof(a) _a = a;\ - typeof(b) _b = b;\ - _a < _b ? _a : _b; }) - -typedef enum { - NORMAL = 1, - MAIN_HEADING, - MAIN_MENU_BOX, - MAIN_MENU_FORE, - MAIN_MENU_BACK, - MAIN_MENU_GREY, - MAIN_MENU_HEADING, - SCROLLWIN_TEXT, - SCROLLWIN_HEADING, - SCROLLWIN_BOX, - DIALOG_TEXT, - DIALOG_MENU_FORE, - DIALOG_MENU_BACK, - DIALOG_BOX, - INPUT_BOX, - INPUT_HEADING, - INPUT_TEXT, - INPUT_FIELD, - FUNCTION_TEXT, - FUNCTION_HIGHLIGHT, - ATTR_MAX -} attributes_t; -extern attributes_t attributes[]; - -typedef enum { - F_HELP = 1, - F_SYMBOL = 2, - F_INSTS = 3, - F_CONF = 4, - F_BACK = 5, - F_SAVE = 6, - F_LOAD = 7, - F_SEARCH = 8, - F_EXIT = 9, -} function_key; - -void set_colors(void); - -/* this changes the windows attributes !!! */ -void print_in_middle(WINDOW *win, - int starty, - int startx, - int width, - const char *string, - chtype color); -int get_line_length(const char *line); -int get_line_no(const char *text); -const char *get_line(const char *text, int line_no); -void fill_window(WINDOW *win, const char *text); -int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); -int dialog_inputbox(WINDOW *main_window, - const char *title, const char *prompt, - const char *init, char *result, int result_len); -void refresh_all_windows(WINDOW *main_window); -void show_scroll_win(WINDOW *main_window, - const char *title, - const char *text); diff -Nru seabios-1.7.1/tools/kconfig/POTFILES.in seabios-1.7.4/tools/kconfig/POTFILES.in --- seabios-1.7.1/tools/kconfig/POTFILES.in 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/POTFILES.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -tools/kconfig/lxdialog/checklist.c -tools/kconfig/lxdialog/inputbox.c -tools/kconfig/lxdialog/menubox.c -tools/kconfig/lxdialog/textbox.c -tools/kconfig/lxdialog/util.c -tools/kconfig/lxdialog/yesno.c -tools/kconfig/mconf.c -tools/kconfig/conf.c -tools/kconfig/confdata.c -tools/kconfig/gconf.c -tools/kconfig/gconf.glade.h -tools/kconfig/qconf.cc diff -Nru seabios-1.7.1/tools/kconfig/qconf.cc seabios-1.7.4/tools/kconfig/qconf.cc --- seabios-1.7.1/tools/kconfig/qconf.cc 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/qconf.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,1787 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include - -#if QT_VERSION < 0x040000 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "lkc.h" -#include "qconf.h" - -#include "qconf.moc" -#include "images.c" - -#ifdef _ -# undef _ -# define _ qgettext -#endif - -static QApplication *configApp; -static ConfigSettings *configSettings; - -Q3Action *ConfigMainWindow::saveAction; - -static inline QString qgettext(const char* str) -{ - return QString::fromLocal8Bit(gettext(str)); -} - -static inline QString qgettext(const QString& str) -{ - return QString::fromLocal8Bit(gettext(str.latin1())); -} - -/** - * Reads a list of integer values from the application settings. - */ -Q3ValueList ConfigSettings::readSizes(const QString& key, bool *ok) -{ - Q3ValueList result; - QStringList entryList = readListEntry(key, ok); - QStringList::Iterator it; - - for (it = entryList.begin(); it != entryList.end(); ++it) - result.push_back((*it).toInt()); - - return result; -} - -/** - * Writes a list of integer values to the application settings. - */ -bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList& value) -{ - QStringList stringList; - Q3ValueList::ConstIterator it; - - for (it = value.begin(); it != value.end(); ++it) - stringList.push_back(QString::number(*it)); - return writeEntry(key, stringList); -} - - -/* - * set the new data - * TODO check the value - */ -void ConfigItem::okRename(int col) -{ - Parent::okRename(col); - sym_set_string_value(menu->sym, text(dataColIdx).latin1()); - listView()->updateList(this); -} - -/* - * update the displayed of a menu entry - */ -void ConfigItem::updateMenu(void) -{ - ConfigList* list; - struct symbol* sym; - struct property *prop; - QString prompt; - int type; - tristate expr; - - list = listView(); - if (goParent) { - setPixmap(promptColIdx, list->menuBackPix); - prompt = ".."; - goto set_prompt; - } - - sym = menu->sym; - prop = menu->prompt; - prompt = _(menu_get_prompt(menu)); - - if (prop) switch (prop->type) { - case P_MENU: - if (list->mode == singleMode || list->mode == symbolMode) { - /* a menuconfig entry is displayed differently - * depending whether it's at the view root or a child. - */ - if (sym && list->rootEntry == menu) - break; - setPixmap(promptColIdx, list->menuPix); - } else { - if (sym) - break; - setPixmap(promptColIdx, 0); - } - goto set_prompt; - case P_COMMENT: - setPixmap(promptColIdx, 0); - goto set_prompt; - default: - ; - } - if (!sym) - goto set_prompt; - - setText(nameColIdx, QString::fromLocal8Bit(sym->name)); - - type = sym_get_type(sym); - switch (type) { - case S_BOOLEAN: - case S_TRISTATE: - char ch; - - if (!sym_is_changable(sym) && list->optMode == normalOpt) { - setPixmap(promptColIdx, 0); - setText(noColIdx, QString::null); - setText(modColIdx, QString::null); - setText(yesColIdx, QString::null); - break; - } - expr = sym_get_tristate_value(sym); - switch (expr) { - case yes: - if (sym_is_choice_value(sym) && type == S_BOOLEAN) - setPixmap(promptColIdx, list->choiceYesPix); - else - setPixmap(promptColIdx, list->symbolYesPix); - setText(yesColIdx, "Y"); - ch = 'Y'; - break; - case mod: - setPixmap(promptColIdx, list->symbolModPix); - setText(modColIdx, "M"); - ch = 'M'; - break; - default: - if (sym_is_choice_value(sym) && type == S_BOOLEAN) - setPixmap(promptColIdx, list->choiceNoPix); - else - setPixmap(promptColIdx, list->symbolNoPix); - setText(noColIdx, "N"); - ch = 'N'; - break; - } - if (expr != no) - setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); - if (expr != mod) - setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); - if (expr != yes) - setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); - - setText(dataColIdx, QChar(ch)); - break; - case S_INT: - case S_HEX: - case S_STRING: - const char* data; - - data = sym_get_string_value(sym); - - int i = list->mapIdx(dataColIdx); - if (i >= 0) - setRenameEnabled(i, TRUE); - setText(dataColIdx, data); - if (type == S_STRING) - prompt = QString("%1: %2").arg(prompt).arg(data); - else - prompt = QString("(%2) %1").arg(prompt).arg(data); - break; - } - if (!sym_has_value(sym) && visible) - prompt += _(" (NEW)"); -set_prompt: - setText(promptColIdx, prompt); -} - -void ConfigItem::testUpdateMenu(bool v) -{ - ConfigItem* i; - - visible = v; - if (!menu) - return; - - sym_calc_value(menu->sym); - if (menu->flags & MENU_CHANGED) { - /* the menu entry changed, so update all list items */ - menu->flags &= ~MENU_CHANGED; - for (i = (ConfigItem*)menu->data; i; i = i->nextItem) - i->updateMenu(); - } else if (listView()->updateAll) - updateMenu(); -} - -void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) -{ - ConfigList* list = listView(); - - if (visible) { - if (isSelected() && !list->hasFocus() && list->mode == menuMode) - Parent::paintCell(p, list->inactivedColorGroup, column, width, align); - else - Parent::paintCell(p, cg, column, width, align); - } else - Parent::paintCell(p, list->disabledColorGroup, column, width, align); -} - -/* - * construct a menu entry - */ -void ConfigItem::init(void) -{ - if (menu) { - ConfigList* list = listView(); - nextItem = (ConfigItem*)menu->data; - menu->data = this; - - if (list->mode != fullMode) - setOpen(TRUE); - sym_calc_value(menu->sym); - } - updateMenu(); -} - -/* - * destruct a menu entry - */ -ConfigItem::~ConfigItem(void) -{ - if (menu) { - ConfigItem** ip = (ConfigItem**)&menu->data; - for (; *ip; ip = &(*ip)->nextItem) { - if (*ip == this) { - *ip = nextItem; - break; - } - } - } -} - -ConfigLineEdit::ConfigLineEdit(ConfigView* parent) - : Parent(parent) -{ - connect(this, SIGNAL(lostFocus()), SLOT(hide())); -} - -void ConfigLineEdit::show(ConfigItem* i) -{ - item = i; - if (sym_get_string_value(item->menu->sym)) - setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); - else - setText(QString::null); - Parent::show(); - setFocus(); -} - -void ConfigLineEdit::keyPressEvent(QKeyEvent* e) -{ - switch (e->key()) { - case Qt::Key_Escape: - break; - case Qt::Key_Return: - case Qt::Key_Enter: - sym_set_string_value(item->menu->sym, text().latin1()); - parent()->updateList(item); - break; - default: - Parent::keyPressEvent(e); - return; - } - e->accept(); - parent()->list->setFocus(); - hide(); -} - -ConfigList::ConfigList(ConfigView* p, const char *name) - : Parent(p, name), - updateAll(false), - symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), - choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), - menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), - showName(false), showRange(false), showData(false), optMode(normalOpt), - rootEntry(0), headerPopup(0) -{ - int i; - - setSorting(-1); - setRootIsDecorated(TRUE); - disabledColorGroup = palette().active(); - disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text()); - inactivedColorGroup = palette().active(); - inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight()); - - connect(this, SIGNAL(selectionChanged(void)), - SLOT(updateSelection(void))); - - if (name) { - configSettings->beginGroup(name); - showName = configSettings->readBoolEntry("/showName", false); - showRange = configSettings->readBoolEntry("/showRange", false); - showData = configSettings->readBoolEntry("/showData", false); - optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false); - configSettings->endGroup(); - connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); - } - - for (i = 0; i < colNr; i++) - colMap[i] = colRevMap[i] = -1; - addColumn(promptColIdx, _("Option")); - - reinit(); -} - -bool ConfigList::menuSkip(struct menu *menu) -{ - if (optMode == normalOpt && menu_is_visible(menu)) - return false; - if (optMode == promptOpt && menu_has_prompt(menu)) - return false; - if (optMode == allOpt) - return false; - return true; -} - -void ConfigList::reinit(void) -{ - removeColumn(dataColIdx); - removeColumn(yesColIdx); - removeColumn(modColIdx); - removeColumn(noColIdx); - removeColumn(nameColIdx); - - if (showName) - addColumn(nameColIdx, _("Name")); - if (showRange) { - addColumn(noColIdx, "N"); - addColumn(modColIdx, "M"); - addColumn(yesColIdx, "Y"); - } - if (showData) - addColumn(dataColIdx, _("Value")); - - updateListAll(); -} - -void ConfigList::saveSettings(void) -{ - if (name()) { - configSettings->beginGroup(name()); - configSettings->writeEntry("/showName", showName); - configSettings->writeEntry("/showRange", showRange); - configSettings->writeEntry("/showData", showData); - configSettings->writeEntry("/optionMode", (int)optMode); - configSettings->endGroup(); - } -} - -ConfigItem* ConfigList::findConfigItem(struct menu *menu) -{ - ConfigItem* item = (ConfigItem*)menu->data; - - for (; item; item = item->nextItem) { - if (this == item->listView()) - break; - } - - return item; -} - -void ConfigList::updateSelection(void) -{ - struct menu *menu; - enum prop_type type; - - ConfigItem* item = (ConfigItem*)selectedItem(); - if (!item) - return; - - menu = item->menu; - emit menuChanged(menu); - if (!menu) - return; - type = menu->prompt ? menu->prompt->type : P_UNKNOWN; - if (mode == menuMode && type == P_MENU) - emit menuSelected(menu); -} - -void ConfigList::updateList(ConfigItem* item) -{ - ConfigItem* last = 0; - - if (!rootEntry) { - if (mode != listMode) - goto update; - Q3ListViewItemIterator it(this); - ConfigItem* item; - - for (; it.current(); ++it) { - item = (ConfigItem*)it.current(); - if (!item->menu) - continue; - item->testUpdateMenu(menu_is_visible(item->menu)); - } - return; - } - - if (rootEntry != &rootmenu && (mode == singleMode || - (mode == symbolMode && rootEntry->parent != &rootmenu))) { - item = firstChild(); - if (!item) - item = new ConfigItem(this, 0, true); - last = item; - } - if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && - rootEntry->sym && rootEntry->prompt) { - item = last ? last->nextSibling() : firstChild(); - if (!item) - item = new ConfigItem(this, last, rootEntry, true); - else - item->testUpdateMenu(true); - - updateMenuList(item, rootEntry); - triggerUpdate(); - return; - } -update: - updateMenuList(this, rootEntry); - triggerUpdate(); -} - -void ConfigList::setValue(ConfigItem* item, tristate val) -{ - struct symbol* sym; - int type; - tristate oldval; - - sym = item->menu ? item->menu->sym : 0; - if (!sym) - return; - - type = sym_get_type(sym); - switch (type) { - case S_BOOLEAN: - case S_TRISTATE: - oldval = sym_get_tristate_value(sym); - - if (!sym_set_tristate_value(sym, val)) - return; - if (oldval == no && item->menu->list) - item->setOpen(TRUE); - parent()->updateList(item); - break; - } -} - -void ConfigList::changeValue(ConfigItem* item) -{ - struct symbol* sym; - struct menu* menu; - int type, oldexpr, newexpr; - - menu = item->menu; - if (!menu) - return; - sym = menu->sym; - if (!sym) { - if (item->menu->list) - item->setOpen(!item->isOpen()); - return; - } - - type = sym_get_type(sym); - switch (type) { - case S_BOOLEAN: - case S_TRISTATE: - oldexpr = sym_get_tristate_value(sym); - newexpr = sym_toggle_tristate_value(sym); - if (item->menu->list) { - if (oldexpr == newexpr) - item->setOpen(!item->isOpen()); - else if (oldexpr == no) - item->setOpen(TRUE); - } - if (oldexpr != newexpr) - parent()->updateList(item); - break; - case S_INT: - case S_HEX: - case S_STRING: - if (colMap[dataColIdx] >= 0) - item->startRename(colMap[dataColIdx]); - else - parent()->lineEdit->show(item); - break; - } -} - -void ConfigList::setRootMenu(struct menu *menu) -{ - enum prop_type type; - - if (rootEntry == menu) - return; - type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; - if (type != P_MENU) - return; - updateMenuList(this, 0); - rootEntry = menu; - updateListAll(); - setSelected(currentItem(), hasFocus()); - ensureItemVisible(currentItem()); -} - -void ConfigList::setParentMenu(void) -{ - ConfigItem* item; - struct menu *oldroot; - - oldroot = rootEntry; - if (rootEntry == &rootmenu) - return; - setRootMenu(menu_get_parent_menu(rootEntry->parent)); - - Q3ListViewItemIterator it(this); - for (; (item = (ConfigItem*)it.current()); it++) { - if (item->menu == oldroot) { - setCurrentItem(item); - ensureItemVisible(item); - break; - } - } -} - -/* - * update all the children of a menu entry - * removes/adds the entries from the parent widget as necessary - * - * parent: either the menu list widget or a menu entry widget - * menu: entry to be updated - */ -template -void ConfigList::updateMenuList(P* parent, struct menu* menu) -{ - struct menu* child; - ConfigItem* item; - ConfigItem* last; - bool visible; - enum prop_type type; - - if (!menu) { - while ((item = parent->firstChild())) - delete item; - return; - } - - last = parent->firstChild(); - if (last && !last->goParent) - last = 0; - for (child = menu->list; child; child = child->next) { - item = last ? last->nextSibling() : parent->firstChild(); - type = child->prompt ? child->prompt->type : P_UNKNOWN; - - switch (mode) { - case menuMode: - if (!(child->flags & MENU_ROOT)) - goto hide; - break; - case symbolMode: - if (child->flags & MENU_ROOT) - goto hide; - break; - default: - break; - } - - visible = menu_is_visible(child); - if (!menuSkip(child)) { - if (!child->sym && !child->list && !child->prompt) - continue; - if (!item || item->menu != child) - item = new ConfigItem(parent, last, child, visible); - else - item->testUpdateMenu(visible); - - if (mode == fullMode || mode == menuMode || type != P_MENU) - updateMenuList(item, child); - else - updateMenuList(item, 0); - last = item; - continue; - } - hide: - if (item && item->menu == child) { - last = parent->firstChild(); - if (last == item) - last = 0; - else while (last->nextSibling() != item) - last = last->nextSibling(); - delete item; - } - } -} - -void ConfigList::keyPressEvent(QKeyEvent* ev) -{ - Q3ListViewItem* i = currentItem(); - ConfigItem* item; - struct menu *menu; - enum prop_type type; - - if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) { - emit parentSelected(); - ev->accept(); - return; - } - - if (!i) { - Parent::keyPressEvent(ev); - return; - } - item = (ConfigItem*)i; - - switch (ev->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - if (item->goParent) { - emit parentSelected(); - break; - } - menu = item->menu; - if (!menu) - break; - type = menu->prompt ? menu->prompt->type : P_UNKNOWN; - if (type == P_MENU && rootEntry != menu && - mode != fullMode && mode != menuMode) { - emit menuSelected(menu); - break; - } - case Qt::Key_Space: - changeValue(item); - break; - case Qt::Key_N: - setValue(item, no); - break; - case Qt::Key_M: - setValue(item, mod); - break; - case Qt::Key_Y: - setValue(item, yes); - break; - default: - Parent::keyPressEvent(ev); - return; - } - ev->accept(); -} - -void ConfigList::contentsMousePressEvent(QMouseEvent* e) -{ - //QPoint p(contentsToViewport(e->pos())); - //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); - Parent::contentsMousePressEvent(e); -} - -void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) -{ - QPoint p(contentsToViewport(e->pos())); - ConfigItem* item = (ConfigItem*)itemAt(p); - struct menu *menu; - enum prop_type ptype; - const QPixmap* pm; - int idx, x; - - if (!item) - goto skip; - - menu = item->menu; - x = header()->offset() + p.x(); - idx = colRevMap[header()->sectionAt(x)]; - switch (idx) { - case promptColIdx: - pm = item->pixmap(promptColIdx); - if (pm) { - int off = header()->sectionPos(0) + itemMargin() + - treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); - if (x >= off && x < off + pm->width()) { - if (item->goParent) { - emit parentSelected(); - break; - } else if (!menu) - break; - ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; - if (ptype == P_MENU && rootEntry != menu && - mode != fullMode && mode != menuMode) - emit menuSelected(menu); - else - changeValue(item); - } - } - break; - case noColIdx: - setValue(item, no); - break; - case modColIdx: - setValue(item, mod); - break; - case yesColIdx: - setValue(item, yes); - break; - case dataColIdx: - changeValue(item); - break; - } - -skip: - //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); - Parent::contentsMouseReleaseEvent(e); -} - -void ConfigList::contentsMouseMoveEvent(QMouseEvent* e) -{ - //QPoint p(contentsToViewport(e->pos())); - //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); - Parent::contentsMouseMoveEvent(e); -} - -void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) -{ - QPoint p(contentsToViewport(e->pos())); - ConfigItem* item = (ConfigItem*)itemAt(p); - struct menu *menu; - enum prop_type ptype; - - if (!item) - goto skip; - if (item->goParent) { - emit parentSelected(); - goto skip; - } - menu = item->menu; - if (!menu) - goto skip; - ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; - if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) - emit menuSelected(menu); - else if (menu->sym) - changeValue(item); - -skip: - //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); - Parent::contentsMouseDoubleClickEvent(e); -} - -void ConfigList::focusInEvent(QFocusEvent *e) -{ - struct menu *menu = NULL; - - Parent::focusInEvent(e); - - ConfigItem* item = (ConfigItem *)currentItem(); - if (item) { - setSelected(item, TRUE); - menu = item->menu; - } - emit gotFocus(menu); -} - -void ConfigList::contextMenuEvent(QContextMenuEvent *e) -{ - if (e->y() <= header()->geometry().bottom()) { - if (!headerPopup) { - Q3Action *action; - - headerPopup = new Q3PopupMenu(this); - action = new Q3Action(NULL, _("Show Name"), 0, this); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowName(bool))); - connect(parent(), SIGNAL(showNameChanged(bool)), - action, SLOT(setOn(bool))); - action->setOn(showName); - action->addTo(headerPopup); - action = new Q3Action(NULL, _("Show Range"), 0, this); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowRange(bool))); - connect(parent(), SIGNAL(showRangeChanged(bool)), - action, SLOT(setOn(bool))); - action->setOn(showRange); - action->addTo(headerPopup); - action = new Q3Action(NULL, _("Show Data"), 0, this); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowData(bool))); - connect(parent(), SIGNAL(showDataChanged(bool)), - action, SLOT(setOn(bool))); - action->setOn(showData); - action->addTo(headerPopup); - } - headerPopup->exec(e->globalPos()); - e->accept(); - } else - e->ignore(); -} - -ConfigView*ConfigView::viewList; -QAction *ConfigView::showNormalAction; -QAction *ConfigView::showAllAction; -QAction *ConfigView::showPromptAction; - -ConfigView::ConfigView(QWidget* parent, const char *name) - : Parent(parent, name) -{ - list = new ConfigList(this, name); - lineEdit = new ConfigLineEdit(this); - lineEdit->hide(); - - this->nextView = viewList; - viewList = this; -} - -ConfigView::~ConfigView(void) -{ - ConfigView** vp; - - for (vp = &viewList; *vp; vp = &(*vp)->nextView) { - if (*vp == this) { - *vp = nextView; - break; - } - } -} - -void ConfigView::setOptionMode(QAction *act) -{ - if (act == showNormalAction) - list->optMode = normalOpt; - else if (act == showAllAction) - list->optMode = allOpt; - else - list->optMode = promptOpt; - - list->updateListAll(); -} - -void ConfigView::setShowName(bool b) -{ - if (list->showName != b) { - list->showName = b; - list->reinit(); - emit showNameChanged(b); - } -} - -void ConfigView::setShowRange(bool b) -{ - if (list->showRange != b) { - list->showRange = b; - list->reinit(); - emit showRangeChanged(b); - } -} - -void ConfigView::setShowData(bool b) -{ - if (list->showData != b) { - list->showData = b; - list->reinit(); - emit showDataChanged(b); - } -} - -void ConfigList::setAllOpen(bool open) -{ - Q3ListViewItemIterator it(this); - - for (; it.current(); it++) - it.current()->setOpen(open); -} - -void ConfigView::updateList(ConfigItem* item) -{ - ConfigView* v; - - for (v = viewList; v; v = v->nextView) - v->list->updateList(item); -} - -void ConfigView::updateListAll(void) -{ - ConfigView* v; - - for (v = viewList; v; v = v->nextView) - v->list->updateListAll(); -} - -ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) - : Parent(parent, name), sym(0), _menu(0) -{ - if (name) { - configSettings->beginGroup(name); - _showDebug = configSettings->readBoolEntry("/showDebug", false); - configSettings->endGroup(); - connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); - } -} - -void ConfigInfoView::saveSettings(void) -{ - if (name()) { - configSettings->beginGroup(name()); - configSettings->writeEntry("/showDebug", showDebug()); - configSettings->endGroup(); - } -} - -void ConfigInfoView::setShowDebug(bool b) -{ - if (_showDebug != b) { - _showDebug = b; - if (_menu) - menuInfo(); - else if (sym) - symbolInfo(); - emit showDebugChanged(b); - } -} - -void ConfigInfoView::setInfo(struct menu *m) -{ - if (_menu == m) - return; - _menu = m; - sym = NULL; - if (!_menu) - clear(); - else - menuInfo(); -} - -void ConfigInfoView::symbolInfo(void) -{ - QString str; - - str += "Symbol: "; - str += print_filter(sym->name); - str += "

value: "; - str += print_filter(sym_get_string_value(sym)); - str += "
visibility: "; - str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; - str += "
"; - str += debug_info(sym); - - setText(str); -} - -void ConfigInfoView::menuInfo(void) -{ - struct symbol* sym; - QString head, debug, help; - - sym = _menu->sym; - if (sym) { - if (_menu->prompt) { - head += ""; - head += print_filter(_(_menu->prompt->text)); - head += ""; - if (sym->name) { - head += " ("; - if (showDebug()) - head += QString().sprintf("", sym); - head += print_filter(sym->name); - if (showDebug()) - head += ""; - head += ")"; - } - } else if (sym->name) { - head += ""; - if (showDebug()) - head += QString().sprintf("", sym); - head += print_filter(sym->name); - if (showDebug()) - head += ""; - head += ""; - } - head += "

"; - - if (showDebug()) - debug = debug_info(sym); - - struct gstr help_gstr = str_new(); - menu_get_ext_help(_menu, &help_gstr); - help = print_filter(str_get(&help_gstr)); - str_free(&help_gstr); - } else if (_menu->prompt) { - head += ""; - head += print_filter(_(_menu->prompt->text)); - head += "

"; - if (showDebug()) { - if (_menu->prompt->visible.expr) { - debug += "  dep: "; - expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); - debug += "

"; - } - } - } - if (showDebug()) - debug += QString().sprintf("defined at %s:%d

", _menu->file->name, _menu->lineno); - - setText(head + debug + help); -} - -QString ConfigInfoView::debug_info(struct symbol *sym) -{ - QString debug; - - debug += "type: "; - debug += print_filter(sym_type_name(sym->type)); - if (sym_is_choice(sym)) - debug += " (choice)"; - debug += "
"; - if (sym->rev_dep.expr) { - debug += "reverse dep: "; - expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); - debug += "
"; - } - for (struct property *prop = sym->prop; prop; prop = prop->next) { - switch (prop->type) { - case P_PROMPT: - case P_MENU: - debug += QString().sprintf("prompt: ", prop->menu); - debug += print_filter(_(prop->text)); - debug += "
"; - break; - case P_DEFAULT: - case P_SELECT: - case P_RANGE: - case P_ENV: - debug += prop_get_type_name(prop->type); - debug += ": "; - expr_print(prop->expr, expr_print_help, &debug, E_NONE); - debug += "
"; - break; - case P_CHOICE: - if (sym_is_choice(sym)) { - debug += "choice: "; - expr_print(prop->expr, expr_print_help, &debug, E_NONE); - debug += "
"; - } - break; - default: - debug += "unknown property: "; - debug += prop_get_type_name(prop->type); - debug += "
"; - } - if (prop->visible.expr) { - debug += "    dep: "; - expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); - debug += "
"; - } - } - debug += "
"; - - return debug; -} - -QString ConfigInfoView::print_filter(const QString &str) -{ - QRegExp re("[<>&\"\\n]"); - QString res = str; - for (int i = 0; (i = res.find(re, i)) >= 0;) { - switch (res[i].latin1()) { - case '<': - res.replace(i, 1, "<"); - i += 4; - break; - case '>': - res.replace(i, 1, ">"); - i += 4; - break; - case '&': - res.replace(i, 1, "&"); - i += 5; - break; - case '"': - res.replace(i, 1, """); - i += 6; - break; - case '\n': - res.replace(i, 1, "
"); - i += 4; - break; - } - } - return res; -} - -void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) -{ - QString* text = reinterpret_cast(data); - QString str2 = print_filter(str); - - if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { - *text += QString().sprintf("", sym); - *text += str2; - *text += ""; - } else - *text += str2; -} - -Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) -{ - Q3PopupMenu* popup = Parent::createPopupMenu(pos); - Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); - connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); - action->setOn(showDebug()); - popup->insertSeparator(); - action->addTo(popup); - return popup; -} - -void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e) -{ - Parent::contentsContextMenuEvent(e); -} - -ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) - : Parent(parent, name), result(NULL) -{ - setCaption("Search Config"); - - QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); - QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); - layout2->addWidget(new QLabel(_("Find:"), this)); - editField = new QLineEdit(this); - connect(editField, SIGNAL(returnPressed()), SLOT(search())); - layout2->addWidget(editField); - searchButton = new QPushButton(_("Search"), this); - searchButton->setAutoDefault(FALSE); - connect(searchButton, SIGNAL(clicked()), SLOT(search())); - layout2->addWidget(searchButton); - layout1->addLayout(layout2); - - split = new QSplitter(this); - split->setOrientation(Qt::Vertical); - list = new ConfigView(split, name); - list->list->mode = listMode; - info = new ConfigInfoView(split, name); - connect(list->list, SIGNAL(menuChanged(struct menu *)), - info, SLOT(setInfo(struct menu *))); - connect(list->list, SIGNAL(menuChanged(struct menu *)), - parent, SLOT(setMenuLink(struct menu *))); - - layout1->addWidget(split); - - if (name) { - int x, y, width, height; - bool ok; - - configSettings->beginGroup(name); - width = configSettings->readNumEntry("/window width", parent->width() / 2); - height = configSettings->readNumEntry("/window height", parent->height() / 2); - resize(width, height); - x = configSettings->readNumEntry("/window x", 0, &ok); - if (ok) - y = configSettings->readNumEntry("/window y", 0, &ok); - if (ok) - move(x, y); - Q3ValueList sizes = configSettings->readSizes("/split", &ok); - if (ok) - split->setSizes(sizes); - configSettings->endGroup(); - connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); - } -} - -void ConfigSearchWindow::saveSettings(void) -{ - if (name()) { - configSettings->beginGroup(name()); - configSettings->writeEntry("/window x", pos().x()); - configSettings->writeEntry("/window y", pos().y()); - configSettings->writeEntry("/window width", size().width()); - configSettings->writeEntry("/window height", size().height()); - configSettings->writeSizes("/split", split->sizes()); - configSettings->endGroup(); - } -} - -void ConfigSearchWindow::search(void) -{ - struct symbol **p; - struct property *prop; - ConfigItem *lastItem = NULL; - - free(result); - list->list->clear(); - info->clear(); - - result = sym_re_search(editField->text().latin1()); - if (!result) - return; - for (p = result; *p; p++) { - for_all_prompts((*p), prop) - lastItem = new ConfigItem(list->list, lastItem, prop->menu, - menu_is_visible(prop->menu)); - } -} - -/* - * Construct the complete config widget - */ -ConfigMainWindow::ConfigMainWindow(void) - : searchWindow(0) -{ - QMenuBar* menu; - bool ok; - int x, y, width, height; - char title[256]; - - QDesktopWidget *d = configApp->desktop(); - snprintf(title, sizeof(title), "%s%s", - rootmenu.prompt->text, -#if QT_VERSION < 0x040000 - " (Qt3)" -#else - "" -#endif - ); - setCaption(title); - - width = configSettings->readNumEntry("/window width", d->width() - 64); - height = configSettings->readNumEntry("/window height", d->height() - 64); - resize(width, height); - x = configSettings->readNumEntry("/window x", 0, &ok); - if (ok) - y = configSettings->readNumEntry("/window y", 0, &ok); - if (ok) - move(x, y); - - split1 = new QSplitter(this); - split1->setOrientation(Qt::Horizontal); - setCentralWidget(split1); - - menuView = new ConfigView(split1, "menu"); - menuList = menuView->list; - - split2 = new QSplitter(split1); - split2->setOrientation(Qt::Vertical); - - // create config tree - configView = new ConfigView(split2, "config"); - configList = configView->list; - - helpText = new ConfigInfoView(split2, "help"); - helpText->setTextFormat(Qt::RichText); - - setTabOrder(configList, helpText); - configList->setFocus(); - - menu = menuBar(); - toolBar = new Q3ToolBar("Tools", this); - - backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this); - connect(backAction, SIGNAL(activated()), SLOT(goBack())); - backAction->setEnabled(FALSE); - Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this); - connect(quitAction, SIGNAL(activated()), SLOT(close())); - Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this); - connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); - saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this); - connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); - conf_set_changed_callback(conf_changed); - // Set saveAction's initial state - conf_changed(); - Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this); - connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); - Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this); - connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); - Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this); - connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); - Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this); - connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); - Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this); - connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); - - Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this); - showNameAction->setToggleAction(TRUE); - connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); - connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); - showNameAction->setOn(configView->showName()); - Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this); - showRangeAction->setToggleAction(TRUE); - connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); - connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); - showRangeAction->setOn(configList->showRange); - Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this); - showDataAction->setToggleAction(TRUE); - connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); - connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); - showDataAction->setOn(configList->showData); - - QActionGroup *optGroup = new QActionGroup(this); - optGroup->setExclusive(TRUE); - connect(optGroup, SIGNAL(selected(QAction *)), configView, - SLOT(setOptionMode(QAction *))); - connect(optGroup, SIGNAL(selected(QAction *)), menuView, - SLOT(setOptionMode(QAction *))); - -#if QT_VERSION >= 0x040000 - configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup); - configView->showAllAction = new QAction(_("Show All Options"), optGroup); - configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup); -#else - configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup); - configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup); - configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup); -#endif - configView->showNormalAction->setToggleAction(TRUE); - configView->showNormalAction->setOn(configList->optMode == normalOpt); - configView->showAllAction->setToggleAction(TRUE); - configView->showAllAction->setOn(configList->optMode == allOpt); - configView->showPromptAction->setToggleAction(TRUE); - configView->showPromptAction->setOn(configList->optMode == promptOpt); - - Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this); - showDebugAction->setToggleAction(TRUE); - connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); - connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); - showDebugAction->setOn(helpText->showDebug()); - - Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this); - connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); - Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this); - connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); - - // init tool bar - backAction->addTo(toolBar); - toolBar->addSeparator(); - loadAction->addTo(toolBar); - saveAction->addTo(toolBar); - toolBar->addSeparator(); - singleViewAction->addTo(toolBar); - splitViewAction->addTo(toolBar); - fullViewAction->addTo(toolBar); - - // create config menu - Q3PopupMenu* config = new Q3PopupMenu(this); - menu->insertItem(_("&File"), config); - loadAction->addTo(config); - saveAction->addTo(config); - saveAsAction->addTo(config); - config->insertSeparator(); - quitAction->addTo(config); - - // create edit menu - Q3PopupMenu* editMenu = new Q3PopupMenu(this); - menu->insertItem(_("&Edit"), editMenu); - searchAction->addTo(editMenu); - - // create options menu - Q3PopupMenu* optionMenu = new Q3PopupMenu(this); - menu->insertItem(_("&Option"), optionMenu); - showNameAction->addTo(optionMenu); - showRangeAction->addTo(optionMenu); - showDataAction->addTo(optionMenu); - optionMenu->insertSeparator(); - optGroup->addTo(optionMenu); - optionMenu->insertSeparator(); - - // create help menu - Q3PopupMenu* helpMenu = new Q3PopupMenu(this); - menu->insertSeparator(); - menu->insertItem(_("&Help"), helpMenu); - showIntroAction->addTo(helpMenu); - showAboutAction->addTo(helpMenu); - - connect(configList, SIGNAL(menuChanged(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); - connect(configList, SIGNAL(menuSelected(struct menu *)), - SLOT(changeMenu(struct menu *))); - connect(configList, SIGNAL(parentSelected()), - SLOT(goBack())); - connect(menuList, SIGNAL(menuChanged(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); - connect(menuList, SIGNAL(menuSelected(struct menu *)), - SLOT(changeMenu(struct menu *))); - - connect(configList, SIGNAL(gotFocus(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); - connect(menuList, SIGNAL(gotFocus(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); - connect(menuList, SIGNAL(gotFocus(struct menu *)), - SLOT(listFocusChanged(void))); - connect(helpText, SIGNAL(menuSelected(struct menu *)), - SLOT(setMenuLink(struct menu *))); - - QString listMode = configSettings->readEntry("/listMode", "symbol"); - if (listMode == "single") - showSingleView(); - else if (listMode == "full") - showFullView(); - else /*if (listMode == "split")*/ - showSplitView(); - - // UI setup done, restore splitter positions - Q3ValueList sizes = configSettings->readSizes("/split1", &ok); - if (ok) - split1->setSizes(sizes); - - sizes = configSettings->readSizes("/split2", &ok); - if (ok) - split2->setSizes(sizes); -} - -void ConfigMainWindow::loadConfig(void) -{ - QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this); - if (s.isNull()) - return; - if (conf_read(QFile::encodeName(s))) - QMessageBox::information(this, "qconf", _("Unable to load configuration!")); - ConfigView::updateListAll(); -} - -void ConfigMainWindow::saveConfig(void) -{ - if (conf_write(NULL)) - QMessageBox::information(this, "qconf", _("Unable to save configuration!")); -} - -void ConfigMainWindow::saveConfigAs(void) -{ - QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this); - if (s.isNull()) - return; - if (conf_write(QFile::encodeName(s))) - QMessageBox::information(this, "qconf", _("Unable to save configuration!")); -} - -void ConfigMainWindow::searchConfig(void) -{ - if (!searchWindow) - searchWindow = new ConfigSearchWindow(this, "search"); - searchWindow->show(); -} - -void ConfigMainWindow::changeMenu(struct menu *menu) -{ - configList->setRootMenu(menu); - if (configList->rootEntry->parent == &rootmenu) - backAction->setEnabled(FALSE); - else - backAction->setEnabled(TRUE); -} - -void ConfigMainWindow::setMenuLink(struct menu *menu) -{ - struct menu *parent; - ConfigList* list = NULL; - ConfigItem* item; - - if (configList->menuSkip(menu)) - return; - - switch (configList->mode) { - case singleMode: - list = configList; - parent = menu_get_parent_menu(menu); - if (!parent) - return; - list->setRootMenu(parent); - break; - case symbolMode: - if (menu->flags & MENU_ROOT) { - configList->setRootMenu(menu); - configList->clearSelection(); - list = menuList; - } else { - list = configList; - parent = menu_get_parent_menu(menu->parent); - if (!parent) - return; - item = menuList->findConfigItem(parent); - if (item) { - menuList->setSelected(item, TRUE); - menuList->ensureItemVisible(item); - } - list->setRootMenu(parent); - } - break; - case fullMode: - list = configList; - break; - default: - break; - } - - if (list) { - item = list->findConfigItem(menu); - if (item) { - list->setSelected(item, TRUE); - list->ensureItemVisible(item); - list->setFocus(); - } - } -} - -void ConfigMainWindow::listFocusChanged(void) -{ - if (menuList->mode == menuMode) - configList->clearSelection(); -} - -void ConfigMainWindow::goBack(void) -{ - ConfigItem* item; - - configList->setParentMenu(); - if (configList->rootEntry == &rootmenu) - backAction->setEnabled(FALSE); - item = (ConfigItem*)menuList->selectedItem(); - while (item) { - if (item->menu == configList->rootEntry) { - menuList->setSelected(item, TRUE); - break; - } - item = (ConfigItem*)item->parent(); - } -} - -void ConfigMainWindow::showSingleView(void) -{ - menuView->hide(); - menuList->setRootMenu(0); - configList->mode = singleMode; - if (configList->rootEntry == &rootmenu) - configList->updateListAll(); - else - configList->setRootMenu(&rootmenu); - configList->setAllOpen(TRUE); - configList->setFocus(); -} - -void ConfigMainWindow::showSplitView(void) -{ - configList->mode = symbolMode; - if (configList->rootEntry == &rootmenu) - configList->updateListAll(); - else - configList->setRootMenu(&rootmenu); - configList->setAllOpen(TRUE); - configApp->processEvents(); - menuList->mode = menuMode; - menuList->setRootMenu(&rootmenu); - menuList->setAllOpen(TRUE); - menuView->show(); - menuList->setFocus(); -} - -void ConfigMainWindow::showFullView(void) -{ - menuView->hide(); - menuList->setRootMenu(0); - configList->mode = fullMode; - if (configList->rootEntry == &rootmenu) - configList->updateListAll(); - else - configList->setRootMenu(&rootmenu); - configList->setAllOpen(FALSE); - configList->setFocus(); -} - -/* - * ask for saving configuration before quitting - * TODO ask only when something changed - */ -void ConfigMainWindow::closeEvent(QCloseEvent* e) -{ - if (!conf_get_changed()) { - e->accept(); - return; - } - QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); - mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); - mb.setButtonText(QMessageBox::No, _("&Discard Changes")); - mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); - switch (mb.exec()) { - case QMessageBox::Yes: - conf_write(NULL); - case QMessageBox::No: - e->accept(); - break; - case QMessageBox::Cancel: - e->ignore(); - break; - } -} - -void ConfigMainWindow::showIntro(void) -{ - static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n" - "For each option, a blank box indicates the feature is disabled, a check\n" - "indicates it is enabled, and a dot indicates that it is to be compiled\n" - "as a module. Clicking on the box will cycle through the three states.\n\n" - "If you do not see an option (e.g., a device driver) that you believe\n" - "should be present, try turning on Show All Options under the Options menu.\n" - "Although there is no cross reference yet to help you figure out what other\n" - "options must be enabled to support the option you are interested in, you can\n" - "still view the help of a grayed-out option.\n\n" - "Toggling Show Debug Info under the Options menu will show the dependencies,\n" - "which you can then match by examining other options.\n\n"); - - QMessageBox::information(this, "qconf", str); -} - -void ConfigMainWindow::showAbout(void) -{ - static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel .\n\n" - "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); - - QMessageBox::information(this, "qconf", str); -} - -void ConfigMainWindow::saveSettings(void) -{ - configSettings->writeEntry("/window x", pos().x()); - configSettings->writeEntry("/window y", pos().y()); - configSettings->writeEntry("/window width", size().width()); - configSettings->writeEntry("/window height", size().height()); - - QString entry; - switch(configList->mode) { - case singleMode : - entry = "single"; - break; - - case symbolMode : - entry = "split"; - break; - - case fullMode : - entry = "full"; - break; - - default: - break; - } - configSettings->writeEntry("/listMode", entry); - - configSettings->writeSizes("/split1", split1->sizes()); - configSettings->writeSizes("/split2", split2->sizes()); -} - -void ConfigMainWindow::conf_changed(void) -{ - if (saveAction) - saveAction->setEnabled(conf_get_changed()); -} - -void fixup_rootmenu(struct menu *menu) -{ - struct menu *child; - static int menu_cnt = 0; - - menu->flags |= MENU_ROOT; - for (child = menu->list; child; child = child->next) { - if (child->prompt && child->prompt->type == P_MENU) { - menu_cnt++; - fixup_rootmenu(child); - menu_cnt--; - } else if (!menu_cnt) - fixup_rootmenu(child); - } -} - -static const char *progname; - -static void usage(void) -{ - printf(_("%s \n"), progname); - exit(0); -} - -int main(int ac, char** av) -{ - ConfigMainWindow* v; - const char *name; - - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - -#ifndef LKC_DIRECT_LINK - kconfig_load(); -#endif - - progname = av[0]; - configApp = new QApplication(ac, av); - if (ac > 1 && av[1][0] == '-') { - switch (av[1][1]) { - case 'h': - case '?': - usage(); - } - name = av[2]; - } else - name = av[1]; - if (!name) - usage(); - - conf_parse(name); - fixup_rootmenu(&rootmenu); - conf_read(NULL); - //zconfdump(stdout); - - configSettings = new ConfigSettings(); - configSettings->beginGroup("/kconfig/qconf"); - v = new ConfigMainWindow(); - - //zconfdump(stdout); - configApp->setMainWidget(v); - configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); - configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); - v->show(); - configApp->exec(); - - configSettings->endGroup(); - delete configSettings; - - return 0; -} diff -Nru seabios-1.7.1/tools/kconfig/qconf.h seabios-1.7.4/tools/kconfig/qconf.h --- seabios-1.7.1/tools/kconfig/qconf.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/qconf.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#if QT_VERSION < 0x040000 -#include -#else -#include -#endif -#include - -#if QT_VERSION < 0x040000 -#define Q3ValueList QValueList -#define Q3PopupMenu QPopupMenu -#define Q3ListView QListView -#define Q3ListViewItem QListViewItem -#define Q3VBox QVBox -#define Q3TextBrowser QTextBrowser -#define Q3MainWindow QMainWindow -#define Q3Action QAction -#define Q3ToolBar QToolBar -#define Q3ListViewItemIterator QListViewItemIterator -#define Q3FileDialog QFileDialog -#endif - -class ConfigView; -class ConfigList; -class ConfigItem; -class ConfigLineEdit; -class ConfigMainWindow; - -class ConfigSettings : public QSettings { -public: - Q3ValueList readSizes(const QString& key, bool *ok); - bool writeSizes(const QString& key, const Q3ValueList& value); -}; - -enum colIdx { - promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr -}; -enum listMode { - singleMode, menuMode, symbolMode, fullMode, listMode -}; -enum optionMode { - normalOpt = 0, allOpt, promptOpt -}; - -class ConfigList : public Q3ListView { - Q_OBJECT - typedef class Q3ListView Parent; -public: - ConfigList(ConfigView* p, const char *name = 0); - void reinit(void); - ConfigView* parent(void) const - { - return (ConfigView*)Parent::parent(); - } - ConfigItem* findConfigItem(struct menu *); - -protected: - void keyPressEvent(QKeyEvent *e); - void contentsMousePressEvent(QMouseEvent *e); - void contentsMouseReleaseEvent(QMouseEvent *e); - void contentsMouseMoveEvent(QMouseEvent *e); - void contentsMouseDoubleClickEvent(QMouseEvent *e); - void focusInEvent(QFocusEvent *e); - void contextMenuEvent(QContextMenuEvent *e); - -public slots: - void setRootMenu(struct menu *menu); - - void updateList(ConfigItem *item); - void setValue(ConfigItem* item, tristate val); - void changeValue(ConfigItem* item); - void updateSelection(void); - void saveSettings(void); -signals: - void menuChanged(struct menu *menu); - void menuSelected(struct menu *menu); - void parentSelected(void); - void gotFocus(struct menu *); - -public: - void updateListAll(void) - { - updateAll = true; - updateList(NULL); - updateAll = false; - } - ConfigList* listView() - { - return this; - } - ConfigItem* firstChild() const - { - return (ConfigItem *)Parent::firstChild(); - } - int mapIdx(colIdx idx) - { - return colMap[idx]; - } - void addColumn(colIdx idx, const QString& label) - { - colMap[idx] = Parent::addColumn(label); - colRevMap[colMap[idx]] = idx; - } - void removeColumn(colIdx idx) - { - int col = colMap[idx]; - if (col >= 0) { - Parent::removeColumn(col); - colRevMap[col] = colMap[idx] = -1; - } - } - void setAllOpen(bool open); - void setParentMenu(void); - - bool menuSkip(struct menu *); - - template - void updateMenuList(P*, struct menu*); - - bool updateAll; - - QPixmap symbolYesPix, symbolModPix, symbolNoPix; - QPixmap choiceYesPix, choiceNoPix; - QPixmap menuPix, menuInvPix, menuBackPix, voidPix; - - bool showName, showRange, showData; - enum listMode mode; - enum optionMode optMode; - struct menu *rootEntry; - QColorGroup disabledColorGroup; - QColorGroup inactivedColorGroup; - Q3PopupMenu* headerPopup; - -private: - int colMap[colNr]; - int colRevMap[colNr]; -}; - -class ConfigItem : public Q3ListViewItem { - typedef class Q3ListViewItem Parent; -public: - ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v) - : Parent(parent, after), menu(m), visible(v), goParent(false) - { - init(); - } - ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) - : Parent(parent, after), menu(m), visible(v), goParent(false) - { - init(); - } - ConfigItem(Q3ListView *parent, ConfigItem *after, bool v) - : Parent(parent, after), menu(0), visible(v), goParent(true) - { - init(); - } - ~ConfigItem(void); - void init(void); - void okRename(int col); - void updateMenu(void); - void testUpdateMenu(bool v); - ConfigList* listView() const - { - return (ConfigList*)Parent::listView(); - } - ConfigItem* firstChild() const - { - return (ConfigItem *)Parent::firstChild(); - } - ConfigItem* nextSibling() const - { - return (ConfigItem *)Parent::nextSibling(); - } - void setText(colIdx idx, const QString& text) - { - Parent::setText(listView()->mapIdx(idx), text); - } - QString text(colIdx idx) const - { - return Parent::text(listView()->mapIdx(idx)); - } - void setPixmap(colIdx idx, const QPixmap& pm) - { - Parent::setPixmap(listView()->mapIdx(idx), pm); - } - const QPixmap* pixmap(colIdx idx) const - { - return Parent::pixmap(listView()->mapIdx(idx)); - } - void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align); - - ConfigItem* nextItem; - struct menu *menu; - bool visible; - bool goParent; -}; - -class ConfigLineEdit : public QLineEdit { - Q_OBJECT - typedef class QLineEdit Parent; -public: - ConfigLineEdit(ConfigView* parent); - ConfigView* parent(void) const - { - return (ConfigView*)Parent::parent(); - } - void show(ConfigItem *i); - void keyPressEvent(QKeyEvent *e); - -public: - ConfigItem *item; -}; - -class ConfigView : public Q3VBox { - Q_OBJECT - typedef class Q3VBox Parent; -public: - ConfigView(QWidget* parent, const char *name = 0); - ~ConfigView(void); - static void updateList(ConfigItem* item); - static void updateListAll(void); - - bool showName(void) const { return list->showName; } - bool showRange(void) const { return list->showRange; } - bool showData(void) const { return list->showData; } -public slots: - void setShowName(bool); - void setShowRange(bool); - void setShowData(bool); - void setOptionMode(QAction *); -signals: - void showNameChanged(bool); - void showRangeChanged(bool); - void showDataChanged(bool); -public: - ConfigList* list; - ConfigLineEdit* lineEdit; - - static ConfigView* viewList; - ConfigView* nextView; - - static QAction *showNormalAction; - static QAction *showAllAction; - static QAction *showPromptAction; -}; - -class ConfigInfoView : public Q3TextBrowser { - Q_OBJECT - typedef class Q3TextBrowser Parent; -public: - ConfigInfoView(QWidget* parent, const char *name = 0); - bool showDebug(void) const { return _showDebug; } - -public slots: - void setInfo(struct menu *menu); - void saveSettings(void); - void setShowDebug(bool); - -signals: - void showDebugChanged(bool); - void menuSelected(struct menu *); - -protected: - void symbolInfo(void); - void menuInfo(void); - QString debug_info(struct symbol *sym); - static QString print_filter(const QString &str); - static void expr_print_help(void *data, struct symbol *sym, const char *str); - Q3PopupMenu* createPopupMenu(const QPoint& pos); - void contentsContextMenuEvent(QContextMenuEvent *e); - - struct symbol *sym; - struct menu *_menu; - bool _showDebug; -}; - -class ConfigSearchWindow : public QDialog { - Q_OBJECT - typedef class QDialog Parent; -public: - ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0); - -public slots: - void saveSettings(void); - void search(void); - -protected: - QLineEdit* editField; - QPushButton* searchButton; - QSplitter* split; - ConfigView* list; - ConfigInfoView* info; - - struct symbol **result; -}; - -class ConfigMainWindow : public Q3MainWindow { - Q_OBJECT - - static Q3Action *saveAction; - static void conf_changed(void); -public: - ConfigMainWindow(void); -public slots: - void changeMenu(struct menu *); - void setMenuLink(struct menu *); - void listFocusChanged(void); - void goBack(void); - void loadConfig(void); - void saveConfig(void); - void saveConfigAs(void); - void searchConfig(void); - void showSingleView(void); - void showSplitView(void); - void showFullView(void); - void showIntro(void); - void showAbout(void); - void saveSettings(void); - -protected: - void closeEvent(QCloseEvent *e); - - ConfigSearchWindow *searchWindow; - ConfigView *menuView; - ConfigList *menuList; - ConfigView *configView; - ConfigList *configList; - ConfigInfoView *helpText; - Q3ToolBar *toolBar; - Q3Action *backAction; - QSplitter* split1; - QSplitter* split2; -}; diff -Nru seabios-1.7.1/tools/kconfig/symbol.c seabios-1.7.4/tools/kconfig/symbol.c --- seabios-1.7.1/tools/kconfig/symbol.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/symbol.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1260 +0,0 @@ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -struct symbol symbol_yes = { - .name = "y", - .curr = { "y", yes }, - .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_mod = { - .name = "m", - .curr = { "m", mod }, - .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_no = { - .name = "n", - .curr = { "n", no }, - .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_empty = { - .name = "", - .curr = { "", no }, - .flags = SYMBOL_VALID, -}; - -struct symbol *sym_defconfig_list; -struct symbol *modules_sym; -tristate modules_val; - -struct expr *sym_env_list; - -static void sym_add_default(struct symbol *sym, const char *def) -{ - struct property *prop = prop_alloc(P_DEFAULT, sym); - - prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); -} - -void sym_init(void) -{ - struct symbol *sym; - struct utsname uts; - static bool inited = false; - - if (inited) - return; - inited = true; - - uname(&uts); - - sym = sym_lookup("UNAME_RELEASE", 0); - sym->type = S_STRING; - sym->flags |= SYMBOL_AUTO; - sym_add_default(sym, uts.release); -} - -enum symbol_type sym_get_type(struct symbol *sym) -{ - enum symbol_type type = sym->type; - - if (type == S_TRISTATE) { - if (sym_is_choice_value(sym) && sym->visible == yes) - type = S_BOOLEAN; - else if (modules_val == no) - type = S_BOOLEAN; - } - return type; -} - -const char *sym_type_name(enum symbol_type type) -{ - switch (type) { - case S_BOOLEAN: - return "boolean"; - case S_TRISTATE: - return "tristate"; - case S_INT: - return "integer"; - case S_HEX: - return "hex"; - case S_STRING: - return "string"; - case S_UNKNOWN: - return "unknown"; - case S_OTHER: - break; - } - return "???"; -} - -struct property *sym_get_choice_prop(struct symbol *sym) -{ - struct property *prop; - - for_all_choices(sym, prop) - return prop; - return NULL; -} - -struct property *sym_get_env_prop(struct symbol *sym) -{ - struct property *prop; - - for_all_properties(sym, prop, P_ENV) - return prop; - return NULL; -} - -struct property *sym_get_default_prop(struct symbol *sym) -{ - struct property *prop; - - for_all_defaults(sym, prop) { - prop->visible.tri = expr_calc_value(prop->visible.expr); - if (prop->visible.tri != no) - return prop; - } - return NULL; -} - -static struct property *sym_get_range_prop(struct symbol *sym) -{ - struct property *prop; - - for_all_properties(sym, prop, P_RANGE) { - prop->visible.tri = expr_calc_value(prop->visible.expr); - if (prop->visible.tri != no) - return prop; - } - return NULL; -} - -static int sym_get_range_val(struct symbol *sym, int base) -{ - sym_calc_value(sym); - switch (sym->type) { - case S_INT: - base = 10; - break; - case S_HEX: - base = 16; - break; - default: - break; - } - return strtol(sym->curr.val, NULL, base); -} - -static void sym_validate_range(struct symbol *sym) -{ - struct property *prop; - int base, val, val2; - char str[64]; - - switch (sym->type) { - case S_INT: - base = 10; - break; - case S_HEX: - base = 16; - break; - default: - return; - } - prop = sym_get_range_prop(sym); - if (!prop) - return; - val = strtol(sym->curr.val, NULL, base); - val2 = sym_get_range_val(prop->expr->left.sym, base); - if (val >= val2) { - val2 = sym_get_range_val(prop->expr->right.sym, base); - if (val <= val2) - return; - } - if (sym->type == S_INT) - sprintf(str, "%d", val2); - else - sprintf(str, "0x%x", val2); - sym->curr.val = strdup(str); -} - -static void sym_calc_visibility(struct symbol *sym) -{ - struct property *prop; - tristate tri; - - /* any prompt visible? */ - tri = no; - for_all_prompts(sym, prop) { - prop->visible.tri = expr_calc_value(prop->visible.expr); - tri = EXPR_OR(tri, prop->visible.tri); - } - if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) - tri = yes; - if (sym->visible != tri) { - sym->visible = tri; - sym_set_changed(sym); - } - if (sym_is_choice_value(sym)) - return; - /* defaulting to "yes" if no explicit "depends on" are given */ - tri = yes; - if (sym->dir_dep.expr) - tri = expr_calc_value(sym->dir_dep.expr); - if (tri == mod) - tri = yes; - if (sym->dir_dep.tri != tri) { - sym->dir_dep.tri = tri; - sym_set_changed(sym); - } - tri = no; - if (sym->rev_dep.expr) - tri = expr_calc_value(sym->rev_dep.expr); - if (tri == mod && sym_get_type(sym) == S_BOOLEAN) - tri = yes; - if (sym->rev_dep.tri != tri) { - sym->rev_dep.tri = tri; - sym_set_changed(sym); - } -} - -/* - * Find the default symbol for a choice. - * First try the default values for the choice symbol - * Next locate the first visible choice value - * Return NULL if none was found - */ -struct symbol *sym_choice_default(struct symbol *sym) -{ - struct symbol *def_sym; - struct property *prop; - struct expr *e; - - /* any of the defaults visible? */ - for_all_defaults(sym, prop) { - prop->visible.tri = expr_calc_value(prop->visible.expr); - if (prop->visible.tri == no) - continue; - def_sym = prop_get_symbol(prop); - if (def_sym->visible != no) - return def_sym; - } - - /* just get the first visible value */ - prop = sym_get_choice_prop(sym); - expr_list_for_each_sym(prop->expr, e, def_sym) - if (def_sym->visible != no) - return def_sym; - - /* failed to locate any defaults */ - return NULL; -} - -static struct symbol *sym_calc_choice(struct symbol *sym) -{ - struct symbol *def_sym; - struct property *prop; - struct expr *e; - - /* first calculate all choice values' visibilities */ - prop = sym_get_choice_prop(sym); - expr_list_for_each_sym(prop->expr, e, def_sym) - sym_calc_visibility(def_sym); - - /* is the user choice visible? */ - def_sym = sym->def[S_DEF_USER].val; - if (def_sym && def_sym->visible != no) - return def_sym; - - def_sym = sym_choice_default(sym); - - if (def_sym == NULL) - /* no choice? reset tristate value */ - sym->curr.tri = no; - - return def_sym; -} - -void sym_calc_value(struct symbol *sym) -{ - struct symbol_value newval, oldval; - struct property *prop; - struct expr *e; - - if (!sym) - return; - - if (sym->flags & SYMBOL_VALID) - return; - sym->flags |= SYMBOL_VALID; - - oldval = sym->curr; - - switch (sym->type) { - case S_INT: - case S_HEX: - case S_STRING: - newval = symbol_empty.curr; - break; - case S_BOOLEAN: - case S_TRISTATE: - newval = symbol_no.curr; - break; - default: - sym->curr.val = sym->name; - sym->curr.tri = no; - return; - } - if (!sym_is_choice_value(sym)) - sym->flags &= ~SYMBOL_WRITE; - - sym_calc_visibility(sym); - - /* set default if recursively called */ - sym->curr = newval; - - switch (sym_get_type(sym)) { - case S_BOOLEAN: - case S_TRISTATE: - if (sym_is_choice_value(sym) && sym->visible == yes) { - prop = sym_get_choice_prop(sym); - newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; - } else { - if (sym->visible != no) { - /* if the symbol is visible use the user value - * if available, otherwise try the default value - */ - sym->flags |= SYMBOL_WRITE; - if (sym_has_value(sym)) { - newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, - sym->visible); - goto calc_newval; - } - } - if (sym->rev_dep.tri != no) - sym->flags |= SYMBOL_WRITE; - if (!sym_is_choice(sym)) { - prop = sym_get_default_prop(sym); - if (prop) { - sym->flags |= SYMBOL_WRITE; - newval.tri = EXPR_AND(expr_calc_value(prop->expr), - prop->visible.tri); - } - } - calc_newval: - if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { - struct expr *e; - e = expr_simplify_unmet_dep(sym->rev_dep.expr, - sym->dir_dep.expr); - fprintf(stderr, "warning: ("); - expr_fprint(e, stderr); - fprintf(stderr, ") selects %s which has unmet direct dependencies (", - sym->name); - expr_fprint(sym->dir_dep.expr, stderr); - fprintf(stderr, ")\n"); - expr_free(e); - } - newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); - } - if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) - newval.tri = yes; - break; - case S_STRING: - case S_HEX: - case S_INT: - if (sym->visible != no) { - sym->flags |= SYMBOL_WRITE; - if (sym_has_value(sym)) { - newval.val = sym->def[S_DEF_USER].val; - break; - } - } - prop = sym_get_default_prop(sym); - if (prop) { - struct symbol *ds = prop_get_symbol(prop); - if (ds) { - sym->flags |= SYMBOL_WRITE; - sym_calc_value(ds); - newval.val = ds->curr.val; - } - } - break; - default: - ; - } - - sym->curr = newval; - if (sym_is_choice(sym) && newval.tri == yes) - sym->curr.val = sym_calc_choice(sym); - sym_validate_range(sym); - - if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { - sym_set_changed(sym); - if (modules_sym == sym) { - sym_set_all_changed(); - modules_val = modules_sym->curr.tri; - } - } - - if (sym_is_choice(sym)) { - struct symbol *choice_sym; - - prop = sym_get_choice_prop(sym); - expr_list_for_each_sym(prop->expr, e, choice_sym) { - if ((sym->flags & SYMBOL_WRITE) && - choice_sym->visible != no) - choice_sym->flags |= SYMBOL_WRITE; - if (sym->flags & SYMBOL_CHANGED) - sym_set_changed(choice_sym); - } - } - - if (sym->flags & SYMBOL_AUTO) - sym->flags &= ~SYMBOL_WRITE; -} - -void sym_clear_all_valid(void) -{ - struct symbol *sym; - int i; - - for_all_symbols(i, sym) - sym->flags &= ~SYMBOL_VALID; - sym_add_change_count(1); - if (modules_sym) - sym_calc_value(modules_sym); -} - -void sym_set_changed(struct symbol *sym) -{ - struct property *prop; - - sym->flags |= SYMBOL_CHANGED; - for (prop = sym->prop; prop; prop = prop->next) { - if (prop->menu) - prop->menu->flags |= MENU_CHANGED; - } -} - -void sym_set_all_changed(void) -{ - struct symbol *sym; - int i; - - for_all_symbols(i, sym) - sym_set_changed(sym); -} - -bool sym_tristate_within_range(struct symbol *sym, tristate val) -{ - int type = sym_get_type(sym); - - if (sym->visible == no) - return false; - - if (type != S_BOOLEAN && type != S_TRISTATE) - return false; - - if (type == S_BOOLEAN && val == mod) - return false; - if (sym->visible <= sym->rev_dep.tri) - return false; - if (sym_is_choice_value(sym) && sym->visible == yes) - return val == yes; - return val >= sym->rev_dep.tri && val <= sym->visible; -} - -bool sym_set_tristate_value(struct symbol *sym, tristate val) -{ - tristate oldval = sym_get_tristate_value(sym); - - if (oldval != val && !sym_tristate_within_range(sym, val)) - return false; - - if (!(sym->flags & SYMBOL_DEF_USER)) { - sym->flags |= SYMBOL_DEF_USER; - sym_set_changed(sym); - } - /* - * setting a choice value also resets the new flag of the choice - * symbol and all other choice values. - */ - if (sym_is_choice_value(sym) && val == yes) { - struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); - struct property *prop; - struct expr *e; - - cs->def[S_DEF_USER].val = sym; - cs->flags |= SYMBOL_DEF_USER; - prop = sym_get_choice_prop(cs); - for (e = prop->expr; e; e = e->left.expr) { - if (e->right.sym->visible != no) - e->right.sym->flags |= SYMBOL_DEF_USER; - } - } - - sym->def[S_DEF_USER].tri = val; - if (oldval != val) - sym_clear_all_valid(); - - return true; -} - -tristate sym_toggle_tristate_value(struct symbol *sym) -{ - tristate oldval, newval; - - oldval = newval = sym_get_tristate_value(sym); - do { - switch (newval) { - case no: - newval = mod; - break; - case mod: - newval = yes; - break; - case yes: - newval = no; - break; - } - if (sym_set_tristate_value(sym, newval)) - break; - } while (oldval != newval); - return newval; -} - -bool sym_string_valid(struct symbol *sym, const char *str) -{ - signed char ch; - - switch (sym->type) { - case S_STRING: - return true; - case S_INT: - ch = *str++; - if (ch == '-') - ch = *str++; - if (!isdigit(ch)) - return false; - if (ch == '0' && *str != 0) - return false; - while ((ch = *str++)) { - if (!isdigit(ch)) - return false; - } - return true; - case S_HEX: - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) - str += 2; - ch = *str++; - do { - if (!isxdigit(ch)) - return false; - } while ((ch = *str++)); - return true; - case S_BOOLEAN: - case S_TRISTATE: - switch (str[0]) { - case 'y': case 'Y': - case 'm': case 'M': - case 'n': case 'N': - return true; - } - return false; - default: - return false; - } -} - -bool sym_string_within_range(struct symbol *sym, const char *str) -{ - struct property *prop; - int val; - - switch (sym->type) { - case S_STRING: - return sym_string_valid(sym, str); - case S_INT: - if (!sym_string_valid(sym, str)) - return false; - prop = sym_get_range_prop(sym); - if (!prop) - return true; - val = strtol(str, NULL, 10); - return val >= sym_get_range_val(prop->expr->left.sym, 10) && - val <= sym_get_range_val(prop->expr->right.sym, 10); - case S_HEX: - if (!sym_string_valid(sym, str)) - return false; - prop = sym_get_range_prop(sym); - if (!prop) - return true; - val = strtol(str, NULL, 16); - return val >= sym_get_range_val(prop->expr->left.sym, 16) && - val <= sym_get_range_val(prop->expr->right.sym, 16); - case S_BOOLEAN: - case S_TRISTATE: - switch (str[0]) { - case 'y': case 'Y': - return sym_tristate_within_range(sym, yes); - case 'm': case 'M': - return sym_tristate_within_range(sym, mod); - case 'n': case 'N': - return sym_tristate_within_range(sym, no); - } - return false; - default: - return false; - } -} - -bool sym_set_string_value(struct symbol *sym, const char *newval) -{ - const char *oldval; - char *val; - int size; - - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (newval[0]) { - case 'y': case 'Y': - return sym_set_tristate_value(sym, yes); - case 'm': case 'M': - return sym_set_tristate_value(sym, mod); - case 'n': case 'N': - return sym_set_tristate_value(sym, no); - } - return false; - default: - ; - } - - if (!sym_string_within_range(sym, newval)) - return false; - - if (!(sym->flags & SYMBOL_DEF_USER)) { - sym->flags |= SYMBOL_DEF_USER; - sym_set_changed(sym); - } - - oldval = sym->def[S_DEF_USER].val; - size = strlen(newval) + 1; - if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { - size += 2; - sym->def[S_DEF_USER].val = val = malloc(size); - *val++ = '0'; - *val++ = 'x'; - } else if (!oldval || strcmp(oldval, newval)) - sym->def[S_DEF_USER].val = val = malloc(size); - else - return true; - - strcpy(val, newval); - free((void *)oldval); - sym_clear_all_valid(); - - return true; -} - -/* - * Find the default value associated to a symbol. - * For tristate symbol handle the modules=n case - * in which case "m" becomes "y". - * If the symbol does not have any default then fallback - * to the fixed default values. - */ -const char *sym_get_string_default(struct symbol *sym) -{ - struct property *prop; - struct symbol *ds; - const char *str; - tristate val; - - sym_calc_visibility(sym); - sym_calc_value(modules_sym); - val = symbol_no.curr.tri; - str = symbol_empty.curr.val; - - /* If symbol has a default value look it up */ - prop = sym_get_default_prop(sym); - if (prop != NULL) { - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - /* The visibility may limit the value from yes => mod */ - val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); - break; - default: - /* - * The following fails to handle the situation - * where a default value is further limited by - * the valid range. - */ - ds = prop_get_symbol(prop); - if (ds != NULL) { - sym_calc_value(ds); - str = (const char *)ds->curr.val; - } - } - } - - /* Handle select statements */ - val = EXPR_OR(val, sym->rev_dep.tri); - - /* transpose mod to yes if modules are not enabled */ - if (val == mod) - if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no) - val = yes; - - /* transpose mod to yes if type is bool */ - if (sym->type == S_BOOLEAN && val == mod) - val = yes; - - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (val) { - case no: return "n"; - case mod: return "m"; - case yes: return "y"; - } - case S_INT: - case S_HEX: - return str; - case S_STRING: - return str; - case S_OTHER: - case S_UNKNOWN: - break; - } - return ""; -} - -const char *sym_get_string_value(struct symbol *sym) -{ - tristate val; - - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - val = sym_get_tristate_value(sym); - switch (val) { - case no: - return "n"; - case mod: - return "m"; - case yes: - return "y"; - } - break; - default: - ; - } - return (const char *)sym->curr.val; -} - -bool sym_is_changable(struct symbol *sym) -{ - return sym->visible > sym->rev_dep.tri; -} - -static unsigned strhash(const char *s) -{ - /* fnv32 hash */ - unsigned hash = 2166136261U; - for (; *s; s++) - hash = (hash ^ *s) * 0x01000193; - return hash; -} - -struct symbol *sym_lookup(const char *name, int flags) -{ - struct symbol *symbol; - char *new_name; - int hash; - - if (name) { - if (name[0] && !name[1]) { - switch (name[0]) { - case 'y': return &symbol_yes; - case 'm': return &symbol_mod; - case 'n': return &symbol_no; - } - } - hash = strhash(name) % SYMBOL_HASHSIZE; - - for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { - if (symbol->name && - !strcmp(symbol->name, name) && - (flags ? symbol->flags & flags - : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) - return symbol; - } - new_name = strdup(name); - } else { - new_name = NULL; - hash = 0; - } - - symbol = malloc(sizeof(*symbol)); - memset(symbol, 0, sizeof(*symbol)); - symbol->name = new_name; - symbol->type = S_UNKNOWN; - symbol->flags |= flags; - - symbol->next = symbol_hash[hash]; - symbol_hash[hash] = symbol; - - return symbol; -} - -struct symbol *sym_find(const char *name) -{ - struct symbol *symbol = NULL; - int hash = 0; - - if (!name) - return NULL; - - if (name[0] && !name[1]) { - switch (name[0]) { - case 'y': return &symbol_yes; - case 'm': return &symbol_mod; - case 'n': return &symbol_no; - } - } - hash = strhash(name) % SYMBOL_HASHSIZE; - - for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { - if (symbol->name && - !strcmp(symbol->name, name) && - !(symbol->flags & SYMBOL_CONST)) - break; - } - - return symbol; -} - -/* - * Expand symbol's names embedded in the string given in argument. Symbols' - * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to - * the empty string. - */ -const char *sym_expand_string_value(const char *in) -{ - const char *src; - char *res; - size_t reslen; - - reslen = strlen(in) + 1; - res = malloc(reslen); - res[0] = '\0'; - - while ((src = strchr(in, '$'))) { - char *p, name[SYMBOL_MAXLENGTH]; - const char *symval = ""; - struct symbol *sym; - size_t newlen; - - strncat(res, in, src - in); - src++; - - p = name; - while (isalnum(*src) || *src == '_') - *p++ = *src++; - *p = '\0'; - - sym = sym_find(name); - if (sym != NULL) { - sym_calc_value(sym); - symval = sym_get_string_value(sym); - } - - newlen = strlen(res) + strlen(symval) + strlen(src) + 1; - if (newlen > reslen) { - reslen = newlen; - res = realloc(res, reslen); - } - - strcat(res, symval); - in = src; - } - strcat(res, in); - - return res; -} - -struct symbol **sym_re_search(const char *pattern) -{ - struct symbol *sym, **sym_arr = NULL; - int i, cnt, size; - regex_t re; - - cnt = size = 0; - /* Skip if empty */ - if (strlen(pattern) == 0) - return NULL; - if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) - return NULL; - - for_all_symbols(i, sym) { - if (sym->flags & SYMBOL_CONST || !sym->name) - continue; - if (regexec(&re, sym->name, 0, NULL, 0)) - continue; - if (cnt + 1 >= size) { - void *tmp = sym_arr; - size += 16; - sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); - if (!sym_arr) { - free(tmp); - return NULL; - } - } - sym_calc_value(sym); - sym_arr[cnt++] = sym; - } - if (sym_arr) - sym_arr[cnt] = NULL; - regfree(&re); - - return sym_arr; -} - -/* - * When we check for recursive dependencies we use a stack to save - * current state so we can print out relevant info to user. - * The entries are located on the call stack so no need to free memory. - * Note inser() remove() must always match to properly clear the stack. - */ -static struct dep_stack { - struct dep_stack *prev, *next; - struct symbol *sym; - struct property *prop; - struct expr *expr; -} *check_top; - -static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) -{ - memset(stack, 0, sizeof(*stack)); - if (check_top) - check_top->next = stack; - stack->prev = check_top; - stack->sym = sym; - check_top = stack; -} - -static void dep_stack_remove(void) -{ - check_top = check_top->prev; - if (check_top) - check_top->next = NULL; -} - -/* - * Called when we have detected a recursive dependency. - * check_top point to the top of the stact so we use - * the ->prev pointer to locate the bottom of the stack. - */ -static void sym_check_print_recursive(struct symbol *last_sym) -{ - struct dep_stack *stack; - struct symbol *sym, *next_sym; - struct menu *menu = NULL; - struct property *prop; - struct dep_stack cv_stack; - - if (sym_is_choice_value(last_sym)) { - dep_stack_insert(&cv_stack, last_sym); - last_sym = prop_get_symbol(sym_get_choice_prop(last_sym)); - } - - for (stack = check_top; stack != NULL; stack = stack->prev) - if (stack->sym == last_sym) - break; - if (!stack) { - fprintf(stderr, "unexpected recursive dependency error\n"); - return; - } - - for (; stack; stack = stack->next) { - sym = stack->sym; - next_sym = stack->next ? stack->next->sym : last_sym; - prop = stack->prop; - if (prop == NULL) - prop = stack->sym->prop; - - /* for choice values find the menu entry (used below) */ - if (sym_is_choice(sym) || sym_is_choice_value(sym)) { - for (prop = sym->prop; prop; prop = prop->next) { - menu = prop->menu; - if (prop->menu) - break; - } - } - if (stack->sym == last_sym) - fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", - prop->file->name, prop->lineno); - if (stack->expr) { - fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", - prop->file->name, prop->lineno, - sym->name ? sym->name : "", - prop_get_type_name(prop->type), - next_sym->name ? next_sym->name : ""); - } else if (stack->prop) { - fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", - prop->file->name, prop->lineno, - sym->name ? sym->name : "", - next_sym->name ? next_sym->name : ""); - } else if (sym_is_choice(sym)) { - fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", - menu->file->name, menu->lineno, - sym->name ? sym->name : "", - next_sym->name ? next_sym->name : ""); - } else if (sym_is_choice_value(sym)) { - fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", - menu->file->name, menu->lineno, - sym->name ? sym->name : "", - next_sym->name ? next_sym->name : ""); - } else { - fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", - prop->file->name, prop->lineno, - sym->name ? sym->name : "", - next_sym->name ? next_sym->name : ""); - } - } - - if (check_top == &cv_stack) - dep_stack_remove(); -} - -static struct symbol *sym_check_expr_deps(struct expr *e) -{ - struct symbol *sym; - - if (!e) - return NULL; - switch (e->type) { - case E_OR: - case E_AND: - sym = sym_check_expr_deps(e->left.expr); - if (sym) - return sym; - return sym_check_expr_deps(e->right.expr); - case E_NOT: - return sym_check_expr_deps(e->left.expr); - case E_EQUAL: - case E_UNEQUAL: - sym = sym_check_deps(e->left.sym); - if (sym) - return sym; - return sym_check_deps(e->right.sym); - case E_SYMBOL: - return sym_check_deps(e->left.sym); - default: - break; - } - printf("Oops! How to check %d?\n", e->type); - return NULL; -} - -/* return NULL when dependencies are OK */ -static struct symbol *sym_check_sym_deps(struct symbol *sym) -{ - struct symbol *sym2; - struct property *prop; - struct dep_stack stack; - - dep_stack_insert(&stack, sym); - - sym2 = sym_check_expr_deps(sym->rev_dep.expr); - if (sym2) - goto out; - - for (prop = sym->prop; prop; prop = prop->next) { - if (prop->type == P_CHOICE || prop->type == P_SELECT) - continue; - stack.prop = prop; - sym2 = sym_check_expr_deps(prop->visible.expr); - if (sym2) - break; - if (prop->type != P_DEFAULT || sym_is_choice(sym)) - continue; - stack.expr = prop->expr; - sym2 = sym_check_expr_deps(prop->expr); - if (sym2) - break; - stack.expr = NULL; - } - -out: - dep_stack_remove(); - - return sym2; -} - -static struct symbol *sym_check_choice_deps(struct symbol *choice) -{ - struct symbol *sym, *sym2; - struct property *prop; - struct expr *e; - struct dep_stack stack; - - dep_stack_insert(&stack, choice); - - prop = sym_get_choice_prop(choice); - expr_list_for_each_sym(prop->expr, e, sym) - sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); - - choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); - sym2 = sym_check_sym_deps(choice); - choice->flags &= ~SYMBOL_CHECK; - if (sym2) - goto out; - - expr_list_for_each_sym(prop->expr, e, sym) { - sym2 = sym_check_sym_deps(sym); - if (sym2) - break; - } -out: - expr_list_for_each_sym(prop->expr, e, sym) - sym->flags &= ~SYMBOL_CHECK; - - if (sym2 && sym_is_choice_value(sym2) && - prop_get_symbol(sym_get_choice_prop(sym2)) == choice) - sym2 = choice; - - dep_stack_remove(); - - return sym2; -} - -struct symbol *sym_check_deps(struct symbol *sym) -{ - struct symbol *sym2; - struct property *prop; - - if (sym->flags & SYMBOL_CHECK) { - sym_check_print_recursive(sym); - return sym; - } - if (sym->flags & SYMBOL_CHECKED) - return NULL; - - if (sym_is_choice_value(sym)) { - struct dep_stack stack; - - /* for choice groups start the check with main choice symbol */ - dep_stack_insert(&stack, sym); - prop = sym_get_choice_prop(sym); - sym2 = sym_check_deps(prop_get_symbol(prop)); - dep_stack_remove(); - } else if (sym_is_choice(sym)) { - sym2 = sym_check_choice_deps(sym); - } else { - sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); - sym2 = sym_check_sym_deps(sym); - sym->flags &= ~SYMBOL_CHECK; - } - - if (sym2 && sym2 == sym) - sym2 = NULL; - - return sym2; -} - -struct property *prop_alloc(enum prop_type type, struct symbol *sym) -{ - struct property *prop; - struct property **propp; - - prop = malloc(sizeof(*prop)); - memset(prop, 0, sizeof(*prop)); - prop->type = type; - prop->sym = sym; - prop->file = current_file; - prop->lineno = zconf_lineno(); - - /* append property to the prop list of symbol */ - if (sym) { - for (propp = &sym->prop; *propp; propp = &(*propp)->next) - ; - *propp = prop; - } - - return prop; -} - -struct symbol *prop_get_symbol(struct property *prop) -{ - if (prop->expr && (prop->expr->type == E_SYMBOL || - prop->expr->type == E_LIST)) - return prop->expr->left.sym; - return NULL; -} - -const char *prop_get_type_name(enum prop_type type) -{ - switch (type) { - case P_PROMPT: - return "prompt"; - case P_ENV: - return "env"; - case P_COMMENT: - return "comment"; - case P_MENU: - return "menu"; - case P_DEFAULT: - return "default"; - case P_CHOICE: - return "choice"; - case P_SELECT: - return "select"; - case P_RANGE: - return "range"; - case P_SYMBOL: - return "symbol"; - case P_UNKNOWN: - break; - } - return "unknown"; -} - -static void prop_add_env(const char *env) -{ - struct symbol *sym, *sym2; - struct property *prop; - char *p; - - sym = current_entry->sym; - sym->flags |= SYMBOL_AUTO; - for_all_properties(sym, prop, P_ENV) { - sym2 = prop_get_symbol(prop); - if (strcmp(sym2->name, env)) - menu_warn(current_entry, "redefining environment symbol from %s", - sym2->name); - return; - } - - prop = prop_alloc(P_ENV, sym); - prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); - - sym_env_list = expr_alloc_one(E_LIST, sym_env_list); - sym_env_list->right.sym = sym; - - p = getenv(env); - if (p) - sym_add_default(sym, p); - else - menu_warn(current_entry, "environment variable %s undefined", env); -} diff -Nru seabios-1.7.1/tools/kconfig/util.c seabios-1.7.4/tools/kconfig/util.c --- seabios-1.7.1/tools/kconfig/util.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/util.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2002-2005 Roman Zippel - * Copyright (C) 2002-2005 Sam Ravnborg - * - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include "lkc.h" - -/* file already present in list? If not add it */ -struct file *file_lookup(const char *name) -{ - struct file *file; - const char *file_name = sym_expand_string_value(name); - - for (file = file_list; file; file = file->next) { - if (!strcmp(name, file->name)) { - free((void *)file_name); - return file; - } - } - - file = malloc(sizeof(*file)); - memset(file, 0, sizeof(*file)); - file->name = file_name; - file->next = file_list; - file_list = file; - return file; -} - -/* write a dependency file as used by kbuild to track dependencies */ -int file_write_dep(const char *name) -{ - struct symbol *sym, *env_sym; - struct expr *e; - struct file *file; - FILE *out; - - if (!name) - name = ".kconfig.d"; - out = fopen("..config.tmp", "w"); - if (!out) - return 1; - fprintf(out, "deps_config := \\\n"); - for (file = file_list; file; file = file->next) { - if (file->next) - fprintf(out, "\t%s \\\n", file->name); - else - fprintf(out, "\t%s\n", file->name); - } - fprintf(out, "\n%s: \\\n" - "\t$(deps_config)\n\n", conf_get_autoconfig_name()); - - expr_list_for_each_sym(sym_env_list, e, sym) { - struct property *prop; - const char *value; - - prop = sym_get_env_prop(sym); - env_sym = prop_get_symbol(prop); - if (!env_sym) - continue; - value = getenv(env_sym->name); - if (!value) - value = ""; - fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); - fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); - fprintf(out, "endif\n"); - } - - fprintf(out, "\n$(deps_config): ;\n"); - fclose(out); - rename("..config.tmp", name); - return 0; -} - - -/* Allocate initial growable string */ -struct gstr str_new(void) -{ - struct gstr gs; - gs.s = malloc(sizeof(char) * 64); - gs.len = 64; - gs.max_width = 0; - strcpy(gs.s, "\0"); - return gs; -} - -/* Allocate and assign growable string */ -struct gstr str_assign(const char *s) -{ - struct gstr gs; - gs.s = strdup(s); - gs.len = strlen(s) + 1; - gs.max_width = 0; - return gs; -} - -/* Free storage for growable string */ -void str_free(struct gstr *gs) -{ - if (gs->s) - free(gs->s); - gs->s = NULL; - gs->len = 0; -} - -/* Append to growable string */ -void str_append(struct gstr *gs, const char *s) -{ - size_t l; - if (s) { - l = strlen(gs->s) + strlen(s) + 1; - if (l > gs->len) { - gs->s = realloc(gs->s, l); - gs->len = l; - } - strcat(gs->s, s); - } -} - -/* Append printf formatted string to growable string */ -void str_printf(struct gstr *gs, const char *fmt, ...) -{ - va_list ap; - char s[10000]; /* big enough... */ - va_start(ap, fmt); - vsnprintf(s, sizeof(s), fmt, ap); - str_append(gs, s); - va_end(ap); -} - -/* Retrieve value of growable string */ -const char *str_get(struct gstr *gs) -{ - return gs->s; -} - diff -Nru seabios-1.7.1/tools/kconfig/zconf.gperf seabios-1.7.4/tools/kconfig/zconf.gperf --- seabios-1.7.1/tools/kconfig/zconf.gperf 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/zconf.gperf 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%language=ANSI-C -%define hash-function-name kconf_id_hash -%define lookup-function-name kconf_id_lookup -%define string-pool-name kconf_id_strings -%compare-strncmp -%enum -%pic -%struct-type - -struct kconf_id; - -static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); - -%% -mainmenu, T_MAINMENU, TF_COMMAND -menu, T_MENU, TF_COMMAND -endmenu, T_ENDMENU, TF_COMMAND -source, T_SOURCE, TF_COMMAND -choice, T_CHOICE, TF_COMMAND -endchoice, T_ENDCHOICE, TF_COMMAND -comment, T_COMMENT, TF_COMMAND -config, T_CONFIG, TF_COMMAND -menuconfig, T_MENUCONFIG, TF_COMMAND -help, T_HELP, TF_COMMAND -if, T_IF, TF_COMMAND|TF_PARAM -endif, T_ENDIF, TF_COMMAND -depends, T_DEPENDS, TF_COMMAND -optional, T_OPTIONAL, TF_COMMAND -default, T_DEFAULT, TF_COMMAND, S_UNKNOWN -prompt, T_PROMPT, TF_COMMAND -tristate, T_TYPE, TF_COMMAND, S_TRISTATE -def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE -bool, T_TYPE, TF_COMMAND, S_BOOLEAN -boolean, T_TYPE, TF_COMMAND, S_BOOLEAN -def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN -int, T_TYPE, TF_COMMAND, S_INT -hex, T_TYPE, TF_COMMAND, S_HEX -string, T_TYPE, TF_COMMAND, S_STRING -select, T_SELECT, TF_COMMAND -range, T_RANGE, TF_COMMAND -visible, T_VISIBLE, TF_COMMAND -option, T_OPTION, TF_COMMAND -on, T_ON, TF_PARAM -modules, T_OPT_MODULES, TF_OPTION -defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION -env, T_OPT_ENV, TF_OPTION -%% diff -Nru seabios-1.7.1/tools/kconfig/zconf.hash.c_shipped seabios-1.7.4/tools/kconfig/zconf.hash.c_shipped --- seabios-1.7.1/tools/kconfig/zconf.hash.c_shipped 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/zconf.hash.c_shipped 1970-01-01 00:00:00.000000000 +0000 @@ -1,245 +0,0 @@ -/* ANSI-C code produced by gperf version 3.0.3 */ -/* Command-line: gperf */ -/* Computed positions: -k'1,3' */ - -#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ - && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ - && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ - && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ - && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ - && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ - && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ - && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ - && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ - && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ - && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ - && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ - && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ - && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ - && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ - && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ - && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ - && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ - && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ - && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ - && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ - && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ - && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) -/* The character set is not based on ISO-646. */ -#error "gperf generated tables don't work with this execution character set. Please report a bug to ." -#endif - -struct kconf_id; - -static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); -/* maximum key range = 50, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static unsigned int -kconf_id_hash (register const char *str, register unsigned int len) -{ - static unsigned char asso_values[] = - { - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 40, 5, - 0, 0, 5, 52, 0, 20, 52, 52, 10, 20, - 5, 0, 35, 52, 0, 30, 0, 15, 0, 52, - 15, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52 - }; - register int hval = len; - - switch (hval) - { - default: - hval += asso_values[(unsigned char)str[2]]; - /*FALLTHROUGH*/ - case 2: - case 1: - hval += asso_values[(unsigned char)str[0]]; - break; - } - return hval; -} - -struct kconf_id_strings_t - { - char kconf_id_strings_str2[sizeof("on")]; - char kconf_id_strings_str3[sizeof("env")]; - char kconf_id_strings_str5[sizeof("endif")]; - char kconf_id_strings_str6[sizeof("option")]; - char kconf_id_strings_str7[sizeof("endmenu")]; - char kconf_id_strings_str8[sizeof("optional")]; - char kconf_id_strings_str9[sizeof("endchoice")]; - char kconf_id_strings_str10[sizeof("range")]; - char kconf_id_strings_str11[sizeof("choice")]; - char kconf_id_strings_str12[sizeof("default")]; - char kconf_id_strings_str13[sizeof("def_bool")]; - char kconf_id_strings_str14[sizeof("help")]; - char kconf_id_strings_str16[sizeof("config")]; - char kconf_id_strings_str17[sizeof("def_tristate")]; - char kconf_id_strings_str18[sizeof("hex")]; - char kconf_id_strings_str19[sizeof("defconfig_list")]; - char kconf_id_strings_str22[sizeof("if")]; - char kconf_id_strings_str23[sizeof("int")]; - char kconf_id_strings_str27[sizeof("modules")]; - char kconf_id_strings_str28[sizeof("tristate")]; - char kconf_id_strings_str29[sizeof("menu")]; - char kconf_id_strings_str32[sizeof("comment")]; - char kconf_id_strings_str35[sizeof("menuconfig")]; - char kconf_id_strings_str36[sizeof("string")]; - char kconf_id_strings_str37[sizeof("visible")]; - char kconf_id_strings_str41[sizeof("prompt")]; - char kconf_id_strings_str42[sizeof("depends")]; - char kconf_id_strings_str44[sizeof("bool")]; - char kconf_id_strings_str46[sizeof("select")]; - char kconf_id_strings_str47[sizeof("boolean")]; - char kconf_id_strings_str48[sizeof("mainmenu")]; - char kconf_id_strings_str51[sizeof("source")]; - }; -static struct kconf_id_strings_t kconf_id_strings_contents = - { - "on", - "env", - "endif", - "option", - "endmenu", - "optional", - "endchoice", - "range", - "choice", - "default", - "def_bool", - "help", - "config", - "def_tristate", - "hex", - "defconfig_list", - "if", - "int", - "modules", - "tristate", - "menu", - "comment", - "menuconfig", - "string", - "visible", - "prompt", - "depends", - "bool", - "select", - "boolean", - "mainmenu", - "source" - }; -#define kconf_id_strings ((const char *) &kconf_id_strings_contents) -#ifdef __GNUC__ -__inline -#ifdef __GNUC_STDC_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif -#endif -struct kconf_id * -kconf_id_lookup (register const char *str, register unsigned int len) -{ - enum - { - TOTAL_KEYWORDS = 32, - MIN_WORD_LENGTH = 2, - MAX_WORD_LENGTH = 14, - MIN_HASH_VALUE = 2, - MAX_HASH_VALUE = 51 - }; - - static struct kconf_id wordlist[] = - { - {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_OPT_ENV, TF_OPTION}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_CHOICE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_HEX}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION}, - {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT}, - {-1}, {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, - {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, - {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_TYPE, TF_COMMAND, S_STRING}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_VISIBLE, TF_COMMAND}, - {-1}, {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_PROMPT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_DEPENDS, TF_COMMAND}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str44, T_TYPE, TF_COMMAND, S_BOOLEAN}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_SELECT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND}, - {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_SOURCE, TF_COMMAND} - }; - - if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) - { - register int key = kconf_id_hash (str, len); - - if (key <= MAX_HASH_VALUE && key >= 0) - { - register int o = wordlist[key].name; - if (o >= 0) - { - register const char *s = o + kconf_id_strings; - - if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') - return &wordlist[key]; - } - } - } - return 0; -} - diff -Nru seabios-1.7.1/tools/kconfig/zconf.l seabios-1.7.4/tools/kconfig/zconf.l --- seabios-1.7.1/tools/kconfig/zconf.l 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/zconf.l 1970-01-01 00:00:00.000000000 +0000 @@ -1,360 +0,0 @@ -%option backup nostdinit noyywrap never-interactive full ecs -%option 8bit backup nodefault perf-report perf-report -%option noinput -%x COMMAND HELP STRING PARAM -%{ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -#define START_STRSIZE 16 - -static struct { - struct file *file; - int lineno; -} current_pos; - -static char *text; -static int text_size, text_asize; - -struct buffer { - struct buffer *parent; - YY_BUFFER_STATE state; -}; - -struct buffer *current_buf; - -static int last_ts, first_ts; - -static void zconf_endhelp(void); -static void zconf_endfile(void); - -static void new_string(void) -{ - text = malloc(START_STRSIZE); - text_asize = START_STRSIZE; - text_size = 0; - *text = 0; -} - -static void append_string(const char *str, int size) -{ - int new_size = text_size + size + 1; - if (new_size > text_asize) { - new_size += START_STRSIZE - 1; - new_size &= -START_STRSIZE; - text = realloc(text, new_size); - text_asize = new_size; - } - memcpy(text + text_size, str, size); - text_size += size; - text[text_size] = 0; -} - -static void alloc_string(const char *str, int size) -{ - text = malloc(size + 1); - memcpy(text, str, size); - text[size] = 0; -} -%} - -ws [ \n\t] -n [A-Za-z0-9_] - -%% - int str = 0; - int ts, i; - -[ \t]*#.*\n | -[ \t]*\n { - current_file->lineno++; - return T_EOL; -} -[ \t]*#.* - - -[ \t]+ { - BEGIN(COMMAND); -} - -. { - unput(yytext[0]); - BEGIN(COMMAND); -} - - -{ - {n}+ { - struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - BEGIN(PARAM); - current_pos.file = current_file; - current_pos.lineno = current_file->lineno; - if (id && id->flags & TF_COMMAND) { - zconflval.id = id; - return id->token; - } - alloc_string(yytext, yyleng); - zconflval.string = text; - return T_WORD; - } - . - \n { - BEGIN(INITIAL); - current_file->lineno++; - return T_EOL; - } -} - -{ - "&&" return T_AND; - "||" return T_OR; - "(" return T_OPEN_PAREN; - ")" return T_CLOSE_PAREN; - "!" return T_NOT; - "=" return T_EQUAL; - "!=" return T_UNEQUAL; - \"|\' { - str = yytext[0]; - new_string(); - BEGIN(STRING); - } - \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; - --- /* ignore */ - ({n}|[-/.])+ { - struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - if (id && id->flags & TF_PARAM) { - zconflval.id = id; - return id->token; - } - alloc_string(yytext, yyleng); - zconflval.string = text; - return T_WORD; - } - #.* /* comment */ - \\\n current_file->lineno++; - . - <> { - BEGIN(INITIAL); - } -} - -{ - [^'"\\\n]+/\n { - append_string(yytext, yyleng); - zconflval.string = text; - return T_WORD_QUOTE; - } - [^'"\\\n]+ { - append_string(yytext, yyleng); - } - \\.?/\n { - append_string(yytext + 1, yyleng - 1); - zconflval.string = text; - return T_WORD_QUOTE; - } - \\.? { - append_string(yytext + 1, yyleng - 1); - } - \'|\" { - if (str == yytext[0]) { - BEGIN(PARAM); - zconflval.string = text; - return T_WORD_QUOTE; - } else - append_string(yytext, 1); - } - \n { - printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); - current_file->lineno++; - BEGIN(INITIAL); - return T_EOL; - } - <> { - BEGIN(INITIAL); - } -} - -{ - [ \t]+ { - ts = 0; - for (i = 0; i < yyleng; i++) { - if (yytext[i] == '\t') - ts = (ts & ~7) + 8; - else - ts++; - } - last_ts = ts; - if (first_ts) { - if (ts < first_ts) { - zconf_endhelp(); - return T_HELPTEXT; - } - ts -= first_ts; - while (ts > 8) { - append_string(" ", 8); - ts -= 8; - } - append_string(" ", ts); - } - } - [ \t]*\n/[^ \t\n] { - current_file->lineno++; - zconf_endhelp(); - return T_HELPTEXT; - } - [ \t]*\n { - current_file->lineno++; - append_string("\n", 1); - } - [^ \t\n].* { - while (yyleng) { - if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) - break; - yyleng--; - } - append_string(yytext, yyleng); - if (!first_ts) - first_ts = last_ts; - } - <> { - zconf_endhelp(); - return T_HELPTEXT; - } -} - -<> { - if (current_file) { - zconf_endfile(); - return T_EOL; - } - fclose(yyin); - yyterminate(); -} - -%% -void zconf_starthelp(void) -{ - new_string(); - last_ts = first_ts = 0; - BEGIN(HELP); -} - -static void zconf_endhelp(void) -{ - zconflval.string = text; - BEGIN(INITIAL); -} - - -/* - * Try to open specified file with following names: - * ./name - * $(srctree)/name - * The latter is used when srctree is separate from objtree - * when compiling the kernel. - * Return NULL if file is not found. - */ -FILE *zconf_fopen(const char *name) -{ - char *env, fullname[PATH_MAX+1]; - FILE *f; - - f = fopen(name, "r"); - if (!f && name != NULL && name[0] != '/') { - env = getenv(SRCTREE); - if (env) { - sprintf(fullname, "%s/%s", env, name); - f = fopen(fullname, "r"); - } - } - return f; -} - -void zconf_initscan(const char *name) -{ - yyin = zconf_fopen(name); - if (!yyin) { - printf("can't find file %s\n", name); - exit(1); - } - - current_buf = malloc(sizeof(*current_buf)); - memset(current_buf, 0, sizeof(*current_buf)); - - current_file = file_lookup(name); - current_file->lineno = 1; - current_file->flags = FILE_BUSY; -} - -void zconf_nextfile(const char *name) -{ - struct file *file = file_lookup(name); - struct buffer *buf = malloc(sizeof(*buf)); - memset(buf, 0, sizeof(*buf)); - - current_buf->state = YY_CURRENT_BUFFER; - yyin = zconf_fopen(file->name); - if (!yyin) { - printf("%s:%d: can't open file \"%s\"\n", - zconf_curname(), zconf_lineno(), file->name); - exit(1); - } - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); - buf->parent = current_buf; - current_buf = buf; - - if (file->flags & FILE_BUSY) { - printf("%s:%d: do not source '%s' from itself\n", - zconf_curname(), zconf_lineno(), name); - exit(1); - } - if (file->flags & FILE_SCANNED) { - printf("%s:%d: file '%s' is already sourced from '%s'\n", - zconf_curname(), zconf_lineno(), name, - file->parent->name); - exit(1); - } - file->flags |= FILE_BUSY; - file->lineno = 1; - file->parent = current_file; - current_file = file; -} - -static void zconf_endfile(void) -{ - struct buffer *parent; - - current_file->flags |= FILE_SCANNED; - current_file->flags &= ~FILE_BUSY; - current_file = current_file->parent; - - parent = current_buf->parent; - if (parent) { - fclose(yyin); - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(parent->state); - } - free(current_buf); - current_buf = parent; -} - -int zconf_lineno(void) -{ - return current_pos.lineno; -} - -const char *zconf_curname(void) -{ - return current_pos.file ? current_pos.file->name : ""; -} diff -Nru seabios-1.7.1/tools/kconfig/zconf.tab.c_shipped seabios-1.7.4/tools/kconfig/zconf.tab.c_shipped --- seabios-1.7.1/tools/kconfig/zconf.tab.c_shipped 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/zconf.tab.c_shipped 1970-01-01 00:00:00.000000000 +0000 @@ -1,2505 +0,0 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - 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 3 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, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "2.4.1" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - -/* Using locations. */ -#define YYLSP_NEEDED 0 - -/* Substitute the variable and function names. */ -#define yyparse zconfparse -#define yylex zconflex -#define yyerror zconferror -#define yylval zconflval -#define yychar zconfchar -#define yydebug zconfdebug -#define yynerrs zconfnerrs - - -/* Copy the first part of user declarations. */ - - -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) - -#define PRINTD 0x0001 -#define DEBUG_PARSE 0x0002 - -int cdebug = PRINTD; - -extern int zconflex(void); -static void zconfprint(const char *err, ...); -static void zconf_error(const char *err, ...); -static void zconferror(const char *err); -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); - -struct symbol *symbol_hash[SYMBOL_HASHSIZE]; - -static struct menu *current_menu, *current_entry; - -#define YYDEBUG 0 -#if YYDEBUG -#define YYERROR_VERBOSE -#endif - - - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - T_MAINMENU = 258, - T_MENU = 259, - T_ENDMENU = 260, - T_SOURCE = 261, - T_CHOICE = 262, - T_ENDCHOICE = 263, - T_COMMENT = 264, - T_CONFIG = 265, - T_MENUCONFIG = 266, - T_HELP = 267, - T_HELPTEXT = 268, - T_IF = 269, - T_ENDIF = 270, - T_DEPENDS = 271, - T_OPTIONAL = 272, - T_PROMPT = 273, - T_TYPE = 274, - T_DEFAULT = 275, - T_SELECT = 276, - T_RANGE = 277, - T_VISIBLE = 278, - T_OPTION = 279, - T_ON = 280, - T_WORD = 281, - T_WORD_QUOTE = 282, - T_UNEQUAL = 283, - T_CLOSE_PAREN = 284, - T_OPEN_PAREN = 285, - T_EOL = 286, - T_OR = 287, - T_AND = 288, - T_EQUAL = 289, - T_NOT = 290 - }; -#endif - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -{ - - - char *string; - struct file *file; - struct symbol *symbol; - struct expr *expr; - struct menu *menu; - struct kconf_id *id; - - - -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - - -/* Copy the second part of user declarations. */ - - -/* Include zconf.hash.c here so it can see the token constants. */ -#include "zconf.hash.c" - - - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; -#else -typedef short int yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef YY_ -# define YY_(msgid) msgid -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) -#else -# define YYUSE(e) /* empty */ -#endif - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; -#endif -{ - return yyi; -} -#endif - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined _STDLIB_H \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 11 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 290 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 36 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 50 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 118 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 191 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 290 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35 -}; - -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint16 yyprhs[] = -{ - 0, 0, 3, 6, 8, 11, 13, 14, 17, 20, - 23, 26, 31, 36, 40, 42, 44, 46, 48, 50, - 52, 54, 56, 58, 60, 62, 64, 66, 68, 72, - 75, 79, 82, 86, 89, 90, 93, 96, 99, 102, - 105, 108, 112, 117, 122, 127, 133, 137, 138, 142, - 143, 146, 150, 153, 155, 159, 160, 163, 166, 169, - 172, 175, 180, 184, 187, 192, 193, 196, 200, 202, - 206, 207, 210, 213, 216, 220, 224, 228, 230, 234, - 235, 238, 241, 244, 248, 252, 255, 258, 261, 262, - 265, 268, 271, 276, 277, 280, 283, 286, 287, 290, - 292, 294, 297, 300, 303, 305, 308, 309, 312, 314, - 318, 322, 326, 329, 333, 337, 339, 341, 342 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 37, 0, -1, 81, 38, -1, 38, -1, 63, 39, - -1, 39, -1, -1, 39, 41, -1, 39, 55, -1, - 39, 67, -1, 39, 80, -1, 39, 26, 1, 31, - -1, 39, 40, 1, 31, -1, 39, 1, 31, -1, - 16, -1, 18, -1, 19, -1, 21, -1, 17, -1, - 22, -1, 20, -1, 23, -1, 31, -1, 61, -1, - 71, -1, 44, -1, 46, -1, 69, -1, 26, 1, - 31, -1, 1, 31, -1, 10, 26, 31, -1, 43, - 47, -1, 11, 26, 31, -1, 45, 47, -1, -1, - 47, 48, -1, 47, 49, -1, 47, 75, -1, 47, - 73, -1, 47, 42, -1, 47, 31, -1, 19, 78, - 31, -1, 18, 79, 82, 31, -1, 20, 83, 82, - 31, -1, 21, 26, 82, 31, -1, 22, 84, 84, - 82, 31, -1, 24, 50, 31, -1, -1, 50, 26, - 51, -1, -1, 34, 79, -1, 7, 85, 31, -1, - 52, 56, -1, 80, -1, 53, 58, 54, -1, -1, - 56, 57, -1, 56, 75, -1, 56, 73, -1, 56, - 31, -1, 56, 42, -1, 18, 79, 82, 31, -1, - 19, 78, 31, -1, 17, 31, -1, 20, 26, 82, - 31, -1, -1, 58, 41, -1, 14, 83, 81, -1, - 80, -1, 59, 62, 60, -1, -1, 62, 41, -1, - 62, 67, -1, 62, 55, -1, 3, 79, 81, -1, - 4, 79, 31, -1, 64, 76, 74, -1, 80, -1, - 65, 68, 66, -1, -1, 68, 41, -1, 68, 67, - -1, 68, 55, -1, 6, 79, 31, -1, 9, 79, - 31, -1, 70, 74, -1, 12, 31, -1, 72, 13, - -1, -1, 74, 75, -1, 74, 31, -1, 74, 42, - -1, 16, 25, 83, 31, -1, -1, 76, 77, -1, - 76, 31, -1, 23, 82, -1, -1, 79, 82, -1, - 26, -1, 27, -1, 5, 31, -1, 8, 31, -1, - 15, 31, -1, 31, -1, 81, 31, -1, -1, 14, - 83, -1, 84, -1, 84, 34, 84, -1, 84, 28, - 84, -1, 30, 83, 29, -1, 35, 83, -1, 83, - 32, 83, -1, 83, 33, 83, -1, 26, -1, 27, - -1, -1, 26, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 108, 108, 108, 110, 110, 112, 114, 115, 116, - 117, 118, 119, 123, 127, 127, 127, 127, 127, 127, - 127, 127, 131, 132, 133, 134, 135, 136, 140, 141, - 147, 155, 161, 169, 179, 181, 182, 183, 184, 185, - 186, 189, 197, 203, 213, 219, 225, 228, 230, 241, - 242, 247, 256, 261, 269, 272, 274, 275, 276, 277, - 278, 281, 287, 298, 304, 314, 316, 321, 329, 337, - 340, 342, 343, 344, 349, 356, 363, 368, 376, 379, - 381, 382, 383, 386, 394, 401, 408, 414, 421, 423, - 424, 425, 428, 436, 438, 439, 442, 449, 451, 456, - 457, 460, 461, 462, 466, 467, 470, 471, 474, 475, - 476, 477, 478, 479, 480, 483, 484, 487, 488 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", - "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", - "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", - "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", - "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", - "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", - "T_NOT", "$accept", "input", "start", "stmt_list", "option_name", - "common_stmt", "option_error", "config_entry_start", "config_stmt", - "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", - "config_option", "symbol_option", "symbol_option_list", - "symbol_option_arg", "choice", "choice_entry", "choice_end", - "choice_stmt", "choice_option_list", "choice_option", "choice_block", - "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu", - "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt", - "comment", "comment_stmt", "help_start", "help", "depends_list", - "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt", - "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0 -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290 -}; -# endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 36, 37, 37, 38, 38, 39, 39, 39, 39, - 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, - 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, - 43, 44, 45, 46, 47, 47, 47, 47, 47, 47, - 47, 48, 48, 48, 48, 48, 49, 50, 50, 51, - 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, - 56, 57, 57, 57, 57, 58, 58, 59, 60, 61, - 62, 62, 62, 62, 63, 64, 65, 66, 67, 68, - 68, 68, 68, 69, 70, 71, 72, 73, 74, 74, - 74, 74, 75, 76, 76, 76, 77, 78, 78, 79, - 79, 80, 80, 80, 81, 81, 82, 82, 83, 83, - 83, 83, 83, 83, 83, 84, 84, 85, 85 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 2, 1, 2, 1, 0, 2, 2, 2, - 2, 4, 4, 3, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, - 3, 2, 3, 2, 0, 2, 2, 2, 2, 2, - 2, 3, 4, 4, 4, 5, 3, 0, 3, 0, - 2, 3, 2, 1, 3, 0, 2, 2, 2, 2, - 2, 4, 3, 2, 4, 0, 2, 3, 1, 3, - 0, 2, 2, 2, 3, 3, 3, 1, 3, 0, - 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, - 2, 2, 4, 0, 2, 2, 2, 0, 2, 1, - 1, 2, 2, 2, 1, 2, 0, 2, 1, 3, - 3, 3, 2, 3, 3, 1, 1, 0, 1 -}; - -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 6, 0, 104, 0, 3, 0, 6, 6, 99, 100, - 0, 1, 0, 0, 0, 0, 117, 0, 0, 0, - 0, 0, 0, 14, 18, 15, 16, 20, 17, 19, - 21, 0, 22, 0, 7, 34, 25, 34, 26, 55, - 65, 8, 70, 23, 93, 79, 9, 27, 88, 24, - 10, 0, 105, 2, 74, 13, 0, 101, 0, 118, - 0, 102, 0, 0, 0, 115, 116, 0, 0, 0, - 108, 103, 0, 0, 0, 0, 0, 0, 0, 88, - 0, 0, 75, 83, 51, 84, 30, 32, 0, 112, - 0, 0, 67, 0, 0, 11, 12, 0, 0, 0, - 0, 97, 0, 0, 0, 47, 0, 40, 39, 35, - 36, 0, 38, 37, 0, 0, 97, 0, 59, 60, - 56, 58, 57, 66, 54, 53, 71, 73, 69, 72, - 68, 106, 95, 0, 94, 80, 82, 78, 81, 77, - 90, 91, 89, 111, 113, 114, 110, 109, 29, 86, - 0, 106, 0, 106, 106, 106, 0, 0, 0, 87, - 63, 106, 0, 106, 0, 96, 0, 0, 41, 98, - 0, 0, 106, 49, 46, 28, 0, 62, 0, 107, - 92, 42, 43, 44, 0, 0, 48, 61, 64, 45, - 50 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 3, 4, 5, 33, 34, 108, 35, 36, 37, - 38, 74, 109, 110, 157, 186, 39, 40, 124, 41, - 76, 120, 77, 42, 128, 43, 78, 6, 44, 45, - 137, 46, 80, 47, 48, 49, 111, 112, 81, 113, - 79, 134, 152, 153, 50, 7, 165, 69, 70, 60 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -90 -static const yytype_int16 yypact[] = -{ - 4, 42, -90, 96, -90, 111, -90, 15, -90, -90, - 75, -90, 82, 42, 104, 42, 110, 107, 42, 115, - 125, -4, 121, -90, -90, -90, -90, -90, -90, -90, - -90, 162, -90, 163, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, 139, -90, -90, 138, -90, 142, -90, 143, -90, - 152, -90, 164, 167, 168, -90, -90, -4, -4, 77, - -18, -90, 177, 185, 33, 71, 195, 247, 236, -2, - 236, 171, -90, -90, -90, -90, -90, -90, 41, -90, - -4, -4, 138, 97, 97, -90, -90, 186, 187, 194, - 42, 42, -4, 196, 97, -90, 219, -90, -90, -90, - -90, 210, -90, -90, 204, 42, 42, 199, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, 222, -90, 223, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, 215, -90, -90, -90, -90, -90, - -4, 222, 228, 222, -5, 222, 97, 35, 229, -90, - -90, 222, 232, 222, -4, -90, 135, 233, -90, -90, - 234, 235, 222, 240, -90, -90, 237, -90, 239, -13, - -90, -90, -90, -90, 244, 42, -90, -90, -90, -90, - -90 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -90, -90, 269, 271, -90, 23, -70, -90, -90, -90, - -90, 243, -90, -90, -90, -90, -90, -90, -90, -48, - -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -20, -90, -90, -90, -90, -90, 206, 205, -68, - -90, -90, 169, -1, 27, -7, 118, -66, -89, -90 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -86 -static const yytype_int16 yytable[] = -{ - 10, 88, 89, 54, 146, 147, 119, 1, 122, 164, - 93, 141, 56, 142, 58, 156, 94, 62, 1, 90, - 91, 131, 65, 66, 144, 145, 67, 90, 91, 132, - 127, 68, 136, -31, 97, 2, 154, -31, -31, -31, - -31, -31, -31, -31, -31, 98, 52, -31, -31, 99, - -31, 100, 101, 102, 103, 104, -31, 105, 129, 106, - 138, 173, 92, 141, 107, 142, 174, 172, 8, 9, - 143, -33, 97, 90, 91, -33, -33, -33, -33, -33, - -33, -33, -33, 98, 166, -33, -33, 99, -33, 100, - 101, 102, 103, 104, -33, 105, 11, 106, 179, 151, - 123, 126, 107, 135, 125, 130, 2, 139, 2, 90, - 91, -5, 12, 55, 161, 13, 14, 15, 16, 17, - 18, 19, 20, 65, 66, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 57, 59, 31, 61, -4, - 12, 63, 32, 13, 14, 15, 16, 17, 18, 19, - 20, 64, 71, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 72, 73, 31, 180, 90, 91, 52, - 32, -85, 97, 82, 83, -85, -85, -85, -85, -85, - -85, -85, -85, 84, 190, -85, -85, 99, -85, -85, - -85, -85, -85, -85, -85, 85, 97, 106, 86, 87, - -52, -52, 140, -52, -52, -52, -52, 98, 95, -52, - -52, 99, 114, 115, 116, 117, 96, 148, 149, 150, - 158, 106, 155, 159, 97, 163, 118, -76, -76, -76, - -76, -76, -76, -76, -76, 160, 164, -76, -76, 99, - 13, 14, 15, 16, 17, 18, 19, 20, 91, 106, - 21, 22, 14, 15, 140, 17, 18, 19, 20, 168, - 175, 21, 22, 177, 181, 182, 183, 32, 187, 167, - 188, 169, 170, 171, 185, 189, 53, 51, 32, 176, - 75, 178, 121, 0, 133, 162, 0, 0, 0, 0, - 184 -}; - -static const yytype_int16 yycheck[] = -{ - 1, 67, 68, 10, 93, 94, 76, 3, 76, 14, - 28, 81, 13, 81, 15, 104, 34, 18, 3, 32, - 33, 23, 26, 27, 90, 91, 30, 32, 33, 31, - 78, 35, 80, 0, 1, 31, 102, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 31, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 78, 26, - 80, 26, 69, 133, 31, 133, 31, 156, 26, 27, - 29, 0, 1, 32, 33, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 150, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 0, 26, 164, 100, - 77, 78, 31, 80, 77, 78, 31, 80, 31, 32, - 33, 0, 1, 31, 115, 4, 5, 6, 7, 8, - 9, 10, 11, 26, 27, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 31, 26, 26, 31, 0, - 1, 26, 31, 4, 5, 6, 7, 8, 9, 10, - 11, 26, 31, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 1, 1, 26, 31, 32, 33, 31, - 31, 0, 1, 31, 31, 4, 5, 6, 7, 8, - 9, 10, 11, 31, 185, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 31, 1, 26, 31, 31, - 5, 6, 31, 8, 9, 10, 11, 12, 31, 14, - 15, 16, 17, 18, 19, 20, 31, 31, 31, 25, - 1, 26, 26, 13, 1, 26, 31, 4, 5, 6, - 7, 8, 9, 10, 11, 31, 14, 14, 15, 16, - 4, 5, 6, 7, 8, 9, 10, 11, 33, 26, - 14, 15, 5, 6, 31, 8, 9, 10, 11, 31, - 31, 14, 15, 31, 31, 31, 31, 31, 31, 151, - 31, 153, 154, 155, 34, 31, 7, 6, 31, 161, - 37, 163, 76, -1, 79, 116, -1, -1, -1, -1, - 172 -}; - -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 3, 31, 37, 38, 39, 63, 81, 26, 27, - 79, 0, 1, 4, 5, 6, 7, 8, 9, 10, - 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 26, 31, 40, 41, 43, 44, 45, 46, 52, - 53, 55, 59, 61, 64, 65, 67, 69, 70, 71, - 80, 39, 31, 38, 81, 31, 79, 31, 79, 26, - 85, 31, 79, 26, 26, 26, 27, 30, 35, 83, - 84, 31, 1, 1, 47, 47, 56, 58, 62, 76, - 68, 74, 31, 31, 31, 31, 31, 31, 83, 83, - 32, 33, 81, 28, 34, 31, 31, 1, 12, 16, - 18, 19, 20, 21, 22, 24, 26, 31, 42, 48, - 49, 72, 73, 75, 17, 18, 19, 20, 31, 42, - 57, 73, 75, 41, 54, 80, 41, 55, 60, 67, - 80, 23, 31, 74, 77, 41, 55, 66, 67, 80, - 31, 42, 75, 29, 83, 83, 84, 84, 31, 31, - 25, 79, 78, 79, 83, 26, 84, 50, 1, 13, - 31, 79, 78, 26, 14, 82, 83, 82, 31, 82, - 82, 82, 84, 26, 31, 31, 82, 31, 82, 83, - 31, 31, 31, 31, 82, 34, 51, 31, 31, 31, - 79 -}; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ - -#define YYFAIL goto yyerrlab - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) - - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) -#else -# define YYLEX yylex () -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) - { - default: - break; - } -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif -{ - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } -} -#endif /* YYERROR_VERBOSE */ - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else -static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif -{ - YYUSE (yyvaluep); - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - case 53: /* "choice_entry" */ - - { - fprintf(stderr, "%s:%d: missing end statement for this entry\n", - (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); - if (current_menu == (yyvaluep->menu)) - menu_end_menu(); -}; - - break; - case 59: /* "if_entry" */ - - { - fprintf(stderr, "%s:%d: missing end statement for this entry\n", - (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); - if (current_menu == (yyvaluep->menu)) - menu_end_menu(); -}; - - break; - case 65: /* "menu_entry" */ - - { - fprintf(stderr, "%s:%d: missing end statement for this entry\n", - (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); - if (current_menu == (yyvaluep->menu)) - menu_end_menu(); -}; - - break; - - default: - break; - } -} - -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ - -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else -int -yyparse () - -#endif -#endif -{ - - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - *++yyvsp = yylval; - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 10: - - { zconf_error("unexpected end statement"); ;} - break; - - case 11: - - { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;} - break; - - case 12: - - { - zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name); -;} - break; - - case 13: - - { zconf_error("invalid statement"); ;} - break; - - case 28: - - { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;} - break; - - case 29: - - { zconf_error("invalid option"); ;} - break; - - case 30: - - { - struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); - sym->flags |= SYMBOL_OPTIONAL; - menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); -;} - break; - - case 31: - - { - menu_end_entry(); - printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 32: - - { - struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); - sym->flags |= SYMBOL_OPTIONAL; - menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); -;} - break; - - case 33: - - { - if (current_entry->prompt) - current_entry->prompt->type = P_MENU; - else - zconfprint("warning: menuconfig statement without prompt"); - menu_end_entry(); - printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 41: - - { - menu_set_type((yyvsp[(1) - (3)].id)->stype); - printd(DEBUG_PARSE, "%s:%d:type(%u)\n", - zconf_curname(), zconf_lineno(), - (yyvsp[(1) - (3)].id)->stype); -;} - break; - - case 42: - - { - menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); - printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 43: - - { - menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr)); - if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN) - menu_set_type((yyvsp[(1) - (4)].id)->stype); - printd(DEBUG_PARSE, "%s:%d:default(%u)\n", - zconf_curname(), zconf_lineno(), - (yyvsp[(1) - (4)].id)->stype); -;} - break; - - case 44: - - { - menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); - printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 45: - - { - menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr)); - printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 48: - - { - struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); - if (id && id->flags & TF_OPTION) - menu_add_option(id->token, (yyvsp[(3) - (3)].string)); - else - zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string)); - free((yyvsp[(2) - (3)].string)); -;} - break; - - case 49: - - { (yyval.string) = NULL; ;} - break; - - case 50: - - { (yyval.string) = (yyvsp[(2) - (2)].string); ;} - break; - - case 51: - - { - struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); - sym->flags |= SYMBOL_AUTO; - menu_add_entry(sym); - menu_add_expr(P_CHOICE, NULL, NULL); - printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 52: - - { - (yyval.menu) = menu_add_menu(); -;} - break; - - case 53: - - { - if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); - } -;} - break; - - case 61: - - { - menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); - printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 62: - - { - if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) { - menu_set_type((yyvsp[(1) - (3)].id)->stype); - printd(DEBUG_PARSE, "%s:%d:type(%u)\n", - zconf_curname(), zconf_lineno(), - (yyvsp[(1) - (3)].id)->stype); - } else - YYERROR; -;} - break; - - case 63: - - { - current_entry->sym->flags |= SYMBOL_OPTIONAL; - printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 64: - - { - if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) { - menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); - printd(DEBUG_PARSE, "%s:%d:default\n", - zconf_curname(), zconf_lineno()); - } else - YYERROR; -;} - break; - - case 67: - - { - printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); - menu_add_entry(NULL); - menu_add_dep((yyvsp[(2) - (3)].expr)); - (yyval.menu) = menu_add_menu(); -;} - break; - - case 68: - - { - if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); - } -;} - break; - - case 74: - - { - menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); -;} - break; - - case 75: - - { - menu_add_entry(NULL); - menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); - printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 76: - - { - (yyval.menu) = menu_add_menu(); -;} - break; - - case 77: - - { - if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); - } -;} - break; - - case 83: - - { - printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); - zconf_nextfile((yyvsp[(2) - (3)].string)); -;} - break; - - case 84: - - { - menu_add_entry(NULL); - menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL); - printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 85: - - { - menu_end_entry(); -;} - break; - - case 86: - - { - printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); - zconf_starthelp(); -;} - break; - - case 87: - - { - current_entry->help = (yyvsp[(2) - (2)].string); -;} - break; - - case 92: - - { - menu_add_dep((yyvsp[(3) - (4)].expr)); - printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 96: - - { - menu_add_visibility((yyvsp[(2) - (2)].expr)); -;} - break; - - case 98: - - { - menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr)); -;} - break; - - case 101: - - { (yyval.id) = (yyvsp[(1) - (2)].id); ;} - break; - - case 102: - - { (yyval.id) = (yyvsp[(1) - (2)].id); ;} - break; - - case 103: - - { (yyval.id) = (yyvsp[(1) - (2)].id); ;} - break; - - case 106: - - { (yyval.expr) = NULL; ;} - break; - - case 107: - - { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} - break; - - case 108: - - { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;} - break; - - case 109: - - { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} - break; - - case 110: - - { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} - break; - - case 111: - - { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} - break; - - case 112: - - { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;} - break; - - case 113: - - { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} - break; - - case 114: - - { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} - break; - - case 115: - - { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;} - break; - - case 116: - - { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} - break; - - case 117: - - { (yyval.string) = NULL; ;} - break; - - - - default: break; - } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - *++yyvsp = yylval; - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined(yyoverflow) || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} - - - - - -void conf_parse(const char *name) -{ - struct symbol *sym; - int i; - - zconf_initscan(name); - - sym_init(); - _menu_init(); - modules_sym = sym_lookup(NULL, 0); - modules_sym->type = S_BOOLEAN; - modules_sym->flags |= SYMBOL_AUTO; - rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); - -#if YYDEBUG - if (getenv("ZCONF_DEBUG")) - zconfdebug = 1; -#endif - zconfparse(); - if (zconfnerrs) - exit(1); - if (!modules_sym->prop) { - struct property *prop; - - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); - } - - rootmenu.prompt->text = _(rootmenu.prompt->text); - rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); - - menu_finalize(&rootmenu); - for_all_symbols(i, sym) { - if (sym_check_deps(sym)) - zconfnerrs++; - } - if (zconfnerrs) - exit(1); - sym_set_change_count(1); -} - -static const char *zconf_tokenname(int token) -{ - switch (token) { - case T_MENU: return "menu"; - case T_ENDMENU: return "endmenu"; - case T_CHOICE: return "choice"; - case T_ENDCHOICE: return "endchoice"; - case T_IF: return "if"; - case T_ENDIF: return "endif"; - case T_DEPENDS: return "depends"; - case T_VISIBLE: return "visible"; - } - return ""; -} - -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) -{ - if (id->token != endtoken) { - zconf_error("unexpected '%s' within %s block", - kconf_id_strings + id->name, zconf_tokenname(starttoken)); - zconfnerrs++; - return false; - } - if (current_menu->file != current_file) { - zconf_error("'%s' in different file than '%s'", - kconf_id_strings + id->name, zconf_tokenname(starttoken)); - fprintf(stderr, "%s:%d: location of the '%s'\n", - current_menu->file->name, current_menu->lineno, - zconf_tokenname(starttoken)); - zconfnerrs++; - return false; - } - return true; -} - -static void zconfprint(const char *err, ...) -{ - va_list ap; - - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); - va_start(ap, err); - vfprintf(stderr, err, ap); - va_end(ap); - fprintf(stderr, "\n"); -} - -static void zconf_error(const char *err, ...) -{ - va_list ap; - - zconfnerrs++; - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); - va_start(ap, err); - vfprintf(stderr, err, ap); - va_end(ap); - fprintf(stderr, "\n"); -} - -static void zconferror(const char *err) -{ -#if YYDEBUG - fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); -#endif -} - -static void print_quoted_string(FILE *out, const char *str) -{ - const char *p; - int len; - - putc('"', out); - while ((p = strchr(str, '"'))) { - len = p - str; - if (len) - fprintf(out, "%.*s", len, str); - fputs("\\\"", out); - str = p + 1; - } - fputs(str, out); - putc('"', out); -} - -static void print_symbol(FILE *out, struct menu *menu) -{ - struct symbol *sym = menu->sym; - struct property *prop; - - if (sym_is_choice(sym)) - fprintf(out, "\nchoice\n"); - else - fprintf(out, "\nconfig %s\n", sym->name); - switch (sym->type) { - case S_BOOLEAN: - fputs(" boolean\n", out); - break; - case S_TRISTATE: - fputs(" tristate\n", out); - break; - case S_STRING: - fputs(" string\n", out); - break; - case S_INT: - fputs(" integer\n", out); - break; - case S_HEX: - fputs(" hex\n", out); - break; - default: - fputs(" ???\n", out); - break; - } - for (prop = sym->prop; prop; prop = prop->next) { - if (prop->menu != menu) - continue; - switch (prop->type) { - case P_PROMPT: - fputs(" prompt ", out); - print_quoted_string(out, prop->text); - if (!expr_is_yes(prop->visible.expr)) { - fputs(" if ", out); - expr_fprint(prop->visible.expr, out); - } - fputc('\n', out); - break; - case P_DEFAULT: - fputs( " default ", out); - expr_fprint(prop->expr, out); - if (!expr_is_yes(prop->visible.expr)) { - fputs(" if ", out); - expr_fprint(prop->visible.expr, out); - } - fputc('\n', out); - break; - case P_CHOICE: - fputs(" #choice value\n", out); - break; - case P_SELECT: - fputs( " select ", out); - expr_fprint(prop->expr, out); - fputc('\n', out); - break; - case P_RANGE: - fputs( " range ", out); - expr_fprint(prop->expr, out); - fputc('\n', out); - break; - case P_MENU: - fputs( " menu ", out); - print_quoted_string(out, prop->text); - fputc('\n', out); - break; - default: - fprintf(out, " unknown prop %d!\n", prop->type); - break; - } - } - if (menu->help) { - int len = strlen(menu->help); - while (menu->help[--len] == '\n') - menu->help[len] = 0; - fprintf(out, " help\n%s\n", menu->help); - } -} - -void zconfdump(FILE *out) -{ - struct property *prop; - struct symbol *sym; - struct menu *menu; - - menu = rootmenu.list; - while (menu) { - if ((sym = menu->sym)) - print_symbol(out, menu); - else if ((prop = menu->prompt)) { - switch (prop->type) { - case P_COMMENT: - fputs("\ncomment ", out); - print_quoted_string(out, prop->text); - fputs("\n", out); - break; - case P_MENU: - fputs("\nmenu ", out); - print_quoted_string(out, prop->text); - fputs("\n", out); - break; - default: - ; - } - if (!expr_is_yes(prop->visible.expr)) { - fputs(" depends ", out); - expr_fprint(prop->visible.expr, out); - fputc('\n', out); - } - } - - if (menu->list) - menu = menu->list; - else if (menu->next) - menu = menu->next; - else while ((menu = menu->parent)) { - if (menu->prompt && menu->prompt->type == P_MENU) - fputs("\nendmenu\n", out); - if (menu->next) { - menu = menu->next; - break; - } - } - } -} - -#include "lex.zconf.c" -#include "util.c" -#include "confdata.c" -#include "expr.c" -#include "symbol.c" -#include "menu.c" - diff -Nru seabios-1.7.1/tools/kconfig/zconf.y seabios-1.7.4/tools/kconfig/zconf.y --- seabios-1.7.1/tools/kconfig/zconf.y 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/kconfig/zconf.y 1970-01-01 00:00:00.000000000 +0000 @@ -1,749 +0,0 @@ -%{ -/* - * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include -#include -#include - -#define LKC_DIRECT_LINK -#include "lkc.h" - -#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) - -#define PRINTD 0x0001 -#define DEBUG_PARSE 0x0002 - -int cdebug = PRINTD; - -extern int zconflex(void); -static void zconfprint(const char *err, ...); -static void zconf_error(const char *err, ...); -static void zconferror(const char *err); -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); - -struct symbol *symbol_hash[SYMBOL_HASHSIZE]; - -static struct menu *current_menu, *current_entry; - -#define YYDEBUG 0 -#if YYDEBUG -#define YYERROR_VERBOSE -#endif -%} -%expect 30 - -%union -{ - char *string; - struct file *file; - struct symbol *symbol; - struct expr *expr; - struct menu *menu; - struct kconf_id *id; -} - -%token T_MAINMENU -%token T_MENU -%token T_ENDMENU -%token T_SOURCE -%token T_CHOICE -%token T_ENDCHOICE -%token T_COMMENT -%token T_CONFIG -%token T_MENUCONFIG -%token T_HELP -%token T_HELPTEXT -%token T_IF -%token T_ENDIF -%token T_DEPENDS -%token T_OPTIONAL -%token T_PROMPT -%token T_TYPE -%token T_DEFAULT -%token T_SELECT -%token T_RANGE -%token T_VISIBLE -%token T_OPTION -%token T_ON -%token T_WORD -%token T_WORD_QUOTE -%token T_UNEQUAL -%token T_CLOSE_PAREN -%token T_OPEN_PAREN -%token T_EOL - -%left T_OR -%left T_AND -%left T_EQUAL T_UNEQUAL -%nonassoc T_NOT - -%type prompt -%type symbol -%type expr -%type if_expr -%type end -%type option_name -%type if_entry menu_entry choice_entry -%type symbol_option_arg word_opt - -%destructor { - fprintf(stderr, "%s:%d: missing end statement for this entry\n", - $$->file->name, $$->lineno); - if (current_menu == $$) - menu_end_menu(); -} if_entry menu_entry choice_entry - -%{ -/* Include zconf.hash.c here so it can see the token constants. */ -#include "zconf.hash.c" -%} - -%% -input: nl start | start; - -start: mainmenu_stmt stmt_list | stmt_list; - -stmt_list: - /* empty */ - | stmt_list common_stmt - | stmt_list choice_stmt - | stmt_list menu_stmt - | stmt_list end { zconf_error("unexpected end statement"); } - | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } - | stmt_list option_name error T_EOL -{ - zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); -} - | stmt_list error T_EOL { zconf_error("invalid statement"); } -; - -option_name: - T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE -; - -common_stmt: - T_EOL - | if_stmt - | comment_stmt - | config_stmt - | menuconfig_stmt - | source_stmt -; - -option_error: - T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } - | error T_EOL { zconf_error("invalid option"); } -; - - -/* config/menuconfig entry */ - -config_entry_start: T_CONFIG T_WORD T_EOL -{ - struct symbol *sym = sym_lookup($2, 0); - sym->flags |= SYMBOL_OPTIONAL; - menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); -}; - -config_stmt: config_entry_start config_option_list -{ - menu_end_entry(); - printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -}; - -menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL -{ - struct symbol *sym = sym_lookup($2, 0); - sym->flags |= SYMBOL_OPTIONAL; - menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); -}; - -menuconfig_stmt: menuconfig_entry_start config_option_list -{ - if (current_entry->prompt) - current_entry->prompt->type = P_MENU; - else - zconfprint("warning: menuconfig statement without prompt"); - menu_end_entry(); - printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -}; - -config_option_list: - /* empty */ - | config_option_list config_option - | config_option_list symbol_option - | config_option_list depends - | config_option_list help - | config_option_list option_error - | config_option_list T_EOL -; - -config_option: T_TYPE prompt_stmt_opt T_EOL -{ - menu_set_type($1->stype); - printd(DEBUG_PARSE, "%s:%d:type(%u)\n", - zconf_curname(), zconf_lineno(), - $1->stype); -}; - -config_option: T_PROMPT prompt if_expr T_EOL -{ - menu_add_prompt(P_PROMPT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_DEFAULT expr if_expr T_EOL -{ - menu_add_expr(P_DEFAULT, $2, $3); - if ($1->stype != S_UNKNOWN) - menu_set_type($1->stype); - printd(DEBUG_PARSE, "%s:%d:default(%u)\n", - zconf_curname(), zconf_lineno(), - $1->stype); -}; - -config_option: T_SELECT T_WORD if_expr T_EOL -{ - menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); - printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_RANGE symbol symbol if_expr T_EOL -{ - menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); - printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); -}; - -symbol_option: T_OPTION symbol_option_list T_EOL -; - -symbol_option_list: - /* empty */ - | symbol_option_list T_WORD symbol_option_arg -{ - struct kconf_id *id = kconf_id_lookup($2, strlen($2)); - if (id && id->flags & TF_OPTION) - menu_add_option(id->token, $3); - else - zconfprint("warning: ignoring unknown option %s", $2); - free($2); -}; - -symbol_option_arg: - /* empty */ { $$ = NULL; } - | T_EQUAL prompt { $$ = $2; } -; - -/* choice entry */ - -choice: T_CHOICE word_opt T_EOL -{ - struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); - sym->flags |= SYMBOL_AUTO; - menu_add_entry(sym); - menu_add_expr(P_CHOICE, NULL, NULL); - printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); -}; - -choice_entry: choice choice_option_list -{ - $$ = menu_add_menu(); -}; - -choice_end: end -{ - if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); - } -}; - -choice_stmt: choice_entry choice_block choice_end -; - -choice_option_list: - /* empty */ - | choice_option_list choice_option - | choice_option_list depends - | choice_option_list help - | choice_option_list T_EOL - | choice_option_list option_error -; - -choice_option: T_PROMPT prompt if_expr T_EOL -{ - menu_add_prompt(P_PROMPT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -}; - -choice_option: T_TYPE prompt_stmt_opt T_EOL -{ - if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { - menu_set_type($1->stype); - printd(DEBUG_PARSE, "%s:%d:type(%u)\n", - zconf_curname(), zconf_lineno(), - $1->stype); - } else - YYERROR; -}; - -choice_option: T_OPTIONAL T_EOL -{ - current_entry->sym->flags |= SYMBOL_OPTIONAL; - printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); -}; - -choice_option: T_DEFAULT T_WORD if_expr T_EOL -{ - if ($1->stype == S_UNKNOWN) { - menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); - printd(DEBUG_PARSE, "%s:%d:default\n", - zconf_curname(), zconf_lineno()); - } else - YYERROR; -}; - -choice_block: - /* empty */ - | choice_block common_stmt -; - -/* if entry */ - -if_entry: T_IF expr nl -{ - printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); - menu_add_entry(NULL); - menu_add_dep($2); - $$ = menu_add_menu(); -}; - -if_end: end -{ - if (zconf_endtoken($1, T_IF, T_ENDIF)) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); - } -}; - -if_stmt: if_entry if_block if_end -; - -if_block: - /* empty */ - | if_block common_stmt - | if_block menu_stmt - | if_block choice_stmt -; - -/* mainmenu entry */ - -mainmenu_stmt: T_MAINMENU prompt nl -{ - menu_add_prompt(P_MENU, $2, NULL); -}; - -/* menu entry */ - -menu: T_MENU prompt T_EOL -{ - menu_add_entry(NULL); - menu_add_prompt(P_MENU, $2, NULL); - printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); -}; - -menu_entry: menu visibility_list depends_list -{ - $$ = menu_add_menu(); -}; - -menu_end: end -{ - if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); - } -}; - -menu_stmt: menu_entry menu_block menu_end -; - -menu_block: - /* empty */ - | menu_block common_stmt - | menu_block menu_stmt - | menu_block choice_stmt -; - -source_stmt: T_SOURCE prompt T_EOL -{ - printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); - zconf_nextfile($2); -}; - -/* comment entry */ - -comment: T_COMMENT prompt T_EOL -{ - menu_add_entry(NULL); - menu_add_prompt(P_COMMENT, $2, NULL); - printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); -}; - -comment_stmt: comment depends_list -{ - menu_end_entry(); -}; - -/* help option */ - -help_start: T_HELP T_EOL -{ - printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); - zconf_starthelp(); -}; - -help: help_start T_HELPTEXT -{ - current_entry->help = $2; -}; - -/* depends option */ - -depends_list: - /* empty */ - | depends_list depends - | depends_list T_EOL - | depends_list option_error -; - -depends: T_DEPENDS T_ON expr T_EOL -{ - menu_add_dep($3); - printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); -}; - -/* visibility option */ - -visibility_list: - /* empty */ - | visibility_list visible - | visibility_list T_EOL -; - -visible: T_VISIBLE if_expr -{ - menu_add_visibility($2); -}; - -/* prompt statement */ - -prompt_stmt_opt: - /* empty */ - | prompt if_expr -{ - menu_add_prompt(P_PROMPT, $1, $2); -}; - -prompt: T_WORD - | T_WORD_QUOTE -; - -end: T_ENDMENU T_EOL { $$ = $1; } - | T_ENDCHOICE T_EOL { $$ = $1; } - | T_ENDIF T_EOL { $$ = $1; } -; - -nl: - T_EOL - | nl T_EOL -; - -if_expr: /* empty */ { $$ = NULL; } - | T_IF expr { $$ = $2; } -; - -expr: symbol { $$ = expr_alloc_symbol($1); } - | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } - | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } - | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } - | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } - | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } - | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } -; - -symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } - | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } -; - -word_opt: /* empty */ { $$ = NULL; } - | T_WORD - -%% - -void conf_parse(const char *name) -{ - struct symbol *sym; - int i; - - zconf_initscan(name); - - sym_init(); - _menu_init(); - modules_sym = sym_lookup(NULL, 0); - modules_sym->type = S_BOOLEAN; - modules_sym->flags |= SYMBOL_AUTO; - rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); - -#if YYDEBUG - if (getenv("ZCONF_DEBUG")) - zconfdebug = 1; -#endif - zconfparse(); - if (zconfnerrs) - exit(1); - if (!modules_sym->prop) { - struct property *prop; - - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); - } - - rootmenu.prompt->text = _(rootmenu.prompt->text); - rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); - - menu_finalize(&rootmenu); - for_all_symbols(i, sym) { - if (sym_check_deps(sym)) - zconfnerrs++; - } - if (zconfnerrs) - exit(1); - sym_set_change_count(1); -} - -static const char *zconf_tokenname(int token) -{ - switch (token) { - case T_MENU: return "menu"; - case T_ENDMENU: return "endmenu"; - case T_CHOICE: return "choice"; - case T_ENDCHOICE: return "endchoice"; - case T_IF: return "if"; - case T_ENDIF: return "endif"; - case T_DEPENDS: return "depends"; - case T_VISIBLE: return "visible"; - } - return ""; -} - -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) -{ - if (id->token != endtoken) { - zconf_error("unexpected '%s' within %s block", - kconf_id_strings + id->name, zconf_tokenname(starttoken)); - zconfnerrs++; - return false; - } - if (current_menu->file != current_file) { - zconf_error("'%s' in different file than '%s'", - kconf_id_strings + id->name, zconf_tokenname(starttoken)); - fprintf(stderr, "%s:%d: location of the '%s'\n", - current_menu->file->name, current_menu->lineno, - zconf_tokenname(starttoken)); - zconfnerrs++; - return false; - } - return true; -} - -static void zconfprint(const char *err, ...) -{ - va_list ap; - - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); - va_start(ap, err); - vfprintf(stderr, err, ap); - va_end(ap); - fprintf(stderr, "\n"); -} - -static void zconf_error(const char *err, ...) -{ - va_list ap; - - zconfnerrs++; - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); - va_start(ap, err); - vfprintf(stderr, err, ap); - va_end(ap); - fprintf(stderr, "\n"); -} - -static void zconferror(const char *err) -{ -#if YYDEBUG - fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); -#endif -} - -static void print_quoted_string(FILE *out, const char *str) -{ - const char *p; - int len; - - putc('"', out); - while ((p = strchr(str, '"'))) { - len = p - str; - if (len) - fprintf(out, "%.*s", len, str); - fputs("\\\"", out); - str = p + 1; - } - fputs(str, out); - putc('"', out); -} - -static void print_symbol(FILE *out, struct menu *menu) -{ - struct symbol *sym = menu->sym; - struct property *prop; - - if (sym_is_choice(sym)) - fprintf(out, "\nchoice\n"); - else - fprintf(out, "\nconfig %s\n", sym->name); - switch (sym->type) { - case S_BOOLEAN: - fputs(" boolean\n", out); - break; - case S_TRISTATE: - fputs(" tristate\n", out); - break; - case S_STRING: - fputs(" string\n", out); - break; - case S_INT: - fputs(" integer\n", out); - break; - case S_HEX: - fputs(" hex\n", out); - break; - default: - fputs(" ???\n", out); - break; - } - for (prop = sym->prop; prop; prop = prop->next) { - if (prop->menu != menu) - continue; - switch (prop->type) { - case P_PROMPT: - fputs(" prompt ", out); - print_quoted_string(out, prop->text); - if (!expr_is_yes(prop->visible.expr)) { - fputs(" if ", out); - expr_fprint(prop->visible.expr, out); - } - fputc('\n', out); - break; - case P_DEFAULT: - fputs( " default ", out); - expr_fprint(prop->expr, out); - if (!expr_is_yes(prop->visible.expr)) { - fputs(" if ", out); - expr_fprint(prop->visible.expr, out); - } - fputc('\n', out); - break; - case P_CHOICE: - fputs(" #choice value\n", out); - break; - case P_SELECT: - fputs( " select ", out); - expr_fprint(prop->expr, out); - fputc('\n', out); - break; - case P_RANGE: - fputs( " range ", out); - expr_fprint(prop->expr, out); - fputc('\n', out); - break; - case P_MENU: - fputs( " menu ", out); - print_quoted_string(out, prop->text); - fputc('\n', out); - break; - default: - fprintf(out, " unknown prop %d!\n", prop->type); - break; - } - } - if (menu->help) { - int len = strlen(menu->help); - while (menu->help[--len] == '\n') - menu->help[len] = 0; - fprintf(out, " help\n%s\n", menu->help); - } -} - -void zconfdump(FILE *out) -{ - struct property *prop; - struct symbol *sym; - struct menu *menu; - - menu = rootmenu.list; - while (menu) { - if ((sym = menu->sym)) - print_symbol(out, menu); - else if ((prop = menu->prompt)) { - switch (prop->type) { - case P_COMMENT: - fputs("\ncomment ", out); - print_quoted_string(out, prop->text); - fputs("\n", out); - break; - case P_MENU: - fputs("\nmenu ", out); - print_quoted_string(out, prop->text); - fputs("\n", out); - break; - default: - ; - } - if (!expr_is_yes(prop->visible.expr)) { - fputs(" depends ", out); - expr_fprint(prop->visible.expr, out); - fputc('\n', out); - } - } - - if (menu->list) - menu = menu->list; - else if (menu->next) - menu = menu->next; - else while ((menu = menu->parent)) { - if (menu->prompt && menu->prompt->type == P_MENU) - fputs("\nendmenu\n", out); - if (menu->next) { - menu = menu->next; - break; - } - } - } -} - -#include "lex.zconf.c" -#include "util.c" -#include "confdata.c" -#include "expr.c" -#include "symbol.c" -#include "menu.c" diff -Nru seabios-1.7.1/tools/layoutrom.py seabios-1.7.4/tools/layoutrom.py --- seabios-1.7.1/tools/layoutrom.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/layoutrom.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,630 +0,0 @@ -#!/usr/bin/env python -# Script to analyze code and arrange ld sections. -# -# Copyright (C) 2008-2010 Kevin O'Connor -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -import sys - -# LD script headers/trailers -COMMONHEADER = """ -/* DO NOT EDIT! This is an autogenerated file. See tools/layoutrom.py. */ -OUTPUT_FORMAT("elf32-i386") -OUTPUT_ARCH("i386") -SECTIONS -{ -""" -COMMONTRAILER = """ - - /* Discard regular data sections to force a link error if - * code attempts to access data not marked with VAR16 (or other - * appropriate macro) - */ - /DISCARD/ : { - *(.text*) *(.data*) *(.bss*) *(.rodata*) - *(COMMON) *(.discard*) *(.eh_frame) *(.note*) - } -} -""" - - -###################################################################### -# Determine section locations -###################################################################### - -# Align 'pos' to 'alignbytes' offset -def alignpos(pos, alignbytes): - mask = alignbytes - 1 - return (pos + mask) & ~mask - -# Determine the final addresses for a list of sections that end at an -# address. -def setSectionsStart(sections, endaddr, minalign=1, segoffset=0): - totspace = 0 - for section in sections: - if section.align > minalign: - minalign = section.align - totspace = alignpos(totspace, section.align) + section.size - startaddr = (endaddr - totspace) / minalign * minalign - curaddr = startaddr - for section in sections: - curaddr = alignpos(curaddr, section.align) - section.finalloc = curaddr - section.finalsegloc = curaddr - segoffset - curaddr += section.size - return startaddr, minalign - -# The 16bit code can't exceed 64K of space. -BUILD_BIOS_ADDR = 0xf0000 -BUILD_BIOS_SIZE = 0x10000 -BUILD_ROM_START = 0xc0000 - -# Layout the 16bit code. This ensures sections with fixed offset -# requirements are placed in the correct location. It also places the -# 16bit code as high as possible in the f-segment. -def fitSections(sections, fillsections): - # fixedsections = [(addr, section), ...] - fixedsections = [] - for section in sections: - if section.name.startswith('.fixedaddr.'): - addr = int(section.name[11:], 16) - section.finalloc = addr + BUILD_BIOS_ADDR - section.finalsegloc = addr - fixedsections.append((addr, section)) - if section.align != 1: - print "Error: Fixed section %s has non-zero alignment (%d)" % ( - section.name, section.align) - sys.exit(1) - fixedsections.sort() - firstfixed = fixedsections[0][0] - - # Find freespace in fixed address area - # fixedAddr = [(freespace, section), ...] - fixedAddr = [] - for i in range(len(fixedsections)): - fixedsectioninfo = fixedsections[i] - addr, section = fixedsectioninfo - if i == len(fixedsections) - 1: - nextaddr = BUILD_BIOS_SIZE - else: - nextaddr = fixedsections[i+1][0] - avail = nextaddr - addr - section.size - fixedAddr.append((avail, section)) - fixedAddr.sort() - - # Attempt to fit other sections into fixed area - canrelocate = [(section.size, section.align, section.name, section) - for section in fillsections] - canrelocate.sort() - canrelocate = [section for size, align, name, section in canrelocate] - totalused = 0 - for freespace, fixedsection in fixedAddr: - addpos = fixedsection.finalsegloc + fixedsection.size - totalused += fixedsection.size - nextfixedaddr = addpos + freespace -# print "Filling section %x uses %d, next=%x, available=%d" % ( -# fixedsection.finalloc, fixedsection.size, nextfixedaddr, freespace) - while 1: - canfit = None - for fitsection in canrelocate: - if addpos + fitsection.size > nextfixedaddr: - # Can't fit and nothing else will fit. - break - fitnextaddr = alignpos(addpos, fitsection.align) + fitsection.size -# print "Test %s - %x vs %x" % ( -# fitsection.name, fitnextaddr, nextfixedaddr) - if fitnextaddr > nextfixedaddr: - # This item can't fit. - continue - canfit = (fitnextaddr, fitsection) - if canfit is None: - break - # Found a section that can fit. - fitnextaddr, fitsection = canfit - canrelocate.remove(fitsection) - fitsection.finalloc = addpos + BUILD_BIOS_ADDR - fitsection.finalsegloc = addpos - addpos = fitnextaddr - totalused += fitsection.size -# print " Adding %s (size %d align %d) pos=%x avail=%d" % ( -# fitsection[2], fitsection[0], fitsection[1] -# , fitnextaddr, nextfixedaddr - fitnextaddr) - - # Report stats - total = BUILD_BIOS_SIZE-firstfixed - slack = total - totalused - print ("Fixed space: 0x%x-0x%x total: %d slack: %d" - " Percent slack: %.1f%%" % ( - firstfixed, BUILD_BIOS_SIZE, total, slack, - (float(slack) / total) * 100.0)) - - return firstfixed + BUILD_BIOS_ADDR - -# Return the subset of sections with a given category -def getSectionsCategory(sections, category): - return [section for section in sections if section.category == category] - -# Return the subset of sections with a given name prefix -def getSectionsPrefix(sections, prefix): - return [section for section in sections - if section.name.startswith(prefix)] - -# The sections (and associated information) to be placed in output rom -class LayoutInfo: - sections16 = sec16_start = sec16_align = None - sections32seg = sec32seg_start = sec32seg_align = None - sections32flat = sec32flat_start = sec32flat_align = None - sections32init = sec32init_start = sec32init_align = None - sections32low = sec32low_start = sec32low_align = None - datalow_base = final_sec32low_start = None - -# Determine final memory addresses for sections -def doLayout(sections, genreloc): - li = LayoutInfo() - # Determine 16bit positions - li.sections16 = getSectionsCategory(sections, '16') - textsections = getSectionsPrefix(li.sections16, '.text.') - rodatasections = ( - getSectionsPrefix(li.sections16, '.rodata.str1.1') - + getSectionsPrefix(li.sections16, '.rodata.__func__.') - + getSectionsPrefix(li.sections16, '.rodata.__PRETTY_FUNCTION__.')) - datasections = getSectionsPrefix(li.sections16, '.data16.') - fixedsections = getSectionsPrefix(li.sections16, '.fixedaddr.') - - firstfixed = fitSections(fixedsections, textsections) - remsections = [s for s in textsections+rodatasections+datasections - if s.finalloc is None] - li.sec16_start, li.sec16_align = setSectionsStart( - remsections, firstfixed, segoffset=BUILD_BIOS_ADDR) - - # Determine 32seg positions - li.sections32seg = getSectionsCategory(sections, '32seg') - textsections = getSectionsPrefix(li.sections32seg, '.text.') - rodatasections = ( - getSectionsPrefix(li.sections32seg, '.rodata.str1.1') - + getSectionsPrefix(li.sections32seg, '.rodata.__func__.') - + getSectionsPrefix(li.sections32seg, '.rodata.__PRETTY_FUNCTION__.')) - datasections = getSectionsPrefix(li.sections32seg, '.data32seg.') - - li.sec32seg_start, li.sec32seg_align = setSectionsStart( - textsections + rodatasections + datasections, li.sec16_start - , segoffset=BUILD_BIOS_ADDR) - - # Determine 32flat runtime positions - li.sections32flat = getSectionsCategory(sections, '32flat') - textsections = getSectionsPrefix(li.sections32flat, '.text.') - rodatasections = getSectionsPrefix(li.sections32flat, '.rodata') - datasections = getSectionsPrefix(li.sections32flat, '.data.') - bsssections = getSectionsPrefix(li.sections32flat, '.bss.') - - li.sec32flat_start, li.sec32flat_align = setSectionsStart( - textsections + rodatasections + datasections + bsssections - , li.sec32seg_start, 16) - - # Determine 32flat init positions - li.sections32init = getSectionsCategory(sections, '32init') - textsections = getSectionsPrefix(li.sections32init, '.text.') - rodatasections = getSectionsPrefix(li.sections32init, '.rodata') - datasections = getSectionsPrefix(li.sections32init, '.data.') - bsssections = getSectionsPrefix(li.sections32init, '.bss.') - - li.sec32init_start, li.sec32init_align = setSectionsStart( - textsections + rodatasections + datasections + bsssections - , li.sec32flat_start, 16) - - # Determine "low memory" data positions - li.sections32low = getSectionsCategory(sections, '32low') - if genreloc: - sec32low_top = li.sec32init_start - final_sec32low_top = min(BUILD_BIOS_ADDR, li.sec32flat_start) - else: - sec32low_top = min(BUILD_BIOS_ADDR, li.sec32init_start) - final_sec32low_top = sec32low_top - relocdelta = final_sec32low_top - sec32low_top - datalow_base = final_sec32low_top - 64*1024 - li.datalow_base = max(BUILD_ROM_START, alignpos(datalow_base, 2*1024)) - li.sec32low_start, li.sec32low_align = setSectionsStart( - li.sections32low, sec32low_top, 16 - , segoffset=li.datalow_base - relocdelta) - li.final_sec32low_start = li.sec32low_start + relocdelta - - # Print statistics - size16 = BUILD_BIOS_ADDR + BUILD_BIOS_SIZE - li.sec16_start - size32seg = li.sec16_start - li.sec32seg_start - size32flat = li.sec32seg_start - li.sec32flat_start - size32init = li.sec32flat_start - li.sec32init_start - sizelow = sec32low_top - li.sec32low_start - print "16bit size: %d" % size16 - print "32bit segmented size: %d" % size32seg - print "32bit flat size: %d" % size32flat - print "32bit flat init size: %d" % size32init - print "Lowmem size: %d" % sizelow - return li - - -###################################################################### -# Linker script output -###################################################################### - -# Write LD script includes for the given cross references -def outXRefs(sections, useseg=0): - xrefs = {} - out = "" - for section in sections: - for reloc in section.relocs: - symbol = reloc.symbol - if (symbol.section is None - or (symbol.section.fileid == section.fileid - and symbol.name == reloc.symbolname) - or reloc.symbolname in xrefs): - continue - xrefs[reloc.symbolname] = 1 - loc = symbol.section.finalloc - if useseg: - loc = symbol.section.finalsegloc - out += "%s = 0x%x ;\n" % (reloc.symbolname, loc + symbol.offset) - return out - -# Write LD script includes for the given sections using relative offsets -def outRelSections(sections, startsym, useseg=0): - sections = [(section.finalloc, section) for section in sections - if section.finalloc is not None] - sections.sort() - out = "" - for addr, section in sections: - loc = section.finalloc - if useseg: - loc = section.finalsegloc - out += ". = ( 0x%x - %s ) ;\n" % (loc, startsym) - if section.name == '.rodata.str1.1': - out += "_rodata = . ;\n" - out += "*(%s)\n" % (section.name,) - return out - -# Build linker script output for a list of relocations. -def strRelocs(outname, outrel, relocs): - relocs.sort() - return (" %s_start = ABSOLUTE(.) ;\n" % (outname,) - + "".join(["LONG(0x%x - %s)\n" % (pos, outrel) - for pos in relocs]) - + " %s_end = ABSOLUTE(.) ;\n" % (outname,)) - -# Find all relocations in the given sections with the given attributes -def getRelocs(sections, type=None, category=None, notcategory=None): - out = [] - for section in sections: - for reloc in section.relocs: - if reloc.symbol.section is None: - continue - destcategory = reloc.symbol.section.category - if ((type is None or reloc.type == type) - and (category is None or destcategory == category) - and (notcategory is None or destcategory != notcategory)): - out.append(section.finalloc + reloc.offset) - return out - -# Return the start address and minimum alignment for a set of sections -def getSectionsStart(sections, defaddr=0): - return min([section.finalloc for section in sections - if section.finalloc is not None] or [defaddr]) - -# Output the linker scripts for all required sections. -def writeLinkerScripts(li, entrysym, genreloc, out16, out32seg, out32flat): - # Write 16bit linker script - out = outXRefs(li.sections16, useseg=1) + """ - datalow_base = 0x%x ; - _datalow_seg = 0x%x ; - - code16_start = 0x%x ; - .text16 code16_start : { -%s - } -""" % (li.datalow_base, - li.datalow_base / 16, - li.sec16_start - BUILD_BIOS_ADDR, - outRelSections(li.sections16, 'code16_start', useseg=1)) - outfile = open(out16, 'wb') - outfile.write(COMMONHEADER + out + COMMONTRAILER) - outfile.close() - - # Write 32seg linker script - out = outXRefs(li.sections32seg, useseg=1) + """ - code32seg_start = 0x%x ; - .text32seg code32seg_start : { -%s - } -""" % (li.sec32seg_start - BUILD_BIOS_ADDR, - outRelSections(li.sections32seg, 'code32seg_start', useseg=1)) - outfile = open(out32seg, 'wb') - outfile.write(COMMONHEADER + out + COMMONTRAILER) - outfile.close() - - # Write 32flat linker script - sections32all = li.sections32flat + li.sections32init + li.sections32low - sec32all_start = li.sec32low_start - entrysympos = entrysym.section.finalloc + entrysym.offset - relocstr = "" - if genreloc: - # Generate relocations - absrelocs = getRelocs( - li.sections32init, type='R_386_32', category='32init') - relrelocs = getRelocs( - li.sections32init, type='R_386_PC32', notcategory='32init') - initrelocs = getRelocs( - li.sections32flat + li.sections32low + li.sections16 - + li.sections32seg, category='32init') - lowrelocs = getRelocs(sections32all, category='32low') - relocstr = (strRelocs("_reloc_abs", "code32init_start", absrelocs) - + strRelocs("_reloc_rel", "code32init_start", relrelocs) - + strRelocs("_reloc_init", "code32flat_start", initrelocs) - + strRelocs("_reloc_datalow", "code32flat_start", lowrelocs)) - numrelocs = len(absrelocs + relrelocs + initrelocs + lowrelocs) - sec32all_start -= numrelocs * 4 - out = outXRefs(sections32all) + """ - %s = 0x%x ; - _reloc_min_align = 0x%x ; - datalow_base = 0x%x ; - final_datalow_start = 0x%x ; - - code32flat_start = 0x%x ; - .text code32flat_start : { -%s - datalow_start = ABSOLUTE(.) ; -%s - datalow_end = ABSOLUTE(.) ; - code32init_start = ABSOLUTE(.) ; -%s - code32init_end = ABSOLUTE(.) ; -%s - . = ( 0x%x - code32flat_start ) ; - *(.text32seg) - . = ( 0x%x - code32flat_start ) ; - *(.text16) - code32flat_end = ABSOLUTE(.) ; - } :text -""" % (entrysym.name, entrysympos, - li.sec32init_align, - li.datalow_base, - li.final_sec32low_start, - sec32all_start, - relocstr, - outRelSections(li.sections32low, 'code32flat_start'), - outRelSections(li.sections32init, 'code32flat_start'), - outRelSections(li.sections32flat, 'code32flat_start'), - li.sec32seg_start, - li.sec16_start) - out = COMMONHEADER + out + COMMONTRAILER + """ -ENTRY(%s) -PHDRS -{ - text PT_LOAD AT ( code32flat_start ) ; -} -""" % (entrysym.name,) - outfile = open(out32flat, 'wb') - outfile.write(out) - outfile.close() - - -###################################################################### -# Detection of init code -###################################################################### - -def markRuntime(section, sections): - if (section is None or not section.keep or section.category is not None - or '.init.' in section.name or section.fileid != '32flat'): - return - section.category = '32flat' - # Recursively mark all sections this section points to - for reloc in section.relocs: - markRuntime(reloc.symbol.section, sections) - -def findInit(sections): - # Recursively find and mark all "runtime" sections. - for section in sections: - if ('.datalow.' in section.name or '.runtime.' in section.name - or '.export.' in section.name): - markRuntime(section, sections) - for section in sections: - if section.category is not None: - continue - if section.fileid == '32flat': - section.category = '32init' - else: - section.category = section.fileid - - -###################################################################### -# Section garbage collection -###################################################################### - -CFUNCPREFIX = [('_cfunc16_', 0), ('_cfunc32seg_', 1), ('_cfunc32flat_', 2)] - -# Find and keep the section associated with a symbol (if available). -def keepsymbol(reloc, infos, pos, isxref): - symbolname = reloc.symbolname - mustbecfunc = 0 - for symprefix, needpos in CFUNCPREFIX: - if symbolname.startswith(symprefix): - if needpos != pos: - return -1 - symbolname = symbolname[len(symprefix):] - mustbecfunc = 1 - break - symbol = infos[pos][1].get(symbolname) - if (symbol is None or symbol.section is None - or symbol.section.name.startswith('.discard.')): - return -1 - isdestcfunc = (symbol.section.name.startswith('.text.') - and not symbol.section.name.startswith('.text.asm.')) - if ((mustbecfunc and not isdestcfunc) - or (not mustbecfunc and isdestcfunc and isxref)): - return -1 - - reloc.symbol = symbol - keepsection(symbol.section, infos, pos) - return 0 - -# Note required section, and recursively set all referenced sections -# as required. -def keepsection(section, infos, pos=0): - if section.keep: - # Already kept - nothing to do. - return - section.keep = 1 - # Keep all sections that this section points to - for reloc in section.relocs: - ret = keepsymbol(reloc, infos, pos, 0) - if not ret: - continue - # Not in primary sections - it may be a cross 16/32 reference - ret = keepsymbol(reloc, infos, (pos+1)%3, 1) - if not ret: - continue - ret = keepsymbol(reloc, infos, (pos+2)%3, 1) - if not ret: - continue - -# Determine which sections are actually referenced and need to be -# placed into the output file. -def gc(info16, info32seg, info32flat): - # infos = ((sections16, symbols16), (sect32seg, sym32seg) - # , (sect32flat, sym32flat)) - infos = (info16, info32seg, info32flat) - # Start by keeping sections that are globally visible. - for section in info16[0]: - if section.name.startswith('.fixedaddr.') or '.export.' in section.name: - keepsection(section, infos) - return [section for section in info16[0]+info32seg[0]+info32flat[0] - if section.keep] - - -###################################################################### -# Startup and input parsing -###################################################################### - -class Section: - name = size = alignment = fileid = relocs = None - finalloc = finalsegloc = category = keep = None -class Reloc: - offset = type = symbolname = symbol = None -class Symbol: - name = offset = section = None - -# Read in output from objdump -def parseObjDump(file, fileid): - # sections = [section, ...] - sections = [] - sectionmap = {} - # symbols[symbolname] = symbol - symbols = {} - - state = None - for line in file.readlines(): - line = line.rstrip() - if line == 'Sections:': - state = 'section' - continue - if line == 'SYMBOL TABLE:': - state = 'symbol' - continue - if line.startswith('RELOCATION RECORDS FOR ['): - sectionname = line[24:-2] - if sectionname.startswith('.debug_'): - # Skip debugging sections (to reduce parsing time) - state = None - continue - state = 'reloc' - relocsection = sectionmap[sectionname] - continue - - if state == 'section': - try: - idx, name, size, vma, lma, fileoff, align = line.split() - if align[:3] != '2**': - continue - section = Section() - section.name = name - section.size = int(size, 16) - section.align = 2**int(align[3:]) - section.fileid = fileid - section.relocs = [] - sections.append(section) - sectionmap[name] = section - except ValueError: - pass - continue - if state == 'symbol': - try: - parts = line[17:].split() - if len(parts) == 3: - sectionname, size, name = parts - elif len(parts) == 4 and parts[2] == '.hidden': - sectionname, size, hidden, name = parts - else: - continue - symbol = Symbol() - symbol.size = int(size, 16) - symbol.offset = int(line[:8], 16) - symbol.name = name - symbol.section = sectionmap.get(sectionname) - symbols[name] = symbol - except ValueError: - pass - continue - if state == 'reloc': - try: - off, type, symbolname = line.split() - reloc = Reloc() - reloc.offset = int(off, 16) - reloc.type = type - reloc.symbolname = symbolname - reloc.symbol = symbols.get(symbolname) - if reloc.symbol is None: - # Some binutils (2.20.1) give section name instead - # of a symbol - create a dummy symbol. - reloc.symbol = symbol = Symbol() - symbol.size = 0 - symbol.offset = 0 - symbol.name = symbolname - symbol.section = sectionmap.get(symbolname) - symbols[symbolname] = symbol - relocsection.relocs.append(reloc) - except ValueError: - pass - return sections, symbols - -def main(): - # Get output name - in16, in32seg, in32flat, out16, out32seg, out32flat = sys.argv[1:] - - # Read in the objdump information - infile16 = open(in16, 'rb') - infile32seg = open(in32seg, 'rb') - infile32flat = open(in32flat, 'rb') - - # infoX = (sections, symbols) - info16 = parseObjDump(infile16, '16') - info32seg = parseObjDump(infile32seg, '32seg') - info32flat = parseObjDump(infile32flat, '32flat') - - # Figure out which sections to keep. - sections = gc(info16, info32seg, info32flat) - - # Separate 32bit flat into runtime and init parts - findInit(sections) - - # Note "low memory" parts - for section in getSectionsPrefix(sections, '.datalow.'): - section.category = '32low' - - # Determine the final memory locations of each kept section. - genreloc = '_reloc_abs_start' in info32flat[1] - li = doLayout(sections, genreloc) - - # Write out linker script files. - entrysym = info16[1]['entry_elf'] - writeLinkerScripts(li, entrysym, genreloc, out16, out32seg, out32flat) - -if __name__ == '__main__': - main() Binary files /tmp/tmpQX5B3r/1ILzN7giy_/seabios-1.7.1/tools/layoutrom.pyc and /tmp/tmpQX5B3r/EbHQumljnX/seabios-1.7.4/tools/layoutrom.pyc differ diff -Nru seabios-1.7.1/tools/readserial.py seabios-1.7.4/tools/readserial.py --- seabios-1.7.1/tools/readserial.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/readserial.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,186 +0,0 @@ -#!/usr/bin/env python -# Script that can read from a serial device and show timestamps. -# -# Copyright (C) 2009 Kevin O'Connor -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -# Usage: -# tools/readserial.py /dev/ttyUSB0 115200 - -import sys -import time -import select -import optparse - -# Reset time counter after this much idle time. -RESTARTINTERVAL = 60 -# Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data -# bits + 1 stop bit. -BITSPERBYTE = 10 - -def calibrateserialwrite(outfile, byteadjust): - # Build 4000 bytes of dummy data. - data = "0123456789" * 4 + "012345678" + "\n" - data = data * 80 - while 1: - st = time.time() - outfile.write(data) - outfile.flush() - et = time.time() - sys.stdout.write( - "Wrote %d - %.1fus per char (theory states %.1fus)\n" % ( - len(data), (et-st) / len(data) * 1000000, byteadjust * 1000000)) - sys.stdout.flush() - time.sleep(3) - -def calibrateserialread(infile, byteadjust): - starttime = lasttime = 0 - totalchars = 0 - while 1: - select.select([infile], [], []) - d = infile.read(4096) - curtime = time.time() - if curtime - lasttime > 1.0: - if starttime and totalchars: - sys.stdout.write( - "Calibrating on %d bytes - %.1fus per char" - " (theory states %.1fus)\n" % ( - totalchars, - float(lasttime - starttime) * 1000000 / totalchars, - byteadjust * 1000000)) - totalchars = 0 - starttime = curtime - else: - totalchars += len(d) - lasttime = curtime - -def readserial(infile, logfile, byteadjust): - lasttime = 0 - while 1: - # Read data - try: - res = select.select([infile, sys.stdin], [], []) - except KeyboardInterrupt: - sys.stdout.write("\n") - break - if sys.stdin in res[0]: - # Got keyboard input - force reset on next serial input - sys.stdin.read(1) - lasttime = 0 - if len(res[0]) == 1: - continue - d = infile.read(4096) - if not d: - break - datatime = time.time() - - datatime -= len(d) * byteadjust - - # Reset start time if no data for some time - if datatime - lasttime > RESTARTINTERVAL: - starttime = datatime - charcount = 0 - isnewline = 1 - msg = "\n\n======= %s (adjust=%.1fus)\n" % ( - time.asctime(time.localtime(datatime)), byteadjust * 1000000) - sys.stdout.write(msg) - logfile.write(msg) - lasttime = datatime - - # Translate unprintable chars; add timestamps - out = "" - for c in d: - if isnewline: - delta = datatime - starttime - (charcount * byteadjust) - out += "%06.3f: " % delta - isnewline = 0 - oc = ord(c) - charcount += 1 - datatime += byteadjust - if oc == 0x0d: - continue - if oc == 0x00: - out += "<00>\n" - isnewline = 1 - continue - if oc == 0x0a: - out += "\n" - isnewline = 1 - continue - if oc < 0x20 or oc >= 0x7f and oc != 0x09: - out += "<%02x>" % oc - continue - out += c - - sys.stdout.write(out) - sys.stdout.flush() - logfile.write(out) - logfile.flush() - -def main(): - usage = "%prog [options] [ []]" - opts = optparse.OptionParser(usage) - opts.add_option("-f", "--file", - action="store_false", dest="serial", default=True, - help="read from file instead of serialdevice") - opts.add_option("-n", "--no-adjust", - action="store_false", dest="adjustbaud", default=True, - help="don't adjust times by serial rate") - opts.add_option("-c", "--calibrate-read", - action="store_true", dest="calibrate_read", default=False, - help="read from serial port to calibrate it") - opts.add_option("-C", "--calibrate-write", - action="store_true", dest="calibrate_write", default=False, - help="write to serial port to calibrate it") - opts.add_option("-t", "--time", - type="float", dest="time", default=None, - help="time to write one byte on serial port (in us)") - options, args = opts.parse_args() - serialport = 0 - baud = 115200 - if len(args) > 2: - opts.error("Too many arguments") - if len(args) > 0: - serialport = args[0] - if len(args) > 1: - baud = int(args[1]) - byteadjust = float(BITSPERBYTE) / baud - if options.time is not None: - byteadjust = options.time / 1000000.0 - if not options.adjustbaud: - byteadjust = 0.0 - - if options.serial: - # Read from serial port - try: - import serial - except ImportError: - print """ -Unable to find pyserial package ( http://pyserial.sourceforge.net/ ). -On Linux machines try: yum install pyserial -Or: apt-get install python-serial -""" - sys.exit(1) - ser = serial.Serial(serialport, baud, timeout=0) - else: - # Read from a file - ser = open(serialport, 'rb') - import fcntl - import os - fcntl.fcntl(ser, fcntl.F_SETFL - , fcntl.fcntl(ser, fcntl.F_GETFL) | os.O_NONBLOCK) - - if options.calibrate_read: - calibrateserialread(ser, byteadjust) - return - if options.calibrate_write: - calibrateserialwrite(ser, byteadjust) - return - - logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log") - f = open(logname, 'wb') - readserial(ser, f, byteadjust) - -if __name__ == '__main__': - main() diff -Nru seabios-1.7.1/tools/test-build.sh seabios-1.7.4/tools/test-build.sh --- seabios-1.7.1/tools/test-build.sh 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/test-build.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -#!/bin/sh -# Script to test if the build works properly. - -# Test IASL is installed. -$IASL -h > /dev/null 2>&1 -if [ $? -ne 0 ]; then - echo "The SeaBIOS project requires the 'iasl' package be installed." >&2 - echo "Many Linux distributions have this package." >&2 - echo "Try: sudo yum install iasl" >&2 - echo "Or: sudo apt-get install iasl" >&2 - echo "" >&2 - echo "Please install iasl and retry." >&2 - echo -1 - exit 0 -fi - -mkdir -p out -TMPFILE1=out/tmp_testcompile1.c -TMPFILE1o=out/tmp_testcompile1.o -TMPFILE1_ld=out/tmp_testcompile1.lds -TMPFILE2=out/tmp_testcompile2.c -TMPFILE2o=out/tmp_testcompile2.o -TMPFILE3o=out/tmp_testcompile3.o - -# Test if ld's alignment handling is correct. This is a known problem -# with the linker that ships with Ubuntu 11.04. -cat - > $TMPFILE1 < $TMPFILE1_ld < /dev/null 2>&1 -$LD -T $TMPFILE1_ld $TMPFILE1o -o $TMPFILE2o > /dev/null 2>&1 -if [ $? -ne 0 ]; then - echo "The version of LD on this system does not properly handle" >&2 - echo "alignments. As a result, this project can not be built." >&2 - echo "" >&2 - echo "The problem may be the result of this LD bug report:" >&2 - echo " http://sourceware.org/bugzilla/show_bug.cgi?id=12726" >&2 - echo "" >&2 - echo "Please update to a working version of binutils and retry." >&2 - echo -1 - exit 0 -fi - -# Test for "-fwhole-program". Older versions of gcc (pre v4.1) don't -# support the whole-program optimization - detect that. -$CC -fwhole-program -S -o /dev/null -xc /dev/null > /dev/null 2>&1 -if [ $? -ne 0 ]; then - echo " Working around no -fwhole-program" >&2 - echo 2 - exit 0 -fi - -# Test if "visible" variables and functions are marked global. On -# OpenSuse 10.3 "visible" variables declared with "extern" first -# aren't marked as global in the resulting assembler. On Ubuntu 7.10 -# "visible" functions aren't marked as global in the resulting -# assembler. -cat - > $TMPFILE1 < /dev/null 2>&1 -cat - > $TMPFILE2 < /dev/null 2>&1 -$CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1 -if [ $? -ne 0 ]; then - echo " Working around non-functional -fwhole-program" >&2 - echo 2 - exit 0 -fi - -# Test if "-combine" works. On Ubuntu 8.04 the compiler doesn't work -# correctly with combine and the "struct bregs" register due to the -# anonymous unions and structs. On Fedora Core 12 the compiler throws -# an internal compiler error when multiple files access global -# variables with debugging enabled. -cat - > $TMPFILE1 <v=0; -} -EOF -cat - > $TMPFILE2 < /dev/null 2>&1 -if [ $? -eq 0 ]; then - echo 0 -else - echo " Working around non-functional -combine" >&2 - echo 1 -fi - -# Also, on several compilers, -combine fails if code is emitted with a -# reference to an extern variable that is later found to be externally -# visible - the compiler does not mark those variables as global. -# This is being worked around by ordering the compile objects to avoid -# this case. - -# Also, the Ubuntu 8.04 compiler has a bug causing corruption when the -# "ebp" register is clobberred in an "asm" statement. The code has -# been modified to not clobber "ebp" - no test is available yet. - -rm -f $TMPFILE1 $TMPFILE1o $TMPFILE1_ld $TMPFILE2 $TMPFILE2o $TMPFILE3o diff -Nru seabios-1.7.1/tools/transdump.py seabios-1.7.4/tools/transdump.py --- seabios-1.7.1/tools/transdump.py 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/tools/transdump.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -#!/usr/bin/env python - -# This script is useful for taking the output of memdump() and -# converting it back into binary output. This can be useful, for -# example, when one wants to push that data into other tools like -# objdump or hexdump. -# -# (C) Copyright 2010 Kevin O'Connor -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -import sys -import struct - -def unhex(str): - return int(str, 16) - -def parseMem(filehdl): - mem = [] - for line in filehdl: - parts = line.split(':') - if len(parts) < 2: - continue - try: - vaddr = unhex(parts[0]) - parts = parts[1].split() - mem.extend([unhex(v) for v in parts]) - except ValueError: - continue - return mem - -def printUsage(): - sys.stderr.write("Usage:\n %s \n" - % (sys.argv[0],)) - sys.exit(1) - -def main(): - if len(sys.argv) != 2: - printUsage() - filename = sys.argv[1] - if filename == '-': - filehdl = sys.stdin - else: - filehdl = open(filename, 'r') - mem = parseMem(filehdl) - for i in mem: - sys.stdout.write(struct.pack(" -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -# The x86emu code widely used in Linux distributions when running Xorg -# in vesamode is known to have issues with "retl", "leavel", "entryl", -# and some variants of "calll". This code modifies those instructions -# (ret and leave) that are known to be generated by gcc to avoid -# triggering the x86emu bugs. - -# It is also known that the Windows vgabios emulator has issues with -# addressing negative offsets to the %esp register. That has been -# worked around by not using the gcc paremeter "-fomit-frame-pointer" -# when compiling. - -import sys - -def main(): - infilename, outfilename = sys.argv[1:] - infile = open(infilename, 'rb') - out = [] - for line in infile: - sline = line.strip() - if sline == 'ret': - out.append('retw $2\n') - elif sline == 'leave': - out.append('movl %ebp, %esp ; popl %ebp\n') - else: - out.append(line) - infile.close() - outfile = open(outfilename, 'wb') - outfile.write(''.join(out)) - outfile.close() - -if __name__ == '__main__': - main() diff -Nru seabios-1.7.1/.version seabios-1.7.4/.version --- seabios-1.7.1/.version 2012-08-31 16:16:40.000000000 +0000 +++ seabios-1.7.4/.version 2013-12-23 16:04:51.000000000 +0000 @@ -1 +1 @@ -1.7.1 +1.7.4 diff -Nru seabios-1.7.1/vgasrc/bochsvga.c seabios-1.7.4/vgasrc/bochsvga.c --- seabios-1.7.1/vgasrc/bochsvga.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/bochsvga.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,15 +6,16 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "vgabios.h" // struct vbe_modeinfo -#include "vbe.h" // VBE_CAPABILITY_8BIT_DAC +#include "biosvar.h" // GET_GLOBAL #include "bochsvga.h" // bochsvga_set_mode -#include "util.h" // dprintf #include "config.h" // CONFIG_* -#include "biosvar.h" // GET_GLOBAL +#include "hw/pci.h" // pci_config_readl +#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "output.h" // dprintf +#include "std/vbe.h" // VBE_CAPABILITY_8BIT_DAC #include "stdvga.h" // VGAREG_SEQU_ADDRESS -#include "pci.h" // pci_config_readl -#include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "vgabios.h" // struct vbe_modeinfo +#include "x86.h" // outw /**************************************************************** @@ -68,6 +69,9 @@ { 0x14a, { MM_DIRECT, 1152, 864, 16, 8, 16, SEG_GRAPH } }, { 0x14b, { MM_DIRECT, 1152, 864, 24, 8, 16, SEG_GRAPH } }, { 0x14c, { MM_DIRECT, 1152, 864, 32, 8, 16, SEG_GRAPH } }, + { 0x175, { MM_DIRECT, 1280, 768, 16, 8, 16, SEG_GRAPH } }, + { 0x176, { MM_DIRECT, 1280, 768, 24, 8, 16, SEG_GRAPH } }, + { 0x177, { MM_DIRECT, 1280, 768, 32, 8, 16, SEG_GRAPH } }, { 0x178, { MM_DIRECT, 1280, 800, 16, 8, 16, SEG_GRAPH } }, { 0x179, { MM_DIRECT, 1280, 800, 24, 8, 16, SEG_GRAPH } }, { 0x17a, { MM_DIRECT, 1280, 800, 32, 8, 16, SEG_GRAPH } }, @@ -89,8 +93,16 @@ { 0x18a, { MM_DIRECT, 2560, 1600, 16, 8, 16, SEG_GRAPH } }, { 0x18b, { MM_DIRECT, 2560, 1600, 24, 8, 16, SEG_GRAPH } }, { 0x18c, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } }, + { 0x18d, { MM_DIRECT, 1280, 720, 16, 8, 16, SEG_GRAPH } }, + { 0x18e, { MM_DIRECT, 1280, 720, 24, 8, 16, SEG_GRAPH } }, + { 0x18f, { MM_DIRECT, 1280, 720, 32, 8, 16, SEG_GRAPH } }, + { 0x190, { MM_DIRECT, 1920, 1080, 16, 8, 16, SEG_GRAPH } }, + { 0x191, { MM_DIRECT, 1920, 1080, 24, 8, 16, SEG_GRAPH } }, + { 0x192, { MM_DIRECT, 1920, 1080, 32, 8, 16, SEG_GRAPH } }, }; +static int dispi_found VAR16 = 0; + static int is_bochsvga_mode(struct vgamode_s *vmode_g) { return (vmode_g >= &bochsvga_modes[0].info @@ -100,9 +112,10 @@ struct vgamode_s *bochsvga_find_mode(int mode) { struct bochsvga_mode *m = bochsvga_modes; - for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)]; m++) - if (GET_GLOBAL(m->mode) == mode) - return &m->info; + if (GET_GLOBAL(dispi_found)) + for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)]; m++) + if (GET_GLOBAL(m->mode) == mode) + return &m->info; return stdvga_find_mode(mode); } @@ -110,12 +123,14 @@ bochsvga_list_modes(u16 seg, u16 *dest, u16 *last) { struct bochsvga_mode *m = bochsvga_modes; - for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)] && destmode); - if (mode == 0xffff) - continue; - SET_FARVAR(seg, *dest, mode); - dest++; + if (GET_GLOBAL(dispi_found)) { + for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)] && destmode); + if (mode == 0xffff) + continue; + SET_FARVAR(seg, *dest, mode); + dest++; + } } stdvga_list_modes(seg, dest, last); } @@ -125,9 +140,22 @@ * Helper functions ****************************************************************/ +static inline u16 dispi_read(u16 reg) +{ + outw(reg, VBE_DISPI_IOPORT_INDEX); + return inw(VBE_DISPI_IOPORT_DATA); +} +static inline void dispi_write(u16 reg, u16 val) +{ + outw(reg, VBE_DISPI_IOPORT_INDEX); + outw(val, VBE_DISPI_IOPORT_DATA); +} + int bochsvga_get_window(struct vgamode_s *vmode_g, int window) { + if (!GET_GLOBAL(dispi_found)) + return stdvga_get_window(vmode_g, window); if (window != 0) return -1; return dispi_read(VBE_DISPI_INDEX_BANK); @@ -136,6 +164,8 @@ int bochsvga_set_window(struct vgamode_s *vmode_g, int window, int val) { + if (!GET_GLOBAL(dispi_found)) + return stdvga_set_window(vmode_g, window, val); if (window != 0) return -1; dispi_write(VBE_DISPI_INDEX_BANK, val); @@ -147,6 +177,8 @@ int bochsvga_get_linelength(struct vgamode_s *vmode_g) { + if (!GET_GLOBAL(dispi_found)) + return stdvga_get_linelength(vmode_g); return dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * vga_bpp(vmode_g) / 8; } @@ -154,14 +186,18 @@ bochsvga_set_linelength(struct vgamode_s *vmode_g, int val) { stdvga_set_linelength(vmode_g, val); - int pixels = (val * 8) / vga_bpp(vmode_g); - dispi_write(VBE_DISPI_INDEX_VIRT_WIDTH, pixels); + if (GET_GLOBAL(dispi_found)) { + int pixels = (val * 8) / vga_bpp(vmode_g); + dispi_write(VBE_DISPI_INDEX_VIRT_WIDTH, pixels); + } return 0; } int bochsvga_get_displaystart(struct vgamode_s *vmode_g) { + if (!GET_GLOBAL(dispi_found)) + return stdvga_get_displaystart(vmode_g); int bpp = vga_bpp(vmode_g); int linelength = dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * bpp / 8; int x = dispi_read(VBE_DISPI_INDEX_X_OFFSET); @@ -173,16 +209,22 @@ bochsvga_set_displaystart(struct vgamode_s *vmode_g, int val) { stdvga_set_displaystart(vmode_g, val); - int bpp = vga_bpp(vmode_g); - int linelength = dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * bpp / 8; - dispi_write(VBE_DISPI_INDEX_X_OFFSET, (val % linelength) * 8 / bpp); - dispi_write(VBE_DISPI_INDEX_Y_OFFSET, val / linelength); + if (GET_GLOBAL(dispi_found)) { + int bpp = vga_bpp(vmode_g); + int linelength = dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * bpp / 8; + if (!linelength) + return 0; + dispi_write(VBE_DISPI_INDEX_X_OFFSET, (val % linelength) * 8 / bpp); + dispi_write(VBE_DISPI_INDEX_Y_OFFSET, val / linelength); + } return 0; } int bochsvga_get_dacformat(struct vgamode_s *vmode_g) { + if (!GET_GLOBAL(dispi_found)) + return stdvga_get_dacformat(vmode_g); u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE); return (en & VBE_DISPI_8BIT_DAC) ? 8 : 6; } @@ -190,6 +232,8 @@ int bochsvga_set_dacformat(struct vgamode_s *vmode_g, int val) { + if (!GET_GLOBAL(dispi_found)) + return stdvga_set_dacformat(vmode_g, val); u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE); if (val == 6) en &= ~VBE_DISPI_8BIT_DAC; @@ -207,7 +251,7 @@ int size = stdvga_size_state(states); if (size < 0) return size; - if (states & 8) + if (GET_GLOBAL(dispi_found) && (states & 8)) size += (VBE_DISPI_INDEX_Y_OFFSET-VBE_DISPI_INDEX_XRES+1)*sizeof(u16); return size; } @@ -219,6 +263,8 @@ if (ret < 0) return ret; + if (!GET_GLOBAL(dispi_found)) + return 0; if (!(states & 8)) return 0; @@ -245,6 +291,8 @@ if (ret < 0) return ret; + if (!GET_GLOBAL(dispi_found)) + return 0; if (!(states & 8)) return 0; @@ -274,18 +322,20 @@ int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags) { - dispi_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); + if (GET_GLOBAL(dispi_found)) + dispi_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); if (! is_bochsvga_mode(vmode_g)) return stdvga_set_mode(vmode_g, flags); + if (!GET_GLOBAL(dispi_found)) + return -1; - u8 depth = GET_GLOBAL(vmode_g->depth); - if (depth == 4) + u8 memmodel = GET_GLOBAL(vmode_g->memmodel); + if (memmodel == MM_PLANAR) stdvga_set_mode(stdvga_find_mode(0x6a), 0); - if (depth == 8) - // XXX load_dac_palette(3); - ; + if (memmodel == MM_PACKED && !(flags & MF_NOPALETTE)) + stdvga_set_packed_palette(); - dispi_write(VBE_DISPI_INDEX_BPP, depth); + dispi_write(VBE_DISPI_INDEX_BPP, GET_GLOBAL(vmode_g->depth)); u16 width = GET_GLOBAL(vmode_g->width); u16 height = GET_GLOBAL(vmode_g->height); dispi_write(VBE_DISPI_INDEX_XRES, width); @@ -313,12 +363,13 @@ stdvga_attr_mask(0x10, 0x00, 0x01); stdvga_grdc_write(0x06, 0x05); stdvga_sequ_write(0x02, 0x0f); - if (depth >= 8) { + if (memmodel != MM_PLANAR) { stdvga_crtc_mask(crtc_addr, 0x14, 0x00, 0x40); stdvga_attr_mask(0x10, 0x00, 0x40); stdvga_sequ_mask(0x04, 0x00, 0x08); stdvga_grdc_mask(0x05, 0x20, 0x40); } + stdvga_attrindex_write(0x20); return 0; } @@ -329,20 +380,21 @@ ****************************************************************/ int -bochsvga_init(void) +bochsvga_setup(void) { - int ret = stdvga_init(); + int ret = stdvga_setup(); if (ret) return ret; /* Sanity checks */ dispi_write(VBE_DISPI_INDEX_ID, VBE_DISPI_ID0); if (dispi_read(VBE_DISPI_INDEX_ID) != VBE_DISPI_ID0) { - dprintf(1, "No VBE DISPI interface detected\n"); - return -1; + dprintf(1, "No VBE DISPI interface detected, falling back to stdvga\n"); + return 0; } dispi_write(VBE_DISPI_INDEX_ID, VBE_DISPI_ID5); + SET_VGA(dispi_found, 1); if (GET_GLOBAL(HaveRunInit)) return 0; @@ -364,6 +416,7 @@ SET_VGA(VBE_framebuffer, lfb_addr); u32 totalmem = dispi_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024; SET_VGA(VBE_total_memory, totalmem); + SET_VGA(VBE_win_granularity, 64); SET_VGA(VBE_capabilities, VBE_CAPABILITY_8BIT_DAC); dprintf(1, "VBE DISPI: lfb_addr=%x, size %d MB\n", @@ -381,7 +434,7 @@ u16 height = GET_GLOBAL(m->info.height); u8 depth = GET_GLOBAL(m->info.depth); u32 mem = (height * DIV_ROUND_UP(width * vga_bpp(&m->info), 8) - * 4 / stdvga_bpp_factor(&m->info)); + * stdvga_vram_ratio(&m->info)); if (width > max_xres || depth > max_bpp || mem > totalmem) { dprintf(1, "Removing mode %x\n", GET_GLOBAL(m->mode)); diff -Nru seabios-1.7.1/vgasrc/bochsvga.h seabios-1.7.4/vgasrc/bochsvga.h --- seabios-1.7.1/vgasrc/bochsvga.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/bochsvga.h 2013-12-23 15:40:06.000000000 +0000 @@ -2,7 +2,6 @@ #define __BOCHSVGA_H #include "types.h" // u8 -#include "ioport.h" // outw #define VBE_DISPI_BANK_ADDRESS 0xA0000 #define VBE_DISPI_BANK_SIZE_KB 64 @@ -41,17 +40,6 @@ #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 -static inline u16 dispi_read(u16 reg) -{ - outw(reg, VBE_DISPI_IOPORT_INDEX); - return inw(VBE_DISPI_IOPORT_DATA); -} -static inline void dispi_write(u16 reg, u16 val) -{ - outw(reg, VBE_DISPI_IOPORT_INDEX); - outw(val, VBE_DISPI_IOPORT_DATA); -} - struct vgamode_s *bochsvga_find_mode(int mode); void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last); int bochsvga_get_window(struct vgamode_s *vmode_g, int window); @@ -66,6 +54,6 @@ int bochsvga_save_state(u16 seg, void *data, int states); int bochsvga_restore_state(u16 seg, void *data, int states); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags); -int bochsvga_init(void); +int bochsvga_setup(void); #endif // bochsvga.h diff -Nru seabios-1.7.1/vgasrc/clext.c seabios-1.7.4/vgasrc/clext.c --- seabios-1.7.1/vgasrc/clext.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/clext.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,14 +5,15 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "clext.h" // clext_init -#include "vgabios.h" // VBE_VENDOR_STRING #include "biosvar.h" // GET_GLOBAL -#include "util.h" // dprintf #include "bregs.h" // struct bregs +#include "clext.h" // clext_setup +#include "hw/pci.h" // pci_config_readl +#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "output.h" // dprintf #include "stdvga.h" // VGAREG_SEQU_ADDRESS -#include "pci.h" // pci_config_readl -#include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "string.h" // memset16_far +#include "vgabios.h" // VBE_VENDOR_STRING /**************************************************************** @@ -328,17 +329,16 @@ u16 crtc_addr = stdvga_get_crtc(); u8 reg13 = stdvga_crtc_read(crtc_addr, 0x13); u8 reg1b = stdvga_crtc_read(crtc_addr, 0x1b); - return (((reg1b & 0x10) << 4) + reg13) * stdvga_bpp_factor(vmode_g) * 2; + return (((reg1b & 0x10) << 4) + reg13) * 8 / stdvga_vram_ratio(vmode_g); } int clext_set_linelength(struct vgamode_s *vmode_g, int val) { u16 crtc_addr = stdvga_get_crtc(); - int factor = stdvga_bpp_factor(vmode_g) * 2; - int new_line_offset = DIV_ROUND_UP(val, factor); - stdvga_crtc_write(crtc_addr, 0x13, new_line_offset); - stdvga_crtc_mask(crtc_addr, 0x1b, 0x10, (new_line_offset & 0x100) >> 4); + val = DIV_ROUND_UP(val * stdvga_vram_ratio(vmode_g), 8); + stdvga_crtc_write(crtc_addr, 0x13, val); + stdvga_crtc_mask(crtc_addr, 0x1b, 0x10, (val & 0x100) >> 4); return 0; } @@ -352,14 +352,14 @@ u8 b4 = stdvga_crtc_read(crtc_addr, 0x1d); int val = (b1 | (b2<<8) | ((b3 & 0x01) << 16) | ((b3 & 0x0c) << 15) | ((b4 & 0x80) << 12)); - return val * stdvga_bpp_factor(vmode_g); + return val * 4 / stdvga_vram_ratio(vmode_g); } int clext_set_displaystart(struct vgamode_s *vmode_g, int val) { u16 crtc_addr = stdvga_get_crtc(); - val /= stdvga_bpp_factor(vmode_g); + val = val * stdvga_vram_ratio(vmode_g) / 4; stdvga_crtc_write(crtc_addr, 0x0d, val); stdvga_crtc_write(crtc_addr, 0x0c, val >> 8); stdvga_crtc_mask(crtc_addr, 0x1d, 0x80, (val & 0x0800) >> 4); @@ -433,6 +433,7 @@ else if (memmodel != MM_TEXT) on = 0x01; stdvga_attr_mask(0x10, 0x01, on); + stdvga_attrindex_write(0x20); } static void @@ -442,14 +443,14 @@ } static void -cirrus_clear_vram(void) +cirrus_clear_vram(u16 fill) { cirrus_enable_16k_granularity(); - u8 count = GET_GLOBAL(VBE_total_memory) / (16 * 1024); - u8 i; + int count = GET_GLOBAL(VBE_total_memory) / (16 * 1024); + int i; for (i=0; imemmodel) == MM_PACKED && !(flags & MF_NOPALETTE)) + stdvga_set_packed_palette(); if (!(flags & MF_LINEARFB)) cirrus_enable_16k_granularity(); if (!(flags & MF_NOCLEARMEM)) - cirrus_clear_vram(); + // fill with 0xff to keep win 2K happy + cirrus_clear_vram(flags & MF_LEGACY ? 0xffff : 0x0000); return 0; } @@ -603,9 +607,9 @@ } int -clext_init(void) +clext_setup(void) { - int ret = stdvga_init(); + int ret = stdvga_setup(); if (ret) return ret; diff -Nru seabios-1.7.1/vgasrc/clext.h seabios-1.7.4/vgasrc/clext.h --- seabios-1.7.1/vgasrc/clext.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/clext.h 2013-12-23 15:40:06.000000000 +0000 @@ -17,6 +17,6 @@ int clext_set_mode(struct vgamode_s *vmode_g, int flags); struct bregs; void clext_1012(struct bregs *regs); -int clext_init(void); +int clext_setup(void); #endif // clext.h diff -Nru seabios-1.7.1/vgasrc/geodevga.c seabios-1.7.4/vgasrc/geodevga.c --- seabios-1.7.1/vgasrc/geodevga.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/geodevga.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,21 +6,21 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "geodevga.h" // geodevga_init -#include "farptr.h" // SET_FARVAR #include "biosvar.h" // GET_BDA -#include "vgabios.h" // VGAREG_* -#include "util.h" // memset +#include "farptr.h" // SET_FARVAR +#include "geodevga.h" // geodevga_setup +#include "hw/pci.h" // pci_config_readl +#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "output.h" // dprintf #include "stdvga.h" // stdvga_crtc_write -#include "pci.h" // pci_config_readl -#include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "vgabios.h" // VGAREG_* /**************************************************************** * MSR and High Mem access through VSA Virtual Register ****************************************************************/ -static union u64_u32_u geode_msrRead(u32 msrAddr) +static u64 geode_msr_read(u32 msrAddr) { union u64_u32_u val; asm __volatile__ ( @@ -33,11 +33,21 @@ : "c"(msrAddr) : "cc" ); - return val; + + dprintf(4, "%s(0x%08x) = 0x%08x-0x%08x\n" + , __func__, msrAddr, val.hi, val.lo); + return val.val; } -static void geode_msrWrite(u32 msrAddr,u32 andhi, u32 andlo, u32 orhi, u32 orlo) +static void geode_msr_mask(u32 msrAddr, u64 off, u64 on) { + union u64_u32_u uand, uor; + uand.val = ~off; + uor.val = on; + + dprintf(4, "%s(0x%08x, 0x%016llx, 0x%016llx)\n" + , __func__, msrAddr, off, on); + asm __volatile__ ( "push %%eax \n" "movw $0x0AC1C, %%dx \n" @@ -47,12 +57,12 @@ "pop %%eax \n" "outw %%ax, %%dx \n" : - : "c"(msrAddr), "S" (andhi), "D" (andlo), "b" (orhi), "a" (orlo) + : "c"(msrAddr), "S" (uand.hi), "D" (uand.lo), "b" (uor.hi), "a" (uor.lo) : "%edx","cc" ); } -static u32 geode_memRead(u32 addr) +static u32 geode_mem_read(u32 addr) { u32 val; asm __volatile__ ( @@ -69,7 +79,7 @@ return val; } -static void geode_memWrite(u32 addr, u32 and, u32 or ) +static void geode_mem_mask(u32 addr, u32 off, u32 or) { asm __volatile__ ( "movw $0x0AC1C, %%dx \n" @@ -78,167 +88,179 @@ "addb $2, %%dl \n" "outw %%ax, %%dx \n" : - : "b"(addr), "S" (and), "D" (or) + : "b"(addr), "S" (~off), "D" (or) : "%eax","cc" ); } -static int legacyio_check(void) -{ - int ret=0; - union u64_u32_u val; - - if (CONFIG_VGA_GEODEGX2) - val=geode_msrRead(GLIU0_P2D_BM_4); - else - val=geode_msrRead(MSR_GLIU0_BASE4); - if (val.lo != 0x0A0fffe0) - ret|=1; - - val=geode_msrRead(GLIU0_IOD_BM_0); - if (val.lo != 0x3c0ffff0) - ret|=2; +#define VP_FP_START 0x400 - val=geode_msrRead(GLIU0_IOD_BM_1); - if (val.lo != 0x3d0ffff0) - ret|=4; +static u32 GeodeFB VAR16; +static u32 GeodeDC VAR16; +static u32 GeodeVP VAR16; - return ret; +static u32 geode_dc_read(int reg) +{ + u32 val = geode_mem_read(GET_GLOBAL(GeodeDC) + reg); + dprintf(4, "%s(0x%08x) = 0x%08x\n" + , __func__, GET_GLOBAL(GeodeDC) + reg, val); + return val; } -/**************************************************************** -* Extened CRTC Register functions -****************************************************************/ -static void crtce_lock(void) +static void geode_dc_write(int reg, u32 val) { - stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK - , CRTCE_LOCK); + dprintf(4, "%s(0x%08x, 0x%08x)\n" + , __func__, GET_GLOBAL(GeodeDC) + reg, val); + geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, ~0, val); } -static void crtce_unlock(void) +static void geode_dc_mask(int reg, u32 off, u32 on) { - stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK - , CRTCE_UNLOCK); + dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n" + , __func__, GET_GLOBAL(GeodeDC) + reg, off, on); + geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, off, on); } -static u8 crtce_read(u8 reg) +static u32 geode_vp_read(int reg) { - crtce_unlock(); - u8 val = stdvga_crtc_read(VGAREG_VGA_CRTC_ADDRESS, reg); - crtce_lock(); + u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + reg); + dprintf(4, "%s(0x%08x) = 0x%08x\n" + , __func__, GET_GLOBAL(GeodeVP) + reg, val); return val; } -static void crtce_write(u8 reg, u8 val) +static void geode_vp_write(int reg, u32 val) { - crtce_unlock(); - stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, reg, val); - crtce_lock(); + dprintf(4, "%s(0x%08x, 0x%08x)\n" + , __func__, GET_GLOBAL(GeodeVP) + reg, val); + geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, ~0, val); } -/**************************************************************** -* Display Controller Functions -****************************************************************/ -static u32 dc_read(u16 seg, u32 reg) +static void geode_vp_mask(int reg, u32 off, u32 on) { - u32 val, *dest_far = (void*)reg; - val = GET_FARVAR(seg,*dest_far); - return val; + dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n" + , __func__, GET_GLOBAL(GeodeVP) + reg, off, on); + geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, off, on); } -static void dc_write(u16 seg, u32 reg, u32 val) +static u32 geode_fp_read(int reg) { - u32 *dest_far = (void*)reg; - SET_FARVAR(seg,*dest_far,val); + u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + VP_FP_START + reg); + dprintf(4, "%s(0x%08x) = 0x%08x\n" + , __func__, GET_GLOBAL(GeodeVP) + VP_FP_START + reg, val); + return val; } -static void dc_set(u16 seg, u32 reg, u32 and, u32 or) +static void geode_fp_write(int reg, u32 val) { - u32 val = dc_read(seg,reg); - val &=and; - val |=or; - dc_write(seg,reg,val); + dprintf(4, "%s(0x%08x, 0x%08x)\n" + , __func__, GET_GLOBAL(GeodeVP) + VP_FP_START + reg, val); + geode_mem_mask(GET_GLOBAL(GeodeVP) + VP_FP_START + reg, ~0, val); } -static void dc_unlock(u16 seg) -{ - dc_write(seg,DC_UNLOCK,DC_LOCK_UNLOCK); -} +/**************************************************************** + * Helper functions + ****************************************************************/ -static void dc_lock(u16 seg) +static int legacyio_check(void) { - dc_write(seg,DC_UNLOCK,DC_LOCK_LOCK); -} + int ret=0; + u64 val; -static u16 dc_map(u16 seg) -{ - u8 reg; + if (CONFIG_VGA_GEODEGX2) + val = geode_msr_read(GLIU0_P2D_BM_4); + else + val = geode_msr_read(MSR_GLIU0_BASE4); + if ((val & 0xffffffff) != 0x0A0fffe0) + ret|=1; - reg = crtce_read(EXTENDED_MODE_CONTROL); - reg &= 0xf9; - switch (seg) { - case SEG_GRAPH: - reg |= 0x02; - break; - case SEG_MTEXT: - reg |= 0x04; - break; - case SEG_CTEXT: - reg |= 0x06; - break; - default: - seg=0; - break; - } + val = geode_msr_read(GLIU0_IOD_BM_0); + if ((val & 0xffffffff) != 0x3c0ffff0) + ret|=2; + + val = geode_msr_read(GLIU0_IOD_BM_1); + if ((val & 0xffffffff) != 0x3d0ffff0) + ret|=4; - crtce_write(EXTENDED_MODE_CONTROL,reg); - return seg; + return ret; } -static void dc_unmap(void) +static u32 framebuffer_size(void) { - dc_map(0); -} + /* We use the P2D_R0 msr to read out the number of pages. + * One page has a size of 4k + * + * Bit Name Description + * 39:20 PMAX Physical Memory Address Max + * 19:0 PMIX Physical Memory Address Min + * + */ + u64 msr = geode_msr_read(GLIU0_P2D_RO); + u32 pmax = (msr >> 20) & 0x000fffff; + u32 pmin = msr & 0x000fffff; + + u32 val = pmax - pmin; + val += 1; + + /* The page size is 4k */ + return (val << 12); +} /**************************************************************** * Init Functions ****************************************************************/ +static void geodevga_set_output_mode(void) +{ + u64 msr_addr; + u64 msr; + + /* set output to crt and RGB/YUV */ + if (CONFIG_VGA_GEODEGX2) + msr_addr = VP_MSR_CONFIG_GX2; + else + msr_addr = VP_MSR_CONFIG_LX; + + /* set output mode (RGB/YUV) */ + msr = geode_msr_read(msr_addr); + msr &= ~VP_MSR_CONFIG_FMT; // mask out FMT (bits 5:3) + + if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) { + msr |= VP_MSR_CONFIG_FMT_FP; // flat panel + + if (CONFIG_VGA_OUTPUT_CRT_PANEL) { + msr |= VP_MSR_CONFIG_FPC; // simultaneous Flat Panel and CRT + dprintf(1, "output: simultaneous Flat Panel and CRT\n"); + } else { + msr &= ~VP_MSR_CONFIG_FPC; // no simultaneous Flat Panel and CRT + dprintf(1, "ouput: flat panel\n"); + } + } else { + msr |= VP_MSR_CONFIG_FMT_CRT; // CRT only + dprintf(1, "output: CRT\n"); + } + geode_msr_mask(msr_addr, ~msr, msr); +} + /* Set up the dc (display controller) portion of the geodelx -* The dc provides hardware support for VGA graphics -* for features not accessible from the VGA registers, -* the dc's pci bar can be mapped to a vga memory segment +* The dc provides hardware support for VGA graphics. */ -static int dc_setup(void) +static void dc_setup(void) { - u32 fb, dc_fb; - u16 seg; - dprintf(2, "DC_SETUP\n"); - seg = dc_map(SEG_GRAPH); - dc_unlock(seg); + geode_dc_write(DC_UNLOCK, DC_LOCK_UNLOCK); /* zero memory config */ - dc_write(seg,DC_FB_ST_OFFSET,0x0); - dc_write(seg,DC_CB_ST_OFFSET,0x0); - dc_write(seg,DC_CURS_ST_OFFSET,0x0); + geode_dc_write(DC_FB_ST_OFFSET, 0x0); + geode_dc_write(DC_CB_ST_OFFSET, 0x0); + geode_dc_write(DC_CURS_ST_OFFSET, 0x0); - /* read fb-bar from pci, then point dc to the fb base */ - dc_fb = dc_read(seg,DC_GLIU0_MEM_OFFSET); - fb = pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_0); - if (fb!=dc_fb) { - dc_write(seg,DC_GLIU0_MEM_OFFSET,fb); - } + geode_dc_mask(DC_DISPLAY_CFG, ~DC_CFG_MSK, DC_DISPLAY_CFG_GDEN|DC_DISPLAY_CFG_TRUP); + geode_dc_write(DC_GENERAL_CFG, DC_GENERAL_CFG_VGAE); - dc_set(seg,DC_DISPLAY_CFG,DC_CFG_MSK,DC_GDEN+DC_TRUP); - dc_set(seg,DC_GENERAL_CFG,0,DC_VGAE); - - dc_lock(seg); - dc_unmap(); - - return 0; + geode_dc_write(DC_UNLOCK, DC_LOCK_LOCK); } /* Setup the vp (video processor) portion of the geodelx @@ -247,38 +269,49 @@ * The High Mem Access virtual register is used to configure the * pci mmio bar from 16bit friendly io space. */ -int vp_setup(void) +static void vp_setup(void) { - u32 reg,vp; - dprintf(2,"VP_SETUP\n"); - /* set output to crt and RGB/YUV */ - if (CONFIG_VGA_GEODEGX2) - geode_msrWrite(VP_MSR_CONFIG_GX2, ~0, ~0xf8, 0, 0); - else - geode_msrWrite(VP_MSR_CONFIG_LX, ~0, ~0xf8, 0, 0); - /* get vp register base from pci */ - vp = pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_3); + geodevga_set_output_mode(); /* Set mmio registers * there may be some timing issues here, the reads seem * to slow things down enough work reliably */ - reg = geode_memRead(vp+VP_MISC); + u32 reg = geode_vp_read(VP_MISC); dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg); - geode_memWrite(vp+VP_MISC,0,VP_BYP_BOTH); - reg = geode_memRead(vp+VP_MISC); + geode_vp_write(VP_MISC, VP_DCFG_BYP_BOTH); + reg = geode_vp_read(VP_MISC); dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg); - reg = geode_memRead(vp+VP_DCFG); + reg = geode_vp_read(VP_DCFG); dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg); - geode_memWrite(vp+VP_DCFG, ~0,VP_CRT_EN+VP_HSYNC_EN+VP_VSYNC_EN+VP_DAC_BL_EN+VP_CRT_SKEW); - reg = geode_memRead(vp+VP_DCFG); + geode_vp_mask(VP_DCFG, 0, VP_DCFG_CRT_EN|VP_DCFG_HSYNC_EN|VP_DCFG_VSYNC_EN|VP_DCFG_DAC_BL_EN|VP_DCFG_CRT_SKEW); + reg = geode_vp_read(VP_DCFG); dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg); - return 0; + /* setup flat panel */ + if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) { + u64 msr; + + dprintf(1, "Setting up flat panel\n"); + /* write timing register */ + geode_fp_write(FP_PT1, 0x0); + geode_fp_write(FP_PT2, FP_PT2_SCRC); + + /* set pad select for TFT/LVDS */ + msr = VP_MSR_PADSEL_TFT_SEL_HIGH; + msr = msr << 32; + msr |= VP_MSR_PADSEL_TFT_SEL_LOW; + geode_msr_mask(VP_MSR_PADSEL, ~msr, msr); + + /* turn the panel on (if it isn't already) */ + reg = geode_fp_read(FP_PM); + reg |= FP_PM_P; + geode_fp_write(FP_PM, reg); + } } static u8 geode_crtc_01[] VAR16 = { @@ -337,16 +370,16 @@ 0x9b, 0x8d, 0x8f, 0x28, 0x40, 0x98, 0xb9, 0xa3, 0xff }; -int geodevga_init(void) +int geodevga_setup(void) { - int ret = stdvga_init(); + int ret = stdvga_setup(); if (ret) return ret; - dprintf(1,"GEODEVGA_INIT\n"); + dprintf(1,"GEODEVGA_SETUP\n"); if ((ret=legacyio_check())) { - dprintf(1,"GEODEVGA_INIT legacyio_check=0x%x\n",ret); + dprintf(1,"GEODEVGA_SETUP legacyio_check=0x%x\n",ret); } // Updated timings from geode datasheets, table 6-53 in particular @@ -366,8 +399,35 @@ if (GET_GLOBAL(VgaBDF) < 0) // Device should be at 00:01.1 SET_VGA(VgaBDF, pci_to_bdf(0, 1, 1)); - ret |= vp_setup(); - ret |= dc_setup(); - return ret; + // setup geode struct which is used for register access + SET_VGA(GeodeFB, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_0)); + SET_VGA(GeodeDC, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_2)); + SET_VGA(GeodeVP, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_3)); + + dprintf(1, "fb addr: 0x%08x\n", GET_GLOBAL(GeodeFB)); + dprintf(1, "dc addr: 0x%08x\n", GET_GLOBAL(GeodeDC)); + dprintf(1, "vp addr: 0x%08x\n", GET_GLOBAL(GeodeVP)); + + /* setup framebuffer */ + geode_dc_write(DC_UNLOCK, DC_LOCK_UNLOCK); + + /* read fb-bar from pci, then point dc to the fb base */ + u32 fb = GET_GLOBAL(GeodeFB); + if (geode_dc_read(DC_GLIU0_MEM_OFFSET) != fb) + geode_dc_write(DC_GLIU0_MEM_OFFSET, fb); + + geode_dc_write(DC_UNLOCK, DC_LOCK_LOCK); + + u32 fb_size = framebuffer_size(); // in byte + dprintf(1, "%d KB of video memory at 0x%08x\n", fb_size / 1024, fb); + + /* update VBE variables */ + SET_VGA(VBE_framebuffer, fb); + SET_VGA(VBE_total_memory, fb_size / 1024 / 64); // number of 64K blocks + + vp_setup(); + dc_setup(); + + return 0; } diff -Nru seabios-1.7.1/vgasrc/geodevga.h seabios-1.7.4/vgasrc/geodevga.h --- seabios-1.7.1/vgasrc/geodevga.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/geodevga.h 2013-12-23 15:40:06.000000000 +0000 @@ -13,13 +13,6 @@ #define VRC_DATA 0xAC1E // Data register #define VR_UNLOCK 0xFC53 // Virtual register unlock code -#define EXTENDED_REGISTER_LOCK 0x30 -#define EXTENDED_MODE_CONTROL 0x43 -#define EXTENDED_START_ADDR 0x44 - -#define CRTCE_UNLOCK 0x4c -#define CRTCE_LOCK 0xff - // Graphics-specific registers: #define OEM_BAR0 0x50 #define OEM_BAR1 0x54 @@ -33,11 +26,23 @@ #define MSR_GLIU0 (1 << 28) #define MSR_GLIU0_BASE4 (MSR_GLIU0 + 0x23) /* LX */ #define GLIU0_P2D_BM_4 (MSR_GLIU0 + 0x24) /* GX2 */ +#define GLIU0_P2D_RO (MSR_GLIU0 + 0x29) #define GLIU0_IOD_BM_0 (MSR_GLIU0 + 0xE0) #define GLIU0_IOD_BM_1 (MSR_GLIU0 + 0xE1) #define DC_SPARE 0x80000011 #define VP_MSR_CONFIG_GX2 0xc0002001 /* GX2 */ #define VP_MSR_CONFIG_LX 0x48002001 /* LX */ +#define VP_MSR_PADSEL 0x48002011 + +#define VP_MSR_PADSEL_TFT_SEL_LOW 0xDFFFFFFF +#define VP_MSR_PADSEL_TFT_SEL_HIGH 0x0000003F + +/* VP_MSR_CONFIG bits */ +#define VP_MSR_CONFIG_FMT_CRT (0) +#define VP_MSR_CONFIG_FMT_FP (1 << 3) +#define VP_MSR_CONFIG_FPC (1 << 15) +#define VP_MSR_CONFIG_FMT ((1 << 3) | (1 << 4) | (1 << 5)) + /* DC REG OFFSET */ #define DC_UNLOCK 0x0 @@ -53,23 +58,32 @@ #define VP_DCFG 0x8 #define VP_MISC 0x50 +/* FP REG OFFSET */ +#define FP_PT1 0x00 +#define FP_PT2 0x08 +#define FP_PM 0x10 + /* DC bits */ -#define DC_VGAE (1 << 7) -#define DC_GDEN (1 << 3) -#define DC_TRUP (1 << 6) +#define DC_GENERAL_CFG_VGAE (1 << 7) +#define DC_DISPLAY_CFG_GDEN (1 << 3) +#define DC_DISPLAY_CFG_TRUP (1 << 6) /* VP bits */ -#define VP_CRT_EN (1 << 0) -#define VP_HSYNC_EN (1 << 1) -#define VP_VSYNC_EN (1 << 2) -#define VP_DAC_BL_EN (1 << 3) -#define VP_CRT_SKEW (1 << 16) -#define VP_BYP_BOTH (1 << 0) +#define VP_DCFG_CRT_EN (1 << 0) +#define VP_DCFG_HSYNC_EN (1 << 1) +#define VP_DCFG_VSYNC_EN (1 << 2) +#define VP_DCFG_DAC_BL_EN (1 << 3) +#define VP_DCFG_CRT_SKEW (1 << 16) +#define VP_DCFG_BYP_BOTH (1 << 0) + +/* FP bits */ +#define FP_PM_P (1 << 24) /* panel power ctl */ +#define FP_PT2_SCRC (1 << 27) /* panel shift clock retrace activity ctl */ /* Mask */ #define DC_CFG_MSK 0xf000a6 -int geodevga_init(); +int geodevga_setup(); #endif diff -Nru seabios-1.7.1/vgasrc/Kconfig seabios-1.7.4/vgasrc/Kconfig --- seabios-1.7.1/vgasrc/Kconfig 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/Kconfig 2013-12-23 15:40:06.000000000 +0000 @@ -11,14 +11,14 @@ Do not build a VGA BIOS. config VGA_STANDARD_VGA - depends on !COREBOOT + depends on QEMU bool "QEMU/Bochs Original IBM 256K VGA" help Build basic VGA BIOS support (pre Super-VGA) for use on emulators. config VGA_CIRRUS - depends on !COREBOOT + depends on QEMU bool "QEMU/Bochs Cirrus SVGA" help Build support for Cirrus VGA emulation found on QEMU @@ -26,7 +26,7 @@ intended for use on real Cirrus hardware. config VGA_BOCHS - depends on !COREBOOT + depends on QEMU bool "QEMU/Bochs VBE SVGA" help Build support for Bochs DISPI interface (a custom VBE @@ -43,10 +43,45 @@ Build support for Geode LX vga. endchoice + choice + depends on VGA_GEODEGX2 || VGA_GEODELX + prompt "Output Mode" + default VGA_OUTPUT_CRT + + config VGA_OUTPUT_CRT + bool "CRT" + help + Use CRT for output. + + config VGA_OUTPUT_PANEL + bool "Flat Panel" + help + Use flat panel for output. + + config VGA_OUTPUT_CRT_PANEL + bool "CRT and Flat Panel" + help + Use CRT and flat panel for output. + endchoice + config BUILD_VGABIOS bool default !NO_VGABIOS + config VGA_ALLOCATE_EXTRA_STACK + depends on BUILD_VGABIOS + bool "Allocate an internal stack for 16bit interrupt entry point" + default y + help + Attempt to allocate (via BIOS PMM call) an internal stack + for the legacy 16bit 0x10 interrupt entry point. This + reduces the amount of space on the caller's stack that + SeaVGABIOS uses. + + config VGA_EXTRA_STACK_SIZE + int + default 512 + config VGA_VBE depends on BUILD_VGABIOS bool "Video BIOS Extensions (VBE)" diff -Nru seabios-1.7.1/vgasrc/stdvga.c seabios-1.7.4/vgasrc/stdvga.c --- seabios-1.7.1/vgasrc/stdvga.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/stdvga.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,12 +5,12 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "vgabios.h" // struct vgamode_s -#include "stdvga.h" // stdvga_init -#include "ioport.h" // outb -#include "farptr.h" // SET_FARVAR #include "biosvar.h" // GET_GLOBAL -#include "util.h" // memcpy_far +#include "farptr.h" // SET_FARVAR +#include "stdvga.h" // stdvga_setup +#include "string.h" // memset_far +#include "vgabios.h" // struct vgamode_s +#include "x86.h" // outb /**************************************************************** @@ -123,6 +123,7 @@ u16 intensity = ((77 * rgb[0] + 151 * rgb[1] + 28 * rgb[2]) + 0x80) >> 8; if (intensity > 0x3f) intensity = 0x3f; + rgb[0] = rgb[1] = rgb[2] = intensity; stdvga_dac_write(GET_SEG(SS), rgb, i, 1); } @@ -211,19 +212,19 @@ return VGAREG_MDA_CRTC_ADDRESS; } -// Return the multiplication factor needed for the vga offset register. +// Ratio between system visible framebuffer ram and the actual videoram used. int -stdvga_bpp_factor(struct vgamode_s *vmode_g) +stdvga_vram_ratio(struct vgamode_s *vmode_g) { switch (GET_GLOBAL(vmode_g->memmodel)) { case MM_TEXT: return 2; case MM_CGA: - return GET_GLOBAL(vmode_g->depth); + return 4 / GET_GLOBAL(vmode_g->depth); case MM_PLANAR: - return 1; - default: return 4; + default: + return 1; } } @@ -277,14 +278,14 @@ stdvga_get_linelength(struct vgamode_s *vmode_g) { u8 val = stdvga_crtc_read(stdvga_get_crtc(), 0x13); - return val * stdvga_bpp_factor(vmode_g) * 2; + return val * 8 / stdvga_vram_ratio(vmode_g); } int stdvga_set_linelength(struct vgamode_s *vmode_g, int val) { - int factor = stdvga_bpp_factor(vmode_g) * 2; - stdvga_crtc_write(stdvga_get_crtc(), 0x13, DIV_ROUND_UP(val, factor)); + val = DIV_ROUND_UP(val * stdvga_vram_ratio(vmode_g), 8); + stdvga_crtc_write(stdvga_get_crtc(), 0x13, val); return 0; } @@ -294,14 +295,14 @@ u16 crtc_addr = stdvga_get_crtc(); int addr = (stdvga_crtc_read(crtc_addr, 0x0c) << 8 | stdvga_crtc_read(crtc_addr, 0x0d)); - return addr * stdvga_bpp_factor(vmode_g); + return addr * 4 / stdvga_vram_ratio(vmode_g); } int stdvga_set_displaystart(struct vgamode_s *vmode_g, int val) { u16 crtc_addr = stdvga_get_crtc(); - val /= stdvga_bpp_factor(vmode_g); + val = val * stdvga_vram_ratio(vmode_g) / 4; stdvga_crtc_write(crtc_addr, 0x0c, val >> 8); stdvga_crtc_write(crtc_addr, 0x0d, val); return 0; @@ -490,7 +491,7 @@ } int -stdvga_init(void) +stdvga_setup(void) { // switch to color mode and enable CPU access 480 lines stdvga_misc_write(0xc3); diff -Nru seabios-1.7.1/vgasrc/stdvga.h seabios-1.7.4/vgasrc/stdvga.h --- seabios-1.7.1/vgasrc/stdvga.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/stdvga.h 2013-12-23 15:40:06.000000000 +0000 @@ -50,6 +50,7 @@ void stdvga_build_video_param(void); void stdvga_override_crtc(int mode, u8 *crtc); int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); +void stdvga_set_packed_palette(void); // stdvgaio.c u8 stdvga_pelmask_read(void); @@ -90,7 +91,7 @@ void stdvga_load_font(u16 seg, void *src_far, u16 count , u16 start, u8 destflags, u8 fontsize); u16 stdvga_get_crtc(void); -int stdvga_bpp_factor(struct vgamode_s *vmode_g); +int stdvga_vram_ratio(struct vgamode_s *vmode_g); void stdvga_set_cursor_shape(u8 start, u8 end); void stdvga_set_cursor_pos(int address); void stdvga_set_scan_lines(u8 lines); @@ -107,6 +108,6 @@ int stdvga_save_state(u16 seg, void *data, int states); int stdvga_restore_state(u16 seg, void *data, int states); void stdvga_enable_video_addressing(u8 disable); -int stdvga_init(void); +int stdvga_setup(void); #endif // stdvga.h diff -Nru seabios-1.7.1/vgasrc/stdvgaio.c seabios-1.7.4/vgasrc/stdvgaio.c --- seabios-1.7.1/vgasrc/stdvgaio.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/stdvgaio.c 2013-12-23 15:40:06.000000000 +0000 @@ -4,9 +4,9 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "stdvga.h" // stdvga_pelmask_read #include "farptr.h" // GET_FARVAR -#include "ioport.h" // inb +#include "stdvga.h" // stdvga_pelmask_read +#include "x86.h" // inb u8 stdvga_pelmask_read(void) diff -Nru seabios-1.7.1/vgasrc/stdvgamodes.c seabios-1.7.4/vgasrc/stdvgamodes.c --- seabios-1.7.1/vgasrc/stdvgamodes.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/stdvgamodes.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,10 +5,11 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "vgabios.h" // struct VideoParamTableEntry_s #include "biosvar.h" // GET_GLOBAL -#include "util.h" // memcpy_far +#include "output.h" // warn_internalerror #include "stdvga.h" // stdvga_find_mode +#include "string.h" // memcpy_far +#include "vgabios.h" // struct VideoParamTableEntry_s /**************************************************************** @@ -334,6 +335,16 @@ void stdvga_list_modes(u16 seg, u16 *dest, u16 *last) { + int i; + for (i = 0; i < ARRAY_SIZE(vga_modes); i++) { + struct stdvga_mode_s *stdmode_g = &vga_modes[i]; + u16 mode = GET_GLOBAL(stdmode_g->mode); + if (mode == 0xffff) + continue; + SET_FARVAR(seg, *dest, mode); + dest++; + } + SET_FARVAR(seg, *dest, 0xffff); } @@ -494,3 +505,10 @@ return 0; } + +// Load the standard palette associated with 8bpp packed pixel vga modes. +void +stdvga_set_packed_palette(void) +{ + stdvga_dac_write(get_global_seg(), palette3, 0, sizeof(palette3) / 3); +} diff -Nru seabios-1.7.1/vgasrc/vbe.c seabios-1.7.4/vgasrc/vbe.c --- seabios-1.7.1/vgasrc/vbe.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/vbe.c 2013-12-23 15:40:06.000000000 +0000 @@ -6,18 +6,19 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "vgabios.h" // handle_104f -#include "config.h" // CONFIG_* -#include "bregs.h" // struct bregs -#include "vbe.h" // struct vbe_info -#include "util.h" // dprintf #include "biosvar.h" // GET_GLOBAL +#include "bregs.h" // struct bregs +#include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "std/vbe.h" // struct vbe_info +#include "string.h" // memset_far +#include "vgabios.h" // handle_104f #include "vgahw.h" // vgahw_set_mode u32 VBE_total_memory VAR16 = 256 * 1024; u32 VBE_capabilities VAR16; u32 VBE_framebuffer VAR16; -u16 VBE_win_granularity VAR16 = 64; +u16 VBE_win_granularity VAR16; static void vbe_104f00(struct bregs *regs) @@ -74,7 +75,7 @@ dprintf(1, "VBE mode info request: %x\n", mode); - struct vgamode_s *vmode_g = vgahw_find_mode(mode); + struct vgamode_s *vmode_g = vgahw_find_mode(mode & ~MF_VBEFLAGS); if (! vmode_g) { dprintf(1, "VBE mode %x not found\n", mode); regs->ax = 0x014f; @@ -82,27 +83,22 @@ } memset_far(seg, info, 0, sizeof(*info)); - u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED | - VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | - VBE_MODE_ATTRIBUTE_COLOR_MODE | - VBE_MODE_ATTRIBUTE_GRAPHICS_MODE | - VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE; - u32 framebuffer = GET_GLOBAL(VBE_framebuffer); - if (framebuffer) - mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE; - SET_FARVAR(seg, info->mode_attributes, mode_attr); + + // Basic information about video controller. + u32 win_granularity = GET_GLOBAL(VBE_win_granularity); SET_FARVAR(seg, info->winA_attributes, - VBE_WINDOW_ATTRIBUTE_RELOCATABLE | + (win_granularity ? VBE_WINDOW_ATTRIBUTE_RELOCATABLE : 0) | VBE_WINDOW_ATTRIBUTE_READABLE | VBE_WINDOW_ATTRIBUTE_WRITEABLE); SET_FARVAR(seg, info->winB_attributes, 0); - SET_FARVAR(seg, info->win_granularity, GET_GLOBAL(VBE_win_granularity)); + SET_FARVAR(seg, info->win_granularity, win_granularity); SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */ SET_FARVAR(seg, info->winA_seg, GET_GLOBAL(vmode_g->sstart)); SET_FARVAR(seg, info->winB_seg, 0x0); extern void entry_104f05(void); SET_FARVAR(seg, info->win_func_ptr , SEGOFF(get_global_seg(), (u32)entry_104f05)); + // Basic information about mode. int width = GET_GLOBAL(vmode_g->width); int height = GET_GLOBAL(vmode_g->height); int linesize = DIV_ROUND_UP(width * vga_bpp(vmode_g), 8); @@ -112,18 +108,54 @@ SET_FARVAR(seg, info->xcharsize, GET_GLOBAL(vmode_g->cwidth)); SET_FARVAR(seg, info->ycharsize, GET_GLOBAL(vmode_g->cheight)); int depth = GET_GLOBAL(vmode_g->depth); - int planes = (depth == 4) ? 4 : 1; - SET_FARVAR(seg, info->planes, planes); SET_FARVAR(seg, info->bits_per_pixel, depth); - SET_FARVAR(seg, info->banks, 1); - SET_FARVAR(seg, info->mem_model, GET_GLOBAL(vmode_g->memmodel)); - SET_FARVAR(seg, info->bank_size, 0); - u32 pages = GET_GLOBAL(VBE_total_memory) / ALIGN(height * linesize, 64*1024); - SET_FARVAR(seg, info->pages, (pages / planes) - 1); + u8 memmodel = GET_GLOBAL(vmode_g->memmodel); + SET_FARVAR(seg, info->mem_model, memmodel); SET_FARVAR(seg, info->reserved0, 1); - u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos; + // Mode specific info. + u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED | + VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | + VBE_MODE_ATTRIBUTE_COLOR_MODE | + VBE_MODE_ATTRIBUTE_GRAPHICS_MODE | + VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE; + u32 framebuffer = 0; + int planes = 1, banks = 1; + u32 pages = GET_GLOBAL(VBE_total_memory) / ALIGN(height * linesize, 64*1024); + switch (memmodel) { + case MM_TEXT: + mode_attr &= ~VBE_MODE_ATTRIBUTE_GRAPHICS_MODE; + mode_attr |= VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT; + if (GET_GLOBAL(vmode_g->sstart) == SEG_MTEXT) + mode_attr &= ~VBE_MODE_ATTRIBUTE_COLOR_MODE; + pages = 1; + break; + case MM_CGA: + pages = 1; + banks = 2; + SET_FARVAR(seg, info->bank_size, 8); + break; + case MM_PLANAR: + planes = 4; + pages /= 4; + break; + default: + framebuffer = GET_GLOBAL(VBE_framebuffer); + if (framebuffer) + mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE; + break; + } + if (pages > 128) + pages = 128; + if (pages < 2) + pages++; + SET_FARVAR(seg, info->mode_attributes, mode_attr); + SET_FARVAR(seg, info->planes, planes); + SET_FARVAR(seg, info->pages, pages - 1); + SET_FARVAR(seg, info->banks, banks); + // Pixel color breakdown + u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos; switch (depth) { case 15: r_size = 5; r_pos = 10; g_size = 5; g_pos = 5; b_size = 5; b_pos = 0; a_size = 1; a_pos = 15; break; @@ -132,11 +164,13 @@ case 24: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8; b_size = 8; b_pos = 0; a_size = 0; a_pos = 0; break; case 32: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8; - b_size = 8; b_pos = 0; a_size = 8; a_pos = 24; break; + b_size = 8; b_pos = 0; a_size = 8; a_pos = 24; + SET_FARVAR(seg, info->directcolor_info, + VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE); + break; default: r_size = 0; r_pos = 0; g_size = 0; g_pos = 0; b_size = 0; b_pos = 0; a_size = 0; a_pos = 0; break; } - SET_FARVAR(seg, info->red_size, r_size); SET_FARVAR(seg, info->red_pos, r_pos); SET_FARVAR(seg, info->green_size, g_size); @@ -146,31 +180,23 @@ SET_FARVAR(seg, info->alpha_size, a_size); SET_FARVAR(seg, info->alpha_pos, a_pos); - if (depth == 32) - SET_FARVAR(seg, info->directcolor_info, - VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE); - else - SET_FARVAR(seg, info->directcolor_info, 0); - - if (depth > 4) - SET_FARVAR(seg, info->phys_base, GET_GLOBAL(VBE_framebuffer)); - else - SET_FARVAR(seg, info->phys_base, 0); - - SET_FARVAR(seg, info->reserved1, 0); - SET_FARVAR(seg, info->reserved2, 0); - SET_FARVAR(seg, info->linear_bytes_per_scanline, linesize); - SET_FARVAR(seg, info->bank_pages, 0); - SET_FARVAR(seg, info->linear_pages, 0); - SET_FARVAR(seg, info->linear_red_size, r_size); - SET_FARVAR(seg, info->linear_red_pos, r_pos); - SET_FARVAR(seg, info->linear_green_size, g_size); - SET_FARVAR(seg, info->linear_green_pos, g_pos); - SET_FARVAR(seg, info->linear_blue_size, b_size); - SET_FARVAR(seg, info->linear_blue_pos, b_pos); - SET_FARVAR(seg, info->linear_alpha_size, a_size); - SET_FARVAR(seg, info->linear_alpha_pos, a_pos); - SET_FARVAR(seg, info->pixclock_max, 0); + // Linear framebuffer info. + if (framebuffer) { + SET_FARVAR(seg, info->phys_base, framebuffer); + + SET_FARVAR(seg, info->reserved1, 0); + SET_FARVAR(seg, info->reserved2, 0); + SET_FARVAR(seg, info->linear_bytes_per_scanline, linesize); + SET_FARVAR(seg, info->linear_pages, 0); + SET_FARVAR(seg, info->linear_red_size, r_size); + SET_FARVAR(seg, info->linear_red_pos, r_pos); + SET_FARVAR(seg, info->linear_green_size, g_size); + SET_FARVAR(seg, info->linear_green_pos, g_pos); + SET_FARVAR(seg, info->linear_blue_size, b_size); + SET_FARVAR(seg, info->linear_blue_pos, b_pos); + SET_FARVAR(seg, info->linear_alpha_size, a_size); + SET_FARVAR(seg, info->linear_alpha_pos, a_pos); + } regs->ax = 0x004f; } diff -Nru seabios-1.7.1/vgasrc/vgabios.c seabios-1.7.4/vgasrc/vgabios.c --- seabios-1.7.1/vgasrc/vgabios.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/vgabios.c 2013-12-23 15:40:06.000000000 +0000 @@ -1,52 +1,20 @@ // VGA bios implementation // -// Copyright (C) 2009-2012 Kevin O'Connor +// Copyright (C) 2009-2013 Kevin O'Connor // Copyright (C) 2001-2008 the LGPL VGABios developers Team // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "bregs.h" // struct bregs #include "biosvar.h" // GET_BDA -#include "util.h" // memset -#include "vgabios.h" // calc_page_size -#include "optionroms.h" // struct pci_data +#include "bregs.h" // struct bregs +#include "clext.h" // clext_1012 #include "config.h" // CONFIG_* +#include "output.h" // dprintf +#include "std/vbe.h" // VBE_RETURN_STATUS_FAILED #include "stdvga.h" // stdvga_set_cursor_shape -#include "clext.h" // clext_1012 +#include "string.h" // memset_far +#include "vgabios.h" // calc_page_size #include "vgahw.h" // vgahw_set_mode -#include "vbe.h" // VBE_RETURN_STATUS_FAILED -#include "pci.h" // pci_config_readw -#include "pci_regs.h" // PCI_VENDOR_ID - -// Standard Video Save Pointer Table -struct VideoSavePointer_s { - struct segoff_s videoparam; - struct segoff_s paramdynamicsave; - struct segoff_s textcharset; - struct segoff_s graphcharset; - struct segoff_s secsavepointer; - u8 reserved[8]; -} PACKED; - -static struct VideoSavePointer_s video_save_pointer_table VAR16; - -struct VideoParam_s video_param_table[29] VAR16; - - -/**************************************************************** - * PCI Data - ****************************************************************/ - -struct pci_data rom_pci_data VAR16VISIBLE = { - .signature = PCI_ROM_SIGNATURE, - .vendor = CONFIG_VGA_VID, - .device = CONFIG_VGA_DID, - .dlen = 0x18, - .class_hi = 0x300, - .irevision = 1, - .type = PCIROM_CODETYPE_X86, - .indicator = 0x80, -}; /**************************************************************** @@ -420,7 +388,7 @@ else regs->al = 0x30; - int flags = GET_BDA(modeset_ctl) & (MF_NOPALETTE|MF_GRAYSUM); + int flags = MF_LEGACY | (GET_BDA(modeset_ctl) & (MF_NOPALETTE|MF_GRAYSUM)); if (regs->al & 0x80) flags |= MF_NOCLEARMEM; @@ -797,6 +765,61 @@ } static void +handle_101120(struct bregs *regs) +{ + SET_IVT(0x1f, SEGOFF(regs->es, regs->bp)); +} + +void +load_gfx_font(u16 seg, u16 off, u8 height, u8 bl, u8 dl) +{ + u8 rows; + + SET_IVT(0x43, SEGOFF(seg, off)); + switch(bl) { + case 0: + rows = dl; + break; + case 1: + rows = 14; + break; + case 3: + rows = 43; + break; + case 2: + default: + rows = 25; + break; + } + SET_BDA(video_rows, rows - 1); + SET_BDA(char_height, height); +} + +static void +handle_101121(struct bregs *regs) +{ + load_gfx_font(regs->es, regs->bp, regs->cx, regs->bl, regs->dl); +} + +static void +handle_101122(struct bregs *regs) +{ + load_gfx_font(get_global_seg(), (u32)vgafont14, 14, regs->bl, regs->dl); +} + +static void +handle_101123(struct bregs *regs) +{ + load_gfx_font(get_global_seg(), (u32)vgafont8, 8, regs->bl, regs->dl); +} + +static void +handle_101124(struct bregs *regs) +{ + load_gfx_font(get_global_seg(), (u32)vgafont16, 16, regs->bl, regs->dl); +} + +static void handle_101130(struct bregs *regs) { switch (regs->bh) { @@ -867,6 +890,11 @@ case 0x12: handle_101112(regs); break; case 0x14: handle_101114(regs); break; case 0x30: handle_101130(regs); break; + case 0x20: handle_101120(regs); break; + case 0x21: handle_101121(regs); break; + case 0x22: handle_101122(regs); break; + case 0x23: handle_101123(regs); break; + case 0x24: handle_101124(regs); break; default: handle_1011XX(regs); break; } } @@ -1186,78 +1214,3 @@ default: handle_10XX(regs); break; } } - - -/**************************************************************** - * VGA post - ****************************************************************/ - -static void -init_bios_area(void) -{ - // init detected hardware BIOS Area - // set 80x25 color (not clear from RBIL but usual) - set_equipment_flags(0x30, 0x20); - - // the default char height - SET_BDA(char_height, 0x10); - - // Clear the screen - SET_BDA(video_ctl, 0x60); - - // Set the basic screen we have - SET_BDA(video_switches, 0xf9); - - // Set the basic modeset options - SET_BDA(modeset_ctl, 0x51); - - // Set the default MSR - SET_BDA(video_msr, 0x09); -} - -int VgaBDF VAR16 = -1; -int HaveRunInit VAR16; - -void VISIBLE16 -vga_post(struct bregs *regs) -{ - debug_serial_setup(); - dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION); - debug_enter(regs, DEBUG_VGA_POST); - - if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) { - u16 bdf = regs->ax; - if ((pci_config_readw(bdf, PCI_VENDOR_ID) - == GET_GLOBAL(rom_pci_data.vendor)) - && (pci_config_readw(bdf, PCI_DEVICE_ID) - == GET_GLOBAL(rom_pci_data.device))) - SET_VGA(VgaBDF, bdf); - } - - int ret = vgahw_init(); - if (ret) { - dprintf(1, "Failed to initialize VGA hardware. Exiting.\n"); - return; - } - - if (GET_GLOBAL(HaveRunInit)) - return; - - init_bios_area(); - - SET_VGA(video_save_pointer_table.videoparam - , SEGOFF(get_global_seg(), (u32)video_param_table)); - stdvga_build_video_param(); - - extern void entry_10(void); - SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10)); - - SET_VGA(HaveRunInit, 1); - - // Fixup checksum - extern u8 _rom_header_size, _rom_header_checksum; - SET_VGA(_rom_header_checksum, 0); - u8 sum = -checksum_far(get_global_seg(), 0, - GET_GLOBAL(_rom_header_size) * 512); - SET_VGA(_rom_header_checksum, sum); -} diff -Nru seabios-1.7.1/vgasrc/vgabios.h seabios-1.7.4/vgasrc/vgabios.h --- seabios-1.7.1/vgasrc/vgabios.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/vgabios.h 2013-12-23 15:40:06.000000000 +0000 @@ -39,6 +39,7 @@ }; // Mode flags +#define MF_LEGACY 0x0001 #define MF_GRAYSUM 0x0002 #define MF_NOPALETTE 0x0008 #define MF_CUSTOMCRTC 0x0800 @@ -77,6 +78,9 @@ #define DEBUG_VGA_POST 1 #define DEBUG_VGA_10 3 +// vgainit.c +extern struct VideoSavePointer_s video_save_pointer_table; + // vgabios.c extern int VgaBDF; extern int HaveRunInit; diff -Nru seabios-1.7.1/vgasrc/vgaentry.S seabios-1.7.4/vgasrc/vgaentry.S --- seabios-1.7.1/vgasrc/vgaentry.S 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/vgaentry.S 2013-12-23 15:40:06.000000000 +0000 @@ -1,10 +1,11 @@ // Rom layout and bios assembler to C interface. // -// Copyright (C) 2009-2012 Kevin O'Connor +// Copyright (C) 2009-2013 Kevin O'Connor // // This file may be distributed under the terms of the GNU LGPLv3 license. +#include "asm-offsets.h" // BREGS_* #include "config.h" // CONFIG_* #include "entryfuncs.S" // ENTRY_* @@ -44,17 +45,82 @@ * Entry points ****************************************************************/ + // This macro is the same as ENTRY_ARG except the "calll" + // instruction is avoided to work around known issues in the + // emulation of some versions of x86emu. + .macro ENTRY_ARG_VGA cfunc + cli + cld + PUSHBREGS + movw %ss, %ax // Move %ss to %ds + movw %ax, %ds + movl %esp, %ebx // Backup %esp, then zero high bits + movzwl %sp, %esp + movl %esp, %eax // First arg is pointer to struct bregs + pushw %ax ; callw \cfunc + movl %ebx, %esp // Restore %esp (including high bits) + POPBREGS + .endm + DECLFUNC entry_104f05 entry_104f05: - ENTRY_ARG vbe_104f05 + ENTRY_ARG_VGA vbe_104f05 lretw DECLFUNC _optionrom_entry _optionrom_entry: - ENTRY_ARG vga_post + ENTRY_ARG_VGA vga_post lretw DECLFUNC entry_10 entry_10: - ENTRY_ARG handle_10 + ENTRY_ARG_VGA handle_10 + iretw + + // Entry point using extra stack + DECLFUNC entry_10_extrastack +entry_10_extrastack: + cli + cld + pushw %ds // Set %ds:%eax to space on ExtraStack + pushl %eax + movw %cs:ExtraStackSeg, %ds + movl $(CONFIG_VGA_EXTRA_STACK_SIZE-BREGS_size-8), %eax + popl BREGS_eax(%eax) // Backup registers + popw BREGS_ds(%eax) + movl %edi, BREGS_edi(%eax) + movl %esi, BREGS_esi(%eax) + movl %ebp, BREGS_ebp(%eax) + movl %ebx, BREGS_ebx(%eax) + movl %edx, BREGS_edx(%eax) + movl %ecx, BREGS_ecx(%eax) + movw %es, BREGS_es(%eax) + movl %esp, BREGS_size+0(%eax) + movw %ss, BREGS_size+4(%eax) + popl BREGS_code(%eax) + popw BREGS_flags(%eax) + + movw %ds, %dx // Setup %ss/%esp and call function + movw %dx, %ss + movl %eax, %esp + pushw %ax ; callw handle_10 + + movl %esp, %eax // Restore registers and return + movw BREGS_size+4(%eax), %ss + movl BREGS_size+0(%eax), %esp + popl %edx + popw %dx + pushw BREGS_flags(%eax) + pushl BREGS_code(%eax) + movl BREGS_edi(%eax), %edi + movl BREGS_esi(%eax), %esi + movl BREGS_ebp(%eax), %ebp + movl BREGS_ebx(%eax), %ebx + movl BREGS_edx(%eax), %edx + movl BREGS_ecx(%eax), %ecx + movw BREGS_es(%eax), %es + pushw BREGS_ds(%eax) + pushl BREGS_eax(%eax) + popl %eax + popw %ds iretw diff -Nru seabios-1.7.1/vgasrc/vgafb.c seabios-1.7.4/vgasrc/vgafb.c --- seabios-1.7.1/vgasrc/vgafb.c 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/vgafb.c 2013-12-23 15:40:06.000000000 +0000 @@ -5,10 +5,12 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "vgabios.h" // vgafb_scroll #include "biosvar.h" // GET_BDA -#include "util.h" // memset_far +#include "byteorder.h" // cpu_to_be16 +#include "output.h" // dprintf #include "stdvga.h" // stdvga_planar4_plane +#include "string.h" // memset_far +#include "vgabios.h" // vgafb_scroll /**************************************************************** @@ -41,7 +43,7 @@ scroll_pl4(struct vgamode_s *vmode_g, int nblines, int attr , struct cursorpos ul, struct cursorpos lr) { - int cheight = GET_GLOBAL(vmode_g->cheight); + int cheight = GET_BDA(char_height); int cwidth = 1; int stride = GET_BDA(video_cols) * cwidth; void *src_far, *dest_far; @@ -77,7 +79,7 @@ scroll_cga(struct vgamode_s *vmode_g, int nblines, int attr , struct cursorpos ul, struct cursorpos lr) { - int cheight = GET_GLOBAL(vmode_g->cheight) / 2; + int cheight = GET_BDA(char_height) / 2; int cwidth = GET_GLOBAL(vmode_g->depth); int stride = GET_BDA(video_cols) * cwidth; void *src_far, *dest_far; @@ -115,7 +117,7 @@ scroll_lin(struct vgamode_s *vmode_g, int nblines, int attr , struct cursorpos ul, struct cursorpos lr) { - int cheight = 8; + int cheight = GET_BDA(char_height); int cwidth = 8; int stride = GET_BDA(video_cols) * cwidth; void *src_far, *dest_far; @@ -204,6 +206,21 @@ * Read/write characters to screen ****************************************************************/ +static struct segoff_s +get_font_data(u8 c) +{ + int char_height = GET_BDA(char_height); + struct segoff_s font; + if (char_height == 8 && c >= 128) { + font = GET_IVT(0x1f); + c -= 128; + } else { + font = GET_IVT(0x43); + } + font.offset += c * char_height; + return font; +} + static void write_gfx_char_pl4(struct vgamode_s *vmode_g , struct cursorpos cp, struct carattr ca) @@ -212,28 +229,20 @@ if (cp.x >= nbcols) return; - u8 cheight = GET_GLOBAL(vmode_g->cheight); - u8 *fdata_g; - switch (cheight) { - case 14: - fdata_g = vgafont14; - break; - case 16: - fdata_g = vgafont16; - break; - default: - fdata_g = vgafont8; - } - u16 addr = cp.x + cp.y * cheight * nbcols; - u16 src = ca.car * cheight; + struct segoff_s font = get_font_data(ca.car); + int cheight = GET_BDA(char_height); + int cwidth = 1; + int stride = nbcols * cwidth; + int addr = cp.y * cheight * stride + cp.x * cwidth; int i; for (i=0; i<4; i++) { stdvga_planar4_plane(i); u8 colors = ((ca.attr & (1<= nbcols) return; - u8 *fdata_g = vgafont8; - u8 bpp = GET_GLOBAL(vmode_g->depth); - u16 addr = (cp.x * bpp) + cp.y * 320; - u16 src = ca.car * 8; - u8 i; - for (i = 0; i < 8; i++) { - u8 *dest_far = (void*)(addr + (i >> 1) * 80); + struct segoff_s font = get_font_data(ca.car); + int cheight = GET_BDA(char_height) / 2; + int cwidth = GET_GLOBAL(vmode_g->depth); + int stride = nbcols * cwidth; + int addr = cp.y * cheight * stride + cp.x * cwidth; + int i; + for (i = 0; i < cheight*2; i++) { + u8 *dest_far = (void*)(addr + (i >> 1) * stride); if (i & 1) dest_far += 0x2000; - if (bpp == 1) { + u8 fontline = GET_FARVAR(font.seg, *(u8*)(font.offset+i)); + if (cwidth == 1) { u8 colors = (ca.attr & 0x01) ? 0xff : 0x00; - u8 pixels = colors & GET_GLOBAL(fdata_g[src + i]); + u8 pixels = colors & fontline; if (ca.attr & 0x80) pixels ^= GET_FARVAR(SEG_GRAPH, *dest_far); SET_FARVAR(SEG_CTEXT, *dest_far, pixels); } else { - u16 pixels = 0; - u8 fontline = GET_GLOBAL(fdata_g[src + i]); - int j; - for (j = 0; j < 8; j++) - if (fontline & (1<= nbcols) return; - u8 *fdata_g = vgafont8; - u16 addr = cp.x * 8 + cp.y * nbcols * 64; - u16 src = ca.car * 8; - u8 i; - for (i = 0; i < 8; i++) { - u8 *dest_far = (void*)(addr + i * nbcols * 8); - u8 fontline = GET_GLOBAL(fdata_g[src + i]); - u8 j; + struct segoff_s font = get_font_data(ca.car); + int cheight = GET_BDA(char_height); + int cwidth = 8; + int stride = nbcols * cwidth; + int addr = cp.y * cheight * stride + cp.x * cwidth; + int i; + for (i = 0; i < cheight; i++) { + u8 *dest_far = (void*)(addr + i * stride); + u8 fontline = GET_FARVAR(font.seg, *(u8*)(font.offset+i)); + int j; for (j = 0; j < 8; j++) { u8 pixel = (fontline & (0x80>>j)) ? ca.attr : 0x00; SET_FARVAR(SEG_GRAPH, dest_far[j], pixel); @@ -308,16 +321,16 @@ write_text_char(struct vgamode_s *vmode_g , struct cursorpos cp, struct carattr ca) { - // Compute the address - u16 nbcols = GET_BDA(video_cols); - void *address_far = (void*)(GET_BDA(video_pagesize) * cp.page - + (cp.x + cp.y * nbcols) * 2); - + int cheight = 1; + int cwidth = 2; + int stride = GET_BDA(video_cols) * cwidth; + int addr = cp.y * cheight * stride + cp.x * cwidth; + void *dest_far = (void*)(GET_BDA(video_pagesize) * cp.page + addr); if (ca.use_attr) { u16 dummy = (ca.attr << 8) | ca.car; - SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u16*)address_far, dummy); + SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u16*)dest_far, dummy); } else { - SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)address_far, ca.car); + SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, ca.car); } } @@ -364,10 +377,12 @@ } // Compute the address - u16 nbcols = GET_BDA(video_cols); - u16 *address_far = (void*)(GET_BDA(video_pagesize) * cp.page - + (cp.x + cp.y * nbcols) * 2); - u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *address_far); + int cheight = 1; + int cwidth = 2; + int stride = GET_BDA(video_cols) * cwidth; + int addr = cp.y * cheight * stride + cp.x * cwidth; + u16 *src_far = (void*)(GET_BDA(video_pagesize) * cp.page + addr); + u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *src_far); struct carattr ca = {v, v>>8, 0}; return ca; diff -Nru seabios-1.7.1/vgasrc/vgahw.h seabios-1.7.4/vgasrc/vgahw.h --- seabios-1.7.1/vgasrc/vgahw.h 2012-08-31 16:12:45.000000000 +0000 +++ seabios-1.7.4/vgasrc/vgahw.h 2013-12-23 15:40:06.000000000 +0000 @@ -7,7 +7,7 @@ #include "clext.h" // clext_set_mode #include "bochsvga.h" // bochsvga_set_mode #include "stdvga.h" // stdvga_set_mode -#include "geodevga.h" // geodevga_init +#include "geodevga.h" // geodevga_setup static inline struct vgamode_s *vgahw_find_mode(int mode) { if (CONFIG_VGA_CIRRUS) @@ -34,14 +34,14 @@ stdvga_list_modes(seg, dest, last); } -static inline int vgahw_init(void) { +static inline int vgahw_setup(void) { if (CONFIG_VGA_CIRRUS) - return clext_init(); + return clext_setup(); if (CONFIG_VGA_BOCHS) - return bochsvga_init(); + return bochsvga_setup(); if (CONFIG_VGA_GEODEGX2 || CONFIG_VGA_GEODELX) - return geodevga_init(); - return stdvga_init(); + return geodevga_setup(); + return stdvga_setup(); } static inline int vgahw_get_window(struct vgamode_s *vmode_g, int window) { diff -Nru seabios-1.7.1/vgasrc/vgainit.c seabios-1.7.4/vgasrc/vgainit.c --- seabios-1.7.1/vgasrc/vgainit.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.7.4/vgasrc/vgainit.c 2013-12-23 15:40:06.000000000 +0000 @@ -0,0 +1,170 @@ +// Main VGA bios initialization +// +// Copyright (C) 2009-2013 Kevin O'Connor +// Copyright (C) 2001-2008 the LGPL VGABios developers Team +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // SET_BDA +#include "bregs.h" // struct bregs +#include "hw/pci.h" // pci_config_readw +#include "hw/pci_regs.h" // PCI_VENDOR_ID +#include "output.h" // dprintf +#include "std/optionrom.h" // struct pci_data +#include "std/pmm.h" // struct pmmheader +#include "string.h" // checksum_far +#include "util.h" // VERSION +#include "vgabios.h" // struct VideoSavePointer_s +#include "vgahw.h" // vgahw_setup + +// Standard Video Save Pointer Table +struct VideoSavePointer_s { + struct segoff_s videoparam; + struct segoff_s paramdynamicsave; + struct segoff_s textcharset; + struct segoff_s graphcharset; + struct segoff_s secsavepointer; + u8 reserved[8]; +} PACKED; + +struct VideoSavePointer_s video_save_pointer_table VAR16; + +struct VideoParam_s video_param_table[29] VAR16; + + +/**************************************************************** + * PCI Data + ****************************************************************/ + +struct pci_data rom_pci_data VAR16 VISIBLE16 = { + .signature = PCI_ROM_SIGNATURE, + .vendor = CONFIG_VGA_VID, + .device = CONFIG_VGA_DID, + .dlen = 0x18, + .class_hi = 0x300, + .irevision = 1, + .type = PCIROM_CODETYPE_X86, + .indicator = 0x80, +}; + + +/**************************************************************** + * PMM call and extra stack setup + ****************************************************************/ + +u16 ExtraStackSeg VAR16 VISIBLE16; + +static void +allocate_extra_stack(void) +{ + if (!CONFIG_VGA_ALLOCATE_EXTRA_STACK) + return; + void *pmmscan = (void*)BUILD_BIOS_ADDR; + for (; pmmscan < (void*)BUILD_BIOS_ADDR+BUILD_BIOS_SIZE; pmmscan+=16) { + struct pmmheader *pmm = pmmscan; + if (pmm->signature != PMM_SIGNATURE) + continue; + if (checksum_far(0, pmm, pmm->length)) + continue; + struct segoff_s entry = pmm->entry; + dprintf(1, "Attempting to allocate VGA stack via pmm call to %04x:%04x\n" + , entry.seg, entry.offset); + u16 res1, res2; + asm volatile( + "pushl %0\n" + "pushw $(8|1)\n" // Permanent low memory request + "pushl $0xffffffff\n" // Anonymous handle + "pushl $" __stringify(CONFIG_VGA_EXTRA_STACK_SIZE) "\n" + "pushw $0x00\n" // PMM allocation request + "lcallw *12(%%esp)\n" + "addl $16, %%esp\n" + "cli\n" + "cld\n" + : "+r" (entry.segoff), "=a" (res1), "=d" (res2) : : "cc", "memory"); + u32 res = res1 | (res2 << 16); + if (!res || res == PMM_FUNCTION_NOT_SUPPORTED) + return; + dprintf(1, "VGA stack allocated at %x\n", res); + SET_VGA(ExtraStackSeg, res >> 4); + extern void entry_10_extrastack(void); + SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10_extrastack)); + return; + } +} + + +/**************************************************************** + * VGA post + ****************************************************************/ + +static void +init_bios_area(void) +{ + // init detected hardware BIOS Area + // set 80x25 color (not clear from RBIL but usual) + set_equipment_flags(0x30, 0x20); + + // the default char height + SET_BDA(char_height, 0x10); + + // Clear the screen + SET_BDA(video_ctl, 0x60); + + // Set the basic screen we have + SET_BDA(video_switches, 0xf9); + + // Set the basic modeset options + SET_BDA(modeset_ctl, 0x51); + + // Set the default MSR + SET_BDA(video_msr, 0x09); +} + +int VgaBDF VAR16 = -1; +int HaveRunInit VAR16; + +void VISIBLE16 +vga_post(struct bregs *regs) +{ + debug_preinit(); + dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION); + debug_enter(regs, DEBUG_VGA_POST); + + if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) { + u16 bdf = regs->ax; + if ((pci_config_readw(bdf, PCI_VENDOR_ID) + == GET_GLOBAL(rom_pci_data.vendor)) + && (pci_config_readw(bdf, PCI_DEVICE_ID) + == GET_GLOBAL(rom_pci_data.device))) + SET_VGA(VgaBDF, bdf); + } + + int ret = vgahw_setup(); + if (ret) { + dprintf(1, "Failed to initialize VGA hardware. Exiting.\n"); + return; + } + + if (GET_GLOBAL(HaveRunInit)) + return; + + init_bios_area(); + + SET_VGA(video_save_pointer_table.videoparam + , SEGOFF(get_global_seg(), (u32)video_param_table)); + stdvga_build_video_param(); + + extern void entry_10(void); + SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10)); + + allocate_extra_stack(); + + SET_VGA(HaveRunInit, 1); + + // Fixup checksum + extern u8 _rom_header_size, _rom_header_checksum; + SET_VGA(_rom_header_checksum, 0); + u8 sum = -checksum_far(get_global_seg(), 0, + GET_GLOBAL(_rom_header_size) * 512); + SET_VGA(_rom_header_checksum, sum); +}