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.
12 #include "qemu-common.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
)
33 target_phys_addr_t ram_bases
[4], ram_sizes
[4];
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;
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
;
52 uint32_t timebase_freq
;
53 uint32_t mem_reg_property
[]={0, 0, ram_size
};
55 printf("%s: START\n", __func__
);
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
];
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
;
81 env
= cpu_ppc_init("440");
83 fprintf(stderr
, "Unable to initilize CPU!\n");
88 printf("Calling function ppc440_init\n");
89 ppc440ep_init(env
, ram_bases
, ram_sizes
, &pic
, &pci
, 1);
90 printf("Done calling ppc440_init\n");
93 cpu_register_physical_memory(0, ram_size
, 0);
95 kvm_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
);
101 fprintf(stderr
, "qemu: could not load kernel '%s'\n",
105 printf("kernel is at guest address: 0x%lx\n", (unsigned long)la
);
108 if (initrd_filename
) {
109 initrd_base
= kernel_size
+ la
;
110 printf("%s: load initrd\n", __func__
);
111 initrd_size
= load_image(initrd_filename
,
112 phys_ram_base
+ initrd_base
);
114 printf("initrd is at guest address: 0x%lx\n",
115 (unsigned long) initrd_base
);
117 if (initrd_size
< 0) {
119 "qemu: could not load initial ram disk '%s'\n",
126 /* get variable for device tree */
127 cpu_freq
= read_proc_dt_prop_cell("cpus/cpu@0/clock-frequency");
128 timebase_freq
= read_proc_dt_prop_cell("cpus/cpu@0/timebase-frequency");
130 /* load binary device tree into qemu (not guest memory) */
131 printf("%s: load device tree file\n", __func__
);
133 /* get string size */
134 ret
= asprintf(&buf
, "%s/%s", bios_dir
,
135 BINARY_DEVICE_TREE_FILE
);
138 printf("%s: Unable to malloc string buffer buf\n",
143 /* set base for device tree that will be in guest memory */
145 dt_base
= initrd_base
+ initrd_size
;
147 dt_base
= kernel_size
+ la
;
149 fdt
= load_device_tree(buf
, (unsigned long)(phys_ram_base
+ dt_base
));
151 printf("Loading device tree failed!\n");
155 printf("device tree address is at guest address: 0x%lx\n",
156 (unsigned long) dt_base
);
160 /* manipulate device tree in memory */
161 dt_cell(fdt
, "/cpus/cpu@0", "clock-frequency", cpu_freq
);
162 dt_cell(fdt
, "/cpus/cpu@0", "timebase-frequency", timebase_freq
);
163 dt_cell_multi(fdt
, "/memory", "reg", mem_reg_property
,
164 sizeof(mem_reg_property
));
165 dt_cell(fdt
, "/chosen", "linux,initrd-start", initrd_base
);
166 dt_cell(fdt
, "/chosen", "linux,initrd-end",
167 (initrd_base
+ initrd_size
));
168 dt_string(fdt
, "/chosen", "bootargs", (char *)kernel_cmdline
);
172 /* XXX insert TLB entries */
173 env
->gpr
[1] = (16<<20) - 8;
176 /* location of device tree in register */
177 env
->gpr
[3] = dt_base
;
185 /* Add virtio block devices. */
186 while ((i
= drive_get_index(IF_VIRTIO
, 0, unit_id
)) != -1) {
187 virtio_blk_init(pci
->bus
, 0x1AF4, 0x1001,
188 drives_table
[i
].bdrv
);
192 /* Register network interfaces. */
193 for (i
= 0; i
< nb_nics
; i
++) {
196 nd
->model
= "virtio";
197 pci_nic_init(pci
->bus
, nd
, -1);
201 printf("%s: DONE\n", __func__
);
204 QEMUMachine bamboo_machine
= {