mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-29 21:14:28 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			11943 lines
		
	
	
		
			310 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			11943 lines
		
	
	
		
			310 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| GIT 1783e2f0f21444020e3dee1be46b1e34af0ea3e7 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-newsetup.git
 | |
| 
 | |
| commit 1783e2f0f21444020e3dee1be46b1e34af0ea3e7
 | |
| Author: Venki Pallipadi <venkatesh.pallipadi@intel.com>
 | |
| 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 <venkatesh.pallipadi@intel.com>
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit cd19eb67cd6636a4e5c9df99631422c7c7286f59
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 100327ad6b609cd28970219be57d293847d1261d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 7c91a172b8af7d4ba087f1f88ed5b155ed459ca3
 | |
| Author: Antonino A. Daplas <adaplas@gmail.com>
 | |
| 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 <adaplas@gmail.com>
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 6eac2d442de8d87eac94a4ca8600bd87219fa06b
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit f7d89f05a30433034a1b4651143afdbb2a8a9c92
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 14c2fdb3bbfd6a9a774980e446c2443150749891
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit e071b068a3b9f318be314f0378e655e2eb50ac89
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit abe0c5aa1827932cda9c754a3842ec22b278d704
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit c2e5887ad275aab90673a3e33344f09946159cf7
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit ce82e3b93eba48b6852822a03efa73c74e165d4f
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit e5f3a529457a5bfaf8f8783fb86013221279a81c
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit d9dbde725687ab99d1f529f49f14d1e280cc5cac
 | |
| Author: Alexander van Heukelum <heukelum@mailshack.com>
 | |
| 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 <heukelum@mailshack.com>
 | |
| 
 | |
| commit 0d7558a81cf61e9fd2332a54897c5fd18df0d7f2
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 017ce54e8a4a9628a76d6b510c7309a7e4e111a8
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit b794f5f9c5089709f3df38c6d91869fa38a9c1a4
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 21c2b7c99c417d07015ee8e516a634ec3d98c4ee
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 52ca0431390d389a2a2246f02fe652ea84c1ddd8
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 4db77a97793104a32e5fb83e62b943fa144b329d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 4fbccbc1457d6710d3a9ce55ad70ec6cb0b75fc5
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Tue May 15 09:16:29 2007 -0700
 | |
| 
 | |
|     x86 setup: include <asm/msr-index.h> not <asm/msr.h>
 | |
|     
 | |
|     <asm/msr.h> 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 <asm/msr-index.h>
 | |
|     instead, which only includes the numeric constants.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 839cafa9c0020e7506722dd2a4fd82a71c2939cc
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit d60357ad68a694b03e9b952eadba5ac277c31df0
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Sat May 12 12:18:53 2007 -0700
 | |
| 
 | |
|     x86 setup: remove unused variable
 | |
|     
 | |
|     Remove unused variable
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit e21a2030b01081612259847321bcce13eae1e883
 | |
| Author: Sam Ravnborg <sam@ravnborg.org>
 | |
| 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 <sam@ravnborg.org>
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 8618d92339d0d106045f98f34833d863c3235cdb
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 85dfc374ea9aad33b9e0315f07a4b2722dc11e3e
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit f4f7949f126d2f152b09fa9367b1ec693f2ea818
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 51ba7113ea5b07189b7f8a0534d400a072535197
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 1b8f73d9b2bf7630a2914ddab606db16fddb509e
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit b81f3c88923e4470cd0942d4596fafc0fb1cf4fd
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit be58b6d7e9c14e482bce495e8343955999dea77f
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 22f6bd8cc23b512af28e34ae7d40036982a0ac63
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 7f73f1f4aa4c97745bffe07a3ebcf226a4965b00
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 6770176714bc12ec92372311ac02c14f0d22776e
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Thu May 10 15:24:27 2007 -0700
 | |
| 
 | |
|     x86 setup: whitespace cleanup
 | |
|     
 | |
|     Clean up stealth whitespace.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit ba0480a3537cf471b08bdb99dae6d0780cfb1972
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Wed May 9 16:54:42 2007 -0700
 | |
| 
 | |
|     x86: sync the CPU feature string arrays
 | |
|     
 | |
|     With <asm/cpufeature.h> unified, synchronize the CPU feature string
 | |
|     arrays.  The whole kernel/cpu directory really needs to be unified.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit ecb53b84efddbad3d9aa49e95598550831324348
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit dc97fc053faff17b984ec962686caea52bd27628
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 7907f05e9692557c53c9ac13647db5e5343c7c76
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 8e509f9ebc44f45544d231454e84f10bf78d5772
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 9912b9aed7943773d1fadaa2e2e52f42af395048
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 732eb3fac2d772980e6555b8c69902c8107c72aa
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 2d5e47f21202e156fe97aba0a88d158d5c157a33
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit bf2a428a4e7c1ee3ab9acb23cfafb45e818887a1
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 9ea8429fabe5df6aed6393ac3a00d0b64445ba6a
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 9edc55718f57195c664ee3175514d652f651cfd2
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit e1003433f2d491bf17c79437cd75268da220dab5
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 853499c3dc3fcbeb192a613ac241d150ebc7c5a0
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit f235a61f6d6dff57883efad351d746540bcb8caf
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 0d0e10091be48f7e4c8888e9d5c2836c704994f5
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 47aab0b8f4d012fad3c42b5b0754d3cb87961b37
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit d22571534d7eabf9408f29d9da423e1c6e04445f
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit e5145601a752bd998e783d159c187d3017d45d6d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Sat May 5 15:20:19 2007 -0700
 | |
| 
 | |
|     x86 setup: whitespace cleanup
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 045ecb52f91a74eecad93ffc8791eefe59cf7fd1
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 58c04ed7e2d7d5979e1917a74b49bdc0f3dde211
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 07bc3931175fb98256140275c03194426d441b74
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit a830f615eeef838d461cbf7bbbee8c1c84708ec8
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 3e159a323bdfa5d5a7be2c1f6be089ca22d598e0
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 4cf4424e7a0f29f251b781f9b5e3655b0645cb7f
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 7c616d098579fb790662cdc703f2a0f26ea1668c
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 5bc1019227e94576e4876d05ee920f59195bce90
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 0f96b52497f444be2d52d1184ca90be49f713ea3
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 3a23a428b20cbb31fd7ff5516a053b99afc447f7
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit e93ec58911995971aa059990f8a91a02b05f6c8f
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 2f47f004f614e2744867c0df274c55d8af2a42d5
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Fri May 4 12:06:04 2007 -0700
 | |
| 
 | |
|     x86: fix differences between i386 and x86-64 <asm/e820.h>
 | |
|     
 | |
|     Fix minor differences between i386 and x86-64 <asm/e820.h>
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 56ec52f14e948f430af941052adee98019a617b7
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 1d4429eaa564b0085d9ee3aa2de57e87a093a14e
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 6a85f1b5fd041ea99d8604782559ce0502a60cc0
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <asm/alternative.h>
 | |
|     and <asm/cpufeature.h>; resolve this.
 | |
|     
 | |
|     Add #ifndef _SETUP in <asm/e820.h> so it can be included from the boot
 | |
|     code.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit f6bbdc254bdbd5f7cf7a40c4cd6f9844af90824a
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Fri May 4 10:40:26 2007 -0700
 | |
| 
 | |
|     x86: Complete <asm/cpufeature.h> with the union of i386 and x86-64
 | |
|     
 | |
|     Add a feature to <asm/cpufeature.h> which was previously present
 | |
|     in x86-64 but missing in i386.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 1a0819281060489901732914f67869e0aa8f26fd
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Fri May 4 10:39:32 2007 -0700
 | |
| 
 | |
|     x86: unify <asm/boot.h>
 | |
|     
 | |
|     Unify <asm/boot.h> between i386 and x86-64
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 8d9c54585f4623e0310f970fb5c6eda7ec1614df
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Fri May 4 10:38:35 2007 -0700
 | |
| 
 | |
|     x86-64: verify_cpu.S: use new masks
 | |
|     
 | |
|     Use the <asm/required-features.h> masks.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 6cf3308646bb7a3210f0f76bcb895b2dea76a93c
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 1324201a93ce380b46a3128826ecbd794e617e59
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Fri May 4 10:35:37 2007 -0700
 | |
| 
 | |
|     x86-64: <asm/segment.h>: add boot segment descriptors
 | |
|     
 | |
|     Add boot segment descriptors to <asm/segment.h> to match i386.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit a0b15a9e79ed0310813709cd0690d6838917fe82
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 8f5d14d11a7318e257351ae477392c7f7e314602
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit a32f68b6d4023c1c6b1e62e8561189516c571ab9
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 4f34ca8e926b2d0bf3a7502b99f8dfced8cdba9d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 19eb9b73cc1632a923003a002108b242af7a6080
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 3b9fb73c65151ee043bc74c333d9e3c9b1872125
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit a6d01d375a2269be1e3a6b31bcc4d426ad5a473d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit cbe5b7585d800435080bcbf1b1fd242926982674
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Thu May 3 10:33:12 2007 -0700
 | |
| 
 | |
|     x86 setup: use the required masks from <asm/required-features.h>
 | |
|     
 | |
|     Use the now-uniform features from <asm/required-features.h>.
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 99ed30180ecc1bb4e93f6edda5f6bad1adf3e630
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 1120d70a2be8f2deb6bda64047da288d8f86dad3
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit ebc308c204149b86984ae2216f5b9b2e63932028
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 8b50b640e015bf5d0f65502437da6fcab46c391b
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 35d23b60dfb110da81c24bcbfcda089cfc4fd264
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Wed May 2 23:37:50 2007 -0700
 | |
| 
 | |
|     x86 setup: cpu detection cleanups
 | |
|     
 | |
|     - Use <asm/processor-flags.h>
 | |
|     - Make sure %cr0 isn't in a dangerous configuration before probing the FPU
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit a1150a03247b355d11a4bb696b8aae1f46612992
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 7eb52e8ad1bdf01886023d1a13b3313084cd7db6
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit e90317a027c30176968220d18eb18bd6a9d9cc74
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 060f9b3db33c67b5344b2b4110bc823eb776e5cd
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Wed May 2 19:51:34 2007 -0700
 | |
| 
 | |
|     x86 setup: whitespace cleanup
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 9f997a5569ec8fceaa15c2e9cf28e728e2ce118d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit de4e976376fddec340651ef40b16a45f6189619d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Wed May 2 19:05:34 2007 -0700
 | |
| 
 | |
|     x86 setup: whitespace cleanup
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit bcd2d2f8de5d4568b6628aa133fce1ac40ece526
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 752aef90cbfc888084bf11fd83f8f72b6a668fc9
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit dde94003e4759aab275732cf9f1834440cd381d0
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 9403917d79e3349184318704476fa080836bd52c
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 712f65ffbd1d4b55b4c55d68b4dcd32406c28fb8
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 9cf083204fe14cda3b09840eba8d131d2e48ccdf
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 890cbe950589e30af17eac9da800efc76e35e01d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 08a44dc655e0086d23fc3c70cb93eb51eaeec259
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 57e69acff1f577de430cae1523fd49a5d113e885
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit c0dda0b90f92d43872d55d295630a71cd357cfa6
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 0db5086e79810e7c5d560006b1c9a7501a02d80c
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 41f3fddeeb764687bf3fb0cf77fd858128571d58
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit dfa94cd86aca2c01d2f5e14b6e7c3e8258276195
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 2487575a36435c0a983febbb4f3751331bd2df7a
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 530d4f4f1732335ae8725c0b8c332a618e63ea1d
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 8617cd56ff2e43303147da012b26c9dd46af726e
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| Date:   Tue May 1 21:32:47 2007 -0700
 | |
| 
 | |
|     x86 setup: fix missing semicolon in video-ati.c
 | |
|     
 | |
|     Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 | |
| 
 | |
| commit 7bbf7fa3e199b9cef4877c5a56128faff8636cc9
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 45bcd4406e4b812b32d317d9b3b8db2e5f135a3c
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit a39479d4ccf4dceffb623ad2ec7e2d708c38c637
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit d8f3d4928ead72e8febe2fcd740d0fee71a61f42
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 4f1462ed0377e180484a223e622d62432baa64b7
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit a5ba7e6df198bd204b0f87fc6e3f68388b9d14c1
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| 
 | |
| commit 6c821fc005655a99eff6e86c2e4b13654de94dea
 | |
| Author: H. Peter Anvin <hpa@zytor.com>
 | |
| 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 <hpa@zytor.com>
 | |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
 | |
| ---
 | |
| 
 | |
|  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 <linux/bitops.h> */
 | |
| +
 | |
| +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 <stdarg.h>
 | |
| +#include <linux/types.h>
 | |
| +#include <linux/edd.h>
 | |
| +#include <asm/boot.h>
 | |
| +#include <asm/bootparam.h>
 | |
| +
 | |
| +/* 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 <asm/boot.h>
 | |
| -
 | |
| -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 <linux/linkage.h>
 | |
| -#include <linux/vmalloc.h>
 | |
|  #include <linux/screen_info.h>
 | |
|  #include <asm/io.h>
 | |
|  #include <asm/page.h>
 | |
| @@ -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 <asm/cpufeature.h>
 | |
| +
 | |
| +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 <linux/types.h>
 | |
| +#include <asm/cpufeature.h>
 | |
| +#include <asm/processor-flags.h>
 | |
| +#include <asm/required-features.h>
 | |
| +#include <asm/msr-index.h>
 | |
| +
 | |
| +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 <Matt_Domsch@dell.com> October 2002
 | |
| - * conformant to T13 Committee www.t13.org
 | |
| - *   projects 1572D, 1484D, 1386D, 1226DT
 | |
| - * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
 | |
| - *	and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
 | |
| - * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
 | |
| - *      March 2004
 | |
| - * Command line option parsing, Matt Domsch, November 2004
 | |
| - */
 | |
| -
 | |
| -#include <linux/edd.h>
 | |
| -#include <asm/setup.h>
 | |
| -
 | |
| -#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 <linux/edd.h>
 | |
| +
 | |
| +#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 <asm/segment.h>
 | |
| +#include <linux/utsrelease.h>
 | |
| +#include <asm/boot.h>
 | |
| +#include <asm/e820.h>
 | |
| +#include <asm/page.h>
 | |
| +#include <asm/setup.h>
 | |
| +#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 <asm/segment.h>
 | |
| +
 | |
| +/*
 | |
| + * 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 <asm/boot.h>
 | |
| +#include <asm/segment.h>
 | |
| +
 | |
| +	.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
 | |
| - * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
 | |
| - *
 | |
| - * Video handling moved to video.S by Martin Mares, March 1996
 | |
| - * <mj@k332.feld.cvut.cz>
 | |
| - *
 | |
| - * 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.
 | |
| - * <stiker@northlink.com>
 | |
| - *
 | |
| - * 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 <michaelm@mjmm.org>
 | |
| - *
 | |
| - * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
 | |
| - * by Robert Schwebel, December 2001 <robert@schwebel.de>
 | |
| - */
 | |
| -
 | |
| -#include <asm/segment.h>
 | |
| -#include <linux/utsrelease.h>
 | |
| -#include <linux/compile.h>
 | |
| -#include <asm/boot.h>
 | |
| -#include <asm/e820.h>
 | |
| -#include <asm/page.h>
 | |
| -#include <asm/setup.h>
 | |
| -	
 | |
| -/* 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 <linux/edd.h>
 | |
| +
 | |
| +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 <stdio.h>
 | |
| @@ -32,23 +32,25 @@
 | |
|  #include <sys/sysmacros.h>
 | |
|  #include <unistd.h>
 | |
|  #include <fcntl.h>
 | |
| +#include <sys/mman.h>
 | |
|  #include <asm/boot.h>
 | |
|  
 | |
| -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 <linux/utsrelease.h>
 | |
| +#include <linux/compile.h>
 | |
| +
 | |
| +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 <mj@ucw.cz>
 | |
| - *	Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
 | |
| - *
 | |
| - *	Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> 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 <RETURN> to see video modes available, "
 | |
| -		.ascii	"<SPACE> 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 <mj@ucw.cz>."
 | |
| -		.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 <ENTER> to see video modes available, "
 | |
| +	     "<SPACE> 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 <linux/types.h>
 | |
| +
 | |
| +/* 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 <linux/cpu.h>
 | |
| +
 | |
| +#include <asm/processor.h>
 | |
| +
 | |
| +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 <asm/cpufeature.h>
 | |
| -#include <asm/msr.h>
 | |
| -
 | |
| -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 <asm/boot.h>
 | |
| -
 | |
| -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
 | |
| - * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
 | |
| - *
 | |
| - * Video handling moved to video.S by Martin Mares, March 1996
 | |
| - * <mj@k332.feld.cvut.cz>
 | |
| - *
 | |
| - * 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.
 | |
| - * <stiker@northlink.com>
 | |
| - *
 | |
| - * 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 <michaelm@mjmm.org>
 | |
| - *
 | |
| - * Added long mode checking and SSE force. March 2003, Andi Kleen.		
 | |
| - */
 | |
| -
 | |
| -#include <asm/segment.h>
 | |
| -#include <linux/utsrelease.h>
 | |
| -#include <linux/compile.h>
 | |
| -#include <asm/boot.h>
 | |
| -#include <asm/e820.h>
 | |
| -#include <asm/page.h>
 | |
| -#include <asm/setup.h>
 | |
| -
 | |
| -/* 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 <stdio.h>
 | |
| -#include <string.h>
 | |
| -#include <stdlib.h>
 | |
| -#include <stdarg.h>
 | |
| -#include <sys/types.h>
 | |
| -#include <sys/stat.h>
 | |
| -#include <sys/sysmacros.h>
 | |
| -#include <unistd.h>
 | |
| -#include <fcntl.h>
 | |
| -#include <asm/boot.h>
 | |
| -
 | |
| -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
 | |
| -		<if any> 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 <linux/types.h>
 | |
| +#include <linux/screen_info.h>
 | |
| +#include <linux/apm_bios.h>
 | |
| +#include <asm/e820.h>
 | |
| +#include <linux/edd.h>
 | |
| +#include <video/edid.h>
 | |
| +
 | |
| +struct setup_header {
 | |
| +	u8	setup_sects;
 | |
| +	u16	root_flags;
 | |
| +	u32	syssize;
 | |
| +	u16	ram_size;
 | |
| +	u16	vid_mode;
 | |
| +	u16	root_dev;
 | |
| +	u16	boot_flag;
 | |
| +	u16	jump;
 | |
| +	u32	header;
 | |
| +	u16	version;
 | |
| +	u32	realmode_swtch;
 | |
| +	u16	start_sys;
 | |
| +	u16	kernel_version;
 | |
| +	u8	type_of_loader;
 | |
| +	u8	loadflags;
 | |
| +#define LOADED_HIGH	0x01
 | |
| +#define CAN_USE_HEAP	0x80
 | |
| +	u16	setup_move_size;
 | |
| +	u32	code32_start;
 | |
| +	u32	ramdisk_image;
 | |
| +	u32	ramdisk_size;
 | |
| +	u32	bootsect_kludge;
 | |
| +	u16	heap_end_ptr;
 | |
| +	u16	_pad1;
 | |
| +	u32	cmd_line_ptr;
 | |
| +	u32	initrd_addr_max;
 | |
| +	u32	kernel_alignment;
 | |
| +	u8	relocatable_kernel;
 | |
| +} __attribute__((packed));
 | |
| +
 | |
| +struct sys_desc_table {
 | |
| +	u16 length;
 | |
| +	u8  table[14];
 | |
| +};
 | |
| +
 | |
| +struct efi_info {
 | |
| +	u32 _pad1;
 | |
| +	u32 efi_systab;
 | |
| +	u32 efi_memdesc_size;
 | |
| +	u32 efi_memdec_version;
 | |
| +	u32 efi_memmap;
 | |
| +	u32 fi_memmap_size;
 | |
| +	u32 _pad2[2];
 | |
| +};
 | |
| +
 | |
| +/* The so-called "zeropage" */
 | |
| +struct boot_params {
 | |
| +	struct screen_info screen_info;			/* 0x000 */
 | |
| +	struct apm_bios_info apm_bios_info;		/* 0x040 */
 | |
| +	u8  _pad2[12];					/* 0x054 */
 | |
| +	u32 speedstep_info[4];				/* 0x060 */
 | |
| +	u8  _pad3[16];					/* 0x070 */
 | |
| +	u8  hd0_info[16];	/* obsolete! */		/* 0x080 */
 | |
| +	u8  hd1_info[16];	/* obsolete! */		/* 0x090 */
 | |
| +	struct sys_desc_table sys_desc_table;		/* 0x0a0 */
 | |
| +	u8  _pad4[144];					/* 0x0b0 */
 | |
| +	struct edid_info edid_info;			/* 0x140 */
 | |
| +	struct efi_info efi_info;			/* 0x1c0 */
 | |
| +	u32 alt_mem_k;					/* 0x1e0 */
 | |
| +	u32 scratch;		/* Scratch field! */	/* 0x1e4 */
 | |
| +	u8  e820_entries;				/* 0x1e8 */
 | |
| +	u8  eddbuf_entries;				/* 0x1e9 */
 | |
| +	u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
 | |
| +	u8  _pad6[6];					/* 0x1eb */
 | |
| +	struct setup_header hdr;    /* setup header */	/* 0x1f1 */
 | |
| +	u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
 | |
| +	u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];	/* 0x290 */
 | |
| +	struct e820entry e820_map[E820MAX];		/* 0x2d0 */
 | |
| +	u8  _pad8[48];					/* 0xcd0 */
 | |
| +	struct edd_info eddbuf[EDDMAXNR];		/* 0xd00 */
 | |
| +	u8  _pad9[276];					/* 0xeec */
 | |
| +} __attribute__((packed));
 | |
| +
 | |
| +#endif /* _ASM_BOOTPARAM_H */
 | |
| diff -puN include/asm-i386/cpufeature.h~git-newsetup include/asm-i386/cpufeature.h
 | |
| --- a/include/asm-i386/cpufeature.h~git-newsetup
 | |
| +++ a/include/asm-i386/cpufeature.h
 | |
| @@ -12,7 +12,7 @@
 | |
|  #endif
 | |
|  #include <asm/required-features.h>
 | |
|  
 | |
| -#define NCAPINTS	7	/* N 32-bit words worth of info */
 | |
| +#define NCAPINTS	8	/* N 32-bit words worth of info */
 | |
|  
 | |
|  /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
 | |
|  #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
 | |
| @@ -81,6 +81,7 @@
 | |
|  #define X86_FEATURE_BTS		(3*32+13)  /* Branch Trace Store */
 | |
|  #define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */
 | |
|  #define X86_FEATURE_SYNC_RDTSC	(3*32+15)  /* RDTSC synchronizes the CPU */
 | |
| +#define X86_FEATURE_REP_GOOD   (3*32+16) /* rep microcode works well on this CPU */
 | |
|  
 | |
|  /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 | |
|  #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
 | |
| @@ -108,11 +109,24 @@
 | |
|  #define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
 | |
|  #define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
 | |
|  
 | |
| -#define cpu_has(c, bit)					\
 | |
| -	((__builtin_constant_p(bit) && (bit) < 32 && 	\
 | |
| -		(1UL << (bit)) & REQUIRED_MASK1) ?	\
 | |
| -		1 : 					\
 | |
| -	test_bit(bit, (c)->x86_capability))
 | |
| +/*
 | |
| + * Auxiliary flags: Linux defined - For features scattered in various
 | |
| + * CPUID levels like 0x6, 0xA etc
 | |
| + */
 | |
| +#define X86_FEATURE_IDA		(7*32+ 0) /* Intel Dynamic Acceleration */
 | |
| +
 | |
| +#define cpu_has(c, bit)							\
 | |
| +	(__builtin_constant_p(bit) &&					\
 | |
| +	 ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) ||	\
 | |
| +	   (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) ||	\
 | |
| +	   (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) ||	\
 | |
| +	   (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) ||	\
 | |
| +	   (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) ||	\
 | |
| +	   (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) ||	\
 | |
| +	   (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) ||	\
 | |
| +	   (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) )	\
 | |
| +	  ? 1 :								\
 | |
| +	  test_bit(bit, (c)->x86_capability))
 | |
|  #define boot_cpu_has(bit)	cpu_has(&boot_cpu_data, bit)
 | |
|  
 | |
|  #define cpu_has_fpu		boot_cpu_has(X86_FEATURE_FPU)
 | |
| diff -puN include/asm-i386/e820.h~git-newsetup include/asm-i386/e820.h
 | |
| --- a/include/asm-i386/e820.h~git-newsetup
 | |
| +++ a/include/asm-i386/e820.h
 | |
| @@ -25,13 +25,15 @@
 | |
|  
 | |
|  #ifndef __ASSEMBLY__
 | |
|  
 | |
| +struct e820entry {
 | |
| +	u64 addr;	/* start of memory segment */
 | |
| +	u64 size;	/* size of memory segment */
 | |
| +	u32 type;	/* type of memory segment */
 | |
| +} __attribute__((packed));
 | |
| +
 | |
|  struct e820map {
 | |
| -    int nr_map;
 | |
| -    struct e820entry {
 | |
| -	unsigned long long addr;	/* start of memory segment */
 | |
| -	unsigned long long size;	/* size of memory segment */
 | |
| -	unsigned long type;		/* type of memory segment */
 | |
| -    } map[E820MAX];
 | |
| +	u32 nr_map;
 | |
| +	struct e820entry map[E820MAX];
 | |
|  };
 | |
|  
 | |
|  extern struct e820map e820;
 | |
| diff -puN include/asm-i386/processor.h~git-newsetup include/asm-i386/processor.h
 | |
| --- a/include/asm-i386/processor.h~git-newsetup
 | |
| +++ a/include/asm-i386/processor.h
 | |
| @@ -118,6 +118,7 @@ void __init cpu_detect(struct cpuinfo_x8
 | |
|  extern void identify_boot_cpu(void);
 | |
|  extern void identify_secondary_cpu(struct cpuinfo_x86 *);
 | |
|  extern void print_cpu_info(struct cpuinfo_x86 *);
 | |
| +extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 | |
|  extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 | |
|  extern unsigned short num_cache_leaves;
 | |
|  
 | |
| diff -puN include/asm-i386/required-features.h~git-newsetup include/asm-i386/required-features.h
 | |
| --- a/include/asm-i386/required-features.h~git-newsetup
 | |
| +++ a/include/asm-i386/required-features.h
 | |
| @@ -3,7 +3,7 @@
 | |
|  
 | |
|  /* Define minimum CPUID feature set for kernel These bits are checked
 | |
|     really early to actually display a visible error message before the
 | |
| -   kernel dies.  Only add word 0 bits here
 | |
| +   kernel dies.  Make sure to assign features to the proper mask!
 | |
|  
 | |
|     Some requirements that are not in CPUID yet are also in the
 | |
|     CONFIG_X86_MINIMUM_CPU mode which is checked too.
 | |
| @@ -11,24 +11,45 @@
 | |
|     The real information is in arch/i386/Kconfig.cpu, this just converts
 | |
|     the CONFIGs into a bitmask */
 | |
|  
 | |
| +#ifndef CONFIG_MATH_EMULATION
 | |
| +# define NEED_FPU	(1<<(X86_FEATURE_FPU & 31))
 | |
| +#else
 | |
| +# define NEED_FPU	0
 | |
| +#endif
 | |
| +
 | |
|  #ifdef CONFIG_X86_PAE
 | |
| -#define NEED_PAE	(1<<X86_FEATURE_PAE)
 | |
| +# define NEED_PAE	(1<<(X86_FEATURE_PAE & 31))
 | |
|  #else
 | |
| -#define NEED_PAE	0
 | |
| +# define NEED_PAE	0
 | |
|  #endif
 | |
|  
 | |
|  #ifdef CONFIG_X86_CMOV
 | |
| -#define NEED_CMOV	(1<<X86_FEATURE_CMOV)
 | |
| +# define NEED_CMOV	(1<<(X86_FEATURE_CMOV & 31))
 | |
|  #else
 | |
| -#define NEED_CMOV	0
 | |
| +# define NEED_CMOV	0
 | |
|  #endif
 | |
|  
 | |
|  #ifdef CONFIG_X86_CMPXCHG64
 | |
| -#define NEED_CMPXCHG64  (1<<X86_FEATURE_CX8)
 | |
| +# define NEED_CX8	(1<<(X86_FEATURE_CX8 & 31))
 | |
| +#else
 | |
| +# define NEED_CX8	0
 | |
| +#endif
 | |
| +
 | |
| +#define REQUIRED_MASK0	(NEED_FPU|NEED_PAE|NEED_CMOV|NEED_CX8)
 | |
| +
 | |
| +#ifdef CONFIG_X86_USE_3DNOW
 | |
| +# define NEED_3DNOW	(1<<(X86_FEATURE_3DNOW & 31))
 | |
|  #else
 | |
| -#define NEED_CMPXCHG64  0
 | |
| +# define NEED_3DNOW	0
 | |
|  #endif
 | |
|  
 | |
| -#define REQUIRED_MASK1	(NEED_PAE|NEED_CMOV|NEED_CMPXCHG64)
 | |
| +#define REQUIRED_MASK1	(NEED_3DNOW)
 | |
| +
 | |
| +#define REQUIRED_MASK2	0
 | |
| +#define REQUIRED_MASK3	0
 | |
| +#define REQUIRED_MASK4	0
 | |
| +#define REQUIRED_MASK5	0
 | |
| +#define REQUIRED_MASK6	0
 | |
| +#define REQUIRED_MASK7	0
 | |
|  
 | |
|  #endif
 | |
| diff -puN include/asm-i386/setup.h~git-newsetup include/asm-i386/setup.h
 | |
| --- a/include/asm-i386/setup.h~git-newsetup
 | |
| +++ a/include/asm-i386/setup.h
 | |
| @@ -26,12 +26,15 @@
 | |
|  #define NEW_CL_POINTER		0x228	/* Relative to real mode data */
 | |
|  
 | |
|  #ifndef __ASSEMBLY__
 | |
| +
 | |
| +#include <asm/bootparam.h>
 | |
| +
 | |
|  /*
 | |
|   * This is set up by the setup-routine at boot-time
 | |
|   */
 | |
| -extern unsigned char boot_params[PARAM_SIZE];
 | |
| +extern struct boot_params boot_params;
 | |
|  
 | |
| -#define PARAM	(boot_params)
 | |
| +#define PARAM	((char *)&boot_params)
 | |
|  #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
 | |
|  #define EXT_MEM_K (*(unsigned short *) (PARAM+2))
 | |
|  #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
 | |
| @@ -39,8 +42,7 @@ extern unsigned char boot_params[PARAM_S
 | |
|  #define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))
 | |
|  #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
 | |
|  #define IST_INFO   (*(struct ist_info *) (PARAM+0x60))
 | |
| -#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
 | |
| -#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
 | |
| +#define SYS_DESC_TABLE (*(struct sys_desc_table *)(PARAM+0xa0))
 | |
|  #define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
 | |
|  #define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
 | |
|  #define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
 | |
| diff -puN include/asm-x86_64/alternative.h~git-newsetup include/asm-x86_64/alternative.h
 | |
| --- a/include/asm-x86_64/alternative.h~git-newsetup
 | |
| +++ a/include/asm-x86_64/alternative.h
 | |
| @@ -5,6 +5,41 @@
 | |
|  
 | |
|  #include <linux/types.h>
 | |
|  #include <linux/stddef.h>
 | |
| +
 | |
| +/*
 | |
| + * Alternative inline assembly for SMP.
 | |
| + *
 | |
| + * The LOCK_PREFIX macro defined here replaces the LOCK and
 | |
| + * LOCK_PREFIX macros used everywhere in the source tree.
 | |
| + *
 | |
| + * SMP alternatives use the same data structures as the other
 | |
| + * alternatives and the X86_FEATURE_UP flag to indicate the case of a
 | |
| + * UP system running a SMP kernel.  The existing apply_alternatives()
 | |
| + * works fine for patching a SMP kernel for UP.
 | |
| + *
 | |
| + * The SMP alternative tables can be kept after boot and contain both
 | |
| + * UP and SMP versions of the instructions to allow switching back to
 | |
| + * SMP at runtime, when hotplugging in a new CPU, which is especially
 | |
| + * useful in virtualized environments.
 | |
| + *
 | |
| + * The very common lock prefix is handled as special case in a
 | |
| + * separate table which is a pure address list without replacement ptr
 | |
| + * and size information.  That keeps the table sizes small.
 | |
| + */
 | |
| +
 | |
| +#ifdef CONFIG_SMP
 | |
| +#define LOCK_PREFIX \
 | |
| +		".section .smp_locks,\"a\"\n"	\
 | |
| +		"  .align 8\n"			\
 | |
| +		"  .quad 661f\n" /* address */	\
 | |
| +		".previous\n"			\
 | |
| +	       	"661:\n\tlock; "
 | |
| +
 | |
| +#else /* ! CONFIG_SMP */
 | |
| +#define LOCK_PREFIX ""
 | |
| +#endif
 | |
| +
 | |
| +/* This must be included *after* the definition of LOCK_PREFIX */
 | |
|  #include <asm/cpufeature.h>
 | |
|  
 | |
|  struct alt_instr {
 | |
| @@ -108,39 +143,6 @@ static inline void alternatives_smp_swit
 | |
|   */
 | |
|  #define ASM_OUTPUT2(a, b) a, b
 | |
|  
 | |
| -/*
 | |
| - * Alternative inline assembly for SMP.
 | |
| - *
 | |
| - * The LOCK_PREFIX macro defined here replaces the LOCK and
 | |
| - * LOCK_PREFIX macros used everywhere in the source tree.
 | |
| - *
 | |
| - * SMP alternatives use the same data structures as the other
 | |
| - * alternatives and the X86_FEATURE_UP flag to indicate the case of a
 | |
| - * UP system running a SMP kernel.  The existing apply_alternatives()
 | |
| - * works fine for patching a SMP kernel for UP.
 | |
| - *
 | |
| - * The SMP alternative tables can be kept after boot and contain both
 | |
| - * UP and SMP versions of the instructions to allow switching back to
 | |
| - * SMP at runtime, when hotplugging in a new CPU, which is especially
 | |
| - * useful in virtualized environments.
 | |
| - *
 | |
| - * The very common lock prefix is handled as special case in a
 | |
| - * separate table which is a pure address list without replacement ptr
 | |
| - * and size information.  That keeps the table sizes small.
 | |
| - */
 | |
| -
 | |
| -#ifdef CONFIG_SMP
 | |
| -#define LOCK_PREFIX \
 | |
| -		".section .smp_locks,\"a\"\n"	\
 | |
| -		"  .align 8\n"			\
 | |
| -		"  .quad 661f\n" /* address */	\
 | |
| -		".previous\n"			\
 | |
| -	       	"661:\n\tlock; "
 | |
| -
 | |
| -#else /* ! CONFIG_SMP */
 | |
| -#define LOCK_PREFIX ""
 | |
| -#endif
 | |
| -
 | |
|  struct paravirt_patch;
 | |
|  #ifdef CONFIG_PARAVIRT
 | |
|  void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
 | |
| diff -puN include/asm-x86_64/boot.h~git-newsetup include/asm-x86_64/boot.h
 | |
| --- a/include/asm-x86_64/boot.h~git-newsetup
 | |
| +++ a/include/asm-x86_64/boot.h
 | |
| @@ -1,15 +1 @@
 | |
| -#ifndef _LINUX_BOOT_H
 | |
| -#define _LINUX_BOOT_H
 | |
| -
 | |
| -/* Don't touch these, unless you really know what you're doing. */
 | |
| -#define DEF_INITSEG	0x9000
 | |
| -#define DEF_SYSSEG	0x1000
 | |
| -#define DEF_SETUPSEG	0x9020
 | |
| -#define DEF_SYSSIZE	0x7F00
 | |
| -
 | |
| -/* Internal svga startup constants */
 | |
| -#define NORMAL_VGA	0xffff		/* 80x25 mode */
 | |
| -#define EXTENDED_VGA	0xfffe		/* 80x50 mode */
 | |
| -#define ASK_VGA		0xfffd		/* ask for it at bootup */
 | |
| -
 | |
| -#endif
 | |
| +#include <asm-i386/boot.h>
 | |
| diff -puN /dev/null include/asm-x86_64/bootparam.h
 | |
| --- /dev/null
 | |
| +++ a/include/asm-x86_64/bootparam.h
 | |
| @@ -0,0 +1 @@
 | |
| +#include <asm-i386/bootparam.h>
 | |
| diff -puN include/asm-x86_64/cpufeature.h~git-newsetup include/asm-x86_64/cpufeature.h
 | |
| --- a/include/asm-x86_64/cpufeature.h~git-newsetup
 | |
| +++ a/include/asm-x86_64/cpufeature.h
 | |
| @@ -7,115 +7,24 @@
 | |
|  #ifndef __ASM_X8664_CPUFEATURE_H
 | |
|  #define __ASM_X8664_CPUFEATURE_H
 | |
|  
 | |
| -#define NCAPINTS	7	/* N 32-bit words worth of info */
 | |
| +#include <asm-i386/cpufeature.h>
 | |
|  
 | |
| -/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
 | |
| -#define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
 | |
| -#define X86_FEATURE_VME		(0*32+ 1) /* Virtual Mode Extensions */
 | |
| -#define X86_FEATURE_DE		(0*32+ 2) /* Debugging Extensions */
 | |
| -#define X86_FEATURE_PSE 	(0*32+ 3) /* Page Size Extensions */
 | |
| -#define X86_FEATURE_TSC		(0*32+ 4) /* Time Stamp Counter */
 | |
| -#define X86_FEATURE_MSR		(0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */
 | |
| -#define X86_FEATURE_PAE		(0*32+ 6) /* Physical Address Extensions */
 | |
| -#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Architecture */
 | |
| -#define X86_FEATURE_CX8		(0*32+ 8) /* CMPXCHG8 instruction */
 | |
| -#define X86_FEATURE_APIC	(0*32+ 9) /* Onboard APIC */
 | |
| -#define X86_FEATURE_SEP		(0*32+11) /* SYSENTER/SYSEXIT */
 | |
| -#define X86_FEATURE_MTRR	(0*32+12) /* Memory Type Range Registers */
 | |
| -#define X86_FEATURE_PGE		(0*32+13) /* Page Global Enable */
 | |
| -#define X86_FEATURE_MCA		(0*32+14) /* Machine Check Architecture */
 | |
| -#define X86_FEATURE_CMOV	(0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
 | |
| -#define X86_FEATURE_PAT		(0*32+16) /* Page Attribute Table */
 | |
| -#define X86_FEATURE_PSE36	(0*32+17) /* 36-bit PSEs */
 | |
| -#define X86_FEATURE_PN		(0*32+18) /* Processor serial number */
 | |
| -#define X86_FEATURE_CLFLSH	(0*32+19) /* Supports the CLFLUSH instruction */
 | |
| -#define X86_FEATURE_DS		(0*32+21) /* Debug Store */
 | |
| -#define X86_FEATURE_ACPI	(0*32+22) /* ACPI via MSR */
 | |
| -#define X86_FEATURE_MMX		(0*32+23) /* Multimedia Extensions */
 | |
| -#define X86_FEATURE_FXSR	(0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
 | |
| -				          /* of FPU context), and CR4.OSFXSR available */
 | |
| -#define X86_FEATURE_XMM		(0*32+25) /* Streaming SIMD Extensions */
 | |
| -#define X86_FEATURE_XMM2	(0*32+26) /* Streaming SIMD Extensions-2 */
 | |
| -#define X86_FEATURE_SELFSNOOP	(0*32+27) /* CPU self snoop */
 | |
| -#define X86_FEATURE_HT		(0*32+28) /* Hyper-Threading */
 | |
| -#define X86_FEATURE_ACC		(0*32+29) /* Automatic clock control */
 | |
| -#define X86_FEATURE_IA64	(0*32+30) /* IA-64 processor */
 | |
| -
 | |
| -/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
 | |
| -/* Don't duplicate feature flags which are redundant with Intel! */
 | |
| -#define X86_FEATURE_SYSCALL	(1*32+11) /* SYSCALL/SYSRET */
 | |
| -#define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
 | |
| -#define X86_FEATURE_FXSR_OPT	(1*32+25) /* FXSR optimizations */
 | |
| -#define X86_FEATURE_RDTSCP	(1*32+27) /* RDTSCP */
 | |
| -#define X86_FEATURE_LM		(1*32+29) /* Long Mode (x86-64) */
 | |
| -#define X86_FEATURE_3DNOWEXT	(1*32+30) /* AMD 3DNow! extensions */
 | |
| -#define X86_FEATURE_3DNOW	(1*32+31) /* 3DNow! */
 | |
| -
 | |
| -/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
 | |
| -#define X86_FEATURE_RECOVERY	(2*32+ 0) /* CPU in recovery mode */
 | |
| -#define X86_FEATURE_LONGRUN	(2*32+ 1) /* Longrun power control */
 | |
| -#define X86_FEATURE_LRTI	(2*32+ 3) /* LongRun table interface */
 | |
| -
 | |
| -/* Other features, Linux-defined mapping, word 3 */
 | |
| -/* This range is used for feature bits which conflict or are synthesized */
 | |
| -#define X86_FEATURE_CXMMX	(3*32+ 0) /* Cyrix MMX extensions */
 | |
| -#define X86_FEATURE_K6_MTRR	(3*32+ 1) /* AMD K6 nonstandard MTRRs */
 | |
| -#define X86_FEATURE_CYRIX_ARR	(3*32+ 2) /* Cyrix ARRs (= MTRRs) */
 | |
| -#define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
 | |
| -#define X86_FEATURE_REP_GOOD	(3*32+ 4) /* rep microcode works well on this CPU */
 | |
| -#define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
 | |
| -#define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
 | |
| -#define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
 | |
| -#define X86_FEATURE_UP		(3*32+8) /* SMP kernel running on UP */
 | |
| -#define X86_FEATURE_ARCH_PERFMON (3*32+9) /* Intel Architectural PerfMon */
 | |
| -#define X86_FEATURE_PEBS	(3*32+10) /* Precise-Event Based Sampling */
 | |
| -#define X86_FEATURE_BTS		(3*32+11) /* Branch Trace Store */
 | |
| -
 | |
| -/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 | |
| -#define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
 | |
| -#define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
 | |
| -#define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
 | |
| -#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
 | |
| -#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
 | |
| -#define X86_FEATURE_CID		(4*32+10) /* Context ID */
 | |
| -#define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
 | |
| -#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
 | |
| -
 | |
| -/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
 | |
| -#define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
 | |
| -#define X86_FEATURE_XSTORE_EN	(5*32+ 3) /* on-CPU RNG enabled */
 | |
| -#define X86_FEATURE_XCRYPT	(5*32+ 6) /* on-CPU crypto (xcrypt insn) */
 | |
| -#define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* on-CPU crypto enabled */
 | |
| -
 | |
| -/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
 | |
| -#define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
 | |
| -#define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
 | |
| -
 | |
| -#define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 | |
| -#define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
 | |
| -
 | |
| -#define cpu_has_fpu            1
 | |
| +#undef  cpu_has_vme
 | |
|  #define cpu_has_vme            0
 | |
| -#define cpu_has_de             1
 | |
| -#define cpu_has_pse            1
 | |
| -#define cpu_has_tsc            1
 | |
| +
 | |
| +#undef  cpu_has_pae
 | |
|  #define cpu_has_pae            ___BUG___
 | |
| -#define cpu_has_pge            1
 | |
| -#define cpu_has_apic           boot_cpu_has(X86_FEATURE_APIC)
 | |
| -#define cpu_has_mtrr           1
 | |
| -#define cpu_has_mmx            1
 | |
| -#define cpu_has_fxsr           1
 | |
| -#define cpu_has_xmm            1
 | |
| -#define cpu_has_xmm2           1
 | |
| -#define cpu_has_xmm3           boot_cpu_has(X86_FEATURE_XMM3)
 | |
| -#define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
 | |
| +
 | |
| +#undef  cpu_has_mp
 | |
|  #define cpu_has_mp             1 /* XXX */
 | |
| +
 | |
| +#undef  cpu_has_k6_mtrr
 | |
|  #define cpu_has_k6_mtrr        0
 | |
| +
 | |
| +#undef  cpu_has_cyrix_arr
 | |
|  #define cpu_has_cyrix_arr      0
 | |
| +
 | |
| +#undef  cpu_has_centaur_mcr
 | |
|  #define cpu_has_centaur_mcr    0
 | |
| -#define cpu_has_clflush	       boot_cpu_has(X86_FEATURE_CLFLSH)
 | |
| -#define cpu_has_ds 	       boot_cpu_has(X86_FEATURE_DS)
 | |
| -#define cpu_has_pebs 	       boot_cpu_has(X86_FEATURE_PEBS)
 | |
| -#define cpu_has_bts 	       boot_cpu_has(X86_FEATURE_BTS)
 | |
|  
 | |
|  #endif /* __ASM_X8664_CPUFEATURE_H */
 | |
| diff -puN include/asm-x86_64/e820.h~git-newsetup include/asm-x86_64/e820.h
 | |
| --- a/include/asm-x86_64/e820.h~git-newsetup
 | |
| +++ a/include/asm-x86_64/e820.h
 | |
| @@ -11,7 +11,9 @@
 | |
|  #ifndef __E820_HEADER
 | |
|  #define __E820_HEADER
 | |
|  
 | |
| -#include <linux/mmzone.h>
 | |
| +#ifndef _SETUP
 | |
| +# include <linux/mmzone.h>
 | |
| +#endif
 | |
|  
 | |
|  #define E820MAP	0x2d0		/* our map */
 | |
|  #define E820MAX	128		/* number of entries in E820MAP */
 | |
| @@ -30,7 +32,7 @@ struct e820entry {
 | |
|  } __attribute__((packed));
 | |
|  
 | |
|  struct e820map {
 | |
| -    int nr_map;
 | |
| +	u32 nr_map;
 | |
|  	struct e820entry map[E820MAX];
 | |
|  };
 | |
|  
 | |
| diff -puN include/asm-x86_64/processor.h~git-newsetup include/asm-x86_64/processor.h
 | |
| --- a/include/asm-x86_64/processor.h~git-newsetup
 | |
| +++ a/include/asm-x86_64/processor.h
 | |
| @@ -99,6 +99,7 @@ extern char ignore_irq13;
 | |
|  
 | |
|  extern void identify_cpu(struct cpuinfo_x86 *);
 | |
|  extern void print_cpu_info(struct cpuinfo_x86 *);
 | |
| +extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 | |
|  extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 | |
|  extern unsigned short num_cache_leaves;
 | |
|  
 | |
| @@ -367,8 +368,6 @@ static inline void sync_core(void)
 | |
|  	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
 | |
|  } 
 | |
|  
 | |
| -#define cpu_has_fpu 1
 | |
| -
 | |
|  #define ARCH_HAS_PREFETCH
 | |
|  static inline void prefetch(void *x) 
 | |
|  { 
 | |
| diff -puN /dev/null include/asm-x86_64/required-features.h
 | |
| --- /dev/null
 | |
| +++ a/include/asm-x86_64/required-features.h
 | |
| @@ -0,0 +1,46 @@
 | |
| +#ifndef _ASM_REQUIRED_FEATURES_H
 | |
| +#define _ASM_REQUIRED_FEATURES_H 1
 | |
| +
 | |
| +/* Define minimum CPUID feature set for kernel These bits are checked
 | |
| +   really early to actually display a visible error message before the
 | |
| +   kernel dies.  Make sure to assign features to the proper mask!
 | |
| +
 | |
| +   The real information is in arch/x86_64/Kconfig.cpu, this just converts
 | |
| +   the CONFIGs into a bitmask */
 | |
| +
 | |
| +/* x86-64 baseline features */
 | |
| +#define NEED_FPU	(1<<(X86_FEATURE_FPU & 31))
 | |
| +#define NEED_PSE	(1<<(X86_FEATURE_PSE & 31))
 | |
| +#define NEED_MSR	(1<<(X86_FEATURE_MSR & 31))
 | |
| +#define NEED_PAE	(1<<(X86_FEATURE_PAE & 31))
 | |
| +#define NEED_CX8	(1<<(X86_FEATURE_CX8 & 31))
 | |
| +#define NEED_PGE	(1<<(X86_FEATURE_PGE & 31))
 | |
| +#define NEED_FXSR	(1<<(X86_FEATURE_FXSR & 31))
 | |
| +#define NEED_CMOV	(1<<(X86_FEATURE_CMOV & 31))
 | |
| +#define NEED_XMM	(1<<(X86_FEATURE_XMM & 31))
 | |
| +#define NEED_XMM2	(1<<(X86_FEATURE_XMM2 & 31))
 | |
| +
 | |
| +#define REQUIRED_MASK0	(NEED_FPU|NEED_PSE|NEED_MSR|NEED_PAE|\
 | |
| +			 NEED_CX8|NEED_PGE|NEED_FXSR|NEED_CMOV|\
 | |
| +			 NEED_XMM|NEED_XMM2)
 | |
| +#define SSE_MASK	(NEED_XMM|NEED_XMM2)
 | |
| +
 | |
| +/* x86-64 baseline features */
 | |
| +#define NEED_LM		(1<<(X86_FEATURE_LM & 31))
 | |
| +
 | |
| +#ifdef CONFIG_X86_USE_3DNOW
 | |
| +# define NEED_3DNOW	(1<<(X86_FEATURE_3DNOW & 31))
 | |
| +#else
 | |
| +# define NEED_3DNOW	0
 | |
| +#endif
 | |
| +
 | |
| +#define REQUIRED_MASK1	(NEED_LM|NEED_3DNOW)
 | |
| +
 | |
| +#define REQUIRED_MASK2	0
 | |
| +#define REQUIRED_MASK3	0
 | |
| +#define REQUIRED_MASK4	0
 | |
| +#define REQUIRED_MASK5	0
 | |
| +#define REQUIRED_MASK6	0
 | |
| +#define REQUIRED_MASK7	0
 | |
| +
 | |
| +#endif
 | |
| diff -puN include/asm-x86_64/segment.h~git-newsetup include/asm-x86_64/segment.h
 | |
| --- a/include/asm-x86_64/segment.h~git-newsetup
 | |
| +++ a/include/asm-x86_64/segment.h
 | |
| @@ -3,6 +3,14 @@
 | |
|  
 | |
|  #include <asm/cache.h>
 | |
|  
 | |
| +/* Simple and small GDT entries for booting only */
 | |
| +
 | |
| +#define GDT_ENTRY_BOOT_CS		2
 | |
| +#define __BOOT_CS	(GDT_ENTRY_BOOT_CS * 8)
 | |
| +
 | |
| +#define GDT_ENTRY_BOOT_DS		(GDT_ENTRY_BOOT_CS + 1)
 | |
| +#define __BOOT_DS	(GDT_ENTRY_BOOT_DS * 8)
 | |
| +
 | |
|  #define __KERNEL_CS	0x10
 | |
|  #define __KERNEL_DS	0x18
 | |
|  
 | |
| diff -puN include/linux/edd.h~git-newsetup include/linux/edd.h
 | |
| --- a/include/linux/edd.h~git-newsetup
 | |
| +++ a/include/linux/edd.h
 | |
| @@ -49,10 +49,6 @@
 | |
|  #define EDD_MBR_SIG_MAX 16        /* max number of signatures to store */
 | |
|  #define EDD_MBR_SIG_NR_BUF 0x1ea  /* addr of number of MBR signtaures at EDD_MBR_SIG_BUF
 | |
|  				     in boot_params - treat this as 1 byte  */
 | |
| -#define EDD_CL_EQUALS   0x3d646465     /* "edd=" */
 | |
| -#define EDD_CL_OFF      0x666f         /* "of" for off  */
 | |
| -#define EDD_CL_SKIP     0x6b73         /* "sk" for skipmbr */
 | |
| -#define EDD_CL_ON       0x6e6f	       /* "on" for on */
 | |
|  
 | |
|  #ifndef __ASSEMBLY__
 | |
|  
 | |
| diff -puN include/linux/screen_info.h~git-newsetup include/linux/screen_info.h
 | |
| --- a/include/linux/screen_info.h~git-newsetup
 | |
| +++ a/include/linux/screen_info.h
 | |
| @@ -10,7 +10,7 @@
 | |
|  struct screen_info {
 | |
|  	u8  orig_x;		/* 0x00 */
 | |
|  	u8  orig_y;		/* 0x01 */
 | |
| -	u16 dontuse1;		/* 0x02 -- EXT_MEM_K sits here */
 | |
| +	u16 ext_mem_k;		/* 0x02 */
 | |
|  	u16 orig_video_page;	/* 0x04 */
 | |
|  	u8  orig_video_mode;	/* 0x06 */
 | |
|  	u8  orig_video_cols;	/* 0x07 */
 | |
| @@ -27,7 +27,7 @@ struct screen_info {
 | |
|  	u16 lfb_depth;		/* 0x16 */
 | |
|  	u32 lfb_base;		/* 0x18 */
 | |
|  	u32 lfb_size;		/* 0x1c */
 | |
| -	u16 dontuse2, dontuse3;	/* 0x20 -- CL_MAGIC and CL_OFFSET here */
 | |
| +	u16 cl_magic, cl_offset; /* 0x20 */
 | |
|  	u16 lfb_linelength;	/* 0x24 */
 | |
|  	u8  red_size;		/* 0x26 */
 | |
|  	u8  red_pos;		/* 0x27 */
 | |
| @@ -42,9 +42,8 @@ struct screen_info {
 | |
|  	u16 pages;		/* 0x32 */
 | |
|  	u16 vesa_attributes;	/* 0x34 */
 | |
|  	u32 capabilities;       /* 0x36 */
 | |
| -				/* 0x3a -- 0x3b reserved for future expansion */
 | |
| -				/* 0x3c -- 0x3f micro stack for relocatable kernels */
 | |
| -};
 | |
| +	u8  _reserved[6];	/* 0x3a */
 | |
| +} __attribute__((packed));
 | |
|  
 | |
|  extern struct screen_info screen_info;
 | |
|  
 | |
| _
 |