Commit | Line | Data |
---|---|---|
62607313 PA |
1 | /* -*- linux-c -*- ------------------------------------------------------- * |
2 | * | |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | |
5 | * | |
6 | * This file is part of the Linux kernel, and is made available under | |
7 | * the terms of the GNU General Public License version 2. | |
8 | * | |
9 | * ----------------------------------------------------------------------- */ | |
10 | ||
11 | /* | |
12 | * arch/i386/boot/main.c | |
13 | * | |
14 | * Main module for the real-mode kernel code | |
15 | */ | |
16 | ||
17 | #include "boot.h" | |
18 | ||
19 | struct boot_params boot_params __attribute__((aligned(16))); | |
20 | ||
21 | char *HEAP = _end; | |
22 | char *heap_end = _end; /* Default end of heap = no heap */ | |
23 | ||
24 | /* | |
25 | * Copy the header into the boot parameter block. Since this | |
26 | * screws up the old-style command line protocol, adjust by | |
27 | * filling in the new-style command line pointer instead. | |
28 | */ | |
62607313 PA |
29 | |
30 | static void copy_boot_params(void) | |
31 | { | |
32 | struct old_cmdline { | |
33 | u16 cl_magic; | |
34 | u16 cl_offset; | |
35 | }; | |
36 | const struct old_cmdline * const oldcmd = | |
37 | (const struct old_cmdline *)OLD_CL_ADDRESS; | |
38 | ||
39 | BUILD_BUG_ON(sizeof boot_params != 4096); | |
40 | memcpy(&boot_params.hdr, &hdr, sizeof hdr); | |
41 | ||
42 | if (!boot_params.hdr.cmd_line_ptr && | |
43 | oldcmd->cl_magic == OLD_CL_MAGIC) { | |
44 | /* Old-style command line protocol. */ | |
45 | u16 cmdline_seg; | |
46 | ||
47 | /* Figure out if the command line falls in the region | |
48 | of memory that an old kernel would have copied up | |
49 | to 0x90000... */ | |
50 | if (oldcmd->cl_offset < boot_params.hdr.setup_move_size) | |
51 | cmdline_seg = ds(); | |
52 | else | |
53 | cmdline_seg = 0x9000; | |
54 | ||
55 | boot_params.hdr.cmd_line_ptr = | |
56 | (cmdline_seg << 4) + oldcmd->cl_offset; | |
57 | } | |
58 | } | |
59 | ||
60 | /* | |
61 | * Set the keyboard repeat rate to maximum. Unclear why this | |
62 | * is done here; this might be possible to kill off as stale code. | |
63 | */ | |
64 | static void keyboard_set_repeat(void) | |
65 | { | |
66 | u16 ax = 0x0305; | |
67 | u16 bx = 0; | |
68 | asm volatile("int $0x16" | |
69 | : "+a" (ax), "+b" (bx) | |
70 | : : "ecx", "edx", "esi", "edi"); | |
71 | } | |
72 | ||
73 | /* | |
238b706d | 74 | * Get Intel SpeedStep (IST) information. |
62607313 | 75 | */ |
238b706d | 76 | static void query_ist(void) |
62607313 PA |
77 | { |
78 | asm("int $0x15" | |
238b706d PA |
79 | : "=a" (boot_params.ist_info.signature), |
80 | "=b" (boot_params.ist_info.command), | |
81 | "=c" (boot_params.ist_info.event), | |
82 | "=d" (boot_params.ist_info.perf_level) | |
62607313 PA |
83 | : "a" (0x0000e980), /* IST Support */ |
84 | "d" (0x47534943)); /* Request value */ | |
85 | } | |
86 | ||
87 | /* | |
88 | * Tell the BIOS what CPU mode we intend to run in. | |
89 | */ | |
90 | static void set_bios_mode(void) | |
91 | { | |
92 | #ifdef CONFIG_X86_64 | |
93 | u32 eax, ebx; | |
94 | ||
95 | eax = 0xec00; | |
96 | ebx = 2; | |
97 | asm volatile("int $0x15" | |
98 | : "+a" (eax), "+b" (ebx) | |
99 | : : "ecx", "edx", "esi", "edi"); | |
100 | #endif | |
101 | } | |
102 | ||
103 | void main(void) | |
104 | { | |
105 | /* First, copy the boot header into the "zeropage" */ | |
106 | copy_boot_params(); | |
107 | ||
108 | /* End of heap check */ | |
109 | if (boot_params.hdr.loadflags & CAN_USE_HEAP) { | |
110 | heap_end = (char *)(boot_params.hdr.heap_end_ptr | |
111 | +0x200-STACK_SIZE); | |
112 | } else { | |
113 | /* Boot protocol 2.00 only, no heap available */ | |
114 | puts("WARNING: Ancient bootloader, some functionality " | |
115 | "may be limited!\n"); | |
116 | } | |
117 | ||
118 | /* Make sure we have all the proper CPU support */ | |
119 | if (validate_cpu()) { | |
120 | puts("Unable to boot - please use a kernel appropriate " | |
121 | "for your CPU.\n"); | |
122 | die(); | |
123 | } | |
124 | ||
125 | /* Tell the BIOS what CPU mode we intend to run in. */ | |
126 | set_bios_mode(); | |
127 | ||
128 | /* Detect memory layout */ | |
129 | detect_memory(); | |
130 | ||
131 | /* Set keyboard repeat rate (why?) */ | |
132 | keyboard_set_repeat(); | |
133 | ||
62607313 PA |
134 | /* Query MCA information */ |
135 | query_mca(); | |
136 | ||
137 | /* Voyager */ | |
138 | #ifdef CONFIG_X86_VOYAGER | |
139 | query_voyager(); | |
140 | #endif | |
141 | ||
238b706d PA |
142 | /* Query Intel SpeedStep (IST) information */ |
143 | query_ist(); | |
62607313 PA |
144 | |
145 | /* Query APM information */ | |
146 | #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) | |
147 | query_apm_bios(); | |
148 | #endif | |
149 | ||
150 | /* Query EDD information */ | |
151 | #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) | |
152 | query_edd(); | |
153 | #endif | |
1a8514e0 PA |
154 | |
155 | /* Set the video mode */ | |
156 | set_video(); | |
157 | ||
62607313 PA |
158 | /* Do the last things and invoke protected mode */ |
159 | go_to_protected_mode(); | |
160 | } |