From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59974) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VdTGJ-00041h-Tn for qemu-devel@nongnu.org; Mon, 04 Nov 2013 18:08:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VdTGE-00045Q-9t for qemu-devel@nongnu.org; Mon, 04 Nov 2013 18:08:47 -0500 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Tue, 5 Nov 2013 00:09:45 +0100 Message-Id: <1383606592-12783-4-git-send-email-hpoussin@reactos.org> In-Reply-To: <1383606592-12783-1-git-send-email-hpoussin@reactos.org> References: <1383606592-12783-1-git-send-email-hpoussin@reactos.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH v3 03/10] raven: move BIOS loading from board code to PCI host List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Herv=C3=A9=20Poussineau?= , =?UTF-8?q?Andreas=20F=C3=A4rber?= , qemu-ppc@nongnu.org Raven datasheet explains where firmware lives in system memory, so do it there instead of in board code. Other boards using the same PCI host will not have to copy the firmware loading code. However, add a specific hack for Open Hack'Ware, which provides only a 512KB blob to be loaded at 0xfff00000, but expects valid code at 0xfffffffc (specific Open Hack'Ware reset instruction pointer). Signed-off-by: Herv=C3=A9 Poussineau --- hw/pci-host/prep.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++= +++++ hw/ppc/prep.c | 50 +++++++++++++---------------------------------= ---- 2 files changed, 64 insertions(+), 37 deletions(-) diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 6ca9802..4dc5456 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -28,7 +28,9 @@ #include "hw/pci/pci_bus.h" #include "hw/pci/pci_host.h" #include "hw/i386/pc.h" +#include "hw/loader.h" #include "exec/address-spaces.h" +#include "elf.h" =20 #define TYPE_RAVEN_PCI_DEVICE "raven" #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" @@ -38,6 +40,9 @@ =20 typedef struct RavenPCIState { PCIDevice dev; + uint32_t elf_machine; + char *bios_name; + MemoryRegion bios; } RavenPCIState; =20 #define RAVEN_PCI_HOST_BRIDGE(obj) \ @@ -52,6 +57,8 @@ typedef struct PRePPCIState { RavenPCIState pci_dev; } PREPPCIState; =20 +#define BIOS_SIZE (1024 * 1024) + static inline uint32_t PPC_PCIIO_config(hwaddr addr) { int i; @@ -169,10 +176,46 @@ static void raven_pcihost_initfn(Object *obj) =20 static int raven_init(PCIDevice *d) { + Object *obj =3D OBJECT(d); + RavenPCIState *s =3D RAVEN_PCI_DEVICE(d); + char *filename; + int bios_size =3D -1; + d->config[0x0C] =3D 0x08; // cache_line_size d->config[0x0D] =3D 0x10; // latency_timer d->config[0x34] =3D 0x00; // capabilities_pointer =20 + memory_region_init_ram(&s->bios, obj, "bios", BIOS_SIZE); + memory_region_set_readonly(&s->bios, true); + memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SI= ZE), + &s->bios); + vmstate_register_ram_global(&s->bios); + if (s->bios_name) { + filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name); + if (filename) { + if (s->elf_machine !=3D EM_NONE) { + bios_size =3D load_elf(filename, NULL, NULL, NULL, + NULL, NULL, 1, s->elf_machine, 0); + } + if (bios_size < 0) { + bios_size =3D get_image_size(filename); + if (bios_size > 0 && bios_size <=3D BIOS_SIZE) { + hwaddr bios_addr; + bios_size =3D (bios_size + 0xfff) & ~0xfff; + bios_addr =3D (uint32_t)(-BIOS_SIZE); + bios_size =3D load_image_targphys(filename, bios_add= r, + bios_size); + } + } + } + if (bios_size < 0 || bios_size > BIOS_SIZE) { + hw_error("qemu: could not load bios image '%s'\n", s->bios_n= ame); + } + if (filename) { + g_free(filename); + } + } + return 0; } =20 @@ -208,12 +251,20 @@ static const TypeInfo raven_info =3D { .class_init =3D raven_class_init, }; =20 +static Property raven_pcihost_properties[] =3D { + DEFINE_PROP_UINT32("elf-machine", PREPPCIState, pci_dev.elf_machine, + EM_NONE), + DEFINE_PROP_STRING("bios-name", PREPPCIState, pci_dev.bios_name), + DEFINE_PROP_END_OF_LIST() +}; + static void raven_pcihost_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); =20 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->realize =3D raven_pcihost_realizefn; + dc->props =3D raven_pcihost_properties; dc->fw_name =3D "pci"; dc->no_user =3D 1; } diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 9f8538c..8a09e2b 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -456,7 +456,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) MemoryRegion *sysmem =3D get_system_memory(); PowerPCCPU *cpu =3D NULL; CPUPPCState *env =3D NULL; - char *filename; nvram_t nvram; M48t59State *m48t59; MemoryRegion *PPC_io_memory =3D g_new(MemoryRegion, 1); @@ -464,7 +463,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) #if 0 MemoryRegion *xcsr =3D g_new(MemoryRegion, 1); #endif - int linux_boot, i, nb_nics1, bios_size; + int linux_boot, i, nb_nics1; MemoryRegion *ram =3D g_new(MemoryRegion, 1); MemoryRegion *bios =3D g_new(MemoryRegion, 1); uint32_t kernel_base, initrd_base; @@ -510,41 +509,13 @@ static void ppc_prep_init(QEMUMachineInitArgs *args= ) memory_region_add_subregion(sysmem, 0, ram); =20 /* allocate and load BIOS */ - memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE); - memory_region_set_readonly(bios, true); - memory_region_add_subregion(sysmem, (uint32_t)(-BIOS_SIZE), bios); - vmstate_register_ram_global(bios); - if (bios_name =3D=3D NULL) - bios_name =3D BIOS_FILENAME; - filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - bios_size =3D load_elf(filename, NULL, NULL, NULL, - NULL, NULL, 1, ELF_MACHINE, 0); - if (bios_size < 0) { - bios_size =3D get_image_size(filename); - if (bios_size > 0 && bios_size <=3D BIOS_SIZE) { - hwaddr bios_addr; - bios_size =3D (bios_size + 0xfff) & ~0xfff; - bios_addr =3D (uint32_t)(-bios_size); - bios_size =3D load_image_targphys(filename, bios_addr, b= ios_size); - } - if (bios_size > BIOS_SIZE) { - fprintf(stderr, "qemu: PReP bios '%s' is too large (0x%x= )\n", - bios_name, bios_size); - exit(1); - } - } - } else { - bios_size =3D -1; - } - if (bios_size < 0 && !qtest_enabled()) { - fprintf(stderr, "qemu: could not load PPC PReP bios '%s'\n", - bios_name); - exit(1); - } - if (filename) { - g_free(filename); - } + /* Open Hack'Ware hack: bios size is 512K and is loaded at 0xfff0000= 0. + * However, reset address is 0xfffffffc. Mirror the bios from + * 0xfff00000 to 0xfff80000. + */ + memory_region_init_alias(bios, NULL, "bios-alias", sysmem, 0xfff0000= 0, + 0x00080000); + memory_region_add_subregion_overlap(sysmem, 0xfff80000, bios, 1); =20 if (linux_boot) { kernel_base =3D KERNEL_LOAD_ADDR; @@ -593,6 +564,11 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) } =20 dev =3D qdev_create(NULL, "raven-pcihost"); + if (bios_name =3D=3D NULL) { + bios_name =3D BIOS_FILENAME; + } + qdev_prop_set_string(dev, "bios-name", bios_name); + qdev_prop_set_uint32(dev, "elf-machine", ELF_MACHINE); pcihost =3D PCI_HOST_BRIDGE(dev); object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), = NULL); qdev_init_nofail(dev); --=20 1.7.10.4