| 1 | /* |
|---|
| 2 | * hvmloader.c: HVM ROMBIOS/VGABIOS/ACPI/VMXAssist image loader. |
|---|
| 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 | */ |
|---|
| 22 | |
|---|
| 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 <xen/version.h> |
|---|
| 31 | #include <xen/hvm/params.h> |
|---|
| 32 | |
|---|
| 33 | asm( |
|---|
| 34 | " .text \n" |
|---|
| 35 | " .globl _start \n" |
|---|
| 36 | "_start: \n" |
|---|
| 37 | /* C runtime kickoff. */ |
|---|
| 38 | " cld \n" |
|---|
| 39 | " cli \n" |
|---|
| 40 | " movl $stack_top,%esp \n" |
|---|
| 41 | " movl %esp,%ebp \n" |
|---|
| 42 | " call main \n" |
|---|
| 43 | /* Relocate real-mode trampoline to 0x0. */ |
|---|
| 44 | " mov $trampoline_start,%esi \n" |
|---|
| 45 | " xor %edi,%edi \n" |
|---|
| 46 | " mov $trampoline_end,%ecx \n" |
|---|
| 47 | " sub %esi,%ecx \n" |
|---|
| 48 | " rep movsb \n" |
|---|
| 49 | /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */ |
|---|
| 50 | " lgdt gdt_desr \n" |
|---|
| 51 | " mov $0x0010,%ax \n" |
|---|
| 52 | " mov %ax,%ds \n" |
|---|
| 53 | " mov %ax,%es \n" |
|---|
| 54 | " mov %ax,%fs \n" |
|---|
| 55 | " mov %ax,%gs \n" |
|---|
| 56 | " mov %ax,%ss \n" |
|---|
| 57 | /* Initialise all 32-bit GPRs to zero. */ |
|---|
| 58 | " xor %eax,%eax \n" |
|---|
| 59 | " xor %ebx,%ebx \n" |
|---|
| 60 | " xor %ecx,%ecx \n" |
|---|
| 61 | " xor %edx,%edx \n" |
|---|
| 62 | " xor %esp,%esp \n" |
|---|
| 63 | " xor %ebp,%ebp \n" |
|---|
| 64 | " xor %esi,%esi \n" |
|---|
| 65 | " xor %edi,%edi \n" |
|---|
| 66 | /* Enter real mode, reload all segment registers and IDT. */ |
|---|
| 67 | " ljmp $0x8,$0x0 \n" |
|---|
| 68 | "trampoline_start: .code16 \n" |
|---|
| 69 | " mov %eax,%cr0 \n" |
|---|
| 70 | " ljmp $0,$1f-trampoline_start\n" |
|---|
| 71 | "1: mov %ax,%ds \n" |
|---|
| 72 | " mov %ax,%es \n" |
|---|
| 73 | " mov %ax,%fs \n" |
|---|
| 74 | " mov %ax,%gs \n" |
|---|
| 75 | " mov %ax,%ss \n" |
|---|
| 76 | " lidt 1f-trampoline_start \n" |
|---|
| 77 | " ljmp $0xf000,$0xfff0 \n" |
|---|
| 78 | "1: .word 0x3ff,0,0 \n" |
|---|
| 79 | "trampoline_end: .code32 \n" |
|---|
| 80 | " \n" |
|---|
| 81 | "gdt_desr: \n" |
|---|
| 82 | " .word gdt_end - gdt - 1 \n" |
|---|
| 83 | " .long gdt \n" |
|---|
| 84 | " \n" |
|---|
| 85 | " .align 8 \n" |
|---|
| 86 | "gdt: \n" |
|---|
| 87 | " .quad 0x0000000000000000 \n" |
|---|
| 88 | " .quad 0x00009a000000ffff \n" /* Ring 0 code, base 0 limit 0xffff */ |
|---|
| 89 | " .quad 0x000092000000ffff \n" /* Ring 0 data, base 0 limit 0xffff */ |
|---|
| 90 | "gdt_end: \n" |
|---|
| 91 | " \n" |
|---|
| 92 | " .bss \n" |
|---|
| 93 | " .align 8 \n" |
|---|
| 94 | "stack: \n" |
|---|
| 95 | " .skip 0x4000 \n" |
|---|
| 96 | "stack_top: \n" |
|---|
| 97 | ); |
|---|
| 98 | |
|---|
| 99 | void create_mp_tables(void); |
|---|
| 100 | int hvm_write_smbios_tables(void); |
|---|
| 101 | |
|---|
| 102 | static int |
|---|
| 103 | cirrus_check(void) |
|---|
| 104 | { |
|---|
| 105 | outw(0x3C4, 0x9206); |
|---|
| 106 | return inb(0x3C5) == 0x12; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | static int |
|---|
| 110 | check_amd(void) |
|---|
| 111 | { |
|---|
| 112 | char id[12]; |
|---|
| 113 | |
|---|
| 114 | __asm__ __volatile__ ( |
|---|
| 115 | "cpuid" |
|---|
| 116 | : "=b" (*(int *)(&id[0])), |
|---|
| 117 | "=c" (*(int *)(&id[8])), |
|---|
| 118 | "=d" (*(int *)(&id[4])) |
|---|
| 119 | : "a" (0) ); |
|---|
| 120 | return __builtin_memcmp(id, "AuthenticAMD", 12) == 0; |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | static void |
|---|
| 124 | wrmsr(uint32_t idx, uint64_t v) |
|---|
| 125 | { |
|---|
| 126 | __asm__ __volatile__ ( |
|---|
| 127 | "wrmsr" |
|---|
| 128 | : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) ); |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | static void |
|---|
| 132 | init_hypercalls(void) |
|---|
| 133 | { |
|---|
| 134 | uint32_t eax, ebx, ecx, edx; |
|---|
| 135 | unsigned long i; |
|---|
| 136 | char signature[13]; |
|---|
| 137 | xen_extraversion_t extraversion; |
|---|
| 138 | |
|---|
| 139 | cpuid(0x40000000, &eax, &ebx, &ecx, &edx); |
|---|
| 140 | |
|---|
| 141 | *(uint32_t *)(signature + 0) = ebx; |
|---|
| 142 | *(uint32_t *)(signature + 4) = ecx; |
|---|
| 143 | *(uint32_t *)(signature + 8) = edx; |
|---|
| 144 | signature[12] = '\0'; |
|---|
| 145 | |
|---|
| 146 | if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) ) |
|---|
| 147 | { |
|---|
| 148 | printf("FATAL: Xen hypervisor not detected\n"); |
|---|
| 149 | __asm__ __volatile__( "ud2" ); |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | /* Fill in hypercall transfer pages. */ |
|---|
| 153 | cpuid(0x40000002, &eax, &ebx, &ecx, &edx); |
|---|
| 154 | for ( i = 0; i < eax; i++ ) |
|---|
| 155 | wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i); |
|---|
| 156 | |
|---|
| 157 | /* Print version information. */ |
|---|
| 158 | cpuid(0x40000001, &eax, &ebx, &ecx, &edx); |
|---|
| 159 | hypercall_xen_version(XENVER_extraversion, extraversion); |
|---|
| 160 | printf("Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion); |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | static void apic_setup(void) |
|---|
| 164 | { |
|---|
| 165 | /* Set the IOAPIC ID to tha static value used in the MP/ACPI tables. */ |
|---|
| 166 | ioapic_write(0x00, IOAPIC_ID); |
|---|
| 167 | |
|---|
| 168 | /* Set up Virtual Wire mode. */ |
|---|
| 169 | lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF); |
|---|
| 170 | lapic_write(APIC_LVT0, APIC_MODE_EXTINT << 8); |
|---|
| 171 | lapic_write(APIC_LVT1, APIC_MODE_NMI << 8); |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | static void pci_setup(void) |
|---|
| 175 | { |
|---|
| 176 | uint32_t devfn, bar_reg, bar_data, bar_sz, cmd; |
|---|
| 177 | uint32_t *base, io_base = 0xc000, mem_base = HVM_BELOW_4G_MMIO_START; |
|---|
| 178 | uint16_t class, vendor_id, device_id; |
|---|
| 179 | unsigned int bar, pin, link, isa_irq; |
|---|
| 180 | |
|---|
| 181 | /* Program PCI-ISA bridge with appropriate link routes. */ |
|---|
| 182 | link = 0; |
|---|
| 183 | for ( isa_irq = 0; isa_irq < 15; isa_irq++ ) |
|---|
| 184 | { |
|---|
| 185 | if ( !(PCI_ISA_IRQ_MASK & (1U << isa_irq)) ) |
|---|
| 186 | continue; |
|---|
| 187 | pci_writeb(PCI_ISA_DEVFN, 0x60 + link, isa_irq); |
|---|
| 188 | printf("PCI-ISA link %u routed to IRQ%u\n", link, isa_irq); |
|---|
| 189 | if ( link++ == 4 ) |
|---|
| 190 | break; |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | /* Program ELCR to match PCI-wired IRQs. */ |
|---|
| 194 | outb(0x4d0, (uint8_t)(PCI_ISA_IRQ_MASK >> 0)); |
|---|
| 195 | outb(0x4d1, (uint8_t)(PCI_ISA_IRQ_MASK >> 8)); |
|---|
| 196 | |
|---|
| 197 | /* Scan the PCI bus and map resources. */ |
|---|
| 198 | for ( devfn = 0; devfn < 128; devfn++ ) |
|---|
| 199 | { |
|---|
| 200 | class = pci_readw(devfn, PCI_CLASS_DEVICE); |
|---|
| 201 | vendor_id = pci_readw(devfn, PCI_VENDOR_ID); |
|---|
| 202 | device_id = pci_readw(devfn, PCI_DEVICE_ID); |
|---|
| 203 | if ( (vendor_id == 0xffff) && (device_id == 0xffff) ) |
|---|
| 204 | continue; |
|---|
| 205 | |
|---|
| 206 | ASSERT((devfn != PCI_ISA_DEVFN) || |
|---|
| 207 | ((vendor_id == 0x8086) && (device_id == 0x7000))); |
|---|
| 208 | |
|---|
| 209 | switch ( class ) |
|---|
| 210 | { |
|---|
| 211 | case 0x0680: |
|---|
| 212 | ASSERT((vendor_id == 0x8086) && (device_id == 0x7113)); |
|---|
| 213 | /* |
|---|
| 214 | * PIIX4 ACPI PM. Special device with special PCI config space. |
|---|
| 215 | * No ordinary BARs. |
|---|
| 216 | */ |
|---|
| 217 | pci_writew(devfn, 0x20, 0x0000); /* No smb bus IO enable */ |
|---|
| 218 | pci_writew(devfn, 0x22, 0x0000); |
|---|
| 219 | pci_writew(devfn, 0x3c, 0x0009); /* Hardcoded IRQ9 */ |
|---|
| 220 | pci_writew(devfn, 0x3d, 0x0001); |
|---|
| 221 | break; |
|---|
| 222 | case 0x0101: |
|---|
| 223 | /* PIIX3 IDE */ |
|---|
| 224 | ASSERT((vendor_id == 0x8086) && (device_id == 0x7010)); |
|---|
| 225 | pci_writew(devfn, 0x40, 0x8000); /* enable IDE0 */ |
|---|
| 226 | pci_writew(devfn, 0x42, 0x8000); /* enable IDE1 */ |
|---|
| 227 | /* fall through */ |
|---|
| 228 | default: |
|---|
| 229 | /* Default memory mappings. */ |
|---|
| 230 | for ( bar = 0; bar < 7; bar++ ) |
|---|
| 231 | { |
|---|
| 232 | bar_reg = PCI_BASE_ADDRESS_0 + 4*bar; |
|---|
| 233 | if ( bar == 6 ) |
|---|
| 234 | bar_reg = PCI_ROM_ADDRESS; |
|---|
| 235 | |
|---|
| 236 | bar_data = pci_readl(devfn, bar_reg); |
|---|
| 237 | |
|---|
| 238 | pci_writel(devfn, bar_reg, ~0); |
|---|
| 239 | bar_sz = pci_readl(devfn, bar_reg); |
|---|
| 240 | if ( bar_sz == 0 ) |
|---|
| 241 | continue; |
|---|
| 242 | |
|---|
| 243 | if ( (bar_data & PCI_BASE_ADDRESS_SPACE) == |
|---|
| 244 | PCI_BASE_ADDRESS_SPACE_MEMORY ) |
|---|
| 245 | { |
|---|
| 246 | base = &mem_base; |
|---|
| 247 | bar_sz &= PCI_BASE_ADDRESS_MEM_MASK; |
|---|
| 248 | bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK; |
|---|
| 249 | } |
|---|
| 250 | else |
|---|
| 251 | { |
|---|
| 252 | base = &io_base; |
|---|
| 253 | bar_sz &= PCI_BASE_ADDRESS_IO_MASK & 0xffff; |
|---|
| 254 | bar_data &= ~PCI_BASE_ADDRESS_IO_MASK; |
|---|
| 255 | } |
|---|
| 256 | bar_sz &= ~(bar_sz - 1); |
|---|
| 257 | |
|---|
| 258 | *base = (*base + bar_sz - 1) & ~(bar_sz - 1); |
|---|
| 259 | bar_data |= *base; |
|---|
| 260 | *base += bar_sz; |
|---|
| 261 | |
|---|
| 262 | pci_writel(devfn, bar_reg, bar_data); |
|---|
| 263 | printf("pci dev %02x:%x bar %02x size %08x: %08x\n", |
|---|
| 264 | devfn>>3, devfn&7, bar_reg, bar_sz, bar_data); |
|---|
| 265 | |
|---|
| 266 | /* Now enable the memory or I/O mapping. */ |
|---|
| 267 | cmd = pci_readw(devfn, PCI_COMMAND); |
|---|
| 268 | if ( (bar_reg == PCI_ROM_ADDRESS) || |
|---|
| 269 | ((bar_data & PCI_BASE_ADDRESS_SPACE) == |
|---|
| 270 | PCI_BASE_ADDRESS_SPACE_MEMORY) ) |
|---|
| 271 | cmd |= PCI_COMMAND_MEMORY; |
|---|
| 272 | else |
|---|
| 273 | cmd |= PCI_COMMAND_IO; |
|---|
| 274 | pci_writew(devfn, PCI_COMMAND, cmd); |
|---|
| 275 | } |
|---|
| 276 | break; |
|---|
| 277 | } |
|---|
| 278 | |
|---|
| 279 | /* Map the interrupt. */ |
|---|
| 280 | pin = pci_readb(devfn, PCI_INTERRUPT_PIN); |
|---|
| 281 | if ( pin != 0 ) |
|---|
| 282 | { |
|---|
| 283 | /* This is the barber's pole mapping used by Xen. */ |
|---|
| 284 | link = ((pin - 1) + (devfn >> 3)) & 3; |
|---|
| 285 | isa_irq = pci_readb(PCI_ISA_DEVFN, 0x60 + link); |
|---|
| 286 | pci_writeb(devfn, PCI_INTERRUPT_LINE, isa_irq); |
|---|
| 287 | printf("pci dev %02x:%x INT%c->IRQ%u\n", |
|---|
| 288 | devfn>>3, devfn&7, 'A'+pin-1, isa_irq); |
|---|
| 289 | } |
|---|
| 290 | } |
|---|
| 291 | } |
|---|
| 292 | |
|---|
| 293 | /* |
|---|
| 294 | * If the network card is in the boot order, load the Etherboot option ROM. |
|---|
| 295 | * Read the boot order bytes from CMOS and check if any of them are 0x4. |
|---|
| 296 | */ |
|---|
| 297 | static int must_load_nic(void) |
|---|
| 298 | { |
|---|
| 299 | uint8_t boot_order; |
|---|
| 300 | |
|---|
| 301 | /* Read CMOS register 0x3d (boot choices 0 and 1). */ |
|---|
| 302 | boot_order = cmos_inb(0x3d); |
|---|
| 303 | if ( ((boot_order & 0xf) == 0x4) || ((boot_order & 0xf0) == 0x40) ) |
|---|
| 304 | return 1; |
|---|
| 305 | |
|---|
| 306 | /* Read CMOS register 0x38 (boot choice 2 and FDD test flag). */ |
|---|
| 307 | boot_order = cmos_inb(0x38); |
|---|
| 308 | return ((boot_order & 0xf0) == 0x40); |
|---|
| 309 | } |
|---|
| 310 | |
|---|
| 311 | /* Replace possibly erroneous memory-size CMOS fields with correct values. */ |
|---|
| 312 | static void cmos_write_memory_size(void) |
|---|
| 313 | { |
|---|
| 314 | struct e820entry *map = E820_MAP; |
|---|
| 315 | int i, nr = *E820_MAP_NR; |
|---|
| 316 | uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0; |
|---|
| 317 | |
|---|
| 318 | for ( i = 0; i < nr; i++ ) |
|---|
| 319 | if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) ) |
|---|
| 320 | break; |
|---|
| 321 | |
|---|
| 322 | if ( i != nr ) |
|---|
| 323 | { |
|---|
| 324 | alt_mem = ext_mem = map[i].addr + map[i].size; |
|---|
| 325 | ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0; |
|---|
| 326 | if ( ext_mem > 0xffff ) |
|---|
| 327 | ext_mem = 0xffff; |
|---|
| 328 | alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0; |
|---|
| 329 | } |
|---|
| 330 | |
|---|
| 331 | /* All BIOSes: conventional memory (CMOS *always* reports 640kB). */ |
|---|
| 332 | cmos_outb(0x15, (uint8_t)(base_mem >> 0)); |
|---|
| 333 | cmos_outb(0x16, (uint8_t)(base_mem >> 8)); |
|---|
| 334 | |
|---|
| 335 | /* All BIOSes: extended memory (1kB chunks above 1MB). */ |
|---|
| 336 | cmos_outb(0x17, (uint8_t)( ext_mem >> 0)); |
|---|
| 337 | cmos_outb(0x18, (uint8_t)( ext_mem >> 8)); |
|---|
| 338 | cmos_outb(0x30, (uint8_t)( ext_mem >> 0)); |
|---|
| 339 | cmos_outb(0x31, (uint8_t)( ext_mem >> 8)); |
|---|
| 340 | |
|---|
| 341 | /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */ |
|---|
| 342 | cmos_outb(0x34, (uint8_t)( alt_mem >> 0)); |
|---|
| 343 | cmos_outb(0x35, (uint8_t)( alt_mem >> 8)); |
|---|
| 344 | } |
|---|
| 345 | |
|---|
| 346 | int main(void) |
|---|
| 347 | { |
|---|
| 348 | int acpi_sz = 0, vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz; |
|---|
| 349 | |
|---|
| 350 | printf("HVM Loader\n"); |
|---|
| 351 | |
|---|
| 352 | init_hypercalls(); |
|---|
| 353 | |
|---|
| 354 | printf("Writing SMBIOS tables ...\n"); |
|---|
| 355 | smbios_sz = hvm_write_smbios_tables(); |
|---|
| 356 | |
|---|
| 357 | printf("Loading ROMBIOS ...\n"); |
|---|
| 358 | rombios_sz = sizeof(rombios); |
|---|
| 359 | if ( rombios_sz > 0x10000 ) |
|---|
| 360 | rombios_sz = 0x10000; |
|---|
| 361 | memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, rombios_sz); |
|---|
| 362 | highbios_setup(); |
|---|
| 363 | |
|---|
| 364 | apic_setup(); |
|---|
| 365 | pci_setup(); |
|---|
| 366 | |
|---|
| 367 | if ( (get_vcpu_nr() > 1) || get_apic_mode() ) |
|---|
| 368 | create_mp_tables(); |
|---|
| 369 | |
|---|
| 370 | if ( cirrus_check() ) |
|---|
| 371 | { |
|---|
| 372 | printf("Loading Cirrus VGABIOS ...\n"); |
|---|
| 373 | memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, |
|---|
| 374 | vgabios_cirrusvga, sizeof(vgabios_cirrusvga)); |
|---|
| 375 | vgabios_sz = sizeof(vgabios_cirrusvga); |
|---|
| 376 | } |
|---|
| 377 | else |
|---|
| 378 | { |
|---|
| 379 | printf("Loading Standard VGABIOS ...\n"); |
|---|
| 380 | memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, |
|---|
| 381 | vgabios_stdvga, sizeof(vgabios_stdvga)); |
|---|
| 382 | vgabios_sz = sizeof(vgabios_stdvga); |
|---|
| 383 | } |
|---|
| 384 | |
|---|
| 385 | if ( must_load_nic() ) |
|---|
| 386 | { |
|---|
| 387 | printf("Loading ETHERBOOT ...\n"); |
|---|
| 388 | memcpy((void *)ETHERBOOT_PHYSICAL_ADDRESS, |
|---|
| 389 | etherboot, sizeof(etherboot)); |
|---|
| 390 | etherboot_sz = sizeof(etherboot); |
|---|
| 391 | } |
|---|
| 392 | |
|---|
| 393 | if ( get_acpi_enabled() ) |
|---|
| 394 | { |
|---|
| 395 | printf("Loading ACPI ...\n"); |
|---|
| 396 | acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS); |
|---|
| 397 | ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000); |
|---|
| 398 | } |
|---|
| 399 | |
|---|
| 400 | cmos_write_memory_size(); |
|---|
| 401 | |
|---|
| 402 | printf("BIOS map:\n"); |
|---|
| 403 | if ( vgabios_sz ) |
|---|
| 404 | printf(" %05x-%05x: VGA BIOS\n", |
|---|
| 405 | VGABIOS_PHYSICAL_ADDRESS, |
|---|
| 406 | VGABIOS_PHYSICAL_ADDRESS + vgabios_sz - 1); |
|---|
| 407 | if ( etherboot_sz ) |
|---|
| 408 | printf(" %05x-%05x: Etherboot ROM\n", |
|---|
| 409 | ETHERBOOT_PHYSICAL_ADDRESS, |
|---|
| 410 | ETHERBOOT_PHYSICAL_ADDRESS + etherboot_sz - 1); |
|---|
| 411 | if ( !check_amd() ) |
|---|
| 412 | printf(" %05x-%05x: VMXAssist\n", |
|---|
| 413 | VMXASSIST_PHYSICAL_ADDRESS, |
|---|
| 414 | VMXASSIST_PHYSICAL_ADDRESS + sizeof(vmxassist) - 1); |
|---|
| 415 | if ( smbios_sz ) |
|---|
| 416 | printf(" %05x-%05x: SMBIOS tables\n", |
|---|
| 417 | SMBIOS_PHYSICAL_ADDRESS, |
|---|
| 418 | SMBIOS_PHYSICAL_ADDRESS + smbios_sz - 1); |
|---|
| 419 | if ( acpi_sz ) |
|---|
| 420 | printf(" %05x-%05x: ACPI tables\n", |
|---|
| 421 | ACPI_PHYSICAL_ADDRESS, |
|---|
| 422 | ACPI_PHYSICAL_ADDRESS + acpi_sz - 1); |
|---|
| 423 | if ( rombios_sz ) |
|---|
| 424 | printf(" %05x-%05x: Main BIOS\n", |
|---|
| 425 | ROMBIOS_PHYSICAL_ADDRESS, |
|---|
| 426 | ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1); |
|---|
| 427 | |
|---|
| 428 | if ( !check_amd() ) |
|---|
| 429 | { |
|---|
| 430 | printf("Loading VMXAssist ...\n"); |
|---|
| 431 | memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS, |
|---|
| 432 | vmxassist, sizeof(vmxassist)); |
|---|
| 433 | |
|---|
| 434 | printf("VMX go ...\n"); |
|---|
| 435 | __asm__ __volatile__( |
|---|
| 436 | "jmp *%%eax" |
|---|
| 437 | : : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0) |
|---|
| 438 | ); |
|---|
| 439 | } |
|---|
| 440 | |
|---|
| 441 | printf("Invoking ROMBIOS ...\n"); |
|---|
| 442 | return 0; |
|---|
| 443 | } |
|---|
| 444 | |
|---|
| 445 | /* |
|---|
| 446 | * Local variables: |
|---|
| 447 | * mode: C |
|---|
| 448 | * c-set-style: "BSD" |
|---|
| 449 | * c-basic-offset: 4 |
|---|
| 450 | * tab-width: 4 |
|---|
| 451 | * indent-tabs-mode: nil |
|---|
| 452 | * End: |
|---|
| 453 | */ |
|---|