645e84fd36bd22975d9c318eced6eed5b2acdbf1
[sdk/emulator/qemu.git] / hw / ppc440_bamboo.c
1 /*
2  * Qemu PowerPC 440 Bamboo board emulation
3  *
4  * Copyright 2007 IBM Corporation.
5  * Authors:
6  *      Jerone Young <jyoung5@us.ibm.com>
7  *      Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
8  *      Hollis Blanchard <hollisb@us.ibm.com>
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 "boards.h"
20 #include "sysemu.h"
21 #include "ppc440.h"
22 #include "kvm.h"
23 #include "kvm_ppc.h"
24 #include "device_tree.h"
25 #include "loader.h"
26 #include "elf.h"
27
28 #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
29
30 /* from u-boot */
31 #define KERNEL_ADDR  0x1000000
32 #define FDT_ADDR     0x1800000
33 #define RAMDISK_ADDR 0x1900000
34
35 static int bamboo_load_device_tree(target_phys_addr_t addr,
36                                      uint32_t ramsize,
37                                      target_phys_addr_t initrd_base,
38                                      target_phys_addr_t initrd_size,
39                                      const char *kernel_cmdline)
40 {
41     int ret = -1;
42 #ifdef CONFIG_FDT
43     uint32_t mem_reg_property[] = { 0, 0, ramsize };
44     char *filename;
45     int fdt_size;
46     void *fdt;
47
48     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
49     if (!filename) {
50         goto out;
51     }
52     fdt = load_device_tree(filename, &fdt_size);
53     qemu_free(filename);
54     if (fdt == NULL) {
55         goto out;
56     }
57
58     /* Manipulate device tree in memory. */
59
60     ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
61                                sizeof(mem_reg_property));
62     if (ret < 0)
63         fprintf(stderr, "couldn't set /memory/reg\n");
64
65     ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
66                                     initrd_base);
67     if (ret < 0)
68         fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
69
70     ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
71                                     (initrd_base + initrd_size));
72     if (ret < 0)
73         fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
74
75     ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
76                                       kernel_cmdline);
77     if (ret < 0)
78         fprintf(stderr, "couldn't set /chosen/bootargs\n");
79
80     if (kvm_enabled())
81         kvmppc_fdt_update(fdt);
82
83     ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
84     qemu_free(fdt);
85
86 out:
87 #endif
88
89     return ret;
90 }
91
92 static void bamboo_init(ram_addr_t ram_size,
93                         const char *boot_device,
94                         const char *kernel_filename,
95                         const char *kernel_cmdline,
96                         const char *initrd_filename,
97                         const char *cpu_model)
98 {
99     unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
100     PCIBus *pcibus;
101     CPUState *env;
102     uint64_t elf_entry;
103     uint64_t elf_lowaddr;
104     target_phys_addr_t entry = 0;
105     target_phys_addr_t loadaddr = 0;
106     target_long initrd_size = 0;
107     int success;
108     int i;
109
110     /* Setup CPU. */
111     env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1, cpu_model);
112
113     if (pcibus) {
114         /* Register network interfaces. */
115         for (i = 0; i < nb_nics; i++) {
116             /* There are no PCI NICs on the Bamboo board, but there are
117              * PCI slots, so we can pick whatever default model we want. */
118             pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
119         }
120     }
121
122     /* Load kernel. */
123     if (kernel_filename) {
124         success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
125         if (success < 0) {
126             success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
127                                &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
128             entry = elf_entry;
129             loadaddr = elf_lowaddr;
130         }
131         /* XXX try again as binary */
132         if (success < 0) {
133             fprintf(stderr, "qemu: could not load kernel '%s'\n",
134                     kernel_filename);
135             exit(1);
136         }
137     }
138
139     /* Load initrd. */
140     if (initrd_filename) {
141         initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
142                                           ram_size - RAMDISK_ADDR);
143
144         if (initrd_size < 0) {
145             fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
146                     initrd_filename, RAMDISK_ADDR);
147             exit(1);
148         }
149     }
150
151     /* If we're loading a kernel directly, we must load the device tree too. */
152     if (kernel_filename) {
153         if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
154                                     initrd_size, kernel_cmdline) < 0) {
155             fprintf(stderr, "couldn't load device tree\n");
156             exit(1);
157         }
158
159         /* Set initial guest state. */
160         env->gpr[1] = (16<<20) - 8;
161         env->gpr[3] = FDT_ADDR;
162         env->nip = entry;
163         /* XXX we currently depend on KVM to create some initial TLB entries. */
164     }
165
166     if (kvm_enabled())
167         kvmppc_init();
168 }
169
170 static QEMUMachine bamboo_machine = {
171     .name = "bamboo-0.13",
172     .alias = "bamboo",
173     .desc = "bamboo",
174     .init = bamboo_init,
175 };
176
177 static QEMUMachine bamboo_machine_v0_12 = {
178     .name = "bamboo-0.12",
179     .desc = "bamboo",
180     .init = bamboo_init,
181     .compat_props = (GlobalProperty[]) {
182         {
183             .driver   = "virtio-serial-pci",
184             .property = "max_ports",
185             .value    = stringify(1),
186         },{
187             .driver   = "virtio-serial-pci",
188             .property = "vectors",
189             .value    = stringify(0),
190         },
191         { /* end of list */ }
192     },
193 };
194
195 static void bamboo_machine_init(void)
196 {
197     qemu_register_machine(&bamboo_machine);
198     qemu_register_machine(&bamboo_machine_v0_12);
199 }
200
201 machine_init(bamboo_machine_init);