Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / x86 / boot / main.c
1 /* -*- linux-c -*- ------------------------------------------------------- *
2  *
3  *   Copyright (C) 1991, 1992 Linus Torvalds
4  *   Copyright 2007 rPath, Inc. - All Rights Reserved
5  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
6  *
7  *   This file is part of the Linux kernel, and is made available under
8  *   the terms of the GNU General Public License version 2.
9  *
10  * ----------------------------------------------------------------------- */
11
12 /*
13  * Main module for the real-mode kernel code
14  */
15
16 #include "boot.h"
17 #include "string.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  */
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  * Query the keyboard lock status as given by the BIOS, and
62  * set the keyboard repeat rate to maximum.  Unclear why the latter
63  * is done here; this might be possible to kill off as stale code.
64  */
65 static void keyboard_init(void)
66 {
67         struct biosregs ireg, oreg;
68         initregs(&ireg);
69
70         ireg.ah = 0x02;         /* Get keyboard status */
71         intcall(0x16, &ireg, &oreg);
72         boot_params.kbd_status = oreg.al;
73
74         ireg.ax = 0x0305;       /* Set keyboard repeat rate */
75         intcall(0x16, &ireg, NULL);
76 }
77
78 /*
79  * Get Intel SpeedStep (IST) information.
80  */
81 static void query_ist(void)
82 {
83         struct biosregs ireg, oreg;
84
85         /* Some older BIOSes apparently crash on this call, so filter
86            it from machines too old to have SpeedStep at all. */
87         if (cpu.level < 6)
88                 return;
89
90         initregs(&ireg);
91         ireg.ax  = 0xe980;       /* IST Support */
92         ireg.edx = 0x47534943;   /* Request value */
93         intcall(0x15, &ireg, &oreg);
94
95         boot_params.ist_info.signature  = oreg.eax;
96         boot_params.ist_info.command    = oreg.ebx;
97         boot_params.ist_info.event      = oreg.ecx;
98         boot_params.ist_info.perf_level = oreg.edx;
99 }
100
101 /*
102  * Tell the BIOS what CPU mode we intend to run in.
103  */
104 static void set_bios_mode(void)
105 {
106 #ifdef CONFIG_X86_64
107         struct biosregs ireg;
108
109         initregs(&ireg);
110         ireg.ax = 0xec00;
111         ireg.bx = 2;
112         intcall(0x15, &ireg, NULL);
113 #endif
114 }
115
116 static void init_heap(void)
117 {
118         char *stack_end;
119
120         if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
121                 asm("leal %P1(%%esp),%0"
122                     : "=r" (stack_end) : "i" (-STACK_SIZE));
123
124                 heap_end = (char *)
125                         ((size_t)boot_params.hdr.heap_end_ptr + 0x200);
126                 if (heap_end > stack_end)
127                         heap_end = stack_end;
128         } else {
129                 /* Boot protocol 2.00 only, no heap available */
130                 puts("WARNING: Ancient bootloader, some functionality "
131                      "may be limited!\n");
132         }
133 }
134
135 void main(void)
136 {
137         /* First, copy the boot header into the "zeropage" */
138         copy_boot_params();
139
140         /* Initialize the early-boot console */
141         console_init();
142         if (cmdline_find_option_bool("debug"))
143                 puts("early console in setup code\n");
144
145         /* End of heap check */
146         init_heap();
147
148         /* Make sure we have all the proper CPU support */
149         if (validate_cpu()) {
150                 puts("Unable to boot - please use a kernel appropriate "
151                      "for your CPU.\n");
152                 die();
153         }
154
155         /* Tell the BIOS what CPU mode we intend to run in. */
156         set_bios_mode();
157
158         /* Detect memory layout */
159         detect_memory();
160
161         /* Set keyboard repeat rate (why?) and query the lock flags */
162         keyboard_init();
163
164         /* Query MCA information */
165         query_mca();
166
167         /* Query Intel SpeedStep (IST) information */
168         query_ist();
169
170         /* Query APM information */
171 #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
172         query_apm_bios();
173 #endif
174
175         /* Query EDD information */
176 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
177         query_edd();
178 #endif
179
180         /* Set the video mode */
181         set_video();
182
183         /* Do the last things and invoke protected mode */
184         go_to_protected_mode();
185 }