ia64/xen-unstable

view tools/firmware/hvmloader/hvmloader.c @ 19709:011948e1b5a7

hvmloader: Scan for gpxe-capable NICs until one is found.

Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 03 16:12:34 2009 +0100 (2009-06-03)
parents 909bb1245930
children
line source
1 /*
2 * hvmloader.c: HVM bootloader.
3 *
4 * Leendert van Doorn, leendert@watson.ibm.com
5 * Copyright (c) 2005, International Business Machines Corporation.
6 *
7 * Copyright (c) 2006, Keir Fraser, XenSource Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 * Place - Suite 330, Boston, MA 02111-1307 USA.
21 */
23 #include "roms.h"
24 #include "acpi/acpi2_0.h"
25 #include "hypercall.h"
26 #include "util.h"
27 #include "config.h"
28 #include "apic_regs.h"
29 #include "pci_regs.h"
30 #include "e820.h"
31 #include "option_rom.h"
32 #include <xen/version.h>
33 #include <xen/hvm/params.h>
34 #include <xen/memory.h>
36 asm (
37 " .text \n"
38 " .globl _start \n"
39 "_start: \n"
40 /* C runtime kickoff. */
41 " cld \n"
42 " cli \n"
43 " movl $stack_top,%esp \n"
44 " movl %esp,%ebp \n"
45 " call main \n"
46 /* Relocate real-mode trampoline to 0x0. */
47 " mov $trampoline_start,%esi \n"
48 " xor %edi,%edi \n"
49 " mov $trampoline_end,%ecx \n"
50 " sub %esi,%ecx \n"
51 " rep movsb \n"
52 /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */
53 " lgdt gdt_desr \n"
54 " mov $0x0010,%ax \n"
55 " mov %ax,%ds \n"
56 " mov %ax,%es \n"
57 " mov %ax,%fs \n"
58 " mov %ax,%gs \n"
59 " mov %ax,%ss \n"
60 /* Initialise all 32-bit GPRs to zero. */
61 " xor %eax,%eax \n"
62 " xor %ebx,%ebx \n"
63 " xor %ecx,%ecx \n"
64 " xor %edx,%edx \n"
65 " xor %esp,%esp \n"
66 " xor %ebp,%ebp \n"
67 " xor %esi,%esi \n"
68 " xor %edi,%edi \n"
69 /* Enter real mode, reload all segment registers and IDT. */
70 " ljmp $0x8,$0x0 \n"
71 "trampoline_start: .code16 \n"
72 " mov %eax,%cr0 \n"
73 " ljmp $0,$1f-trampoline_start\n"
74 "1: mov %ax,%ds \n"
75 " mov %ax,%es \n"
76 " mov %ax,%fs \n"
77 " mov %ax,%gs \n"
78 " mov %ax,%ss \n"
79 " lidt 1f-trampoline_start \n"
80 " ljmp $0xf000,$0xfff0 \n"
81 "1: .word 0x3ff,0,0 \n"
82 "trampoline_end: .code32 \n"
83 " \n"
84 "gdt_desr: \n"
85 " .word gdt_end - gdt - 1 \n"
86 " .long gdt \n"
87 " \n"
88 " .align 8 \n"
89 "gdt: \n"
90 " .quad 0x0000000000000000 \n"
91 " .quad 0x008f9a000000ffff \n" /* Ring 0 16b code, base 0 limit 4G */
92 " .quad 0x008f92000000ffff \n" /* Ring 0 16b data, base 0 limit 4G */
93 "gdt_end: \n"
94 " \n"
95 " .bss \n"
96 " .align 8 \n"
97 "stack: \n"
98 " .skip 0x4000 \n"
99 "stack_top: \n"
100 " .text \n"
101 );
103 unsigned long pci_mem_start = PCI_MEM_START;
104 unsigned long pci_mem_end = PCI_MEM_END;
106 static enum { VGA_none, VGA_std, VGA_cirrus } virtual_vga = VGA_none;
108 static void init_hypercalls(void)
109 {
110 uint32_t eax, ebx, ecx, edx;
111 unsigned long i;
112 char signature[13];
113 xen_extraversion_t extraversion;
114 uint32_t base;
116 for ( base = 0x40000000; base < 0x40001000; base += 0x100 )
117 {
118 cpuid(base, &eax, &ebx, &ecx, &edx);
120 *(uint32_t *)(signature + 0) = ebx;
121 *(uint32_t *)(signature + 4) = ecx;
122 *(uint32_t *)(signature + 8) = edx;
123 signature[12] = '\0';
125 if ( !strcmp("XenVMMXenVMM", signature) )
126 break;
127 }
129 BUG_ON(strcmp("XenVMMXenVMM", signature) || ((eax - base) < 2));
131 /* Fill in hypercall transfer pages. */
132 cpuid(base + 2, &eax, &ebx, &ecx, &edx);
133 for ( i = 0; i < eax; i++ )
134 wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
136 /* Print version information. */
137 cpuid(base + 1, &eax, &ebx, &ecx, &edx);
138 hypercall_xen_version(XENVER_extraversion, extraversion);
139 printf("Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
140 }
142 static void apic_setup(void)
143 {
144 /* Set the IOAPIC ID to tha static value used in the MP/ACPI tables. */
145 ioapic_write(0x00, IOAPIC_ID);
147 /* Set up Virtual Wire mode. */
148 lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
149 lapic_write(APIC_LVT0, APIC_MODE_EXTINT << 8);
150 lapic_write(APIC_LVT1, APIC_MODE_NMI << 8);
151 }
153 static void pci_setup(void)
154 {
155 uint32_t base, devfn, bar_reg, bar_data, bar_sz, cmd, mmio_total = 0;
156 uint16_t class, vendor_id, device_id;
157 unsigned int bar, pin, link, isa_irq;
159 /* Resources assignable to PCI devices via BARs. */
160 struct resource {
161 uint32_t base, max;
162 } *resource, mem_resource, io_resource;
164 /* Create a list of device BARs in descending order of size. */
165 struct bars {
166 uint32_t devfn, bar_reg, bar_sz;
167 } *bars = (struct bars *)SCRATCH_PHYSICAL_ADDRESS;
168 unsigned int i, nr_bars = 0;
170 /* Program PCI-ISA bridge with appropriate link routes. */
171 isa_irq = 0;
172 for ( link = 0; link < 4; link++ )
173 {
174 do { isa_irq = (isa_irq + 1) & 15;
175 } while ( !(PCI_ISA_IRQ_MASK & (1U << isa_irq)) );
176 pci_writeb(PCI_ISA_DEVFN, 0x60 + link, isa_irq);
177 printf("PCI-ISA link %u routed to IRQ%u\n", link, isa_irq);
178 }
180 /* Program ELCR to match PCI-wired IRQs. */
181 outb(0x4d0, (uint8_t)(PCI_ISA_IRQ_MASK >> 0));
182 outb(0x4d1, (uint8_t)(PCI_ISA_IRQ_MASK >> 8));
184 /* Scan the PCI bus and map resources. */
185 for ( devfn = 0; devfn < 128; devfn++ )
186 {
187 class = pci_readw(devfn, PCI_CLASS_DEVICE);
188 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
189 device_id = pci_readw(devfn, PCI_DEVICE_ID);
190 if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
191 continue;
193 ASSERT((devfn != PCI_ISA_DEVFN) ||
194 ((vendor_id == 0x8086) && (device_id == 0x7000)));
196 switch ( class )
197 {
198 case 0x0300:
199 if ( (vendor_id == 0x1234) && (device_id == 0x1111) )
200 virtual_vga = VGA_std;
201 if ( (vendor_id == 0x1013) && (device_id == 0xb8) )
202 virtual_vga = VGA_cirrus;
203 break;
204 case 0x0680:
205 /* PIIX4 ACPI PM. Special device with special PCI config space. */
206 ASSERT((vendor_id == 0x8086) && (device_id == 0x7113));
207 pci_writew(devfn, 0x20, 0x0000); /* No smb bus IO enable */
208 pci_writew(devfn, 0x22, 0x0000);
209 pci_writew(devfn, 0x3c, 0x0009); /* Hardcoded IRQ9 */
210 pci_writew(devfn, 0x3d, 0x0001);
211 break;
212 case 0x0101:
213 if ( vendor_id == 0x8086 )
214 {
215 /* Intel ICHs since PIIX3: enable IDE legacy mode. */
216 pci_writew(devfn, 0x40, 0x8000); /* enable IDE0 */
217 pci_writew(devfn, 0x42, 0x8000); /* enable IDE1 */
218 }
219 break;
220 }
222 /* Map the I/O memory and port resources. */
223 for ( bar = 0; bar < 7; bar++ )
224 {
225 bar_reg = PCI_BASE_ADDRESS_0 + 4*bar;
226 if ( bar == 6 )
227 bar_reg = PCI_ROM_ADDRESS;
229 bar_data = pci_readl(devfn, bar_reg);
230 pci_writel(devfn, bar_reg, ~0);
231 bar_sz = pci_readl(devfn, bar_reg);
232 pci_writel(devfn, bar_reg, bar_data);
233 if ( bar_sz == 0 )
234 continue;
236 bar_sz &= (((bar_data & PCI_BASE_ADDRESS_SPACE) ==
237 PCI_BASE_ADDRESS_SPACE_MEMORY) ?
238 PCI_BASE_ADDRESS_MEM_MASK :
239 (PCI_BASE_ADDRESS_IO_MASK & 0xffff));
240 bar_sz &= ~(bar_sz - 1);
242 for ( i = 0; i < nr_bars; i++ )
243 if ( bars[i].bar_sz < bar_sz )
244 break;
246 if ( i != nr_bars )
247 memmove(&bars[i+1], &bars[i], (nr_bars-i) * sizeof(*bars));
249 bars[i].devfn = devfn;
250 bars[i].bar_reg = bar_reg;
251 bars[i].bar_sz = bar_sz;
253 if ( (bar_data & PCI_BASE_ADDRESS_SPACE) ==
254 PCI_BASE_ADDRESS_SPACE_MEMORY )
255 mmio_total += bar_sz;
257 nr_bars++;
259 /* Skip the upper-half of the address for a 64-bit BAR. */
260 if ( (bar_data & (PCI_BASE_ADDRESS_SPACE |
261 PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
262 (PCI_BASE_ADDRESS_SPACE_MEMORY |
263 PCI_BASE_ADDRESS_MEM_TYPE_64) )
264 bar++;
265 }
267 /* Map the interrupt. */
268 pin = pci_readb(devfn, PCI_INTERRUPT_PIN);
269 if ( pin != 0 )
270 {
271 /* This is the barber's pole mapping used by Xen. */
272 link = ((pin - 1) + (devfn >> 3)) & 3;
273 isa_irq = pci_readb(PCI_ISA_DEVFN, 0x60 + link);
274 pci_writeb(devfn, PCI_INTERRUPT_LINE, isa_irq);
275 printf("pci dev %02x:%x INT%c->IRQ%u\n",
276 devfn>>3, devfn&7, 'A'+pin-1, isa_irq);
277 }
279 /* Enable bus mastering. */
280 cmd = pci_readw(devfn, PCI_COMMAND);
281 cmd |= PCI_COMMAND_MASTER;
282 pci_writew(devfn, PCI_COMMAND, cmd);
283 }
285 while ( (mmio_total > (pci_mem_end - pci_mem_start)) &&
286 ((pci_mem_start << 1) != 0) )
287 pci_mem_start <<= 1;
289 while ( (pci_mem_start >> PAGE_SHIFT) < hvm_info->low_mem_pgend )
290 {
291 struct xen_add_to_physmap xatp;
292 if ( hvm_info->high_mem_pgend == 0 )
293 hvm_info->high_mem_pgend = 1ull << (32 - PAGE_SHIFT);
294 xatp.domid = DOMID_SELF;
295 xatp.space = XENMAPSPACE_gmfn;
296 xatp.idx = --hvm_info->low_mem_pgend;
297 xatp.gpfn = hvm_info->high_mem_pgend++;
298 if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
299 BUG();
300 }
302 mem_resource.base = pci_mem_start;
303 mem_resource.max = pci_mem_end;
304 io_resource.base = 0xc000;
305 io_resource.max = 0x10000;
307 /* Assign iomem and ioport resources in descending order of size. */
308 for ( i = 0; i < nr_bars; i++ )
309 {
310 devfn = bars[i].devfn;
311 bar_reg = bars[i].bar_reg;
312 bar_sz = bars[i].bar_sz;
314 bar_data = pci_readl(devfn, bar_reg);
316 if ( (bar_data & PCI_BASE_ADDRESS_SPACE) ==
317 PCI_BASE_ADDRESS_SPACE_MEMORY )
318 {
319 resource = &mem_resource;
320 bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK;
321 }
322 else
323 {
324 resource = &io_resource;
325 bar_data &= ~PCI_BASE_ADDRESS_IO_MASK;
326 }
328 base = (resource->base + bar_sz - 1) & ~(bar_sz - 1);
329 bar_data |= base;
330 base += bar_sz;
332 if ( (base < resource->base) || (base > resource->max) )
333 {
334 printf("pci dev %02x:%x bar %02x size %08x: no space for "
335 "resource!\n", devfn>>3, devfn&7, bar_reg, bar_sz);
336 continue;
337 }
339 resource->base = base;
341 pci_writel(devfn, bar_reg, bar_data);
342 printf("pci dev %02x:%x bar %02x size %08x: %08x\n",
343 devfn>>3, devfn&7, bar_reg, bar_sz, bar_data);
345 /* Now enable the memory or I/O mapping. */
346 cmd = pci_readw(devfn, PCI_COMMAND);
347 if ( (bar_reg == PCI_ROM_ADDRESS) ||
348 ((bar_data & PCI_BASE_ADDRESS_SPACE) ==
349 PCI_BASE_ADDRESS_SPACE_MEMORY) )
350 cmd |= PCI_COMMAND_MEMORY;
351 else
352 cmd |= PCI_COMMAND_IO;
353 pci_writew(devfn, PCI_COMMAND, cmd);
354 }
355 }
357 /*
358 * Scan the list of Option ROMs at @roms for one which supports
359 * PCI (@vendor_id, @device_id) found at slot @devfn. If one is found,
360 * copy it to @dest and return its size rounded up to a multiple 2kB. This
361 * function will not copy ROMs beyond address OPTIONROM_PHYSICAL_END.
362 */
363 #define round_option_rom(x) (((x) + 2047) & ~2047)
364 static int scan_option_rom(
365 uint8_t devfn, uint16_t vendor_id, uint16_t device_id,
366 void *roms, uint32_t dest)
367 {
368 struct option_rom_header *rom;
369 struct option_rom_pnp_header *pnph;
370 struct option_rom_pci_header *pcih;
371 uint8_t csum;
372 int i;
374 static uint32_t orom_ids[64];
375 static int nr_roms;
377 /* Avoid duplicate ROMs. */
378 for ( i = 0; i < nr_roms; i++ )
379 if ( orom_ids[i] == (vendor_id | ((uint32_t)device_id << 16)) )
380 return 0;
382 rom = roms;
383 for ( ; ; )
384 {
385 /* Invalid signature means we're out of option ROMs. */
386 if ( strncmp((char *)rom->signature, "\x55\xaa", 2) ||
387 (rom->rom_size == 0) )
388 break;
390 /* Invalid checksum means we're out of option ROMs. */
391 csum = 0;
392 for ( i = 0; i < (rom->rom_size * 512); i++ )
393 csum += ((uint8_t *)rom)[i];
394 if ( csum != 0 )
395 break;
397 /* Check the PCI PnP header (if any) for a match. */
398 pcih = (struct option_rom_pci_header *)
399 ((char *)rom + rom->pci_header_offset);
400 if ( (rom->pci_header_offset != 0) &&
401 !strncmp((char *)pcih->signature, "PCIR", 4) &&
402 (pcih->vendor_id == vendor_id) &&
403 (pcih->device_id == device_id) )
404 goto found;
406 rom = (struct option_rom_header *)
407 ((char *)rom + rom->rom_size * 512);
408 }
410 return 0;
412 found:
413 /* Find the PnP expansion header (if any). */
414 pnph = ((rom->expansion_header_offset != 0)
415 ? ((struct option_rom_pnp_header *)
416 ((char *)rom + rom->expansion_header_offset))
417 : ((struct option_rom_pnp_header *)NULL));
418 while ( (pnph != NULL) && strncmp((char *)pnph->signature, "$PnP", 4) )
419 pnph = ((pnph->next_header_offset != 0)
420 ? ((struct option_rom_pnp_header *)
421 ((char *)rom + pnph->next_header_offset))
422 : ((struct option_rom_pnp_header *)NULL));
424 printf("Loading PCI Option ROM ...\n");
425 if ( (pnph != NULL) && (pnph->manufacturer_name_offset != 0) )
426 printf(" - Manufacturer: %s\n",
427 (char *)rom + pnph->manufacturer_name_offset);
428 if ( (pnph != NULL) && (pnph->product_name_offset != 0) )
429 printf(" - Product name: %s\n",
430 (char *)rom + pnph->product_name_offset);
432 if ( (dest + rom->rom_size * 512 + 1) > OPTIONROM_PHYSICAL_END )
433 {
434 printf("Option ROM size %x exceeds available space\n",
435 rom->rom_size * 512);
436 return 0;
437 }
439 orom_ids[nr_roms++] = vendor_id | ((uint32_t)device_id << 16);
440 memcpy((void *)dest, rom, rom->rom_size * 512);
441 *(uint8_t *)(dest + rom->rom_size * 512) = devfn;
442 return round_option_rom(rom->rom_size * 512 + 1);
443 }
445 /*
446 * Scan the PCI bus for the first NIC supported by etherboot, and copy
447 * the corresponding rom data to *copy_rom_dest. Returns the length of the
448 * selected rom, or 0 if no NIC found.
449 */
450 static int scan_etherboot_nic(uint32_t copy_rom_dest)
451 {
452 uint8_t devfn;
453 uint16_t class, vendor_id, device_id;
454 int rom_size = 0;
456 for ( devfn = 0; (devfn < 128) && !rom_size; devfn++ )
457 {
458 class = pci_readw(devfn, PCI_CLASS_DEVICE);
459 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
460 device_id = pci_readw(devfn, PCI_DEVICE_ID);
462 /* We're only interested in NICs. */
463 if ( (vendor_id != 0xffff) &&
464 (device_id != 0xffff) &&
465 (class == 0x0200) )
466 rom_size = scan_option_rom(
467 devfn, vendor_id, device_id, etherboot, copy_rom_dest);
468 }
470 return rom_size;
471 }
473 /*
474 * Scan the PCI bus for the devices that have an option ROM, and copy
475 * the corresponding rom data to rom_phys_addr.
476 */
477 static int pci_load_option_roms(uint32_t rom_base_addr)
478 {
479 uint32_t option_rom_addr, rom_phys_addr = rom_base_addr;
480 uint16_t vendor_id, device_id;
481 uint8_t devfn, class;
483 for ( devfn = 0; devfn < 128; devfn++ )
484 {
485 class = pci_readb(devfn, PCI_CLASS_DEVICE + 1);
486 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
487 device_id = pci_readw(devfn, PCI_DEVICE_ID);
489 if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
490 continue;
492 /*
493 * Currently only scan options from mass storage devices and serial
494 * bus controller (Fibre Channel included).
495 */
496 if ( (class != 0x1) && (class != 0xc) )
497 continue;
499 option_rom_addr = pci_readl(devfn, PCI_ROM_ADDRESS);
500 if ( !option_rom_addr )
501 continue;
503 /* Ensure Expansion Bar is enabled before copying */
504 pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr | 0x1);
506 rom_phys_addr += scan_option_rom(
507 devfn, vendor_id, device_id,
508 (void *)(option_rom_addr & ~2047), rom_phys_addr);
510 /* Restore the default original value of Expansion Bar */
511 pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr);
512 }
514 return rom_phys_addr - rom_base_addr;
515 }
517 /* Replace possibly erroneous memory-size CMOS fields with correct values. */
518 static void cmos_write_memory_size(void)
519 {
520 uint32_t base_mem = 640, ext_mem, alt_mem;
522 alt_mem = ext_mem = hvm_info->low_mem_pgend << PAGE_SHIFT;
523 ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
524 if ( ext_mem > 0xffff )
525 ext_mem = 0xffff;
526 alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
528 /* All BIOSes: conventional memory (CMOS *always* reports 640kB). */
529 cmos_outb(0x15, (uint8_t)(base_mem >> 0));
530 cmos_outb(0x16, (uint8_t)(base_mem >> 8));
532 /* All BIOSes: extended memory (1kB chunks above 1MB). */
533 cmos_outb(0x17, (uint8_t)( ext_mem >> 0));
534 cmos_outb(0x18, (uint8_t)( ext_mem >> 8));
535 cmos_outb(0x30, (uint8_t)( ext_mem >> 0));
536 cmos_outb(0x31, (uint8_t)( ext_mem >> 8));
538 /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */
539 cmos_outb(0x34, (uint8_t)( alt_mem >> 0));
540 cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
541 }
543 /*
544 * Set up an empty TSS area for virtual 8086 mode to use.
545 * The only important thing is that it musn't have any bits set
546 * in the interrupt redirection bitmap, so all zeros will do.
547 */
548 static void init_vm86_tss(void)
549 {
550 void *tss;
551 struct xen_hvm_param p;
553 tss = mem_alloc(128, 128);
554 memset(tss, 0, 128);
555 p.domid = DOMID_SELF;
556 p.index = HVM_PARAM_VM86_TSS;
557 p.value = virt_to_phys(tss);
558 hypercall_hvm_op(HVMOP_set_param, &p);
559 printf("vm86 TSS at %08lx\n", virt_to_phys(tss));
560 }
562 /* Create an E820 table based on memory parameters provided in hvm_info. */
563 static void build_e820_table(void)
564 {
565 struct e820entry *e820 = E820;
566 unsigned int nr = 0;
568 /* 0x0-0x9FC00: Ordinary RAM. */
569 e820[nr].addr = 0x0;
570 e820[nr].size = 0x9FC00;
571 e820[nr].type = E820_RAM;
572 nr++;
574 /* 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). */
575 e820[nr].addr = 0x9FC00;
576 e820[nr].size = 0x400;
577 e820[nr].type = E820_RESERVED;
578 nr++;
580 /*
581 * Following regions are standard regions of the PC memory map.
582 * They are not covered by e820 regions. OSes will not use as RAM.
583 * 0xA0000-0xC0000: VGA memory-mapped I/O. Not covered by E820.
584 * 0xC0000-0xE0000: 16-bit devices, expansion ROMs (inc. vgabios).
585 * TODO: free pages which turn out to be unused.
586 */
588 /*
589 * 0xE0000-0x0F0000: PC-specific area. We place various tables here.
590 * 0xF0000-0x100000: System BIOS.
591 * TODO: free pages which turn out to be unused.
592 */
593 e820[nr].addr = 0xE0000;
594 e820[nr].size = 0x20000;
595 e820[nr].type = E820_RESERVED;
596 nr++;
598 /* Low RAM goes here. Reserve space for special pages. */
599 BUG_ON((hvm_info->low_mem_pgend << PAGE_SHIFT) < (2u << 20));
600 e820[nr].addr = 0x100000;
601 e820[nr].size = (hvm_info->low_mem_pgend << PAGE_SHIFT) - e820[nr].addr;
602 e820[nr].type = E820_RAM;
603 nr++;
605 /*
606 * Explicitly reserve space for special pages.
607 * This space starts at RESERVED_MEMBASE an extends to cover various
608 * fixed hardware mappings (e.g., LAPIC, IOAPIC, default SVGA framebuffer).
609 */
610 e820[nr].addr = RESERVED_MEMBASE;
611 e820[nr].size = (uint32_t)-e820[nr].addr;
612 e820[nr].type = E820_RESERVED;
613 nr++;
615 if ( hvm_info->high_mem_pgend )
616 {
617 e820[nr].addr = ((uint64_t)1 << 32);
618 e820[nr].size =
619 ((uint64_t)hvm_info->high_mem_pgend << PAGE_SHIFT) - e820[nr].addr;
620 e820[nr].type = E820_RAM;
621 nr++;
622 }
624 *E820_NR = nr;
625 }
627 int main(void)
628 {
629 int option_rom_sz = 0, vgabios_sz = 0, etherboot_sz = 0;
630 int rombios_sz, smbios_sz;
631 uint32_t etherboot_phys_addr, option_rom_phys_addr, bios32_addr;
632 struct bios_info *bios_info;
634 printf("HVM Loader\n");
636 init_hypercalls();
638 printf("CPU speed is %u MHz\n", get_cpu_mhz());
640 apic_setup();
641 pci_setup();
643 smp_initialise();
645 perform_tests();
647 printf("Writing SMBIOS tables ...\n");
648 smbios_sz = hvm_write_smbios_tables();
650 printf("Loading ROMBIOS ...\n");
651 rombios_sz = sizeof(rombios);
652 if ( rombios_sz > 0x10000 )
653 rombios_sz = 0x10000;
654 memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, rombios_sz);
655 bios32_addr = highbios_setup();
657 if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode )
658 create_mp_tables();
660 switch ( virtual_vga )
661 {
662 case VGA_cirrus:
663 printf("Loading Cirrus VGABIOS ...\n");
664 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
665 vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
666 vgabios_sz = round_option_rom(sizeof(vgabios_cirrusvga));
667 break;
668 case VGA_std:
669 printf("Loading Standard VGABIOS ...\n");
670 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
671 vgabios_stdvga, sizeof(vgabios_stdvga));
672 vgabios_sz = round_option_rom(sizeof(vgabios_stdvga));
673 break;
674 default:
675 printf("No emulated VGA adaptor ...\n");
676 break;
677 }
679 etherboot_phys_addr = VGABIOS_PHYSICAL_ADDRESS + vgabios_sz;
680 if ( etherboot_phys_addr < OPTIONROM_PHYSICAL_ADDRESS )
681 etherboot_phys_addr = OPTIONROM_PHYSICAL_ADDRESS;
682 etherboot_sz = scan_etherboot_nic(etherboot_phys_addr);
684 option_rom_phys_addr = etherboot_phys_addr + etherboot_sz;
685 option_rom_sz = pci_load_option_roms(option_rom_phys_addr);
687 if ( hvm_info->acpi_enabled )
688 {
689 printf("Loading ACPI ...\n");
690 acpi_build_tables();
691 }
693 init_vm86_tss();
695 cmos_write_memory_size();
697 printf("BIOS map:\n");
698 if ( vgabios_sz )
699 printf(" %05x-%05x: VGA BIOS\n",
700 VGABIOS_PHYSICAL_ADDRESS,
701 VGABIOS_PHYSICAL_ADDRESS + vgabios_sz - 1);
702 if ( etherboot_sz )
703 printf(" %05x-%05x: Etherboot ROM\n",
704 etherboot_phys_addr,
705 etherboot_phys_addr + etherboot_sz - 1);
706 if ( option_rom_sz )
707 printf(" %05x-%05x: PCI Option ROMs\n",
708 option_rom_phys_addr,
709 option_rom_phys_addr + option_rom_sz - 1);
710 if ( smbios_sz )
711 printf(" %05x-%05x: SMBIOS tables\n",
712 SMBIOS_PHYSICAL_ADDRESS,
713 SMBIOS_PHYSICAL_ADDRESS + smbios_sz - 1);
714 if ( rombios_sz )
715 printf(" %05x-%05x: Main BIOS\n",
716 ROMBIOS_PHYSICAL_ADDRESS,
717 ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1);
719 build_e820_table();
721 bios_info = (struct bios_info *)BIOS_INFO_PHYSICAL_ADDRESS;
722 memset(bios_info, 0, sizeof(*bios_info));
723 bios_info->com1_present = uart_exists(0x3f8);
724 bios_info->com2_present = uart_exists(0x2f8);
725 bios_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS);
726 bios_info->pci_min = pci_mem_start;
727 bios_info->pci_len = pci_mem_end - pci_mem_start;
728 bios_info->bios32_entry = bios32_addr;
730 printf("Invoking ROMBIOS ...\n");
731 return 0;
732 }
734 /*
735 * Local variables:
736 * mode: C
737 * c-set-style: "BSD"
738 * c-basic-offset: 4
739 * tab-width: 4
740 * indent-tabs-mode: nil
741 * End:
742 */