Whole document tree 3. Linux early setup
(from linux/arch/i386/boot/setup.S and linux/arch/i386/boot/video.S) NOTE: Register notation is %regname and constant notation is a number, with or without a leading '$' sign.
3.1 IA-32 Kernel Setup
"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 the kernel have been loaded by the boot block. "setup.S" is assembled as 16-bit real-mode code. It switches the processor to 32-bit protected mode and jumps to the 32-bit kernel code. This code asks the BIOS for memory/disk/other parameters, and puts them in a "safe" place: 0x90000-0x901FF, that is, 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. The "setup.S" code begins with a jmp instruction around the "setup header", which must begin at location %cs:2. This is the setup header:
start_of_setup:
Read second hard drive DASD type
Read the DASD type of the second hard drive (BIOS int. 0x13, %ax=0x1500, %dl=0x81). # Bootlin depends on this being done early. [TBD:why?]
Check that LILO loaded us right
Check the signature words at the end of setup. Signature words are used to ensure that LILO loaded us right. If the two words are not found correctly, copy the setup sectors and check for the signature words again. If they still aren't found, panic("No setup signature found ...").
Check old loader trying to load a big kernel
If the kernel image is "big" (and hence is "loaded high"), then if the loader cannot handle "loaded high" images, then panic ("Wrong loader, giving up...").
Determine system memory size
Get the extended memory size {above 1 MB} in KB. First clear the extended memory size to 0. #ifndef STANDARD_MEMORY_BIOS_CALL Clear the E820 memory area counter. Try three different memory detection schemes. Method E820H populates a table in the empty_zero_block that contains a list of usable address/size/type tuples. In "linux/arch/i386/kernel/setup.c", this information is transferred into the e820map, and in "linux/arch/i386/mm/init.c", that new information is used to mark pages reserved or not. Method E820H: Method E801H: This is the sum of 2 registers, normalized to 1 KB chunk sizes: %ecx = memory size from 1 MB to 16 MB range, in 1 KB chunks + %edx = memory size above 16 MB, in 64 KB chunks. Ye Olde Traditional Methode: #endif Set the keyboard repeat rate to the maximum rate using using BIOS int. 0x16.
Video adapter modes
Find the video adapter and its supported modes and allow the user to browse video modes. call video # {see Video section below}
Get Hard Disk parameters
Get hd0 data: Save the hd0 descriptor (from int. vector 0x41) at INITSEG:0x80 length 0x10. Get hd1 data: Save the hd1 descriptor (from int. vector 0x46) at INITSEG:0x90 length 0x10. Check that there IS an hd1, using BIOS int. 0x13. If not, clear its descriptor.
Get Micro Channel bus information
Check for Micro Channel (MCA) bus:
Check for mouse
Check for PS/2 pointing device by using BIOS int. 0x11 {get equipment list}.
Check for APM BIOS support
Check for an APM BIOS (if kernel is configured for APM support):
Prepare to move to protected mode
We build a jump instruction to the kernel's code32_start address. (The loader may have changed it.) Move the kernel to its correct place if necessary. Load the segment descriptors (load %ds = %cs). Make sure that we are at the right position in memory, to accommodate the command line and boot parameters at their fixed locations. Load the IDT pointer register with 0,0. Calculate the linear base address of the kernel GDT (table) and load the GDT pointer register with its base address and limit. This early kernel GDT describes kernel code as 4 GB, with base address 0, code/readable/executable, with granularity of 4 KB. The kernel data segment is described as 4 GB, with base address 0, data/readable/writable, with granularity of 4 KB.
Enable address line A20
Make sure any possible coprocessor is properly reset
Mask all interrupts
Now we mask all interrupts; the rest is done in init_IRQ().
Move to Protected Mode
Now is the time to actually move into protected mode. To make things as simple as possible, we do no register setup 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. Set the PE (Protected mode Enable) bit in the MSW and jump to the following instruction to flush the instruction fetch queue. Clear %bx to indicate that this is the BSP (first CPU only).
Jump to startup_32 code
Jump to the 32-bit kernel code (startup_32). NOTE: For high-loaded big kernels we need:
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).
This jumps to "startup_32" in "linux/arch/i386/kernel/head.S".
3.2 Video Setup
"linux/arch/i386/boot/video.S" is included into "linux/arch/i386/boot/setup.S", so they are assembled together. The file separation is a logical module separation even though the two modules aren't built separately. "video.S" handles Linux/i386 display adapter and video mode setup. For more information about Linux/i386 video modes, see "linux/Documentation/svga.txt" by Martin Mares [mj@ucw.cz]. Video mode selection is a kernel build option. When it is enabled, You can select a specific (fixed) video mode to be used during kernel booting or you can ask to view a selection menu and then choose a video mode from that menu. There are a few esoteric (!) "video.S" build options that not covered here. See "linux/Documentation/svga.txt" for all of them. CONFIG_VIDEO_SVGA (for automatic detection of SVGA adapters and modes) is normally #undefined. The normal method of video adapter detection on Linux/i386 is VESA (CONFIG_VIDEO_VESA, for autodetection of VESA modes). "video:" is the main entry point called by "setup.S". The %ds register *must* be pointing to the bootsector. The "video.S" code uses different segments from the main "setup.S" code. This is a simplified description of the code flow in "video.S". It does not address the CONFIG_VIDEO_LOCAL, CONFIG_VIDEO_400_HACK, and CONFIG_VIDEO_GFX_HACK build options and it does not dive deep into video BIOS calls or video register accesses.
video:
basic_detect:
mode_params:
#ifdef CONFIG_VIDEO_SELECT
mopar_gr:
mode_menu:
Build the mode list table and display the mode menu.
mode_set:
For the selected video mode, use BIOS int. 0x10 calls or register writes as needed to set some or all of:
Some video modes require register writes to set:
{end of mode_set} #ifdef CONFIG_VIDEO_RETAIN /* Normally _IS_ #defined */
store_screen:
CONFIG_VIDEO_RETAIN is used to retain screen contents when switching modes. This option stores the screen contents to a temporary memory buffer (if there is enough memory) so that they can be restored later.
restore_screen:
Restores screen contents from temporary buffer (if already saved).
#endif /* CONFIG_VIDEO_RETAIN */
mode_table:
Build the table of video modes at `modelist'.
mode_scan:
Scans for video modes.
#ifdef CONFIG_VIDEO_SVGA
svga_modes:
Try to detect the type of SVGA card and supply (usually approximate) video mode table for it.
#endif /* CONFIG_VIDEO_SVGA */ #endif /* CONFIG_VIDEO_SELECT */
Next Previous Contents |