ia64/xen-unstable

annotate tools/firmware/hvmloader/hvmloader.c @ 16992:9d0e86d8c1d1

x86 vmx: Remove vmxassist.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 06 12:07:55 2008 +0000 (2008-02-06)
parents 42369d21641d
children b280ee89dcdc
rev   line source
kaf24@8708 1 /*
keir@16992 2 * hvmloader.c: HVM bootloader.
kaf24@8708 3 *
kaf24@8708 4 * Leendert van Doorn, leendert@watson.ibm.com
kaf24@8708 5 * Copyright (c) 2005, International Business Machines Corporation.
kaf24@8708 6 *
kfraser@12554 7 * Copyright (c) 2006, Keir Fraser, XenSource Inc.
kfraser@12554 8 *
kaf24@8708 9 * This program is free software; you can redistribute it and/or modify it
kaf24@8708 10 * under the terms and conditions of the GNU General Public License,
kaf24@8708 11 * version 2, as published by the Free Software Foundation.
kaf24@8708 12 *
kaf24@8708 13 * This program is distributed in the hope it will be useful, but WITHOUT
kaf24@8708 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
kaf24@8708 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
kaf24@8708 16 * more details.
kaf24@8708 17 *
kaf24@8708 18 * You should have received a copy of the GNU General Public License along with
kaf24@8708 19 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
kaf24@8708 20 * Place - Suite 330, Boston, MA 02111-1307 USA.
kaf24@8708 21 */
kfraser@14959 22
kaf24@8708 23 #include "roms.h"
kfraser@14959 24 #include "acpi/acpi2_0.h"
kfraser@10976 25 #include "hypercall.h"
kfraser@10976 26 #include "util.h"
kfraser@12548 27 #include "config.h"
kaf24@12571 28 #include "apic_regs.h"
kfraser@12554 29 #include "pci_regs.h"
keir@15303 30 #include "e820.h"
kfraser@10976 31 #include <xen/version.h>
kfraser@11081 32 #include <xen/hvm/params.h>
kaf24@8708 33
kaf24@8708 34 asm(
kfraser@12548 35 " .text \n"
kfraser@12548 36 " .globl _start \n"
kfraser@12548 37 "_start: \n"
kfraser@14373 38 /* C runtime kickoff. */
kfraser@12548 39 " cld \n"
kfraser@12548 40 " cli \n"
kfraser@14373 41 " movl $stack_top,%esp \n"
kfraser@14373 42 " movl %esp,%ebp \n"
kfraser@14373 43 " call main \n"
kfraser@14373 44 /* Relocate real-mode trampoline to 0x0. */
kfraser@14373 45 " mov $trampoline_start,%esi \n"
kfraser@14373 46 " xor %edi,%edi \n"
kfraser@14373 47 " mov $trampoline_end,%ecx \n"
kfraser@14373 48 " sub %esi,%ecx \n"
kfraser@14373 49 " rep movsb \n"
kfraser@14373 50 /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */
kfraser@12548 51 " lgdt gdt_desr \n"
kfraser@14373 52 " mov $0x0010,%ax \n"
kfraser@14373 53 " mov %ax,%ds \n"
kfraser@14373 54 " mov %ax,%es \n"
kfraser@14373 55 " mov %ax,%fs \n"
kfraser@14373 56 " mov %ax,%gs \n"
kfraser@14373 57 " mov %ax,%ss \n"
kfraser@14391 58 /* Initialise all 32-bit GPRs to zero. */
kfraser@14391 59 " xor %eax,%eax \n"
kfraser@14391 60 " xor %ebx,%ebx \n"
kfraser@14391 61 " xor %ecx,%ecx \n"
kfraser@14391 62 " xor %edx,%edx \n"
kfraser@14391 63 " xor %esp,%esp \n"
kfraser@14391 64 " xor %ebp,%ebp \n"
kfraser@14391 65 " xor %esi,%esi \n"
kfraser@14391 66 " xor %edi,%edi \n"
kfraser@14373 67 /* Enter real mode, reload all segment registers and IDT. */
kfraser@14391 68 " ljmp $0x8,$0x0 \n"
kfraser@14373 69 "trampoline_start: .code16 \n"
kfraser@14373 70 " mov %eax,%cr0 \n"
kfraser@14373 71 " ljmp $0,$1f-trampoline_start\n"
kfraser@14391 72 "1: mov %ax,%ds \n"
kfraser@14373 73 " mov %ax,%es \n"
kfraser@14373 74 " mov %ax,%fs \n"
kfraser@14373 75 " mov %ax,%gs \n"
kfraser@14373 76 " mov %ax,%ss \n"
kfraser@14373 77 " lidt 1f-trampoline_start \n"
kfraser@14373 78 " ljmp $0xf000,$0xfff0 \n"
kfraser@14373 79 "1: .word 0x3ff,0,0 \n"
kfraser@14373 80 "trampoline_end: .code32 \n"
kfraser@12548 81 " \n"
kfraser@12548 82 "gdt_desr: \n"
kfraser@12548 83 " .word gdt_end - gdt - 1 \n"
kfraser@12548 84 " .long gdt \n"
kfraser@12548 85 " \n"
kfraser@12548 86 " .align 8 \n"
kfraser@12548 87 "gdt: \n"
kfraser@12548 88 " .quad 0x0000000000000000 \n"
kfraser@14373 89 " .quad 0x00009a000000ffff \n" /* Ring 0 code, base 0 limit 0xffff */
kfraser@14373 90 " .quad 0x000092000000ffff \n" /* Ring 0 data, base 0 limit 0xffff */
kfraser@12548 91 "gdt_end: \n"
kfraser@12548 92 " \n"
kfraser@12548 93 " .bss \n"
kfraser@12548 94 " .align 8 \n"
kfraser@12548 95 "stack: \n"
kfraser@12548 96 " .skip 0x4000 \n"
kfraser@12548 97 "stack_top: \n"
kfraser@12548 98 );
kaf24@8708 99
kfraser@14959 100 void create_mp_tables(void);
kfraser@14959 101 int hvm_write_smbios_tables(void);
kaf24@8708 102
kfraser@10976 103 static int
kaf24@8708 104 cirrus_check(void)
kaf24@8708 105 {
kfraser@12548 106 outw(0x3C4, 0x9206);
kfraser@12548 107 return inb(0x3C5) == 0x12;
kaf24@8708 108 }
kaf24@8708 109
kfraser@10976 110 static int
kaf24@8708 111 check_amd(void)
kaf24@8708 112 {
kfraser@12548 113 char id[12];
kaf24@8708 114
kfraser@12548 115 __asm__ __volatile__ (
kfraser@12548 116 "cpuid"
kfraser@12548 117 : "=b" (*(int *)(&id[0])),
kfraser@12548 118 "=c" (*(int *)(&id[8])),
kfraser@12548 119 "=d" (*(int *)(&id[4]))
kfraser@12548 120 : "a" (0) );
kfraser@12548 121 return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
kaf24@8708 122 }
kaf24@8708 123
kfraser@10976 124 static void
kfraser@10976 125 wrmsr(uint32_t idx, uint64_t v)
kfraser@10976 126 {
kfraser@12548 127 __asm__ __volatile__ (
kfraser@12548 128 "wrmsr"
kfraser@12548 129 : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );
kfraser@10976 130 }
kfraser@10976 131
kfraser@10976 132 static void
kfraser@10976 133 init_hypercalls(void)
kfraser@10976 134 {
kfraser@12548 135 uint32_t eax, ebx, ecx, edx;
kfraser@12548 136 unsigned long i;
kfraser@12554 137 char signature[13];
kfraser@12548 138 xen_extraversion_t extraversion;
kfraser@10976 139
kfraser@12548 140 cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
kfraser@10976 141
kfraser@12548 142 *(uint32_t *)(signature + 0) = ebx;
kfraser@12548 143 *(uint32_t *)(signature + 4) = ecx;
kfraser@12548 144 *(uint32_t *)(signature + 8) = edx;
kfraser@12548 145 signature[12] = '\0';
kfraser@10976 146
kfraser@12548 147 if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) )
kfraser@12548 148 {
kfraser@12554 149 printf("FATAL: Xen hypervisor not detected\n");
kfraser@12548 150 __asm__ __volatile__( "ud2" );
kfraser@12548 151 }
kfraser@10976 152
kfraser@12554 153 /* Fill in hypercall transfer pages. */
kfraser@12548 154 cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
kfraser@12548 155 for ( i = 0; i < eax; i++ )
kfraser@12548 156 wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
kfraser@12548 157
kfraser@12554 158 /* Print version information. */
kfraser@12554 159 cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
kfraser@12548 160 hypercall_xen_version(XENVER_extraversion, extraversion);
kfraser@12554 161 printf("Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
kfraser@10976 162 }
kfraser@10976 163
kfraser@12548 164 static void apic_setup(void)
kaf24@8708 165 {
kaf24@12571 166 /* Set the IOAPIC ID to tha static value used in the MP/ACPI tables. */
kaf24@12571 167 ioapic_write(0x00, IOAPIC_ID);
kaf24@8708 168
kaf24@12571 169 /* Set up Virtual Wire mode. */
kaf24@12571 170 lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
kaf24@12571 171 lapic_write(APIC_LVT0, APIC_MODE_EXTINT << 8);
kaf24@12571 172 lapic_write(APIC_LVT1, APIC_MODE_NMI << 8);
kaf24@8708 173 }
kaf24@8708 174
kfraser@12554 175 static void pci_setup(void)
kfraser@12554 176 {
keir@16835 177 uint32_t base, devfn, bar_reg, bar_data, bar_sz, cmd;
kfraser@12554 178 uint16_t class, vendor_id, device_id;
kfraser@12554 179 unsigned int bar, pin, link, isa_irq;
kfraser@12554 180
keir@16835 181 /* Resources assignable to PCI devices via BARs. */
keir@16835 182 struct resource {
keir@16835 183 uint32_t base, max;
keir@16835 184 } *resource;
keir@16835 185 struct resource mem_resource = { 0xf0000000, 0xfc000000 };
keir@16835 186 struct resource io_resource = { 0xc000, 0x10000 };
keir@16835 187
keir@16834 188 /* Create a list of device BARs in descending order of size. */
keir@16834 189 struct bars {
keir@16834 190 uint32_t devfn, bar_reg, bar_sz;
keir@16834 191 } *bars = (struct bars *)0xc0000;
keir@16834 192 unsigned int i, nr_bars = 0;
keir@16834 193
kfraser@12554 194 /* Program PCI-ISA bridge with appropriate link routes. */
kfraser@15581 195 isa_irq = 0;
kfraser@15581 196 for ( link = 0; link < 4; link++ )
kfraser@12554 197 {
kfraser@15581 198 do { isa_irq = (isa_irq + 1) & 15;
kfraser@15581 199 } while ( !(PCI_ISA_IRQ_MASK & (1U << isa_irq)) );
kfraser@12554 200 pci_writeb(PCI_ISA_DEVFN, 0x60 + link, isa_irq);
kfraser@12554 201 printf("PCI-ISA link %u routed to IRQ%u\n", link, isa_irq);
kfraser@12554 202 }
kfraser@12554 203
kfraser@12554 204 /* Program ELCR to match PCI-wired IRQs. */
kfraser@12554 205 outb(0x4d0, (uint8_t)(PCI_ISA_IRQ_MASK >> 0));
kfraser@12554 206 outb(0x4d1, (uint8_t)(PCI_ISA_IRQ_MASK >> 8));
kfraser@12554 207
kfraser@12554 208 /* Scan the PCI bus and map resources. */
kfraser@12554 209 for ( devfn = 0; devfn < 128; devfn++ )
kfraser@12554 210 {
kfraser@12554 211 class = pci_readw(devfn, PCI_CLASS_DEVICE);
kfraser@12554 212 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
kfraser@12554 213 device_id = pci_readw(devfn, PCI_DEVICE_ID);
kfraser@12554 214 if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
kfraser@12554 215 continue;
kfraser@12554 216
kfraser@12554 217 ASSERT((devfn != PCI_ISA_DEVFN) ||
kfraser@12554 218 ((vendor_id == 0x8086) && (device_id == 0x7000)));
kfraser@12554 219
kfraser@12554 220 switch ( class )
kfraser@12554 221 {
kfraser@12554 222 case 0x0680:
kfraser@12554 223 ASSERT((vendor_id == 0x8086) && (device_id == 0x7113));
kfraser@12554 224 /*
kfraser@12554 225 * PIIX4 ACPI PM. Special device with special PCI config space.
kfraser@12554 226 * No ordinary BARs.
kfraser@12554 227 */
kfraser@12554 228 pci_writew(devfn, 0x20, 0x0000); /* No smb bus IO enable */
kfraser@12554 229 pci_writew(devfn, 0x22, 0x0000);
kfraser@12554 230 pci_writew(devfn, 0x3c, 0x0009); /* Hardcoded IRQ9 */
kfraser@12554 231 pci_writew(devfn, 0x3d, 0x0001);
kfraser@12554 232 break;
kfraser@12554 233 case 0x0101:
kfraser@12554 234 /* PIIX3 IDE */
kfraser@12554 235 ASSERT((vendor_id == 0x8086) && (device_id == 0x7010));
kfraser@12554 236 pci_writew(devfn, 0x40, 0x8000); /* enable IDE0 */
kfraser@12554 237 pci_writew(devfn, 0x42, 0x8000); /* enable IDE1 */
kfraser@12554 238 /* fall through */
kfraser@12554 239 default:
kfraser@12554 240 /* Default memory mappings. */
kfraser@12554 241 for ( bar = 0; bar < 7; bar++ )
kfraser@12554 242 {
kfraser@12554 243 bar_reg = PCI_BASE_ADDRESS_0 + 4*bar;
kfraser@12554 244 if ( bar == 6 )
kfraser@12554 245 bar_reg = PCI_ROM_ADDRESS;
kfraser@12554 246
kfraser@12554 247 bar_data = pci_readl(devfn, bar_reg);
kfraser@12554 248 pci_writel(devfn, bar_reg, ~0);
kfraser@12554 249 bar_sz = pci_readl(devfn, bar_reg);
keir@16834 250 pci_writel(devfn, bar_reg, bar_data);
kfraser@12554 251 if ( bar_sz == 0 )
kfraser@12554 252 continue;
kfraser@12554 253
keir@16834 254 bar_sz &= (((bar_data & PCI_BASE_ADDRESS_SPACE) ==
keir@16834 255 PCI_BASE_ADDRESS_SPACE_MEMORY) ?
keir@16834 256 PCI_BASE_ADDRESS_MEM_MASK :
keir@16834 257 (PCI_BASE_ADDRESS_IO_MASK & 0xffff));
kfraser@12554 258 bar_sz &= ~(bar_sz - 1);
kfraser@12554 259
keir@16834 260 for ( i = 0; i < nr_bars; i++ )
keir@16834 261 if ( bars[i].bar_sz < bar_sz )
keir@16834 262 break;
kfraser@12554 263
keir@16834 264 if ( i != nr_bars )
keir@16834 265 memmove(&bars[i+1], &bars[i], (nr_bars-i) * sizeof(*bars));
keir@16834 266
keir@16834 267 bars[i].devfn = devfn;
keir@16834 268 bars[i].bar_reg = bar_reg;
keir@16834 269 bars[i].bar_sz = bar_sz;
keir@16834 270
keir@16834 271 nr_bars++;
kfraser@12554 272 }
kfraser@12554 273 break;
kfraser@12554 274 }
kfraser@12554 275
kfraser@12554 276 /* Map the interrupt. */
kfraser@12554 277 pin = pci_readb(devfn, PCI_INTERRUPT_PIN);
kfraser@12554 278 if ( pin != 0 )
kfraser@12554 279 {
kfraser@12554 280 /* This is the barber's pole mapping used by Xen. */
kfraser@12554 281 link = ((pin - 1) + (devfn >> 3)) & 3;
kfraser@12554 282 isa_irq = pci_readb(PCI_ISA_DEVFN, 0x60 + link);
kfraser@12554 283 pci_writeb(devfn, PCI_INTERRUPT_LINE, isa_irq);
kfraser@12554 284 printf("pci dev %02x:%x INT%c->IRQ%u\n",
kfraser@12554 285 devfn>>3, devfn&7, 'A'+pin-1, isa_irq);
kfraser@12554 286 }
kfraser@12554 287 }
keir@16834 288
keir@16834 289 /* Assign iomem and ioport resources in descending order of size. */
keir@16834 290 for ( i = 0; i < nr_bars; i++ )
keir@16834 291 {
keir@16834 292 devfn = bars[i].devfn;
keir@16834 293 bar_reg = bars[i].bar_reg;
keir@16834 294 bar_sz = bars[i].bar_sz;
keir@16834 295
keir@16834 296 bar_data = pci_readl(devfn, bar_reg);
keir@16834 297
keir@16834 298 if ( (bar_data & PCI_BASE_ADDRESS_SPACE) ==
keir@16834 299 PCI_BASE_ADDRESS_SPACE_MEMORY )
keir@16834 300 {
keir@16835 301 resource = &mem_resource;
keir@16834 302 bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK;
keir@16834 303 }
keir@16834 304 else
keir@16834 305 {
keir@16835 306 resource = &io_resource;
keir@16834 307 bar_data &= ~PCI_BASE_ADDRESS_IO_MASK;
keir@16834 308 }
keir@16834 309
keir@16835 310 base = (resource->base + bar_sz - 1) & ~(bar_sz - 1);
keir@16835 311 bar_data |= base;
keir@16835 312 base += bar_sz;
keir@16835 313
keir@16835 314 if ( (base < resource->base) || (base > resource->max) )
keir@16835 315 {
keir@16835 316 printf("pci dev %02x:%x bar %02x size %08x: no space for "
keir@16835 317 "resource!\n", devfn>>3, devfn&7, bar_reg, bar_sz);
keir@16835 318 continue;
keir@16835 319 }
keir@16835 320
keir@16835 321 resource->base = base;
keir@16834 322
keir@16834 323 pci_writel(devfn, bar_reg, bar_data);
keir@16835 324 printf("pci dev %02x:%x bar %02x size %08x: %08x\n",
keir@16835 325 devfn>>3, devfn&7, bar_reg, bar_sz, bar_data);
keir@16834 326
keir@16834 327 /* Now enable the memory or I/O mapping. */
keir@16834 328 cmd = pci_readw(devfn, PCI_COMMAND);
keir@16834 329 if ( (bar_reg == PCI_ROM_ADDRESS) ||
keir@16834 330 ((bar_data & PCI_BASE_ADDRESS_SPACE) ==
keir@16834 331 PCI_BASE_ADDRESS_SPACE_MEMORY) )
keir@16834 332 cmd |= PCI_COMMAND_MEMORY;
keir@16834 333 else
keir@16834 334 cmd |= PCI_COMMAND_IO;
keir@16834 335 pci_writew(devfn, PCI_COMMAND, cmd);
keir@16834 336 }
kfraser@12554 337 }
kfraser@12554 338
keir@16747 339 static int must_load_extboot(void)
keir@16747 340 {
keir@16747 341 return (inb(0x404) == 1);
keir@16747 342 }
keir@16747 343
keir@16960 344 /*
keir@16960 345 * Scan the PCI bus for the first NIC supported by etherboot, and copy
keir@16960 346 * the corresponding rom data to *copy_rom_dest. Returns the length of the
keir@16960 347 * selected rom, or 0 if no NIC found.
keir@16960 348 */
keir@16960 349 static int scan_etherboot_nic(void *copy_rom_dest)
keir@16960 350 {
keir@16960 351 static struct etherboots_table_entry {
keir@16960 352 char *name;
keir@16960 353 void *etherboot_rom;
keir@16960 354 int etherboot_sz;
keir@16960 355 uint16_t vendor, device;
keir@16960 356 } etherboots_table[] = {
keir@16960 357 #define ETHERBOOT_ROM(name, vendor, device) \
keir@16960 358 { #name, etherboot_##name, sizeof(etherboot_##name), vendor, device },
keir@16960 359 ETHERBOOT_ROM_LIST
keir@16960 360 { 0 }
keir@16960 361 };
keir@16960 362
keir@16960 363 uint32_t devfn;
keir@16960 364 uint16_t class, vendor_id, device_id;
keir@16960 365 struct etherboots_table_entry *eb;
keir@16960 366
keir@16960 367 for ( devfn = 0; devfn < 128; devfn++ )
keir@16960 368 {
keir@16960 369 class = pci_readw(devfn, PCI_CLASS_DEVICE);
keir@16960 370 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
keir@16960 371 device_id = pci_readw(devfn, PCI_DEVICE_ID);
keir@16960 372
keir@16960 373 if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
keir@16960 374 continue;
keir@16960 375
keir@16960 376 if ( class != 0x0200 ) /* Not a NIC */
keir@16960 377 continue;
keir@16960 378
keir@16960 379 for ( eb = etherboots_table; eb->name; eb++ )
keir@16960 380 if (eb->vendor == vendor_id &&
keir@16960 381 eb->device == device_id)
keir@16960 382 goto found;
keir@16960 383 }
keir@16960 384
keir@16960 385 return 0;
keir@16960 386
keir@16960 387 found:
keir@16960 388 printf("Loading %s Etherboot PXE ROM ...\n", eb->name);
keir@16960 389 memcpy(copy_rom_dest, eb->etherboot_rom, eb->etherboot_sz);
keir@16960 390 return eb->etherboot_sz;
keir@16960 391 }
keir@16960 392
keir@14449 393 /* Replace possibly erroneous memory-size CMOS fields with correct values. */
keir@14449 394 static void cmos_write_memory_size(void)
keir@14449 395 {
keir@15303 396 struct e820entry *map = HVM_E820;
keir@15303 397 int i, nr = *HVM_E820_NR;
keir@14449 398 uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0;
keir@14449 399
keir@14449 400 for ( i = 0; i < nr; i++ )
keir@14449 401 if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) )
keir@14449 402 break;
keir@14449 403
keir@14449 404 if ( i != nr )
keir@14449 405 {
keir@14449 406 alt_mem = ext_mem = map[i].addr + map[i].size;
keir@14449 407 ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
keir@14449 408 if ( ext_mem > 0xffff )
keir@14449 409 ext_mem = 0xffff;
keir@14449 410 alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
keir@14449 411 }
keir@14449 412
keir@14877 413 /* All BIOSes: conventional memory (CMOS *always* reports 640kB). */
keir@14449 414 cmos_outb(0x15, (uint8_t)(base_mem >> 0));
keir@14449 415 cmos_outb(0x16, (uint8_t)(base_mem >> 8));
keir@14449 416
keir@14449 417 /* All BIOSes: extended memory (1kB chunks above 1MB). */
keir@14449 418 cmos_outb(0x17, (uint8_t)( ext_mem >> 0));
keir@14449 419 cmos_outb(0x18, (uint8_t)( ext_mem >> 8));
keir@14449 420 cmos_outb(0x30, (uint8_t)( ext_mem >> 0));
keir@14449 421 cmos_outb(0x31, (uint8_t)( ext_mem >> 8));
keir@14449 422
keir@14449 423 /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */
keir@14449 424 cmos_outb(0x34, (uint8_t)( alt_mem >> 0));
keir@14449 425 cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
Tim@13140 426 }
Tim@13140 427
kfraser@12548 428 int main(void)
kfraser@12548 429 {
kfraser@14959 430 int acpi_sz = 0, vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz;
keir@16747 431 int extboot_sz = 0;
kaf24@12574 432
kfraser@12554 433 printf("HVM Loader\n");
kfraser@12548 434
kfraser@12548 435 init_hypercalls();
kfraser@12548 436
kfraser@12554 437 printf("Writing SMBIOS tables ...\n");
kfraser@14959 438 smbios_sz = hvm_write_smbios_tables();
kfraser@12548 439
kfraser@12554 440 printf("Loading ROMBIOS ...\n");
kfraser@14959 441 rombios_sz = sizeof(rombios);
kfraser@14959 442 if ( rombios_sz > 0x10000 )
kfraser@14959 443 rombios_sz = 0x10000;
kfraser@14959 444 memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, rombios_sz);
kaf24@13656 445 highbios_setup();
kfraser@12548 446
kfraser@12548 447 apic_setup();
kfraser@12554 448 pci_setup();
kaf24@12574 449
kfraser@12600 450 if ( (get_vcpu_nr() > 1) || get_apic_mode() )
kaf24@12574 451 create_mp_tables();
kfraser@12548 452
kfraser@12548 453 if ( cirrus_check() )
kfraser@12548 454 {
kfraser@12554 455 printf("Loading Cirrus VGABIOS ...\n");
kfraser@12548 456 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kfraser@12548 457 vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
kfraser@14959 458 vgabios_sz = sizeof(vgabios_cirrusvga);
kfraser@12548 459 }
kfraser@12548 460 else
kfraser@12548 461 {
kfraser@12554 462 printf("Loading Standard VGABIOS ...\n");
kfraser@12548 463 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kfraser@12548 464 vgabios_stdvga, sizeof(vgabios_stdvga));
kfraser@14959 465 vgabios_sz = sizeof(vgabios_stdvga);
kfraser@12548 466 }
kfraser@12548 467
keir@16960 468 etherboot_sz = scan_etherboot_nic((void*)ETHERBOOT_PHYSICAL_ADDRESS);
Tim@13140 469
keir@16747 470 if ( must_load_extboot() )
keir@16747 471 {
keir@16747 472 printf("Loading EXTBOOT ...\n");
keir@16747 473 memcpy((void *)EXTBOOT_PHYSICAL_ADDRESS,
keir@16747 474 extboot, sizeof(extboot));
keir@16747 475 extboot_sz = sizeof(extboot);
keir@16747 476 }
keir@16747 477
kfraser@14959 478 if ( get_acpi_enabled() )
kfraser@12548 479 {
kfraser@12554 480 printf("Loading ACPI ...\n");
kaf24@12574 481 acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS);
kfraser@12634 482 ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000);
kfraser@12548 483 }
kfraser@12548 484
keir@14449 485 cmos_write_memory_size();
keir@14449 486
kfraser@14959 487 printf("BIOS map:\n");
kfraser@14959 488 if ( vgabios_sz )
kfraser@14959 489 printf(" %05x-%05x: VGA BIOS\n",
kfraser@14959 490 VGABIOS_PHYSICAL_ADDRESS,
kfraser@14959 491 VGABIOS_PHYSICAL_ADDRESS + vgabios_sz - 1);
kfraser@14959 492 if ( etherboot_sz )
kfraser@14959 493 printf(" %05x-%05x: Etherboot ROM\n",
kfraser@14959 494 ETHERBOOT_PHYSICAL_ADDRESS,
kfraser@14959 495 ETHERBOOT_PHYSICAL_ADDRESS + etherboot_sz - 1);
keir@16747 496 if ( extboot_sz )
keir@16747 497 printf(" %05x-%05x: Extboot ROM\n",
keir@16747 498 EXTBOOT_PHYSICAL_ADDRESS,
keir@16747 499 EXTBOOT_PHYSICAL_ADDRESS + extboot_sz - 1);
kfraser@14959 500 if ( smbios_sz )
kfraser@14959 501 printf(" %05x-%05x: SMBIOS tables\n",
kfraser@14959 502 SMBIOS_PHYSICAL_ADDRESS,
kfraser@14959 503 SMBIOS_PHYSICAL_ADDRESS + smbios_sz - 1);
kfraser@14959 504 if ( acpi_sz )
kfraser@14959 505 printf(" %05x-%05x: ACPI tables\n",
kfraser@14959 506 ACPI_PHYSICAL_ADDRESS,
kfraser@14959 507 ACPI_PHYSICAL_ADDRESS + acpi_sz - 1);
kfraser@14959 508 if ( rombios_sz )
kfraser@14959 509 printf(" %05x-%05x: Main BIOS\n",
kfraser@14959 510 ROMBIOS_PHYSICAL_ADDRESS,
kfraser@14959 511 ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1);
kfraser@14959 512
kfraser@14373 513 printf("Invoking ROMBIOS ...\n");
kfraser@12548 514 return 0;
kfraser@12548 515 }
kfraser@12548 516
kfraser@12548 517 /*
kfraser@12548 518 * Local variables:
kfraser@12548 519 * mode: C
kfraser@12548 520 * c-set-style: "BSD"
kfraser@12548 521 * c-basic-offset: 4
kfraser@12548 522 * tab-width: 4
kfraser@12548 523 * indent-tabs-mode: nil
kfraser@12548 524 * End:
kfraser@12548 525 */