These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / seabios / src / post.c
1 // 32bit code to Power On Self Test (POST) a machine.
2 //
3 // Copyright (C) 2008-2013  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002  MandrakeSoft S.A.
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "biosvar.h" // SET_BDA
9 #include "bregs.h" // struct bregs
10 #include "config.h" // CONFIG_*
11 #include "e820map.h" // e820_add
12 #include "fw/paravirt.h" // qemu_cfg_preinit
13 #include "fw/xen.h" // xen_preinit
14 #include "hw/ahci.h" // ahci_setup
15 #include "hw/ata.h" // ata_setup
16 #include "hw/esp-scsi.h" // esp_scsi_setup
17 #include "hw/lsi-scsi.h" // lsi_scsi_setup
18 #include "hw/megasas.h" // megasas_setup
19 #include "hw/pvscsi.h" // pvscsi_setup
20 #include "hw/pic.h" // pic_setup
21 #include "hw/ps2port.h" // ps2port_setup
22 #include "hw/rtc.h" // rtc_write
23 #include "hw/serialio.h" // serial_debug_preinit
24 #include "hw/usb.h" // usb_setup
25 #include "hw/virtio-blk.h" // virtio_blk_setup
26 #include "hw/virtio-scsi.h" // virtio_scsi_setup
27 #include "malloc.h" // malloc_init
28 #include "memmap.h" // SYMBOL
29 #include "output.h" // dprintf
30 #include "string.h" // memset
31 #include "util.h" // kbd_init
32 #include "tcgbios.h" // tpm_*
33
34
35 /****************************************************************
36  * BIOS initialization and hardware setup
37  ****************************************************************/
38
39 static void
40 ivt_init(void)
41 {
42     dprintf(3, "init ivt\n");
43
44     // Setup reset-vector entry point (controls legacy reboots).
45     HaveRunPost = 1;
46     rtc_write(CMOS_RESET_CODE, 0);
47
48     // Initialize all vectors to the default handler.
49     int i;
50     for (i=0; i<256; i++)
51         SET_IVT(i, FUNC16(entry_iret_official));
52
53     // Initialize all hw vectors to a default hw handler.
54     for (i=BIOS_HWIRQ0_VECTOR; i<BIOS_HWIRQ0_VECTOR+8; i++)
55         SET_IVT(i, FUNC16(entry_hwpic1));
56     for (i=BIOS_HWIRQ8_VECTOR; i<BIOS_HWIRQ8_VECTOR+8; i++)
57         SET_IVT(i, FUNC16(entry_hwpic2));
58
59     // Initialize software handlers.
60     SET_IVT(0x02, FUNC16(entry_02));
61     SET_IVT(0x10, FUNC16(entry_10));
62     SET_IVT(0x11, FUNC16(entry_11));
63     SET_IVT(0x12, FUNC16(entry_12));
64     SET_IVT(0x13, FUNC16(entry_13_official));
65     SET_IVT(0x14, FUNC16(entry_14));
66     SET_IVT(0x15, FUNC16(entry_15_official));
67     SET_IVT(0x16, FUNC16(entry_16));
68     SET_IVT(0x17, FUNC16(entry_17));
69     SET_IVT(0x18, FUNC16(entry_18));
70     SET_IVT(0x19, FUNC16(entry_19_official));
71     SET_IVT(0x1a, FUNC16(entry_1a_official));
72     SET_IVT(0x40, FUNC16(entry_40));
73
74     // INT 60h-66h reserved for user interrupt
75     for (i=0x60; i<=0x66; i++)
76         SET_IVT(i, SEGOFF(0, 0));
77
78     // set vector 0x79 to zero
79     // this is used by 'gardian angel' protection system
80     SET_IVT(0x79, SEGOFF(0, 0));
81 }
82
83 static void
84 bda_init(void)
85 {
86     dprintf(3, "init bda\n");
87
88     struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
89     memset(bda, 0, sizeof(*bda));
90
91     int esize = EBDA_SIZE_START;
92     u16 ebda_seg = EBDA_SEGMENT_START;
93     if (!CONFIG_MALLOC_UPPERMEMORY)
94         ebda_seg = FLATPTR_TO_SEG(ALIGN_DOWN(SYMBOL(final_varlow_start), 1024)
95                                   - EBDA_SIZE_START*1024);
96     SET_BDA(ebda_seg, ebda_seg);
97
98     SET_BDA(mem_size_kb, ebda_seg / (1024/16));
99
100     // Init ebda
101     struct extended_bios_data_area_s *ebda = get_ebda_ptr();
102     memset(ebda, 0, sizeof(*ebda));
103     ebda->size = esize;
104
105     e820_add((u32)ebda, BUILD_LOWRAM_END-(u32)ebda, E820_RESERVED);
106
107     // Init extra stack
108     StackPos = &ExtraStack[BUILD_EXTRA_STACK_SIZE] - SYMBOL(zonelow_base);
109 }
110
111 void
112 interface_init(void)
113 {
114     // Running at new code address - do code relocation fixups
115     malloc_init();
116
117     // Setup romfile items.
118     qemu_cfg_init();
119     coreboot_cbfs_init();
120     multiboot_init();
121
122     // Setup ivt/bda/ebda
123     ivt_init();
124     bda_init();
125
126     // Other interfaces
127     boot_init();
128     bios32_init();
129     pmm_init();
130     pnp_init();
131     kbd_init();
132     mouse_init();
133 }
134
135 // Initialize hardware devices
136 void
137 device_hardware_setup(void)
138 {
139     usb_setup();
140     ps2port_setup();
141     lpt_setup();
142     serial_setup();
143
144     floppy_setup();
145     ata_setup();
146     ahci_setup();
147     sdcard_setup();
148     cbfs_payload_setup();
149     ramdisk_setup();
150     virtio_blk_setup();
151     virtio_scsi_setup();
152     lsi_scsi_setup();
153     esp_scsi_setup();
154     megasas_setup();
155     pvscsi_setup();
156 }
157
158 static void
159 platform_hardware_setup(void)
160 {
161     // Make sure legacy DMA isn't running.
162     dma_setup();
163
164     // Init base pc hardware.
165     pic_setup();
166     thread_setup();
167     mathcp_setup();
168
169     // Platform specific setup
170     qemu_platform_setup();
171     coreboot_platform_setup();
172
173     // Setup timers and periodic clock interrupt
174     timer_setup();
175     clock_setup();
176
177     // Initialize TPM
178     tpm_setup();
179 }
180
181 void
182 prepareboot(void)
183 {
184     // Change TPM phys. presence state befor leaving BIOS
185     tpm_prepboot();
186
187     // Run BCVs
188     bcv_prepboot();
189
190     // Finalize data structures before boot
191     cdrom_prepboot();
192     pmm_prepboot();
193     malloc_prepboot();
194     e820_prepboot();
195
196     HaveRunPost = 2;
197
198     // Setup bios checksum.
199     BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE);
200 }
201
202 // Begin the boot process by invoking an int0x19 in 16bit mode.
203 void VISIBLE32FLAT
204 startBoot(void)
205 {
206     // Clear low-memory allocations (required by PMM spec).
207     memset((void*)BUILD_STACK_ADDR, 0, BUILD_EBDA_MINIMUM - BUILD_STACK_ADDR);
208
209     dprintf(3, "Jump to int19\n");
210     struct bregs br;
211     memset(&br, 0, sizeof(br));
212     br.flags = F_IF;
213     call16_int(0x19, &br);
214 }
215
216 // Main setup code.
217 static void
218 maininit(void)
219 {
220     // Initialize internal interfaces.
221     interface_init();
222
223     // Setup platform devices.
224     platform_hardware_setup();
225
226     // Start hardware initialization (if threads allowed during optionroms)
227     if (threads_during_optionroms())
228         device_hardware_setup();
229
230     // Run vga option rom
231     vgarom_setup();
232
233     // Do hardware initialization (if running synchronously)
234     if (!threads_during_optionroms()) {
235         device_hardware_setup();
236         wait_threads();
237     }
238
239     // Run option roms
240     optionrom_setup();
241
242     // Allow user to modify overall boot order.
243     interactive_bootmenu();
244     wait_threads();
245
246     // Prepare for boot.
247     prepareboot();
248
249     // Write protect bios memory.
250     make_bios_readonly();
251
252     // Invoke int 19 to start boot process.
253     startBoot();
254 }
255
256
257 /****************************************************************
258  * POST entry and code relocation
259  ****************************************************************/
260
261 // Update given relocs for the code at 'dest' with a given 'delta'
262 static void
263 updateRelocs(void *dest, u32 *rstart, u32 *rend, u32 delta)
264 {
265     u32 *reloc;
266     for (reloc = rstart; reloc < rend; reloc++)
267         *((u32*)(dest + *reloc)) += delta;
268 }
269
270 // Relocate init code and then call a function at its new address.
271 // The passed function should be in the "init" section and must not
272 // return.
273 void __noreturn
274 reloc_preinit(void *f, void *arg)
275 {
276     void (*func)(void *) __noreturn = f;
277     if (!CONFIG_RELOCATE_INIT)
278         func(arg);
279
280     // Allocate space for init code.
281     u32 initsize = SYMBOL(code32init_end) - SYMBOL(code32init_start);
282     u32 codealign = SYMBOL(_reloc_min_align);
283     void *codedest = memalign_tmp(codealign, initsize);
284     void *codesrc = VSYMBOL(code32init_start);
285     if (!codedest)
286         panic("No space for init relocation.\n");
287
288     // Copy code and update relocs (init absolute, init relative, and runtime)
289     dprintf(1, "Relocating init from %p to %p (size %d)\n"
290             , codesrc, codedest, initsize);
291     s32 delta = codedest - codesrc;
292     memcpy(codedest, codesrc, initsize);
293     updateRelocs(codedest, VSYMBOL(_reloc_abs_start), VSYMBOL(_reloc_abs_end)
294                  , delta);
295     updateRelocs(codedest, VSYMBOL(_reloc_rel_start), VSYMBOL(_reloc_rel_end)
296                  , -delta);
297     updateRelocs(VSYMBOL(code32flat_start), VSYMBOL(_reloc_init_start)
298                  , VSYMBOL(_reloc_init_end), delta);
299     if (f >= codesrc && f < VSYMBOL(code32init_end))
300         func = f + delta;
301
302     // Call function in relocated code.
303     barrier();
304     func(arg);
305 }
306
307 // Setup for code relocation and then relocate.
308 void VISIBLE32INIT
309 dopost(void)
310 {
311     // Detect ram and setup internal malloc.
312     qemu_preinit();
313     coreboot_preinit();
314     malloc_preinit();
315
316     // Relocate initialization code and call maininit().
317     reloc_preinit(maininit, NULL);
318 }
319
320 // Entry point for Power On Self Test (POST) - the BIOS initilization
321 // phase.  This function makes the memory at 0xc0000-0xfffff
322 // read/writable and then calls dopost().
323 void VISIBLE32FLAT
324 handle_post(void)
325 {
326     if (!CONFIG_QEMU && !CONFIG_COREBOOT)
327         return;
328
329     serial_debug_preinit();
330     debug_banner();
331
332     // Check if we are running under Xen.
333     xen_preinit();
334
335     // Allow writes to modify bios area (0xf0000)
336     make_bios_writable();
337
338     // Now that memory is read/writable - start post process.
339     dopost();
340 }