Jun Nakajima | 8679793 | 2011-01-29 14:24:24 -0800 | [diff] [blame] | 1 | /* |
| 2 | * QEMU PC System Emulator |
| 3 | * |
| 4 | * Copyright (c) 2003-2004 Fabrice Bellard |
| 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | * of this software and associated documentation files (the "Software"), to deal |
| 8 | * in the Software without restriction, including without limitation the rights |
| 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 10 | * copies of the Software, and to permit persons to whom the Software is |
| 11 | * furnished to do so, subject to the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice shall be included in |
| 14 | * all copies or substantial portions of the Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 22 | * THE SOFTWARE. |
| 23 | */ |
| 24 | #include "hw.h" |
| 25 | #include "pc.h" |
| 26 | #include "fdc.h" |
| 27 | #include "pci.h" |
| 28 | #include "block.h" |
| 29 | #include "sysemu.h" |
| 30 | #include "blockdev.h" |
| 31 | #include "audio/audio.h" |
| 32 | #include "net.h" |
| 33 | //#include "smbus.h" |
| 34 | #include "boards.h" |
| 35 | #include "android/globals.h" |
| 36 | #include "monitor.h" |
| 37 | #include "fw_cfg.h" |
| 38 | //#include "hpet_emul.h" |
| 39 | #include "watchdog.h" |
| 40 | #include "smbios.h" |
| 41 | #include "console.h" |
| 42 | |
| 43 | #include "goldfish_device.h" |
| 44 | |
| 45 | char* audio_input_source = NULL; |
| 46 | /* output Bochs bios info messages */ |
| 47 | //#define DEBUG_BIOS |
| 48 | |
| 49 | #define BIOS_FILENAME "bios.bin" |
| 50 | #define VGABIOS_FILENAME "vgabios.bin" |
| 51 | #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" |
| 52 | |
| 53 | #define PC_MAX_BIOS_SIZE (4 * 1024 * 1024) |
| 54 | |
| 55 | /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */ |
| 56 | #define ACPI_DATA_SIZE 0x10000 |
| 57 | #define BIOS_CFG_IOPORT 0x510 |
| 58 | #define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) |
| 59 | #define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) |
| 60 | |
| 61 | #define MAX_IDE_BUS 2 |
| 62 | #ifndef CONFIG_ANDROID |
| 63 | static fdctrl_t *floppy_controller; |
| 64 | #endif |
| 65 | static RTCState *rtc_state; |
| 66 | static PITState *pit; |
| 67 | static IOAPICState *ioapic; |
| 68 | static PCIDevice *i440fx_state; |
| 69 | |
| 70 | typedef struct rom_reset_data { |
| 71 | uint8_t *data; |
| 72 | target_phys_addr_t addr; |
| 73 | unsigned size; |
| 74 | } RomResetData; |
| 75 | |
| 76 | static void option_rom_reset(void *_rrd) |
| 77 | { |
| 78 | RomResetData *rrd = _rrd; |
| 79 | |
| 80 | cpu_physical_memory_write_rom(rrd->addr, rrd->data, rrd->size); |
| 81 | } |
| 82 | |
| 83 | static void option_rom_setup_reset(target_phys_addr_t addr, unsigned size) |
| 84 | { |
| 85 | RomResetData *rrd = qemu_malloc(sizeof *rrd); |
| 86 | |
| 87 | rrd->data = qemu_malloc(size); |
| 88 | cpu_physical_memory_read(addr, rrd->data, size); |
| 89 | rrd->addr = addr; |
| 90 | rrd->size = size; |
| 91 | qemu_register_reset(option_rom_reset, 0, rrd); |
| 92 | } |
| 93 | |
| 94 | static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) |
| 95 | { |
| 96 | } |
| 97 | |
| 98 | /* MSDOS compatibility mode FPU exception support */ |
| 99 | static qemu_irq ferr_irq; |
| 100 | /* XXX: add IGNNE support */ |
| 101 | void cpu_set_ferr(CPUX86State *s) |
| 102 | { |
| 103 | qemu_irq_raise(ferr_irq); |
| 104 | } |
| 105 | |
| 106 | static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data) |
| 107 | { |
| 108 | qemu_irq_lower(ferr_irq); |
| 109 | } |
| 110 | |
| 111 | /* TSC handling */ |
| 112 | uint64_t cpu_get_tsc(CPUX86State *env) |
| 113 | { |
| 114 | /* Note: when using kqemu, it is more logical to return the host TSC |
| 115 | because kqemu does not trap the RDTSC instruction for |
| 116 | performance reasons */ |
| 117 | #ifdef CONFIG_KQEMU |
| 118 | if (env->kqemu_enabled) { |
| 119 | return cpu_get_real_ticks(); |
| 120 | } else |
| 121 | #endif |
| 122 | { |
| 123 | return cpu_get_ticks(); |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | /* SMM support */ |
| 128 | void cpu_smm_update(CPUState *env) |
| 129 | { |
| 130 | if (i440fx_state && env == first_cpu) |
| 131 | i440fx_set_smm(i440fx_state, (env->hflags >> HF_SMM_SHIFT) & 1); |
| 132 | } |
| 133 | |
| 134 | |
| 135 | /* IRQ handling */ |
| 136 | int cpu_get_pic_interrupt(CPUState *env) |
| 137 | { |
| 138 | int intno; |
| 139 | |
| 140 | intno = apic_get_interrupt(env); |
| 141 | if (intno >= 0) { |
| 142 | /* set irq request if a PIC irq is still pending */ |
| 143 | /* XXX: improve that */ |
| 144 | pic_update_irq(isa_pic); |
| 145 | return intno; |
| 146 | } |
| 147 | /* read the irq from the PIC */ |
| 148 | if (!apic_accept_pic_intr(env)) |
| 149 | return -1; |
| 150 | |
| 151 | intno = pic_read_irq(isa_pic); |
| 152 | return intno; |
| 153 | } |
| 154 | |
| 155 | static void pic_irq_request(void *opaque, int irq, int level) |
| 156 | { |
| 157 | CPUState *env = first_cpu; |
| 158 | |
| 159 | if (env->apic_state) { |
| 160 | while (env) { |
| 161 | if (apic_accept_pic_intr(env)) |
| 162 | apic_deliver_pic_intr(env, level); |
| 163 | env = env->next_cpu; |
| 164 | } |
| 165 | } else { |
| 166 | if (level) |
| 167 | cpu_interrupt(env, CPU_INTERRUPT_HARD); |
| 168 | else |
| 169 | cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | /* PC cmos mappings */ |
| 174 | |
| 175 | #define REG_EQUIPMENT_BYTE 0x14 |
| 176 | |
| 177 | #ifndef CONFIG_ANDROID |
| 178 | static int cmos_get_fd_drive_type(int fd0) |
| 179 | { |
| 180 | int val; |
| 181 | |
| 182 | switch (fd0) { |
| 183 | case 0: |
| 184 | /* 1.44 Mb 3"5 drive */ |
| 185 | val = 4; |
| 186 | break; |
| 187 | case 1: |
| 188 | /* 2.88 Mb 3"5 drive */ |
| 189 | val = 5; |
| 190 | break; |
| 191 | case 2: |
| 192 | /* 1.2 Mb 5"5 drive */ |
| 193 | val = 2; |
| 194 | break; |
| 195 | default: |
| 196 | val = 0; |
| 197 | break; |
| 198 | } |
| 199 | return val; |
| 200 | } |
| 201 | #endif |
| 202 | |
| 203 | static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd) |
| 204 | { |
| 205 | RTCState *s = rtc_state; |
| 206 | int cylinders, heads, sectors; |
| 207 | bdrv_get_geometry_hint(hd, &cylinders, &heads, §ors); |
| 208 | rtc_set_memory(s, type_ofs, 47); |
| 209 | rtc_set_memory(s, info_ofs, cylinders); |
| 210 | rtc_set_memory(s, info_ofs + 1, cylinders >> 8); |
| 211 | rtc_set_memory(s, info_ofs + 2, heads); |
| 212 | rtc_set_memory(s, info_ofs + 3, 0xff); |
| 213 | rtc_set_memory(s, info_ofs + 4, 0xff); |
| 214 | rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3)); |
| 215 | rtc_set_memory(s, info_ofs + 6, cylinders); |
| 216 | rtc_set_memory(s, info_ofs + 7, cylinders >> 8); |
| 217 | rtc_set_memory(s, info_ofs + 8, sectors); |
| 218 | } |
| 219 | |
| 220 | /* convert boot_device letter to something recognizable by the bios */ |
| 221 | static int boot_device2nibble(char boot_device) |
| 222 | { |
| 223 | switch(boot_device) { |
| 224 | case 'a': |
| 225 | case 'b': |
| 226 | return 0x01; /* floppy boot */ |
| 227 | case 'c': |
| 228 | return 0x02; /* hard drive boot */ |
| 229 | case 'd': |
| 230 | return 0x03; /* CD-ROM boot */ |
| 231 | case 'n': |
| 232 | return 0x04; /* Network boot */ |
| 233 | } |
| 234 | return 0; |
| 235 | } |
| 236 | |
| 237 | /* copy/pasted from cmos_init, should be made a general function |
| 238 | and used there as well */ |
| 239 | static int pc_boot_set(void *opaque, const char *boot_device) |
| 240 | { |
| 241 | Monitor *mon = cur_mon; |
| 242 | #define PC_MAX_BOOT_DEVICES 3 |
| 243 | RTCState *s = (RTCState *)opaque; |
| 244 | int nbds, bds[3] = { 0, }; |
| 245 | int i; |
| 246 | |
| 247 | nbds = strlen(boot_device); |
| 248 | if (nbds > PC_MAX_BOOT_DEVICES) { |
| 249 | monitor_printf(mon, "Too many boot devices for PC\n"); |
| 250 | return(1); |
| 251 | } |
| 252 | for (i = 0; i < nbds; i++) { |
| 253 | bds[i] = boot_device2nibble(boot_device[i]); |
| 254 | if (bds[i] == 0) { |
| 255 | monitor_printf(mon, "Invalid boot device for PC: '%c'\n", |
| 256 | boot_device[i]); |
| 257 | return(1); |
| 258 | } |
| 259 | } |
| 260 | rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]); |
| 261 | rtc_set_memory(s, 0x38, (bds[2] << 4)); |
| 262 | return(0); |
| 263 | } |
| 264 | |
| 265 | /* hd_table must contain 4 block drivers */ |
| 266 | static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, |
| 267 | const char *boot_device, BlockDriverState **hd_table) |
| 268 | { |
| 269 | RTCState *s = rtc_state; |
| 270 | int nbds, bds[3] = { 0, }; |
| 271 | int val; |
| 272 | #ifndef CONFIG_ANDROID |
| 273 | int fd0, fd1, nb; |
| 274 | #endif |
| 275 | int i; |
| 276 | |
| 277 | /* various important CMOS locations needed by PC/Bochs bios */ |
| 278 | |
| 279 | /* memory size */ |
| 280 | val = 640; /* base memory in K */ |
| 281 | rtc_set_memory(s, 0x15, val); |
| 282 | rtc_set_memory(s, 0x16, val >> 8); |
| 283 | |
| 284 | val = (ram_size / 1024) - 1024; |
| 285 | if (val > 65535) |
| 286 | val = 65535; |
| 287 | rtc_set_memory(s, 0x17, val); |
| 288 | rtc_set_memory(s, 0x18, val >> 8); |
| 289 | rtc_set_memory(s, 0x30, val); |
| 290 | rtc_set_memory(s, 0x31, val >> 8); |
| 291 | |
| 292 | if (above_4g_mem_size) { |
| 293 | rtc_set_memory(s, 0x5b, (unsigned int)above_4g_mem_size >> 16); |
| 294 | rtc_set_memory(s, 0x5c, (unsigned int)above_4g_mem_size >> 24); |
| 295 | rtc_set_memory(s, 0x5d, (uint64_t)above_4g_mem_size >> 32); |
| 296 | } |
| 297 | |
| 298 | if (ram_size > (16 * 1024 * 1024)) |
| 299 | val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536); |
| 300 | else |
| 301 | val = 0; |
| 302 | if (val > 65535) |
| 303 | val = 65535; |
| 304 | rtc_set_memory(s, 0x34, val); |
| 305 | rtc_set_memory(s, 0x35, val >> 8); |
| 306 | |
| 307 | /* set the number of CPU */ |
| 308 | rtc_set_memory(s, 0x5f, smp_cpus - 1); |
| 309 | |
| 310 | /* set boot devices, and disable floppy signature check if requested */ |
| 311 | #define PC_MAX_BOOT_DEVICES 3 |
| 312 | nbds = strlen(boot_device); |
| 313 | if (nbds > PC_MAX_BOOT_DEVICES) { |
| 314 | fprintf(stderr, "Too many boot devices for PC\n"); |
| 315 | exit(1); |
| 316 | } |
| 317 | for (i = 0; i < nbds; i++) { |
| 318 | bds[i] = boot_device2nibble(boot_device[i]); |
| 319 | if (bds[i] == 0) { |
| 320 | fprintf(stderr, "Invalid boot device for PC: '%c'\n", |
| 321 | boot_device[i]); |
| 322 | exit(1); |
| 323 | } |
| 324 | } |
| 325 | rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]); |
| 326 | rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1)); |
| 327 | |
| 328 | /* floppy type */ |
| 329 | |
| 330 | #ifndef CONFIG_ANDROID |
| 331 | fd0 = fdctrl_get_drive_type(floppy_controller, 0); |
| 332 | fd1 = fdctrl_get_drive_type(floppy_controller, 1); |
| 333 | |
| 334 | val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1); |
| 335 | rtc_set_memory(s, 0x10, val); |
| 336 | |
| 337 | val = 0; |
| 338 | nb = 0; |
| 339 | if (fd0 < 3) |
| 340 | nb++; |
| 341 | if (fd1 < 3) |
| 342 | nb++; |
| 343 | switch (nb) { |
| 344 | case 0: |
| 345 | break; |
| 346 | case 1: |
| 347 | val |= 0x01; /* 1 drive, ready for boot */ |
| 348 | break; |
| 349 | case 2: |
| 350 | val |= 0x41; /* 2 drives, ready for boot */ |
| 351 | break; |
| 352 | } |
| 353 | val |= 0x02; /* FPU is there */ |
| 354 | val |= 0x04; /* PS/2 mouse installed */ |
| 355 | rtc_set_memory(s, REG_EQUIPMENT_BYTE, val); |
| 356 | #endif |
| 357 | |
| 358 | /* hard drives */ |
| 359 | |
| 360 | rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0)); |
| 361 | if (hd_table[0]) |
| 362 | cmos_init_hd(0x19, 0x1b, hd_table[0]); |
| 363 | if (hd_table[1]) |
| 364 | cmos_init_hd(0x1a, 0x24, hd_table[1]); |
| 365 | |
| 366 | val = 0; |
| 367 | for (i = 0; i < 4; i++) { |
| 368 | if (hd_table[i]) { |
| 369 | int cylinders, heads, sectors, translation; |
| 370 | /* NOTE: bdrv_get_geometry_hint() returns the physical |
| 371 | geometry. It is always such that: 1 <= sects <= 63, 1 |
| 372 | <= heads <= 16, 1 <= cylinders <= 16383. The BIOS |
| 373 | geometry can be different if a translation is done. */ |
| 374 | translation = bdrv_get_translation_hint(hd_table[i]); |
| 375 | if (translation == BIOS_ATA_TRANSLATION_AUTO) { |
| 376 | bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors); |
| 377 | if (cylinders <= 1024 && heads <= 16 && sectors <= 63) { |
| 378 | /* No translation. */ |
| 379 | translation = 0; |
| 380 | } else { |
| 381 | /* LBA translation. */ |
| 382 | translation = 1; |
| 383 | } |
| 384 | } else { |
| 385 | translation--; |
| 386 | } |
| 387 | val |= translation << (i * 2); |
| 388 | } |
| 389 | } |
| 390 | rtc_set_memory(s, 0x39, val); |
| 391 | } |
| 392 | |
| 393 | void ioport_set_a20(int enable) |
| 394 | { |
| 395 | /* XXX: send to all CPUs ? */ |
| 396 | cpu_x86_set_a20(first_cpu, enable); |
| 397 | } |
| 398 | |
| 399 | int ioport_get_a20(void) |
| 400 | { |
| 401 | return ((first_cpu->a20_mask >> 20) & 1); |
| 402 | } |
| 403 | |
| 404 | static void ioport92_write(void *opaque, uint32_t addr, uint32_t val) |
| 405 | { |
| 406 | ioport_set_a20((val >> 1) & 1); |
| 407 | /* XXX: bit 0 is fast reset */ |
| 408 | } |
| 409 | |
| 410 | static uint32_t ioport92_read(void *opaque, uint32_t addr) |
| 411 | { |
| 412 | return ioport_get_a20() << 1; |
| 413 | } |
| 414 | |
| 415 | /***********************************************************/ |
| 416 | /* Bochs BIOS debug ports */ |
| 417 | |
| 418 | static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) |
| 419 | { |
| 420 | static const char shutdown_str[8] = "Shutdown"; |
| 421 | static int shutdown_index = 0; |
| 422 | |
| 423 | switch(addr) { |
| 424 | /* Bochs BIOS messages */ |
| 425 | case 0x400: |
| 426 | case 0x401: |
| 427 | fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val); |
| 428 | exit(1); |
| 429 | case 0x402: |
| 430 | case 0x403: |
| 431 | #ifdef DEBUG_BIOS |
| 432 | fprintf(stderr, "%c", val); |
| 433 | #endif |
| 434 | break; |
| 435 | case 0x8900: |
| 436 | /* same as Bochs power off */ |
| 437 | if (val == shutdown_str[shutdown_index]) { |
| 438 | shutdown_index++; |
| 439 | if (shutdown_index == 8) { |
| 440 | shutdown_index = 0; |
| 441 | qemu_system_shutdown_request(); |
| 442 | } |
| 443 | } else { |
| 444 | shutdown_index = 0; |
| 445 | } |
| 446 | break; |
| 447 | |
| 448 | /* LGPL'ed VGA BIOS messages */ |
| 449 | case 0x501: |
| 450 | case 0x502: |
| 451 | fprintf(stderr, "VGA BIOS panic, line %d\n", val); |
| 452 | exit(1); |
| 453 | case 0x500: |
| 454 | case 0x503: |
| 455 | #ifdef DEBUG_BIOS |
| 456 | fprintf(stderr, "%c", val); |
| 457 | #endif |
| 458 | break; |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | extern uint64_t node_cpumask[MAX_NODES]; |
| 463 | |
| 464 | static void bochs_bios_init(void) |
| 465 | { |
| 466 | void *fw_cfg; |
| 467 | uint8_t *smbios_table; |
| 468 | size_t smbios_len; |
| 469 | uint64_t *numa_fw_cfg; |
| 470 | int i, j; |
| 471 | |
| 472 | register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL); |
| 473 | register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL); |
| 474 | register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL); |
| 475 | register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL); |
| 476 | register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL); |
| 477 | |
| 478 | register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL); |
| 479 | register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL); |
| 480 | register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL); |
| 481 | register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); |
| 482 | |
| 483 | fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); |
| 484 | fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); |
| 485 | fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); |
| 486 | #ifndef CONFIG_ANDROID |
| 487 | fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables, |
| 488 | acpi_tables_len); |
| 489 | #endif |
| 490 | smbios_table = smbios_get_table(&smbios_len); |
| 491 | if (smbios_table) |
| 492 | fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, |
| 493 | smbios_table, smbios_len); |
| 494 | |
| 495 | /* allocate memory for the NUMA channel: one (64bit) word for the number |
| 496 | * of nodes, one word for each VCPU->node and one word for each node to |
| 497 | * hold the amount of memory. |
| 498 | */ |
| 499 | numa_fw_cfg = qemu_mallocz((1 + smp_cpus + nb_numa_nodes) * 8); |
| 500 | numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); |
| 501 | for (i = 0; i < smp_cpus; i++) { |
| 502 | for (j = 0; j < nb_numa_nodes; j++) { |
| 503 | if (node_cpumask[j] & (1 << i)) { |
| 504 | numa_fw_cfg[i + 1] = cpu_to_le64(j); |
| 505 | break; |
| 506 | } |
| 507 | } |
| 508 | } |
| 509 | for (i = 0; i < nb_numa_nodes; i++) { |
| 510 | numa_fw_cfg[smp_cpus + 1 + i] = cpu_to_le64(node_mem[i]); |
| 511 | } |
| 512 | fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, (uint8_t *)numa_fw_cfg, |
| 513 | (1 + smp_cpus + nb_numa_nodes) * 8); |
| 514 | } |
| 515 | |
| 516 | /* Generate an initial boot sector which sets state and jump to |
| 517 | a specified vector */ |
| 518 | static void generate_bootsect(target_phys_addr_t option_rom, |
| 519 | uint32_t gpr[8], uint16_t segs[6], uint16_t ip) |
| 520 | { |
| 521 | uint8_t rom[512], *p, *reloc; |
| 522 | uint8_t sum; |
| 523 | int i; |
| 524 | |
| 525 | memset(rom, 0, sizeof(rom)); |
| 526 | |
| 527 | p = rom; |
| 528 | /* Make sure we have an option rom signature */ |
| 529 | *p++ = 0x55; |
| 530 | *p++ = 0xaa; |
| 531 | |
| 532 | /* ROM size in sectors*/ |
| 533 | *p++ = 1; |
| 534 | |
| 535 | /* Hook int19 */ |
| 536 | |
| 537 | *p++ = 0x50; /* push ax */ |
| 538 | *p++ = 0x1e; /* push ds */ |
| 539 | *p++ = 0x31; *p++ = 0xc0; /* xor ax, ax */ |
| 540 | *p++ = 0x8e; *p++ = 0xd8; /* mov ax, ds */ |
| 541 | |
| 542 | *p++ = 0xc7; *p++ = 0x06; /* movvw _start,0x64 */ |
| 543 | *p++ = 0x64; *p++ = 0x00; |
| 544 | reloc = p; |
| 545 | *p++ = 0x00; *p++ = 0x00; |
| 546 | |
| 547 | *p++ = 0x8c; *p++ = 0x0e; /* mov cs,0x66 */ |
| 548 | *p++ = 0x66; *p++ = 0x00; |
| 549 | |
| 550 | *p++ = 0x1f; /* pop ds */ |
| 551 | *p++ = 0x58; /* pop ax */ |
| 552 | *p++ = 0xcb; /* lret */ |
| 553 | |
| 554 | /* Actual code */ |
| 555 | *reloc = (p - rom); |
| 556 | |
| 557 | *p++ = 0xfa; /* CLI */ |
| 558 | *p++ = 0xfc; /* CLD */ |
| 559 | |
| 560 | for (i = 0; i < 6; i++) { |
| 561 | if (i == 1) /* Skip CS */ |
| 562 | continue; |
| 563 | |
| 564 | *p++ = 0xb8; /* MOV AX,imm16 */ |
| 565 | *p++ = segs[i]; |
| 566 | *p++ = segs[i] >> 8; |
| 567 | *p++ = 0x8e; /* MOV <seg>,AX */ |
| 568 | *p++ = 0xc0 + (i << 3); |
| 569 | } |
| 570 | |
| 571 | for (i = 0; i < 8; i++) { |
| 572 | *p++ = 0x66; /* 32-bit operand size */ |
| 573 | *p++ = 0xb8 + i; /* MOV <reg>,imm32 */ |
| 574 | *p++ = gpr[i]; |
| 575 | *p++ = gpr[i] >> 8; |
| 576 | *p++ = gpr[i] >> 16; |
| 577 | *p++ = gpr[i] >> 24; |
| 578 | } |
| 579 | |
| 580 | *p++ = 0xea; /* JMP FAR */ |
| 581 | *p++ = ip; /* IP */ |
| 582 | *p++ = ip >> 8; |
| 583 | *p++ = segs[1]; /* CS */ |
| 584 | *p++ = segs[1] >> 8; |
| 585 | |
| 586 | /* sign rom */ |
| 587 | sum = 0; |
| 588 | for (i = 0; i < (sizeof(rom) - 1); i++) |
| 589 | sum += rom[i]; |
| 590 | rom[sizeof(rom) - 1] = -sum; |
| 591 | |
| 592 | cpu_physical_memory_write_rom(option_rom, rom, sizeof(rom)); |
| 593 | option_rom_setup_reset(option_rom, sizeof (rom)); |
| 594 | } |
| 595 | |
| 596 | static long get_file_size(FILE *f) |
| 597 | { |
| 598 | long where, size; |
| 599 | |
| 600 | /* XXX: on Unix systems, using fstat() probably makes more sense */ |
| 601 | |
| 602 | where = ftell(f); |
| 603 | fseek(f, 0, SEEK_END); |
| 604 | size = ftell(f); |
| 605 | fseek(f, where, SEEK_SET); |
| 606 | |
| 607 | return size; |
| 608 | } |
| 609 | |
| 610 | static void load_linux(target_phys_addr_t option_rom, |
| 611 | const char *kernel_filename, |
| 612 | const char *initrd_filename, |
| 613 | const char *kernel_cmdline, |
| 614 | target_phys_addr_t max_ram_size) |
| 615 | { |
| 616 | uint16_t protocol; |
| 617 | uint32_t gpr[8]; |
| 618 | uint16_t seg[6]; |
| 619 | uint16_t real_seg; |
| 620 | int setup_size, kernel_size, initrd_size = 0, cmdline_size; |
| 621 | uint32_t initrd_max; |
| 622 | uint8_t header[1024]; |
| 623 | target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr = 0; |
| 624 | FILE *f, *fi; |
| 625 | |
| 626 | /* Align to 16 bytes as a paranoia measure */ |
| 627 | cmdline_size = (strlen(kernel_cmdline)+16) & ~15; |
| 628 | |
| 629 | /* load the kernel header */ |
| 630 | f = fopen(kernel_filename, "rb"); |
| 631 | if (!f || !(kernel_size = get_file_size(f)) || |
| 632 | fread(header, 1, 1024, f) != 1024) { |
| 633 | fprintf(stderr, "qemu: could not load kernel '%s'\n", |
| 634 | kernel_filename); |
| 635 | exit(1); |
| 636 | } |
| 637 | |
| 638 | /* kernel protocol version */ |
| 639 | #if 0 |
| 640 | fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202)); |
| 641 | #endif |
| 642 | if (ldl_p(header+0x202) == 0x53726448) |
| 643 | protocol = lduw_p(header+0x206); |
| 644 | else |
| 645 | protocol = 0; |
| 646 | |
| 647 | if (protocol < 0x200 || !(header[0x211] & 0x01)) { |
| 648 | /* Low kernel */ |
| 649 | real_addr = 0x90000; |
| 650 | cmdline_addr = 0x9a000 - cmdline_size; |
| 651 | prot_addr = 0x10000; |
| 652 | } else if (protocol < 0x202) { |
| 653 | /* High but ancient kernel */ |
| 654 | real_addr = 0x90000; |
| 655 | cmdline_addr = 0x9a000 - cmdline_size; |
| 656 | prot_addr = 0x100000; |
| 657 | } else { |
| 658 | /* High and recent kernel */ |
| 659 | real_addr = 0x10000; |
| 660 | cmdline_addr = 0x20000; |
| 661 | prot_addr = 0x100000; |
| 662 | } |
| 663 | |
| 664 | #if 0 |
| 665 | fprintf(stderr, |
| 666 | "qemu: real_addr = 0x" TARGET_FMT_plx "\n" |
| 667 | "qemu: cmdline_addr = 0x" TARGET_FMT_plx "\n" |
| 668 | "qemu: prot_addr = 0x" TARGET_FMT_plx "\n", |
| 669 | real_addr, |
| 670 | cmdline_addr, |
| 671 | prot_addr); |
| 672 | #endif |
| 673 | |
| 674 | /* highest address for loading the initrd */ |
| 675 | if (protocol >= 0x203) |
| 676 | initrd_max = ldl_p(header+0x22c); |
| 677 | else |
| 678 | initrd_max = 0x37ffffff; |
| 679 | |
| 680 | if (initrd_max >= max_ram_size-ACPI_DATA_SIZE) |
| 681 | initrd_max = max_ram_size-ACPI_DATA_SIZE-1; |
| 682 | |
| 683 | /* kernel command line */ |
| 684 | pstrcpy_targphys(cmdline_addr, 4096, kernel_cmdline); |
| 685 | |
| 686 | if (protocol >= 0x202) { |
| 687 | stl_p(header+0x228, cmdline_addr); |
| 688 | } else { |
| 689 | stw_p(header+0x20, 0xA33F); |
| 690 | stw_p(header+0x22, cmdline_addr-real_addr); |
| 691 | } |
| 692 | |
| 693 | /* loader type */ |
| 694 | /* High nybble = B reserved for Qemu; low nybble is revision number. |
| 695 | If this code is substantially changed, you may want to consider |
| 696 | incrementing the revision. */ |
| 697 | if (protocol >= 0x200) |
| 698 | header[0x210] = 0xB0; |
| 699 | |
| 700 | /* heap */ |
| 701 | if (protocol >= 0x201) { |
| 702 | header[0x211] |= 0x80; /* CAN_USE_HEAP */ |
| 703 | stw_p(header+0x224, cmdline_addr-real_addr-0x200); |
| 704 | } |
| 705 | |
| 706 | /* load initrd */ |
| 707 | if (initrd_filename) { |
| 708 | if (protocol < 0x200) { |
| 709 | fprintf(stderr, "qemu: linux kernel too old to load a ram disk %s, %s, %s\n", |
| 710 | kernel_filename, initrd_filename, kernel_cmdline); |
| 711 | exit(1); |
| 712 | } |
| 713 | |
| 714 | fi = fopen(initrd_filename, "rb"); |
| 715 | if (!fi) { |
| 716 | fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", |
| 717 | initrd_filename); |
| 718 | exit(1); |
| 719 | } |
| 720 | |
| 721 | initrd_size = get_file_size(fi); |
| 722 | initrd_addr = (initrd_max-initrd_size) & ~4095; |
| 723 | |
| 724 | if (!fread_targphys_ok(initrd_addr, initrd_size, fi)) { |
| 725 | fprintf(stderr, "qemu: read error on initial ram disk '%s'\n", |
| 726 | initrd_filename); |
| 727 | exit(1); |
| 728 | } |
| 729 | fclose(fi); |
| 730 | |
| 731 | stl_p(header+0x218, initrd_addr); |
| 732 | stl_p(header+0x21c, initrd_size); |
| 733 | } |
| 734 | |
| 735 | /* store the finalized header and load the rest of the kernel */ |
| 736 | cpu_physical_memory_write(real_addr, header, 1024); |
| 737 | |
| 738 | setup_size = header[0x1f1]; |
| 739 | if (setup_size == 0) |
| 740 | setup_size = 4; |
| 741 | |
| 742 | setup_size = (setup_size+1)*512; |
| 743 | kernel_size -= setup_size; /* Size of protected-mode code */ |
| 744 | |
| 745 | if (!fread_targphys_ok(real_addr+1024, setup_size-1024, f) || |
| 746 | !fread_targphys_ok(prot_addr, kernel_size, f)) { |
| 747 | fprintf(stderr, "qemu: read error on kernel '%s'\n", |
| 748 | kernel_filename); |
| 749 | exit(1); |
| 750 | } |
| 751 | fclose(f); |
| 752 | |
| 753 | /* generate bootsector to set up the initial register state */ |
| 754 | real_seg = real_addr >> 4; |
| 755 | seg[0] = seg[2] = seg[3] = seg[4] = seg[4] = real_seg; |
| 756 | seg[1] = real_seg+0x20; /* CS */ |
| 757 | memset(gpr, 0, sizeof gpr); |
| 758 | gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */ |
| 759 | |
| 760 | option_rom_setup_reset(real_addr, setup_size); |
| 761 | option_rom_setup_reset(prot_addr, kernel_size); |
| 762 | option_rom_setup_reset(cmdline_addr, cmdline_size); |
| 763 | if (initrd_filename) |
| 764 | option_rom_setup_reset(initrd_addr, initrd_size); |
| 765 | |
| 766 | generate_bootsect(option_rom, gpr, seg, 0); |
| 767 | } |
| 768 | |
| 769 | static void main_cpu_reset(void *opaque) |
| 770 | { |
| 771 | CPUState *env = opaque; |
| 772 | cpu_reset(env); |
| 773 | } |
| 774 | |
| 775 | static const int ide_iobase[2] = { 0x1f0, 0x170 }; |
| 776 | static const int ide_iobase2[2] = { 0x3f6, 0x376 }; |
| 777 | static const int ide_irq[2] = { 14, 15 }; |
| 778 | |
| 779 | #define NE2000_NB_MAX 6 |
| 780 | |
| 781 | static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; |
| 782 | static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; |
| 783 | |
| 784 | /* static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; |
| 785 | static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 }; |
| 786 | |
| 787 | static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; |
| 788 | static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; */ |
| 789 | |
| 790 | #ifdef HAS_AUDIO |
Jun Nakajima | 6f19836 | 2011-02-24 13:16:01 -0800 | [diff] [blame] | 791 | #ifndef CONFIG_ANDROID |
Jun Nakajima | 8679793 | 2011-01-29 14:24:24 -0800 | [diff] [blame] | 792 | static void audio_init (PCIBus *pci_bus, qemu_irq *pic) |
| 793 | { |
| 794 | struct soundhw *c; |
| 795 | |
| 796 | for (c = soundhw; c->name; ++c) { |
| 797 | if (c->enabled) { |
| 798 | if (c->isa) { |
| 799 | c->init.init_isa(pic); |
| 800 | } else { |
| 801 | if (pci_bus) { |
| 802 | c->init.init_pci(pci_bus); |
| 803 | } |
| 804 | } |
| 805 | } |
| 806 | } |
| 807 | } |
| 808 | #endif |
Jun Nakajima | 6f19836 | 2011-02-24 13:16:01 -0800 | [diff] [blame] | 809 | #endif |
Jun Nakajima | 8679793 | 2011-01-29 14:24:24 -0800 | [diff] [blame] | 810 | |
| 811 | static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic) |
| 812 | { |
| 813 | static int nb_ne2k = 0; |
| 814 | |
| 815 | if (nb_ne2k == NE2000_NB_MAX) |
| 816 | return; |
| 817 | isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd); |
| 818 | nb_ne2k++; |
| 819 | } |
| 820 | |
| 821 | static int load_option_rom(const char *oprom, target_phys_addr_t start, |
| 822 | target_phys_addr_t end) |
| 823 | { |
| 824 | int size; |
| 825 | char *filename; |
| 826 | |
| 827 | filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, oprom); |
| 828 | if (filename) { |
| 829 | size = get_image_size(filename); |
| 830 | if (size > 0 && start + size > end) { |
| 831 | fprintf(stderr, "Not enough space to load option rom '%s'\n", |
| 832 | oprom); |
| 833 | exit(1); |
| 834 | } |
| 835 | size = load_image_targphys(filename, start, end - start); |
| 836 | qemu_free(filename); |
| 837 | } else { |
| 838 | size = -1; |
| 839 | } |
| 840 | if (size < 0) { |
| 841 | fprintf(stderr, "Could not load option rom '%s'\n", oprom); |
| 842 | exit(1); |
| 843 | } |
| 844 | /* Round up optiom rom size to the next 2k boundary */ |
| 845 | size = (size + 2047) & ~2047; |
| 846 | option_rom_setup_reset(start, size); |
| 847 | return size; |
| 848 | } |
| 849 | |
| 850 | int cpu_is_bsp(CPUState *env) |
| 851 | { |
| 852 | return env->cpuid_apic_id == 0; |
| 853 | } |
| 854 | |
| 855 | static struct goldfish_device event0_device = { |
| 856 | .name = "goldfish_events", |
| 857 | .id = 0, |
| 858 | .size = 0x1000, |
| 859 | .irq_count = 1 |
| 860 | }; |
| 861 | |
| 862 | static struct goldfish_device nand_device = { |
| 863 | .name = "goldfish_nand", |
| 864 | .id = 0, |
| 865 | .size = 0x1000 |
| 866 | }; |
| 867 | |
| 868 | void goldfish_memlog_init(uint32_t base); |
| 869 | |
| 870 | /* PC hardware initialisation */ |
| 871 | static void pc_init1(ram_addr_t ram_size, |
| 872 | const char *boot_device, |
| 873 | const char *kernel_filename, const char *kernel_cmdline, |
| 874 | const char *initrd_filename, |
| 875 | int pci_enabled, const char *cpu_model) |
| 876 | { |
| 877 | char *filename; |
| 878 | int ret, linux_boot, i; |
| 879 | ram_addr_t ram_addr, bios_offset, option_rom_offset; |
| 880 | ram_addr_t below_4g_mem_size, above_4g_mem_size = 0; |
| 881 | int bios_size, isa_bios_size, oprom_area_size; |
| 882 | PCIBus *pci_bus; |
| 883 | int piix3_devfn = -1; |
| 884 | CPUState *env; |
| 885 | qemu_irq *cpu_irq; |
| 886 | qemu_irq *i8259; |
| 887 | #ifndef CONFIG_ANDROID |
| 888 | int index; |
| 889 | #endif |
| 890 | BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
| 891 | #ifndef CONFIG_ANDROID |
| 892 | BlockDriverState *fd[MAX_FD]; |
| 893 | #endif |
| 894 | int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled; |
| 895 | |
| 896 | if (ram_size >= 0xe0000000 ) { |
| 897 | above_4g_mem_size = ram_size - 0xe0000000; |
| 898 | below_4g_mem_size = 0xe0000000; |
| 899 | } else { |
| 900 | below_4g_mem_size = ram_size; |
| 901 | } |
| 902 | |
| 903 | linux_boot = (kernel_filename != NULL); |
| 904 | |
| 905 | /* init CPUs */ |
| 906 | if (cpu_model == NULL) { |
| 907 | #ifdef TARGET_X86_64 |
| 908 | cpu_model = "qemu64"; |
| 909 | #else |
| 910 | cpu_model = "qemu32"; |
| 911 | #endif |
| 912 | } |
| 913 | |
| 914 | for(i = 0; i < smp_cpus; i++) { |
| 915 | env = cpu_init(cpu_model); |
| 916 | if (!env) { |
| 917 | fprintf(stderr, "Unable to find x86 CPU definition\n"); |
| 918 | exit(1); |
| 919 | } |
| 920 | if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { |
| 921 | env->cpuid_apic_id = env->cpu_index; |
| 922 | apic_init(env); |
| 923 | } |
| 924 | qemu_register_reset(main_cpu_reset, 0, env); |
| 925 | } |
| 926 | #ifndef CONFIG_ANDROID |
| 927 | vmport_init(); |
Jun Nakajima | bac9add | 2011-02-08 22:10:52 -0800 | [diff] [blame] | 928 | |
Jun Nakajima | 8679793 | 2011-01-29 14:24:24 -0800 | [diff] [blame] | 929 | /* allocate RAM */ |
| 930 | ram_addr = qemu_ram_alloc(0xa0000); |
| 931 | cpu_register_physical_memory(0, 0xa0000, ram_addr); |
| 932 | |
| 933 | /* Allocate, even though we won't register, so we don't break the |
| 934 | * phys_ram_base + PA assumption. This range includes vga (0xa0000 - 0xc0000), |
| 935 | * and some bios areas, which will be registered later |
| 936 | */ |
| 937 | ram_addr = qemu_ram_alloc(0x100000 - 0xa0000); |
| 938 | ram_addr = qemu_ram_alloc(below_4g_mem_size - 0x100000); |
| 939 | cpu_register_physical_memory(0x100000, |
| 940 | below_4g_mem_size - 0x100000, |
| 941 | ram_addr); |
Jun Nakajima | bac9add | 2011-02-08 22:10:52 -0800 | [diff] [blame] | 942 | #else |
| 943 | /* |
| 944 | * Allocate a single contiguous RAM so that the goldfish |
| 945 | * framebuffer can work well especially when the frame buffer is |
| 946 | * large. |
| 947 | */ |
| 948 | ram_addr = qemu_ram_alloc(below_4g_mem_size); |
| 949 | cpu_register_physical_memory(0, below_4g_mem_size, ram_addr); |
| 950 | #endif |
Jun Nakajima | 8679793 | 2011-01-29 14:24:24 -0800 | [diff] [blame] | 951 | |
| 952 | /* above 4giga memory allocation */ |
| 953 | if (above_4g_mem_size > 0) { |
| 954 | #if TARGET_PHYS_ADDR_BITS == 32 |
| 955 | hw_error("To much RAM for 32-bit physical address"); |
| 956 | #else |
| 957 | ram_addr = qemu_ram_alloc(above_4g_mem_size); |
| 958 | cpu_register_physical_memory(0x100000000ULL, |
| 959 | above_4g_mem_size, |
| 960 | ram_addr); |
| 961 | #endif |
| 962 | } |
| 963 | |
| 964 | |
| 965 | /* BIOS load */ |
| 966 | if (bios_name == NULL) |
| 967 | bios_name = BIOS_FILENAME; |
| 968 | filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); |
| 969 | if (filename) { |
| 970 | bios_size = get_image_size(filename); |
| 971 | } else { |
| 972 | bios_size = -1; |
| 973 | } |
| 974 | if (bios_size <= 0 || |
| 975 | (bios_size % 65536) != 0) { |
| 976 | goto bios_error; |
| 977 | } |
| 978 | bios_offset = qemu_ram_alloc(bios_size); |
| 979 | ret = load_image(filename, qemu_get_ram_ptr(bios_offset)); |
| 980 | if (ret != bios_size) { |
| 981 | bios_error: |
| 982 | fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); |
| 983 | exit(1); |
| 984 | } |
| 985 | if (filename) { |
| 986 | qemu_free(filename); |
| 987 | } |
| 988 | /* map the last 128KB of the BIOS in ISA space */ |
| 989 | isa_bios_size = bios_size; |
| 990 | if (isa_bios_size > (128 * 1024)) |
| 991 | isa_bios_size = 128 * 1024; |
| 992 | cpu_register_physical_memory(0x100000 - isa_bios_size, |
| 993 | isa_bios_size, |
| 994 | (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); |
| 995 | |
| 996 | |
| 997 | |
| 998 | option_rom_offset = qemu_ram_alloc(0x20000); |
| 999 | oprom_area_size = 0; |
| 1000 | cpu_register_physical_memory(0xc0000, 0x20000, option_rom_offset); |
| 1001 | |
| 1002 | if (using_vga) { |
| 1003 | const char *vgabios_filename; |
| 1004 | /* VGA BIOS load */ |
| 1005 | if (cirrus_vga_enabled) { |
| 1006 | vgabios_filename = VGABIOS_CIRRUS_FILENAME; |
| 1007 | } else { |
| 1008 | vgabios_filename = VGABIOS_FILENAME; |
| 1009 | } |
| 1010 | oprom_area_size = load_option_rom(vgabios_filename, 0xc0000, 0xe0000); |
| 1011 | } |
| 1012 | /* Although video roms can grow larger than 0x8000, the area between |
| 1013 | * 0xc0000 - 0xc8000 is reserved for them. It means we won't be looking |
| 1014 | * for any other kind of option rom inside this area */ |
| 1015 | if (oprom_area_size < 0x8000) |
| 1016 | oprom_area_size = 0x8000; |
| 1017 | |
| 1018 | if (linux_boot) { |
| 1019 | load_linux(0xc0000 + oprom_area_size, |
| 1020 | kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size); |
| 1021 | oprom_area_size += 2048; |
| 1022 | } |
| 1023 | |
| 1024 | for (i = 0; i < nb_option_roms; i++) { |
| 1025 | oprom_area_size += load_option_rom(option_rom[i], |
| 1026 | 0xc0000 + oprom_area_size, 0xe0000); |
| 1027 | } |
| 1028 | |
| 1029 | /* map all the bios at the top of memory */ |
| 1030 | cpu_register_physical_memory((uint32_t)(-bios_size), |
| 1031 | bios_size, bios_offset | IO_MEM_ROM); |
| 1032 | |
| 1033 | bochs_bios_init(); |
| 1034 | |
| 1035 | cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1); |
| 1036 | i8259 = i8259_init(cpu_irq[0]); |
| 1037 | ferr_irq = i8259[13]; |
| 1038 | |
| 1039 | #define IRQ_PDEV_BUS 4 |
| 1040 | goldfish_device_init(i8259, 0xff010000, 0x7f0000, 5, 5); |
| 1041 | goldfish_device_bus_init(0xff001000, IRQ_PDEV_BUS); |
| 1042 | |
| 1043 | if (android_hw->hw_battery) |
| 1044 | goldfish_battery_init(); |
| 1045 | |
| 1046 | goldfish_memlog_init(0); |
| 1047 | |
| 1048 | #ifdef CONFIG_NAND |
| 1049 | goldfish_add_device_no_io(&nand_device); |
| 1050 | nand_dev_init(nand_device.base); |
| 1051 | #endif |
| 1052 | |
| 1053 | { |
| 1054 | DriveInfo* info = drive_get( IF_IDE, 0, 0 ); |
| 1055 | if (info != NULL) { |
| 1056 | goldfish_mmc_init(0xff005000, 0, info->bdrv); |
| 1057 | } |
| 1058 | } |
| 1059 | |
| 1060 | if (pci_enabled) { |
| 1061 | pci_bus = i440fx_init(&i440fx_state, i8259); |
| 1062 | piix3_devfn = piix3_init(pci_bus, -1); |
| 1063 | } else { |
| 1064 | pci_bus = NULL; |
| 1065 | } |
| 1066 | |
| 1067 | /* init basic PC hardware */ |
| 1068 | register_ioport_write(0x80, 1, 1, ioport80_write, NULL); |
| 1069 | |
| 1070 | register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL); |
| 1071 | |
| 1072 | #ifndef CONFIG_ANDROID |
| 1073 | if (cirrus_vga_enabled) { |
| 1074 | if (pci_enabled) { |
| 1075 | pci_cirrus_vga_init(pci_bus); |
| 1076 | } else { |
| 1077 | isa_cirrus_vga_init(); |
| 1078 | } |
| 1079 | } else if (vmsvga_enabled) { |
| 1080 | if (pci_enabled) |
| 1081 | pci_vmsvga_init(pci_bus); |
| 1082 | else |
| 1083 | fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__); |
| 1084 | } else if (std_vga_enabled) { |
| 1085 | if (pci_enabled) { |
| 1086 | pci_vga_init(pci_bus, 0, 0); |
| 1087 | } else { |
| 1088 | isa_vga_init(); |
| 1089 | } |
| 1090 | } |
| 1091 | #endif |
| 1092 | |
| 1093 | rtc_state = rtc_init(0x70, i8259[8], 2000); |
| 1094 | |
| 1095 | qemu_register_boot_set(pc_boot_set, rtc_state); |
| 1096 | |
| 1097 | register_ioport_read(0x92, 1, 1, ioport92_read, NULL); |
| 1098 | register_ioport_write(0x92, 1, 1, ioport92_write, NULL); |
| 1099 | |
| 1100 | if (pci_enabled) { |
| 1101 | ioapic = ioapic_init(); |
| 1102 | } |
| 1103 | pit = pit_init(0x40, i8259[0]); |
| 1104 | |
| 1105 | #ifndef CONFIG_ANDROID |
| 1106 | pcspk_init(pit); |
| 1107 | |
| 1108 | if (!no_hpet) { |
| 1109 | hpet_init(i8259); |
| 1110 | } |
| 1111 | #endif |
| 1112 | |
| 1113 | if (pci_enabled) { |
| 1114 | pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic); |
| 1115 | } |
| 1116 | |
| 1117 | goldfish_tty_add(serial_hds[0], 0, 0, 0); |
| 1118 | for(i = 1; i < MAX_SERIAL_PORTS; i++) { |
| 1119 | if(serial_hds[i]) { |
| 1120 | goldfish_tty_add(serial_hds[i], i, 0, 0); |
| 1121 | } |
| 1122 | } |
| 1123 | |
| 1124 | #ifndef CONFIG_ANDROID |
| 1125 | for(i = 0; i < MAX_SERIAL_PORTS; i++) { |
| 1126 | if (serial_hds[i]) { |
| 1127 | serial_init(serial_io[i], i8259[serial_irq[i]], 115200, |
| 1128 | serial_hds[i]); |
| 1129 | } |
| 1130 | } |
| 1131 | |
| 1132 | for(i = 0; i < MAX_PARALLEL_PORTS; i++) { |
| 1133 | if (parallel_hds[i]) { |
| 1134 | parallel_init(parallel_io[i], i8259[parallel_irq[i]], |
| 1135 | parallel_hds[i]); |
| 1136 | } |
| 1137 | } |
| 1138 | #endif |
| 1139 | |
| 1140 | watchdog_pc_init(pci_bus); |
| 1141 | |
| 1142 | for(i = 0; i < nb_nics; i++) { |
| 1143 | NICInfo *nd = &nd_table[i]; |
| 1144 | |
| 1145 | if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) |
| 1146 | pc_init_ne2k_isa(nd, i8259); |
| 1147 | else |
| 1148 | pci_nic_init(pci_bus, nd, -1, "ne2k_pci"); |
| 1149 | } |
| 1150 | |
| 1151 | #ifdef CONFIG_ANDROID |
| 1152 | for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) |
| 1153 | hd[i] = NULL; |
| 1154 | #else |
| 1155 | qemu_system_hot_add_init(); |
| 1156 | |
| 1157 | if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { |
| 1158 | fprintf(stderr, "qemu: too many IDE bus\n"); |
| 1159 | exit(1); |
| 1160 | } |
| 1161 | |
| 1162 | for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) { |
| 1163 | index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); |
| 1164 | if (index != -1) |
| 1165 | hd[i] = drives_table[index].bdrv; |
| 1166 | else |
| 1167 | hd[i] = NULL; |
| 1168 | } |
| 1169 | |
| 1170 | if (pci_enabled) { |
| 1171 | pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259); |
| 1172 | } else { |
| 1173 | for(i = 0; i < MAX_IDE_BUS; i++) { |
| 1174 | isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]], |
| 1175 | hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); |
| 1176 | } |
| 1177 | } |
| 1178 | #endif |
| 1179 | |
| 1180 | i8042_init(i8259[1], i8259[12], 0x60); |
| 1181 | DMA_init(0); |
| 1182 | |
| 1183 | goldfish_fb_init(0); |
| 1184 | |
| 1185 | goldfish_add_device_no_io(&event0_device); |
| 1186 | events_dev_init(event0_device.base, i8259[event0_device.irq]); |
| 1187 | |
| 1188 | #ifdef HAS_AUDIO |
Jun Nakajima | 6f19836 | 2011-02-24 13:16:01 -0800 | [diff] [blame] | 1189 | #ifndef CONFIG_ANDROID |
Jun Nakajima | 8679793 | 2011-01-29 14:24:24 -0800 | [diff] [blame] | 1190 | audio_init(pci_enabled ? pci_bus : NULL, i8259); |
Jun Nakajima | 6f19836 | 2011-02-24 13:16:01 -0800 | [diff] [blame] | 1191 | #else |
| 1192 | goldfish_audio_init(0xff004000, 0, audio_input_source); |
| 1193 | #endif |
Jun Nakajima | 8679793 | 2011-01-29 14:24:24 -0800 | [diff] [blame] | 1194 | #endif |
| 1195 | |
| 1196 | #ifndef CONFIG_ANDROID |
| 1197 | for(i = 0; i < MAX_FD; i++) { |
| 1198 | index = drive_get_index(IF_FLOPPY, 0, i); |
| 1199 | if (index != -1) |
| 1200 | fd[i] = drives_table[index].bdrv; |
| 1201 | else |
| 1202 | fd[i] = NULL; |
| 1203 | } |
| 1204 | |
| 1205 | floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd); |
| 1206 | #endif |
| 1207 | |
| 1208 | cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd); |
| 1209 | |
| 1210 | #ifndef CONFIG_ANDROID |
| 1211 | if (pci_enabled && usb_enabled) { |
| 1212 | usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); |
| 1213 | } |
| 1214 | |
| 1215 | if (pci_enabled && acpi_enabled) { |
| 1216 | uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */ |
| 1217 | i2c_bus *smbus; |
| 1218 | |
| 1219 | /* TODO: Populate SPD eeprom data. */ |
| 1220 | smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[9]); |
| 1221 | for (i = 0; i < 8; i++) { |
| 1222 | DeviceState *eeprom; |
| 1223 | eeprom = qdev_create((BusState *)smbus, "smbus-eeprom"); |
| 1224 | qdev_set_prop_int(eeprom, "address", 0x50 + i); |
| 1225 | qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256)); |
| 1226 | qdev_init(eeprom); |
| 1227 | } |
| 1228 | } |
| 1229 | #endif |
| 1230 | |
| 1231 | if (i440fx_state) { |
| 1232 | i440fx_init_memory_mappings(i440fx_state); |
| 1233 | } |
| 1234 | |
| 1235 | if (pci_enabled) { |
| 1236 | int max_bus; |
| 1237 | int bus; |
| 1238 | |
| 1239 | max_bus = drive_get_max_bus(IF_SCSI); |
| 1240 | for (bus = 0; bus <= max_bus; bus++) { |
| 1241 | pci_create_simple(pci_bus, -1, "lsi53c895a"); |
| 1242 | } |
| 1243 | } |
| 1244 | #ifndef CONFIG_ANDROID |
| 1245 | /* Add virtio block devices */ |
| 1246 | if (pci_enabled) { |
| 1247 | int index; |
| 1248 | int unit_id = 0; |
| 1249 | |
| 1250 | while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { |
| 1251 | pci_create_simple(pci_bus, -1, "virtio-blk-pci"); |
| 1252 | unit_id++; |
| 1253 | } |
| 1254 | } |
| 1255 | |
| 1256 | /* Add virtio balloon device */ |
| 1257 | if (pci_enabled && !no_virtio_balloon) { |
| 1258 | pci_create_simple(pci_bus, -1, "virtio-balloon-pci"); |
| 1259 | } |
| 1260 | |
| 1261 | /* Add virtio console devices */ |
| 1262 | if (pci_enabled) { |
| 1263 | for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { |
| 1264 | if (virtcon_hds[i]) { |
| 1265 | pci_create_simple(pci_bus, -1, "virtio-console-pci"); |
| 1266 | } |
| 1267 | } |
| 1268 | } |
| 1269 | #endif |
| 1270 | } |
| 1271 | |
| 1272 | static void pc_init_pci(ram_addr_t ram_size, |
| 1273 | const char *boot_device, |
| 1274 | const char *kernel_filename, |
| 1275 | const char *kernel_cmdline, |
| 1276 | const char *initrd_filename, |
| 1277 | const char *cpu_model) |
| 1278 | { |
| 1279 | pc_init1(ram_size, boot_device, |
| 1280 | kernel_filename, kernel_cmdline, |
| 1281 | initrd_filename, 1, cpu_model); |
| 1282 | } |
| 1283 | |
| 1284 | static void pc_init_isa(ram_addr_t ram_size, |
| 1285 | const char *boot_device, |
| 1286 | const char *kernel_filename, |
| 1287 | const char *kernel_cmdline, |
| 1288 | const char *initrd_filename, |
| 1289 | const char *cpu_model) |
| 1290 | { |
| 1291 | pc_init1(ram_size, boot_device, |
| 1292 | kernel_filename, kernel_cmdline, |
| 1293 | initrd_filename, 0, cpu_model); |
| 1294 | } |
| 1295 | |
| 1296 | /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE) |
| 1297 | BIOS will read it and start S3 resume at POST Entry */ |
| 1298 | void cmos_set_s3_resume(void) |
| 1299 | { |
| 1300 | if (rtc_state) |
| 1301 | rtc_set_memory(rtc_state, 0xF, 0xFE); |
| 1302 | } |
| 1303 | |
| 1304 | static QEMUMachine pc_machine = { |
| 1305 | .name = "pc", |
| 1306 | .desc = "Standard PC", |
| 1307 | .init = pc_init_pci, |
| 1308 | .max_cpus = 255, |
| 1309 | .is_default = 1, |
| 1310 | }; |
| 1311 | |
| 1312 | static QEMUMachine isapc_machine = { |
| 1313 | .name = "isapc", |
| 1314 | .desc = "ISA-only PC", |
| 1315 | .init = pc_init_isa, |
| 1316 | .max_cpus = 1, |
| 1317 | }; |
| 1318 | |
| 1319 | static void pc_machine_init(void) |
| 1320 | { |
| 1321 | qemu_register_machine(&pc_machine); |
| 1322 | qemu_register_machine(&isapc_machine); |
| 1323 | } |
| 1324 | |
| 1325 | machine_init(pc_machine_init); |