|
|
1.1 ! root 1: /* ! 2: * Qemu PowerPC 440 Bamboo board emulation ! 3: * ! 4: * Copyright 2007 IBM Corporation. ! 5: * Authors: ! 6: * Jerone Young <[email protected]> ! 7: * Christian Ehrhardt <[email protected]> ! 8: * Hollis Blanchard <[email protected]> ! 9: * ! 10: * This work is licensed under the GNU GPL license version 2 or later. ! 11: * ! 12: */ ! 13: ! 14: #include "config.h" ! 15: #include "qemu-common.h" ! 16: #include "net.h" ! 17: #include "hw.h" ! 18: #include "pci.h" ! 19: #include "virtio-blk.h" ! 20: #include "virtio-console.h" ! 21: #include "boards.h" ! 22: #include "sysemu.h" ! 23: #include "ppc440.h" ! 24: #include "kvm.h" ! 25: #include "kvm_ppc.h" ! 26: #include "device_tree.h" ! 27: ! 28: #define BINARY_DEVICE_TREE_FILE "bamboo.dtb" ! 29: ! 30: static void *bamboo_load_device_tree(void *addr, ! 31: uint32_t ramsize, ! 32: target_phys_addr_t initrd_base, ! 33: target_phys_addr_t initrd_size, ! 34: const char *kernel_cmdline) ! 35: { ! 36: void *fdt = NULL; ! 37: #ifdef HAVE_FDT ! 38: uint32_t mem_reg_property[] = { 0, 0, ramsize }; ! 39: char *path; ! 40: int pathlen; ! 41: int ret; ! 42: ! 43: pathlen = snprintf(NULL, 0, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE) + 1; ! 44: path = qemu_malloc(pathlen); ! 45: ! 46: snprintf(path, pathlen, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE); ! 47: ! 48: fdt = load_device_tree(path, addr); ! 49: free(path); ! 50: if (fdt == NULL) ! 51: goto out; ! 52: ! 53: /* Manipulate device tree in memory. */ ! 54: ! 55: ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, ! 56: sizeof(mem_reg_property)); ! 57: if (ret < 0) ! 58: fprintf(stderr, "couldn't set /memory/reg\n"); ! 59: ! 60: ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", ! 61: initrd_base); ! 62: if (ret < 0) ! 63: fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); ! 64: ! 65: ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", ! 66: (initrd_base + initrd_size)); ! 67: if (ret < 0) ! 68: fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); ! 69: ! 70: ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", ! 71: kernel_cmdline); ! 72: if (ret < 0) ! 73: fprintf(stderr, "couldn't set /chosen/bootargs\n"); ! 74: ! 75: if (kvm_enabled()) ! 76: kvmppc_fdt_update(fdt); ! 77: ! 78: out: ! 79: #endif ! 80: ! 81: return fdt; ! 82: } ! 83: ! 84: static void bamboo_init(ram_addr_t ram_size, int vga_ram_size, ! 85: const char *boot_device, ! 86: const char *kernel_filename, ! 87: const char *kernel_cmdline, ! 88: const char *initrd_filename, ! 89: const char *cpu_model) ! 90: { ! 91: unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 }; ! 92: PCIBus *pcibus; ! 93: CPUState *env; ! 94: uint64_t elf_entry; ! 95: uint64_t elf_lowaddr; ! 96: target_ulong entry = 0; ! 97: target_ulong loadaddr = 0; ! 98: target_long kernel_size = 0; ! 99: target_ulong initrd_base = 0; ! 100: target_long initrd_size = 0; ! 101: target_ulong dt_base = 0; ! 102: void *fdt; ! 103: int i; ! 104: ! 105: /* Setup CPU. */ ! 106: env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1); ! 107: ! 108: if (pcibus) { ! 109: int unit_id = 0; ! 110: ! 111: /* Add virtio block devices. */ ! 112: while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { ! 113: virtio_blk_init(pcibus, drives_table[i].bdrv); ! 114: unit_id++; ! 115: } ! 116: ! 117: /* Add virtio console devices */ ! 118: for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { ! 119: if (virtcon_hds[i]) ! 120: virtio_console_init(pcibus, virtcon_hds[i]); ! 121: } ! 122: ! 123: /* Register network interfaces. */ ! 124: for (i = 0; i < nb_nics; i++) { ! 125: /* There are no PCI NICs on the Bamboo board, but there are ! 126: * PCI slots, so we can pick whatever default model we want. */ ! 127: pci_nic_init(pcibus, &nd_table[i], -1, "e1000"); ! 128: } ! 129: } ! 130: ! 131: /* Load kernel. */ ! 132: if (kernel_filename) { ! 133: kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL); ! 134: if (kernel_size < 0) { ! 135: kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr, ! 136: NULL); ! 137: entry = elf_entry; ! 138: loadaddr = elf_lowaddr; ! 139: } ! 140: /* XXX try again as binary */ ! 141: if (kernel_size < 0) { ! 142: fprintf(stderr, "qemu: could not load kernel '%s'\n", ! 143: kernel_filename); ! 144: exit(1); ! 145: } ! 146: } ! 147: ! 148: /* Load initrd. */ ! 149: if (initrd_filename) { ! 150: initrd_base = kernel_size + loadaddr; ! 151: initrd_size = load_image(initrd_filename, phys_ram_base + initrd_base); ! 152: ! 153: if (initrd_size < 0) { ! 154: fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", ! 155: initrd_filename); ! 156: exit(1); ! 157: } ! 158: } ! 159: ! 160: /* If we're loading a kernel directly, we must load the device tree too. */ ! 161: if (kernel_filename) { ! 162: if (initrd_base) ! 163: dt_base = initrd_base + initrd_size; ! 164: else ! 165: dt_base = kernel_size + loadaddr; ! 166: ! 167: fdt = bamboo_load_device_tree(phys_ram_base + dt_base, ram_size, ! 168: initrd_base, initrd_size, kernel_cmdline); ! 169: if (fdt == NULL) { ! 170: fprintf(stderr, "couldn't load device tree\n"); ! 171: exit(1); ! 172: } ! 173: ! 174: /* Set initial guest state. */ ! 175: env->gpr[1] = (16<<20) - 8; ! 176: env->gpr[3] = dt_base; ! 177: env->nip = entry; ! 178: /* XXX we currently depend on KVM to create some initial TLB entries. */ ! 179: } ! 180: ! 181: if (kvm_enabled()) ! 182: kvmppc_init(); ! 183: } ! 184: ! 185: QEMUMachine bamboo_machine = { ! 186: .name = "bamboo", ! 187: .desc = "bamboo", ! 188: .init = bamboo_init, ! 189: .ram_require = 8<<20 | RAMSIZE_FIXED, ! 190: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.