1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "sysemu/sysemu.h"
19#include "config.h"
20#include "hw/sysbus.h"
21#include "hw/devices.h"
22#include "hw/loader.h"
23#include "hw/misc/blob-loader.h"
24#include "qemu/error-report.h"
25#include "sysemu/dma.h"
26#include "hw/loader.h"
27#include "elf.h"
28
29#define BLOB_LOADER_CPU_NONE 0xff
30
31static Property blob_loader_props[] = {
32 DEFINE_PROP_UINT64("addr", BlobLoaderState, addr, 0),
33 DEFINE_PROP_UINT64("data", BlobLoaderState, data, 0),
34 DEFINE_PROP_UINT8("data-len", BlobLoaderState, data_len, 0),
35 DEFINE_PROP_UINT8("cpu", BlobLoaderState, cpu_nr, BLOB_LOADER_CPU_NONE),
36 DEFINE_PROP_BOOL("force-raw", BlobLoaderState, force_raw, false),
37 DEFINE_PROP_STRING("file", BlobLoaderState, file),
38 DEFINE_PROP_END_OF_LIST(),
39};
40
41extern AddressSpace *loader_as;
42
43static void blob_loader_realize(DeviceState *dev, Error **errp)
44{
45 BlobLoaderState *s = BLOB_LOADER(dev);
46 int size = 0;
47 hwaddr entry;
48
49 if (s->cpu_nr != BLOB_LOADER_CPU_NONE) {
50 CPUState *cs = first_cpu;
51 int cpu_nr = s->cpu_nr;
52
53 while (cs && cpu_nr) {
54 cs = CPU_NEXT(cs);
55 cpu_nr--;
56 }
57 if (!cs) {
58 error_setg(errp, "Specified boot cpu #%d is non existant",
59 s->cpu_nr);
60 return;
61 }
62 s->cpu = cs;
63 }
64
65 if (s->cpu) {
66 loader_as = s->cpu->as;
67 }
68
69 if (s->file) {
70
71 if (s->force_raw) {
72 goto do_raw;
73 }
74 size = load_elf(s->file, NULL, NULL, &entry, NULL, NULL, 0,
75 ELF_MACHINE, 0);
76
77 if (size < 0) {
78 size = load_uimage(s->file, &entry, NULL, NULL, NULL, NULL);
79 }
80
81do_raw:
82 if (size < 0) {
83
84 size = load_image_targphys(s->file, s->addr, 0);
85 } else {
86 s->addr = entry;
87 }
88 if (size < 0) {
89 error_setg(errp, "Cannot load specified image %s", s->file);
90 return;
91 }
92 }
93
94 loader_as = NULL;
95
96}
97
98static void blob_loader_reset(DeviceState *dev)
99{
100 BlobLoaderState *s = BLOB_LOADER(dev);
101
102 if (s->cpu) {
103 CPUClass *cc = CPU_GET_CLASS(s->cpu);
104 cpu_reset(s->cpu);
105 cc->set_pc(s->cpu, s->addr);
106 cpu_halt_reset_common(s->cpu, NULL, false, true);
107 }
108
109 if (s->data_len) {
110 dma_memory_write((s->cpu ? s->cpu : first_cpu)->as, s->addr, &s->data,
111 s->data_len);
112 }
113}
114
115static void blob_loader_class_init(ObjectClass *klass, void *data)
116{
117 DeviceClass *dc = DEVICE_CLASS(klass);
118
119 dc->reset = blob_loader_reset;
120 dc->realize = blob_loader_realize;
121 dc->props = blob_loader_props;
122 dc->desc = "blob loader";
123}
124
125static TypeInfo blob_loader_info = {
126 .name = TYPE_BLOB_LOADER,
127 .parent = TYPE_DEVICE,
128 .instance_size = sizeof(BlobLoaderState),
129 .class_init = blob_loader_class_init,
130};
131
132static void blob_loader_register_type(void)
133{
134 type_register_static(&blob_loader_info);
135}
136
137type_init(blob_loader_register_type)
138