From 4a79268282e3b4cd2c5e3ef15c940600ead1e101 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 26 Jul 2007 21:18:21 +0000 Subject: Use the new x86 code, thanks sn9 ! git-svn-id: svn://svn.openwrt.org/openwrt/trunk@8185 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../linux/rdc-2.6/patches/000-git-newsetup.patch | 11942 +++++++++++++++++++ target/linux/rdc-2.6/patches/000-rdc_fixes.patch | 39 - .../rdc-2.6/patches/001-git-newsetup-fixup.patch | 22 + target/linux/rdc-2.6/patches/600-x86_lzma.patch | 11 +- 4 files changed, 11969 insertions(+), 45 deletions(-) create mode 100644 target/linux/rdc-2.6/patches/000-git-newsetup.patch create mode 100644 target/linux/rdc-2.6/patches/001-git-newsetup-fixup.patch (limited to 'target/linux/rdc-2.6/patches') diff --git a/target/linux/rdc-2.6/patches/000-git-newsetup.patch b/target/linux/rdc-2.6/patches/000-git-newsetup.patch new file mode 100644 index 0000000000..d73691fb35 --- /dev/null +++ b/target/linux/rdc-2.6/patches/000-git-newsetup.patch @@ -0,0 +1,11942 @@ +GIT 1783e2f0f21444020e3dee1be46b1e34af0ea3e7 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-newsetup.git + +commit 1783e2f0f21444020e3dee1be46b1e34af0ea3e7 +Author: Venki Pallipadi +Date: Wed Jun 20 14:12:39 2007 -0700 + + Use a new CPU feature word to cover all Intel features that are spread around + + in different CPUID leafs like 0x5, 0x6 and 0xA. Make this + feature detection code common across i386 and x86_64. + + Display Intel Dynamic Acceleration feature in /proc/cpuinfo. This feature + will be enabled automatically by current acpi-cpufreq driver. + + Refer to Intel Software Developer's Manual for more details about the feature. + + Thanks to hpa (H Peter Anvin) for the making the actual code detecting the + scattered features data-driven. + + Signed-off-by: Venkatesh Pallipadi + Signed-off-by: H. Peter Anvin + +commit cd19eb67cd6636a4e5c9df99631422c7c7286f59 +Author: H. Peter Anvin +Date: Wed Jun 20 14:33:17 2007 -0700 + + x86 setup: move __bss_start into the .bss segment + + Move __bss_start into the .bss segment, and create __bss_end. + + Signed-off-by: H. Peter Anvin + +commit 100327ad6b609cd28970219be57d293847d1261d +Author: H. Peter Anvin +Date: Wed Jun 6 22:07:01 2007 -0700 + + x86 setup: remove TSC as a required feature + + Remove TSC as a required feature, in anticipation of CONFIG_X86_TSC + removal. + + Signed-off-by: H. Peter Anvin + +commit 7c91a172b8af7d4ba087f1f88ed5b155ed459ca3 +Author: Antonino A. Daplas +Date: Tue Jun 5 19:21:05 2007 +0800 + + i386: Set 6-bit DAC channel properties in vesa video setup + + If the video BIOS is not capable of switching or failed to switch the + hardware to 8-bit DAC, the channel properties are not set. This leads + to a blank (all black) display with vesafb at 8 bpp. Fix by defaulting + to a 6-bit DAC. + + Signed-off-by: Antonino Daplas + Signed-off-by: H. Peter Anvin + +commit 6eac2d442de8d87eac94a4ca8600bd87219fa06b +Author: H. Peter Anvin +Date: Tue Jun 5 16:19:36 2007 -0700 + + x86 setup: arch/i386/boot/cpucheck.c whitespace cleanup + + Remove stealth whitespace + + Signed-off-by: H. Peter Anvin + +commit f7d89f05a30433034a1b4651143afdbb2a8a9c92 +Author: H. Peter Anvin +Date: Thu May 24 16:56:44 2007 -0700 + + hd.c: remove BIOS/CMOS queries + + An ST-506 disk these days is pretty much someone trying to pull ancient + data using an auxilliary controller. Pulling data from the BIOS or CMOS + is just plain wrong, since it's likely to be the primary OS disk... and + would be user-entered data anyway. Instead, require the user enters it + on the command line. + + Signed-off-by: H. Peter Anvin + +commit 14c2fdb3bbfd6a9a774980e446c2443150749891 +Author: H. Peter Anvin +Date: Thu May 24 15:25:10 2007 -0700 + + x86: add back pbe bit to visible CPUID flags + + Add pbe back to the visible CPUID flags. We *do* correctly filter abuses + of this bit for 3DNow! in all the appropriate paths. + + Signed-off-by: H. Peter Anvin + +commit e071b068a3b9f318be314f0378e655e2eb50ac89 +Author: H. Peter Anvin +Date: Wed May 23 14:52:34 2007 -0700 + + x86 setup: VIA feature mask MSR doesn't just apply to model <= 9 + + The VIA feature mask MSR is known to be present on model 10, and it + seems likely it will continue to be supported. Since we only touch the + MSR if we're about to print an error message anyway, go ahead and be + aggressive. + + Signed-off-by: H. Peter Anvin + +commit abe0c5aa1827932cda9c754a3842ec22b278d704 +Author: H. Peter Anvin +Date: Tue May 22 17:17:41 2007 -0700 + + x86 setup: correct inline assembly constraints in edd.c + + Fix the inline assembly constraints in edd.c. In particular, "driveno" + was getting clobbered on some (buggy?) BIOSes. + + Signed-off-by: H. Peter Anvin + +commit c2e5887ad275aab90673a3e33344f09946159cf7 +Author: H. Peter Anvin +Date: Fri May 18 10:02:55 2007 -0700 + + x86 setup: force the assembler to generate a 2-byte jump in header + + The jump instruction in the header only has two bytes available, so + it *better* be a 2-byte jump! Unfortunately, the assembler will + always generate a 3/5-byte jump when the target is in a different + section. Deal with that by generating the jump instruction + explicitly from .byte's, just like we do elsewhere when we need a + specific binary representation of a certain instruction. + + Signed-off-by: H. Peter Anvin + +commit ce82e3b93eba48b6852822a03efa73c74e165d4f +Author: H. Peter Anvin +Date: Thu May 17 15:44:48 2007 -0700 + + x86 setup: move the symbol start_of_setup into the proper section. + + start_of_setup is the beginning of the executable code and should be + located in the appropriate section. + + Signed-off-by: H. Peter Anvin + +commit e5f3a529457a5bfaf8f8783fb86013221279a81c +Author: H. Peter Anvin +Date: Thu May 17 15:43:19 2007 -0700 + + x86 setup: add an ASSERT that the header ends up in the right place + + Just in case we have funnies involving the linker or people putting + inappropriate align statements, make the linker abort if the setup + header ends up in the wrong place. + + Signed-off-by: H. Peter Anvin + +commit d9dbde725687ab99d1f529f49f14d1e280cc5cac +Author: Alexander van Heukelum +Date: Thu May 17 20:54:25 2007 +0200 + + x86 new setup: use appropriate sections for code and data + + An intermediate elf file is generated for the 16-bit setup code. + The generated code can be viewed using objdump -m i8086 -d. As it + stands, it also tries to disassemble the bugger_off_msg, which + results in garbage. This introduces two new sections to separate + the code and the data part of the bootsector stub. It also moves + some code from the .header section (a data section) to .inittext. + + Signed-off-by: Alexander van Heukelum + +commit 0d7558a81cf61e9fd2332a54897c5fd18df0d7f2 +Author: H. Peter Anvin +Date: Wed May 16 22:03:16 2007 -0700 + + x86 setup: use -include code16gcc.h instead of explicit #include + + Use -include in the Makefile instead of #include to include code16gcc.h. + This really is more of a compiler switch than anything else, and is a lot + cleaner to do implicitly. + + Signed-off-by: H. Peter Anvin + +commit 017ce54e8a4a9628a76d6b510c7309a7e4e111a8 +Author: H. Peter Anvin +Date: Wed May 16 18:48:06 2007 -0700 + + x86 setup: enable features on Centaur (VIA) and Transmeta processors + + AMD are not the only ones who sometimes mask features which the kernel + may very well depend on. VIA and Transmeta do, too. Add code to enable + these features during checking. + + Signed-off-by: H. Peter Anvin + +commit b794f5f9c5089709f3df38c6d91869fa38a9c1a4 +Author: H. Peter Anvin +Date: Wed May 16 16:37:47 2007 -0700 + + x86 setup: in older versions of ld, ASSERT() is an expression + + Older versions of ld (pre-2.15 or so) need: + + . = ASSERT(foo, "msg"); + + instead of: + + ASSERT(foo, "msg") + + Signed-off-by: H. Peter Anvin + +commit 21c2b7c99c417d07015ee8e516a634ec3d98c4ee +Author: H. Peter Anvin +Date: Wed May 16 10:52:41 2007 -0700 + + x86 setup: print a warning message if the bootloader gave us no heap. + + If the bootloader is so old it doesn't set the CAN_USE_HEAP flag, + a lot of functionality will by necessity be disabled, so print a + warning message. This means either a 2.00 protocol bootloader or + a buggy bootloader; the Qemu bootloader falls in this category. + + Signed-off-by: H. Peter Anvin + +commit 52ca0431390d389a2a2246f02fe652ea84c1ddd8 +Author: H. Peter Anvin +Date: Wed May 16 10:51:03 2007 -0700 + + x86 setup: rely on a compiled-in default for load high/load low + + When deciding if we should move the kernel from 0x10000 to 0x1000, as + is required for a zImage kernel, rely on a compiled-in default since + Qemu unconditionally zeroes the loadflags. This, of course, is a bug + in Qemu, but still... + + Signed-off-by: H. Peter Anvin + +commit 4db77a97793104a32e5fb83e62b943fa144b329d +Author: H. Peter Anvin +Date: Wed May 16 08:45:37 2007 -0700 + + x86 setup: correct assembly constraints. + + Double use of "d" in an asm() constraints; most gcc versions correctly + detect and avoid using it, but some version of gcc runs itself into + a brick wall instead. Fix the one "d" which should have been "a". + + Signed-off-by: H. Peter Anvin + +commit 4fbccbc1457d6710d3a9ce55ad70ec6cb0b75fc5 +Author: H. Peter Anvin +Date: Tue May 15 09:16:29 2007 -0700 + + x86 setup: include not + + brings in the accessor functions, which may potentially + bring in all other kinds of kernel headers which are inappropriate for + the setup code. For the setup code, include + instead, which only includes the numeric constants. + + Signed-off-by: H. Peter Anvin + +commit 839cafa9c0020e7506722dd2a4fd82a71c2939cc +Author: H. Peter Anvin +Date: Mon May 14 15:49:01 2007 -0700 + + x86 setup: protocol 2.0[01]: base for CL_OFFSET depends on setup_move_size + + Handle the use of boot protocol 2.00 and 2.01: the base segment for + CL_OFFSET depends on the value of setup_move_size. + + Signed-off-by: H. Peter Anvin + +commit d60357ad68a694b03e9b952eadba5ac277c31df0 +Author: H. Peter Anvin +Date: Sat May 12 12:18:53 2007 -0700 + + x86 setup: remove unused variable + + Remove unused variable + + Signed-off-by: H. Peter Anvin + +commit e21a2030b01081612259847321bcce13eae1e883 +Author: Sam Ravnborg +Date: Sat May 12 12:17:30 2007 -0700 + + x86 setup: share i386 Makefile with x86_64 + + The boot Makefile for i386 and x86_64 are equal + except for the CFLAGS setting. + Teach x86_64 to use the Makefile from i386 and + make CFLAGS setting arch dependent in i386 Makefile. + + Signed-off-by: Sam Ravnborg + Signed-off-by: H. Peter Anvin + +commit 8618d92339d0d106045f98f34833d863c3235cdb +Author: H. Peter Anvin +Date: Sat May 12 00:32:12 2007 -0700 + + x86 setup: video-bios.c missed the pointer to the set_mode method! + + We need the actual pointer to the set_mode method (oops!) + + Signed-off-by: H. Peter Anvin + +commit 85dfc374ea9aad33b9e0315f07a4b2722dc11e3e +Author: H. Peter Anvin +Date: Sat May 12 00:14:43 2007 -0700 + + x86 setup: when setting unknown BIOS modes and failing, try to revert + + If we set an unknown BIOS mode and fail, then explicitly try to revert + to the original mode. + + Signed-off-by: H. Peter Anvin + +commit f4f7949f126d2f152b09fa9367b1ec693f2ea818 +Author: H. Peter Anvin +Date: Fri May 11 11:20:59 2007 -0700 + + x86 setup: fix typo "video_bios" should be "video-bios" + + Signed-off-by: H. Peter Anvin + +commit 51ba7113ea5b07189b7f8a0534d400a072535197 +Author: H. Peter Anvin +Date: Fri May 11 11:09:55 2007 -0700 + + x86 setup: allow setting VESA modes "blind" + + Apparently, people really do set VESA modes "blind". As a result, make + the framework for settting blind modes more general, to remove some + special cases. + + Signed-off-by: H. Peter Anvin + +commit 1b8f73d9b2bf7630a2914ddab606db16fddb509e +Author: H. Peter Anvin +Date: Thu May 10 22:08:45 2007 -0700 + + x86_64: CONFIG_PHYSICAL_ALIGN should be 2 MB + + It's not actually used yet, but set CONFIG_PHYSICAL_ALIGN to 2 MB + as it should be, to prevent conflicts with other works in progress. + + Signed-off-by: H. Peter Anvin + +commit b81f3c88923e4470cd0942d4596fafc0fb1cf4fd +Author: H. Peter Anvin +Date: Thu May 10 19:11:32 2007 -0700 + + x86 setup: remove debugging statements + + Remove debugging statements in video.c that were not meant for + production. + + Signed-off-by: H. Peter Anvin + +commit be58b6d7e9c14e482bce495e8343955999dea77f +Author: H. Peter Anvin +Date: Thu May 10 18:49:40 2007 -0700 + + x86 setup: only restore the screen image when needed + + Only restore the screen image when needed. This is how the original + code behaves, so it's presumably the desired behaviour. + + Signed-off-by: H. Peter Anvin + +commit 22f6bd8cc23b512af28e34ae7d40036982a0ac63 +Author: H. Peter Anvin +Date: Thu May 10 18:44:08 2007 -0700 + + x86 setup: correct the definition of the GDT limit + + Like all other x86 segment limits, the GDT limit points to the last byte + that is *permitted* to access, so it needs to be sizeof(boot_gdt)-1. + + Signed-off-by: H. Peter Anvin + +commit 7f73f1f4aa4c97745bffe07a3ebcf226a4965b00 +Author: H. Peter Anvin +Date: Thu May 10 15:47:48 2007 -0700 + + x86 setup: Re-implement scanning for hidden video modes + + Re-implement scanning for hidden video modes. Every now and then, + apparently, you can find them hidden like easter eggs. + + Signed-off-by: H. Peter Anvin + +commit 6770176714bc12ec92372311ac02c14f0d22776e +Author: H. Peter Anvin +Date: Thu May 10 15:24:27 2007 -0700 + + x86 setup: whitespace cleanup + + Clean up stealth whitespace. + + Signed-off-by: H. Peter Anvin + +commit ba0480a3537cf471b08bdb99dae6d0780cfb1972 +Author: H. Peter Anvin +Date: Wed May 9 16:54:42 2007 -0700 + + x86: sync the CPU feature string arrays + + With unified, synchronize the CPU feature string + arrays. The whole kernel/cpu directory really needs to be unified. + + Signed-off-by: H. Peter Anvin + +commit ecb53b84efddbad3d9aa49e95598550831324348 +Author: H. Peter Anvin +Date: Tue May 8 22:06:04 2007 -0700 + + x86 setup: need to set orig_video_isVGA + + After detecting a VGA console, we need to set + boot_params.screen_info.orig_video_isVGA. + + Signed-off-by: H. Peter Anvin + +commit dc97fc053faff17b984ec962686caea52bd27628 +Author: H. Peter Anvin +Date: Tue May 8 20:51:17 2007 -0700 + + x86 setup: boot sector should use ljmp, not jmpl + + We have an "jmpl" instruction in the boot sector, which was meant + to be an "ljmp" instruction. It worked anyway because gas interpreted + a two-argument "jmpl" as an "ljmpl" instruction, however, use plain + "ljmp" (i.e. "ljmpw".) + + Signed-off-by: H. Peter Anvin + +commit 7907f05e9692557c53c9ac13647db5e5343c7c76 +Author: H. Peter Anvin +Date: Tue May 8 20:27:10 2007 -0700 + + x86 setup: only make VESA graphics modes selectable if CONFIG_FB + + If we select a VESA graphics mode, we better have framebuffer support + or the user will have no console. Therefore, make these modes + non-selectable if CONFIG_FB is not set. + + Signed-off-by: H. Peter Anvin + +commit 8e509f9ebc44f45544d231454e84f10bf78d5772 +Author: H. Peter Anvin +Date: Tue May 8 20:24:11 2007 -0700 + + x86 setup: need to probe VESA EDID block 0 only + + The VESA EDID BIOS call takes the EDID block number in %dx, and may + corrupt it by spec. Pass it in properly. + + Signed-off-by: H. Peter Anvin + +commit 9912b9aed7943773d1fadaa2e2e52f42af395048 +Author: H. Peter Anvin +Date: Mon May 7 18:22:04 2007 -0700 + + x86 setup: add missing file "bitops.h" missing from previous checkins + + The file "bitops.h" was missing from previous checkins. + + Signed-off-by: H. Peter Anvin + +commit 732eb3fac2d772980e6555b8c69902c8107c72aa +Author: H. Peter Anvin +Date: Mon May 7 14:59:43 2007 -0700 + + x86 setup: add -fno-stack-protector; other Makefile fixes + + Add -fno-stack-protector for the gcc's that need that; + Use -ffreestanding consistently; + Use $(LINUXINCLUDE); + Handle linker scripts consistently with other Makefiles. + + Signed-off-by: H. Peter Anvin + +commit 2d5e47f21202e156fe97aba0a88d158d5c157a33 +Author: H. Peter Anvin +Date: Mon May 7 14:45:25 2007 -0700 + + x86 setup: swap cpu.c and cpucheck.c; rename functions + + Make cpucheck.c the reusable component; the generically-named cpu.c + gets to be the wrapper. Accordingly, rename functions to make it + less confusing. + + Signed-off-by: H. Peter Anvin + +commit bf2a428a4e7c1ee3ab9acb23cfafb45e818887a1 +Author: H. Peter Anvin +Date: Mon May 7 14:09:38 2007 -0700 + + x86 setup: remove code moved from cpucheck.c -> cpu.c + + Move all info about requirements into cpu.c. + + Signed-off-by: H. Peter Anvin + +commit 9ea8429fabe5df6aed6393ac3a00d0b64445ba6a +Author: H. Peter Anvin +Date: Mon May 7 09:42:51 2007 -0700 + + x86 setup: remove double nesting of a20_test() + + a20_test() was invoked as either a20_test() or a20_wait(), where the + latter was simply a loop around a loop. Make the count a parameter + instead; this is clearer and saves a couple of bytes. + + Signed-off-by: H. Peter Anvin + +commit 9edc55718f57195c664ee3175514d652f651cfd2 +Author: H. Peter Anvin +Date: Mon May 7 09:30:41 2007 -0700 + + x86 setup: compile with -fomit-frame-pointer + + Compiling with -fomit-frame-pointer reduces the size by about 2%. + + Signed-off-by: H. Peter Anvin + +commit e1003433f2d491bf17c79437cd75268da220dab5 +Author: H. Peter Anvin +Date: Mon May 7 09:30:04 2007 -0700 + + x86 setup: be more paranoid about the stack setup in header.S + + In particular, deal correctly with the stack pointer being zero on entry. + While we're at it, align the stack. + + Signed-off-by: H. Peter Anvin + +commit 853499c3dc3fcbeb192a613ac241d150ebc7c5a0 +Author: H. Peter Anvin +Date: Sun May 6 23:25:10 2007 -0700 + + x86 setup: Factor out the environment-independent part of the CPU check. + + Factor out the environment-independent part of the CPU check so it can + be invoked from other parts of the kernel as well. + + Signed-off-by: H. Peter Anvin + +commit f235a61f6d6dff57883efad351d746540bcb8caf +Author: H. Peter Anvin +Date: Sat May 5 22:16:54 2007 -0700 + + x86 setup: when watching the setup size, take the stack into account + + When watching the setup size, we have to take the stack into account. + In particular, the stack is used not only by the setup code itself, but + by BIOS interrupt handlers and system calls. Reserve a minimum of + 512 bytes. + + Signed-off-by: H. Peter Anvin + +commit 0d0e10091be48f7e4c8888e9d5c2836c704994f5 +Author: H. Peter Anvin +Date: Sat May 5 19:25:51 2007 -0700 + + x86 setup: actually check the end of the heap. + + Keep track of where the heap ends and actually watch out for it. + + Signed-off-by: H. Peter Anvin + +commit 47aab0b8f4d012fad3c42b5b0754d3cb87961b37 +Author: H. Peter Anvin +Date: Sat May 5 15:47:58 2007 -0700 + + x86 setup: coppyright rPath, Inc. + + This work was done on the dime of rPath, Inc.; they own the copyright. + + Signed-off-by: H. Peter Anvin + +commit d22571534d7eabf9408f29d9da423e1c6e04445f +Author: H. Peter Anvin +Date: Sat May 5 15:21:11 2007 -0700 + + x86 setup: implement screen contents save/restore + + The old setup code had screen contents save and restore, so implement + it for the new one as well. + + Signed-off-by: H. Peter Anvin + +commit e5145601a752bd998e783d159c187d3017d45d6d +Author: H. Peter Anvin +Date: Sat May 5 15:20:19 2007 -0700 + + x86 setup: whitespace cleanup + + Signed-off-by: H. Peter Anvin + +commit 045ecb52f91a74eecad93ffc8791eefe59cf7fd1 +Author: H. Peter Anvin +Date: Sat May 5 14:22:39 2007 -0700 + + x86 setup: allow setting of VESA graphics modes; cleanups + + - Allow setting of VESA graphics modes (used by vesafb) + - Clean up the macros related to the heap + - #if 0 copy functions that aren't actually currently being used + + Signed-off-by: H. Peter Anvin + +commit 58c04ed7e2d7d5979e1917a74b49bdc0f3dde211 +Author: H. Peter Anvin +Date: Sat May 5 12:06:14 2007 -0700 + + x86 setup: move all VESA-related code into video-vesa.c; add EDID + + - Move all VESA-related code into video-vesa.c + - Add VESA EDID query support + - Remove some totally obsolete definitions from video.h + + Signed-off-by: H. Peter Anvin + +commit 07bc3931175fb98256140275c03194426d441b74 +Author: H. Peter Anvin +Date: Sat May 5 12:04:40 2007 -0700 + + x86-64: remove -traditional from AFLAGS + + In arch/x86_64/boot/compressed, remove -traditional from AFLAGS. + + Signed-off-by: H. Peter Anvin + +commit a830f615eeef838d461cbf7bbbee8c1c84708ec8 +Author: H. Peter Anvin +Date: Fri May 4 18:44:38 2007 -0700 + + x86 setup: share code between i386 and x86-64 + + Share the boot (setup) code and tools between i386 and x86-64. + The compression code is now running in 64-bit mode in order to support + relocation, so do *not* share that code. + + Signed-off-by: H. Peter Anvin + +commit 3e159a323bdfa5d5a7be2c1f6be089ca22d598e0 +Author: H. Peter Anvin +Date: Fri May 4 18:43:35 2007 -0700 + + x86-64: use 0x1b4 as the scratch area in boot_params, not 0x3c + + Use 0x1b4 as the scratch area in boot_params rather than 0x3c. + + Signed-off-by: H. Peter Anvin + +commit 4cf4424e7a0f29f251b781f9b5e3655b0645cb7f +Author: H. Peter Anvin +Date: Fri May 4 18:26:18 2007 -0700 + + Revert "x86-64: Make arch/x86-64/boot a symlink to arch/i386/boot" + + This reverts commit b2ad90f4969226fe8cf3edc5330711ed5fc20105. + + Restore arch/x86_64/boot as a separate directory hierarchy. + + Conflicts: + +commit 8ed1ae1d2f94410811b7cca4b1a426e37652457f +Author: H. Peter Anvin +Date: Fri May 4 17:00:33 2007 -0700 + + x86-64: It appears MTRR isn't a required feature after all. + + MTRR was documented as a required feature, but appears to boot fine + without it (tested since Bochs doesn't have MTRR support.) + + Signed-off-by: H. Peter Anvin + +commit 7c616d098579fb790662cdc703f2a0f26ea1668c +Author: H. Peter Anvin +Date: Fri May 4 16:22:57 2007 -0700 + + x86 setup: use 0x1e4 as scratch, instead of 0x3c + + The compressed relocation needs a 4-byte scratch area to obtain + its own address. + + 0x3c is at the end of the video area, which is quite constrained -- it + only has 6 bytes left (12 if we recycle the obsolete fields which invade + this space.) Define 0x1e4 as a scratch field, and use it. + + Signed-off-by: H. Peter Anvin + +commit 5bc1019227e94576e4876d05ee920f59195bce90 +Author: H. Peter Anvin +Date: Fri May 4 16:09:15 2007 -0700 + + x86 setup: boot_params.e820_map is just the map, not the count; adjust + + boot_params.e820_map is just a list of entries, whereas + "struct e820map" contains a count as well. Thus, don't use + "struct e820map" to describe struct boot_params. + + Signed-off-by: H. Peter Anvin + +commit 0f96b52497f444be2d52d1184ca90be49f713ea3 +Author: H. Peter Anvin +Date: Fri May 4 15:49:03 2007 -0700 + + x86 setup: E820MAX is a definitional constant; no need to use sizeof hacks + + Now when we're using the standard headers for the setup code, we can use + E820MAX instead of playing sizeof games. + + Signed-off-by: H. Peter Anvin + +commit 3a23a428b20cbb31fd7ff5516a053b99afc447f7 +Author: H. Peter Anvin +Date: Fri May 4 12:08:46 2007 -0700 + + x86: move the bootparam structure definition into include/ + + Move the bootparam structure definition into include/, and make other + things use it. Haven't cleaned up all the macros yet, though. + + Signed-off-by: H. Peter Anvin + +commit e93ec58911995971aa059990f8a91a02b05f6c8f +Author: H. Peter Anvin +Date: Fri May 4 12:07:50 2007 -0700 + + i386: change %lu to %u in arch/i386/kernel/e820.h + + It's an u32, print it with %u + + Signed-off-by: H. Peter Anvin + +commit 2f47f004f614e2744867c0df274c55d8af2a42d5 +Author: H. Peter Anvin +Date: Fri May 4 12:06:04 2007 -0700 + + x86: fix differences between i386 and x86-64 + + Fix minor differences between i386 and x86-64 + + Signed-off-by: H. Peter Anvin + +commit 56ec52f14e948f430af941052adee98019a617b7 +Author: H. Peter Anvin +Date: Fri May 4 11:45:17 2007 -0700 + + x86: fix the definition of struct screen_info + + Name the fields that aren't really struct screen_info, and declare + the structure packed (the "capabilities" field is misaligned.) + + Signed-off-by: H. Peter Anvin + +commit 1d4429eaa564b0085d9ee3aa2de57e87a093a14e +Author: H. Peter Anvin +Date: Fri May 4 11:43:10 2007 -0700 + + x86-64: Make arch/x86-64/boot a symlink to arch/i386/boot + + Until such time that Kbuild allows for a cleaner solution, make + arch/x86-64/boot a symlink to arch/i386/boot. + + Signed-off-by: H. Peter Anvin + +commit 6a85f1b5fd041ea99d8604782559ce0502a60cc0 +Author: H. Peter Anvin +Date: Fri May 4 10:42:06 2007 -0700 + + x86-64: rearrange includes due to unifications and inclusion from setup + + Unification caused a circular dependency between + and ; resolve this. + + Add #ifndef _SETUP in so it can be included from the boot + code. + + Signed-off-by: H. Peter Anvin + +commit f6bbdc254bdbd5f7cf7a40c4cd6f9844af90824a +Author: H. Peter Anvin +Date: Fri May 4 10:40:26 2007 -0700 + + x86: Complete with the union of i386 and x86-64 + + Add a feature to which was previously present + in x86-64 but missing in i386. + + Signed-off-by: H. Peter Anvin + +commit 1a0819281060489901732914f67869e0aa8f26fd +Author: H. Peter Anvin +Date: Fri May 4 10:39:32 2007 -0700 + + x86: unify + + Unify between i386 and x86-64 + + Signed-off-by: H. Peter Anvin + +commit 8d9c54585f4623e0310f970fb5c6eda7ec1614df +Author: H. Peter Anvin +Date: Fri May 4 10:38:35 2007 -0700 + + x86-64: verify_cpu.S: use new masks + + Use the masks. + + Signed-off-by: H. Peter Anvin + +commit 6cf3308646bb7a3210f0f76bcb895b2dea76a93c +Author: H. Peter Anvin +Date: Fri May 4 10:37:26 2007 -0700 + + x86-64: fix compilation errors due to required-features.h change + + Fix compilation errors induced by required-features.h change. + + Signed-off-by: H. Peter Anvin + +commit 1324201a93ce380b46a3128826ecbd794e617e59 +Author: H. Peter Anvin +Date: Fri May 4 10:35:37 2007 -0700 + + x86-64: : add boot segment descriptors + + Add boot segment descriptors to to match i386. + + Signed-off-by: H. Peter Anvin + +commit a0b15a9e79ed0310813709cd0690d6838917fe82 +Author: H. Peter Anvin +Date: Fri May 4 10:34:37 2007 -0700 + + x86-64: add CONFIG_PHYSICAL_ALIGN to match i386 + + Add CONFIG_PHYSICAL_ALIGN to match i386, even though we don't use it. + + Signed-off-by: H. Peter Anvin + +commit 8f5d14d11a7318e257351ae477392c7f7e314602 +Author: H. Peter Anvin +Date: Fri May 4 10:33:54 2007 -0700 + + x86 setup: cleanups for compatibility with x86-64 + + These changes are necessary to compile on x86-64. + + Signed-off-by: H. Peter Anvin + +commit a32f68b6d4023c1c6b1e62e8561189516c571ab9 +Author: H. Peter Anvin +Date: Fri May 4 08:40:07 2007 -0700 + + x86 setup: add missing linker script + + Add linker script for the setup code, apparently missing from previous + checkins. + + Signed-off-by: H. Peter Anvin + +commit 4f34ca8e926b2d0bf3a7502b99f8dfced8cdba9d +Author: H. Peter Anvin +Date: Thu May 3 17:42:29 2007 -0700 + + x86 setup: paranoia: clear the high half of %esp + + We're invoked in 16-bit mode from an unknown bootloader. Make sure + we explicitly zero the upper half of %esp to avoid nasty surprises. + + Signed-off-by: H. Peter Anvin + +commit 19eb9b73cc1632a923003a002108b242af7a6080 +Author: H. Peter Anvin +Date: Thu May 3 17:35:41 2007 -0700 + + x86 setup: bootlin is *so* dead... + + Bootlin was never able to load bzImage kernels, so who cares about it. + + Signed-off-by: H. Peter Anvin + +commit 3b9fb73c65151ee043bc74c333d9e3c9b1872125 +Author: H. Peter Anvin +Date: Thu May 3 10:56:40 2007 -0700 + + x86 setup: apparently $(src) is insufficient, needs $(srctree)/$(src) + + For some unfanthomable reason the location of the source tree that + corresponds to the current directory has to be written as + $(srctree)/$(src) apparently. There might be a good reason for it, + but shorthand would be appreciated, and $(src) really should be the + short form. + + Signed-off-by: H. Peter Anvin + +commit a6d01d375a2269be1e3a6b31bcc4d426ad5a473d +Author: H. Peter Anvin +Date: Thu May 3 10:51:45 2007 -0700 + + x86 setup: remove reference to obsolete cpureq.c + + cpureq.c has been removed; remove it from the Makefile too. + + Signed-off-by: H. Peter Anvin + +commit cbe5b7585d800435080bcbf1b1fd242926982674 +Author: H. Peter Anvin +Date: Thu May 3 10:33:12 2007 -0700 + + x86 setup: use the required masks from + + Use the now-uniform features from . + + Signed-off-by: H. Peter Anvin + +commit 99ed30180ecc1bb4e93f6edda5f6bad1adf3e630 +Author: H. Peter Anvin +Date: Thu May 3 10:31:12 2007 -0700 + + x86: make the handling of required features consistent + + Make the handling of required features consistent between i386 + and x86-64. + + Signed-off-by: H. Peter Anvin + +commit 1120d70a2be8f2deb6bda64047da288d8f86dad3 +Author: H. Peter Anvin +Date: Thu May 3 00:09:53 2007 -0700 + + x86: Kconfig.cpu: the minimum CPU model is always 3; WP_WORKS_OK = i486 + + The minimum CPU model number is always 3 (i386), and if we have + WP_WORKS_OK it means we need an i486. + + Signed-off-by: H. Peter Anvin + +commit ebc308c204149b86984ae2216f5b9b2e63932028 +Author: H. Peter Anvin +Date: Thu May 3 00:08:48 2007 -0700 + + x86 setup: use CONFIG_X86_MINIMUM_CPU_MODEL + + Use CONFIG_X86_MINIMUM_CPU_MODEL as defined in Kconfig.cpu. + + Signed-off-by: H. Peter Anvin + +commit 8b50b640e015bf5d0f65502437da6fcab46c391b +Author: H. Peter Anvin +Date: Wed May 2 23:45:42 2007 -0700 + + x86 setup: remove bogus "static" + + Remove invalid "static" declarations in cpu.c + + Signed-off-by: H. Peter Anvin + +commit 35d23b60dfb110da81c24bcbfcda089cfc4fd264 +Author: H. Peter Anvin +Date: Wed May 2 23:37:50 2007 -0700 + + x86 setup: cpu detection cleanups + + - Use + - Make sure %cr0 isn't in a dangerous configuration before probing the FPU + + Signed-off-by: H. Peter Anvin + +commit a1150a03247b355d11a4bb696b8aae1f46612992 +Author: H. Peter Anvin +Date: Wed May 2 23:36:55 2007 -0700 + + x86 setup: compile with -DSETUP + + Define SETUP to make it easier to share code with the rest of the kernel. + + Signed-off-by: H. Peter Anvin + +commit 7eb52e8ad1bdf01886023d1a13b3313084cd7db6 +Author: H. Peter Anvin +Date: Wed May 2 23:34:57 2007 -0700 + + x86 setup: remove unused verify_cpu.S + + verify_cpu.S is obsoleted by boot/cpu.c. + + Signed-off-by: H. Peter Anvin + +commit e90317a027c30176968220d18eb18bd6a9d9cc74 +Author: H. Peter Anvin +Date: Wed May 2 20:07:43 2007 -0700 + + x86 setup: files missing from previous checkin (cpu.c, cpureq.c) + + These files were missing from a previous checkin; CPU feature-checking + code and the list of CPU features to check for. + + Signed-off-by: H. Peter Anvin + +commit 060f9b3db33c67b5344b2b4110bc823eb776e5cd +Author: H. Peter Anvin +Date: Wed May 2 19:51:34 2007 -0700 + + x86 setup: whitespace cleanup + + Signed-off-by: H. Peter Anvin + +commit 9f997a5569ec8fceaa15c2e9cf28e728e2ce118d +Author: H. Peter Anvin +Date: Wed May 2 19:07:14 2007 -0700 + + x86 setup: add CPU feature detect/abort on insufficient featurage + + The x86 setup is the right place to check features and abort if they + are not present, since we can still get a message to the user via the + firmware. + + Signed-off-by: H. Peter Anvin + +commit de4e976376fddec340651ef40b16a45f6189619d +Author: H. Peter Anvin +Date: Wed May 2 19:05:34 2007 -0700 + + x86 setup: whitespace cleanup + + Signed-off-by: H. Peter Anvin + +commit bcd2d2f8de5d4568b6628aa133fce1ac40ece526 +Author: H. Peter Anvin +Date: Wed May 2 16:19:59 2007 -0700 + + x86 setup: tag functions noreturn; error message on A20 failure + + Tag appropriate functions noreturn. + If the A20 gate fails, output an error message and refuse to boot. + + Signed-off-by: H. Peter Anvin + +commit 752aef90cbfc888084bf11fd83f8f72b6a668fc9 +Author: H. Peter Anvin +Date: Wed May 2 15:45:08 2007 -0700 + + x86 setup: clobber registers in keyboard BIOS call + + Keyboard BIOS call to set repeat rate is known to clobber registers on + "many" BIOSes. + + Signed-off-by: H. Peter Anvin + +commit dde94003e4759aab275732cf9f1834440cd381d0 +Author: H. Peter Anvin +Date: Wed May 2 15:44:21 2007 -0700 + + x86 setup: implement APM BIOS probe + + APM BIOS probe ported from assembly + + Signed-off-by: H. Peter Anvin + +commit 9403917d79e3349184318704476fa080836bd52c +Author: H. Peter Anvin +Date: Wed May 2 15:17:14 2007 -0700 + + x86 setup: remove references to obsolete probes + + Remove "Hello, World!" as well as references to probes which are no + longer used... + + Signed-off-by: H. Peter Anvin + +commit 712f65ffbd1d4b55b4c55d68b4dcd32406c28fb8 +Author: H. Peter Anvin +Date: Wed May 2 12:17:15 2007 -0700 + + x86 setup: video.c: correct the handling of special mode numbers + + Special mode numbers with the high bit set need to be handled *before* + masking out the high bit. + + Signed-off-by: H. Peter Anvin + +commit 9cf083204fe14cda3b09840eba8d131d2e48ccdf +Author: H. Peter Anvin +Date: Wed May 2 11:44:16 2007 -0700 + + x86 setup: Modern ATI cards pass the probe but lacks the modes. + + It appears modern ATI cards pass the probe for ATI-ness but lack the + modes. Kill off the driver as being incorrect. + + Signed-off-by: H. Peter Anvin + +commit 890cbe950589e30af17eac9da800efc76e35e01d +Author: H. Peter Anvin +Date: Wed May 2 11:32:21 2007 -0700 + + x86 setup: a20.c: make empty_8042() return status + + Make functions which could reasonably return status do so. It may + be relevant in the future, and it's a lot better if the programmer + doesn't have to figure out where everything should hook in. + + Just on principle. + + Signed-off-by: H. Peter Anvin + +commit 08a44dc655e0086d23fc3c70cb93eb51eaeec259 +Author: H. Peter Anvin +Date: Wed May 2 11:31:03 2007 -0700 + + x86 setup: video.c: clean up unused stuff + + Clean up unused variables that we have no intent on using, as well + as other cruft. + + Signed-off-by: H. Peter Anvin + +commit 57e69acff1f577de430cae1523fd49a5d113e885 +Author: H. Peter Anvin +Date: Wed May 2 11:18:13 2007 -0700 + + x86 setup: drop video mode range checking + + Drop video mode range checking. If someone really has, say, 12x40 mode + visible through the BIOS then allow them to select it... odds are low + that it will actually conflict with the very sparse allocation we have + anyway. + + Signed-off-by: H. Peter Anvin + +commit c0dda0b90f92d43872d55d295630a71cd357cfa6 +Author: H. Peter Anvin +Date: Wed May 2 11:15:53 2007 -0700 + + x86 setup: if no specific video mode ID is given, generate one + + If we don't specify a certain video mode ID in the driver, then + generate the 0xRRCC mode ID automatically. + + Signed-off-by: H. Peter Anvin + +commit 0db5086e79810e7c5d560006b1c9a7501a02d80c +Author: H. Peter Anvin +Date: Wed May 2 11:10:28 2007 -0700 + + x86 setup: Sadly, Cirrus removed extended text modes from their BIOS. + + In the later era of the Cirrus 54xx series, Cirrus removed extended text + modes from their BIOS. Neither Qemu nor Bochs implement them in the BIOS. + If we can find a direct-register-poking method of setting them that + works in Bochs/Qemu it might be worthwhile to resurrect this; the probing + routine *does* work. + + Of course, the Right Thing[TM] would be to submit such a routine to the + Bochs/Qemu BIOS as a VESA text mode. + + Signed-off-by: H. Peter Anvin + +commit 41f3fddeeb764687bf3fb0cf77fd858128571d58 +Author: H. Peter Anvin +Date: Wed May 2 10:18:07 2007 -0700 + + x86 setup: remove assembly implementation of putchar and puts + + Already unused, remove assembly implementation of putchar and puts. + + Signed-off-by: H. Peter Anvin + +commit dfa94cd86aca2c01d2f5e14b6e7c3e8258276195 +Author: H. Peter Anvin +Date: Tue May 1 21:41:28 2007 -0700 + + x86 setup: Call INT 15h AX=E820h properly + + The calling convention for BIOS call 15:E820 was messed up. + + Signed-off-by: H. Peter Anvin + +commit 2487575a36435c0a983febbb4f3751331bd2df7a +Author: H. Peter Anvin +Date: Tue May 1 21:34:12 2007 -0700 + + x86 setup: advance one e820 descriptor at a time... + + Adding sizeof(foo) to a foo * is not just useless, it's pretty damaging... + + Signed-off-by: H. Peter Anvin + +commit 530d4f4f1732335ae8725c0b8c332a618e63ea1d +Author: H. Peter Anvin +Date: Tue May 1 21:33:28 2007 -0700 + + x86 setup: fix memcmp_[fg]s() + + Actually return a value from memcmp_[fg]s()... + + Signed-off-by: H. Peter Anvin + +commit 8617cd56ff2e43303147da012b26c9dd46af726e +Author: H. Peter Anvin +Date: Tue May 1 21:32:47 2007 -0700 + + x86 setup: fix missing semicolon in video-ati.c + + Signed-off-by: H. Peter Anvin + +commit 7bbf7fa3e199b9cef4877c5a56128faff8636cc9 +Author: H. Peter Anvin +Date: Tue May 1 21:26:48 2007 -0700 + + x86 setup: make the video setup code actually do something... + + Basic video setup now works (there is still work to be done, however.) + + Signed-off-by: H. Peter Anvin + +commit 45bcd4406e4b812b32d317d9b3b8db2e5f135a3c +Author: H. Peter Anvin +Date: Tue May 1 21:25:20 2007 -0700 + + x86 setup: segment descriptors need to be Present + + The segment descriptors were missing the Present bit. + + Signed-off-by: H. Peter Anvin + +commit a39479d4ccf4dceffb623ad2ec7e2d708c38c637 +Author: H. Peter Anvin +Date: Tue May 1 21:24:32 2007 -0700 + + build: setup sectors doesn't include the boot sector + + The "setup sectors" field doesn't include the old boot sector, + even though the two are now one module. + + Signed-off-by: H. Peter Anvin + +commit d8f3d4928ead72e8febe2fcd740d0fee71a61f42 +Author: H. Peter Anvin +Date: Tue May 1 21:23:44 2007 -0700 + + x86 setup: in tty.c, actually tell it what character to print + + putchar() was missing the actual passing of the character code to the + BIOS call, with very silly-looking results. + + Signed-off-by: H. Peter Anvin + +commit 4f1462ed0377e180484a223e622d62432baa64b7 +Author: H. Peter Anvin +Date: Tue May 1 21:22:46 2007 -0700 + + x86 setup: printf.c needs code16gcc.h + + printf.c was missing code16gcc.h, with predictable consequences. + + Signed-off-by: H. Peter Anvin + +commit a5ba7e6df198bd204b0f87fc6e3f68388b9d14c1 +Author: H. Peter Anvin +Date: Mon Apr 30 20:56:42 2007 -0700 + + MAINTAINERS: formally take responsibility for the i386 boot code + + Change MAINTAINERS to formally take responsibility for the i386 boot code. + + Signed-off-by: H. Peter Anvin + +commit 6c821fc005655a99eff6e86c2e4b13654de94dea +Author: H. Peter Anvin +Date: Mon Apr 30 20:54:07 2007 -0700 + + x86 setup code rewrite: initial development snapshot + + Clean up the setup code and rewrite it in C. + This is an initial development snapshot, not a working tree. + + Signed-off-by: H. Peter Anvin +Signed-off-by: Andrew Morton +--- + + MAINTAINERS | 4 + arch/i386/Kconfig.cpu | 4 + arch/i386/boot/Makefile | 45 + arch/i386/boot/a20.c | 161 + + arch/i386/boot/apm.c | 97 + arch/i386/boot/bitops.h | 45 + arch/i386/boot/boot.h | 290 ++ + arch/i386/boot/bootsect.S | 98 + arch/i386/boot/cmdline.c | 97 + arch/i386/boot/code16gcc.h | 9 + arch/i386/boot/compressed/Makefile | 7 + arch/i386/boot/compressed/head.S | 6 + arch/i386/boot/compressed/misc.c | 3 + arch/i386/boot/copy.S | 101 + arch/i386/boot/cpu.c | 69 + arch/i386/boot/cpucheck.c | 266 ++ + arch/i386/boot/edd.S | 231 -- + arch/i386/boot/edd.c | 196 + + arch/i386/boot/header.S | 283 ++ + arch/i386/boot/main.c | 161 + + arch/i386/boot/mca.c | 43 + arch/i386/boot/memory.c | 99 + arch/i386/boot/pm.c | 170 + + arch/i386/boot/pmjump.S | 54 + arch/i386/boot/printf.c | 331 ++ + arch/i386/boot/setup.S | 1075 --------- + arch/i386/boot/setup.ld | 54 + arch/i386/boot/string.c | 34 + arch/i386/boot/tools/build.c | 156 - + arch/i386/boot/tty.c | 112 + arch/i386/boot/version.c | 23 + arch/i386/boot/vesa.h | 79 + arch/i386/boot/video-bios.c | 125 + + arch/i386/boot/video-vesa.c | 283 ++ + arch/i386/boot/video-vga.c | 260 ++ + arch/i386/boot/video.S | 2043 ------------------ + arch/i386/boot/video.c | 456 ++++ + arch/i386/boot/video.h | 145 + + arch/i386/boot/voyager.c | 46 + arch/i386/kernel/cpu/addon_cpuid_features.c | 50 + arch/i386/kernel/cpu/common.c | 2 + arch/i386/kernel/cpu/proc.c | 21 + arch/i386/kernel/e820.c | 2 + arch/i386/kernel/setup.c | 12 + arch/i386/kernel/verify_cpu.S | 94 + arch/x86_64/Kconfig | 4 + arch/x86_64/boot/Makefile | 136 - + arch/x86_64/boot/bootsect.S | 98 + arch/x86_64/boot/compressed/Makefile | 9 + arch/x86_64/boot/compressed/head.S | 6 + arch/x86_64/boot/install.sh | 2 + arch/x86_64/boot/mtools.conf.in | 17 + arch/x86_64/boot/setup.S | 826 ------- + arch/x86_64/boot/tools/build.c | 185 - + arch/x86_64/kernel/Makefile | 2 + arch/x86_64/kernel/setup.c | 21 + arch/x86_64/kernel/verify_cpu.S | 22 + drivers/ide/legacy/hd.c | 73 + include/asm-i386/boot.h | 6 + include/asm-i386/bootparam.h | 85 + include/asm-i386/cpufeature.h | 26 + include/asm-i386/e820.h | 14 + include/asm-i386/processor.h | 1 + include/asm-i386/required-features.h | 37 + include/asm-i386/setup.h | 10 + include/asm-x86_64/alternative.h | 68 + include/asm-x86_64/boot.h | 16 + include/asm-x86_64/bootparam.h | 1 + include/asm-x86_64/cpufeature.h | 115 - + include/asm-x86_64/e820.h | 6 + include/asm-x86_64/processor.h | 3 + include/asm-x86_64/required-features.h | 46 + include/asm-x86_64/segment.h | 8 + include/linux/edd.h | 4 + include/linux/screen_info.h | 9 + 75 files changed, 4594 insertions(+), 5204 deletions(-) + +diff -puN MAINTAINERS~git-newsetup MAINTAINERS +--- a/MAINTAINERS~git-newsetup ++++ a/MAINTAINERS +@@ -1774,8 +1774,8 @@ T: http://www.harbaum.org/till/i2c_tiny_ + S: Maintained + + i386 BOOT CODE +-P: Riley H. Williams +-M: Riley@Williams.Name ++P: H. Peter Anvin ++M: hpa@zytor.com + L: Linux-Kernel@vger.kernel.org + S: Maintained + +diff -puN arch/i386/Kconfig.cpu~git-newsetup arch/i386/Kconfig.cpu +--- a/arch/i386/Kconfig.cpu~git-newsetup ++++ a/arch/i386/Kconfig.cpu +@@ -346,6 +346,6 @@ config X86_CMOV + + config X86_MINIMUM_CPU_MODEL + int +- default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP +- default "0" ++ default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK ++ default "3" + +diff -puN arch/i386/boot/Makefile~git-newsetup arch/i386/boot/Makefile +--- a/arch/i386/boot/Makefile~git-newsetup ++++ a/arch/i386/boot/Makefile +@@ -25,27 +25,53 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA + + #RAMDISK := -DRAMDISK=512 + +-targets := vmlinux.bin bootsect bootsect.o \ +- setup setup.o zImage bzImage ++targets := vmlinux.bin setup.bin setup.elf zImage bzImage + subdir- := compressed + ++setup-y += a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o ++setup-y += header.o main.o mca.o memory.o pm.o pmjump.o ++setup-y += printf.o string.o tty.o video.o version.o voyager.o ++ ++# The link order of the video-*.o modules can matter. In particular, ++# video-vga.o *must* be listed first, followed by video-vesa.o. ++# Hardware-specific drivers should follow in the order they should be ++# probed, and video-bios.o should typically be last. ++setup-y += video-vga.o ++setup-y += video-vesa.o ++setup-y += video-bios.o ++ + hostprogs-y := tools/build + + HOSTCFLAGS_build.o := $(LINUXINCLUDE) + + # --------------------------------------------------------------------------- + ++# How to compile the 16-bit code. Note we always compile for -march=i386, ++# that way we can complain to the user if the CPU is insufficient. ++cflags-i386 := ++cflags-x86_64 := -m32 ++CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ ++ $(cflags-$(ARCH)) \ ++ -Wall -Wstrict-prototypes \ ++ -march=i386 -mregparm=3 \ ++ -include $(srctree)/$(src)/code16gcc.h \ ++ -fno-strict-aliasing -fomit-frame-pointer \ ++ $(call cc-option, -ffreestanding) \ ++ $(call cc-option, -fno-stack-protector) ++AFLAGS := $(CFLAGS) -D__ASSEMBLY__ ++ + $(obj)/zImage: IMAGE_OFFSET := 0x1000 + $(obj)/zImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) + $(obj)/bzImage: IMAGE_OFFSET := 0x100000 ++$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__ + $(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ + $(obj)/bzImage: BUILDFLAGS := -b + + quiet_cmd_image = BUILD $@ +-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ ++cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \ + $(obj)/vmlinux.bin $(ROOT_DEV) > $@ + +-$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ ++$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \ + $(obj)/vmlinux.bin $(obj)/tools/build FORCE + $(call if_changed,image) + @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' +@@ -53,12 +79,17 @@ $(obj)/zImage $(obj)/bzImage: $(obj)/boo + $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE + $(call if_changed,objcopy) + +-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary +-LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext ++SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) + +-$(obj)/setup $(obj)/bootsect: %: %.o FORCE ++LDFLAGS_setup.elf := -T ++$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE + $(call if_changed,ld) + ++OBJCOPYFLAGS_setup.bin := -O binary ++ ++$(obj)/setup.bin: $(obj)/setup.elf FORCE ++ $(call if_changed,objcopy) ++ + $(obj)/compressed/vmlinux: FORCE + $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ + +diff -puN /dev/null arch/i386/boot/a20.c +--- /dev/null ++++ a/arch/i386/boot/a20.c +@@ -0,0 +1,161 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/a20.c ++ * ++ * Enable A20 gate (return -1 on failure) ++ */ ++ ++#include "boot.h" ++ ++#define MAX_8042_LOOPS 100000 ++ ++static int empty_8042(void) ++{ ++ u8 status; ++ int loops = MAX_8042_LOOPS; ++ ++ while (loops--) { ++ io_delay(); ++ ++ status = inb(0x64); ++ if (status & 1) { ++ /* Read and discard input data */ ++ io_delay(); ++ (void)inb(0x60); ++ } else if (!(status & 2)) { ++ /* Buffers empty, finished! */ ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++/* Returns nonzero if the A20 line is enabled. The memory address ++ used as a test is the int $0x80 vector, which should be safe. */ ++ ++#define A20_TEST_ADDR (4*0x80) ++#define A20_TEST_SHORT 32 ++#define A20_TEST_LONG 2097152 /* 2^21 */ ++ ++static int a20_test(int loops) ++{ ++ int ok = 0; ++ int saved, ctr; ++ ++ set_fs(0x0000); ++ set_gs(0xffff); ++ ++ saved = ctr = rdfs32(A20_TEST_ADDR); ++ ++ while (loops--) { ++ wrfs32(++ctr, A20_TEST_ADDR); ++ io_delay(); /* Serialize and make delay constant */ ++ ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr; ++ if (ok) ++ break; ++ } ++ ++ wrfs32(saved, A20_TEST_ADDR); ++ return ok; ++} ++ ++/* Quick test to see if A20 is already enabled */ ++static int a20_test_short(void) ++{ ++ return a20_test(A20_TEST_SHORT); ++} ++ ++/* Longer test that actually waits for A20 to come on line; this ++ is useful when dealing with the KBC or other slow external circuitry. */ ++static int a20_test_long(void) ++{ ++ return a20_test(A20_TEST_LONG); ++} ++ ++static void enable_a20_bios(void) ++{ ++ asm volatile("pushfl; int $0x15; popfl" ++ : : "a" ((u16)0x2401)); ++} ++ ++static void enable_a20_kbc(void) ++{ ++ empty_8042(); ++ ++ outb(0xd1, 0x64); /* Command write */ ++ empty_8042(); ++ ++ outb(0xdf, 0x60); /* A20 on */ ++ empty_8042(); ++} ++ ++static void enable_a20_fast(void) ++{ ++ u8 port_a; ++ ++ port_a = inb(0x92); /* Configuration port A */ ++ port_a |= 0x02; /* Enable A20 */ ++ port_a &= ~0x01; /* Do not reset machine */ ++ outb(port_a, 0x92); ++} ++ ++/* ++ * Actual routine to enable A20; return 0 on ok, -1 on failure ++ */ ++ ++#define A20_ENABLE_LOOPS 255 /* Number of times to try */ ++ ++int enable_a20(void) ++{ ++ int loops = A20_ENABLE_LOOPS; ++ ++#if defined(CONFIG_X86_ELAN) ++ /* Elan croaks if we try to touch the KBC */ ++ enable_a20_fast(); ++ while (!a20_test_long()) ++ ; ++ return 0; ++#elif defined(CONFIG_X86_VOYAGER) ++ /* On Voyager, a20_test() is unsafe? */ ++ enable_a20_kbc(); ++ return 0; ++#else ++ while (loops--) { ++ /* First, check to see if A20 is already enabled ++ (legacy free, etc.) */ ++ if (a20_test_short()) ++ return 0; ++ ++ /* Next, try the BIOS (INT 0x15, AX=0x2401) */ ++ enable_a20_bios(); ++ if (a20_test_short()) ++ return 0; ++ ++ /* Try enabling A20 through the keyboard controller */ ++ empty_8042(); ++ if (a20_test_short()) ++ return 0; /* BIOS worked, but with delayed reaction */ ++ ++ enable_a20_kbc(); ++ if (a20_test_long()) ++ return 0; ++ ++ /* Finally, try enabling the "fast A20 gate" */ ++ enable_a20_fast(); ++ if (a20_test_long()) ++ return 0; ++ } ++ ++ return -1; ++#endif ++} +diff -puN /dev/null arch/i386/boot/apm.c +--- /dev/null ++++ a/arch/i386/boot/apm.c +@@ -0,0 +1,97 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * Original APM BIOS checking by Stephen Rothwell, May 1994 ++ * (sfr@canb.auug.org.au) ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/apm.c ++ * ++ * Get APM BIOS information ++ */ ++ ++#include "boot.h" ++ ++#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) ++ ++int query_apm_bios(void) ++{ ++ u16 ax, bx, cx, dx, di; ++ u32 ebx, esi; ++ u8 err; ++ ++ /* APM BIOS installation check */ ++ ax = 0x5300; ++ bx = cx = 0; ++ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" ++ : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) ++ : : "esi", "edi"); ++ ++ if (err) ++ return -1; /* No APM BIOS */ ++ ++ if (bx != 0x504d) /* "PM" signature */ ++ return -1; ++ ++ if (cx & 0x02) /* 32 bits supported? */ ++ return -1; ++ ++ /* Disconnect first, just in case */ ++ ax = 0x5304; ++ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" ++ : "+a" (ax) ++ : : "ebx", "ecx", "edx", "esi", "edi"); ++ ++ /* Paranoia */ ++ ebx = esi = 0; ++ cx = dx = di = 0; ++ ++ /* 32-bit connect */ ++ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" ++ : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), ++ "+S" (esi), "+D" (di), "=m" (err) ++ : "a" (0x5303)); ++ ++ boot_params.apm_bios_info.cseg = ax; ++ boot_params.apm_bios_info.offset = ebx; ++ boot_params.apm_bios_info.cseg_16 = cx; ++ boot_params.apm_bios_info.dseg = dx; ++ boot_params.apm_bios_info.cseg_len = (u16)esi; ++ boot_params.apm_bios_info.cseg_16_len = esi >> 16; ++ boot_params.apm_bios_info.dseg_len = di; ++ ++ if (err) ++ return -1; ++ ++ /* Redo the installation check as the 32-bit connect; ++ some BIOSes return different flags this way... */ ++ ++ ax = 0x5300; ++ bx = cx = 0; ++ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" ++ : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) ++ : : "esi", "edi"); ++ ++ if (err || bx != 0x504d) { ++ /* Failure with 32-bit connect, try to disconect and ignore */ ++ ax = 0x5304; ++ bx = 0; ++ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" ++ : "+a" (ax), "+b" (bx) ++ : : "ecx", "edx", "esi", "edi"); ++ return -1; ++ } ++ ++ boot_params.apm_bios_info.version = ax; ++ boot_params.apm_bios_info.flags = cx; ++ return 0; ++} ++ ++#endif +diff -puN /dev/null arch/i386/boot/bitops.h +--- /dev/null ++++ a/arch/i386/boot/bitops.h +@@ -0,0 +1,45 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/bitops.h ++ * ++ * Very simple bitops for the boot code. ++ */ ++ ++#ifndef BOOT_BITOPS_H ++#define BOOT_BITOPS_H ++#define _LINUX_BITOPS_H /* Inhibit inclusion of */ ++ ++static inline int constant_test_bit(int nr, const void *addr) ++{ ++ const u32 *p = (const u32 *)addr; ++ return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0; ++} ++static inline int variable_test_bit(int nr, const void *addr) ++{ ++ u8 v; ++ const u32 *p = (const u32 *)addr; ++ ++ asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); ++ return v; ++} ++ ++#define test_bit(nr,addr) \ ++(__builtin_constant_p(nr) ? \ ++ constant_test_bit((nr),(addr)) : \ ++ variable_test_bit((nr),(addr))) ++ ++static inline void set_bit(int nr, void *addr) ++{ ++ asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr)); ++} ++ ++#endif /* BOOT_BITOPS_H */ +diff -puN /dev/null arch/i386/boot/boot.h +--- /dev/null ++++ a/arch/i386/boot/boot.h +@@ -0,0 +1,290 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/boot.h ++ * ++ * Header file for the real-mode kernel code ++ */ ++ ++#ifndef BOOT_BOOT_H ++#define BOOT_BOOT_H ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Useful macros */ ++#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) ++ ++extern struct setup_header hdr; ++extern struct boot_params boot_params; ++ ++/* Basic port I/O */ ++static inline void outb(u8 v, u16 port) ++{ ++ asm volatile("outb %0,%1" : : "a" (v), "dN" (port)); ++} ++static inline u8 inb(u16 port) ++{ ++ u8 v; ++ asm volatile("inb %1,%0" : "=a" (v) : "dN" (port)); ++ return v; ++} ++ ++static inline void outw(u16 v, u16 port) ++{ ++ asm volatile("outw %0,%1" : : "a" (v), "dN" (port)); ++} ++static inline u16 inw(u16 port) ++{ ++ u16 v; ++ asm volatile("inw %1,%0" : "=a" (v) : "dN" (port)); ++ return v; ++} ++ ++static inline void outl(u32 v, u16 port) ++{ ++ asm volatile("outl %0,%1" : : "a" (v), "dn" (port)); ++} ++static inline u32 inl(u32 port) ++{ ++ u32 v; ++ asm volatile("inl %1,%0" : "=a" (v) : "dN" (port)); ++ return v; ++} ++ ++static inline void io_delay(void) ++{ ++ const u16 DELAY_PORT = 0x80; ++ asm volatile("outb %%al,%0" : : "dN" (DELAY_PORT)); ++} ++ ++/* These functions are used to reference data in other segments. */ ++ ++static inline u16 ds(void) ++{ ++ u16 seg; ++ asm("movw %%ds,%0" : "=rm" (seg)); ++ return seg; ++} ++ ++static inline void set_fs(u16 seg) ++{ ++ asm volatile("movw %0,%%fs" : : "rm" (seg)); ++} ++static inline u16 fs(void) ++{ ++ u16 seg; ++ asm("movw %%fs,%0" : "=rm" (seg)); ++ return seg; ++} ++ ++static inline void set_gs(u16 seg) ++{ ++ asm volatile("movw %0,%%gs" : : "rm" (seg)); ++} ++static inline u16 gs(void) ++{ ++ u16 seg; ++ asm("movw %%gs,%0" : "=rm" (seg)); ++ return seg; ++} ++ ++typedef unsigned int addr_t; ++ ++static inline u8 rdfs8(addr_t addr) ++{ ++ u8 v; ++ asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); ++ return v; ++} ++static inline u16 rdfs16(addr_t addr) ++{ ++ u16 v; ++ asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); ++ return v; ++} ++static inline u32 rdfs32(addr_t addr) ++{ ++ u32 v; ++ asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); ++ return v; ++} ++ ++static inline void wrfs8(u8 v, addr_t addr) ++{ ++ asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v)); ++} ++static inline void wrfs16(u16 v, addr_t addr) ++{ ++ asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v)); ++} ++static inline void wrfs32(u32 v, addr_t addr) ++{ ++ asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v)); ++} ++ ++static inline u8 rdgs8(addr_t addr) ++{ ++ u8 v; ++ asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); ++ return v; ++} ++static inline u16 rdgs16(addr_t addr) ++{ ++ u16 v; ++ asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); ++ return v; ++} ++static inline u32 rdgs32(addr_t addr) ++{ ++ u32 v; ++ asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); ++ return v; ++} ++ ++static inline void wrgs8(u8 v, addr_t addr) ++{ ++ asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v)); ++} ++static inline void wrgs16(u16 v, addr_t addr) ++{ ++ asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v)); ++} ++static inline void wrgs32(u32 v, addr_t addr) ++{ ++ asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v)); ++} ++ ++/* Note: these only return true/false, not a signed return value! */ ++static inline int memcmp(const void *s1, const void *s2, size_t len) ++{ ++ u8 diff; ++ asm("repe; cmpsb; setnz %0" ++ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); ++ return diff; ++} ++ ++static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) ++{ ++ u8 diff; ++ asm("fs; repe; cmpsb; setnz %0" ++ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); ++ return diff; ++} ++static inline int memcmp_gs(const void *s1, addr_t s2, size_t len) ++{ ++ u8 diff; ++ asm("gs; repe; cmpsb; setnz %0" ++ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); ++ return diff; ++} ++ ++/* Heap -- available for dynamic lists. */ ++#define STACK_SIZE 512 /* Minimum number of bytes for stack */ ++ ++extern char _end[]; ++extern char *HEAP; ++extern char *heap_end; ++#define RESET_HEAP() ((void *)( HEAP = _end )) ++static inline char *__get_heap(size_t s, size_t a, size_t n) ++{ ++ char *tmp; ++ ++ HEAP = (char *)(((size_t)HEAP+(a-1)) & ~(a-1)); ++ tmp = HEAP; ++ HEAP += s*n; ++ return tmp; ++} ++#define GET_HEAP(type, n) \ ++ ((type *)__get_heap(sizeof(type),__alignof__(type),(n))) ++ ++static inline int heap_free(void) ++{ ++ return heap_end-HEAP; ++} ++ ++/* copy.S */ ++ ++void copy_to_fs(addr_t dst, void *src, size_t len); ++void *copy_from_fs(void *dst, addr_t src, size_t len); ++void copy_to_gs(addr_t dst, void *src, size_t len); ++void *copy_from_gs(void *dst, addr_t src, size_t len); ++void *memcpy(void *dst, void *src, size_t len); ++void *memset(void *dst, int c, size_t len); ++ ++#define memcpy(d,s,l) __builtin_memcpy(d,s,l) ++#define memset(d,c,l) __builtin_memset(d,c,l) ++ ++/* a20.c */ ++int enable_a20(void); ++ ++/* apm.c */ ++int query_apm_bios(void); ++ ++/* cmdline.c */ ++int cmdline_find_option(const char *option, char *buffer, int bufsize); ++ ++/* cpu.c, cpucheck.c */ ++int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); ++int validate_cpu(void); ++ ++/* edd.c */ ++void query_edd(void); ++ ++/* header.S */ ++void __attribute__((noreturn)) die(void); ++ ++/* mca.c */ ++int query_mca(void); ++ ++/* memory.c */ ++int detect_memory(void); ++ ++/* pm.c */ ++void __attribute__((noreturn)) go_to_protected_mode(void); ++ ++/* pmjump.S */ ++void __attribute__((noreturn)) ++ protected_mode_jump(u32 entrypoint, u32 bootparams); ++ ++/* printf.c */ ++unsigned int atou(const char *s); ++int sprintf(char *buf, const char *fmt, ...); ++int vsprintf(char *buf, const char *fmt, va_list args); ++int printf(const char *fmt, ...); ++ ++/* string.c */ ++int strcmp(const char *str1, const char *str2); ++ ++/* tty.c */ ++void puts(const char *); ++void putchar(int); ++int getchar(void); ++void kbd_flush(void); ++int getchar_timeout(void); ++ ++/* video.c */ ++void set_video(void); ++ ++/* video-vesa.c */ ++void vesa_store_edid(void); ++ ++/* voyager.c */ ++int query_voyager(void); ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* BOOT_BOOT_H */ +diff -puN arch/i386/boot/bootsect.S~git-newsetup /dev/null +--- a/arch/i386/boot/bootsect.S ++++ /dev/null +@@ -1,98 +0,0 @@ +-/* +- * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds +- * +- * modified by Drew Eckhardt +- * modified by Bruce Evans (bde) +- * modified by Chris Noe (May 1999) (as86 -> gas) +- * gutted by H. Peter Anvin (Jan 2003) +- * +- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment +- * addresses must be multiplied by 16 to obtain their respective linear +- * addresses. To avoid confusion, linear addresses are written using leading +- * hex while segment addresses are written as segment:offset. +- * +- */ +- +-#include +- +-SETUPSECTS = 4 /* default nr of setup-sectors */ +-BOOTSEG = 0x07C0 /* original address of boot-sector */ +-INITSEG = DEF_INITSEG /* we move boot here - out of the way */ +-SETUPSEG = DEF_SETUPSEG /* setup starts here */ +-SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ +-SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ +- /* to be loaded */ +-ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ +-SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ +- +-#ifndef SVGA_MODE +-#define SVGA_MODE ASK_VGA +-#endif +- +-#ifndef RAMDISK +-#define RAMDISK 0 +-#endif +- +-#ifndef ROOT_RDONLY +-#define ROOT_RDONLY 1 +-#endif +- +-.code16 +-.text +- +-.global _start +-_start: +- +- # Normalize the start address +- jmpl $BOOTSEG, $start2 +- +-start2: +- movw %cs, %ax +- movw %ax, %ds +- movw %ax, %es +- movw %ax, %ss +- movw $0x7c00, %sp +- sti +- cld +- +- movw $bugger_off_msg, %si +- +-msg_loop: +- lodsb +- andb %al, %al +- jz die +- movb $0xe, %ah +- movw $7, %bx +- int $0x10 +- jmp msg_loop +- +-die: +- # Allow the user to press a key, then reboot +- xorw %ax, %ax +- int $0x16 +- int $0x19 +- +- # int 0x19 should never return. In case it does anyway, +- # invoke the BIOS reset code... +- ljmp $0xf000,$0xfff0 +- +- +-bugger_off_msg: +- .ascii "Direct booting from floppy is no longer supported.\r\n" +- .ascii "Please use a boot loader program instead.\r\n" +- .ascii "\n" +- .ascii "Remove disk and press any key to reboot . . .\r\n" +- .byte 0 +- +- +- # Kernel attributes; used by setup +- +- .org 497 +-setup_sects: .byte SETUPSECTS +-root_flags: .word ROOT_RDONLY +-syssize: .word SYSSIZE +-swap_dev: .word SWAP_DEV +-ram_size: .word RAMDISK +-vid_mode: .word SVGA_MODE +-root_dev: .word ROOT_DEV +-boot_flag: .word 0xAA55 +diff -puN /dev/null arch/i386/boot/cmdline.c +--- /dev/null ++++ a/arch/i386/boot/cmdline.c +@@ -0,0 +1,97 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/cmdline.c ++ * ++ * Simple command-line parser for early boot. ++ */ ++ ++#include "boot.h" ++ ++static inline int myisspace(u8 c) ++{ ++ return c <= ' '; /* Close enough approximation */ ++} ++ ++/* ++ * Find a non-boolean option, that is, "option=argument". In accordance ++ * with standard Linux practice, if this option is repeated, this returns ++ * the last instance on the command line. ++ * ++ * Returns the length of the argument (regardless of if it was ++ * truncated to fit in the buffer), or -1 on not found. ++ */ ++int cmdline_find_option(const char *option, char *buffer, int bufsize) ++{ ++ u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr; ++ addr_t cptr; ++ char c; ++ int len = -1; ++ const char *opptr = NULL; ++ char *bufptr = buffer; ++ enum { ++ st_wordstart, /* Start of word/after whitespace */ ++ st_wordcmp, /* Comparing this word */ ++ st_wordskip, /* Miscompare, skip */ ++ st_bufcpy /* Copying this to buffer */ ++ } state = st_wordstart; ++ ++ if (!cmdline_ptr || cmdline_ptr >= 0x100000) ++ return -1; /* No command line, or inaccessible */ ++ ++ cptr = cmdline_ptr & 0xf; ++ set_fs(cmdline_ptr >> 4); ++ ++ while (cptr < 0x10000 && (c = rdfs8(cptr++))) { ++ switch (state) { ++ case st_wordstart: ++ if (myisspace(c)) ++ break; ++ ++ /* else */ ++ state = st_wordcmp; ++ opptr = option; ++ /* fall through */ ++ ++ case st_wordcmp: ++ if (c == '=' && !*opptr) { ++ len = 0; ++ bufptr = buffer; ++ state = st_bufcpy; ++ } else if (myisspace(c)) { ++ state = st_wordstart; ++ } else if (c != *opptr++) { ++ state = st_wordskip; ++ } ++ break; ++ ++ case st_wordskip: ++ if (myisspace(c)) ++ state = st_wordstart; ++ break; ++ ++ case st_bufcpy: ++ if (myisspace(c)) { ++ state = st_wordstart; ++ } else { ++ if (len < bufsize-1) ++ *bufptr++ = c; ++ len++; ++ } ++ break; ++ } ++ } ++ ++ if (bufsize) ++ *bufptr = '\0'; ++ ++ return len; ++} +diff -puN /dev/null arch/i386/boot/code16gcc.h +--- /dev/null ++++ a/arch/i386/boot/code16gcc.h +@@ -0,0 +1,9 @@ ++/* ++ * code16gcc.h ++ * ++ * This file is -include'd when compiling 16-bit C code. ++ */ ++ ++#ifndef __ASSEMBLY__ ++asm(".code16gcc"); ++#endif +diff -puN arch/i386/boot/compressed/Makefile~git-newsetup arch/i386/boot/compressed/Makefile +--- a/arch/i386/boot/compressed/Makefile~git-newsetup ++++ a/arch/i386/boot/compressed/Makefile +@@ -9,9 +9,14 @@ targets := vmlinux vmlinux.bin vmlinux. + EXTRA_AFLAGS := -traditional + + LDFLAGS_vmlinux := -T +-CFLAGS_misc.o += -fPIC + hostprogs-y := relocs + ++CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ ++ -fno-strict-aliasing -fPIC \ ++ $(call cc-option,-ffreestanding) \ ++ $(call cc-option,-fno-stack-protector) ++LDFLAGS := -m elf_i386 ++ + $(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE + $(call if_changed,ld) + @: +diff -puN arch/i386/boot/compressed/head.S~git-newsetup arch/i386/boot/compressed/head.S +--- a/arch/i386/boot/compressed/head.S~git-newsetup ++++ a/arch/i386/boot/compressed/head.S +@@ -45,10 +45,10 @@ startup_32: + * at and where we were actually loaded at. This can only be done + * with a short local call on x86. Nothing else will tell us what + * address we are running at. The reserved chunk of the real-mode +- * data at 0x34-0x3f are used as the stack for this calculation. +- * Only 4 bytes are needed. ++ * data at 0x1e4 (defined as a scratch field) are used as the stack ++ * for this calculation. Only 4 bytes are needed. + */ +- leal 0x40(%esi), %esp ++ leal (0x1e4+4)(%esi), %esp + call 1f + 1: popl %ebp + subl $1b, %ebp +diff -puN arch/i386/boot/compressed/misc.c~git-newsetup arch/i386/boot/compressed/misc.c +--- a/arch/i386/boot/compressed/misc.c~git-newsetup ++++ a/arch/i386/boot/compressed/misc.c +@@ -11,7 +11,6 @@ + + #undef CONFIG_PARAVIRT + #include +-#include + #include + #include + #include +@@ -364,8 +363,10 @@ asmlinkage void decompress_kernel(void * + + if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1)) + error("Destination address not CONFIG_PHYSICAL_ALIGN aligned"); ++#ifndef CONFIG_X86_64 + if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff)) + error("Destination address too large"); ++#endif + #ifndef CONFIG_RELOCATABLE + if ((u32)output != LOAD_PHYSICAL_ADDR) + error("Wrong destination address"); +diff -puN /dev/null arch/i386/boot/copy.S +--- /dev/null ++++ a/arch/i386/boot/copy.S +@@ -0,0 +1,101 @@ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/copy.S ++ * ++ * Memory copy routines ++ */ ++ ++ .code16gcc ++ .text ++ ++ .globl memcpy ++ .type memcpy, @function ++memcpy: ++ pushw %si ++ pushw %di ++ movw %ax, %di ++ movw %dx, %si ++ pushw %cx ++ shrw $2, %cx ++ rep; movsl ++ popw %cx ++ andw $3, %cx ++ rep; movsb ++ popw %di ++ popw %si ++ ret ++ .size memcpy, .-memcpy ++ ++ .globl memset ++ .type memset, @function ++memset: ++ pushw %di ++ movw %ax, %di ++ movzbl %dl, %eax ++ imull $0x01010101,%eax ++ pushw %cx ++ shrw $2, %cx ++ rep; stosl ++ popw %cx ++ andw $3, %cx ++ rep; stosb ++ popw %di ++ ret ++ .size memset, .-memset ++ ++ .globl copy_from_fs ++ .type copy_from_fs, @function ++copy_from_fs: ++ pushw %ds ++ pushw %fs ++ popw %ds ++ call memcpy ++ popw %ds ++ ret ++ .size copy_from_fs, .-copy_from_fs ++ ++ .globl copy_to_fs ++ .type copy_to_fs, @function ++copy_to_fs: ++ pushw %es ++ pushw %fs ++ popw %es ++ call memcpy ++ popw %es ++ ret ++ .size copy_to_fs, .-copy_to_fs ++ ++#if 0 /* Not currently used, but can be enabled as needed */ ++ ++ .globl copy_from_gs ++ .type copy_from_gs, @function ++copy_from_gs: ++ pushw %ds ++ pushw %gs ++ popw %ds ++ call memcpy ++ popw %ds ++ ret ++ .size copy_from_gs, .-copy_from_gs ++ .globl copy_to_gs ++ ++ .type copy_to_gs, @function ++copy_to_gs: ++ pushw %es ++ pushw %gs ++ popw %es ++ call memcpy ++ popw %es ++ ret ++ .size copy_to_gs, .-copy_to_gs ++ ++#endif +diff -puN /dev/null arch/i386/boot/cpu.c +--- /dev/null ++++ a/arch/i386/boot/cpu.c +@@ -0,0 +1,69 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/cpucheck.c ++ * ++ * Check for obligatory CPU features and abort if the features are not ++ * present. ++ */ ++ ++#include "boot.h" ++#include "bitops.h" ++#include ++ ++static char *cpu_name(int level) ++{ ++ static char buf[6]; ++ ++ if (level == 64) { ++ return "x86-64"; ++ } else { ++ sprintf(buf, "i%d86", level); ++ return buf; ++ } ++} ++ ++int validate_cpu(void) ++{ ++ u32 *err_flags; ++ int cpu_level, req_level; ++ ++ check_cpu(&cpu_level, &req_level, &err_flags); ++ ++ if (cpu_level < req_level) { ++ printf("This kernel requires an %s CPU, ", ++ cpu_name(req_level)); ++ printf("but only detected an %s CPU.\n", ++ cpu_name(cpu_level)); ++ return -1; ++ } ++ ++ if (err_flags) { ++ int i, j; ++ puts("This kernel requires the following features " ++ "not present on the CPU:\n"); ++ ++ for (i = 0; i < NCAPINTS; i++) { ++ u32 e = err_flags[i]; ++ ++ for (j = 0; j < 32; j++) { ++ if (e & 1) ++ printf("%d:%d ", i, j); ++ ++ e >>= 1; ++ } ++ } ++ putchar('\n'); ++ return -1; ++ } else { ++ return 0; ++ } ++} +diff -puN /dev/null arch/i386/boot/cpucheck.c +--- /dev/null ++++ a/arch/i386/boot/cpucheck.c +@@ -0,0 +1,266 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/cpu.c ++ * ++ * Check for obligatory CPU features and abort if the features are not ++ * present. This code should be compilable as 16-, 32- or 64-bit ++ * code, so be very careful with types and inline assembly. ++ * ++ * This code should not contain any messages; that requires an ++ * additional wrapper. ++ * ++ * As written, this code is not safe for inclusion into the kernel ++ * proper (after FPU initialization, in particular). ++ */ ++ ++#ifdef _SETUP ++# include "boot.h" ++# include "bitops.h" ++#endif ++#include ++#include ++#include ++#include ++#include ++ ++struct cpu_features { ++ int level; ++ int model; ++ u32 flags[NCAPINTS]; ++}; ++ ++static struct cpu_features cpu; ++static u32 cpu_vendor[3]; ++static u32 err_flags[NCAPINTS]; ++ ++#ifdef CONFIG_X86_64 ++static const int req_level = 64; ++#elif defined(CONFIG_X86_MINIMUM_CPU_MODEL) ++static const int req_level = CONFIG_X86_MINIMUM_CPU_MODEL; ++#else ++static const int req_level = 3; ++#endif ++ ++static const u32 req_flags[NCAPINTS] = ++{ ++ REQUIRED_MASK0, ++ REQUIRED_MASK1, ++ REQUIRED_MASK2, ++ REQUIRED_MASK3, ++ REQUIRED_MASK4, ++ REQUIRED_MASK5, ++ REQUIRED_MASK6, ++}; ++ ++#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a)) ++ ++static int is_amd(void) ++{ ++ return cpu_vendor[0] == A32('A','u','t','h') && ++ cpu_vendor[1] == A32('e','n','t','i') && ++ cpu_vendor[2] == A32('c','A','M','D'); ++} ++ ++static int is_centaur(void) ++{ ++ return cpu_vendor[0] == A32('C','e','n','t') && ++ cpu_vendor[1] == A32('a','u','r','H') && ++ cpu_vendor[2] == A32('a','u','l','s'); ++} ++ ++static int is_transmeta(void) ++{ ++ return cpu_vendor[0] == A32('G','e','n','u') && ++ cpu_vendor[1] == A32('i','n','e','T') && ++ cpu_vendor[2] == A32('M','x','8','6'); ++} ++ ++static int has_fpu(void) ++{ ++ u16 fcw = -1, fsw = -1; ++ u32 cr0; ++ ++ asm("movl %%cr0,%0" : "=r" (cr0)); ++ if (cr0 & (X86_CR0_EM|X86_CR0_TS)) { ++ cr0 &= ~(X86_CR0_EM|X86_CR0_TS); ++ asm volatile("movl %0,%%cr0" : : "r" (cr0)); ++ } ++ ++ asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw)); ++ ++ return fsw == 0 && (fcw & 0x103f) == 0x003f; ++} ++ ++static int has_eflag(u32 mask) ++{ ++ u32 f0, f1; ++ ++ asm("pushfl ; " ++ "pushfl ; " ++ "popl %0 ; " ++ "movl %0,%1 ; " ++ "xorl %2,%1 ; " ++ "pushl %1 ; " ++ "popfl ; " ++ "pushfl ; " ++ "popl %1 ; " ++ "popfl" ++ : "=r" (f0), "=r" (f1) ++ : "g" (mask)); ++ ++ return !!((f0^f1) & mask); ++} ++ ++static void get_flags(void) ++{ ++ u32 max_intel_level, max_amd_level; ++ u32 tfms; ++ ++ if (has_fpu()) ++ set_bit(X86_FEATURE_FPU, cpu.flags); ++ ++ if (has_eflag(X86_EFLAGS_ID)) { ++ asm("cpuid" ++ : "=a" (max_intel_level), ++ "=b" (cpu_vendor[0]), ++ "=d" (cpu_vendor[1]), ++ "=c" (cpu_vendor[2]) ++ : "a" (0)); ++ ++ if (max_intel_level >= 0x00000001 && ++ max_intel_level <= 0x0000ffff) { ++ asm("cpuid" ++ : "=a" (tfms), ++ "=c" (cpu.flags[4]), ++ "=d" (cpu.flags[0]) ++ : "a" (0x00000001) ++ : "ebx"); ++ cpu.level = (tfms >> 8) & 15; ++ cpu.model = (tfms >> 4) & 15; ++ if (cpu.level >= 6) ++ cpu.model += ((tfms >> 16) & 0xf) << 4; ++ } ++ ++ asm("cpuid" ++ : "=a" (max_amd_level) ++ : "a" (0x80000000) ++ : "ebx", "ecx", "edx"); ++ ++ if (max_amd_level >= 0x80000001 && ++ max_amd_level <= 0x8000ffff) { ++ u32 eax = 0x80000001; ++ asm("cpuid" ++ : "+a" (eax), ++ "=c" (cpu.flags[6]), ++ "=d" (cpu.flags[1]) ++ : : "ebx"); ++ } ++ } ++} ++ ++/* Returns a bitmask of which words we have error bits in */ ++static int check_flags(void) ++{ ++ u32 err; ++ int i; ++ ++ err = 0; ++ for (i = 0; i < NCAPINTS; i++) { ++ err_flags[i] = req_flags[i] & ~cpu.flags[i]; ++ if (err_flags[i]) ++ err |= 1 << i; ++ } ++ ++ return err; ++} ++ ++/* ++ * Returns -1 on error. ++ * ++ * *cpu_level is set to the current CPU level; *req_level to the required ++ * level. x86-64 is considered level 64 for this purpose. ++ * ++ * *err_flags_ptr is set to the flags error array if there are flags missing. ++ */ ++int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) ++{ ++ int err; ++ ++ memset(&cpu.flags, 0, sizeof cpu.flags); ++ cpu.level = 3; ++ ++ if (has_eflag(X86_EFLAGS_AC)) ++ cpu.level = 4; ++ ++ get_flags(); ++ err = check_flags(); ++ ++ if (test_bit(X86_FEATURE_LM, cpu.flags)) ++ cpu.level = 64; ++ ++ if (err == 0x01 && ++ !(err_flags[0] & ++ ~((1 << X86_FEATURE_XMM)|(1 << X86_FEATURE_XMM2))) && ++ is_amd()) { ++ /* If this is an AMD and we're only missing SSE+SSE2, try to ++ turn them on */ ++ ++ u32 ecx = MSR_K7_HWCR; ++ u32 eax, edx; ++ ++ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); ++ eax &= ~(1 << 15); ++ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); ++ ++ get_flags(); /* Make sure it really did something */ ++ err = check_flags(); ++ } else if (err == 0x01 && ++ !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) && ++ is_centaur() && cpu.model >= 6) { ++ /* If this is a VIA C3, we might have to enable CX8 ++ explicitly */ ++ ++ u32 ecx = MSR_VIA_FCR; ++ u32 eax, edx; ++ ++ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); ++ eax |= (1<<1)|(1<<7); ++ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); ++ ++ set_bit(X86_FEATURE_CX8, cpu.flags); ++ err = check_flags(); ++ } else if (err == 0x01 && is_transmeta()) { ++ /* Transmeta might have masked feature bits in word 0 */ ++ ++ u32 ecx = 0x80860004; ++ u32 eax, edx; ++ u32 level = 1; ++ ++ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); ++ asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx)); ++ asm("cpuid" ++ : "+a" (level), "=d" (cpu.flags[0]) ++ : : "ecx", "ebx"); ++ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); ++ ++ err = check_flags(); ++ } ++ ++ if (err_flags_ptr) ++ *err_flags_ptr = err ? err_flags : NULL; ++ if (cpu_level_ptr) ++ *cpu_level_ptr = cpu.level; ++ if (req_level_ptr) ++ *req_level_ptr = req_level; ++ ++ return (cpu.level < req_level || err) ? -1 : 0; ++} +diff -puN arch/i386/boot/edd.S~git-newsetup /dev/null +--- a/arch/i386/boot/edd.S ++++ /dev/null +@@ -1,231 +0,0 @@ +-/* +- * BIOS Enhanced Disk Drive support +- * Copyright (C) 2002, 2003, 2004 Dell, Inc. +- * by Matt Domsch October 2002 +- * conformant to T13 Committee www.t13.org +- * projects 1572D, 1484D, 1386D, 1226DT +- * disk signature read by Matt Domsch +- * and Andrew Wilks September 2003, June 2004 +- * legacy CHS retrieval by Patrick J. LoPresti +- * March 2004 +- * Command line option parsing, Matt Domsch, November 2004 +- */ +- +-#include +-#include +- +-#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) +- +-# It is assumed that %ds == INITSEG here +- +- movb $0, (EDD_MBR_SIG_NR_BUF) +- movb $0, (EDDNR) +- +-# Check the command line for options: +-# edd=of disables EDD completely (edd=off) +-# edd=sk skips the MBR test (edd=skipmbr) +-# edd=on re-enables EDD (edd=on) +- +- pushl %esi +- movw $edd_mbr_sig_start, %di # Default to edd=on +- +- movl %cs:(cmd_line_ptr), %esi +- andl %esi, %esi +- jz old_cl # Old boot protocol? +- +-# Convert to a real-mode pointer in fs:si +- movl %esi, %eax +- shrl $4, %eax +- movw %ax, %fs +- andw $0xf, %si +- jmp have_cl_pointer +- +-# Old-style boot protocol? +-old_cl: +- push %ds # aka INITSEG +- pop %fs +- +- cmpw $0xa33f, (0x20) +- jne done_cl # No command line at all? +- movw (0x22), %si # Pointer relative to INITSEG +- +-# fs:si has the pointer to the command line now +-have_cl_pointer: +- +-# Loop through kernel command line one byte at a time. Just in +-# case the loader is buggy and failed to null-terminate the command line +-# terminate if we get close enough to the end of the segment that we +-# cannot fit "edd=XX"... +-cl_atspace: +- cmpw $-5, %si # Watch for segment wraparound +- jae done_cl +- movl %fs:(%si), %eax +- andb %al, %al # End of line? +- jz done_cl +- cmpl $EDD_CL_EQUALS, %eax +- jz found_edd_equals +- cmpb $0x20, %al # <= space consider whitespace +- ja cl_skipword +- incw %si +- jmp cl_atspace +- +-cl_skipword: +- cmpw $-5, %si # Watch for segment wraparound +- jae done_cl +- movb %fs:(%si), %al # End of string? +- andb %al, %al +- jz done_cl +- cmpb $0x20, %al +- jbe cl_atspace +- incw %si +- jmp cl_skipword +- +-found_edd_equals: +-# only looking at first two characters after equals +-# late overrides early on the command line, so keep going after finding something +- movw %fs:4(%si), %ax +- cmpw $EDD_CL_OFF, %ax # edd=of +- je do_edd_off +- cmpw $EDD_CL_SKIP, %ax # edd=sk +- je do_edd_skipmbr +- cmpw $EDD_CL_ON, %ax # edd=on +- je do_edd_on +- jmp cl_skipword +-do_edd_skipmbr: +- movw $edd_start, %di +- jmp cl_skipword +-do_edd_off: +- movw $edd_done, %di +- jmp cl_skipword +-do_edd_on: +- movw $edd_mbr_sig_start, %di +- jmp cl_skipword +- +-done_cl: +- popl %esi +- jmpw *%di +- +-# Read the first sector of each BIOS disk device and store the 4-byte signature +-edd_mbr_sig_start: +- movb $0x80, %dl # from device 80 +- movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx +-edd_mbr_sig_read: +- movl $0xFFFFFFFF, %eax +- movl %eax, (%bx) # assume failure +- pushw %bx +- movb $READ_SECTORS, %ah +- movb $1, %al # read 1 sector +- movb $0, %dh # at head 0 +- movw $1, %cx # cylinder 0, sector 0 +- pushw %es +- pushw %ds +- popw %es +- movw $EDDBUF, %bx # disk's data goes into EDDBUF +- pushw %dx # work around buggy BIOSes +- stc # work around buggy BIOSes +- int $0x13 +- sti # work around buggy BIOSes +- popw %dx +- popw %es +- popw %bx +- jc edd_mbr_sig_done # on failure, we're done. +- cmpb $0, %ah # some BIOSes do not set CF +- jne edd_mbr_sig_done # on failure, we're done. +- movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR +- movl %eax, (%bx) # store success +- incb (EDD_MBR_SIG_NR_BUF) # note that we stored something +- incb %dl # increment to next device +- addw $4, %bx # increment sig buffer ptr +- cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space? +- jb edd_mbr_sig_read # keep looping +-edd_mbr_sig_done: +- +-# Do the BIOS Enhanced Disk Drive calls +-# This consists of two calls: +-# int 13h ah=41h "Check Extensions Present" +-# int 13h ah=48h "Get Device Parameters" +-# int 13h ah=08h "Legacy Get Device Parameters" +-# +-# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use +-# in the boot_params at EDDBUF. The first four bytes of which are +-# used to store the device number, interface support map and version +-# results from fn41. The next four bytes are used to store the legacy +-# cylinders, heads, and sectors from fn08. The following 74 bytes are used to +-# store the results from fn48. Starting from device 80h, fn41, then fn48 +-# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE). +-# Then the pointer is incremented to store the data for the next call. +-# This repeats until either a device doesn't exist, or until EDDMAXNR +-# devices have been stored. +-# The one tricky part is that ds:si always points EDDEXTSIZE bytes into +-# the structure, and the fn41 and fn08 results are stored at offsets +-# from there. This removes the need to increment the pointer for +-# every store, and leaves it ready for the fn48 call. +-# A second one-byte buffer, EDDNR, in the boot_params stores +-# the number of BIOS devices which exist, up to EDDMAXNR. +-# In setup.c, copy_edd() stores both boot_params buffers away +-# for later use, as they would get overwritten otherwise. +-# This code is sensitive to the size of the structs in edd.h +-edd_start: +- # %ds points to the bootsector +- # result buffer for fn48 +- movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results +- # kept just before that +- movb $0x80, %dl # BIOS device 0x80 +- +-edd_check_ext: +- movb $CHECKEXTENSIONSPRESENT, %ah # Function 41 +- movw $EDDMAGIC1, %bx # magic +- int $0x13 # make the call +- jc edd_done # no more BIOS devices +- +- cmpw $EDDMAGIC2, %bx # is magic right? +- jne edd_next # nope, next... +- +- movb %dl, %ds:-8(%si) # store device number +- movb %ah, %ds:-7(%si) # store version +- movw %cx, %ds:-6(%si) # store extensions +- incb (EDDNR) # note that we stored something +- +-edd_get_device_params: +- movw $EDDPARMSIZE, %ds:(%si) # put size +- movw $0x0, %ds:2(%si) # work around buggy BIOSes +- movb $GETDEVICEPARAMETERS, %ah # Function 48 +- int $0x13 # make the call +- # Don't check for fail return +- # it doesn't matter. +-edd_get_legacy_chs: +- xorw %ax, %ax +- movw %ax, %ds:-4(%si) +- movw %ax, %ds:-2(%si) +- # Ralf Brown's Interrupt List says to set ES:DI to +- # 0000h:0000h "to guard against BIOS bugs" +- pushw %es +- movw %ax, %es +- movw %ax, %di +- pushw %dx # legacy call clobbers %dl +- movb $LEGACYGETDEVICEPARAMETERS, %ah # Function 08 +- int $0x13 # make the call +- jc edd_legacy_done # failed +- movb %cl, %al # Low 6 bits are max +- andb $0x3F, %al # sector number +- movb %al, %ds:-1(%si) # Record max sect +- movb %dh, %ds:-2(%si) # Record max head number +- movb %ch, %al # Low 8 bits of max cyl +- shr $6, %cl +- movb %cl, %ah # High 2 bits of max cyl +- movw %ax, %ds:-4(%si) +- +-edd_legacy_done: +- popw %dx +- popw %es +- movw %si, %ax # increment si +- addw $EDDPARMSIZE+EDDEXTSIZE, %ax +- movw %ax, %si +- +-edd_next: +- incb %dl # increment to next device +- cmpb $EDDMAXNR, (EDDNR) # Out of space? +- jb edd_check_ext # keep looping +- +-edd_done: +-#endif +diff -puN /dev/null arch/i386/boot/edd.c +--- /dev/null ++++ a/arch/i386/boot/edd.c +@@ -0,0 +1,196 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/edd.c ++ * ++ * Get EDD BIOS disk information ++ */ ++ ++#include "boot.h" ++#include ++ ++#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) ++ ++struct edd_dapa { ++ u8 pkt_size; ++ u8 rsvd; ++ u16 sector_cnt; ++ u16 buf_off, buf_seg; ++ u64 lba; ++ u64 buf_lin_addr; ++}; ++ ++/* ++ * Note: this uses the heap to hold the loaded sector. ++ */ ++static int read_sector(u8 devno, u64 lba, void *buf) ++{ ++ struct edd_dapa dapa; ++ u16 ax, bx, cx, dx, si; ++ ++ memset(&dapa, 0, sizeof dapa); ++ dapa.pkt_size = sizeof(dapa); ++ dapa.sector_cnt = 1; ++ dapa.buf_off = (size_t)buf; ++ dapa.buf_seg = ds(); ++ dapa.lba = lba; ++ ++ ax = 0x4200; /* Extended Read */ ++ si = (size_t)&dapa; ++ dx = devno; ++ asm("pushfl; stc; int $0x13; setc %%al; popfl" ++ : "+a" (ax), "+S" (si), "+d" (dx) ++ : "m" (dapa) ++ : "ebx", "ecx", "edi", "memory"); ++ ++ if (!(u8)ax) ++ return 0; /* OK */ ++ ++ ax = 0x0201; /* Legacy Read, one sector */ ++ cx = 0x0001; /* Sector 0-0-1 */ ++ dx = devno; ++ bx = (size_t)buf; ++ asm("pushfl; stc; int $0x13; setc %%al; popfl" ++ : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) ++ : : "esi", "edi", "memory"); ++ ++ return -(u8)ax; /* 0 or -1 */ ++} ++ ++static u32 read_mbr_sig(u8 devno, struct edd_info *ei) ++{ ++ int sector_size; ++ char *mbrbuf_ptr, *mbrbuf_end; ++ u32 mbrsig; ++ u32 buf_base, mbr_base; ++ extern char _end[]; ++ static char mbr_buf[1024]; ++ ++ sector_size = ei->params.bytes_per_sector; ++ if (!sector_size) ++ sector_size = 512; /* Best available guess */ ++ ++ buf_base = (ds() << 4) + (u32)&_end; ++ mbr_base = (buf_base+sector_size-1) & ~(sector_size-1); ++ mbrbuf_ptr = mbr_buf + (mbr_base-buf_base); ++ mbrbuf_end = mbrbuf_ptr + sector_size; ++ ++ if (!(boot_params.hdr.loadflags & CAN_USE_HEAP)) ++ return 0; ++ if (mbrbuf_end > (char *)(size_t)boot_params.hdr.heap_end_ptr) ++ return 0; ++ ++ if (read_sector(devno, 0, mbrbuf_ptr)) ++ return 0; ++ ++ mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET]; ++ return mbrsig; ++} ++ ++static int get_edd_info(u8 devno, struct edd_info *ei) ++{ ++ u16 ax, bx, cx, dx, di; ++ ++ memset(ei, 0, sizeof *ei); ++ ++ /* Check Extensions Present */ ++ ++ ax = 0x4100; ++ bx = EDDMAGIC1; ++ dx = devno; ++ asm("pushfl; stc; int $0x13; setc %%al; popfl" ++ : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx) ++ : : "esi", "edi"); ++ ++ if ((u8)ax) ++ return -1; /* No extended information */ ++ ++ if (bx != EDDMAGIC2) ++ return -1; ++ ++ ei->device = devno; ++ ei->version = ax >> 8; /* EDD version number */ ++ ei->interface_support = cx; /* EDD functionality subsets */ ++ ++ /* Extended Get Device Parameters */ ++ ++ ei->params.length = sizeof(ei->params); ++ ax = 0x4800; ++ dx = devno; ++ asm("pushfl; int $0x13; popfl" ++ : "+a" (ax), "+d" (dx) ++ : "S" (&ei->params) ++ : "ebx", "ecx", "edi"); ++ ++ /* Get legacy CHS parameters */ ++ ++ /* Ralf Brown recommends setting ES:DI to 0:0 */ ++ ax = 0x0800; ++ dx = devno; ++ di = 0; ++ asm("pushw %%es; " ++ "movw %%di,%%es; " ++ "pushfl; stc; int $0x13; setc %%al; popfl; " ++ "popw %%es" ++ : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di) ++ : : "esi"); ++ ++ if ((u8)ax == 0) { ++ ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2); ++ ei->legacy_max_head = dx >> 8; ++ ei->legacy_sectors_per_track = cx & 0x3f; ++ } ++ ++ return 0; ++} ++ ++void query_edd(void) ++{ ++ char eddarg[8]; ++ int do_mbr = 1; ++ int do_edd = 1; ++ int devno; ++ struct edd_info ei, *edp; ++ ++ if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) { ++ if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip")) ++ do_mbr = 0; ++ else if (!strcmp(eddarg, "off")) ++ do_edd = 0; ++ } ++ ++ edp = (struct edd_info *)boot_params.eddbuf; ++ ++ if (!do_edd) ++ return; ++ ++ for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) { ++ /* ++ * Scan the BIOS-supported hard disks and query EDD ++ * information... ++ */ ++ get_edd_info(devno, &ei); ++ ++ if (boot_params.eddbuf_entries < EDDMAXNR) { ++ memcpy(edp, &ei, sizeof ei); ++ edp++; ++ boot_params.eddbuf_entries++; ++ } ++ ++ if (do_mbr) { ++ u32 mbr_sig; ++ mbr_sig = read_mbr_sig(devno, &ei); ++ boot_params.edd_mbr_sig_buffer[devno-0x80] = mbr_sig; ++ } ++ } ++} ++ ++#endif +diff -puN /dev/null arch/i386/boot/header.S +--- /dev/null ++++ a/arch/i386/boot/header.S +@@ -0,0 +1,283 @@ ++/* ++ * header.S ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * ++ * Based on bootsect.S and setup.S ++ * modified by more people than can be counted ++ * ++ * Rewritten as a common file by H. Peter Anvin (Apr 2007) ++ * ++ * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment ++ * addresses must be multiplied by 16 to obtain their respective linear ++ * addresses. To avoid confusion, linear addresses are written using leading ++ * hex while segment addresses are written as segment:offset. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "boot.h" ++ ++SETUPSECTS = 4 /* default nr of setup-sectors */ ++BOOTSEG = 0x07C0 /* original address of boot-sector */ ++SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ ++SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ ++ /* to be loaded */ ++ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ ++SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ ++ ++#ifndef SVGA_MODE ++#define SVGA_MODE ASK_VGA ++#endif ++ ++#ifndef RAMDISK ++#define RAMDISK 0 ++#endif ++ ++#ifndef ROOT_RDONLY ++#define ROOT_RDONLY 1 ++#endif ++ ++ .code16 ++ .section ".bstext", "ax" ++ ++ .global bootsect_start ++bootsect_start: ++ ++ # Normalize the start address ++ ljmp $BOOTSEG, $start2 ++ ++start2: ++ movw %cs, %ax ++ movw %ax, %ds ++ movw %ax, %es ++ movw %ax, %ss ++ xorw %sp, %sp ++ sti ++ cld ++ ++ movw $bugger_off_msg, %si ++ ++msg_loop: ++ lodsb ++ andb %al, %al ++ jz bs_die ++ movb $0xe, %ah ++ movw $7, %bx ++ int $0x10 ++ jmp msg_loop ++ ++bs_die: ++ # Allow the user to press a key, then reboot ++ xorw %ax, %ax ++ int $0x16 ++ int $0x19 ++ ++ # int 0x19 should never return. In case it does anyway, ++ # invoke the BIOS reset code... ++ ljmp $0xf000,$0xfff0 ++ ++ .section ".bsdata", "a" ++bugger_off_msg: ++ .ascii "Direct booting from floppy is no longer supported.\r\n" ++ .ascii "Please use a boot loader program instead.\r\n" ++ .ascii "\n" ++ .ascii "Remove disk and press any key to reboot . . .\r\n" ++ .byte 0 ++ ++ ++ # Kernel attributes; used by setup. This is part 1 of the ++ # header, from the old boot sector. ++ ++ .section ".header", "a" ++ .globl hdr ++hdr: ++setup_sects: .byte SETUPSECTS ++root_flags: .word ROOT_RDONLY ++syssize: .long SYSSIZE ++ram_size: .word RAMDISK ++vid_mode: .word SVGA_MODE ++root_dev: .word ROOT_DEV ++boot_flag: .word 0xAA55 ++ ++ # offset 512, entry point ++ ++ .globl _start ++_start: ++ # Explicitly enter this as bytes, or the assembler ++ # tries to generate a 3-byte jump here, which causes ++ # everything else to push off to the wrong offset. ++ .byte 0xeb # short (2-byte) jump ++ .byte start_of_setup-1f ++1: ++ ++ # Part 2 of the header, from the old setup.S ++ ++ .ascii "HdrS" # header signature ++ .word 0x0206 # header version number (>= 0x0105) ++ # or else old loadlin-1.5 will fail) ++ .globl realmode_swtch ++realmode_swtch: .word 0, 0 # default_switch, SETUPSEG ++start_sys_seg: .word SYSSEG ++ .word kernel_version-512 # pointing to kernel version string ++ # above section of header is compatible ++ # with loadlin-1.5 (header v1.5). Don't ++ # change it. ++ ++type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, ++ # Bootlin, SYSLX, bootsect...) ++ # See Documentation/i386/boot.txt for ++ # assigned ids ++ ++# flags, unused bits must be zero (RFU) bit within loadflags ++loadflags: ++LOADED_HIGH = 1 # If set, the kernel is loaded high ++CAN_USE_HEAP = 0x80 # If set, the loader also has set ++ # heap_end_ptr to tell how much ++ # space behind setup.S can be used for ++ # heap purposes. ++ # Only the loader knows what is free ++#ifndef __BIG_KERNEL__ ++ .byte 0 ++#else ++ .byte LOADED_HIGH ++#endif ++ ++setup_move_size: .word 0x8000 # size to move, when setup is not ++ # loaded at 0x90000. We will move setup ++ # to 0x90000 then just before jumping ++ # into the kernel. However, only the ++ # loader knows how much data behind ++ # us also needs to be loaded. ++ ++code32_start: # here loaders can put a different ++ # start address for 32-bit code. ++#ifndef __BIG_KERNEL__ ++ .long 0x1000 # 0x1000 = default for zImage ++#else ++ .long 0x100000 # 0x100000 = default for big kernel ++#endif ++ ++ramdisk_image: .long 0 # address of loaded ramdisk image ++ # Here the loader puts the 32-bit ++ # address where it loaded the image. ++ # This only will be read by the kernel. ++ ++ramdisk_size: .long 0 # its size in bytes ++ ++bootsect_kludge: ++ .long 0 # obsolete ++ ++heap_end_ptr: .word _end+1024 # (Header version 0x0201 or later) ++ # space from here (exclusive) down to ++ # end of setup code can be used by setup ++ # for local heap purposes. ++ ++pad1: .word 0 ++cmd_line_ptr: .long 0 # (Header version 0x0202 or later) ++ # If nonzero, a 32-bit pointer ++ # to the kernel command line. ++ # The command line should be ++ # located between the start of ++ # setup and the end of low ++ # memory (0xa0000), or it may ++ # get overwritten before it ++ # gets read. If this field is ++ # used, there is no longer ++ # anything magical about the ++ # 0x90000 segment; the setup ++ # can be located anywhere in ++ # low memory 0x10000 or higher. ++ ++ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff ++ # (Header version 0x0203 or later) ++ # The highest safe address for ++ # the contents of an initrd ++ ++kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment ++ #required for protected mode ++ #kernel ++#ifdef CONFIG_RELOCATABLE ++relocatable_kernel: .byte 1 ++#else ++relocatable_kernel: .byte 0 ++#endif ++pad2: .byte 0 ++pad3: .word 0 ++ ++cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, ++ #added with boot protocol ++ #version 2.06 ++ ++# End of setup header ##################################################### ++ ++ .section ".inittext", "ax" ++start_of_setup: ++#ifdef SAFE_RESET_DISK_CONTROLLER ++# Reset the disk controller. ++ movw $0x0000, %ax # Reset disk controller ++ movb $0x80, %dl # All disks ++ int $0x13 ++#endif ++ ++# We will have entired with %cs = %ds+0x20, normalize %cs so ++# it is on par with the other segments. ++ pushw %ds ++ pushw $setup2 ++ lretw ++ ++setup2: ++# Force %es = %ds ++ movw %ds, %ax ++ movw %ax, %es ++ cld ++ ++# Stack paranoia: align the stack and make sure it is good ++# for both 16- and 32-bit references. In particular, if we ++# were meant to have been using the full 16-bit segment, the ++# caller might have set %sp to zero, which breaks %esp-based ++# references. ++ andw $~3, %sp # dword align (might as well...) ++ jnz 1f ++ movw $0xfffc, %sp # Make sure we're not zero ++1: movzwl %sp, %esp # Clear upper half of %esp ++ sti ++ ++# Check signature at end of setup ++ cmpl $0x5a5aaa55, setup_sig ++ jne setup_bad ++ ++# Zero the bss ++ movw $__bss_start, %di ++ movw $_end+3, %cx ++ xorl %eax, %eax ++ subw %di, %cx ++ shrw $2, %cx ++ rep; stosl ++ ++# Jump to C code (should not return) ++ calll main ++ ++# Setup corrupt somehow... ++setup_bad: ++ movl $setup_corrupt, %eax ++ calll puts ++ # Fall through... ++ ++ .globl die ++ .type die, @function ++die: ++ hlt ++ jmp die ++ ++ .size die, .-due ++ ++ .section ".initdata", "a" ++setup_corrupt: ++ .byte 7 ++ .string "No setup signature found..." +diff -puN /dev/null arch/i386/boot/main.c +--- /dev/null ++++ a/arch/i386/boot/main.c +@@ -0,0 +1,161 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/main.c ++ * ++ * Main module for the real-mode kernel code ++ */ ++ ++#include "boot.h" ++ ++struct boot_params boot_params __attribute__((aligned(16))); ++ ++char *HEAP = _end; ++char *heap_end = _end; /* Default end of heap = no heap */ ++ ++/* ++ * Copy the header into the boot parameter block. Since this ++ * screws up the old-style command line protocol, adjust by ++ * filling in the new-style command line pointer instead. ++ */ ++#define OLD_CL_MAGIC 0xA33F ++#define OLD_CL_ADDRESS 0x20 ++ ++static void copy_boot_params(void) ++{ ++ struct old_cmdline { ++ u16 cl_magic; ++ u16 cl_offset; ++ }; ++ const struct old_cmdline * const oldcmd = ++ (const struct old_cmdline *)OLD_CL_ADDRESS; ++ ++ BUILD_BUG_ON(sizeof boot_params != 4096); ++ memcpy(&boot_params.hdr, &hdr, sizeof hdr); ++ ++ if (!boot_params.hdr.cmd_line_ptr && ++ oldcmd->cl_magic == OLD_CL_MAGIC) { ++ /* Old-style command line protocol. */ ++ u16 cmdline_seg; ++ ++ /* Figure out if the command line falls in the region ++ of memory that an old kernel would have copied up ++ to 0x90000... */ ++ if (oldcmd->cl_offset < boot_params.hdr.setup_move_size) ++ cmdline_seg = ds(); ++ else ++ cmdline_seg = 0x9000; ++ ++ boot_params.hdr.cmd_line_ptr = ++ (cmdline_seg << 4) + oldcmd->cl_offset; ++ } ++} ++ ++/* ++ * Set the keyboard repeat rate to maximum. Unclear why this ++ * is done here; this might be possible to kill off as stale code. ++ */ ++static void keyboard_set_repeat(void) ++{ ++ u16 ax = 0x0305; ++ u16 bx = 0; ++ asm volatile("int $0x16" ++ : "+a" (ax), "+b" (bx) ++ : : "ecx", "edx", "esi", "edi"); ++} ++ ++/* ++ * Get Intel SpeedStep IST information. ++ */ ++static void query_speedstep_ist(void) ++{ ++ asm("int $0x15" ++ : "=a" (boot_params.speedstep_info[0]), ++ "=b" (boot_params.speedstep_info[1]), ++ "=c" (boot_params.speedstep_info[2]), ++ "=d" (boot_params.speedstep_info[3]) ++ : "a" (0x0000e980), /* IST Support */ ++ "d" (0x47534943)); /* Request value */ ++} ++ ++/* ++ * Tell the BIOS what CPU mode we intend to run in. ++ */ ++static void set_bios_mode(void) ++{ ++#ifdef CONFIG_X86_64 ++ u32 eax, ebx; ++ ++ eax = 0xec00; ++ ebx = 2; ++ asm volatile("int $0x15" ++ : "+a" (eax), "+b" (ebx) ++ : : "ecx", "edx", "esi", "edi"); ++#endif ++} ++ ++void main(void) ++{ ++ /* First, copy the boot header into the "zeropage" */ ++ copy_boot_params(); ++ ++ /* End of heap check */ ++ if (boot_params.hdr.loadflags & CAN_USE_HEAP) { ++ heap_end = (char *)(boot_params.hdr.heap_end_ptr ++ +0x200-STACK_SIZE); ++ } else { ++ /* Boot protocol 2.00 only, no heap available */ ++ puts("WARNING: Ancient bootloader, some functionality " ++ "may be limited!\n"); ++ } ++ ++ /* Make sure we have all the proper CPU support */ ++ if (validate_cpu()) { ++ puts("Unable to boot - please use a kernel appropriate " ++ "for your CPU.\n"); ++ die(); ++ } ++ ++ /* Tell the BIOS what CPU mode we intend to run in. */ ++ set_bios_mode(); ++ ++ /* Detect memory layout */ ++ detect_memory(); ++ ++ /* Set keyboard repeat rate (why?) */ ++ keyboard_set_repeat(); ++ ++ /* Set the video mode */ ++ set_video(); ++ ++ /* Query MCA information */ ++ query_mca(); ++ ++ /* Voyager */ ++#ifdef CONFIG_X86_VOYAGER ++ query_voyager(); ++#endif ++ ++ /* Query SpeedStep IST information */ ++ query_speedstep_ist(); ++ ++ /* Query APM information */ ++#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) ++ query_apm_bios(); ++#endif ++ ++ /* Query EDD information */ ++#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) ++ query_edd(); ++#endif ++ /* Do the last things and invoke protected mode */ ++ go_to_protected_mode(); ++} +diff -puN /dev/null arch/i386/boot/mca.c +--- /dev/null ++++ a/arch/i386/boot/mca.c +@@ -0,0 +1,43 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/mca.c ++ * ++ * Get the MCA system description table ++ */ ++ ++#include "boot.h" ++ ++int query_mca(void) ++{ ++ u8 err; ++ u16 es, bx, len; ++ ++ asm("pushw %%es ; " ++ "int $0x15 ; " ++ "setc %0 ; " ++ "movw %%es, %1 ; " ++ "popw %%es" ++ : "=acdSDm" (err), "=acdSDm" (es), "=b" (bx) ++ : "a" (0xc000)); ++ ++ if (err) ++ return -1; /* No MCA present */ ++ ++ set_fs(es); ++ len = rdfs16(bx); ++ ++ if (len > sizeof(boot_params.sys_desc_table)) ++ len = sizeof(boot_params.sys_desc_table); ++ ++ copy_from_fs(&boot_params.sys_desc_table, bx, len); ++ return 0; ++} +diff -puN /dev/null arch/i386/boot/memory.c +--- /dev/null ++++ a/arch/i386/boot/memory.c +@@ -0,0 +1,99 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/memory.c ++ * ++ * Memory detection code ++ */ ++ ++#include "boot.h" ++ ++#define SMAP 0x534d4150 /* ASCII "SMAP" */ ++ ++static int detect_memory_e820(void) ++{ ++ u32 next = 0; ++ u32 size, id; ++ u8 err; ++ struct e820entry *desc = boot_params.e820_map; ++ ++ do { ++ size = sizeof(struct e820entry); ++ id = SMAP; ++ asm("int $0x15; setc %0" ++ : "=am" (err), "+b" (next), "+d" (id), "+c" (size), ++ "=m" (*desc) ++ : "D" (desc), "a" (0xe820)); ++ ++ if (err || id != SMAP) ++ break; ++ ++ boot_params.e820_entries++; ++ desc++; ++ } while (next && boot_params.e820_entries < E820MAX); ++ ++ return boot_params.e820_entries; ++} ++ ++static int detect_memory_e801(void) ++{ ++ u16 ax, bx, cx, dx; ++ u8 err; ++ ++ bx = cx = dx = 0; ++ ax = 0xe801; ++ asm("stc; int $0x15; setc %0" ++ : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx)); ++ ++ if (err) ++ return -1; ++ ++ /* Do we really need to do this? */ ++ if (cx || dx) { ++ ax = cx; ++ bx = dx; ++ } ++ ++ if (ax > 15*1024) ++ return -1; /* Bogus! */ ++ ++ /* This ignores memory above 16MB if we have a memory hole ++ there. If someone actually finds a machine with a memory ++ hole at 16MB and no support for 0E820h they should probably ++ generate a fake e820 map. */ ++ boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax; ++ ++ return 0; ++} ++ ++static int detect_memory_88(void) ++{ ++ u16 ax; ++ u8 err; ++ ++ ax = 0x8800; ++ asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax)); ++ ++ boot_params.screen_info.ext_mem_k = ax; ++ ++ return -err; ++} ++ ++int detect_memory(void) ++{ ++ if (detect_memory_e820() > 0) ++ return 0; ++ ++ if (!detect_memory_e801()) ++ return 0; ++ ++ return detect_memory_88(); ++} +diff -puN /dev/null arch/i386/boot/pm.c +--- /dev/null ++++ a/arch/i386/boot/pm.c +@@ -0,0 +1,170 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/pm.c ++ * ++ * Prepare the machine for transition to protected mode. ++ */ ++ ++#include "boot.h" ++#include ++ ++/* ++ * Invoke the realmode switch hook if present; otherwise ++ * disable all interrupts. ++ */ ++static void realmode_switch_hook(void) ++{ ++ if (boot_params.hdr.realmode_swtch) { ++ asm volatile("lcallw *%0" ++ : : "m" (boot_params.hdr.realmode_swtch) ++ : "eax", "ebx", "ecx", "edx"); ++ } else { ++ asm volatile("cli"); ++ outb(0x80, 0x70); /* Disable NMI */ ++ io_delay(); ++ } ++} ++ ++/* ++ * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000. ++ * A bzImage kernel is loaded and runs at 0x100000. ++ */ ++static void move_kernel_around(void) ++{ ++ /* Note: rely on the compile-time option here rather than ++ the LOADED_HIGH flag. The Qemu kernel loader unconditionally ++ sets the loadflags to zero. */ ++#ifndef __BIG_KERNEL__ ++ u16 dst_seg, src_seg; ++ u32 syssize; ++ ++ dst_seg = 0x1000 >> 4; ++ src_seg = 0x10000 >> 4; ++ syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraps */ ++ ++ while (syssize) { ++ int paras = (syssize >= 0x1000) ? 0x1000 : syssize; ++ int dwords = paras << 2; ++ ++ asm volatile("pushw %%es ; " ++ "pushw %%ds ; " ++ "movw %1,%%es ; " ++ "movw %2,%%ds ; " ++ "xorw %%di,%%di ; " ++ "xorw %%si,%%si ; " ++ "rep;movsl ; " ++ "popw %%ds ; " ++ "popw %%es" ++ : "+c" (dwords) ++ : "rm" (dst_seg), "rm" (src_seg) ++ : "esi", "edi"); ++ ++ syssize -= paras; ++ dst_seg += paras; ++ src_seg += paras; ++ } ++#endif ++} ++ ++/* ++ * Disable all interrupts at the legacy PIC. ++ */ ++static void mask_all_interrupts(void) ++{ ++ outb(0xff, 0xa1); /* Mask all interrupts on the seconday PIC */ ++ io_delay(); ++ outb(0xfb, 0x21); /* Mask all but cascade on the primary PIC */ ++ io_delay(); ++} ++ ++/* ++ * Reset IGNNE# if asserted in the FPU. ++ */ ++static void reset_coprocessor(void) ++{ ++ outb(0, 0xf0); ++ io_delay(); ++ outb(0, 0xf1); ++ io_delay(); ++} ++ ++/* ++ * Set up the GDT ++ */ ++#define GDT_ENTRY(flags,base,limit) \ ++ (((u64)(base & 0xff000000) << 32) | \ ++ ((u64)flags << 40) | \ ++ ((u64)(limit & 0x00ff0000) << 32) | \ ++ ((u64)(base & 0x00ffff00) << 16) | \ ++ ((u64)(limit & 0x0000ffff))) ++ ++struct gdt_ptr { ++ u16 len; ++ u32 ptr; ++} __attribute__((packed)); ++ ++static void setup_gdt(void) ++{ ++ /* There are machines which are known to not boot with the GDT ++ being 8-byte unaligned. Intel recommends 16 byte alignment. */ ++ static const u64 boot_gdt[] __attribute__((aligned(16))) = { ++ /* CS: code, read/execute, 4 GB, base 0 */ ++ [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff), ++ /* DS: data, read/write, 4 GB, base 0 */ ++ [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff), ++ }; ++ struct gdt_ptr gdt; ++ ++ gdt.len = sizeof(boot_gdt)-1; ++ gdt.ptr = (u32)&boot_gdt + (ds() << 4); ++ ++ asm volatile("lgdtl %0" : : "m" (gdt)); ++} ++ ++/* ++ * Set up the IDT ++ */ ++static void setup_idt(void) ++{ ++ static const struct gdt_ptr null_idt = {0, 0}; ++ asm volatile("lidtl %0" : : "m" (null_idt)); ++} ++ ++/* ++ * Actual invocation sequence ++ */ ++void go_to_protected_mode(void) ++{ ++ /* Hook before leaving real mode, also disables interrupts */ ++ realmode_switch_hook(); ++ ++ /* Move the kernel/setup to their final resting places */ ++ move_kernel_around(); ++ ++ /* Enable the A20 gate */ ++ if (enable_a20()) { ++ puts("A20 gate not responding, unable to boot...\n"); ++ die(); ++ } ++ ++ /* Reset coprocessor (IGNNE#) */ ++ reset_coprocessor(); ++ ++ /* Mask all interrupts in the PIC */ ++ mask_all_interrupts(); ++ ++ /* Actual transition to protected mode... */ ++ setup_idt(); ++ setup_gdt(); ++ protected_mode_jump(boot_params.hdr.code32_start, ++ (u32)&boot_params + (ds() << 4)); ++} +diff -puN /dev/null arch/i386/boot/pmjump.S +--- /dev/null ++++ a/arch/i386/boot/pmjump.S +@@ -0,0 +1,54 @@ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/pmjump.S ++ * ++ * The actual transition into protected mode ++ */ ++ ++#include ++#include ++ ++ .text ++ ++ .globl protected_mode_jump ++ .type protected_mode_jump, @function ++ ++ .code16 ++ ++/* ++ * void protected_mode_jump(u32 entrypoint, u32 bootparams); ++ */ ++protected_mode_jump: ++ xorl %ebx, %ebx # Flag to indicate this is a boot ++ movl %edx, %esi # Pointer to boot_params table ++ movl %eax, 2f # Patch ljmpl instruction ++ jmp 1f # Short jump to flush instruction q. ++ ++1: ++ movw $__BOOT_DS, %cx ++ ++ movl %cr0, %edx ++ orb $1, %dl # Protected mode (PE) bit ++ movl %edx, %cr0 ++ ++ movw %cx, %ds ++ movw %cx, %es ++ movw %cx, %fs ++ movw %cx, %gs ++ movw %cx, %ss ++ ++ # Jump to the 32-bit entrypoint ++ .byte 0x66, 0xea # ljmpl opcode ++2: .long 0 # offset ++ .word __BOOT_CS # segment ++ ++ .size protected_mode_jump, .-protected_mode_jump +diff -puN /dev/null arch/i386/boot/printf.c +--- /dev/null ++++ a/arch/i386/boot/printf.c +@@ -0,0 +1,331 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/printf.c ++ * ++ * Oh, it's a waste of space, but oh-so-yummy for debugging. This ++ * version of printf() does not include 64-bit support. "Live with ++ * it." ++ * ++ */ ++ ++#include "boot.h" ++ ++static inline int isdigit(int ch) ++{ ++ return (ch >= '0') && (ch <= '9'); ++} ++ ++static int skip_atoi(const char **s) ++{ ++ int i = 0; ++ ++ while (isdigit(**s)) ++ i = i * 10 + *((*s)++) - '0'; ++ return i; ++} ++ ++unsigned int atou(const char *s) ++{ ++ unsigned int i = 0; ++ while (isdigit(*s)) ++ i = i * 10 + (*s++ - '0'); ++ return i; ++} ++ ++static int strnlen(const char *s, int maxlen) ++{ ++ const char *es = s; ++ while (*es && maxlen) { ++ es++; ++ maxlen--; ++ } ++ ++ return (es - s); ++} ++ ++#define ZEROPAD 1 /* pad with zero */ ++#define SIGN 2 /* unsigned/signed long */ ++#define PLUS 4 /* show plus */ ++#define SPACE 8 /* space if plus */ ++#define LEFT 16 /* left justified */ ++#define SPECIAL 32 /* 0x */ ++#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ ++ ++#define do_div(n,base) ({ \ ++int __res; \ ++__res = ((unsigned long) n) % (unsigned) base; \ ++n = ((unsigned long) n) / (unsigned) base; \ ++__res; }) ++ ++static char *number(char *str, long num, int base, int size, int precision, ++ int type) ++{ ++ char c, sign, tmp[66]; ++ const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; ++ int i; ++ ++ if (type & LARGE) ++ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; ++ if (type & LEFT) ++ type &= ~ZEROPAD; ++ if (base < 2 || base > 36) ++ return 0; ++ c = (type & ZEROPAD) ? '0' : ' '; ++ sign = 0; ++ if (type & SIGN) { ++ if (num < 0) { ++ sign = '-'; ++ num = -num; ++ size--; ++ } else if (type & PLUS) { ++ sign = '+'; ++ size--; ++ } else if (type & SPACE) { ++ sign = ' '; ++ size--; ++ } ++ } ++ if (type & SPECIAL) { ++ if (base == 16) ++ size -= 2; ++ else if (base == 8) ++ size--; ++ } ++ i = 0; ++ if (num == 0) ++ tmp[i++] = '0'; ++ else ++ while (num != 0) ++ tmp[i++] = digits[do_div(num, base)]; ++ if (i > precision) ++ precision = i; ++ size -= precision; ++ if (!(type & (ZEROPAD + LEFT))) ++ while (size-- > 0) ++ *str++ = ' '; ++ if (sign) ++ *str++ = sign; ++ if (type & SPECIAL) { ++ if (base == 8) ++ *str++ = '0'; ++ else if (base == 16) { ++ *str++ = '0'; ++ *str++ = digits[33]; ++ } ++ } ++ if (!(type & LEFT)) ++ while (size-- > 0) ++ *str++ = c; ++ while (i < precision--) ++ *str++ = '0'; ++ while (i-- > 0) ++ *str++ = tmp[i]; ++ while (size-- > 0) ++ *str++ = ' '; ++ return str; ++} ++ ++int vsprintf(char *buf, const char *fmt, va_list args) ++{ ++ int len; ++ unsigned long num; ++ int i, base; ++ char *str; ++ const char *s; ++ ++ int flags; /* flags to number() */ ++ ++ int field_width; /* width of output field */ ++ int precision; /* min. # of digits for integers; max ++ number of chars for from string */ ++ int qualifier; /* 'h', 'l', or 'L' for integer fields */ ++ ++ for (str = buf; *fmt; ++fmt) { ++ if (*fmt != '%') { ++ *str++ = *fmt; ++ continue; ++ } ++ ++ /* process flags */ ++ flags = 0; ++ repeat: ++ ++fmt; /* this also skips first '%' */ ++ switch (*fmt) { ++ case '-': ++ flags |= LEFT; ++ goto repeat; ++ case '+': ++ flags |= PLUS; ++ goto repeat; ++ case ' ': ++ flags |= SPACE; ++ goto repeat; ++ case '#': ++ flags |= SPECIAL; ++ goto repeat; ++ case '0': ++ flags |= ZEROPAD; ++ goto repeat; ++ } ++ ++ /* get field width */ ++ field_width = -1; ++ if (isdigit(*fmt)) ++ field_width = skip_atoi(&fmt); ++ else if (*fmt == '*') { ++ ++fmt; ++ /* it's the next argument */ ++ field_width = va_arg(args, int); ++ if (field_width < 0) { ++ field_width = -field_width; ++ flags |= LEFT; ++ } ++ } ++ ++ /* get the precision */ ++ precision = -1; ++ if (*fmt == '.') { ++ ++fmt; ++ if (isdigit(*fmt)) ++ precision = skip_atoi(&fmt); ++ else if (*fmt == '*') { ++ ++fmt; ++ /* it's the next argument */ ++ precision = va_arg(args, int); ++ } ++ if (precision < 0) ++ precision = 0; ++ } ++ ++ /* get the conversion qualifier */ ++ qualifier = -1; ++ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { ++ qualifier = *fmt; ++ ++fmt; ++ } ++ ++ /* default base */ ++ base = 10; ++ ++ switch (*fmt) { ++ case 'c': ++ if (!(flags & LEFT)) ++ while (--field_width > 0) ++ *str++ = ' '; ++ *str++ = (unsigned char)va_arg(args, int); ++ while (--field_width > 0) ++ *str++ = ' '; ++ continue; ++ ++ case 's': ++ s = va_arg(args, char *); ++ len = strnlen(s, precision); ++ ++ if (!(flags & LEFT)) ++ while (len < field_width--) ++ *str++ = ' '; ++ for (i = 0; i < len; ++i) ++ *str++ = *s++; ++ while (len < field_width--) ++ *str++ = ' '; ++ continue; ++ ++ case 'p': ++ if (field_width == -1) { ++ field_width = 2 * sizeof(void *); ++ flags |= ZEROPAD; ++ } ++ str = number(str, ++ (unsigned long)va_arg(args, void *), 16, ++ field_width, precision, flags); ++ continue; ++ ++ case 'n': ++ if (qualifier == 'l') { ++ long *ip = va_arg(args, long *); ++ *ip = (str - buf); ++ } else { ++ int *ip = va_arg(args, int *); ++ *ip = (str - buf); ++ } ++ continue; ++ ++ case '%': ++ *str++ = '%'; ++ continue; ++ ++ /* integer number formats - set up the flags and "break" */ ++ case 'o': ++ base = 8; ++ break; ++ ++ case 'X': ++ flags |= LARGE; ++ case 'x': ++ base = 16; ++ break; ++ ++ case 'd': ++ case 'i': ++ flags |= SIGN; ++ case 'u': ++ break; ++ ++ default: ++ *str++ = '%'; ++ if (*fmt) ++ *str++ = *fmt; ++ else ++ --fmt; ++ continue; ++ } ++ if (qualifier == 'l') ++ num = va_arg(args, unsigned long); ++ else if (qualifier == 'h') { ++ num = (unsigned short)va_arg(args, int); ++ if (flags & SIGN) ++ num = (short)num; ++ } else if (flags & SIGN) ++ num = va_arg(args, int); ++ else ++ num = va_arg(args, unsigned int); ++ str = number(str, num, base, field_width, precision, flags); ++ } ++ *str = '\0'; ++ return str - buf; ++} ++ ++int sprintf(char *buf, const char *fmt, ...) ++{ ++ va_list args; ++ int i; ++ ++ va_start(args, fmt); ++ i = vsprintf(buf, fmt, args); ++ va_end(args); ++ return i; ++} ++ ++int printf(const char *fmt, ...) ++{ ++ char printf_buf[1024]; ++ va_list args; ++ int printed; ++ ++ va_start(args, fmt); ++ printed = vsprintf(printf_buf, fmt, args); ++ va_end(args); ++ ++ puts(printf_buf); ++ ++ return printed; ++} +diff -puN arch/i386/boot/setup.S~git-newsetup /dev/null +--- a/arch/i386/boot/setup.S ++++ /dev/null +@@ -1,1075 +0,0 @@ +-/* +- * setup.S Copyright (C) 1991, 1992 Linus Torvalds +- * +- * setup.s is responsible for getting the system data from the BIOS, +- * and putting them into the appropriate places in system memory. +- * both setup.s and system has been loaded by the bootblock. +- * +- * This code asks the bios for memory/disk/other parameters, and +- * puts them in a "safe" place: 0x90000-0x901FF, ie where the +- * boot-block used to be. It is then up to the protected mode +- * system to read them from there before the area is overwritten +- * for buffer-blocks. +- * +- * Move PS/2 aux init code to psaux.c +- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 +- * +- * some changes and additional features by Christoph Niemann, +- * March 1993/June 1994 (Christoph.Niemann@linux.org) +- * +- * add APM BIOS checking by Stephen Rothwell, May 1994 +- * (sfr@canb.auug.org.au) +- * +- * High load stuff, initrd support and position independency +- * by Hans Lermen & Werner Almesberger, February 1996 +- * , +- * +- * Video handling moved to video.S by Martin Mares, March 1996 +- * +- * +- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david +- * parsons) to avoid loadlin confusion, July 1997 +- * +- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. +- * +- * +- * Fix to work around buggy BIOSes which don't use carry bit correctly +- * and/or report extended memory in CX/DX for e801h memory size detection +- * call. As a result the kernel got wrong figures. The int15/e801h docs +- * from Ralf Brown interrupt list seem to indicate AX/BX should be used +- * anyway. So to avoid breaking many machines (presumably there was a reason +- * to orginally use CX/DX instead of AX/BX), we do a kludge to see +- * if CX/DX have been changed in the e801 call and if so use AX/BX . +- * Michael Miller, April 2001 +- * +- * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes +- * by Robert Schwebel, December 2001 +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* Signature words to ensure LILO loaded us right */ +-#define SIG1 0xAA55 +-#define SIG2 0x5A5A +- +-INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way +-SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). +-SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment +- # ... and the former contents of CS +- +-DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 +- +-.code16 +-.globl begtext, begdata, begbss, endtext, enddata, endbss +- +-.text +-begtext: +-.data +-begdata: +-.bss +-begbss: +-.text +- +-start: +- jmp trampoline +- +-# This is the setup header, and it must start at %cs:2 (old 0x9020:2) +- +- .ascii "HdrS" # header signature +- .word 0x0206 # header version number (>= 0x0105) +- # or else old loadlin-1.5 will fail) +-realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +-start_sys_seg: .word SYSSEG +- .word kernel_version # pointing to kernel version string +- # above section of header is compatible +- # with loadlin-1.5 (header v1.5). Don't +- # change it. +- +-type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, +- # Bootlin, SYSLX, bootsect...) +- # See Documentation/i386/boot.txt for +- # assigned ids +- +-# flags, unused bits must be zero (RFU) bit within loadflags +-loadflags: +-LOADED_HIGH = 1 # If set, the kernel is loaded high +-CAN_USE_HEAP = 0x80 # If set, the loader also has set +- # heap_end_ptr to tell how much +- # space behind setup.S can be used for +- # heap purposes. +- # Only the loader knows what is free +-#ifndef __BIG_KERNEL__ +- .byte 0 +-#else +- .byte LOADED_HIGH +-#endif +- +-setup_move_size: .word 0x8000 # size to move, when setup is not +- # loaded at 0x90000. We will move setup +- # to 0x90000 then just before jumping +- # into the kernel. However, only the +- # loader knows how much data behind +- # us also needs to be loaded. +- +-code32_start: # here loaders can put a different +- # start address for 32-bit code. +-#ifndef __BIG_KERNEL__ +- .long 0x1000 # 0x1000 = default for zImage +-#else +- .long 0x100000 # 0x100000 = default for big kernel +-#endif +- +-ramdisk_image: .long 0 # address of loaded ramdisk image +- # Here the loader puts the 32-bit +- # address where it loaded the image. +- # This only will be read by the kernel. +- +-ramdisk_size: .long 0 # its size in bytes +- +-bootsect_kludge: +- .long 0 # obsolete +- +-heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) +- # space from here (exclusive) down to +- # end of setup code can be used by setup +- # for local heap purposes. +- +-pad1: .word 0 +-cmd_line_ptr: .long 0 # (Header version 0x0202 or later) +- # If nonzero, a 32-bit pointer +- # to the kernel command line. +- # The command line should be +- # located between the start of +- # setup and the end of low +- # memory (0xa0000), or it may +- # get overwritten before it +- # gets read. If this field is +- # used, there is no longer +- # anything magical about the +- # 0x90000 segment; the setup +- # can be located anywhere in +- # low memory 0x10000 or higher. +- +-ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff +- # (Header version 0x0203 or later) +- # The highest safe address for +- # the contents of an initrd +- +-kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment +- #required for protected mode +- #kernel +-#ifdef CONFIG_RELOCATABLE +-relocatable_kernel: .byte 1 +-#else +-relocatable_kernel: .byte 0 +-#endif +-pad2: .byte 0 +-pad3: .word 0 +- +-cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, +- #added with boot protocol +- #version 2.06 +- +-trampoline: call start_of_setup +- .align 16 +- # The offset at this point is 0x240 +- .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) +-# End of setup header ##################################################### +- +-start_of_setup: +-# Bootlin depends on this being done early +- movw $0x01500, %ax +- movb $0x81, %dl +- int $0x13 +- +-#ifdef SAFE_RESET_DISK_CONTROLLER +-# Reset the disk controller. +- movw $0x0000, %ax +- movb $0x80, %dl +- int $0x13 +-#endif +- +-# Set %ds = %cs, we know that SETUPSEG = %cs at this point +- movw %cs, %ax # aka SETUPSEG +- movw %ax, %ds +-# Check signature at end of setup +- cmpw $SIG1, setup_sig1 +- jne bad_sig +- +- cmpw $SIG2, setup_sig2 +- jne bad_sig +- +- jmp good_sig1 +- +-# Routine to print asciiz string at ds:si +-prtstr: +- lodsb +- andb %al, %al +- jz fin +- +- call prtchr +- jmp prtstr +- +-fin: ret +- +-# Space printing +-prtsp2: call prtspc # Print double space +-prtspc: movb $0x20, %al # Print single space (note: fall-thru) +- +-# Part of above routine, this one just prints ascii al +-prtchr: pushw %ax +- pushw %cx +- movw $7,%bx +- movw $0x01, %cx +- movb $0x0e, %ah +- int $0x10 +- popw %cx +- popw %ax +- ret +- +-beep: movb $0x07, %al +- jmp prtchr +- +-no_sig_mess: .string "No setup signature found ..." +- +-good_sig1: +- jmp good_sig +- +-# We now have to find the rest of the setup code/data +-bad_sig: +- movw %cs, %ax # SETUPSEG +- subw $DELTA_INITSEG, %ax # INITSEG +- movw %ax, %ds +- xorb %bh, %bh +- movb (497), %bl # get setup sect from bootsect +- subw $4, %bx # LILO loads 4 sectors of setup +- shlw $8, %bx # convert to words (1sect=2^8 words) +- movw %bx, %cx +- shrw $3, %bx # convert to segment +- addw $SYSSEG, %bx +- movw %bx, %cs:start_sys_seg +-# Move rest of setup code/data to here +- movw $2048, %di # four sectors loaded by LILO +- subw %si, %si +- pushw %cs +- popw %es +- movw $SYSSEG, %ax +- movw %ax, %ds +- rep +- movsw +- movw %cs, %ax # aka SETUPSEG +- movw %ax, %ds +- cmpw $SIG1, setup_sig1 +- jne no_sig +- +- cmpw $SIG2, setup_sig2 +- jne no_sig +- +- jmp good_sig +- +-no_sig: +- lea no_sig_mess, %si +- call prtstr +- +-no_sig_loop: +- hlt +- jmp no_sig_loop +- +-good_sig: +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %ds +-# Check if an old loader tries to load a big-kernel +- testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? +- jz loader_ok # No, no danger for old loaders. +- +- cmpb $0, %cs:type_of_loader # Do we have a loader that +- # can deal with us? +- jnz loader_ok # Yes, continue. +- +- pushw %cs # No, we have an old loader, +- popw %ds # die. +- lea loader_panic_mess, %si +- call prtstr +- +- jmp no_sig_loop +- +-loader_panic_mess: .string "Wrong loader, giving up..." +- +-# check minimum cpuid +-# we do this here because it is the last place we can actually +-# show a user visible error message. Later the video modus +-# might be already messed up. +-loader_ok: +- call verify_cpu +- testl %eax,%eax +- jz cpu_ok +- movw %cs,%ax # aka SETUPSEG +- movw %ax,%ds +- lea cpu_panic_mess,%si +- call prtstr +-1: jmp 1b +- +-cpu_panic_mess: +- .asciz "PANIC: CPU too old for this kernel." +- +-#include "../kernel/verify_cpu.S" +- +-cpu_ok: +-# Get memory size (extended mem, kB) +- +- xorl %eax, %eax +- movl %eax, (0x1e0) +-#ifndef STANDARD_MEMORY_BIOS_CALL +- movb %al, (E820NR) +-# Try three different memory detection schemes. First, try +-# e820h, which lets us assemble a memory map, then try e801h, +-# which returns a 32-bit memory size, and finally 88h, which +-# returns 0-64m +- +-# method E820H: +-# the memory map from hell. e820h returns memory classified into +-# a whole bunch of different types, and allows memory holes and +-# everything. We scan through this memory map and build a list +-# of the first 32 memory areas, which we return at [E820MAP]. +-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. +- +-#define SMAP 0x534d4150 +- +-meme820: +- xorl %ebx, %ebx # continuation counter +- movw $E820MAP, %di # point into the whitelist +- # so we can have the bios +- # directly write into it. +- +-jmpe820: +- movl $0x0000e820, %eax # e820, upper word zeroed +- movl $SMAP, %edx # ascii 'SMAP' +- movl $20, %ecx # size of the e820rec +- pushw %ds # data record. +- popw %es +- int $0x15 # make the call +- jc bail820 # fall to e801 if it fails +- +- cmpl $SMAP, %eax # check the return is `SMAP' +- jne bail820 # fall to e801 if it fails +- +-# cmpl $1, 16(%di) # is this usable memory? +-# jne again820 +- +- # If this is usable memory, we save it by simply advancing %di by +- # sizeof(e820rec). +- # +-good820: +- movb (E820NR), %al # up to 128 entries +- cmpb $E820MAX, %al +- jae bail820 +- +- incb (E820NR) +- movw %di, %ax +- addw $20, %ax +- movw %ax, %di +-again820: +- cmpl $0, %ebx # check to see if +- jne jmpe820 # %ebx is set to EOF +-bail820: +- +- +-# method E801H: +-# memory size is in 1k chunksizes, to avoid confusing loadlin. +-# we store the 0xe801 memory size in a completely different place, +-# because it will most likely be longer than 16 bits. +-# (use 1e0 because that's what Larry Augustine uses in his +-# alternative new memory detection scheme, and it's sensible +-# to write everything into the same place.) +- +-meme801: +- stc # fix to work around buggy +- xorw %cx,%cx # BIOSes which don't clear/set +- xorw %dx,%dx # carry on pass/error of +- # e801h memory size call +- # or merely pass cx,dx though +- # without changing them. +- movw $0xe801, %ax +- int $0x15 +- jc mem88 +- +- cmpw $0x0, %cx # Kludge to handle BIOSes +- jne e801usecxdx # which report their extended +- cmpw $0x0, %dx # memory in AX/BX rather than +- jne e801usecxdx # CX/DX. The spec I have read +- movw %ax, %cx # seems to indicate AX/BX +- movw %bx, %dx # are more reasonable anyway... +- +-e801usecxdx: +- andl $0xffff, %edx # clear sign extend +- shll $6, %edx # and go from 64k to 1k chunks +- movl %edx, (0x1e0) # store extended memory size +- andl $0xffff, %ecx # clear sign extend +- addl %ecx, (0x1e0) # and add lower memory into +- # total size. +- +-# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +-# 64mb, depending on the bios) in ax. +-mem88: +- +-#endif +- movb $0x88, %ah +- int $0x15 +- movw %ax, (2) +- +-# Set the keyboard repeat rate to the max +- movw $0x0305, %ax +- xorw %bx, %bx +- int $0x16 +- +-# Check for video adapter and its parameters and allow the +-# user to browse video modes. +- call video # NOTE: we need %ds pointing +- # to bootsector +- +-# Get hd0 data... +- xorw %ax, %ax +- movw %ax, %ds +- ldsw (4 * 0x41), %si +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- pushw %ax +- movw %ax, %es +- movw $0x0080, %di +- movw $0x10, %cx +- pushw %cx +- cld +- rep +- movsb +-# Get hd1 data... +- xorw %ax, %ax +- movw %ax, %ds +- ldsw (4 * 0x46), %si +- popw %cx +- popw %es +- movw $0x0090, %di +- rep +- movsb +-# Check that there IS a hd1 :-) +- movw $0x01500, %ax +- movb $0x81, %dl +- int $0x13 +- jc no_disk1 +- +- cmpb $3, %ah +- je is_disk1 +- +-no_disk1: +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %es +- movw $0x0090, %di +- movw $0x10, %cx +- xorw %ax, %ax +- cld +- rep +- stosb +-is_disk1: +-# check for Micro Channel (MCA) bus +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %ds +- xorw %ax, %ax +- movw %ax, (0xa0) # set table length to 0 +- movb $0xc0, %ah +- stc +- int $0x15 # moves feature table to es:bx +- jc no_mca +- +- pushw %ds +- movw %es, %ax +- movw %ax, %ds +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %es +- movw %bx, %si +- movw $0xa0, %di +- movw (%si), %cx +- addw $2, %cx # table length is a short +- cmpw $0x10, %cx +- jc sysdesc_ok +- +- movw $0x10, %cx # we keep only first 16 bytes +-sysdesc_ok: +- rep +- movsb +- popw %ds +-no_mca: +-#ifdef CONFIG_X86_VOYAGER +- movb $0xff, 0x40 # flag on config found +- movb $0xc0, %al +- mov $0xff, %ah +- int $0x15 # put voyager config info at es:di +- jc no_voyager +- movw $0x40, %si # place voyager info in apm table +- cld +- movw $7, %cx +-voyager_rep: +- movb %es:(%di), %al +- movb %al,(%si) +- incw %di +- incw %si +- decw %cx +- jnz voyager_rep +-no_voyager: +-#endif +-# Check for PS/2 pointing device +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %ds +- movb $0, (0x1ff) # default is no pointing device +- int $0x11 # int 0x11: equipment list +- testb $0x04, %al # check if mouse installed +- jz no_psmouse +- +- movb $0xAA, (0x1ff) # device present +-no_psmouse: +- +-#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) +- movl $0x0000E980, %eax # IST Support +- movl $0x47534943, %edx # Request value +- int $0x15 +- +- movl %eax, (96) +- movl %ebx, (100) +- movl %ecx, (104) +- movl %edx, (108) +-#endif +- +-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) +-# Then check for an APM BIOS... +- # %ds points to the bootsector +- movw $0, 0x40 # version = 0 means no APM BIOS +- movw $0x05300, %ax # APM BIOS installation check +- xorw %bx, %bx +- int $0x15 +- jc done_apm_bios # Nope, no APM BIOS +- +- cmpw $0x0504d, %bx # Check for "PM" signature +- jne done_apm_bios # No signature, no APM BIOS +- +- andw $0x02, %cx # Is 32 bit supported? +- je done_apm_bios # No 32-bit, no (good) APM BIOS +- +- movw $0x05304, %ax # Disconnect first just in case +- xorw %bx, %bx +- int $0x15 # ignore return code +- movw $0x05303, %ax # 32 bit connect +- xorl %ebx, %ebx +- xorw %cx, %cx # paranoia :-) +- xorw %dx, %dx # ... +- xorl %esi, %esi # ... +- xorw %di, %di # ... +- int $0x15 +- jc no_32_apm_bios # Ack, error. +- +- movw %ax, (66) # BIOS code segment +- movl %ebx, (68) # BIOS entry point offset +- movw %cx, (72) # BIOS 16 bit code segment +- movw %dx, (74) # BIOS data segment +- movl %esi, (78) # BIOS code segment lengths +- movw %di, (82) # BIOS data segment length +-# Redo the installation check as the 32 bit connect +-# modifies the flags returned on some BIOSs +- movw $0x05300, %ax # APM BIOS installation check +- xorw %bx, %bx +- xorw %cx, %cx # paranoia +- int $0x15 +- jc apm_disconnect # error -> shouldn't happen +- +- cmpw $0x0504d, %bx # check for "PM" signature +- jne apm_disconnect # no sig -> shouldn't happen +- +- movw %ax, (64) # record the APM BIOS version +- movw %cx, (76) # and flags +- jmp done_apm_bios +- +-apm_disconnect: # Tidy up +- movw $0x05304, %ax # Disconnect +- xorw %bx, %bx +- int $0x15 # ignore return code +- +- jmp done_apm_bios +- +-no_32_apm_bios: +- andw $0xfffd, (76) # remove 32 bit support bit +-done_apm_bios: +-#endif +- +-#include "edd.S" +- +-# Now we want to move to protected mode ... +- cmpw $0, %cs:realmode_swtch +- jz rmodeswtch_normal +- +- lcall *%cs:realmode_swtch +- +- jmp rmodeswtch_end +- +-rmodeswtch_normal: +- pushw %cs +- call default_switch +- +-rmodeswtch_end: +-# Now we move the system to its rightful place ... but we check if we have a +-# big-kernel. In that case we *must* not move it ... +- testb $LOADED_HIGH, %cs:loadflags +- jz do_move0 # .. then we have a normal low +- # loaded zImage +- # .. or else we have a high +- # loaded bzImage +- jmp end_move # ... and we skip moving +- +-do_move0: +- movw $0x100, %ax # start of destination segment +- movw %cs, %bp # aka SETUPSEG +- subw $DELTA_INITSEG, %bp # aka INITSEG +- movw %cs:start_sys_seg, %bx # start of source segment +- cld +-do_move: +- movw %ax, %es # destination segment +- incb %ah # instead of add ax,#0x100 +- movw %bx, %ds # source segment +- addw $0x100, %bx +- subw %di, %di +- subw %si, %si +- movw $0x800, %cx +- rep +- movsw +- cmpw %bp, %bx # assume start_sys_seg > 0x200, +- # so we will perhaps read one +- # page more than needed, but +- # never overwrite INITSEG +- # because destination is a +- # minimum one page below source +- jb do_move +- +-end_move: +-# then we load the segment descriptors +- movw %cs, %ax # aka SETUPSEG +- movw %ax, %ds +- +-# Check whether we need to be downward compatible with version <=201 +- cmpl $0, cmd_line_ptr +- jne end_move_self # loader uses version >=202 features +- cmpb $0x20, type_of_loader +- je end_move_self # bootsect loader, we know of it +- +-# Boot loader doesnt support boot protocol version 2.02. +-# If we have our code not at 0x90000, we need to move it there now. +-# We also then need to move the params behind it (commandline) +-# Because we would overwrite the code on the current IP, we move +-# it in two steps, jumping high after the first one. +- movw %cs, %ax +- cmpw $SETUPSEG, %ax +- je end_move_self +- +- cli # make sure we really have +- # interrupts disabled ! +- # because after this the stack +- # should not be used +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ss, %dx +- cmpw %ax, %dx +- jb move_self_1 +- +- addw $INITSEG, %dx +- subw %ax, %dx # this will go into %ss after +- # the move +-move_self_1: +- movw %ax, %ds +- movw $INITSEG, %ax # real INITSEG +- movw %ax, %es +- movw %cs:setup_move_size, %cx +- std # we have to move up, so we use +- # direction down because the +- # areas may overlap +- movw %cx, %di +- decw %di +- movw %di, %si +- subw $move_self_here+0x200, %cx +- rep +- movsb +- ljmp $SETUPSEG, $move_self_here +- +-move_self_here: +- movw $move_self_here+0x200, %cx +- rep +- movsb +- movw $SETUPSEG, %ax +- movw %ax, %ds +- movw %dx, %ss +-end_move_self: # now we are at the right place +- +-# +-# Enable A20. This is at the very best an annoying procedure. +-# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin. +-# AMD Elan bug fix by Robert Schwebel. +-# +- +-#if defined(CONFIG_X86_ELAN) +- movb $0x02, %al # alternate A20 gate +- outb %al, $0x92 # this works on SC410/SC520 +-a20_elan_wait: +- call a20_test +- jz a20_elan_wait +- jmp a20_done +-#endif +- +- +-A20_TEST_LOOPS = 32 # Iterations per wait +-A20_ENABLE_LOOPS = 255 # Total loops to try +- +- +-#ifndef CONFIG_X86_VOYAGER +-a20_try_loop: +- +- # First, see if we are on a system with no A20 gate. +-a20_none: +- call a20_test +- jnz a20_done +- +- # Next, try the BIOS (INT 0x15, AX=0x2401) +-a20_bios: +- movw $0x2401, %ax +- pushfl # Be paranoid about flags +- int $0x15 +- popfl +- +- call a20_test +- jnz a20_done +- +- # Try enabling A20 through the keyboard controller +-#endif /* CONFIG_X86_VOYAGER */ +-a20_kbc: +- call empty_8042 +- +-#ifndef CONFIG_X86_VOYAGER +- call a20_test # Just in case the BIOS worked +- jnz a20_done # but had a delayed reaction. +-#endif +- +- movb $0xD1, %al # command write +- outb %al, $0x64 +- call empty_8042 +- +- movb $0xDF, %al # A20 on +- outb %al, $0x60 +- call empty_8042 +- +-#ifndef CONFIG_X86_VOYAGER +- # Wait until a20 really *is* enabled; it can take a fair amount of +- # time on certain systems; Toshiba Tecras are known to have this +- # problem. +-a20_kbc_wait: +- xorw %cx, %cx +-a20_kbc_wait_loop: +- call a20_test +- jnz a20_done +- loop a20_kbc_wait_loop +- +- # Final attempt: use "configuration port A" +-a20_fast: +- inb $0x92, %al # Configuration Port A +- orb $0x02, %al # "fast A20" version +- andb $0xFE, %al # don't accidentally reset +- outb %al, $0x92 +- +- # Wait for configuration port A to take effect +-a20_fast_wait: +- xorw %cx, %cx +-a20_fast_wait_loop: +- call a20_test +- jnz a20_done +- loop a20_fast_wait_loop +- +- # A20 is still not responding. Try frobbing it again. +- # +- decb (a20_tries) +- jnz a20_try_loop +- +- movw $a20_err_msg, %si +- call prtstr +- +-a20_die: +- hlt +- jmp a20_die +- +-a20_tries: +- .byte A20_ENABLE_LOOPS +- +-a20_err_msg: +- .ascii "linux: fatal error: A20 gate not responding!" +- .byte 13, 10, 0 +- +- # If we get here, all is good +-a20_done: +- +-#endif /* CONFIG_X86_VOYAGER */ +-# set up gdt and idt and 32bit start address +- lidt idt_48 # load idt with 0,0 +- xorl %eax, %eax # Compute gdt_base +- movw %ds, %ax # (Convert %ds:gdt to a linear ptr) +- shll $4, %eax +- addl %eax, code32 +- addl $gdt, %eax +- movl %eax, (gdt_48+2) +- lgdt gdt_48 # load gdt with whatever is +- # appropriate +- +-# make sure any possible coprocessor is properly reset.. +- xorw %ax, %ax +- outb %al, $0xf0 +- call delay +- +- outb %al, $0xf1 +- call delay +- +-# well, that went ok, I hope. Now we mask all interrupts - the rest +-# is done in init_IRQ(). +- movb $0xFF, %al # mask all interrupts for now +- outb %al, $0xA1 +- call delay +- +- movb $0xFB, %al # mask all irq's but irq2 which +- outb %al, $0x21 # is cascaded +- +-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't +-# need no steenking BIOS anyway (except for the initial loading :-). +-# The BIOS-routine wants lots of unnecessary data, and it's less +-# "interesting" anyway. This is how REAL programmers do it. +-# +-# Well, now's the time to actually move into protected mode. To make +-# things as simple as possible, we do no register set-up or anything, +-# we let the gnu-compiled 32-bit programs do that. We just jump to +-# absolute address 0x1000 (or the loader supplied one), +-# in 32-bit protected mode. +-# +-# Note that the short jump isn't strictly needed, although there are +-# reasons why it might be a good idea. It won't hurt in any case. +- movw $1, %ax # protected mode (PE) bit +- lmsw %ax # This is it! +- jmp flush_instr +- +-flush_instr: +- xorw %bx, %bx # Flag to indicate a boot +- xorl %esi, %esi # Pointer to real-mode code +- movw %cs, %si +- subw $DELTA_INITSEG, %si +- shll $4, %esi # Convert to 32-bit pointer +- +-# jump to startup_32 in arch/i386/boot/compressed/head.S +-# +-# NOTE: For high loaded big kernels we need a +-# jmpi 0x100000,__BOOT_CS +-# +-# but we yet haven't reloaded the CS register, so the default size +-# of the target offset still is 16 bit. +-# However, using an operand prefix (0x66), the CPU will properly +-# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference +-# Manual, Mixing 16-bit and 32-bit code, page 16-6) +- +- .byte 0x66, 0xea # prefix + jmpi-opcode +-code32: .long startup_32 # will be set to %cs+startup_32 +- .word __BOOT_CS +-.code32 +-startup_32: +- movl $(__BOOT_DS), %eax +- movl %eax, %ds +- movl %eax, %es +- movl %eax, %fs +- movl %eax, %gs +- movl %eax, %ss +- +- xorl %eax, %eax +-1: incl %eax # check that A20 really IS enabled +- movl %eax, 0x00000000 # loop forever if it isn't +- cmpl %eax, 0x00100000 +- je 1b +- +- # Jump to the 32bit entry point +- jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi) +-.code16 +- +-# Here's a bunch of information about your current kernel.. +-kernel_version: .ascii UTS_RELEASE +- .ascii " (" +- .ascii LINUX_COMPILE_BY +- .ascii "@" +- .ascii LINUX_COMPILE_HOST +- .ascii ") " +- .ascii UTS_VERSION +- .byte 0 +- +-# This is the default real mode switch routine. +-# to be called just before protected mode transition +-default_switch: +- cli # no interrupts allowed ! +- movb $0x80, %al # disable NMI for bootup +- # sequence +- outb %al, $0x70 +- lret +- +- +-#ifndef CONFIG_X86_VOYAGER +-# This routine tests whether or not A20 is enabled. If so, it +-# exits with zf = 0. +-# +-# The memory address used, 0x200, is the int $0x80 vector, which +-# should be safe. +- +-A20_TEST_ADDR = 4*0x80 +- +-a20_test: +- pushw %cx +- pushw %ax +- xorw %cx, %cx +- movw %cx, %fs # Low memory +- decw %cx +- movw %cx, %gs # High memory area +- movw $A20_TEST_LOOPS, %cx +- movw %fs:(A20_TEST_ADDR), %ax +- pushw %ax +-a20_test_wait: +- incw %ax +- movw %ax, %fs:(A20_TEST_ADDR) +- call delay # Serialize and make delay constant +- cmpw %gs:(A20_TEST_ADDR+0x10), %ax +- loope a20_test_wait +- +- popw %fs:(A20_TEST_ADDR) +- popw %ax +- popw %cx +- ret +- +-#endif /* CONFIG_X86_VOYAGER */ +- +-# This routine checks that the keyboard command queue is empty +-# (after emptying the output buffers) +-# +-# Some machines have delusions that the keyboard buffer is always full +-# with no keyboard attached... +-# +-# If there is no keyboard controller, we will usually get 0xff +-# to all the reads. With each IO taking a microsecond and +-# a timeout of 100,000 iterations, this can take about half a +-# second ("delay" == outb to port 0x80). That should be ok, +-# and should also be plenty of time for a real keyboard controller +-# to empty. +-# +- +-empty_8042: +- pushl %ecx +- movl $100000, %ecx +- +-empty_8042_loop: +- decl %ecx +- jz empty_8042_end_loop +- +- call delay +- +- inb $0x64, %al # 8042 status port +- testb $1, %al # output buffer? +- jz no_output +- +- call delay +- inb $0x60, %al # read it +- jmp empty_8042_loop +- +-no_output: +- testb $2, %al # is input buffer full? +- jnz empty_8042_loop # yes - loop +-empty_8042_end_loop: +- popl %ecx +- ret +- +-# Read the cmos clock. Return the seconds in al +-gettime: +- pushw %cx +- movb $0x02, %ah +- int $0x1a +- movb %dh, %al # %dh contains the seconds +- andb $0x0f, %al +- movb %dh, %ah +- movb $0x04, %cl +- shrb %cl, %ah +- aad +- popw %cx +- ret +- +-# Delay is needed after doing I/O +-delay: +- outb %al,$0x80 +- ret +- +-# Descriptor tables +-# +-# NOTE: The intel manual says gdt should be sixteen bytes aligned for +-# efficiency reasons. However, there are machines which are known not +-# to boot with misaligned GDTs, so alter this at your peril! If you alter +-# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two +-# empty GDT entries (one for NULL and one reserved). +-# +-# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is +-# true for the Voyager Quad CPU card which will not boot without +-# This directive. 16 byte aligment is recommended by intel. +-# +- .align 16 +-gdt: +- .fill GDT_ENTRY_BOOT_CS,8,0 +- +- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) +- .word 0 # base address = 0 +- .word 0x9A00 # code read/exec +- .word 0x00CF # granularity = 4096, 386 +- # (+5th nibble of limit) +- +- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) +- .word 0 # base address = 0 +- .word 0x9200 # data read/write +- .word 0x00CF # granularity = 4096, 386 +- # (+5th nibble of limit) +-gdt_end: +- .align 4 +- +- .word 0 # alignment byte +-idt_48: +- .word 0 # idt limit = 0 +- .word 0, 0 # idt base = 0L +- +- .word 0 # alignment byte +-gdt_48: +- .word gdt_end - gdt - 1 # gdt limit +- .word 0, 0 # gdt base (filled in later) +- +-# Include video setup & detection code +- +-#include "video.S" +- +-# Setup signature -- must be last +-setup_sig1: .word SIG1 +-setup_sig2: .word SIG2 +- +-# After this point, there is some free space which is used by the video mode +-# handling code to store the temporary mode table (not used by the kernel). +- +-modelist: +- +-.text +-endtext: +-.data +-enddata: +-.bss +-endbss: +diff -puN /dev/null arch/i386/boot/setup.ld +--- /dev/null ++++ a/arch/i386/boot/setup.ld +@@ -0,0 +1,54 @@ ++/* ++ * setup.ld ++ * ++ * Linker script for the i386 setup code ++ */ ++OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") ++OUTPUT_ARCH(i386) ++ENTRY(_start) ++ ++SECTIONS ++{ ++ . = 0; ++ .bstext : { *(.bstext) } ++ .bsdata : { *(.bsdata) } ++ ++ . = 497; ++ .header : { *(.header) } ++ .inittext : { *(.inittext) } ++ .initdata : { *(.initdata) } ++ .text : { *(.text*) } ++ ++ . = ALIGN(16); ++ .rodata : { *(.rodata*) } ++ ++ .videocards : { ++ video_cards = .; ++ *(.videocards) ++ video_cards_end = .; ++ } ++ ++ . = ALIGN(16); ++ .data : { *(.data*) } ++ ++ .signature : { ++ setup_sig = .; ++ LONG(0x5a5aaa55) ++ } ++ ++ ++ . = ALIGN(16); ++ .bss : ++ { ++ __bss_start = .; ++ *(.bss) ++ __bss_end = .; ++ } ++ . = ALIGN(16); ++ _end = .; ++ ++ /DISCARD/ : { *(.note*) } ++ ++ . = ASSERT(_end <= 0x8000, "Setup too big!"); ++ . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); ++} +diff -puN /dev/null arch/i386/boot/string.c +--- /dev/null ++++ a/arch/i386/boot/string.c +@@ -0,0 +1,34 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/string.c ++ * ++ * Very basic string functions ++ */ ++ ++#include "boot.h" ++#include ++ ++int strcmp(const char *str1, const char *str2) ++{ ++ const unsigned char *s1 = (const unsigned char *)str1; ++ const unsigned char *s2 = (const unsigned char *)str2; ++ int delta = 0; ++ ++ while (*s1 || *s2) { ++ delta = *s2 - *s1; ++ if (delta) ++ return delta; ++ s1++; ++ s2++; ++ } ++ return 0; ++} +diff -puN arch/i386/boot/tools/build.c~git-newsetup arch/i386/boot/tools/build.c +--- a/arch/i386/boot/tools/build.c~git-newsetup ++++ a/arch/i386/boot/tools/build.c +@@ -1,13 +1,12 @@ + /* + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1997 Martin Mares ++ * Copyright (C) 2007 H. Peter Anvin + */ + + /* + * This file builds a disk-image from three different files: + * +- * - bootsect: compatibility mbr which prints an error message if +- * someone tries to boot the kernel directly. + * - setup: 8086 machine code, sets up system parm + * - system: 80386 code for actual system + * +@@ -21,6 +20,7 @@ + * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 + * Cross compiling fixes by Gertjan van Wingerde, July 1996 + * Rewritten by Martin Mares, April 1997 ++ * Substantially overhauled by H. Peter Anvin, April 2007 + */ + + #include +@@ -32,23 +32,25 @@ + #include + #include + #include ++#include + #include + +-typedef unsigned char byte; +-typedef unsigned short word; +-typedef unsigned long u32; ++typedef unsigned char u8; ++typedef unsigned short u16; ++typedef unsigned long u32; + + #define DEFAULT_MAJOR_ROOT 0 + #define DEFAULT_MINOR_ROOT 0 + +-/* Minimal number of setup sectors (see also bootsect.S) */ +-#define SETUP_SECTS 4 ++/* Minimal number of setup sectors */ ++#define SETUP_SECT_MIN 5 ++#define SETUP_SECT_MAX 64 + +-byte buf[1024]; +-int fd; ++/* This must be large enough to hold the entire setup */ ++u8 buf[SETUP_SECT_MAX*512]; + int is_big_kernel; + +-void die(const char * str, ...) ++static void die(const char * str, ...) + { + va_list args; + va_start(args, str); +@@ -57,15 +59,9 @@ void die(const char * str, ...) + exit(1); + } + +-void file_open(const char *name) ++static void usage(void) + { +- if ((fd = open(name, O_RDONLY, 0)) < 0) +- die("Unable to open `%s': %m", name); +-} +- +-void usage(void) +-{ +- die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); ++ die("Usage: build [-b] setup system [rootdev] [> image]"); + } + + int main(int argc, char ** argv) +@@ -73,27 +69,30 @@ int main(int argc, char ** argv) + unsigned int i, sz, setup_sectors; + int c; + u32 sys_size; +- byte major_root, minor_root; ++ u8 major_root, minor_root; + struct stat sb; ++ FILE *file; ++ int fd; ++ void *kernel; + + if (argc > 2 && !strcmp(argv[1], "-b")) + { + is_big_kernel = 1; + argc--, argv++; + } +- if ((argc < 4) || (argc > 5)) ++ if ((argc < 3) || (argc > 4)) + usage(); +- if (argc > 4) { +- if (!strcmp(argv[4], "CURRENT")) { ++ if (argc > 3) { ++ if (!strcmp(argv[3], "CURRENT")) { + if (stat("/", &sb)) { + perror("/"); + die("Couldn't stat /"); + } + major_root = major(sb.st_dev); + minor_root = minor(sb.st_dev); +- } else if (strcmp(argv[4], "FLOPPY")) { +- if (stat(argv[4], &sb)) { +- perror(argv[4]); ++ } else if (strcmp(argv[3], "FLOPPY")) { ++ if (stat(argv[3], &sb)) { ++ perror(argv[3]); + die("Couldn't stat root device."); + } + major_root = major(sb.st_rdev); +@@ -108,79 +107,62 @@ int main(int argc, char ** argv) + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + +- file_open(argv[1]); +- i = read(fd, buf, sizeof(buf)); +- fprintf(stderr,"Boot sector %d bytes.\n",i); +- if (i != 512) +- die("Boot block must be exactly 512 bytes"); ++ /* Copy the setup code */ ++ file = fopen(argv[1], "r"); ++ if (!file) ++ die("Unable to open `%s': %m", argv[1]); ++ c = fread(buf, 1, sizeof(buf), file); ++ if (ferror(file)) ++ die("read-error on `setup'"); ++ if (c < 1024) ++ die("The setup must be at least 1024 bytes"); + if (buf[510] != 0x55 || buf[511] != 0xaa) + die("Boot block hasn't got boot flag (0xAA55)"); ++ fclose(file); ++ ++ /* Pad unused space with zeros */ ++ setup_sectors = (c + 511) / 512; ++ if (setup_sectors < SETUP_SECT_MIN) ++ setup_sectors = SETUP_SECT_MIN; ++ i = setup_sectors*512; ++ memset(buf+c, 0, i-c); ++ ++ /* Set the default root device */ + buf[508] = minor_root; + buf[509] = major_root; +- if (write(1, buf, 512) != 512) +- die("Write call failed"); +- close (fd); +- +- file_open(argv[2]); /* Copy the setup code */ +- for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) +- if (write(1, buf, c) != c) +- die("Write call failed"); +- if (c != 0) +- die("read-error on `setup'"); +- close (fd); + +- setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ +- /* for compatibility with ancient versions of LILO. */ +- if (setup_sectors < SETUP_SECTS) +- setup_sectors = SETUP_SECTS; +- fprintf(stderr, "Setup is %d bytes.\n", i); +- memset(buf, 0, sizeof(buf)); +- while (i < setup_sectors * 512) { +- c = setup_sectors * 512 - i; +- if (c > sizeof(buf)) +- c = sizeof(buf); +- if (write(1, buf, c) != c) +- die("Write call failed"); +- i += c; +- } ++ fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); + +- file_open(argv[3]); +- if (fstat (fd, &sb)) +- die("Unable to stat `%s': %m", argv[3]); ++ /* Open and stat the kernel file */ ++ fd = open(argv[2], O_RDONLY); ++ if (fd < 0) ++ die("Unable to open `%s': %m", argv[2]); ++ if (fstat(fd, &sb)) ++ die("Unable to stat `%s': %m", argv[2]); + sz = sb.st_size; +- fprintf (stderr, "System is %d kB\n", sz/1024); ++ fprintf (stderr, "System is %d kB\n", (sz+1023)/1024); ++ kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); ++ if (kernel == MAP_FAILED) ++ die("Unable to mmap '%s': %m", argv[2]); + sys_size = (sz + 15) / 16; + if (!is_big_kernel && sys_size > DEF_SYSSIZE) + die("System is too big. Try using bzImage or modules."); +- while (sz > 0) { +- int l, n; + +- l = (sz > sizeof(buf)) ? sizeof(buf) : sz; +- if ((n=read(fd, buf, l)) != l) { +- if (n < 0) +- die("Error reading %s: %m", argv[3]); +- else +- die("%s: Unexpected EOF", argv[3]); +- } +- if (write(1, buf, l) != l) +- die("Write failed"); +- sz -= l; +- } ++ /* Patch the setup code with the appropriate size parameters */ ++ buf[0x1f1] = setup_sectors-1; ++ buf[0x1f4] = sys_size; ++ buf[0x1f5] = sys_size >> 8; ++ buf[0x1f6] = sys_size >> 16; ++ buf[0x1f7] = sys_size >> 24; ++ ++ if (fwrite(buf, 1, i, stdout) != i) ++ die("Writing setup failed"); ++ ++ /* Copy the kernel code */ ++ if (fwrite(kernel, 1, sz, stdout) != sz) ++ die("Writing kernel failed"); + close(fd); + +- if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ +- die("Output: seek failed"); +- buf[0] = setup_sectors; +- if (write(1, buf, 1) != 1) +- die("Write of setup sector count failed"); +- if (lseek(1, 500, SEEK_SET) != 500) +- die("Output: seek failed"); +- buf[0] = (sys_size & 0xff); +- buf[1] = ((sys_size >> 8) & 0xff); +- buf[2] = ((sys_size >> 16) & 0xff); +- buf[3] = ((sys_size >> 24) & 0xff); +- if (write(1, buf, 4) != 4) +- die("Write of image length failed"); +- +- return 0; /* Everything is OK */ ++ /* Everything is OK */ ++ return 0; + } +diff -puN /dev/null arch/i386/boot/tty.c +--- /dev/null ++++ a/arch/i386/boot/tty.c +@@ -0,0 +1,112 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/tty.c ++ * ++ * Very simple screen I/O ++ * XXX: Probably should add very simple serial I/O? ++ */ ++ ++#include "boot.h" ++ ++/* ++ * These functions are in .inittext so they can be used to signal ++ * error during initialization. ++ */ ++ ++void __attribute__((section(".inittext"))) putchar(int ch) ++{ ++ unsigned char c = ch; ++ ++ if (c == '\n') ++ putchar('\r'); /* \n -> \r\n */ ++ ++ /* int $0x10 is known to have bugs involving touching registers ++ it shouldn't. Be extra conservative... */ ++ asm volatile("pushal; int $0x10; popal" ++ : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); ++} ++ ++void __attribute__((section(".inittext"))) puts(const char *str) ++{ ++ int n = 0; ++ while (*str) { ++ putchar(*str++); ++ n++; ++ } ++} ++ ++/* ++ * Read the CMOS clock through the BIOS, and return the ++ * seconds in BCD. ++ */ ++ ++static u8 gettime(void) ++{ ++ u16 ax = 0x0200; ++ u16 cx, dx; ++ ++ asm("int $0x1a" ++ : "+a" (ax), "=c" (cx), "=d" (dx) ++ : : "ebx", "esi", "edi"); ++ ++ return dx >> 8; ++} ++ ++/* ++ * Read from the keyboard ++ */ ++int getchar(void) ++{ ++ u16 ax = 0; ++ asm("int $0x16" : "+a" (ax)); ++ ++ return ax & 0xff; ++} ++ ++static int kbd_pending(void) ++{ ++ u8 pending; ++ asm("int $0x16; setnz %0" ++ : "=rm" (pending) ++ : "a" (0x0100)); ++ return pending; ++} ++ ++void kbd_flush(void) ++{ ++ for (;;) { ++ if (!kbd_pending()) ++ break; ++ getchar(); ++ } ++} ++ ++int getchar_timeout(void) ++{ ++ int cnt = 30; ++ int t0, t1; ++ ++ t0 = gettime(); ++ ++ while (cnt) { ++ if (kbd_pending()) ++ return getchar(); ++ ++ t1 = gettime(); ++ if (t0 != t1) { ++ cnt--; ++ t0 = t1; ++ } ++ } ++ ++ return 0; /* Timeout! */ ++} +diff -puN /dev/null arch/i386/boot/version.c +--- /dev/null ++++ a/arch/i386/boot/version.c +@@ -0,0 +1,23 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/version.c ++ * ++ * Kernel version string ++ */ ++ ++#include "boot.h" ++#include ++#include ++ ++const char kernel_version[] = ++ UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " ++ UTS_VERSION; +diff -puN /dev/null arch/i386/boot/vesa.h +--- /dev/null ++++ a/arch/i386/boot/vesa.h +@@ -0,0 +1,79 @@ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright 1999-2007 H. Peter Anvin - All Rights Reserved ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, Inc., 53 Temple Place Ste 330, ++ * Boston MA 02111-1307, USA; either version 2 of the License, or ++ * (at your option) any later version; incorporated herein by reference. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++#ifndef BOOT_VESA_H ++#define BOOT_VESA_H ++ ++typedef struct { ++ u16 off, seg; ++} far_ptr; ++ ++/* VESA General Information table */ ++struct vesa_general_info { ++ u32 signature; /* 0 Magic number = "VESA" */ ++ u16 version; /* 4 */ ++ far_ptr vendor_string; /* 6 */ ++ u32 capabilities; /* 10 */ ++ far_ptr video_mode_ptr; /* 14 */ ++ u16 total_memory; /* 18 */ ++ ++ u16 oem_software_rev; /* 20 */ ++ far_ptr oem_vendor_name_ptr; /* 22 */ ++ far_ptr oem_product_name_ptr; /* 26 */ ++ far_ptr oem_product_rev_ptr; /* 30 */ ++ ++ u8 reserved[222]; /* 34 */ ++ u8 oem_data[256]; /* 256 */ ++} __attribute__((packed)); ++ ++#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) ++#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24)) ++ ++struct vesa_mode_info { ++ u16 mode_attr; /* 0 */ ++ u8 win_attr[2]; /* 2 */ ++ u16 win_grain; /* 4 */ ++ u16 win_size; /* 6 */ ++ u16 win_seg[2]; /* 8 */ ++ far_ptr win_scheme; /* 12 */ ++ u16 logical_scan; /* 16 */ ++ ++ u16 h_res; /* 18 */ ++ u16 v_res; /* 20 */ ++ u8 char_width; /* 22 */ ++ u8 char_height; /* 23 */ ++ u8 memory_planes; /* 24 */ ++ u8 bpp; /* 25 */ ++ u8 banks; /* 26 */ ++ u8 memory_layout; /* 27 */ ++ u8 bank_size; /* 28 */ ++ u8 image_planes; /* 29 */ ++ u8 page_function; /* 30 */ ++ ++ u8 rmask; /* 31 */ ++ u8 rpos; /* 32 */ ++ u8 gmask; /* 33 */ ++ u8 gpos; /* 34 */ ++ u8 bmask; /* 35 */ ++ u8 bpos; /* 36 */ ++ u8 resv_mask; /* 37 */ ++ u8 resv_pos; /* 38 */ ++ u8 dcm_info; /* 39 */ ++ ++ u32 lfb_ptr; /* 40 Linear frame buffer address */ ++ u32 offscreen_ptr; /* 44 Offscreen memory address */ ++ u16 offscreen_size; /* 48 */ ++ ++ u8 reserved[206]; /* 50 */ ++} __attribute__((packed)); ++ ++#endif /* LIB_SYS_VESA_H */ +diff -puN /dev/null arch/i386/boot/video-bios.c +--- /dev/null ++++ a/arch/i386/boot/video-bios.c +@@ -0,0 +1,125 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/video-bios.c ++ * ++ * Standard video BIOS modes ++ * ++ * We have two options for this; silent and scanned. ++ */ ++ ++#include "boot.h" ++#include "video.h" ++ ++__videocard video_bios; ++ ++/* Set a conventional BIOS mode */ ++static int set_bios_mode(u8 mode); ++ ++static int bios_set_mode(struct mode_info *mi) ++{ ++ return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS); ++} ++ ++static int set_bios_mode(u8 mode) ++{ ++ u16 ax; ++ u8 new_mode; ++ ++ ax = mode; /* AH=0x00 Set Video Mode */ ++ asm volatile(INT10 ++ : "+a" (ax) ++ : : "ebx", "ecx", "edx", "esi", "edi"); ++ ++ ax = 0x0f00; /* Get Current Video Mode */ ++ asm volatile(INT10 ++ : "+a" (ax) ++ : : "ebx", "ecx", "edx", "esi", "edi"); ++ ++ do_restore = 1; /* Assume video contents was lost */ ++ new_mode = ax & 0x7f; /* Not all BIOSes are clean with the top bit */ ++ ++ if (new_mode == mode) ++ return 0; /* Mode change OK */ ++ ++ if (new_mode != boot_params.screen_info.orig_video_mode) { ++ /* Mode setting failed, but we didn't end up where we ++ started. That's bad. Try to revert to the original ++ video mode. */ ++ ax = boot_params.screen_info.orig_video_mode; ++ asm volatile(INT10 ++ : "+a" (ax) ++ : : "ebx", "ecx", "edx", "esi", "edi"); ++ } ++ return -1; ++} ++ ++static int bios_probe(void) ++{ ++ u8 mode; ++ u8 saved_mode = boot_params.screen_info.orig_video_mode; ++ u16 crtc; ++ struct mode_info *mi; ++ int nmodes = 0; ++ ++ if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA) ++ return 0; ++ ++ set_fs(0); ++ crtc = vga_crtc(); ++ ++ video_bios.modes = GET_HEAP(struct mode_info, 0); ++ ++ for (mode = 0x14; mode <= 0x7f; mode++) { ++ if (heap_free() < sizeof(struct mode_info)) ++ break; ++ ++ if (mode_defined(VIDEO_FIRST_BIOS+mode)) ++ continue; ++ ++ if (set_bios_mode(mode)) ++ continue; ++ ++ /* Try to verify that it's a text mode. */ ++ ++ /* Attribute Controller: make graphics controller disabled */ ++ if (in_idx(0x3c0, 0x10) & 0x01) ++ continue; ++ ++ /* Graphics Controller: verify Alpha addressing enabled */ ++ if (in_idx(0x3ce, 0x06) & 0x01) ++ continue; ++ ++ /* CRTC cursor location low should be zero(?) */ ++ if (in_idx(crtc, 0x0f)) ++ continue; ++ ++ mi = GET_HEAP(struct mode_info, 1); ++ mi->mode = VIDEO_FIRST_BIOS+mode; ++ mi->x = rdfs16(0x44a); ++ mi->y = rdfs8(0x484)+1; ++ nmodes++; ++ } ++ ++ set_bios_mode(saved_mode); ++ ++ return nmodes; ++} ++ ++__videocard video_bios = ++{ ++ .card_name = "BIOS (scanned)", ++ .probe = bios_probe, ++ .set_mode = bios_set_mode, ++ .unsafe = 1, ++ .xmode_first = VIDEO_FIRST_BIOS, ++ .xmode_n = 0x80, ++}; +diff -puN /dev/null arch/i386/boot/video-vesa.c +--- /dev/null ++++ a/arch/i386/boot/video-vesa.c +@@ -0,0 +1,283 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/video-vesa.c ++ * ++ * VESA text modes ++ */ ++ ++#include "boot.h" ++#include "video.h" ++#include "vesa.h" ++ ++/* VESA information */ ++static struct vesa_general_info vginfo; ++static struct vesa_mode_info vminfo; ++ ++__videocard video_vesa; ++ ++static void vesa_store_mode_params_graphics(void); ++ ++static int vesa_probe(void) ++{ ++#ifdef CONFIG_VIDEO_VESA ++ u16 ax; ++ u16 mode; ++ addr_t mode_ptr; ++ struct mode_info *mi; ++ int nmodes = 0; ++ ++ video_vesa.modes = GET_HEAP(struct mode_info, 0); ++ ++ vginfo.signature = VBE2_MAGIC; ++ ++ /* Optimistically assume a VESA BIOS is register-clean... */ ++ ax = 0x4f00; ++ asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo)); ++ ++ if (ax != 0x004f || ++ vginfo.signature != VESA_MAGIC || ++ vginfo.version < 0x0102) ++ return 0; /* Not present */ ++ ++ set_fs(vginfo.video_mode_ptr.seg); ++ mode_ptr = vginfo.video_mode_ptr.off; ++ ++ while ((mode = rdfs16(mode_ptr)) != 0xffff) { ++ mode_ptr += 2; ++ ++ if (heap_free() < sizeof(struct mode_info)) ++ break; /* Heap full, can't save mode info */ ++ ++ if (mode & ~0x1ff) ++ continue; ++ ++ memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ ++ ++ ax = 0x4f01; ++ asm("int $0x10" ++ : "+a" (ax), "=m" (vminfo) ++ : "c" (mode), "D" (&vminfo)); ++ ++ if (ax != 0x004f) ++ continue; ++ ++ if ((vminfo.mode_attr & 0x15) == 0x05) { ++ /* Text Mode, TTY BIOS supported, ++ supported by hardware */ ++ mi = GET_HEAP(struct mode_info, 1); ++ mi->mode = mode + VIDEO_FIRST_VESA; ++ mi->x = vminfo.h_res; ++ mi->y = vminfo.v_res; ++ nmodes++; ++ } else if ((vminfo.mode_attr & 0x99) == 0x99) { ++#ifdef CONFIG_FB ++ /* Graphics mode, color, linear frame buffer ++ supported -- register the mode but hide from ++ the menu. Only do this if framebuffer is ++ configured, however, otherwise the user will ++ be left without a screen. */ ++ mi = GET_HEAP(struct mode_info, 1); ++ mi->mode = mode + VIDEO_FIRST_VESA; ++ mi->x = mi->y = 0; ++ nmodes++; ++#endif ++ } ++ } ++ ++ return nmodes; ++#else ++ return 0; ++#endif ++} ++ ++static int vesa_set_mode(struct mode_info *mode) ++{ ++ u16 ax; ++ int is_graphic; ++ u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA; ++ ++ memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ ++ ++ ax = 0x4f01; ++ asm("int $0x10" ++ : "+a" (ax), "=m" (vminfo) ++ : "c" (vesa_mode), "D" (&vminfo)); ++ ++ if (ax != 0x004f) ++ return -1; ++ ++ if ((vminfo.mode_attr & 0x15) == 0x05) { ++ /* It's a supported text mode */ ++ is_graphic = 0; ++ } else if ((vminfo.mode_attr & 0x99) == 0x99) { ++ /* It's a graphics mode with linear frame buffer */ ++ is_graphic = 1; ++ vesa_mode |= 0x4000; /* Request linear frame buffer */ ++ } else { ++ return -1; /* Invalid mode */ ++ } ++ ++ ++ ax = 0x4f02; ++ asm volatile("int $0x10" ++ : "+a" (ax) ++ : "b" (vesa_mode), "D" (0)); ++ ++ if (ax != 0x004f) ++ return -1; ++ ++ graphic_mode = is_graphic; ++ if (!is_graphic) { ++ /* Text mode */ ++ force_x = mode->x; ++ force_y = mode->y; ++ do_restore = 1; ++ } else { ++ /* Graphics mode */ ++ vesa_store_mode_params_graphics(); ++ } ++ ++ return 0; ++} ++ ++ ++/* Switch DAC to 8-bit mode */ ++static void vesa_dac_set_8bits(void) ++{ ++ u8 dac_size = 6; ++ ++ /* If possible, switch the DAC to 8-bit mode */ ++ if (vginfo.capabilities & 1) { ++ u16 ax, bx; ++ ++ ax = 0x4f08; ++ bx = 0x0800; ++ asm volatile(INT10 ++ : "+a" (ax), "+b" (bx) ++ : : "ecx", "edx", "esi", "edi"); ++ ++ if (ax == 0x004f) ++ dac_size = bx >> 8; ++ } ++ ++ /* Set the color sizes to the DAC size, and offsets to 0 */ ++ boot_params.screen_info.red_size = dac_size; ++ boot_params.screen_info.green_size = dac_size; ++ boot_params.screen_info.blue_size = dac_size; ++ boot_params.screen_info.rsvd_size = dac_size; ++ ++ boot_params.screen_info.red_pos = 0; ++ boot_params.screen_info.green_pos = 0; ++ boot_params.screen_info.blue_pos = 0; ++ boot_params.screen_info.rsvd_pos = 0; ++} ++ ++/* Save the VESA protected mode info */ ++static void vesa_store_pm_info(void) ++{ ++ u16 ax, bx, di, es; ++ ++ ax = 0x4f0a; ++ bx = di = 0; ++ asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es" ++ : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di) ++ : : "ecx", "esi"); ++ ++ if (ax != 0x004f) ++ return; ++ ++ boot_params.screen_info.vesapm_seg = es; ++ boot_params.screen_info.vesapm_off = di; ++} ++ ++/* ++ * Save video mode parameters for graphics mode ++ */ ++static void vesa_store_mode_params_graphics(void) ++{ ++ /* Tell the kernel we're in VESA graphics mode */ ++ boot_params.screen_info.orig_video_isVGA = 0x23; ++ ++ /* Mode parameters */ ++ boot_params.screen_info.vesa_attributes = vminfo.mode_attr; ++ boot_params.screen_info.lfb_linelength = vminfo.logical_scan; ++ boot_params.screen_info.lfb_width = vminfo.h_res; ++ boot_params.screen_info.lfb_height = vminfo.v_res; ++ boot_params.screen_info.lfb_depth = vminfo.bpp; ++ boot_params.screen_info.pages = vminfo.image_planes; ++ boot_params.screen_info.lfb_base = vminfo.lfb_ptr; ++ memcpy(&boot_params.screen_info.red_size, ++ &vminfo.rmask, 8); ++ ++ /* General parameters */ ++ boot_params.screen_info.lfb_size = vginfo.total_memory; ++ ++ if (vminfo.bpp <= 8) ++ vesa_dac_set_8bits(); ++ ++ vesa_store_pm_info(); ++} ++ ++/* ++ * Save EDID information for the kernel; this is invoked, separately, ++ * after mode-setting. ++ */ ++void vesa_store_edid(void) ++{ ++#ifdef CONFIG_FIRMWARE_EDID ++ u16 ax, bx, cx, dx, di; ++ ++ /* Apparently used as a nonsense token... */ ++ memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info); ++ ++ if (vginfo.version < 0x0200) ++ return; /* EDID requires VBE 2.0+ */ ++ ++ ax = 0x4f15; /* VBE DDC */ ++ bx = 0x0000; /* Report DDC capabilities */ ++ cx = 0; /* Controller 0 */ ++ di = 0; /* ES:DI must be 0 by spec */ ++ ++ /* Note: The VBE DDC spec is different from the main VESA spec; ++ we genuinely have to assume all registers are destroyed here. */ ++ ++ asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es" ++ : "+a" (ax), "+b" (bx) ++ : "c" (cx), "D" (di) ++ : "esi"); ++ ++ if (ax != 0x004f) ++ return; /* No EDID */ ++ ++ /* BH = time in seconds to transfer EDD information */ ++ /* BL = DDC level supported */ ++ ++ ax = 0x4f15; /* VBE DDC */ ++ bx = 0x0001; /* Read EDID */ ++ cx = 0; /* Controller 0 */ ++ dx = 0; /* EDID block number */ ++ di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */ ++ asm(INT10 ++ : "+a" (ax), "+b" (bx), "+d" (dx) ++ : "c" (cx), "D" (di) ++ : "esi"); ++#endif /* CONFIG_FIRMWARE_EDID */ ++} ++ ++__videocard video_vesa = ++{ ++ .card_name = "VESA", ++ .probe = vesa_probe, ++ .set_mode = vesa_set_mode, ++ .xmode_first = VIDEO_FIRST_VESA, ++ .xmode_n = 0x200, ++}; +diff -puN /dev/null arch/i386/boot/video-vga.c +--- /dev/null ++++ a/arch/i386/boot/video-vga.c +@@ -0,0 +1,260 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/video-vga.c ++ * ++ * Common all-VGA modes ++ */ ++ ++#include "boot.h" ++#include "video.h" ++ ++static struct mode_info vga_modes[] = { ++ { VIDEO_80x25, 80, 25 }, ++ { VIDEO_8POINT, 80, 50 }, ++ { VIDEO_80x43, 80, 43 }, ++ { VIDEO_80x28, 80, 28 }, ++ { VIDEO_80x30, 80, 30 }, ++ { VIDEO_80x34, 80, 34 }, ++ { VIDEO_80x60, 80, 60 }, ++}; ++ ++static struct mode_info ega_modes[] = { ++ { VIDEO_80x25, 80, 25 }, ++ { VIDEO_8POINT, 80, 43 }, ++}; ++ ++static struct mode_info cga_modes[] = { ++ { VIDEO_80x25, 80, 25 }, ++}; ++ ++__videocard video_vga; ++ ++/* Set basic 80x25 mode */ ++static u8 vga_set_basic_mode(void) ++{ ++ u16 ax; ++ u8 rows; ++ u8 mode; ++ ++#ifdef CONFIG_VIDEO_400_HACK ++ if (adapter >= ADAPTER_VGA) { ++ asm(INT10 ++ : : "a" (0x1202), "b" (0x0030) ++ : "ecx", "edx", "esi", "edi"); ++ } ++#endif ++ ++ ax = 0x0f00; ++ asm(INT10 ++ : "+a" (ax) ++ : : "ebx", "ecx", "edx", "esi", "edi"); ++ ++ mode = (u8)ax; ++ ++ set_fs(0); ++ rows = rdfs8(0x484); /* rows minus one */ ++ ++#ifndef CONFIG_VIDEO_400_HACK ++ if ((ax == 0x5003 || ax == 0x5007) && ++ (rows == 0 || rows == 24)) ++ return mode; ++#endif ++ ++ if (mode != 3 && mode != 7) ++ mode = 3; ++ ++ /* Set the mode */ ++ asm volatile(INT10 ++ : : "a" (mode) ++ : "ebx", "ecx", "edx", "esi", "edi"); ++ do_restore = 1; ++ return mode; ++} ++ ++static void vga_set_8font(void) ++{ ++ /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */ ++ ++ /* Set 8x8 font */ ++ asm volatile(INT10 : : "a" (0x1112), "b" (0)); ++ ++ /* Use alternate print screen */ ++ asm volatile(INT10 : : "a" (0x1200), "b" (0x20)); ++ ++ /* Turn off cursor emulation */ ++ asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); ++ ++ /* Cursor is scan lines 6-7 */ ++ asm volatile(INT10 : : "a" (0x0100), "c" (0x0607)); ++} ++ ++static void vga_set_14font(void) ++{ ++ /* Set 9x14 font - 80x28 on VGA */ ++ ++ /* Set 9x14 font */ ++ asm volatile(INT10 : : "a" (0x1111), "b" (0)); ++ ++ /* Turn off cursor emulation */ ++ asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); ++ ++ /* Cursor is scan lines 11-12 */ ++ asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c)); ++} ++ ++static void vga_set_80x43(void) ++{ ++ /* Set 80x43 mode on VGA (not EGA) */ ++ ++ /* Set 350 scans */ ++ asm volatile(INT10 : : "a" (0x1201), "b" (0x30)); ++ ++ /* Reset video mode */ ++ asm volatile(INT10 : : "a" (0x0003)); ++ ++ vga_set_8font(); ++} ++ ++/* I/O address of the VGA CRTC */ ++u16 vga_crtc(void) ++{ ++ return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4; ++} ++ ++static void vga_set_480_scanlines(int end) ++{ ++ u16 crtc; ++ u8 csel; ++ ++ crtc = vga_crtc(); ++ ++ out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */ ++ out_idx(0x0b, crtc, 0x06); /* Vertical total */ ++ out_idx(0x3e, crtc, 0x07); /* Vertical overflow */ ++ out_idx(0xea, crtc, 0x10); /* Vertical sync start */ ++ out_idx(end, crtc, 0x12); /* Vertical display end */ ++ out_idx(0xe7, crtc, 0x15); /* Vertical blank start */ ++ out_idx(0x04, crtc, 0x16); /* Vertical blank end */ ++ csel = inb(0x3cc); ++ csel &= 0x0d; ++ csel |= 0xe2; ++ outb(csel, 0x3cc); ++} ++ ++static void vga_set_80x30(void) ++{ ++ vga_set_480_scanlines(0xdf); ++} ++ ++static void vga_set_80x34(void) ++{ ++ vga_set_14font(); ++ vga_set_480_scanlines(0xdb); ++} ++ ++static void vga_set_80x60(void) ++{ ++ vga_set_8font(); ++ vga_set_480_scanlines(0xdf); ++} ++ ++static int vga_set_mode(struct mode_info *mode) ++{ ++ /* Set the basic mode */ ++ vga_set_basic_mode(); ++ ++ /* Override a possibly broken BIOS */ ++ force_x = mode->x; ++ force_y = mode->y; ++ ++ switch (mode->mode) { ++ case VIDEO_80x25: ++ break; ++ case VIDEO_8POINT: ++ vga_set_8font(); ++ break; ++ case VIDEO_80x43: ++ vga_set_80x43(); ++ break; ++ case VIDEO_80x28: ++ vga_set_14font(); ++ break; ++ case VIDEO_80x30: ++ vga_set_80x30(); ++ break; ++ case VIDEO_80x34: ++ vga_set_80x34(); ++ break; ++ case VIDEO_80x60: ++ vga_set_80x60(); ++ break; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Note: this probe includes basic information required by all ++ * systems. It should be executed first, by making sure ++ * video-vga.c is listed first in the Makefile. ++ */ ++static int vga_probe(void) ++{ ++ static const char *card_name[] = { ++ "CGA/MDA/HGC", "EGA", "VGA" ++ }; ++ static struct mode_info *mode_lists[] = { ++ cga_modes, ++ ega_modes, ++ vga_modes, ++ }; ++ static int mode_count[] = { ++ sizeof(cga_modes)/sizeof(struct mode_info), ++ sizeof(ega_modes)/sizeof(struct mode_info), ++ sizeof(vga_modes)/sizeof(struct mode_info), ++ }; ++ u8 vga_flag; ++ ++ asm(INT10 ++ : "=b" (boot_params.screen_info.orig_video_ega_bx) ++ : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */ ++ : "ecx", "edx", "esi", "edi"); ++ ++ /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ ++ if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) { ++ /* EGA/VGA */ ++ asm(INT10 ++ : "=a" (vga_flag) ++ : "a" (0x1a00) ++ : "ebx", "ecx", "edx", "esi", "edi"); ++ ++ if (vga_flag == 0x1a) { ++ adapter = ADAPTER_VGA; ++ boot_params.screen_info.orig_video_isVGA = 1; ++ } else { ++ adapter = ADAPTER_EGA; ++ } ++ } else { ++ adapter = ADAPTER_CGA; ++ } ++ ++ video_vga.modes = mode_lists[adapter]; ++ video_vga.card_name = card_name[adapter]; ++ return mode_count[adapter]; ++} ++ ++__videocard video_vga = ++{ ++ .card_name = "VGA", ++ .probe = vga_probe, ++ .set_mode = vga_set_mode, ++}; +diff -puN arch/i386/boot/video.S~git-newsetup /dev/null +--- a/arch/i386/boot/video.S ++++ /dev/null +@@ -1,2043 +0,0 @@ +-/* video.S +- * +- * Display adapter & video mode setup, version 2.13 (14-May-99) +- * +- * Copyright (C) 1995 -- 1998 Martin Mares +- * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson +- * +- * Rewritten to use GNU 'as' by Chris Noe May 1999 +- * +- * For further information, look at Documentation/svga.txt. +- * +- */ +- +-/* Enable autodetection of SVGA adapters and modes. */ +-#undef CONFIG_VIDEO_SVGA +- +-/* Enable autodetection of VESA modes */ +-#define CONFIG_VIDEO_VESA +- +-/* Enable compacting of mode table */ +-#define CONFIG_VIDEO_COMPACT +- +-/* Retain screen contents when switching modes */ +-#define CONFIG_VIDEO_RETAIN +- +-/* Enable local mode list */ +-#undef CONFIG_VIDEO_LOCAL +- +-/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */ +-#undef CONFIG_VIDEO_400_HACK +- +-/* Hack that lets you force specific BIOS mode ID and specific dimensions */ +-#undef CONFIG_VIDEO_GFX_HACK +-#define VIDEO_GFX_BIOS_AX 0x4f02 /* 800x600 on ThinkPad */ +-#define VIDEO_GFX_BIOS_BX 0x0102 +-#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425 /* 100x37 */ +- +-/* This code uses an extended set of video mode numbers. These include: +- * Aliases for standard modes +- * NORMAL_VGA (-1) +- * EXTENDED_VGA (-2) +- * ASK_VGA (-3) +- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack +- * of compatibility when extending the table. These are between 0x00 and 0xff. +- */ +-#define VIDEO_FIRST_MENU 0x0000 +- +-/* Standard BIOS video modes (BIOS number + 0x0100) */ +-#define VIDEO_FIRST_BIOS 0x0100 +- +-/* VESA BIOS video modes (VESA number + 0x0200) */ +-#define VIDEO_FIRST_VESA 0x0200 +- +-/* Video7 special modes (BIOS number + 0x0900) */ +-#define VIDEO_FIRST_V7 0x0900 +- +-/* Special video modes */ +-#define VIDEO_FIRST_SPECIAL 0x0f00 +-#define VIDEO_80x25 0x0f00 +-#define VIDEO_8POINT 0x0f01 +-#define VIDEO_80x43 0x0f02 +-#define VIDEO_80x28 0x0f03 +-#define VIDEO_CURRENT_MODE 0x0f04 +-#define VIDEO_80x30 0x0f05 +-#define VIDEO_80x34 0x0f06 +-#define VIDEO_80x60 0x0f07 +-#define VIDEO_GFX_HACK 0x0f08 +-#define VIDEO_LAST_SPECIAL 0x0f09 +- +-/* Video modes given by resolution */ +-#define VIDEO_FIRST_RESOLUTION 0x1000 +- +-/* The "recalculate timings" flag */ +-#define VIDEO_RECALC 0x8000 +- +-/* Positions of various video parameters passed to the kernel */ +-/* (see also include/linux/tty.h) */ +-#define PARAM_CURSOR_POS 0x00 +-#define PARAM_VIDEO_PAGE 0x04 +-#define PARAM_VIDEO_MODE 0x06 +-#define PARAM_VIDEO_COLS 0x07 +-#define PARAM_VIDEO_EGA_BX 0x0a +-#define PARAM_VIDEO_LINES 0x0e +-#define PARAM_HAVE_VGA 0x0f +-#define PARAM_FONT_POINTS 0x10 +- +-#define PARAM_LFB_WIDTH 0x12 +-#define PARAM_LFB_HEIGHT 0x14 +-#define PARAM_LFB_DEPTH 0x16 +-#define PARAM_LFB_BASE 0x18 +-#define PARAM_LFB_SIZE 0x1c +-#define PARAM_LFB_LINELENGTH 0x24 +-#define PARAM_LFB_COLORS 0x26 +-#define PARAM_VESAPM_SEG 0x2e +-#define PARAM_VESAPM_OFF 0x30 +-#define PARAM_LFB_PAGES 0x32 +-#define PARAM_VESA_ATTRIB 0x34 +-#define PARAM_CAPABILITIES 0x36 +- +-/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ +-#ifdef CONFIG_VIDEO_RETAIN +-#define DO_STORE call store_screen +-#else +-#define DO_STORE +-#endif /* CONFIG_VIDEO_RETAIN */ +- +-# This is the main entry point called by setup.S +-# %ds *must* be pointing to the bootsector +-video: pushw %ds # We use different segments +- pushw %ds # FS contains original DS +- popw %fs +- pushw %cs # DS is equal to CS +- popw %ds +- pushw %cs # ES is equal to CS +- popw %es +- xorw %ax, %ax +- movw %ax, %gs # GS is zero +- cld +- call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA) +-#ifdef CONFIG_VIDEO_SELECT +- movw %fs:(0x01fa), %ax # User selected video mode +- cmpw $ASK_VGA, %ax # Bring up the menu +- jz vid2 +- +- call mode_set # Set the mode +- jc vid1 +- +- leaw badmdt, %si # Invalid mode ID +- call prtstr +-vid2: call mode_menu +-vid1: +-#ifdef CONFIG_VIDEO_RETAIN +- call restore_screen # Restore screen contents +-#endif /* CONFIG_VIDEO_RETAIN */ +- call store_edid +-#endif /* CONFIG_VIDEO_SELECT */ +- call mode_params # Store mode parameters +- popw %ds # Restore original DS +- ret +- +-# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel. +-basic_detect: +- movb $0, %fs:(PARAM_HAVE_VGA) +- movb $0x12, %ah # Check EGA/VGA +- movb $0x10, %bl +- int $0x10 +- movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel +- cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card. +- je basret +- +- incb adapter +- movw $0x1a00, %ax # Check EGA or VGA? +- int $0x10 +- cmpb $0x1a, %al # 1a means VGA... +- jne basret # anything else is EGA. +- +- incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA +- incb adapter +-basret: ret +- +-# Store the video mode parameters for later usage by the kernel. +-# This is done by asking the BIOS except for the rows/columns +-# parameters in the default 80x25 mode -- these are set directly, +-# because some very obscure BIOSes supply insane values. +-mode_params: +-#ifdef CONFIG_VIDEO_SELECT +- cmpb $0, graphic_mode +- jnz mopar_gr +-#endif +- movb $0x03, %ah # Read cursor position +- xorb %bh, %bh +- int $0x10 +- movw %dx, %fs:(PARAM_CURSOR_POS) +- movb $0x0f, %ah # Read page/mode/width +- int $0x10 +- movw %bx, %fs:(PARAM_VIDEO_PAGE) +- movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width +- cmpb $0x7, %al # MDA/HGA => segment differs +- jnz mopar0 +- +- movw $0xb000, video_segment +-mopar0: movw %gs:(0x485), %ax # Font size +- movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA) +- movw force_size, %ax # Forced size? +- orw %ax, %ax +- jz mopar1 +- +- movb %ah, %fs:(PARAM_VIDEO_COLS) +- movb %al, %fs:(PARAM_VIDEO_LINES) +- ret +- +-mopar1: movb $25, %al +- cmpb $0, adapter # If we are on CGA/MDA/HGA, the +- jz mopar2 # screen must have 25 lines. +- +- movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS +- incb %al # location of max lines. +-mopar2: movb %al, %fs:(PARAM_VIDEO_LINES) +- ret +- +-#ifdef CONFIG_VIDEO_SELECT +-# Fetching of VESA frame buffer parameters +-mopar_gr: +- leaw modelist+1024, %di +- movb $0x23, %fs:(PARAM_HAVE_VGA) +- movw 16(%di), %ax +- movw %ax, %fs:(PARAM_LFB_LINELENGTH) +- movw 18(%di), %ax +- movw %ax, %fs:(PARAM_LFB_WIDTH) +- movw 20(%di), %ax +- movw %ax, %fs:(PARAM_LFB_HEIGHT) +- movb 25(%di), %al +- movb $0, %ah +- movw %ax, %fs:(PARAM_LFB_DEPTH) +- movb 29(%di), %al +- movb $0, %ah +- movw %ax, %fs:(PARAM_LFB_PAGES) +- movl 40(%di), %eax +- movl %eax, %fs:(PARAM_LFB_BASE) +- movl 31(%di), %eax +- movl %eax, %fs:(PARAM_LFB_COLORS) +- movl 35(%di), %eax +- movl %eax, %fs:(PARAM_LFB_COLORS+4) +- movw 0(%di), %ax +- movw %ax, %fs:(PARAM_VESA_ATTRIB) +- +-# get video mem size +- leaw modelist+1024, %di +- movw $0x4f00, %ax +- int $0x10 +- xorl %eax, %eax +- movw 18(%di), %ax +- movl %eax, %fs:(PARAM_LFB_SIZE) +- +-# store mode capabilities +- movl 10(%di), %eax +- movl %eax, %fs:(PARAM_CAPABILITIES) +- +-# switching the DAC to 8-bit is for <= 8 bpp only +- movw %fs:(PARAM_LFB_DEPTH), %ax +- cmpw $8, %ax +- jg dac_done +- +-# get DAC switching capability +- xorl %eax, %eax +- movb 10(%di), %al +- testb $1, %al +- jz dac_set +- +-# attempt to switch DAC to 8-bit +- movw $0x4f08, %ax +- movw $0x0800, %bx +- int $0x10 +- cmpw $0x004f, %ax +- jne dac_set +- movb %bh, dac_size # store actual DAC size +- +-dac_set: +-# set color size to DAC size +- movb dac_size, %al +- movb %al, %fs:(PARAM_LFB_COLORS+0) +- movb %al, %fs:(PARAM_LFB_COLORS+2) +- movb %al, %fs:(PARAM_LFB_COLORS+4) +- movb %al, %fs:(PARAM_LFB_COLORS+6) +- +-# set color offsets to 0 +- movb $0, %fs:(PARAM_LFB_COLORS+1) +- movb $0, %fs:(PARAM_LFB_COLORS+3) +- movb $0, %fs:(PARAM_LFB_COLORS+5) +- movb $0, %fs:(PARAM_LFB_COLORS+7) +- +-dac_done: +-# get protected mode interface informations +- movw $0x4f0a, %ax +- xorw %bx, %bx +- xorw %di, %di +- int $0x10 +- cmp $0x004f, %ax +- jnz no_pm +- +- movw %es, %fs:(PARAM_VESAPM_SEG) +- movw %di, %fs:(PARAM_VESAPM_OFF) +-no_pm: ret +- +-# The video mode menu +-mode_menu: +- leaw keymsg, %si # "Return/Space/Timeout" message +- call prtstr +- call flush +-nokey: call getkt +- +- cmpb $0x0d, %al # ENTER ? +- je listm # yes - manual mode selection +- +- cmpb $0x20, %al # SPACE ? +- je defmd1 # no - repeat +- +- call beep +- jmp nokey +- +-defmd1: ret # No mode chosen? Default 80x25 +- +-listm: call mode_table # List mode table +-listm0: leaw name_bann, %si # Print adapter name +- call prtstr +- movw card_name, %si +- orw %si, %si +- jnz an2 +- +- movb adapter, %al +- leaw old_name, %si +- orb %al, %al +- jz an1 +- +- leaw ega_name, %si +- decb %al +- jz an1 +- +- leaw vga_name, %si +- jmp an1 +- +-an2: call prtstr +- leaw svga_name, %si +-an1: call prtstr +- leaw listhdr, %si # Table header +- call prtstr +- movb $0x30, %dl # DL holds mode number +- leaw modelist, %si +-lm1: cmpw $ASK_VGA, (%si) # End? +- jz lm2 +- +- movb %dl, %al # Menu selection number +- call prtchr +- call prtsp2 +- lodsw +- call prthw # Mode ID +- call prtsp2 +- movb 0x1(%si), %al +- call prtdec # Rows +- movb $0x78, %al # the letter 'x' +- call prtchr +- lodsw +- call prtdec # Columns +- movb $0x0d, %al # New line +- call prtchr +- movb $0x0a, %al +- call prtchr +- incb %dl # Next character +- cmpb $0x3a, %dl +- jnz lm1 +- +- movb $0x61, %dl +- jmp lm1 +- +-lm2: leaw prompt, %si # Mode prompt +- call prtstr +- leaw edit_buf, %di # Editor buffer +-lm3: call getkey +- cmpb $0x0d, %al # Enter? +- jz lment +- +- cmpb $0x08, %al # Backspace? +- jz lmbs +- +- cmpb $0x20, %al # Printable? +- jc lm3 +- +- cmpw $edit_buf+4, %di # Enough space? +- jz lm3 +- +- stosb +- call prtchr +- jmp lm3 +- +-lmbs: cmpw $edit_buf, %di # Backspace +- jz lm3 +- +- decw %di +- movb $0x08, %al +- call prtchr +- call prtspc +- movb $0x08, %al +- call prtchr +- jmp lm3 +- +-lment: movb $0, (%di) +- leaw crlft, %si +- call prtstr +- leaw edit_buf, %si +- cmpb $0, (%si) # Empty string = default mode +- jz lmdef +- +- cmpb $0, 1(%si) # One character = menu selection +- jz mnusel +- +- cmpw $0x6373, (%si) # "scan" => mode scanning +- jnz lmhx +- +- cmpw $0x6e61, 2(%si) +- jz lmscan +- +-lmhx: xorw %bx, %bx # Else => mode ID in hex +-lmhex: lodsb +- orb %al, %al +- jz lmuse1 +- +- subb $0x30, %al +- jc lmbad +- +- cmpb $10, %al +- jc lmhx1 +- +- subb $7, %al +- andb $0xdf, %al +- cmpb $10, %al +- jc lmbad +- +- cmpb $16, %al +- jnc lmbad +- +-lmhx1: shlw $4, %bx +- orb %al, %bl +- jmp lmhex +- +-lmuse1: movw %bx, %ax +- jmp lmuse +- +-mnusel: lodsb # Menu selection +- xorb %ah, %ah +- subb $0x30, %al +- jc lmbad +- +- cmpb $10, %al +- jc lmuse +- +- cmpb $0x61-0x30, %al +- jc lmbad +- +- subb $0x61-0x30-10, %al +- cmpb $36, %al +- jnc lmbad +- +-lmuse: call mode_set +- jc lmdef +- +-lmbad: leaw unknt, %si +- call prtstr +- jmp lm2 +-lmscan: cmpb $0, adapter # Scanning only on EGA/VGA +- jz lmbad +- +- movw $0, mt_end # Scanning of modes is +- movb $1, scanning # done as new autodetection. +- call mode_table +- jmp listm0 +-lmdef: ret +- +-# Additional parts of mode_set... (relative jumps, you know) +-setv7: # Video7 extended modes +- DO_STORE +- subb $VIDEO_FIRST_V7>>8, %bh +- movw $0x6f05, %ax +- int $0x10 +- stc +- ret +- +-_setrec: jmp setrec # Ugly... +-_set_80x25: jmp set_80x25 +- +-# Aliases for backward compatibility. +-setalias: +- movw $VIDEO_80x25, %ax +- incw %bx +- jz mode_set +- +- movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al +- incw %bx +- jnz setbad # Fall-through! +- +-# Setting of user mode (AX=mode ID) => CF=success +-mode_set: +- movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S +- movw %ax, %bx +- cmpb $0xff, %ah +- jz setalias +- +- testb $VIDEO_RECALC>>8, %ah +- jnz _setrec +- +- cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah +- jnc setres +- +- cmpb $VIDEO_FIRST_SPECIAL>>8, %ah +- jz setspc +- +- cmpb $VIDEO_FIRST_V7>>8, %ah +- jz setv7 +- +- cmpb $VIDEO_FIRST_VESA>>8, %ah +- jnc check_vesa +- +- orb %ah, %ah +- jz setmenu +- +- decb %ah +- jz setbios +- +-setbad: clc +- movb $0, do_restore # The screen needn't be restored +- ret +- +-setvesa: +- DO_STORE +- subb $VIDEO_FIRST_VESA>>8, %bh +- movw $0x4f02, %ax # VESA BIOS mode set call +- int $0x10 +- cmpw $0x004f, %ax # AL=4f if implemented +- jnz setbad # AH=0 if OK +- +- stc +- ret +- +-setbios: +- DO_STORE +- int $0x10 # Standard BIOS mode set call +- pushw %bx +- movb $0x0f, %ah # Check if really set +- int $0x10 +- popw %bx +- cmpb %bl, %al +- jnz setbad +- +- stc +- ret +- +-setspc: xorb %bh, %bh # Set special mode +- cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl +- jnc setbad +- +- addw %bx, %bx +- jmp *spec_inits(%bx) +- +-setmenu: +- orb %al, %al # 80x25 is an exception +- jz _set_80x25 +- +- pushw %bx # Set mode chosen from menu +- call mode_table # Build the mode table +- popw %ax +- shlw $2, %ax +- addw %ax, %si +- cmpw %di, %si +- jnc setbad +- +- movw (%si), %ax # Fetch mode ID +-_m_s: jmp mode_set +- +-setres: pushw %bx # Set mode chosen by resolution +- call mode_table +- popw %bx +- xchgb %bl, %bh +-setr1: lodsw +- cmpw $ASK_VGA, %ax # End of the list? +- jz setbad +- +- lodsw +- cmpw %bx, %ax +- jnz setr1 +- +- movw -4(%si), %ax # Fetch mode ID +- jmp _m_s +- +-check_vesa: +-#ifdef CONFIG_FIRMWARE_EDID +- leaw modelist+1024, %di +- movw $0x4f00, %ax +- int $0x10 +- cmpw $0x004f, %ax +- jnz setbad +- +- movw 4(%di), %ax +- movw %ax, vbe_version +-#endif +- leaw modelist+1024, %di +- subb $VIDEO_FIRST_VESA>>8, %bh +- movw %bx, %cx # Get mode information structure +- movw $0x4f01, %ax +- int $0x10 +- addb $VIDEO_FIRST_VESA>>8, %bh +- cmpw $0x004f, %ax +- jnz setbad +- +- movb (%di), %al # Check capabilities. +- andb $0x19, %al +- cmpb $0x09, %al +- jz setvesa # This is a text mode +- +- movb (%di), %al # Check capabilities. +- andb $0x99, %al +- cmpb $0x99, %al +- jnz _setbad # Doh! No linear frame buffer. +- +- subb $VIDEO_FIRST_VESA>>8, %bh +- orw $0x4000, %bx # Use linear frame buffer +- movw $0x4f02, %ax # VESA BIOS mode set call +- int $0x10 +- cmpw $0x004f, %ax # AL=4f if implemented +- jnz _setbad # AH=0 if OK +- +- movb $1, graphic_mode # flag graphic mode +- movb $0, do_restore # no screen restore +- stc +- ret +- +-_setbad: jmp setbad # Ugly... +- +-# Recalculate vertical display end registers -- this fixes various +-# inconsistencies of extended modes on many adapters. Called when +-# the VIDEO_RECALC flag is set in the mode ID. +- +-setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode +- call mode_set +- jnc rct3 +- +- movw %gs:(0x485), %ax # Font size in pixels +- movb %gs:(0x484), %bl # Number of rows +- incb %bl +- mulb %bl # Number of visible +- decw %ax # scan lines - 1 +- movw $0x3d4, %dx +- movw %ax, %bx +- movb $0x12, %al # Lower 8 bits +- movb %bl, %ah +- outw %ax, %dx +- movb $0x07, %al # Bits 8 and 9 in the overflow register +- call inidx +- xchgb %al, %ah +- andb $0xbd, %ah +- shrb %bh +- jnc rct1 +- orb $0x02, %ah +-rct1: shrb %bh +- jnc rct2 +- orb $0x40, %ah +-rct2: movb $0x07, %al +- outw %ax, %dx +- stc +-rct3: ret +- +-# Table of routines for setting of the special modes. +-spec_inits: +- .word set_80x25 +- .word set_8pixel +- .word set_80x43 +- .word set_80x28 +- .word set_current +- .word set_80x30 +- .word set_80x34 +- .word set_80x60 +- .word set_gfx +- +-# Set the 80x25 mode. If already set, do nothing. +-set_80x25: +- movw $0x5019, force_size # Override possibly broken BIOS +-use_80x25: +-#ifdef CONFIG_VIDEO_400_HACK +- movw $0x1202, %ax # Force 400 scan lines +- movb $0x30, %bl +- int $0x10 +-#else +- movb $0x0f, %ah # Get current mode ID +- int $0x10 +- cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available +- jz st80 # on CGA/MDA/HGA and is also available on EGAM +- +- cmpw $0x5003, %ax # Unknown mode, force 80x25 color +- jnz force3 +- +-st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25 +- jz set80 +- +- movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc. +- orb %al, %al # Some buggy BIOS'es set 0 rows +- jz set80 +- +- cmpb $24, %al # It's hopefully correct +- jz set80 +-#endif /* CONFIG_VIDEO_400_HACK */ +-force3: DO_STORE +- movw $0x0003, %ax # Forced set +- int $0x10 +-set80: stc +- ret +- +-# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls. +-set_8pixel: +- DO_STORE +- call use_80x25 # The base is 80x25 +-set_8pt: +- movw $0x1112, %ax # Use 8x8 font +- xorb %bl, %bl +- int $0x10 +- movw $0x1200, %ax # Use alternate print screen +- movb $0x20, %bl +- int $0x10 +- movw $0x1201, %ax # Turn off cursor emulation +- movb $0x34, %bl +- int $0x10 +- movb $0x01, %ah # Define cursor scan lines 6-7 +- movw $0x0607, %cx +- int $0x10 +-set_current: +- stc +- ret +- +-# Set the 80x28 mode. This mode works on all VGA's, because it's a standard +-# 80x25 mode with 14-point fonts instead of 16-point. +-set_80x28: +- DO_STORE +- call use_80x25 # The base is 80x25 +-set14: movw $0x1111, %ax # Use 9x14 font +- xorb %bl, %bl +- int $0x10 +- movb $0x01, %ah # Define cursor scan lines 11-12 +- movw $0x0b0c, %cx +- int $0x10 +- stc +- ret +- +-# Set the 80x43 mode. This mode is works on all VGA's. +-# It's a 350-scanline mode with 8-pixel font. +-set_80x43: +- DO_STORE +- movw $0x1201, %ax # Set 350 scans +- movb $0x30, %bl +- int $0x10 +- movw $0x0003, %ax # Reset video mode +- int $0x10 +- jmp set_8pt # Use 8-pixel font +- +-# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font. +-set_80x30: +- call use_80x25 # Start with real 80x25 +- DO_STORE +- movw $0x3cc, %dx # Get CRTC port +- inb %dx, %al +- movb $0xd4, %dl +- rorb %al # Mono or color? +- jc set48a +- +- movb $0xb4, %dl +-set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7) +- call outidx +- movw $0x0b06, %ax # Vertical total +- call outidx +- movw $0x3e07, %ax # (Vertical) overflow +- call outidx +- movw $0xea10, %ax # Vertical sync start +- call outidx +- movw $0xdf12, %ax # Vertical display end +- call outidx +- movw $0xe715, %ax # Vertical blank start +- call outidx +- movw $0x0416, %ax # Vertical blank end +- call outidx +- pushw %dx +- movb $0xcc, %dl # Misc output register (read) +- inb %dx, %al +- movb $0xc2, %dl # (write) +- andb $0x0d, %al # Preserve clock select bits and color bit +- orb $0xe2, %al # Set correct sync polarity +- outb %al, %dx +- popw %dx +- movw $0x501e, force_size +- stc # That's all. +- ret +- +-# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font. +-set_80x34: +- call set_80x30 # Set 480 scans +- call set14 # And 14-pt font +- movw $0xdb12, %ax # VGA vertical display end +- movw $0x5022, force_size +-setvde: call outidx +- stc +- ret +- +-# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font. +-set_80x60: +- call set_80x30 # Set 480 scans +- call set_8pt # And 8-pt font +- movw $0xdf12, %ax # VGA vertical display end +- movw $0x503c, force_size +- jmp setvde +- +-# Special hack for ThinkPad graphics +-set_gfx: +-#ifdef CONFIG_VIDEO_GFX_HACK +- movw $VIDEO_GFX_BIOS_AX, %ax +- movw $VIDEO_GFX_BIOS_BX, %bx +- int $0x10 +- movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size +- stc +-#endif +- ret +- +-#ifdef CONFIG_VIDEO_RETAIN +- +-# Store screen contents to temporary buffer. +-store_screen: +- cmpb $0, do_restore # Already stored? +- jnz stsr +- +- testb $CAN_USE_HEAP, loadflags # Have we space for storing? +- jz stsr +- +- pushw %ax +- pushw %bx +- pushw force_size # Don't force specific size +- movw $0, force_size +- call mode_params # Obtain params of current mode +- popw force_size +- movb %fs:(PARAM_VIDEO_LINES), %ah +- movb %fs:(PARAM_VIDEO_COLS), %al +- movw %ax, %bx # BX=dimensions +- mulb %ah +- movw %ax, %cx # CX=number of characters +- addw %ax, %ax # Calculate image size +- addw $modelist+1024+4, %ax +- cmpw heap_end_ptr, %ax +- jnc sts1 # Unfortunately, out of memory +- +- movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params +- leaw modelist+1024, %di +- stosw +- movw %bx, %ax +- stosw +- pushw %ds # Store the screen +- movw video_segment, %ds +- xorw %si, %si +- rep +- movsw +- popw %ds +- incb do_restore # Screen will be restored later +-sts1: popw %bx +- popw %ax +-stsr: ret +- +-# Restore screen contents from temporary buffer. +-restore_screen: +- cmpb $0, do_restore # Has the screen been stored? +- jz res1 +- +- call mode_params # Get parameters of current mode +- movb %fs:(PARAM_VIDEO_LINES), %cl +- movb %fs:(PARAM_VIDEO_COLS), %ch +- leaw modelist+1024, %si # Screen buffer +- lodsw # Set cursor position +- movw %ax, %dx +- cmpb %cl, %dh +- jc res2 +- +- movb %cl, %dh +- decb %dh +-res2: cmpb %ch, %dl +- jc res3 +- +- movb %ch, %dl +- decb %dl +-res3: movb $0x02, %ah +- movb $0x00, %bh +- int $0x10 +- lodsw # Display size +- movb %ah, %dl # DL=number of lines +- movb $0, %ah # BX=phys. length of orig. line +- movw %ax, %bx +- cmpb %cl, %dl # Too many? +- jc res4 +- +- pushw %ax +- movb %dl, %al +- subb %cl, %al +- mulb %bl +- addw %ax, %si +- addw %ax, %si +- popw %ax +- movb %cl, %dl +-res4: cmpb %ch, %al # Too wide? +- jc res5 +- +- movb %ch, %al # AX=width of src. line +-res5: movb $0, %cl +- xchgb %ch, %cl +- movw %cx, %bp # BP=width of dest. line +- pushw %es +- movw video_segment, %es +- xorw %di, %di # Move the data +- addw %bx, %bx # Convert BX and BP to _bytes_ +- addw %bp, %bp +-res6: pushw %si +- pushw %di +- movw %ax, %cx +- rep +- movsw +- popw %di +- popw %si +- addw %bp, %di +- addw %bx, %si +- decb %dl +- jnz res6 +- +- popw %es # Done +-res1: ret +-#endif /* CONFIG_VIDEO_RETAIN */ +- +-# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port) +-outidx: outb %al, %dx +- pushw %ax +- movb %ah, %al +- incw %dx +- outb %al, %dx +- decw %dx +- popw %ax +- ret +- +-# Build the table of video modes (stored after the setup.S code at the +-# `modelist' label. Each video mode record looks like: +-# .word MODE-ID (our special mode ID (see above)) +-# .byte rows (number of rows) +-# .byte columns (number of columns) +-# Returns address of the end of the table in DI, the end is marked +-# with a ASK_VGA ID. +-mode_table: +- movw mt_end, %di # Already filled? +- orw %di, %di +- jnz mtab1x +- +- leaw modelist, %di # Store standard modes: +- movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL) +- stosl +- movb adapter, %al # CGA/MDA/HGA -- no more modes +- orb %al, %al +- jz mtabe +- +- decb %al +- jnz mtabv +- +- movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode +- stosl +- jmp mtabe +- +-mtab1x: jmp mtab1 +- +-mtabv: leaw vga_modes, %si # All modes for std VGA +- movw $vga_modes_end-vga_modes, %cx +- rep # I'm unable to use movsw as I don't know how to store a half +- movsb # of the expression above to cx without using explicit shr. +- +- cmpb $0, scanning # Mode scan requested? +- jz mscan1 +- +- call mode_scan +-mscan1: +- +-#ifdef CONFIG_VIDEO_LOCAL +- call local_modes +-#endif /* CONFIG_VIDEO_LOCAL */ +- +-#ifdef CONFIG_VIDEO_VESA +- call vesa_modes # Detect VESA VGA modes +-#endif /* CONFIG_VIDEO_VESA */ +- +-#ifdef CONFIG_VIDEO_SVGA +- cmpb $0, scanning # Bypass when scanning +- jnz mscan2 +- +- call svga_modes # Detect SVGA cards & modes +-mscan2: +-#endif /* CONFIG_VIDEO_SVGA */ +- +-mtabe: +- +-#ifdef CONFIG_VIDEO_COMPACT +- leaw modelist, %si +- movw %di, %dx +- movw %si, %di +-cmt1: cmpw %dx, %si # Scan all modes +- jz cmt2 +- +- leaw modelist, %bx # Find in previous entries +- movw 2(%si), %cx +-cmt3: cmpw %bx, %si +- jz cmt4 +- +- cmpw 2(%bx), %cx # Found => don't copy this entry +- jz cmt5 +- +- addw $4, %bx +- jmp cmt3 +- +-cmt4: movsl # Copy entry +- jmp cmt1 +- +-cmt5: addw $4, %si # Skip entry +- jmp cmt1 +- +-cmt2: +-#endif /* CONFIG_VIDEO_COMPACT */ +- +- movw $ASK_VGA, (%di) # End marker +- movw %di, mt_end +-mtab1: leaw modelist, %si # SI=mode list, DI=list end +-ret0: ret +- +-# Modes usable on all standard VGAs +-vga_modes: +- .word VIDEO_8POINT +- .word 0x5032 # 80x50 +- .word VIDEO_80x43 +- .word 0x502b # 80x43 +- .word VIDEO_80x28 +- .word 0x501c # 80x28 +- .word VIDEO_80x30 +- .word 0x501e # 80x30 +- .word VIDEO_80x34 +- .word 0x5022 # 80x34 +- .word VIDEO_80x60 +- .word 0x503c # 80x60 +-#ifdef CONFIG_VIDEO_GFX_HACK +- .word VIDEO_GFX_HACK +- .word VIDEO_GFX_DUMMY_RESOLUTION +-#endif +- +-vga_modes_end: +-# Detect VESA modes. +- +-#ifdef CONFIG_VIDEO_VESA +-vesa_modes: +- cmpb $2, adapter # VGA only +- jnz ret0 +- +- movw %di, %bp # BP=original mode table end +- addw $0x200, %di # Buffer space +- movw $0x4f00, %ax # VESA Get card info call +- int $0x10 +- movw %bp, %di +- cmpw $0x004f, %ax # Successful? +- jnz ret0 +- +- cmpw $0x4556, 0x200(%di) +- jnz ret0 +- +- cmpw $0x4153, 0x202(%di) +- jnz ret0 +- +- movw $vesa_name, card_name # Set name to "VESA VGA" +- pushw %gs +- lgsw 0x20e(%di), %si # GS:SI=mode list +- movw $128, %cx # Iteration limit +-vesa1: +-# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst. +-# XXX: lodsw %gs:(%si), %ax # Get next mode in the list +- gs; lodsw +- cmpw $0xffff, %ax # End of the table? +- jz vesar +- +- cmpw $0x0080, %ax # Check validity of mode ID +- jc vesa2 +- +- orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff +- jz vesan # Certain BIOSes report 0x80-0xff! +- +- cmpw $0x0800, %ax +- jnc vesae +- +-vesa2: pushw %cx +- movw %ax, %cx # Get mode information structure +- movw $0x4f01, %ax +- int $0x10 +- movw %cx, %bx # BX=mode number +- addb $VIDEO_FIRST_VESA>>8, %bh +- popw %cx +- cmpw $0x004f, %ax +- jnz vesan # Don't report errors (buggy BIOSES) +- +- movb (%di), %al # Check capabilities. We require +- andb $0x19, %al # a color text mode. +- cmpb $0x09, %al +- jnz vesan +- +- cmpw $0xb800, 8(%di) # Standard video memory address required +- jnz vesan +- +- testb $2, (%di) # Mode characteristics supplied? +- movw %bx, (%di) # Store mode number +- jz vesa3 +- +- xorw %dx, %dx +- movw 0x12(%di), %bx # Width +- orb %bh, %bh +- jnz vesan +- +- movb %bl, 0x3(%di) +- movw 0x14(%di), %ax # Height +- orb %ah, %ah +- jnz vesan +- +- movb %al, 2(%di) +- mulb %bl +- cmpw $8193, %ax # Small enough for Linux console driver? +- jnc vesan +- +- jmp vesaok +- +-vesa3: subw $0x8108, %bx # This mode has no detailed info specified, +- jc vesan # so it must be a standard VESA mode. +- +- cmpw $5, %bx +- jnc vesan +- +- movw vesa_text_mode_table(%bx), %ax +- movw %ax, 2(%di) +-vesaok: addw $4, %di # The mode is valid. Store it. +-vesan: loop vesa1 # Next mode. Limit exceeded => error +-vesae: leaw vesaer, %si +- call prtstr +- movw %bp, %di # Discard already found modes. +-vesar: popw %gs +- ret +- +-# Dimensions of standard VESA text modes +-vesa_text_mode_table: +- .byte 60, 80 # 0108 +- .byte 25, 132 # 0109 +- .byte 43, 132 # 010A +- .byte 50, 132 # 010B +- .byte 60, 132 # 010C +-#endif /* CONFIG_VIDEO_VESA */ +- +-# Scan for video modes. A bit dirty, but should work. +-mode_scan: +- movw $0x0100, %cx # Start with mode 0 +-scm1: movb $0, %ah # Test the mode +- movb %cl, %al +- int $0x10 +- movb $0x0f, %ah +- int $0x10 +- cmpb %cl, %al +- jnz scm2 # Mode not set +- +- movw $0x3c0, %dx # Test if it's a text mode +- movb $0x10, %al # Mode bits +- call inidx +- andb $0x03, %al +- jnz scm2 +- +- movb $0xce, %dl # Another set of mode bits +- movb $0x06, %al +- call inidx +- shrb %al +- jc scm2 +- +- movb $0xd4, %dl # Cursor location +- movb $0x0f, %al +- call inidx +- orb %al, %al +- jnz scm2 +- +- movw %cx, %ax # Ok, store the mode +- stosw +- movb %gs:(0x484), %al # Number of rows +- incb %al +- stosb +- movw %gs:(0x44a), %ax # Number of columns +- stosb +-scm2: incb %cl +- jns scm1 +- +- movw $0x0003, %ax # Return back to mode 3 +- int $0x10 +- ret +- +-tstidx: outw %ax, %dx # OUT DX,AX and inidx +-inidx: outb %al, %dx # Read from indexed VGA register +- incw %dx # AL=index, DX=index reg port -> AL=data +- inb %dx, %al +- decw %dx +- ret +- +-# Try to detect type of SVGA card and supply (usually approximate) video +-# mode table for it. +- +-#ifdef CONFIG_VIDEO_SVGA +-svga_modes: +- leaw svga_table, %si # Test all known SVGA adapters +-dosvga: lodsw +- movw %ax, %bp # Default mode table +- orw %ax, %ax +- jz didsv1 +- +- lodsw # Pointer to test routine +- pushw %si +- pushw %di +- pushw %es +- movw $0xc000, %bx +- movw %bx, %es +- call *%ax # Call test routine +- popw %es +- popw %di +- popw %si +- orw %bp, %bp +- jz dosvga +- +- movw %bp, %si # Found, copy the modes +- movb svga_prefix, %ah +-cpsvga: lodsb +- orb %al, %al +- jz didsv +- +- stosw +- movsw +- jmp cpsvga +- +-didsv: movw %si, card_name # Store pointer to card name +-didsv1: ret +- +-# Table of all known SVGA cards. For each card, we store a pointer to +-# a table of video modes supported by the card and a pointer to a routine +-# used for testing of presence of the card. The video mode table is always +-# followed by the name of the card or the chipset. +-svga_table: +- .word ati_md, ati_test +- .word oak_md, oak_test +- .word paradise_md, paradise_test +- .word realtek_md, realtek_test +- .word s3_md, s3_test +- .word chips_md, chips_test +- .word video7_md, video7_test +- .word cirrus5_md, cirrus5_test +- .word cirrus6_md, cirrus6_test +- .word cirrus1_md, cirrus1_test +- .word ahead_md, ahead_test +- .word everex_md, everex_test +- .word genoa_md, genoa_test +- .word trident_md, trident_test +- .word tseng_md, tseng_test +- .word 0 +- +-# Test routines and mode tables: +- +-# S3 - The test algorithm was taken from the SuperProbe package +-# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org +-s3_test: +- movw $0x0f35, %cx # we store some constants in cl/ch +- movw $0x03d4, %dx +- movb $0x38, %al +- call inidx +- movb %al, %bh # store current CRT-register 0x38 +- movw $0x0038, %ax +- call outidx # disable writing to special regs +- movb %cl, %al # check whether we can write special reg 0x35 +- call inidx +- movb %al, %bl # save the current value of CRT reg 0x35 +- andb $0xf0, %al # clear bits 0-3 +- movb %al, %ah +- movb %cl, %al # and write it to CRT reg 0x35 +- call outidx +- call inidx # now read it back +- andb %ch, %al # clear the upper 4 bits +- jz s3_2 # the first test failed. But we have a +- +- movb %bl, %ah # second chance +- movb %cl, %al +- call outidx +- jmp s3_1 # do the other tests +- +-s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35 +- orb %bl, %ah # set the upper 4 bits of ah with the orig value +- call outidx # write ... +- call inidx # ... and reread +- andb %cl, %al # turn off the upper 4 bits +- pushw %ax +- movb %bl, %ah # restore old value in register 0x35 +- movb %cl, %al +- call outidx +- popw %ax +- cmpb %ch, %al # setting lower 4 bits was successful => bad +- je no_s3 # writing is allowed => this is not an S3 +- +-s3_1: movw $0x4838, %ax # allow writing to special regs by putting +- call outidx # magic number into CRT-register 0x38 +- movb %cl, %al # check whether we can write special reg 0x35 +- call inidx +- movb %al, %bl +- andb $0xf0, %al +- movb %al, %ah +- movb %cl, %al +- call outidx +- call inidx +- andb %ch, %al +- jnz no_s3 # no, we can't write => no S3 +- +- movw %cx, %ax +- orb %bl, %ah +- call outidx +- call inidx +- andb %ch, %al +- pushw %ax +- movb %bl, %ah # restore old value in register 0x35 +- movb %cl, %al +- call outidx +- popw %ax +- cmpb %ch, %al +- jne no_s31 # writing not possible => no S3 +- movb $0x30, %al +- call inidx # now get the S3 id ... +- leaw idS3, %di +- movw $0x10, %cx +- repne +- scasb +- je no_s31 +- +- movb %bh, %ah +- movb $0x38, %al +- jmp s3rest +- +-no_s3: movb $0x35, %al # restore CRT register 0x35 +- movb %bl, %ah +- call outidx +-no_s31: xorw %bp, %bp # Detection failed +-s3rest: movb %bh, %ah +- movb $0x38, %al # restore old value of CRT register 0x38 +- jmp outidx +- +-idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95 +- .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0 +- +-s3_md: .byte 0x54, 0x2b, 0x84 +- .byte 0x55, 0x19, 0x84 +- .byte 0 +- .ascii "S3" +- .byte 0 +- +-# ATI cards. +-ati_test: +- leaw idati, %si +- movw $0x31, %di +- movw $0x09, %cx +- repe +- cmpsb +- je atiok +- +- xorw %bp, %bp +-atiok: ret +- +-idati: .ascii "761295520" +- +-ati_md: .byte 0x23, 0x19, 0x84 +- .byte 0x33, 0x2c, 0x84 +- .byte 0x22, 0x1e, 0x64 +- .byte 0x21, 0x19, 0x64 +- .byte 0x58, 0x21, 0x50 +- .byte 0x5b, 0x1e, 0x50 +- .byte 0 +- .ascii "ATI" +- .byte 0 +- +-# AHEAD +-ahead_test: +- movw $0x200f, %ax +- movw $0x3ce, %dx +- outw %ax, %dx +- incw %dx +- inb %dx, %al +- cmpb $0x20, %al +- je isahed +- +- cmpb $0x21, %al +- je isahed +- +- xorw %bp, %bp +-isahed: ret +- +-ahead_md: +- .byte 0x22, 0x2c, 0x84 +- .byte 0x23, 0x19, 0x84 +- .byte 0x24, 0x1c, 0x84 +- .byte 0x2f, 0x32, 0xa0 +- .byte 0x32, 0x22, 0x50 +- .byte 0x34, 0x42, 0x50 +- .byte 0 +- .ascii "Ahead" +- .byte 0 +- +-# Chips & Tech. +-chips_test: +- movw $0x3c3, %dx +- inb %dx, %al +- orb $0x10, %al +- outb %al, %dx +- movw $0x104, %dx +- inb %dx, %al +- movb %al, %bl +- movw $0x3c3, %dx +- inb %dx, %al +- andb $0xef, %al +- outb %al, %dx +- cmpb $0xa5, %bl +- je cantok +- +- xorw %bp, %bp +-cantok: ret +- +-chips_md: +- .byte 0x60, 0x19, 0x84 +- .byte 0x61, 0x32, 0x84 +- .byte 0 +- .ascii "Chips & Technologies" +- .byte 0 +- +-# Cirrus Logic 5X0 +-cirrus1_test: +- movw $0x3d4, %dx +- movb $0x0c, %al +- outb %al, %dx +- incw %dx +- inb %dx, %al +- movb %al, %bl +- xorb %al, %al +- outb %al, %dx +- decw %dx +- movb $0x1f, %al +- outb %al, %dx +- incw %dx +- inb %dx, %al +- movb %al, %bh +- xorb %ah, %ah +- shlb $4, %al +- movw %ax, %cx +- movb %bh, %al +- shrb $4, %al +- addw %ax, %cx +- shlw $8, %cx +- addw $6, %cx +- movw %cx, %ax +- movw $0x3c4, %dx +- outw %ax, %dx +- incw %dx +- inb %dx, %al +- andb %al, %al +- jnz nocirr +- +- movb %bh, %al +- outb %al, %dx +- inb %dx, %al +- cmpb $0x01, %al +- je iscirr +- +-nocirr: xorw %bp, %bp +-iscirr: movw $0x3d4, %dx +- movb %bl, %al +- xorb %ah, %ah +- shlw $8, %ax +- addw $0x0c, %ax +- outw %ax, %dx +- ret +- +-cirrus1_md: +- .byte 0x1f, 0x19, 0x84 +- .byte 0x20, 0x2c, 0x84 +- .byte 0x22, 0x1e, 0x84 +- .byte 0x31, 0x25, 0x64 +- .byte 0 +- .ascii "Cirrus Logic 5X0" +- .byte 0 +- +-# Cirrus Logic 54XX +-cirrus5_test: +- movw $0x3c4, %dx +- movb $6, %al +- call inidx +- movb %al, %bl # BL=backup +- movw $6, %ax +- call tstidx +- cmpb $0x0f, %al +- jne c5fail +- +- movw $0x1206, %ax +- call tstidx +- cmpb $0x12, %al +- jne c5fail +- +- movb $0x1e, %al +- call inidx +- movb %al, %bh +- movb %bh, %ah +- andb $0xc0, %ah +- movb $0x1e, %al +- call tstidx +- andb $0x3f, %al +- jne c5xx +- +- movb $0x1e, %al +- movb %bh, %ah +- orb $0x3f, %ah +- call tstidx +- xorb $0x3f, %al +- andb $0x3f, %al +-c5xx: pushf +- movb $0x1e, %al +- movb %bh, %ah +- outw %ax, %dx +- popf +- je c5done +- +-c5fail: xorw %bp, %bp +-c5done: movb $6, %al +- movb %bl, %ah +- outw %ax, %dx +- ret +- +-cirrus5_md: +- .byte 0x14, 0x19, 0x84 +- .byte 0x54, 0x2b, 0x84 +- .byte 0 +- .ascii "Cirrus Logic 54XX" +- .byte 0 +- +-# Cirrus Logic 64XX -- no known extra modes, but must be identified, because +-# it's misidentified by the Ahead test. +-cirrus6_test: +- movw $0x3ce, %dx +- movb $0x0a, %al +- call inidx +- movb %al, %bl # BL=backup +- movw $0xce0a, %ax +- call tstidx +- orb %al, %al +- jne c2fail +- +- movw $0xec0a, %ax +- call tstidx +- cmpb $0x01, %al +- jne c2fail +- +- movb $0xaa, %al +- call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's. +- shrb $4, %al +- subb $4, %al +- jz c6done +- +- decb %al +- jz c6done +- +- subb $2, %al +- jz c6done +- +- decb %al +- jz c6done +- +-c2fail: xorw %bp, %bp +-c6done: movb $0x0a, %al +- movb %bl, %ah +- outw %ax, %dx +- ret +- +-cirrus6_md: +- .byte 0 +- .ascii "Cirrus Logic 64XX" +- .byte 0 +- +-# Everex / Trident +-everex_test: +- movw $0x7000, %ax +- xorw %bx, %bx +- int $0x10 +- cmpb $0x70, %al +- jne noevrx +- +- shrw $4, %dx +- cmpw $0x678, %dx +- je evtrid +- +- cmpw $0x236, %dx +- jne evrxok +- +-evtrid: leaw trident_md, %bp +-evrxok: ret +- +-noevrx: xorw %bp, %bp +- ret +- +-everex_md: +- .byte 0x03, 0x22, 0x50 +- .byte 0x04, 0x3c, 0x50 +- .byte 0x07, 0x2b, 0x64 +- .byte 0x08, 0x4b, 0x64 +- .byte 0x0a, 0x19, 0x84 +- .byte 0x0b, 0x2c, 0x84 +- .byte 0x16, 0x1e, 0x50 +- .byte 0x18, 0x1b, 0x64 +- .byte 0x21, 0x40, 0xa0 +- .byte 0x40, 0x1e, 0x84 +- .byte 0 +- .ascii "Everex/Trident" +- .byte 0 +- +-# Genoa. +-genoa_test: +- leaw idgenoa, %si # Check Genoa 'clues' +- xorw %ax, %ax +- movb %es:(0x37), %al +- movw %ax, %di +- movw $0x04, %cx +- decw %si +- decw %di +-l1: incw %si +- incw %di +- movb (%si), %al +- testb %al, %al +- jz l2 +- +- cmpb %es:(%di), %al +-l2: loope l1 +- orw %cx, %cx +- je isgen +- +- xorw %bp, %bp +-isgen: ret +- +-idgenoa: .byte 0x77, 0x00, 0x99, 0x66 +- +-genoa_md: +- .byte 0x58, 0x20, 0x50 +- .byte 0x5a, 0x2a, 0x64 +- .byte 0x60, 0x19, 0x84 +- .byte 0x61, 0x1d, 0x84 +- .byte 0x62, 0x20, 0x84 +- .byte 0x63, 0x2c, 0x84 +- .byte 0x64, 0x3c, 0x84 +- .byte 0x6b, 0x4f, 0x64 +- .byte 0x72, 0x3c, 0x50 +- .byte 0x74, 0x42, 0x50 +- .byte 0x78, 0x4b, 0x64 +- .byte 0 +- .ascii "Genoa" +- .byte 0 +- +-# OAK +-oak_test: +- leaw idoakvga, %si +- movw $0x08, %di +- movw $0x08, %cx +- repe +- cmpsb +- je isoak +- +- xorw %bp, %bp +-isoak: ret +- +-idoakvga: .ascii "OAK VGA " +- +-oak_md: .byte 0x4e, 0x3c, 0x50 +- .byte 0x4f, 0x3c, 0x84 +- .byte 0x50, 0x19, 0x84 +- .byte 0x51, 0x2b, 0x84 +- .byte 0 +- .ascii "OAK" +- .byte 0 +- +-# WD Paradise. +-paradise_test: +- leaw idparadise, %si +- movw $0x7d, %di +- movw $0x04, %cx +- repe +- cmpsb +- je ispara +- +- xorw %bp, %bp +-ispara: ret +- +-idparadise: .ascii "VGA=" +- +-paradise_md: +- .byte 0x41, 0x22, 0x50 +- .byte 0x47, 0x1c, 0x84 +- .byte 0x55, 0x19, 0x84 +- .byte 0x54, 0x2c, 0x84 +- .byte 0 +- .ascii "Paradise" +- .byte 0 +- +-# Trident. +-trident_test: +- movw $0x3c4, %dx +- movb $0x0e, %al +- outb %al, %dx +- incw %dx +- inb %dx, %al +- xchgb %al, %ah +- xorb %al, %al +- outb %al, %dx +- inb %dx, %al +- xchgb %ah, %al +- movb %al, %bl # Strange thing ... in the book this wasn't +- andb $0x02, %bl # necessary but it worked on my card which +- jz setb2 # is a trident. Without it the screen goes +- # blurred ... +- andb $0xfd, %al +- jmp clrb2 +- +-setb2: orb $0x02, %al +-clrb2: outb %al, %dx +- andb $0x0f, %ah +- cmpb $0x02, %ah +- je istrid +- +- xorw %bp, %bp +-istrid: ret +- +-trident_md: +- .byte 0x50, 0x1e, 0x50 +- .byte 0x51, 0x2b, 0x50 +- .byte 0x52, 0x3c, 0x50 +- .byte 0x57, 0x19, 0x84 +- .byte 0x58, 0x1e, 0x84 +- .byte 0x59, 0x2b, 0x84 +- .byte 0x5a, 0x3c, 0x84 +- .byte 0 +- .ascii "Trident" +- .byte 0 +- +-# Tseng. +-tseng_test: +- movw $0x3cd, %dx +- inb %dx, %al # Could things be this simple ! :-) +- movb %al, %bl +- movb $0x55, %al +- outb %al, %dx +- inb %dx, %al +- movb %al, %ah +- movb %bl, %al +- outb %al, %dx +- cmpb $0x55, %ah +- je istsen +- +-isnot: xorw %bp, %bp +-istsen: ret +- +-tseng_md: +- .byte 0x26, 0x3c, 0x50 +- .byte 0x2a, 0x28, 0x64 +- .byte 0x23, 0x19, 0x84 +- .byte 0x24, 0x1c, 0x84 +- .byte 0x22, 0x2c, 0x84 +- .byte 0x21, 0x3c, 0x84 +- .byte 0 +- .ascii "Tseng" +- .byte 0 +- +-# Video7. +-video7_test: +- movw $0x3cc, %dx +- inb %dx, %al +- movw $0x3b4, %dx +- andb $0x01, %al +- jz even7 +- +- movw $0x3d4, %dx +-even7: movb $0x0c, %al +- outb %al, %dx +- incw %dx +- inb %dx, %al +- movb %al, %bl +- movb $0x55, %al +- outb %al, %dx +- inb %dx, %al +- decw %dx +- movb $0x1f, %al +- outb %al, %dx +- incw %dx +- inb %dx, %al +- movb %al, %bh +- decw %dx +- movb $0x0c, %al +- outb %al, %dx +- incw %dx +- movb %bl, %al +- outb %al, %dx +- movb $0x55, %al +- xorb $0xea, %al +- cmpb %bh, %al +- jne isnot +- +- movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching +- ret +- +-video7_md: +- .byte 0x40, 0x2b, 0x50 +- .byte 0x43, 0x3c, 0x50 +- .byte 0x44, 0x3c, 0x64 +- .byte 0x41, 0x19, 0x84 +- .byte 0x42, 0x2c, 0x84 +- .byte 0x45, 0x1c, 0x84 +- .byte 0 +- .ascii "Video 7" +- .byte 0 +- +-# Realtek VGA +-realtek_test: +- leaw idrtvga, %si +- movw $0x45, %di +- movw $0x0b, %cx +- repe +- cmpsb +- je isrt +- +- xorw %bp, %bp +-isrt: ret +- +-idrtvga: .ascii "REALTEK VGA" +- +-realtek_md: +- .byte 0x1a, 0x3c, 0x50 +- .byte 0x1b, 0x19, 0x84 +- .byte 0x1c, 0x1e, 0x84 +- .byte 0x1d, 0x2b, 0x84 +- .byte 0x1e, 0x3c, 0x84 +- .byte 0 +- .ascii "REALTEK" +- .byte 0 +- +-#endif /* CONFIG_VIDEO_SVGA */ +- +-# User-defined local mode table (VGA only) +-#ifdef CONFIG_VIDEO_LOCAL +-local_modes: +- leaw local_mode_table, %si +-locm1: lodsw +- orw %ax, %ax +- jz locm2 +- +- stosw +- movsw +- jmp locm1 +- +-locm2: ret +- +-# This is the table of local video modes which can be supplied manually +-# by the user. Each entry consists of mode ID (word) and dimensions +-# (byte for column count and another byte for row count). These modes +-# are placed before all SVGA and VESA modes and override them if table +-# compacting is enabled. The table must end with a zero word followed +-# by NUL-terminated video adapter name. +-local_mode_table: +- .word 0x0100 # Example: 40x25 +- .byte 25,40 +- .word 0 +- .ascii "Local" +- .byte 0 +-#endif /* CONFIG_VIDEO_LOCAL */ +- +-# Read a key and return the ASCII code in al, scan code in ah +-getkey: xorb %ah, %ah +- int $0x16 +- ret +- +-# Read a key with a timeout of 30 seconds. +-# The hardware clock is used to get the time. +-getkt: call gettime +- addb $30, %al # Wait 30 seconds +- cmpb $60, %al +- jl lminute +- +- subb $60, %al +-lminute: +- movb %al, %cl +-again: movb $0x01, %ah +- int $0x16 +- jnz getkey # key pressed, so get it +- +- call gettime +- cmpb %cl, %al +- jne again +- +- movb $0x20, %al # timeout, return `space' +- ret +- +-# Flush the keyboard buffer +-flush: movb $0x01, %ah +- int $0x16 +- jz empty +- +- xorb %ah, %ah +- int $0x16 +- jmp flush +- +-empty: ret +- +-# Print hexadecimal number. +-prthw: pushw %ax +- movb %ah, %al +- call prthb +- popw %ax +-prthb: pushw %ax +- shrb $4, %al +- call prthn +- popw %ax +- andb $0x0f, %al +-prthn: cmpb $0x0a, %al +- jc prth1 +- +- addb $0x07, %al +-prth1: addb $0x30, %al +- jmp prtchr +- +-# Print decimal number in al +-prtdec: pushw %ax +- pushw %cx +- xorb %ah, %ah +- movb $0x0a, %cl +- idivb %cl +- cmpb $0x09, %al +- jbe lt100 +- +- call prtdec +- jmp skip10 +- +-lt100: addb $0x30, %al +- call prtchr +-skip10: movb %ah, %al +- addb $0x30, %al +- call prtchr +- popw %cx +- popw %ax +- ret +- +-store_edid: +-#ifdef CONFIG_FIRMWARE_EDID +- pushw %es # just save all registers +- pushw %ax +- pushw %bx +- pushw %cx +- pushw %dx +- pushw %di +- +- pushw %fs +- popw %es +- +- movl $0x13131313, %eax # memset block with 0x13 +- movw $32, %cx +- movw $0x140, %di +- cld +- rep +- stosl +- +- cmpw $0x0200, vbe_version # only do EDID on >= VBE2.0 +- jl no_edid +- +- pushw %es # save ES +- xorw %di, %di # Report Capability +- pushw %di +- popw %es # ES:DI must be 0:0 +- movw $0x4f15, %ax +- xorw %bx, %bx +- xorw %cx, %cx +- int $0x10 +- popw %es # restore ES +- +- cmpb $0x00, %ah # call successful +- jne no_edid +- +- cmpb $0x4f, %al # function supported +- jne no_edid +- +- movw $0x4f15, %ax # do VBE/DDC +- movw $0x01, %bx +- movw $0x00, %cx +- movw $0x00, %dx +- movw $0x140, %di +- int $0x10 +- +-no_edid: +- popw %di # restore all registers +- popw %dx +- popw %cx +- popw %bx +- popw %ax +- popw %es +-#endif +- ret +- +-# VIDEO_SELECT-only variables +-mt_end: .word 0 # End of video mode table if built +-edit_buf: .space 6 # Line editor buffer +-card_name: .word 0 # Pointer to adapter name +-scanning: .byte 0 # Performing mode scan +-do_restore: .byte 0 # Screen contents altered during mode change +-svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes +-graphic_mode: .byte 0 # Graphic mode with a linear frame buffer +-dac_size: .byte 6 # DAC bit depth +-vbe_version: .word 0 # VBE bios version +- +-# Status messages +-keymsg: .ascii "Press to see video modes available, " +- .ascii " to continue or wait 30 secs" +- .byte 0x0d, 0x0a, 0 +- +-listhdr: .byte 0x0d, 0x0a +- .ascii "Mode: COLSxROWS:" +- +-crlft: .byte 0x0d, 0x0a, 0 +- +-prompt: .byte 0x0d, 0x0a +- .asciz "Enter mode number or `scan': " +- +-unknt: .asciz "Unknown mode ID. Try again." +- +-badmdt: .ascii "You passed an undefined mode number." +- .byte 0x0d, 0x0a, 0 +- +-vesaer: .ascii "Error: Scanning of VESA modes failed. Please " +- .ascii "report to ." +- .byte 0x0d, 0x0a, 0 +- +-old_name: .asciz "CGA/MDA/HGA" +- +-ega_name: .asciz "EGA" +- +-svga_name: .ascii " " +- +-vga_name: .asciz "VGA" +- +-vesa_name: .asciz "VESA" +- +-name_bann: .asciz "Video adapter: " +-#endif /* CONFIG_VIDEO_SELECT */ +- +-# Other variables: +-adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA +-video_segment: .word 0xb800 # Video memory segment +-force_size: .word 0 # Use this size instead of the one in BIOS vars +diff -puN /dev/null arch/i386/boot/video.c +--- /dev/null ++++ a/arch/i386/boot/video.c +@@ -0,0 +1,456 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/video.c ++ * ++ * Select video mode ++ */ ++ ++#include "boot.h" ++#include "video.h" ++#include "vesa.h" ++ ++/* ++ * Mode list variables ++ */ ++static struct card_info cards[]; /* List of cards to probe for */ ++ ++/* ++ * Common variables ++ */ ++int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */ ++u16 video_segment; ++int force_x, force_y; /* Don't query the BIOS for cols/rows */ ++ ++int do_restore = 0; /* Screen contents changed during mode flip */ ++int graphic_mode; /* Graphic mode with linear frame buffer */ ++ ++static void store_cursor_position(void) ++{ ++ u16 curpos; ++ u16 ax, bx; ++ ++ ax = 0x0300; ++ bx = 0; ++ asm(INT10 ++ : "=d" (curpos), "+a" (ax), "+b" (bx) ++ : : "ecx", "esi", "edi"); ++ ++ boot_params.screen_info.orig_x = curpos; ++ boot_params.screen_info.orig_y = curpos >> 8; ++} ++ ++static void store_video_mode(void) ++{ ++ u16 ax, page; ++ ++ /* N.B.: the saving of the video page here is a bit silly, ++ since we pretty much assume page 0 everywhere. */ ++ ax = 0x0f00; ++ asm(INT10 ++ : "+a" (ax), "=b" (page) ++ : : "ecx", "edx", "esi", "edi"); ++ ++ /* Not all BIOSes are clean with respect to the top bit */ ++ boot_params.screen_info.orig_video_mode = ax & 0x7f; ++ boot_params.screen_info.orig_video_page = page; ++} ++ ++/* ++ * Store the video mode parameters for later usage by the kernel. ++ * This is done by asking the BIOS except for the rows/columns ++ * parameters in the default 80x25 mode -- these are set directly, ++ * because some very obscure BIOSes supply insane values. ++ */ ++static void store_mode_params(void) ++{ ++ u16 font_size; ++ int x, y; ++ ++ /* For graphics mode, it is up to the mode-setting driver ++ (currently only video-vesa.c) to store the parameters */ ++ if (graphic_mode) ++ return; ++ ++ store_cursor_position(); ++ store_video_mode(); ++ ++ if (boot_params.screen_info.orig_video_mode == 0x07) { ++ /* MDA, HGC, or VGA in monochrome mode */ ++ video_segment = 0xb000; ++ } else { ++ /* CGA, EGA, VGA and so forth */ ++ video_segment = 0xb800; ++ } ++ ++ set_fs(0); ++ font_size = rdfs16(0x485); /* Font size, BIOS area */ ++ boot_params.screen_info.orig_video_points = font_size; ++ ++ x = rdfs16(0x44a); ++ y = (adapter == ADAPTER_CGA) ? 25 : rdfs8(0x484)+1; ++ ++ if (force_x) ++ x = force_x; ++ if (force_y) ++ y = force_y; ++ ++ boot_params.screen_info.orig_video_cols = x; ++ boot_params.screen_info.orig_video_lines = y; ++} ++ ++/* Probe the video drivers and have them generate their mode lists. */ ++static void probe_cards(int unsafe) ++{ ++ struct card_info *card; ++ static u8 probed[2]; ++ ++ if (probed[unsafe]) ++ return; ++ ++ probed[unsafe] = 1; ++ ++ for (card = video_cards; card < video_cards_end; card++) { ++ if (card->unsafe == unsafe) { ++ if (card->probe) ++ card->nmodes = card->probe(); ++ else ++ card->nmodes = 0; ++ } ++ } ++} ++ ++/* Test if a mode is defined */ ++int mode_defined(u16 mode) ++{ ++ struct card_info *card; ++ struct mode_info *mi; ++ int i; ++ ++ for (card = video_cards; card < video_cards_end; card++) { ++ mi = card->modes; ++ for (i = 0; i < card->nmodes; i++, mi++) { ++ if (mi->mode == mode) ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++/* Set mode (without recalc) */ ++static int raw_set_mode(u16 mode) ++{ ++ int nmode, i; ++ struct card_info *card; ++ struct mode_info *mi; ++ ++ /* Drop the recalc bit if set */ ++ mode &= ~VIDEO_RECALC; ++ ++ /* Scan for mode based on fixed ID, position, or resolution */ ++ nmode = 0; ++ for (card = video_cards; card < video_cards_end; card++) { ++ mi = card->modes; ++ for (i = 0; i < card->nmodes; i++, mi++) { ++ int visible = mi->x || mi->y; ++ ++ if ((mode == nmode && visible) || ++ mode == mi->mode || ++ mode == (mi->y << 8)+mi->x) ++ return card->set_mode(mi); ++ ++ if (visible) ++ nmode++; ++ } ++ } ++ ++ /* Nothing found? Is it an "exceptional" (unprobed) mode? */ ++ for (card = video_cards; card < video_cards_end; card++) { ++ if (mode >= card->xmode_first && ++ mode < card->xmode_first+card->xmode_n) { ++ struct mode_info mix; ++ mix.mode = mode; ++ mix.x = mix.y = 0; ++ return card->set_mode(&mix); ++ } ++ } ++ ++ /* Otherwise, failure... */ ++ return -1; ++} ++ ++/* ++ * Recalculate the vertical video cutoff (hack!) ++ */ ++static void vga_recalc_vertical(void) ++{ ++ unsigned int font_size, rows; ++ u16 crtc; ++ u8 ov; ++ ++ set_fs(0); ++ font_size = rdfs8(0x485); /* BIOS: font size (pixels) */ ++ rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */ ++ ++ rows *= font_size; /* Visible scan lines */ ++ rows--; /* ... minus one */ ++ ++ crtc = vga_crtc(); ++ ++ out_idx((u8)rows, crtc, 0x12); /* Lower height register */ ++ ov = in_idx(crtc, 0x07); /* Overflow register */ ++ ov &= 0xbd; ++ ov |= (rows >> (8-1)) & 0x02; ++ ov |= (rows >> (9-6)) & 0x40; ++ out_idx(ov, crtc, 0x07); ++} ++ ++/* Set mode (with recalc if specified) */ ++static int set_mode(u16 mode) ++{ ++ int rv; ++ ++ /* Very special mode numbers... */ ++ if (mode == VIDEO_CURRENT_MODE) ++ return 0; /* Nothing to do... */ ++ else if (mode == NORMAL_VGA) ++ mode = VIDEO_80x25; ++ else if (mode == EXTENDED_VGA) ++ mode = VIDEO_8POINT; ++ ++ rv = raw_set_mode(mode); ++ if (rv) ++ return rv; ++ ++ if (mode & VIDEO_RECALC) ++ vga_recalc_vertical(); ++ ++ return 0; ++} ++ ++static unsigned int get_entry(void) ++{ ++ char entry_buf[4]; ++ int i, len = 0; ++ int key; ++ unsigned int v; ++ ++ do { ++ key = getchar(); ++ ++ if (key == '\b') { ++ if (len > 0) { ++ puts("\b \b"); ++ len--; ++ } ++ } else if ((key >= '0' && key <= '9') || ++ (key >= 'A' && key <= 'Z') || ++ (key >= 'a' && key <= 'z')) { ++ if (len < sizeof entry_buf) { ++ entry_buf[len++] = key; ++ putchar(key); ++ } ++ } ++ } while (key != '\r'); ++ putchar('\n'); ++ ++ if (len == 0) ++ return VIDEO_CURRENT_MODE; /* Default */ ++ ++ v = 0; ++ for (i = 0; i < len; i++) { ++ v <<= 4; ++ key = entry_buf[i] | 0x20; ++ v += (key > '9') ? key-'a'+10 : key-'0'; ++ } ++ ++ return v; ++} ++ ++static void display_menu(void) ++{ ++ struct card_info *card; ++ struct mode_info *mi; ++ char ch; ++ int i; ++ ++ puts("Mode: COLSxROWS:\n"); ++ ++ ch = '0'; ++ for (card = video_cards; card < video_cards_end; card++) { ++ mi = card->modes; ++ for (i = 0; i < card->nmodes; i++, mi++) { ++ int visible = mi->x && mi->y; ++ u16 mode_id = mi->mode ? mi->mode : ++ (mi->y << 8)+mi->x; ++ ++ if (!visible) ++ continue; /* Hidden mode */ ++ ++ printf("%c %04X %3dx%-3d %s\n", ++ ch, mode_id, mi->x, mi->y, card->card_name); ++ ++ if (ch == '9') ++ ch = 'a'; ++ else if (ch == 'z' || ch == ' ') ++ ch = ' '; /* Out of keys... */ ++ else ++ ch++; ++ } ++ } ++} ++ ++#define H(x) ((x)-'a'+10) ++#define SCAN ((H('s')<<12)+(H('c')<<8)+(H('a')<<4)+H('n')) ++ ++static unsigned int mode_menu(void) ++{ ++ int key; ++ unsigned int sel; ++ ++ puts("Press to see video modes available, " ++ " to continue, or wait 30 sec\n"); ++ ++ kbd_flush(); ++ while (1) { ++ key = getchar_timeout(); ++ if (key == ' ' || key == 0) ++ return VIDEO_CURRENT_MODE; /* Default */ ++ if (key == '\r') ++ break; ++ putchar('\a'); /* Beep! */ ++ } ++ ++ ++ for (;;) { ++ display_menu(); ++ ++ puts("Enter a video mode or \"scan\" to scan for " ++ "additional modes: "); ++ sel = get_entry(); ++ if (sel != SCAN) ++ return sel; ++ ++ probe_cards(1); ++ } ++} ++ ++#ifdef CONFIG_VIDEO_RETAIN ++/* Save screen content to the heap */ ++struct saved_screen { ++ int x, y; ++ int curx, cury; ++ u16 *data; ++} saved; ++ ++static void save_screen(void) ++{ ++ /* Should be called after store_mode_params() */ ++ saved.x = boot_params.screen_info.orig_video_cols; ++ saved.y = boot_params.screen_info.orig_video_lines; ++ saved.curx = boot_params.screen_info.orig_x; ++ saved.cury = boot_params.screen_info.orig_y; ++ ++ if (heap_free() < saved.x*saved.y*sizeof(u16)+512) ++ return; /* Not enough heap to save the screen */ ++ ++ saved.data = GET_HEAP(u16, saved.x*saved.y); ++ ++ set_fs(video_segment); ++ copy_from_fs(saved.data, 0, saved.x*saved.y*sizeof(u16)); ++} ++ ++static void restore_screen(void) ++{ ++ /* Should be called after store_mode_params() */ ++ int xs = boot_params.screen_info.orig_video_cols; ++ int ys = boot_params.screen_info.orig_video_lines; ++ int y; ++ addr_t dst = 0; ++ u16 *src = saved.data; ++ u16 ax, bx, dx; ++ ++ if (graphic_mode) ++ return; /* Can't restore onto a graphic mode */ ++ ++ if (!src) ++ return; /* No saved screen contents */ ++ ++ /* Restore screen contents */ ++ ++ set_fs(video_segment); ++ for (y = 0; y < ys; y++) { ++ int npad; ++ ++ if (y < saved.y) { ++ int copy = (xs < saved.x) ? xs : saved.x; ++ copy_to_fs(dst, src, copy*sizeof(u16)); ++ dst += copy*sizeof(u16); ++ src += saved.x; ++ npad = (xs < saved.x) ? 0 : xs-saved.x; ++ } else { ++ npad = xs; ++ } ++ ++ /* Writes "npad" blank characters to ++ video_segment:dst and advances dst */ ++ asm volatile("pushw %%es ; " ++ "movw %2,%%es ; " ++ "shrw %%cx ; " ++ "jnc 1f ; " ++ "stosw \n\t" ++ "1: rep;stosl ; " ++ "popw %%es" ++ : "+D" (dst), "+c" (npad) ++ : "bdSm" (video_segment), ++ "a" (0x07200720)); ++ } ++ ++ /* Restore cursor position */ ++ ax = 0x0200; /* Set cursor position */ ++ bx = 0; /* Page number (<< 8) */ ++ dx = (saved.cury << 8)+saved.curx; ++ asm volatile(INT10 ++ : "+a" (ax), "+b" (bx), "+d" (dx) ++ : : "ecx", "esi", "edi"); ++} ++#else ++#define save_screen() ((void)0) ++#define restore_screen() ((void)0) ++#endif ++ ++void set_video(void) ++{ ++ u16 mode = boot_params.hdr.vid_mode; ++ ++ RESET_HEAP(); ++ ++ store_mode_params(); ++ save_screen(); ++ probe_cards(0); ++ ++ for (;;) { ++ if (mode == ASK_VGA) ++ mode = mode_menu(); ++ ++ if (!set_mode(mode)) ++ break; ++ ++ printf("Undefined video mode number: %x\n", mode); ++ mode = ASK_VGA; ++ } ++ vesa_store_edid(); ++ store_mode_params(); ++ ++ if (do_restore) ++ restore_screen(); ++} +diff -puN /dev/null arch/i386/boot/video.h +--- /dev/null ++++ a/arch/i386/boot/video.h +@@ -0,0 +1,145 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/video.h ++ * ++ * Header file for the real-mode video probing code ++ */ ++ ++#ifndef BOOT_VIDEO_H ++#define BOOT_VIDEO_H ++ ++#include ++ ++/* Enable autodetection of SVGA adapters and modes. */ ++#undef CONFIG_VIDEO_SVGA ++ ++/* Enable autodetection of VESA modes */ ++#define CONFIG_VIDEO_VESA ++ ++/* Retain screen contents when switching modes */ ++#define CONFIG_VIDEO_RETAIN ++ ++/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */ ++#undef CONFIG_VIDEO_400_HACK ++ ++/* This code uses an extended set of video mode numbers. These include: ++ * Aliases for standard modes ++ * NORMAL_VGA (-1) ++ * EXTENDED_VGA (-2) ++ * ASK_VGA (-3) ++ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack ++ * of compatibility when extending the table. These are between 0x00 and 0xff. ++ */ ++#define VIDEO_FIRST_MENU 0x0000 ++ ++/* Standard BIOS video modes (BIOS number + 0x0100) */ ++#define VIDEO_FIRST_BIOS 0x0100 ++ ++/* VESA BIOS video modes (VESA number + 0x0200) */ ++#define VIDEO_FIRST_VESA 0x0200 ++ ++/* Video7 special modes (BIOS number + 0x0900) */ ++#define VIDEO_FIRST_V7 0x0900 ++ ++/* Special video modes */ ++#define VIDEO_FIRST_SPECIAL 0x0f00 ++#define VIDEO_80x25 0x0f00 ++#define VIDEO_8POINT 0x0f01 ++#define VIDEO_80x43 0x0f02 ++#define VIDEO_80x28 0x0f03 ++#define VIDEO_CURRENT_MODE 0x0f04 ++#define VIDEO_80x30 0x0f05 ++#define VIDEO_80x34 0x0f06 ++#define VIDEO_80x60 0x0f07 ++#define VIDEO_GFX_HACK 0x0f08 ++#define VIDEO_LAST_SPECIAL 0x0f09 ++ ++/* Video modes given by resolution */ ++#define VIDEO_FIRST_RESOLUTION 0x1000 ++ ++/* The "recalculate timings" flag */ ++#define VIDEO_RECALC 0x8000 ++ ++/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ ++#ifdef CONFIG_VIDEO_RETAIN ++void store_screen(void); ++#define DO_STORE() store_screen() ++#else ++#define DO_STORE() ((void)0) ++#endif /* CONFIG_VIDEO_RETAIN */ ++ ++/* ++ * Mode table structures ++ */ ++ ++struct mode_info { ++ u16 mode; /* Mode number (vga= style) */ ++ u8 x, y; /* Width, height */ ++}; ++ ++struct card_info { ++ const char *card_name; ++ int (*set_mode)(struct mode_info *mode); ++ int (*probe)(void); ++ struct mode_info *modes; ++ int nmodes; /* Number of probed modes so far */ ++ int unsafe; /* Probing is unsafe, only do after "scan" */ ++ u16 xmode_first; /* Unprobed modes to try to call anyway */ ++ u16 xmode_n; /* Size of unprobed mode range */ ++}; ++ ++#define __videocard struct card_info __attribute__((section(".videocards"))) ++extern struct card_info video_cards[], video_cards_end[]; ++ ++int mode_defined(u16 mode); /* video.c */ ++ ++/* Basic video information */ ++#define ADAPTER_CGA 0 /* CGA/MDA/HGC */ ++#define ADAPTER_EGA 1 ++#define ADAPTER_VGA 2 ++ ++extern int adapter; ++extern u16 video_segment; ++extern int force_x, force_y; /* Don't query the BIOS for cols/rows */ ++extern int do_restore; /* Restore screen contents */ ++extern int graphic_mode; /* Graphics mode with linear frame buffer */ ++ ++/* ++ * int $0x10 is notorious for touching registers it shouldn't. ++ * gcc doesn't like %ebp being clobbered, so define it as a push/pop ++ * sequence here. ++ */ ++#define INT10 "pushl %%ebp; int $0x10; popl %%ebp" ++ ++/* Accessing VGA indexed registers */ ++static inline u8 in_idx(u16 port, u8 index) ++{ ++ outb(index, port); ++ return inb(port+1); ++} ++ ++static inline void out_idx(u8 v, u16 port, u8 index) ++{ ++ outw(index+(v << 8), port); ++} ++ ++/* Writes a value to an indexed port and then reads the port again */ ++static inline u8 tst_idx(u8 v, u16 port, u8 index) ++{ ++ out_idx(port, index, v); ++ return in_idx(port, index); ++} ++ ++/* Get the I/O port of the VGA CRTC */ ++u16 vga_crtc(void); /* video-vga.c */ ++ ++#endif /* BOOT_VIDEO_H */ +diff -puN /dev/null arch/i386/boot/voyager.c +--- /dev/null ++++ a/arch/i386/boot/voyager.c +@@ -0,0 +1,46 @@ ++/* -*- linux-c -*- ------------------------------------------------------- * ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright 2007 rPath, Inc. - All Rights Reserved ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * arch/i386/boot/voyager.c ++ * ++ * Get the Voyager config information ++ */ ++ ++#include "boot.h" ++ ++#ifdef CONFIG_X86_VOYAGER ++ ++int query_voyager(void) ++{ ++ u8 err; ++ u16 es, di; ++ /* Abuse the apm_bios_info area for this */ ++ u8 *data_ptr = (u8 *)&boot_params.apm_bios_info; ++ ++ data_ptr[0] = 0xff; /* Flag on config not found(?) */ ++ ++ asm("pushw %%es ; " ++ "int $0x15 ; " ++ "setc %0 ; " ++ "movw %%es, %1 ; " ++ "popw %%es" ++ : "=qm" (err), "=rm" (es), "=D" (di) ++ : "a" (0xffc0)); ++ ++ if (err) ++ return -1; /* Not Voyager */ ++ ++ set_fs(es); ++ copy_from_fs(data_ptr, di, 7); /* Table is 7 bytes apparently */ ++ return 0; ++} ++ ++#endif /* CONFIG_X86_VOYAGER */ +diff -puN arch/i386/kernel/cpu/Makefile~git-newsetup arch/i386/kernel/cpu/Makefile +diff -puN /dev/null arch/i386/kernel/cpu/addon_cpuid_features.c +--- /dev/null ++++ a/arch/i386/kernel/cpu/addon_cpuid_features.c +@@ -0,0 +1,50 @@ ++ ++/* ++ * Routines to indentify additional cpu features that are scattered in ++ * cpuid space. ++ */ ++ ++#include ++ ++#include ++ ++struct cpuid_bit { ++ u16 feature; ++ u8 reg; ++ u8 bit; ++ u32 level; ++}; ++ ++enum cpuid_regs { ++ CR_EAX = 0, ++ CR_ECX, ++ CR_EDX, ++ CR_EBX ++}; ++ ++void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) ++{ ++ u32 max_level; ++ u32 regs[4]; ++ const struct cpuid_bit *cb; ++ ++ static const struct cpuid_bit cpuid_bits[] = { ++ { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, ++ { 0, 0, 0, 0 } ++ }; ++ ++ for (cb = cpuid_bits; cb->feature; cb++) { ++ ++ /* Verify that the level is valid */ ++ max_level = cpuid_eax(cb->level & 0xffff0000); ++ if (max_level < cb->level || ++ max_level > (cb->level | 0xffff)) ++ continue; ++ ++ cpuid(cb->level, ®s[CR_EAX], ®s[CR_EBX], ++ ®s[CR_ECX], ®s[CR_EDX]); ++ ++ if (regs[cb->reg] & (1 << cb->bit)) ++ set_bit(cb->feature, c->x86_capability); ++ } ++} +diff -puN arch/i386/kernel/cpu/common.c~git-newsetup arch/i386/kernel/cpu/common.c +--- a/arch/i386/kernel/cpu/common.c~git-newsetup ++++ a/arch/i386/kernel/cpu/common.c +@@ -353,6 +353,8 @@ static void __cpuinit generic_identify(s + if ( xlvl >= 0x80000004 ) + get_model_name(c); /* Default name */ + } ++ ++ init_scattered_cpuid_features(c); + } + + early_intel_workaround(c); +diff -puN arch/i386/kernel/cpu/proc.c~git-newsetup arch/i386/kernel/cpu/proc.c +--- a/arch/i386/kernel/cpu/proc.c~git-newsetup ++++ a/arch/i386/kernel/cpu/proc.c +@@ -29,7 +29,8 @@ static int show_cpuinfo(struct seq_file + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, +- NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow", ++ NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", ++ "3dnowext", "3dnow", + + /* Transmeta-defined */ + "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, +@@ -40,8 +41,9 @@ static int show_cpuinfo(struct seq_file + /* Other (Linux-defined) */ + "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", + NULL, NULL, NULL, NULL, +- "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "constant_tsc", "up", NULL, "arch_perfmon", ++ "pebs", "bts", NULL, "sync_rdtsc", ++ "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Intel-defined (#2) */ +@@ -57,9 +59,16 @@ static int show_cpuinfo(struct seq_file + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* AMD-defined (#2) */ +- "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm", +- "sse4a", "misalignsse", +- "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL, ++ "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy", ++ "altmovcr8", "abm", "sse4a", ++ "misalignsse", "3dnowprefetch", ++ "osvw", "ibs", NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ ++ /* Auxiliary (Linux-defined) */ ++ "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + }; +diff -puN arch/i386/kernel/e820.c~git-newsetup arch/i386/kernel/e820.c +--- a/arch/i386/kernel/e820.c~git-newsetup ++++ a/arch/i386/kernel/e820.c +@@ -766,7 +766,7 @@ void __init print_memory_map(char *who) + case E820_NVS: + printk("(ACPI NVS)\n"); + break; +- default: printk("type %lu\n", e820.map[i].type); ++ default: printk("type %u\n", e820.map[i].type); + break; + } + } +diff -puN arch/i386/kernel/setup.c~git-newsetup arch/i386/kernel/setup.c +--- a/arch/i386/kernel/setup.c~git-newsetup ++++ a/arch/i386/kernel/setup.c +@@ -102,19 +102,10 @@ static unsigned int highmem_pages = -1; + /* + * Setup options + */ +-struct drive_info_struct { char dummy[32]; } drive_info; +-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \ +- defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) +-EXPORT_SYMBOL(drive_info); +-#endif + struct screen_info screen_info; + EXPORT_SYMBOL(screen_info); + struct apm_info apm_info; + EXPORT_SYMBOL(apm_info); +-struct sys_desc_table_struct { +- unsigned short length; +- unsigned char table[0]; +-}; + struct edid_info edid_info; + EXPORT_SYMBOL_GPL(edid_info); + struct ist_info ist_info; +@@ -134,7 +125,7 @@ unsigned long saved_videomode; + + static char __initdata command_line[COMMAND_LINE_SIZE]; + +-unsigned char __initdata boot_params[PARAM_SIZE]; ++struct boot_params __initdata boot_params; + + #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) + struct edd edd; +@@ -528,7 +519,6 @@ void __init setup_arch(char **cmdline_p) + #endif + + ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); +- drive_info = DRIVE_INFO; + screen_info = SCREEN_INFO; + edid_info = EDID_INFO; + apm_info.bios = APM_BIOS_INFO; +diff -puN arch/i386/kernel/verify_cpu.S~git-newsetup /dev/null +--- a/arch/i386/kernel/verify_cpu.S ++++ /dev/null +@@ -1,94 +0,0 @@ +-/* Check if CPU has some minimum CPUID bits +- This runs in 16bit mode so that the caller can still use the BIOS +- to output errors on the screen */ +-#include +-#include +- +-verify_cpu: +- pushfl # Save caller passed flags +- pushl $0 # Kill any dangerous flags +- popfl +- +-#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4 +- pushfl +- pop %eax +- orl $(1<<18),%eax # try setting AC +- push %eax +- popfl +- pushfl +- popl %eax +- testl $(1<<18),%eax +- jz bad +-#endif +-#if REQUIRED_MASK1 != 0 +- pushfl # standard way to check for cpuid +- popl %eax +- movl %eax,%ebx +- xorl $0x200000,%eax +- pushl %eax +- popfl +- pushfl +- popl %eax +- cmpl %eax,%ebx +- pushfl # standard way to check for cpuid +- popl %eax +- movl %eax,%ebx +- xorl $0x200000,%eax +- pushl %eax +- popfl +- pushfl +- popl %eax +- cmpl %eax,%ebx +- jz bad # REQUIRED_MASK1 != 0 requires CPUID +- +- movl $0x0,%eax # See if cpuid 1 is implemented +- cpuid +- cmpl $0x1,%eax +- jb bad # no cpuid 1 +- +-#if REQUIRED_MASK1 & NEED_CMPXCHG64 +- /* Some VIA C3s need magic MSRs to enable CX64. Do this here */ +- cmpl $0x746e6543,%ebx # Cent +- jne 1f +- cmpl $0x48727561,%edx # aurH +- jne 1f +- cmpl $0x736c7561,%ecx # auls +- jne 1f +- movl $1,%eax # check model +- cpuid +- movl %eax,%ebx +- shr $8,%ebx +- andl $0xf,%ebx +- cmp $6,%ebx # check family == 6 +- jne 1f +- shr $4,%eax +- andl $0xf,%eax +- cmpl $6,%eax # check model >= 6 +- jb 1f +- # assume models >= 6 all support this MSR +- movl $MSR_VIA_FCR,%ecx +- rdmsr +- orl $((1<<1)|(1<<7)),%eax # enable CMPXCHG64 and PGE +- wrmsr +-1: +-#endif +- movl $0x1,%eax # Does the cpu have what it takes +- cpuid +- +-#if CONFIG_X86_MINIMUM_CPU_MODEL > 4 +-#error add proper model checking here +-#endif +- +- andl $REQUIRED_MASK1,%edx +- xorl $REQUIRED_MASK1,%edx +- jnz bad +-#endif /* REQUIRED_MASK1 */ +- +- popfl +- xor %eax,%eax +- ret +- +-bad: +- popfl +- movl $1,%eax +- ret +diff -puN arch/x86_64/Kconfig~git-newsetup arch/x86_64/Kconfig +--- a/arch/x86_64/Kconfig~git-newsetup ++++ a/arch/x86_64/Kconfig +@@ -453,6 +453,10 @@ config NR_CPUS + This is purely to save memory - each supported CPU requires + memory in the static kernel configuration. + ++config PHYSICAL_ALIGN ++ hex ++ default "0x200000" ++ + config HOTPLUG_CPU + bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" + depends on SMP && HOTPLUG && EXPERIMENTAL +diff -puN arch/x86_64/boot/Makefile~git-newsetup arch/x86_64/boot/Makefile +--- a/arch/x86_64/boot/Makefile~git-newsetup ++++ a/arch/x86_64/boot/Makefile +@@ -1,135 +1,9 @@ + # + # arch/x86_64/boot/Makefile + # +-# This file is subject to the terms and conditions of the GNU General Public +-# License. See the file "COPYING" in the main directory of this archive +-# for more details. +-# +-# Copyright (C) 1994 by Linus Torvalds +-# +- +-# ROOT_DEV specifies the default root-device when making the image. +-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case +-# the default of FLOPPY is used by 'build'. +- +-ROOT_DEV := CURRENT +- +-# If you want to preset the SVGA mode, uncomment the next line and +-# set SVGA_MODE to whatever number you want. +-# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. +-# The number is the same as you would ordinarily press at bootup. +- +-SVGA_MODE := -DSVGA_MODE=NORMAL_VGA +- +-# If you want the RAM disk device, define this to be the size in blocks. +- +-#RAMDISK := -DRAMDISK=512 +- +-targets := vmlinux.bin bootsect bootsect.o \ +- setup setup.o bzImage mtools.conf +- +-EXTRA_CFLAGS := -m32 +- +-hostprogs-y := tools/build +-HOST_EXTRACFLAGS += $(LINUXINCLUDE) +-subdir- := compressed/ #Let make clean descend in compressed/ +-# --------------------------------------------------------------------------- +- +-$(obj)/bzImage: IMAGE_OFFSET := 0x100000 +-$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ +-$(obj)/bzImage: BUILDFLAGS := -b +- +-quiet_cmd_image = BUILD $@ +-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ +- $(obj)/vmlinux.bin $(ROOT_DEV) > $@ +- +-$(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ +- $(obj)/vmlinux.bin $(obj)/tools/build FORCE +- $(call if_changed,image) +- @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' +- +-$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE +- $(call if_changed,objcopy) +- +-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary +-LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext +- +-$(obj)/setup $(obj)/bootsect: %: %.o FORCE +- $(call if_changed,ld) +- +-$(obj)/compressed/vmlinux: FORCE +- $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ +- +-# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel +-FDARGS = +-# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel +-FDINITRD = +- +-image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,) +- +-$(obj)/mtools.conf: $(src)/mtools.conf.in +- sed -e 's|@OBJ@|$(obj)|g' < $< > $@ +- +-# This requires write access to /dev/fd0 +-zdisk: $(BOOTIMAGE) $(obj)/mtools.conf +- MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync +- syslinux /dev/fd0 ; sync +- echo '$(image_cmdline)' | \ +- MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg +- if [ -f '$(FDINITRD)' ] ; then \ +- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \ +- fi +- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync +- +-# These require being root or having syslinux 2.02 or higher installed +-fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf +- dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 +- MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync +- syslinux $(obj)/fdimage ; sync +- echo '$(image_cmdline)' | \ +- MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg +- if [ -f '$(FDINITRD)' ] ; then \ +- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \ +- fi +- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync +- +-fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf +- dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 +- MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync +- syslinux $(obj)/fdimage ; sync +- echo '$(image_cmdline)' | \ +- MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg +- if [ -f '$(FDINITRD)' ] ; then \ +- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \ +- fi +- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync +- +-isoimage: $(BOOTIMAGE) +- -rm -rf $(obj)/isoimage +- mkdir $(obj)/isoimage +- for i in lib lib64 share end ; do \ +- if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \ +- cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \ +- break ; \ +- fi ; \ +- if [ $$i = end ] ; then exit 1 ; fi ; \ +- done +- cp $(BOOTIMAGE) $(obj)/isoimage/linux +- echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg +- if [ -f '$(FDINITRD)' ] ; then \ +- cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \ +- fi +- mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \ +- -no-emul-boot -boot-load-size 4 -boot-info-table \ +- $(obj)/isoimage +- rm -rf $(obj)/isoimage +- +-zlilo: $(BOOTIMAGE) +- if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi +- if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi +- cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz +- cp System.map $(INSTALL_PATH)/ +- if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi ++# The actual boot code is shared with i386 including the Makefile. ++# So tell kbuild that we fetch the code from i386 and include the ++# Makefile from i386 too. + +-install: +- sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" ++src := arch/i386/boot ++include $(src)/Makefile +diff -puN arch/x86_64/boot/bootsect.S~git-newsetup /dev/null +--- a/arch/x86_64/boot/bootsect.S ++++ /dev/null +@@ -1,98 +0,0 @@ +-/* +- * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds +- * +- * modified by Drew Eckhardt +- * modified by Bruce Evans (bde) +- * modified by Chris Noe (May 1999) (as86 -> gas) +- * gutted by H. Peter Anvin (Jan 2003) +- * +- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment +- * addresses must be multiplied by 16 to obtain their respective linear +- * addresses. To avoid confusion, linear addresses are written using leading +- * hex while segment addresses are written as segment:offset. +- * +- */ +- +-#include +- +-SETUPSECTS = 4 /* default nr of setup-sectors */ +-BOOTSEG = 0x07C0 /* original address of boot-sector */ +-INITSEG = DEF_INITSEG /* we move boot here - out of the way */ +-SETUPSEG = DEF_SETUPSEG /* setup starts here */ +-SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ +-SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ +- /* to be loaded */ +-ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ +-SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ +- +-#ifndef SVGA_MODE +-#define SVGA_MODE ASK_VGA +-#endif +- +-#ifndef RAMDISK +-#define RAMDISK 0 +-#endif +- +-#ifndef ROOT_RDONLY +-#define ROOT_RDONLY 1 +-#endif +- +-.code16 +-.text +- +-.global _start +-_start: +- +- # Normalize the start address +- jmpl $BOOTSEG, $start2 +- +-start2: +- movw %cs, %ax +- movw %ax, %ds +- movw %ax, %es +- movw %ax, %ss +- movw $0x7c00, %sp +- sti +- cld +- +- movw $bugger_off_msg, %si +- +-msg_loop: +- lodsb +- andb %al, %al +- jz die +- movb $0xe, %ah +- movw $7, %bx +- int $0x10 +- jmp msg_loop +- +-die: +- # Allow the user to press a key, then reboot +- xorw %ax, %ax +- int $0x16 +- int $0x19 +- +- # int 0x19 should never return. In case it does anyway, +- # invoke the BIOS reset code... +- ljmp $0xf000,$0xfff0 +- +- +-bugger_off_msg: +- .ascii "Direct booting from floppy is no longer supported.\r\n" +- .ascii "Please use a boot loader program instead.\r\n" +- .ascii "\n" +- .ascii "Remove disk and press any key to reboot . . .\r\n" +- .byte 0 +- +- +- # Kernel attributes; used by setup +- +- .org 497 +-setup_sects: .byte SETUPSECTS +-root_flags: .word ROOT_RDONLY +-syssize: .word SYSSIZE +-swap_dev: .word SWAP_DEV +-ram_size: .word RAMDISK +-vid_mode: .word SVGA_MODE +-root_dev: .word ROOT_DEV +-boot_flag: .word 0xAA55 +diff -puN arch/x86_64/boot/compressed/Makefile~git-newsetup arch/x86_64/boot/compressed/Makefile +--- a/arch/x86_64/boot/compressed/Makefile~git-newsetup ++++ a/arch/x86_64/boot/compressed/Makefile +@@ -7,11 +7,12 @@ + # + + targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o +-EXTRA_AFLAGS := -traditional + +-# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with +-# -m32 +-CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2 -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin ++CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \ ++ -fno-strict-aliasing -fPIC -mcmodel=small \ ++ $(call cc-option, -ffreestanding) \ ++ $(call cc-option, -fno-stack-protector) ++AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + LDFLAGS := -m elf_x86_64 + + LDFLAGS_vmlinux := -T +diff -puN arch/x86_64/boot/compressed/head.S~git-newsetup arch/x86_64/boot/compressed/head.S +--- a/arch/x86_64/boot/compressed/head.S~git-newsetup ++++ a/arch/x86_64/boot/compressed/head.S +@@ -46,10 +46,10 @@ startup_32: + * at and where we were actually loaded at. This can only be done + * with a short local call on x86. Nothing else will tell us what + * address we are running at. The reserved chunk of the real-mode +- * data at 0x34-0x3f are used as the stack for this calculation. +- * Only 4 bytes are needed. ++ * data at 0x1e4 (defined as a scratch field) are used as the stack ++ * for this calculation. Only 4 bytes are needed. + */ +- leal 0x40(%esi), %esp ++ leal (0x1e4+4)(%esi), %esp + call 1f + 1: popl %ebp + subl $1b, %ebp +diff -puN arch/x86_64/boot/install.sh~git-newsetup /dev/null +--- a/arch/x86_64/boot/install.sh ++++ /dev/null +@@ -1,2 +0,0 @@ +-#!/bin/sh +-. $srctree/arch/i386/boot/install.sh +diff -puN arch/x86_64/boot/mtools.conf.in~git-newsetup /dev/null +--- a/arch/x86_64/boot/mtools.conf.in ++++ /dev/null +@@ -1,17 +0,0 @@ +-# +-# mtools configuration file for "make (b)zdisk" +-# +- +-# Actual floppy drive +-drive a: +- file="/dev/fd0" +- +-# 1.44 MB floppy disk image +-drive v: +- file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter +- +-# 2.88 MB floppy disk image (mostly for virtual uses) +-drive w: +- file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter +- +- +diff -puN arch/x86_64/boot/setup.S~git-newsetup /dev/null +--- a/arch/x86_64/boot/setup.S ++++ /dev/null +@@ -1,826 +0,0 @@ +-/* +- * setup.S Copyright (C) 1991, 1992 Linus Torvalds +- * +- * setup.s is responsible for getting the system data from the BIOS, +- * and putting them into the appropriate places in system memory. +- * both setup.s and system has been loaded by the bootblock. +- * +- * This code asks the bios for memory/disk/other parameters, and +- * puts them in a "safe" place: 0x90000-0x901FF, ie where the +- * boot-block used to be. It is then up to the protected mode +- * system to read them from there before the area is overwritten +- * for buffer-blocks. +- * +- * Move PS/2 aux init code to psaux.c +- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 +- * +- * some changes and additional features by Christoph Niemann, +- * March 1993/June 1994 (Christoph.Niemann@linux.org) +- * +- * add APM BIOS checking by Stephen Rothwell, May 1994 +- * (sfr@canb.auug.org.au) +- * +- * High load stuff, initrd support and position independency +- * by Hans Lermen & Werner Almesberger, February 1996 +- * , +- * +- * Video handling moved to video.S by Martin Mares, March 1996 +- * +- * +- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david +- * parsons) to avoid loadlin confusion, July 1997 +- * +- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. +- * +- * +- * Fix to work around buggy BIOSes which don't use carry bit correctly +- * and/or report extended memory in CX/DX for e801h memory size detection +- * call. As a result the kernel got wrong figures. The int15/e801h docs +- * from Ralf Brown interrupt list seem to indicate AX/BX should be used +- * anyway. So to avoid breaking many machines (presumably there was a reason +- * to orginally use CX/DX instead of AX/BX), we do a kludge to see +- * if CX/DX have been changed in the e801 call and if so use AX/BX . +- * Michael Miller, April 2001 +- * +- * Added long mode checking and SSE force. March 2003, Andi Kleen. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* Signature words to ensure LILO loaded us right */ +-#define SIG1 0xAA55 +-#define SIG2 0x5A5A +- +-INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way +-SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). +-SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment +- # ... and the former contents of CS +- +-DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 +- +-.code16 +-.globl begtext, begdata, begbss, endtext, enddata, endbss +- +-.text +-begtext: +-.data +-begdata: +-.bss +-begbss: +-.text +- +-start: +- jmp trampoline +- +-# This is the setup header, and it must start at %cs:2 (old 0x9020:2) +- +- .ascii "HdrS" # header signature +- .word 0x0206 # header version number (>= 0x0105) +- # or else old loadlin-1.5 will fail) +-realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +-start_sys_seg: .word SYSSEG +- .word kernel_version # pointing to kernel version string +- # above section of header is compatible +- # with loadlin-1.5 (header v1.5). Don't +- # change it. +- +-type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, +- # Bootlin, SYSLX, bootsect...) +- # See Documentation/i386/boot.txt for +- # assigned ids +- +-# flags, unused bits must be zero (RFU) bit within loadflags +-loadflags: +-LOADED_HIGH = 1 # If set, the kernel is loaded high +-CAN_USE_HEAP = 0x80 # If set, the loader also has set +- # heap_end_ptr to tell how much +- # space behind setup.S can be used for +- # heap purposes. +- # Only the loader knows what is free +-#ifndef __BIG_KERNEL__ +- .byte 0 +-#else +- .byte LOADED_HIGH +-#endif +- +-setup_move_size: .word 0x8000 # size to move, when setup is not +- # loaded at 0x90000. We will move setup +- # to 0x90000 then just before jumping +- # into the kernel. However, only the +- # loader knows how much data behind +- # us also needs to be loaded. +- +-code32_start: # here loaders can put a different +- # start address for 32-bit code. +-#ifndef __BIG_KERNEL__ +- .long 0x1000 # 0x1000 = default for zImage +-#else +- .long 0x100000 # 0x100000 = default for big kernel +-#endif +- +-ramdisk_image: .long 0 # address of loaded ramdisk image +- # Here the loader puts the 32-bit +- # address where it loaded the image. +- # This only will be read by the kernel. +- +-ramdisk_size: .long 0 # its size in bytes +- +-bootsect_kludge: +- .long 0 # obsolete +- +-heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) +- # space from here (exclusive) down to +- # end of setup code can be used by setup +- # for local heap purposes. +- +-pad1: .word 0 +-cmd_line_ptr: .long 0 # (Header version 0x0202 or later) +- # If nonzero, a 32-bit pointer +- # to the kernel command line. +- # The command line should be +- # located between the start of +- # setup and the end of low +- # memory (0xa0000), or it may +- # get overwritten before it +- # gets read. If this field is +- # used, there is no longer +- # anything magical about the +- # 0x90000 segment; the setup +- # can be located anywhere in +- # low memory 0x10000 or higher. +- +-ramdisk_max: .long 0xffffffff +-kernel_alignment: .long 0x200000 # physical addr alignment required for +- # protected mode relocatable kernel +-#ifdef CONFIG_RELOCATABLE +-relocatable_kernel: .byte 1 +-#else +-relocatable_kernel: .byte 0 +-#endif +-pad2: .byte 0 +-pad3: .word 0 +- +-cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, +- #added with boot protocol +- #version 2.06 +- +-trampoline: call start_of_setup +- .align 16 +- # The offset at this point is 0x240 +- .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) +-# End of setup header ##################################################### +- +-start_of_setup: +-# Bootlin depends on this being done early +- movw $0x01500, %ax +- movb $0x81, %dl +- int $0x13 +- +-#ifdef SAFE_RESET_DISK_CONTROLLER +-# Reset the disk controller. +- movw $0x0000, %ax +- movb $0x80, %dl +- int $0x13 +-#endif +- +-# Set %ds = %cs, we know that SETUPSEG = %cs at this point +- movw %cs, %ax # aka SETUPSEG +- movw %ax, %ds +-# Check signature at end of setup +- cmpw $SIG1, setup_sig1 +- jne bad_sig +- +- cmpw $SIG2, setup_sig2 +- jne bad_sig +- +- jmp good_sig1 +- +-# Routine to print asciiz string at ds:si +-prtstr: +- lodsb +- andb %al, %al +- jz fin +- +- call prtchr +- jmp prtstr +- +-fin: ret +- +-# Space printing +-prtsp2: call prtspc # Print double space +-prtspc: movb $0x20, %al # Print single space (note: fall-thru) +- +-prtchr: +- pushw %ax +- pushw %cx +- movw $0007,%bx +- movw $0x01, %cx +- movb $0x0e, %ah +- int $0x10 +- popw %cx +- popw %ax +- ret +- +-beep: movb $0x07, %al +- jmp prtchr +- +-no_sig_mess: .string "No setup signature found ..." +- +-good_sig1: +- jmp good_sig +- +-# We now have to find the rest of the setup code/data +-bad_sig: +- movw %cs, %ax # SETUPSEG +- subw $DELTA_INITSEG, %ax # INITSEG +- movw %ax, %ds +- xorb %bh, %bh +- movb (497), %bl # get setup sect from bootsect +- subw $4, %bx # LILO loads 4 sectors of setup +- shlw $8, %bx # convert to words (1sect=2^8 words) +- movw %bx, %cx +- shrw $3, %bx # convert to segment +- addw $SYSSEG, %bx +- movw %bx, %cs:start_sys_seg +-# Move rest of setup code/data to here +- movw $2048, %di # four sectors loaded by LILO +- subw %si, %si +- movw %cs, %ax # aka SETUPSEG +- movw %ax, %es +- movw $SYSSEG, %ax +- movw %ax, %ds +- rep +- movsw +- movw %cs, %ax # aka SETUPSEG +- movw %ax, %ds +- cmpw $SIG1, setup_sig1 +- jne no_sig +- +- cmpw $SIG2, setup_sig2 +- jne no_sig +- +- jmp good_sig +- +-no_sig: +- lea no_sig_mess, %si +- call prtstr +- +-no_sig_loop: +- jmp no_sig_loop +- +-good_sig: +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %ds +-# Check if an old loader tries to load a big-kernel +- testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? +- jz loader_ok # No, no danger for old loaders. +- +- cmpb $0, %cs:type_of_loader # Do we have a loader that +- # can deal with us? +- jnz loader_ok # Yes, continue. +- +- pushw %cs # No, we have an old loader, +- popw %ds # die. +- lea loader_panic_mess, %si +- call prtstr +- +- jmp no_sig_loop +- +-loader_panic_mess: .string "Wrong loader, giving up..." +- +-loader_ok: +- /* check for long mode. */ +- /* we have to do this before the VESA setup, otherwise the user +- can't see the error message. */ +- +- pushw %ds +- movw %cs,%ax +- movw %ax,%ds +- +- call verify_cpu +- testl %eax,%eax +- jz sse_ok +- +-no_longmode: +- call beep +- lea long_mode_panic,%si +- call prtstr +-no_longmode_loop: +- jmp no_longmode_loop +-long_mode_panic: +- .string "Your CPU does not support long mode. Use a 32bit distribution." +- .byte 0 +- +-#include "../kernel/verify_cpu.S" +-sse_ok: +- popw %ds +- +-# tell BIOS we want to go to long mode +- movl $0xec00,%eax # declare target operating mode +- movl $2,%ebx # long mode +- int $0x15 +- +-# Get memory size (extended mem, kB) +- +- xorl %eax, %eax +- movl %eax, (0x1e0) +-#ifndef STANDARD_MEMORY_BIOS_CALL +- movb %al, (E820NR) +-# Try three different memory detection schemes. First, try +-# e820h, which lets us assemble a memory map, then try e801h, +-# which returns a 32-bit memory size, and finally 88h, which +-# returns 0-64m +- +-# method E820H: +-# the memory map from hell. e820h returns memory classified into +-# a whole bunch of different types, and allows memory holes and +-# everything. We scan through this memory map and build a list +-# of the first 32 memory areas, which we return at [E820MAP]. +-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. +- +-#define SMAP 0x534d4150 +- +-meme820: +- xorl %ebx, %ebx # continuation counter +- movw $E820MAP, %di # point into the whitelist +- # so we can have the bios +- # directly write into it. +- +-jmpe820: +- movl $0x0000e820, %eax # e820, upper word zeroed +- movl $SMAP, %edx # ascii 'SMAP' +- movl $20, %ecx # size of the e820rec +- pushw %ds # data record. +- popw %es +- int $0x15 # make the call +- jc bail820 # fall to e801 if it fails +- +- cmpl $SMAP, %eax # check the return is `SMAP' +- jne bail820 # fall to e801 if it fails +- +-# cmpl $1, 16(%di) # is this usable memory? +-# jne again820 +- +- # If this is usable memory, we save it by simply advancing %di by +- # sizeof(e820rec). +- # +-good820: +- movb (E820NR), %al # up to 128 entries +- cmpb $E820MAX, %al +- jae bail820 +- +- incb (E820NR) +- movw %di, %ax +- addw $20, %ax +- movw %ax, %di +-again820: +- cmpl $0, %ebx # check to see if +- jne jmpe820 # %ebx is set to EOF +-bail820: +- +- +-# method E801H: +-# memory size is in 1k chunksizes, to avoid confusing loadlin. +-# we store the 0xe801 memory size in a completely different place, +-# because it will most likely be longer than 16 bits. +-# (use 1e0 because that's what Larry Augustine uses in his +-# alternative new memory detection scheme, and it's sensible +-# to write everything into the same place.) +- +-meme801: +- stc # fix to work around buggy +- xorw %cx,%cx # BIOSes which don't clear/set +- xorw %dx,%dx # carry on pass/error of +- # e801h memory size call +- # or merely pass cx,dx though +- # without changing them. +- movw $0xe801, %ax +- int $0x15 +- jc mem88 +- +- cmpw $0x0, %cx # Kludge to handle BIOSes +- jne e801usecxdx # which report their extended +- cmpw $0x0, %dx # memory in AX/BX rather than +- jne e801usecxdx # CX/DX. The spec I have read +- movw %ax, %cx # seems to indicate AX/BX +- movw %bx, %dx # are more reasonable anyway... +- +-e801usecxdx: +- andl $0xffff, %edx # clear sign extend +- shll $6, %edx # and go from 64k to 1k chunks +- movl %edx, (0x1e0) # store extended memory size +- andl $0xffff, %ecx # clear sign extend +- addl %ecx, (0x1e0) # and add lower memory into +- # total size. +- +-# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +-# 64mb, depending on the bios) in ax. +-mem88: +- +-#endif +- movb $0x88, %ah +- int $0x15 +- movw %ax, (2) +- +-# Set the keyboard repeat rate to the max +- movw $0x0305, %ax +- xorw %bx, %bx +- int $0x16 +- +-# Check for video adapter and its parameters and allow the +-# user to browse video modes. +- call video # NOTE: we need %ds pointing +- # to bootsector +- +-# Get hd0 data... +- xorw %ax, %ax +- movw %ax, %ds +- ldsw (4 * 0x41), %si +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- pushw %ax +- movw %ax, %es +- movw $0x0080, %di +- movw $0x10, %cx +- pushw %cx +- cld +- rep +- movsb +-# Get hd1 data... +- xorw %ax, %ax +- movw %ax, %ds +- ldsw (4 * 0x46), %si +- popw %cx +- popw %es +- movw $0x0090, %di +- rep +- movsb +-# Check that there IS a hd1 :-) +- movw $0x01500, %ax +- movb $0x81, %dl +- int $0x13 +- jc no_disk1 +- +- cmpb $3, %ah +- je is_disk1 +- +-no_disk1: +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %es +- movw $0x0090, %di +- movw $0x10, %cx +- xorw %ax, %ax +- cld +- rep +- stosb +-is_disk1: +- +-# Check for PS/2 pointing device +- movw %cs, %ax # aka SETUPSEG +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ax, %ds +- movb $0, (0x1ff) # default is no pointing device +- int $0x11 # int 0x11: equipment list +- testb $0x04, %al # check if mouse installed +- jz no_psmouse +- +- movb $0xAA, (0x1ff) # device present +-no_psmouse: +- +-#include "../../i386/boot/edd.S" +- +-# Now we want to move to protected mode ... +- cmpw $0, %cs:realmode_swtch +- jz rmodeswtch_normal +- +- lcall *%cs:realmode_swtch +- +- jmp rmodeswtch_end +- +-rmodeswtch_normal: +- pushw %cs +- call default_switch +- +-rmodeswtch_end: +-# we get the code32 start address and modify the below 'jmpi' +-# (loader may have changed it) +- movl %cs:code32_start, %eax +- movl %eax, %cs:code32 +- +-# Now we move the system to its rightful place ... but we check if we have a +-# big-kernel. In that case we *must* not move it ... +- testb $LOADED_HIGH, %cs:loadflags +- jz do_move0 # .. then we have a normal low +- # loaded zImage +- # .. or else we have a high +- # loaded bzImage +- jmp end_move # ... and we skip moving +- +-do_move0: +- movw $0x100, %ax # start of destination segment +- movw %cs, %bp # aka SETUPSEG +- subw $DELTA_INITSEG, %bp # aka INITSEG +- movw %cs:start_sys_seg, %bx # start of source segment +- cld +-do_move: +- movw %ax, %es # destination segment +- incb %ah # instead of add ax,#0x100 +- movw %bx, %ds # source segment +- addw $0x100, %bx +- subw %di, %di +- subw %si, %si +- movw $0x800, %cx +- rep +- movsw +- cmpw %bp, %bx # assume start_sys_seg > 0x200, +- # so we will perhaps read one +- # page more than needed, but +- # never overwrite INITSEG +- # because destination is a +- # minimum one page below source +- jb do_move +- +-end_move: +-# then we load the segment descriptors +- movw %cs, %ax # aka SETUPSEG +- movw %ax, %ds +- +-# Check whether we need to be downward compatible with version <=201 +- cmpl $0, cmd_line_ptr +- jne end_move_self # loader uses version >=202 features +- cmpb $0x20, type_of_loader +- je end_move_self # bootsect loader, we know of it +- +-# Boot loader doesnt support boot protocol version 2.02. +-# If we have our code not at 0x90000, we need to move it there now. +-# We also then need to move the params behind it (commandline) +-# Because we would overwrite the code on the current IP, we move +-# it in two steps, jumping high after the first one. +- movw %cs, %ax +- cmpw $SETUPSEG, %ax +- je end_move_self +- +- cli # make sure we really have +- # interrupts disabled ! +- # because after this the stack +- # should not be used +- subw $DELTA_INITSEG, %ax # aka INITSEG +- movw %ss, %dx +- cmpw %ax, %dx +- jb move_self_1 +- +- addw $INITSEG, %dx +- subw %ax, %dx # this will go into %ss after +- # the move +-move_self_1: +- movw %ax, %ds +- movw $INITSEG, %ax # real INITSEG +- movw %ax, %es +- movw %cs:setup_move_size, %cx +- std # we have to move up, so we use +- # direction down because the +- # areas may overlap +- movw %cx, %di +- decw %di +- movw %di, %si +- subw $move_self_here+0x200, %cx +- rep +- movsb +- ljmp $SETUPSEG, $move_self_here +- +-move_self_here: +- movw $move_self_here+0x200, %cx +- rep +- movsb +- movw $SETUPSEG, %ax +- movw %ax, %ds +- movw %dx, %ss +-end_move_self: # now we are at the right place +- lidt idt_48 # load idt with 0,0 +- xorl %eax, %eax # Compute gdt_base +- movw %ds, %ax # (Convert %ds:gdt to a linear ptr) +- shll $4, %eax +- addl $gdt, %eax +- movl %eax, (gdt_48+2) +- lgdt gdt_48 # load gdt with whatever is +- # appropriate +- +-# that was painless, now we enable a20 +- call empty_8042 +- +- movb $0xD1, %al # command write +- outb %al, $0x64 +- call empty_8042 +- +- movb $0xDF, %al # A20 on +- outb %al, $0x60 +- call empty_8042 +- +-# +-# You must preserve the other bits here. Otherwise embarrasing things +-# like laptops powering off on boot happen. Corrected version by Kira +-# Brown from Linux 2.2 +-# +- inb $0x92, %al # +- orb $02, %al # "fast A20" version +- outb %al, $0x92 # some chips have only this +- +-# wait until a20 really *is* enabled; it can take a fair amount of +-# time on certain systems; Toshiba Tecras are known to have this +-# problem. The memory location used here (0x200) is the int 0x80 +-# vector, which should be safe to use. +- +- xorw %ax, %ax # segment 0x0000 +- movw %ax, %fs +- decw %ax # segment 0xffff (HMA) +- movw %ax, %gs +-a20_wait: +- incw %ax # unused memory location <0xfff0 +- movw %ax, %fs:(0x200) # we use the "int 0x80" vector +- cmpw %gs:(0x210), %ax # and its corresponding HMA addr +- je a20_wait # loop until no longer aliased +- +-# make sure any possible coprocessor is properly reset.. +- xorw %ax, %ax +- outb %al, $0xf0 +- call delay +- +- outb %al, $0xf1 +- call delay +- +-# well, that went ok, I hope. Now we mask all interrupts - the rest +-# is done in init_IRQ(). +- movb $0xFF, %al # mask all interrupts for now +- outb %al, $0xA1 +- call delay +- +- movb $0xFB, %al # mask all irq's but irq2 which +- outb %al, $0x21 # is cascaded +- +-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't +-# need no steenking BIOS anyway (except for the initial loading :-). +-# The BIOS-routine wants lots of unnecessary data, and it's less +-# "interesting" anyway. This is how REAL programmers do it. +-# +-# Well, now's the time to actually move into protected mode. To make +-# things as simple as possible, we do no register set-up or anything, +-# we let the gnu-compiled 32-bit programs do that. We just jump to +-# absolute address 0x1000 (or the loader supplied one), +-# in 32-bit protected mode. +-# +-# Note that the short jump isn't strictly needed, although there are +-# reasons why it might be a good idea. It won't hurt in any case. +- movw $1, %ax # protected mode (PE) bit +- lmsw %ax # This is it! +- jmp flush_instr +- +-flush_instr: +- xorw %bx, %bx # Flag to indicate a boot +- xorl %esi, %esi # Pointer to real-mode code +- movw %cs, %si +- subw $DELTA_INITSEG, %si +- shll $4, %esi # Convert to 32-bit pointer +-# NOTE: For high loaded big kernels we need a +-# jmpi 0x100000,__KERNEL_CS +-# +-# but we yet haven't reloaded the CS register, so the default size +-# of the target offset still is 16 bit. +-# However, using an operand prefix (0x66), the CPU will properly +-# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference +-# Manual, Mixing 16-bit and 32-bit code, page 16-6) +- +- .byte 0x66, 0xea # prefix + jmpi-opcode +-code32: .long 0x1000 # will be set to 0x100000 +- # for big kernels +- .word __KERNEL_CS +- +-# Here's a bunch of information about your current kernel.. +-kernel_version: .ascii UTS_RELEASE +- .ascii " (" +- .ascii LINUX_COMPILE_BY +- .ascii "@" +- .ascii LINUX_COMPILE_HOST +- .ascii ") " +- .ascii UTS_VERSION +- .byte 0 +- +-# This is the default real mode switch routine. +-# to be called just before protected mode transition +-default_switch: +- cli # no interrupts allowed ! +- movb $0x80, %al # disable NMI for bootup +- # sequence +- outb %al, $0x70 +- lret +- +- +-# This routine checks that the keyboard command queue is empty +-# (after emptying the output buffers) +-# +-# Some machines have delusions that the keyboard buffer is always full +-# with no keyboard attached... +-# +-# If there is no keyboard controller, we will usually get 0xff +-# to all the reads. With each IO taking a microsecond and +-# a timeout of 100,000 iterations, this can take about half a +-# second ("delay" == outb to port 0x80). That should be ok, +-# and should also be plenty of time for a real keyboard controller +-# to empty. +-# +- +-empty_8042: +- pushl %ecx +- movl $100000, %ecx +- +-empty_8042_loop: +- decl %ecx +- jz empty_8042_end_loop +- +- call delay +- +- inb $0x64, %al # 8042 status port +- testb $1, %al # output buffer? +- jz no_output +- +- call delay +- inb $0x60, %al # read it +- jmp empty_8042_loop +- +-no_output: +- testb $2, %al # is input buffer full? +- jnz empty_8042_loop # yes - loop +-empty_8042_end_loop: +- popl %ecx +- ret +- +-# Read the cmos clock. Return the seconds in al +-gettime: +- pushw %cx +- movb $0x02, %ah +- int $0x1a +- movb %dh, %al # %dh contains the seconds +- andb $0x0f, %al +- movb %dh, %ah +- movb $0x04, %cl +- shrb %cl, %ah +- aad +- popw %cx +- ret +- +-# Delay is needed after doing I/O +-delay: +- outb %al,$0x80 +- ret +- +-# Descriptor tables +-gdt: +- .word 0, 0, 0, 0 # dummy +- +- .word 0, 0, 0, 0 # unused +- +- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) +- .word 0 # base address = 0 +- .word 0x9A00 # code read/exec +- .word 0x00CF # granularity = 4096, 386 +- # (+5th nibble of limit) +- +- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) +- .word 0 # base address = 0 +- .word 0x9200 # data read/write +- .word 0x00CF # granularity = 4096, 386 +- # (+5th nibble of limit) +-gdt_end: +-idt_48: +- .word 0 # idt limit = 0 +- .word 0, 0 # idt base = 0L +-gdt_48: +- .word gdt_end-gdt-1 # gdt limit +- .word 0, 0 # gdt base (filled in later) +- +-# Include video setup & detection code +- +-#include "../../i386/boot/video.S" +- +-# Setup signature -- must be last +-setup_sig1: .word SIG1 +-setup_sig2: .word SIG2 +- +-# After this point, there is some free space which is used by the video mode +-# handling code to store the temporary mode table (not used by the kernel). +- +-modelist: +- +-.text +-endtext: +-.data +-enddata: +-.bss +-endbss: +diff -puN arch/x86_64/boot/tools/build.c~git-newsetup /dev/null +--- a/arch/x86_64/boot/tools/build.c ++++ /dev/null +@@ -1,185 +0,0 @@ +-/* +- * Copyright (C) 1991, 1992 Linus Torvalds +- * Copyright (C) 1997 Martin Mares +- */ +- +-/* +- * This file builds a disk-image from three different files: +- * +- * - bootsect: compatibility mbr which prints an error message if +- * someone tries to boot the kernel directly. +- * - setup: 8086 machine code, sets up system parm +- * - system: 80386 code for actual system +- * +- * It does some checking that all files are of the correct type, and +- * just writes the result to stdout, removing headers and padding to +- * the right amount. It also writes some system data to stderr. +- */ +- +-/* +- * Changes by tytso to allow root device specification +- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 +- * Cross compiling fixes by Gertjan van Wingerde, July 1996 +- * Rewritten by Martin Mares, April 1997 +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-typedef unsigned char byte; +-typedef unsigned short word; +-typedef unsigned long u32; +- +-#define DEFAULT_MAJOR_ROOT 0 +-#define DEFAULT_MINOR_ROOT 0 +- +-/* Minimal number of setup sectors (see also bootsect.S) */ +-#define SETUP_SECTS 4 +- +-byte buf[1024]; +-int fd; +-int is_big_kernel; +- +-void die(const char * str, ...) +-{ +- va_list args; +- va_start(args, str); +- vfprintf(stderr, str, args); +- fputc('\n', stderr); +- exit(1); +-} +- +-void file_open(const char *name) +-{ +- if ((fd = open(name, O_RDONLY, 0)) < 0) +- die("Unable to open `%s': %m", name); +-} +- +-void usage(void) +-{ +- die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); +-} +- +-int main(int argc, char ** argv) +-{ +- unsigned int i, c, sz, setup_sectors; +- u32 sys_size; +- byte major_root, minor_root; +- struct stat sb; +- +- if (argc > 2 && !strcmp(argv[1], "-b")) +- { +- is_big_kernel = 1; +- argc--, argv++; +- } +- if ((argc < 4) || (argc > 5)) +- usage(); +- if (argc > 4) { +- if (!strcmp(argv[4], "CURRENT")) { +- if (stat("/", &sb)) { +- perror("/"); +- die("Couldn't stat /"); +- } +- major_root = major(sb.st_dev); +- minor_root = minor(sb.st_dev); +- } else if (strcmp(argv[4], "FLOPPY")) { +- if (stat(argv[4], &sb)) { +- perror(argv[4]); +- die("Couldn't stat root device."); +- } +- major_root = major(sb.st_rdev); +- minor_root = minor(sb.st_rdev); +- } else { +- major_root = 0; +- minor_root = 0; +- } +- } else { +- major_root = DEFAULT_MAJOR_ROOT; +- minor_root = DEFAULT_MINOR_ROOT; +- } +- fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); +- +- file_open(argv[1]); +- i = read(fd, buf, sizeof(buf)); +- fprintf(stderr,"Boot sector %d bytes.\n",i); +- if (i != 512) +- die("Boot block must be exactly 512 bytes"); +- if (buf[510] != 0x55 || buf[511] != 0xaa) +- die("Boot block hasn't got boot flag (0xAA55)"); +- buf[508] = minor_root; +- buf[509] = major_root; +- if (write(1, buf, 512) != 512) +- die("Write call failed"); +- close (fd); +- +- file_open(argv[2]); /* Copy the setup code */ +- for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) +- if (write(1, buf, c) != c) +- die("Write call failed"); +- if (c != 0) +- die("read-error on `setup'"); +- close (fd); +- +- setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ +- /* for compatibility with ancient versions of LILO. */ +- if (setup_sectors < SETUP_SECTS) +- setup_sectors = SETUP_SECTS; +- fprintf(stderr, "Setup is %d bytes.\n", i); +- memset(buf, 0, sizeof(buf)); +- while (i < setup_sectors * 512) { +- c = setup_sectors * 512 - i; +- if (c > sizeof(buf)) +- c = sizeof(buf); +- if (write(1, buf, c) != c) +- die("Write call failed"); +- i += c; +- } +- +- file_open(argv[3]); +- if (fstat (fd, &sb)) +- die("Unable to stat `%s': %m", argv[3]); +- sz = sb.st_size; +- fprintf (stderr, "System is %d kB\n", sz/1024); +- sys_size = (sz + 15) / 16; +- if (!is_big_kernel && sys_size > DEF_SYSSIZE) +- die("System is too big. Try using bzImage or modules."); +- while (sz > 0) { +- int l, n; +- +- l = (sz > sizeof(buf)) ? sizeof(buf) : sz; +- if ((n=read(fd, buf, l)) != l) { +- if (n < 0) +- die("Error reading %s: %m", argv[3]); +- else +- die("%s: Unexpected EOF", argv[3]); +- } +- if (write(1, buf, l) != l) +- die("Write failed"); +- sz -= l; +- } +- close(fd); +- +- if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ +- die("Output: seek failed"); +- buf[0] = setup_sectors; +- if (write(1, buf, 1) != 1) +- die("Write of setup sector count failed"); +- if (lseek(1, 500, SEEK_SET) != 500) +- die("Output: seek failed"); +- buf[0] = (sys_size & 0xff); +- buf[1] = ((sys_size >> 8) & 0xff); +- buf[2] = ((sys_size >> 16) & 0xff); +- buf[3] = ((sys_size >> 24) & 0xff); +- if (write(1, buf, 4) != 4) +- die("Write of image length failed"); +- +- return 0; /* Everything is OK */ +-} +diff -puN arch/x86_64/kernel/Makefile~git-newsetup arch/x86_64/kernel/Makefile +--- a/arch/x86_64/kernel/Makefile~git-newsetup ++++ a/arch/x86_64/kernel/Makefile +@@ -45,6 +45,7 @@ obj-$(CONFIG_PCI) += early-quirks.o + + obj-y += topology.o + obj-y += intel_cacheinfo.o ++obj-y += addon_cpuid_features.o + obj-y += pcspeaker.o + + CFLAGS_vsyscall.o := $(PROFILING) -g0 +@@ -58,6 +59,7 @@ cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) + topology-y += ../../i386/kernel/topology.o + microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o + intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o ++addon_cpuid_features-y += ../../i386/kernel/cpu/addon_cpuid_features.o + quirks-y += ../../i386/kernel/quirks.o + i8237-y += ../../i386/kernel/i8237.o + msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o +diff -puN arch/x86_64/kernel/setup.c~git-newsetup arch/x86_64/kernel/setup.c +--- a/arch/x86_64/kernel/setup.c~git-newsetup ++++ a/arch/x86_64/kernel/setup.c +@@ -855,6 +855,8 @@ void __cpuinit identify_cpu(struct cpuin + c->x86_capability[2] = cpuid_edx(0x80860001); + } + ++ init_scattered_cpuid_features(c); ++ + c->apicid = phys_pkg_id(0); + + /* +@@ -940,7 +942,7 @@ static int show_cpuinfo(struct seq_file + "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", + "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", + "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", +- "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, ++ "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", + + /* AMD-defined */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +@@ -956,10 +958,11 @@ static int show_cpuinfo(struct seq_file + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Other (Linux-defined) */ +- "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL, +- "constant_tsc", NULL, NULL, +- "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", ++ NULL, NULL, NULL, NULL, ++ "constant_tsc", "up", NULL, "arch_perfmon", ++ "pebs", "bts", NULL, "sync_rdtsc", ++ "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Intel-defined (#2) */ +@@ -970,7 +973,7 @@ static int show_cpuinfo(struct seq_file + + /* VIA/Cyrix/Centaur-defined */ + NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", +- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +@@ -981,6 +984,12 @@ static int show_cpuinfo(struct seq_file + "osvw", "ibs", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ ++ /* Auxiliary (Linux-defined) */ ++ "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + }; + static char *x86_power_flags[] = { + "ts", /* temperature sensor */ +diff -puN arch/x86_64/kernel/verify_cpu.S~git-newsetup arch/x86_64/kernel/verify_cpu.S +--- a/arch/x86_64/kernel/verify_cpu.S~git-newsetup ++++ a/arch/x86_64/kernel/verify_cpu.S +@@ -37,20 +37,6 @@ verify_cpu: + pushl $0 # Kill any dangerous flags + popfl + +- /* minimum CPUID flags for x86-64 as defined by AMD */ +-#define M(x) (1<<(x)) +-#define M2(a,b) M(a)|M(b) +-#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d) +- +-#define SSE_MASK \ +- (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2)) +-#define REQUIRED_MASK1 \ +- (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\ +- M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\ +- M(X86_FEATURE_FXSR)) +-#define REQUIRED_MASK2 \ +- (M(X86_FEATURE_LM - 32)) +- + pushfl # standard way to check for cpuid + popl %eax + movl %eax,%ebx +@@ -79,8 +65,8 @@ verify_cpu: + verify_cpu_noamd: + movl $0x1,%eax # Does the cpu have what it takes + cpuid +- andl $REQUIRED_MASK1,%edx +- xorl $REQUIRED_MASK1,%edx ++ andl $REQUIRED_MASK0,%edx ++ xorl $REQUIRED_MASK0,%edx + jnz verify_cpu_no_longmode + + movl $0x80000000,%eax # See if extended cpuid is implemented +@@ -90,8 +76,8 @@ verify_cpu_noamd: + + movl $0x80000001,%eax # Does the cpu have what it takes + cpuid +- andl $REQUIRED_MASK2,%edx +- xorl $REQUIRED_MASK2,%edx ++ andl $REQUIRED_MASK1,%edx ++ xorl $REQUIRED_MASK1,%edx + jnz verify_cpu_no_longmode + + verify_cpu_sse_test: +diff -puN drivers/ide/legacy/hd.c~git-newsetup drivers/ide/legacy/hd.c +--- a/drivers/ide/legacy/hd.c~git-newsetup ++++ a/drivers/ide/legacy/hd.c +@@ -718,74 +718,25 @@ static int __init hd_init(void) + device_timer.function = hd_times_out; + blk_queue_hardsect_size(hd_queue, 512); + +-#ifdef __i386__ + if (!NR_HD) { +- extern struct drive_info drive_info; +- unsigned char *BIOS = (unsigned char *) &drive_info; +- unsigned long flags; +- int cmos_disks; +- +- for (drive=0 ; drive<2 ; drive++) { +- hd_info[drive].cyl = *(unsigned short *) BIOS; +- hd_info[drive].head = *(2+BIOS); +- hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); +- hd_info[drive].ctl = *(8+BIOS); +- hd_info[drive].lzone = *(unsigned short *) (12+BIOS); +- hd_info[drive].sect = *(14+BIOS); +-#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp +- if (hd_info[drive].cyl && NR_HD == drive) +- NR_HD++; +-#endif +- BIOS += 16; +- } +- +- /* +- We query CMOS about hard disks : it could be that +- we have a SCSI/ESDI/etc controller that is BIOS +- compatible with ST-506, and thus showing up in our +- BIOS table, but not register compatible, and therefore +- not present in CMOS. +- +- Furthermore, we will assume that our ST-506 drives +- are the primary drives in the system, and +- the ones reflected as drive 1 or 2. +- +- The first drive is stored in the high nibble of CMOS +- byte 0x12, the second in the low nibble. This will be +- either a 4 bit drive type or 0xf indicating use byte 0x19 +- for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. +- +- Needless to say, a non-zero value means we have +- an AT controller hard disk for that drive. +- +- Currently the rtc_lock is a bit academic since this +- driver is non-modular, but someday... ? Paul G. +- */ +- +- spin_lock_irqsave(&rtc_lock, flags); +- cmos_disks = CMOS_READ(0x12); +- spin_unlock_irqrestore(&rtc_lock, flags); +- +- if (cmos_disks & 0xf0) { +- if (cmos_disks & 0x0f) +- NR_HD = 2; +- else +- NR_HD = 1; +- } +- } +-#endif /* __i386__ */ +-#ifdef __arm__ +- if (!NR_HD) { +- /* We don't know anything about the drive. This means ++ /* ++ * We don't know anything about the drive. This means + * that you *MUST* specify the drive parameters to the + * kernel yourself. ++ * ++ * If we were on an i386, we used to read this info from ++ * the BIOS or CMOS. This doesn't work all that well, ++ * since this assumes that this is a primary or secondary ++ * drive, and if we're using this legacy driver, it's ++ * probably an auxilliary controller added to recover ++ * legacy data off an ST-506 drive. Either way, it's ++ * definitely safest to have the user explicitly specify ++ * the information. + */ + printk("hd: no drives specified - use hd=cyl,head,sectors" + " on kernel command line\n"); +- } +-#endif +- if (!NR_HD) + goto out; ++ } + + for (drive=0 ; drive < NR_HD ; drive++) { + struct gendisk *disk = alloc_disk(64); +diff -puN include/asm-i386/boot.h~git-newsetup include/asm-i386/boot.h +--- a/include/asm-i386/boot.h~git-newsetup ++++ a/include/asm-i386/boot.h +@@ -1,5 +1,5 @@ +-#ifndef _LINUX_BOOT_H +-#define _LINUX_BOOT_H ++#ifndef _ASM_BOOT_H ++#define _ASM_BOOT_H + + /* Don't touch these, unless you really know what you're doing. */ + #define DEF_INITSEG 0x9000 +@@ -17,4 +17,4 @@ + + (CONFIG_PHYSICAL_ALIGN - 1)) \ + & ~(CONFIG_PHYSICAL_ALIGN - 1)) + +-#endif /* _LINUX_BOOT_H */ ++#endif /* _ASM_BOOT_H */ +diff -puN /dev/null include/asm-i386/bootparam.h +--- /dev/null ++++ a/include/asm-i386/bootparam.h +@@ -0,0 +1,85 @@ ++#ifndef _ASM_BOOTPARAM_H ++#define _ASM_BOOTPARAM_H ++ ++#include ++#include ++#include ++#include ++#include ++#include