kvm: qemu: ppc: if not a uImage, try to load kernel as ELF
[kvm-userspace.git] / qemu / hw / ppc440_bamboo.c
blob13e370a0db1dab52569ea29ccf4c0dc56d8c5c61
1 /*
2 * Qemu PowerPC 440 board emualtion
4 * Copyright 2007 IBM Corporation.
5 * Authors: Jerone Young <jyoung5@us.ibm.com>
7 * This work is licensed under the GNU GPL license version 2 or later.
9 */
11 #include "config.h"
12 #include "qemu-common.h"
13 #include "net.h"
14 #include "hw.h"
15 #include "pci.h"
16 #include "sysemu.h"
17 #include "ppc440.h"
18 #include "qemu-kvm.h"
19 #include "device_tree.h"
21 #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
23 #define bytes_to_mb(a) (a>>20)
25 void bamboo_init(ram_addr_t ram_size, int vga_ram_size,
26 const char *boot_device, DisplayState *ds,
27 const char *kernel_filename,
28 const char *kernel_cmdline,
29 const char *initrd_filename,
30 const char *cpu_model)
32 char *buf=NULL;
33 target_phys_addr_t ram_bases[4], ram_sizes[4];
34 NICInfo *nd;
35 qemu_irq *pic;
36 ppc4xx_pci_t *pci;
37 CPUState *env;
38 uint64_t ep=0;
39 uint64_t la=0;
40 int is_linux=1; /* Will assume allways is Linux for now */
41 target_long kernel_size=0;
42 target_ulong initrd_base=0;
43 target_long initrd_size=0;
44 target_ulong dt_base=0;
45 void *fdt;
46 int ret;
47 int ram_stick_sizes[] = {256<<20, 128<<20, 64<<20,
48 32<<20, 16<<20, 8<<20 }; /* in bytes */
49 ram_addr_t tmp_ram_size;
50 int i=0, k=0;
51 uint32_t cpu_freq;
52 uint32_t timebase_freq;
53 uint32_t mem_reg_property[]={0, 0, ram_size};
55 printf("%s: START\n", __func__);
57 /* Setup Memory */
58 printf("Ram size passed is: %i MB\n",
59 bytes_to_mb((int)ram_size));
61 tmp_ram_size = ram_size;
63 for (i=0; i < (sizeof(ram_sizes)/sizeof(ram_sizes[0])); i++) {
64 for (k=0; k < (sizeof(ram_stick_sizes)/sizeof(ram_stick_sizes[0])); k++) {
65 if ((tmp_ram_size/ram_stick_sizes[k]) > 0) {
66 ram_sizes[i] = ram_stick_sizes[k];
67 tmp_ram_size -= ram_stick_sizes[k];
68 break;
73 if (tmp_ram_size) {
74 printf("WARNING: %i MB left over memory is ram\n",
75 bytes_to_mb((int)tmp_ram_size));
76 ram_size -= tmp_ram_size;
77 mem_reg_property[2] = ram_size;
80 /* Setup CPU.
81 * XXX Since qemu doesn't implement 440, we just say it's a 405. Since
82 * we don't use qemu's CPU emulation it seems to be working OK. */
83 env = cpu_ppc_init("405");
84 if (!env) {
85 fprintf(stderr, "Unable to initialize CPU!\n");
86 exit(1);
89 /* call init */
90 printf("Calling function ppc440_init\n");
91 ppc440ep_init(env, ram_bases, ram_sizes, &pic, &pci, 1);
92 printf("Done calling ppc440_init\n");
94 /* Register mem */
95 cpu_register_physical_memory(0, ram_size, 0);
97 /* load kernel with uboot loader */
98 printf("%s: load kernel\n", __func__);
99 ret = load_uimage(kernel_filename, &ep, &la, &kernel_size, &is_linux);
100 if (ret < 0)
101 ret = load_elf(kernel_filename, 0, &ep, &la, NULL);
103 if (ret < 0) {
104 fprintf(stderr, "qemu: could not load kernel '%s'\n",
105 kernel_filename);
106 exit(1);
108 printf("kernel is at guest address: 0x%lx\n", (unsigned long)la);
110 /* load initrd */
111 if (initrd_filename) {
112 initrd_base = kernel_size + la;
113 printf("%s: load initrd\n", __func__);
114 initrd_size = load_image(initrd_filename,
115 phys_ram_base + initrd_base);
117 printf("initrd is at guest address: 0x%lx\n",
118 (unsigned long) initrd_base);
120 if (initrd_size < 0) {
121 fprintf(stderr,
122 "qemu: could not load initial ram disk '%s'\n",
123 initrd_filename);
124 exit(1);
128 #ifdef CONFIG_LIBFDT
129 /* get variable for device tree */
130 cpu_freq = read_proc_dt_prop_cell("cpus/cpu@0/clock-frequency");
131 timebase_freq = read_proc_dt_prop_cell("cpus/cpu@0/timebase-frequency");
133 /* load binary device tree into qemu (not guest memory) */
134 printf("%s: load device tree file\n", __func__);
136 /* get string size */
137 ret = asprintf(&buf, "%s/%s", bios_dir,
138 BINARY_DEVICE_TREE_FILE);
140 if (ret < 0) {
141 printf("%s: Unable to malloc string buffer buf\n",
142 __func__);
143 exit(1);
146 /* set base for device tree that will be in guest memory */
147 if (initrd_base)
148 dt_base = initrd_base + initrd_size;
149 else
150 dt_base = kernel_size + la;
152 fdt = load_device_tree(buf, (unsigned long)(phys_ram_base + dt_base));
153 if (fdt == NULL) {
154 printf("Loading device tree failed!\n");
155 exit(1);
158 printf("device tree address is at guest address: 0x%lx\n",
159 (unsigned long) dt_base);
161 free(buf);
163 /* manipulate device tree in memory */
164 dt_cell(fdt, "/cpus/cpu@0", "clock-frequency", cpu_freq);
165 dt_cell(fdt, "/cpus/cpu@0", "timebase-frequency", timebase_freq);
166 dt_cell_multi(fdt, "/memory", "reg", mem_reg_property,
167 sizeof(mem_reg_property));
168 dt_cell(fdt, "/chosen", "linux,initrd-start", initrd_base);
169 dt_cell(fdt, "/chosen", "linux,initrd-end",
170 (initrd_base + initrd_size));
171 dt_string(fdt, "/chosen", "bootargs", (char *)kernel_cmdline);
172 #endif
174 if (kvm_enabled()) {
175 /* XXX insert TLB entries */
176 env->gpr[1] = (16<<20) - 8;
178 #ifdef CONFIG_LIBFDT
179 /* location of device tree in register */
180 env->gpr[3] = dt_base;
181 #endif
182 env->nip = ep;
185 if (pci) {
186 int unit_id = 0;
188 /* Add virtio block devices. */
189 while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
190 virtio_blk_init(pci->bus, 0x1AF4, 0x1001,
191 drives_table[i].bdrv);
192 unit_id++;
195 /* Register network interfaces. */
196 for (i = 0; i < nb_nics; i++) {
197 nd = &nd_table[i];
198 if (!nd->model)
199 nd->model = "virtio";
200 pci_nic_init(pci->bus, nd, -1);
204 printf("%s: DONE\n", __func__);
207 QEMUMachine bamboo_machine = {
208 .name = "bamboo",
209 .desc = "bamboo",
210 .init = bamboo_init,
211 .max_cpus = 1,