?? pc.c
字號:
real_addr = phys_ram_base + 0x90000; cmdline_addr = phys_ram_base + 0x9a000 - cmdline_size; prot_addr = phys_ram_base + 0x100000; } else { /* High and recent kernel */ real_addr = phys_ram_base + 0x10000; cmdline_addr = phys_ram_base + 0x20000; prot_addr = phys_ram_base + 0x100000; }#if 0 fprintf(stderr, "qemu: real_addr = %#zx\n" "qemu: cmdline_addr = %#zx\n" "qemu: prot_addr = %#zx\n", real_addr-phys_ram_base, cmdline_addr-phys_ram_base, prot_addr-phys_ram_base);#endif /* highest address for loading the initrd */ if (protocol >= 0x203) initrd_max = ldl_p(header+0x22c); else initrd_max = 0x37ffffff; if (initrd_max >= ram_size-ACPI_DATA_SIZE) initrd_max = ram_size-ACPI_DATA_SIZE-1; /* kernel command line */ pstrcpy((char*)cmdline_addr, 4096, kernel_cmdline); if (protocol >= 0x202) { stl_p(header+0x228, cmdline_addr-phys_ram_base); } else { stw_p(header+0x20, 0xA33F); stw_p(header+0x22, cmdline_addr-real_addr); } /* loader type */ /* High nybble = B reserved for Qemu; low nybble is revision number. If this code is substantially changed, you may want to consider incrementing the revision. */ if (protocol >= 0x200) header[0x210] = 0xB0; /* heap */ if (protocol >= 0x201) { header[0x211] |= 0x80; /* CAN_USE_HEAP */ stw_p(header+0x224, cmdline_addr-real_addr-0x200); } /* load initrd */ if (initrd_filename) { if (protocol < 0x200) { fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n"); exit(1); } fi = fopen(initrd_filename, "rb"); if (!fi) { fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", initrd_filename); exit(1); } initrd_size = get_file_size(fi); initrd_addr = phys_ram_base + ((initrd_max-initrd_size) & ~4095); fprintf(stderr, "qemu: loading initrd (%#x bytes) at %#zx\n", initrd_size, initrd_addr-phys_ram_base); if (fread(initrd_addr, 1, initrd_size, fi) != initrd_size) { fprintf(stderr, "qemu: read error on initial ram disk '%s'\n", initrd_filename); exit(1); } fclose(fi); stl_p(header+0x218, initrd_addr-phys_ram_base); stl_p(header+0x21c, initrd_size); } /* store the finalized header and load the rest of the kernel */ memcpy(real_addr, header, 1024); setup_size = header[0x1f1]; if (setup_size == 0) setup_size = 4; setup_size = (setup_size+1)*512; kernel_size -= setup_size; /* Size of protected-mode code */ if (fread(real_addr+1024, 1, setup_size-1024, f) != setup_size-1024 || fread(prot_addr, 1, kernel_size, f) != kernel_size) { fprintf(stderr, "qemu: read error on kernel '%s'\n", kernel_filename); exit(1); } fclose(f); /* generate bootsector to set up the initial register state */ real_seg = (real_addr-phys_ram_base) >> 4; seg[0] = seg[2] = seg[3] = seg[4] = seg[4] = real_seg; seg[1] = real_seg+0x20; /* CS */ memset(gpr, 0, sizeof gpr); gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */ generate_bootsect(gpr, seg, 0);}static void main_cpu_reset(void *opaque){ CPUState *env = opaque; cpu_reset(env);}static const int ide_iobase[2] = { 0x1f0, 0x170 };static const int ide_iobase2[2] = { 0x3f6, 0x376 };static const int ide_irq[2] = { 14, 15 };#define NE2000_NB_MAX 6static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };#ifdef HAS_AUDIOstatic void audio_init (PCIBus *pci_bus, qemu_irq *pic){ struct soundhw *c; int audio_enabled = 0; for (c = soundhw; !audio_enabled && c->name; ++c) { audio_enabled = c->enabled; } if (audio_enabled) { AudioState *s; s = AUD_init (); if (s) { for (c = soundhw; c->name; ++c) { if (c->enabled) { if (c->isa) { c->init.init_isa (s, pic); } else { if (pci_bus) { c->init.init_pci (pci_bus, s); } } } } } }}#endifstatic void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic){ static int nb_ne2k = 0; if (nb_ne2k == NE2000_NB_MAX) return; isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd); nb_ne2k++;}/* PC hardware initialisation */static void pc_init1(int ram_size, int vga_ram_size, const char *boot_device, DisplayState *ds, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, int pci_enabled, const char *cpu_model){ char buf[1024]; int ret, linux_boot, i; ram_addr_t ram_addr, vga_ram_addr, bios_offset, vga_bios_offset; int bios_size, isa_bios_size, vga_bios_size; PCIBus *pci_bus; int piix3_devfn = -1; CPUState *env; NICInfo *nd; qemu_irq *cpu_irq; qemu_irq *i8259; int index; BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BlockDriverState *fd[MAX_FD]; linux_boot = (kernel_filename != NULL); /* init CPUs */ if (cpu_model == NULL) {#ifdef TARGET_X86_64 cpu_model = "qemu64";#else cpu_model = "qemu32";#endif } for(i = 0; i < smp_cpus; i++) { env = cpu_init(cpu_model); if (!env) { fprintf(stderr, "Unable to find x86 CPU definition\n"); exit(1); } if (i != 0) env->hflags |= HF_HALTED_MASK; if (smp_cpus > 1) { /* XXX: enable it in all cases */ env->cpuid_features |= CPUID_APIC; } register_savevm("cpu", i, 4, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); if (pci_enabled) { apic_init(env); } vmport_init(env); } /* allocate RAM */ ram_addr = qemu_ram_alloc(ram_size); cpu_register_physical_memory(0, ram_size, ram_addr); /* allocate VGA RAM */ vga_ram_addr = qemu_ram_alloc(vga_ram_size); /* BIOS load */ if (bios_name == NULL) bios_name = BIOS_FILENAME; snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); bios_size = get_image_size(buf); if (bios_size <= 0 || (bios_size % 65536) != 0) { goto bios_error; } bios_offset = qemu_ram_alloc(bios_size); ret = load_image(buf, phys_ram_base + bios_offset); if (ret != bios_size) { bios_error: fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", buf); exit(1); } /* VGA BIOS load */ if (cirrus_vga_enabled) { snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME); } else { snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME); } vga_bios_size = get_image_size(buf); if (vga_bios_size <= 0 || vga_bios_size > 65536) goto vga_bios_error; vga_bios_offset = qemu_ram_alloc(65536); ret = load_image(buf, phys_ram_base + vga_bios_offset); if (ret != vga_bios_size) { vga_bios_error: fprintf(stderr, "qemu: could not load VGA BIOS '%s'\n", buf); exit(1); } /* setup basic memory access */ cpu_register_physical_memory(0xc0000, 0x10000, vga_bios_offset | IO_MEM_ROM); /* map the last 128KB of the BIOS in ISA space */ isa_bios_size = bios_size; if (isa_bios_size > (128 * 1024)) isa_bios_size = 128 * 1024; cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size, IO_MEM_UNASSIGNED); cpu_register_physical_memory(0x100000 - isa_bios_size, isa_bios_size, (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); { ram_addr_t option_rom_offset; int size, offset; offset = 0; for (i = 0; i < nb_option_roms; i++) { size = get_image_size(option_rom[i]); if (size < 0) { fprintf(stderr, "Could not load option rom '%s'\n", option_rom[i]); exit(1); } if (size > (0x10000 - offset)) goto option_rom_error; option_rom_offset = qemu_ram_alloc(size); ret = load_image(option_rom[i], phys_ram_base + option_rom_offset); if (ret != size) { option_rom_error: fprintf(stderr, "Too many option ROMS\n"); exit(1); } size = (size + 4095) & ~4095; cpu_register_physical_memory(0xd0000 + offset, size, option_rom_offset | IO_MEM_ROM); offset += size; } } /* map all the bios at the top of memory */ cpu_register_physical_memory((uint32_t)(-bios_size), bios_size, bios_offset | IO_MEM_ROM); bochs_bios_init(); if (linux_boot) load_linux(kernel_filename, initrd_filename, kernel_cmdline); cpu_irq = qemu_allocate_irqs(pic_irq_request, first_cpu, 1); i8259 = i8259_init(cpu_irq[0]); ferr_irq = i8259[13]; if (pci_enabled) { pci_bus = i440fx_init(&i440fx_state, i8259); piix3_devfn = piix3_init(pci_bus, -1); } else { pci_bus = NULL; } /* init basic PC hardware */ register_ioport_write(0x80, 1, 1, ioport80_write, NULL); register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL); if (cirrus_vga_enabled) { if (pci_enabled) { pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr, vga_ram_addr, vga_ram_size); } else { isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr, vga_ram_addr, vga_ram_size); } } else if (vmsvga_enabled) { if (pci_enabled) pci_vmsvga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size); else fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__); } else { if (pci_enabled) { pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr, vga_ram_addr, vga_ram_size, 0, 0); } else { isa_vga_init(ds, phys_ram_base + vga_ram_addr, vga_ram_addr, vga_ram_size); } } rtc_state = rtc_init(0x70, i8259[8]); register_ioport_read(0x92, 1, 1, ioport92_read, NULL); register_ioport_write(0x92, 1, 1, ioport92_write, NULL); if (pci_enabled) { ioapic = ioapic_init(); } pit = pit_init(0x40, i8259[0]); pcspk_init(pit); if (pci_enabled) { pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic); } for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { serial_init(serial_io[i], i8259[serial_irq[i]], serial_hds[i]); } } for(i = 0; i < MAX_PARALLEL_PORTS; i++) { if (parallel_hds[i]) { parallel_init(parallel_io[i], i8259[parallel_irq[i]], parallel_hds[i]); } } for(i = 0; i < nb_nics; i++) { nd = &nd_table[i]; if (!nd->model) { if (pci_enabled) { nd->model = "ne2k_pci"; } else { nd->model = "ne2k_isa"; } } if (strcmp(nd->model, "ne2k_isa") == 0) { pc_init_ne2k_isa(nd, i8259); } else if (pci_enabled) { if (strcmp(nd->model, "?") == 0) fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n"); pci_nic_init(pci_bus, nd, -1); } else if (strcmp(nd->model, "?") == 0) { fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n"); exit(1); } else { fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model); exit(1); } } if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { fprintf(stderr, "qemu: too many IDE bus\n"); exit(1); } for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) { index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); if (index != -1) hd[i] = drives_table[index].bdrv; else hd[i] = NULL; } if (pci_enabled) { pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259); } else { for(i = 0; i < MAX_IDE_BUS; i++) { isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]], hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); } } i8042_init(i8259[1], i8259[12], 0x60); DMA_init(0);#ifdef HAS_AUDIO audio_init(pci_enabled ? pci_bus : NULL, i8259);#endif index = drive_get_index(IF_FLOPPY, 0, i); if (index != -1) fd[i] = drives_table[index].bdrv; else fd[i] = NULL; } floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd); cmos_init(ram_size, boot_device, hd); if (pci_enabled && usb_enabled) { usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); } if (pci_enabled && acpi_enabled) { uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */ i2c_bus *smbus; /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100); for (i = 0; i < 8; i++) { smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256)); } } if (i440fx_state) { i440fx_init_memory_mappings(i440fx_state); } if (pci_enabled) { int max_bus; int bus, unit; void *scsi; max_bus = drive_get_max_bus(IF_SCSI); for (bus = 0; bus <= max_bus; bus++) { scsi = lsi_scsi_init(pci_bus, -1); for (unit = 0; unit < LSI_MAX_DEVS; unit++) { index = drive_get_index(IF_SCSI, bus, unit); if (index == -1) continue; lsi_scsi_attach(scsi, drives_table[index].bdrv, unit); } } }}static void pc_init_pci(int ram_size, int vga_ram_size, const char *boot_device, DisplayState *ds, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model){ pc_init1(ram_size, vga_ram_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, 1, cpu_model);}static void pc_init_isa(int ram_size, int vga_ram_size, const char *boot_device, DisplayState *ds, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model){ pc_init1(ram_size, vga_ram_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, 0, cpu_model);}QEMUMachine pc_machine = { "pc", "Standard PC", pc_init_pci,};QEMUMachine isapc_machine = { "isapc", "ISA-only PC", pc_init_isa,};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -