1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include "qemu/osdep.h"
29#include "hw/fdt_generic_util.h"
30#include "hw/fdt_generic_devices.h"
31#include "net/net.h"
32#include "exec/memory.h"
33#include "exec/address-spaces.h"
34#include "hw/sysbus.h"
35#include "qapi/error.h"
36#include "sysemu/sysemu.h"
37#include "qemu/log.h"
38#include "qom/cpu.h"
39
40#ifndef FDT_GENERIC_UTIL_ERR_DEBUG
41#define FDT_GENERIC_UTIL_ERR_DEBUG 3
42#endif
43#define DB_PRINT(lvl, ...) do { \
44 if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
45 qemu_log_mask(LOG_FDT, ": %s: ", __func__); \
46 qemu_log_mask(LOG_FDT, ## __VA_ARGS__); \
47 } \
48} while (0);
49
50#define DB_PRINT_NP(lvl, ...) do { \
51 if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
52 qemu_log_mask(LOG_FDT, "%s", node_path); \
53 DB_PRINT((lvl), ## __VA_ARGS__); \
54 } \
55} while (0);
56
57#include "hw/remote-port-device.h"
58
59
60
61#include <libfdt.h>
62#include <stdlib.h>
63
64static int simple_bus_fdt_init(char *bus_node_path, FDTMachineInfo *fdti);
65
66typedef struct QEMUIRQSharedState {
67 qemu_irq sink;
68 int num;
69 bool (*merge_fn)(bool *, int);
70
71#define MAX_IRQ_SHARED_INPUTS 128
72 bool inputs[MAX_IRQ_SHARED_INPUTS];
73} QEMUIRQSharedState;
74
75static bool qemu_irq_shared_or_handler(bool *inputs, int n)
76{
77 int i;
78
79 assert(n < MAX_IRQ_SHARED_INPUTS);
80
81 for (i = 0; i < n; ++i) {
82 if (inputs[i]) {
83 return true;
84 }
85 }
86 return false;
87}
88
89static bool qemu_irq_shared_and_handler(bool *inputs, int n)
90{
91 int i;
92
93 assert(n < MAX_IRQ_SHARED_INPUTS);
94
95 for (i = 0; i < n; ++i) {
96 if (!inputs[i]) {
97 return false;
98 }
99 }
100 return true;
101}
102
103static void qemu_irq_shared_handler(void *opaque, int n, int level)
104{
105 QEMUIRQSharedState *s = opaque;
106
107 assert(n < MAX_IRQ_SHARED_INPUTS);
108 s->inputs[n] = level;
109 qemu_set_irq(s->sink, s->merge_fn(s->inputs, s->num));
110}
111
112static void fdt_init_all_irqs(FDTMachineInfo *fdti)
113{
114 while (fdti->irqs) {
115 FDTIRQConnection *first = fdti->irqs;
116 qemu_irq sink = first->irq;
117 bool (*merge_fn)(bool *, int) = first->merge_fn;
118 int num_sources = 0;
119 FDTIRQConnection *irq;
120
121 for (irq = first; irq; irq = irq->next) {
122 if (irq->irq == sink) {
123 num_sources++;
124 }
125 }
126 if (num_sources > 1) {
127 QEMUIRQSharedState *s = g_malloc0(sizeof *s);
128 s->sink = sink;
129 s->merge_fn = merge_fn;
130 qemu_irq *sources = qemu_allocate_irqs(qemu_irq_shared_handler, s,
131 num_sources);
132 for (irq = first; irq; irq = irq->next) {
133 if (irq->irq == sink) {
134 char *shared_irq_name = g_strdup_printf("shared-irq-%p",
135 *sources);
136
137 if (irq->merge_fn != merge_fn) {
138 fprintf(stderr, "ERROR: inconsistent IRQ merge fns\n");
139 exit(1);
140 }
141
142 object_property_add_child(OBJECT(irq->dev), shared_irq_name,
143 OBJECT(*sources), &error_abort);
144 g_free(shared_irq_name);
145 irq->irq = *(sources++);
146 s->num++;
147 }
148 }
149 }
150 DB_PRINT(0, "%s: connected to %s irq line %d (%s)\n",
151 first->sink_info ? first->sink_info : "",
152 object_get_canonical_path(OBJECT(first->dev)),
153 first->i, first->name ? first->name : "");
154
155 qdev_connect_gpio_out_named(DEVICE(first->dev), first->name, first->i,
156 first->irq);
157 fdti->irqs = first->next;
158 g_free(first);
159 }
160}
161
162FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq)
163{
164 char node_path[DT_PATH_LENGTH];
165
166 FDTMachineInfo *fdti = fdt_init_new_fdti(fdt);
167
168 fdti->irq_base = cpu_irq;
169
170
171 if (!qemu_devtree_get_root_node(fdt, node_path)) {
172 memory_region_transaction_begin();
173 fdt_init_set_opaque(fdti, node_path, NULL);
174 simple_bus_fdt_init(node_path, fdti);
175 while (qemu_co_enter_next(fdti->cq));
176 fdt_init_all_irqs(fdti);
177 memory_region_transaction_commit();
178 } else {
179 fprintf(stderr, "FDT: ERROR: cannot get root node from device tree %s\n"
180 , node_path);
181 }
182
183 DB_PRINT(0, "FDT: Device tree scan complete\n");
184 FDTMachineInfo *ret = g_malloc0(sizeof(*ret));
185 return fdti;
186}
187
188struct FDTInitNodeArgs {
189 char *node_path;
190 char *parent_path;
191 FDTMachineInfo *fdti;
192};
193
194static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat);
195
196static void fdt_init_node(void *args)
197{
198 struct FDTInitNodeArgs *a = args;
199 char *node_path = a->node_path;
200 FDTMachineInfo *fdti = a->fdti;
201 g_free(a);
202
203 simple_bus_fdt_init(node_path, fdti);
204
205 char *all_compats = NULL, *compat, *node_name, *next_compat;
206 char *device_type = NULL;
207 int compat_len;
208
209 DB_PRINT_NP(1, "enter\n");
210
211
212 node_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
213 DB_PRINT_NP(1, "node with name: %s\n", node_name ? node_name : "(none)");
214 if (!node_name) {
215 printf("FDT: ERROR: nameless node: %s\n", node_path);
216 }
217 if (!fdt_init_inst_bind(node_path, fdti, node_name)) {
218 DB_PRINT_NP(0, "instance bind successful\n");
219 goto exit;
220 }
221
222
223 all_compats = qemu_fdt_getprop(fdti->fdt, node_path, "compatible",
224 &compat_len, false, NULL);
225 if (!all_compats) {
226 DB_PRINT_NP(0, "no compatibility found\n");
227 }
228
229 for (compat = all_compats; compat && compat_len; compat = next_compat+1) {
230 char *compat_prefixed = g_strdup_printf("compatible:%s", compat);
231 if (!fdt_init_compat(node_path, fdti, compat_prefixed)) {
232 goto exit;
233 }
234 g_free(compat_prefixed);
235 if (!fdt_init_qdev(node_path, fdti, compat)) {
236 goto exit;
237 }
238 next_compat = rawmemchr(compat, '\0');
239 compat_len -= (next_compat + 1 - compat);
240 if (compat_len > 0) {
241 *next_compat = ' ';
242 }
243 }
244
245 device_type = qemu_fdt_getprop(fdti->fdt, node_path,
246 "device_type", NULL, false, NULL);
247 device_type = g_strdup_printf("device_type:%s", device_type);
248 if (!fdt_init_compat(node_path, fdti, device_type)) {
249 goto exit;
250 }
251
252
253
254
255
256 if (!fdt_init_qdev(node_path, fdti, device_type)) {
257 goto exit;
258 }
259
260 if (!all_compats) {
261 goto exit;
262 }
263 DB_PRINT_NP(0, "FDT: Unsupported peripheral invalidated - "
264 "compatibilities %s\n", all_compats);
265 qemu_fdt_setprop_string(fdti->fdt, node_path, "compatible", "invalidated");
266exit:
267
268 DB_PRINT_NP(1, "exit\n");
269
270 if (!fdt_init_has_opaque(fdti, node_path)) {
271 fdt_init_set_opaque(fdti, node_path, NULL);
272 }
273 g_free(node_path);
274 g_free(all_compats);
275 g_free(device_type);
276 return;
277}
278
279static int simple_bus_fdt_init(char *node_path, FDTMachineInfo *fdti)
280{
281 int i;
282 int num_children = qemu_devtree_get_num_children(fdti->fdt, node_path,
283 1);
284 char **children = qemu_devtree_get_children(fdti->fdt, node_path, 1);
285
286 DB_PRINT_NP(num_children ? 0 : 1, "num child devices: %d\n", num_children);
287
288 for (i = 0; i < num_children; i++) {
289 struct FDTInitNodeArgs *init_args = g_malloc0(sizeof(*init_args));
290 init_args->node_path = children[i];
291 init_args->fdti = fdti;
292 qemu_coroutine_enter(qemu_coroutine_create(fdt_init_node), init_args);
293 }
294
295 g_free(children);
296 return 0;
297}
298
299static qemu_irq fdt_get_gpio(FDTMachineInfo *fdti, char *node_path,
300 int* cur_cell, qemu_irq input,
301 const FDTGenericGPIOSet *gpio_set,
302 const char *debug_success, bool *end) {
303 void *fdt = fdti->fdt;
304 uint32_t parent_phandle, parent_cells = 0, cells[32];
305 char parent_node_path[DT_PATH_LENGTH];
306 DeviceState *parent;
307 int i;
308 Error *errp = NULL;
309 const char *reason;
310 bool free_reason = false;
311 const char *propname = gpio_set->names->propname;
312 const char *cells_propname = gpio_set->names->cells_propname;
313
314 cells[0] = 0;
315
316 parent_phandle = qemu_fdt_getprop_cell(fdt, node_path, propname,
317 (*cur_cell)++, false, &errp);
318 if (errp) {
319 reason = g_strdup_printf("Cant get phandle from \"%s\" property\n",
320 propname);
321 *end = true;
322 free_reason = true;
323 goto fail_silent;
324 }
325 if (qemu_devtree_get_node_by_phandle(fdt, parent_node_path,
326 parent_phandle)) {
327 *end = true;
328 reason = "cant get node from phandle\n";
329 goto fail;
330 }
331 parent_cells = qemu_fdt_getprop_cell(fdt, parent_node_path,
332 cells_propname, 0, false, &errp);
333 if (errp) {
334 *end = true;
335 reason = g_strdup_printf("cant get the property \"%s\" from the " \
336 "parent \"%s\"\n",
337 cells_propname, parent_node_path);
338 free_reason = true;
339 goto fail;
340 }
341
342 for (i = 0; i < parent_cells; ++i) {
343 cells[i] = qemu_fdt_getprop_cell(fdt, node_path, propname,
344 (*cur_cell)++, false, &errp);
345 if (errp) {
346 *end = true;
347 reason = "cant get cell value";
348 goto fail;
349 }
350 }
351
352 while (!fdt_init_has_opaque(fdti, parent_node_path)) {
353 fdt_init_yield(fdti);
354 }
355 parent = DEVICE(fdt_init_get_opaque(fdti, parent_node_path));
356
357 if (!parent) {
358 reason = "parent is not a device";
359 goto fail_silent;
360 }
361
362 while (!parent->realized) {
363 fdt_init_yield(fdti);
364 }
365
366 {
367 const FDTGenericGPIOConnection *fgg_con = NULL;
368 uint16_t range, idx;
369 const char *gpio_name = NULL;
370 qemu_irq ret;
371
372 if (object_dynamic_cast(OBJECT(parent), TYPE_FDT_GENERIC_GPIO)) {
373 const FDTGenericGPIOSet *set;
374 FDTGenericGPIOClass *parent_fggc =
375 FDT_GENERIC_GPIO_GET_CLASS(parent);
376
377 for (set = parent_fggc->controller_gpios; set && set->names;
378 set++) {
379 if (!strcmp(gpio_set->names->cells_propname,
380 set->names->cells_propname)) {
381 fgg_con = set->gpios;
382 break;
383 }
384 }
385 }
386
387
388 idx = cells[0] & ~(1ul << 31);
389 if (fgg_con) {
390 range = fgg_con->range ? fgg_con->range : 1;
391 while (!(idx >= fgg_con->fdt_index
392 && idx < (fgg_con->fdt_index + range))
393 && fgg_con->name) {
394 fgg_con++;
395 }
396 if (!fgg_con) {
397 goto fail;
398 }
399
400 idx -= fgg_con->fdt_index;
401 gpio_name = fgg_con->name;
402 }
403
404 if (input) {
405 FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
406 bool (*merge_fn)(bool *, int) = qemu_irq_shared_or_handler;
407
408
409
410
411
412 if (cells[0] & (1 << 31)) {
413 merge_fn = qemu_irq_shared_and_handler;
414 }
415
416 DB_PRINT_NP(1, "%s GPIO output %s[%d] on %s\n", debug_success,
417 gpio_name ? gpio_name : "unnamed", idx,
418 parent_node_path);
419 *irq = (FDTIRQConnection) {
420 .dev = parent,
421 .name = gpio_name,
422 .merge_fn = merge_fn,
423 .i = idx,
424 .irq = input,
425 .sink_info = NULL,
426 .next = fdti->irqs
427 };
428 fdti->irqs = irq;
429 }
430 ret = qdev_get_gpio_in_named(parent, gpio_name, idx);
431
432 if (ret) {
433 DB_PRINT_NP(1, "wiring GPIO input %s on %s ... \n",
434 fgg_con ? fgg_con->name : "unnamed", parent_node_path);
435 }
436 return ret;
437 }
438fail:
439 fprintf(stderr, "%s Failed: %s\n", node_path, reason);
440fail_silent:
441 if (free_reason) {
442 g_free((void *)reason);
443 }
444 return NULL;
445}
446
447static void fdt_get_irq_info_from_intc(FDTMachineInfo *fdti, qemu_irq *ret,
448 char *intc_node_path,
449 uint32_t *cells, uint32_t num_cells,
450 uint32_t max, Error **errp)
451{
452 FDTGenericIntcClass *intc_fdt_class;
453 DeviceState *intc;
454
455 while (!fdt_init_has_opaque(fdti, intc_node_path)) {
456 fdt_init_yield(fdti);
457 }
458 intc = DEVICE(fdt_init_get_opaque(fdti, intc_node_path));
459
460 if (!intc) {
461 goto fail;
462 }
463
464 while (!intc->realized) {
465 fdt_init_yield(fdti);
466 }
467
468 intc_fdt_class = FDT_GENERIC_INTC_GET_CLASS(intc);
469 if (!intc_fdt_class) {
470 goto fail;
471 }
472
473 intc_fdt_class->get_irq(FDT_GENERIC_INTC(intc), ret, cells, num_cells,
474 max, errp);
475
476 return;
477fail:
478 error_setg(errp, "%s", __func__);
479}
480
481static uint32_t imap_cache[4096];
482static bool imap_cached = false;
483
484qemu_irq *fdt_get_irq_info(FDTMachineInfo *fdti, char *node_path, int irq_idx,
485 char *info, bool *map_mode) {
486 void *fdt = fdti->fdt;
487 uint32_t intc_phandle, intc_cells, cells[32];
488 char intc_node_path[DT_PATH_LENGTH];
489 qemu_irq *ret = NULL;
490 int i;
491 Error *errp = NULL;
492
493 intc_phandle = qemu_fdt_getprop_cell(fdt, node_path, "interrupt-parent",
494 0, true, &errp);
495 if (errp) {
496 errp = NULL;
497 intc_cells = qemu_fdt_getprop_cell(fdt, node_path,
498 "#interrupt-cells", 0, true, &errp);
499 *map_mode = true;
500 } else {
501 if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
502 intc_phandle)) {
503 goto fail;
504 }
505
506
507 qemu_fdt_getprop_cell(fdt, node_path, "interrupt-map-mask", 0,
508 false, &errp);
509 if (!errp) {
510 errp = NULL;
511 intc_cells = qemu_fdt_getprop_cell(fdt, node_path,
512 "#interrupt-cells", 0,
513 true, &errp);
514 *map_mode = true;
515 } else {
516 errp = NULL;
517 intc_cells = qemu_fdt_getprop_cell(fdt, intc_node_path,
518 "#interrupt-cells", 0,
519 true, &errp);
520 *map_mode = false;
521 }
522 }
523
524 if (errp) {
525 goto fail;
526 }
527
528 DB_PRINT_NP(2, "%s intc_phandle: %d\n", node_path, intc_phandle);
529
530 for (i = 0; i < intc_cells; ++i) {
531 cells[i] = qemu_fdt_getprop_cell(fdt, node_path, "interrupts",
532 intc_cells * irq_idx + i, false, &errp);
533 if (errp) {
534 goto fail;
535 }
536 }
537
538 if (*map_mode) {
539 int k;
540 ret = g_new0(qemu_irq, 1);
541 int num_matches = 0;
542 int len;
543 uint32_t imap_mask[intc_cells];
544 uint32_t *imap_p;
545 uint32_t *imap;
546 bool use_parent = false;
547
548 for (k = 0; k < intc_cells; ++k) {
549 imap_mask[k] = qemu_fdt_getprop_cell(fdt, node_path,
550 "interrupt-map-mask", k + 2,
551 true, &errp);
552 if (errp) {
553 goto fail;
554 }
555 }
556
557
558 imap = qemu_fdt_getprop(fdt, node_path, "interrupt-map", &len,
559 use_parent, &errp);
560
561 if (!imap || errp) {
562
563
564
565 use_parent = true;
566 errp = NULL;
567
568 imap_p = qemu_fdt_getprop(fdt, node_path, "interrupt-map",
569 &len, use_parent, &errp);
570 if (!imap_cached) {
571 memcpy(imap_cache, imap_p, len);
572 imap_cached = true;
573 }
574 imap = imap_cache;
575
576 if (errp) {
577 goto fail;
578 }
579 }
580
581 len /= sizeof(uint32_t);
582
583 i = 0;
584 assert(imap);
585 while (i < len) {
586 if (!use_parent) {
587
588
589
590 imap = qemu_fdt_getprop(fdt, node_path, "interrupt-map", &len,
591 use_parent, &errp);
592
593 if (errp) {
594 goto fail;
595 }
596
597 len /= sizeof(uint32_t);
598 }
599
600 bool match = true;
601 uint32_t new_intc_cells, new_cells[32];
602 i++; i++;
603 for (k = 0; k < intc_cells; ++k) {
604 uint32_t map_val = be32_to_cpu(imap[i++]);
605 if ((cells[k] ^ map_val) & imap_mask[k]) {
606 match = false;
607 }
608 }
609
610
611
612
613 intc_phandle = be32_to_cpu(imap[i++]);
614 if (intc_phandle & (0xffu << 24)) {
615 new_intc_cells = (intc_phandle >> 24) - 1;
616 } else {
617 if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
618 intc_phandle)) {
619 goto fail;
620 }
621 new_intc_cells = qemu_fdt_getprop_cell(fdt, intc_node_path,
622 "#interrupt-cells", 0,
623 false, &errp);
624 imap[i - 1] = cpu_to_be32(intc_phandle |
625 (new_intc_cells + 1) << 24);
626 if (errp) {
627 goto fail;
628 }
629 }
630 for (k = 0; k < new_intc_cells; ++k) {
631 new_cells[k] = be32_to_cpu(imap[i++]);
632 }
633 if (match) {
634 num_matches++;
635 ret = g_renew(qemu_irq, ret, num_matches + 1);
636 if (intc_phandle & (0xffu << 24)) {
637 if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
638 intc_phandle &
639 ((1 << 24) - 1))) {
640 goto fail;
641 }
642 }
643
644 DB_PRINT_NP(2, "Getting IRQ information: %s -> 0x%x (%s)\n",
645 node_path, intc_phandle, intc_node_path);
646
647 memset(&ret[num_matches], 0, sizeof(*ret));
648 fdt_get_irq_info_from_intc(fdti, &ret[num_matches-1], intc_node_path,
649 new_cells, new_intc_cells, 1, &errp);
650 if (info) {
651 sprintf(info, "%s", intc_node_path);
652 info += strlen(info) + 1;
653 }
654 if (errp) {
655 goto fail;
656 }
657 }
658 }
659 return ret;
660 }
661
662 DB_PRINT_NP(2, "Getting IRQ information: %s -> %s\n",
663 node_path, intc_node_path);
664
665 ret = g_new0(qemu_irq, fdt_generic_num_cpus + 2);
666 fdt_get_irq_info_from_intc(fdti, ret, intc_node_path, cells, intc_cells,
667 fdt_generic_num_cpus, &errp);
668
669 if (errp) {
670 goto fail;
671 }
672
673
674 if (info) {
675 sprintf(info, "%s", intc_node_path);
676 }
677
678 return ret;
679
680fail:
681 if (errp) {
682 sprintf(info, "%s", error_get_pretty(errp));
683 } else {
684 sprintf(info, "(none)");
685 }
686 return NULL;
687}
688
689qemu_irq *fdt_get_irq(FDTMachineInfo *fdti, char *node_path, int irq_idx,
690 bool *map_mode)
691{
692 return fdt_get_irq_info(fdti, node_path, irq_idx, NULL, map_mode);
693}
694
695
696
697#define DIGIT(a) ((a) >= '0' && (a) <= '9')
698#define LOWER_CASE(a) ((a) >= 'a' && (a) <= 'z')
699
700static void trim_version(char *x)
701{
702 for (;;) {
703 x = strchr(x, '-');
704 if (!x) {
705 return;
706 }
707 if (DIGIT(x[1])) {
708
709 char *p;
710 if (strtol(x+1, &p, 0)) {
711 p = p;
712 }
713 if ( *p == '.') {
714 *x = 0;
715 return;
716 } else if ( *p == 0) {
717 return;
718 }
719 } else if (x[1] == 'r' && x[3] == 'p') {
720
721 if (DIGIT(x[2]) && DIGIT(x[4])) {
722 *x = 0;
723 return;
724 }
725 }
726 x++;
727 }
728}
729
730static void substitute_char(char *s, char a, char b)
731{
732 for (;;) {
733 s = strchr(s, a);
734 if (!s) {
735 return;
736 }
737 *s = b;
738 s++;
739 }
740}
741
742static inline const char *trim_vendor(const char *s)
743{
744
745 const char *ret = memchr(s, ',', strlen(s));
746 return ret ? ret + 1 : s;
747}
748
749static Object *fdt_create_from_compat(const char *compat, char **dev_type)
750{
751 Object *ret = NULL;
752 char *c = g_strdup(compat);
753
754
755 ret = object_new(c);
756
757 if (!ret) {
758
759 trim_version(c);
760 ret = object_new(c);
761
762 if (!ret) {
763
764 substitute_char(c, ',', '.');
765 ret = object_new(c);
766 }
767 }
768
769 if (!ret) {
770
771
772
773 g_free(c);
774 c = g_strdup(compat);
775 substitute_char(c, ',', '.');
776 ret = object_new(c);
777 }
778
779 if (dev_type) {
780 *dev_type = c;
781 } else {
782 g_free(c);
783 }
784
785 if (!ret) {
786 const char *no_vendor = trim_vendor(compat);
787
788 if (no_vendor != compat) {
789 return fdt_create_from_compat(no_vendor, dev_type);
790 }
791 }
792 return ret;
793}
794
795
796
797static inline uint64_t get_int_be(const void *p, int len)
798{
799 switch (len) {
800 case 1:
801 return *((uint8_t *)p);
802 case 2:
803 return be16_to_cpu(*((uint16_t *)p));
804 case 4:
805 return be32_to_cpu(*((uint32_t *)p));
806 case 8:
807 return be32_to_cpu(*((uint64_t *)p));
808 default:
809 fprintf(stderr, "unsupported integer length\n");
810 abort();
811 }
812}
813
814
815
816static const char *fdt_generic_reg_size_prop_names[] = {
817 "#address-cells",
818 "#size-cells",
819 "#bus-cells",
820 "#priority-cells",
821};
822
823static const int fdt_generic_reg_cells_defaults[] = {
824 1,
825 1,
826 0,
827 0,
828};
829
830static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat)
831{
832 Object *dev, *parent;
833 char *dev_type = NULL;
834 int is_intc;
835 Error *errp = NULL;
836 int i, j;
837 QEMUDevtreeProp *prop, *props;
838 char parent_node_path[DT_PATH_LENGTH];
839 const FDTGenericGPIOSet *gpio_set = NULL;
840 FDTGenericGPIOClass *fggc = NULL;
841
842 if (!compat) {
843 return 1;
844 }
845 dev = fdt_create_from_compat(compat, &dev_type);
846 if (!dev) {
847 DB_PRINT_NP(1, "no match found for %s\n", compat);
848 return 1;
849 }
850 DB_PRINT_NP(1, "matched compat %s\n", compat);
851
852
853 if (object_dynamic_cast(dev, TYPE_CPU)) {
854 fdt_generic_num_cpus++;
855 DB_PRINT_NP(0, "is a CPU - total so far %d\n", fdt_generic_num_cpus);
856 }
857
858 if (qemu_devtree_getparent(fdti->fdt, parent_node_path, node_path)) {
859 abort();
860 }
861 while (!fdt_init_has_opaque(fdti, parent_node_path)) {
862 fdt_init_yield(fdti);
863 }
864 parent = fdt_init_get_opaque(fdti, parent_node_path);
865 if (dev->parent) {
866 DB_PRINT_NP(0, "Node already parented - skipping node\n");
867 } else if (parent) {
868 DB_PRINT_NP(1, "parenting node\n");
869 object_property_add_child(OBJECT(parent),
870 qemu_devtree_get_node_name(fdti->fdt, node_path),
871 OBJECT(dev), NULL);
872 if (object_dynamic_cast(dev, TYPE_DEVICE)) {
873 Object *parent_bus = parent;
874 unsigned int depth = 0;
875
876 DB_PRINT_NP(1, "bus parenting node\n");
877
878 while (parent_bus && !object_dynamic_cast(parent_bus, TYPE_BUS)) {
879
880
881
882
883 assert(depth < 4096);
884
885 parent_bus = parent_bus->parent;
886 depth++;
887 }
888
889 if (!parent_bus
890 && object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) {
891
892
893
894
895
896 parent_bus = OBJECT(sysbus_get_default());
897 }
898
899 if (parent_bus) {
900 qdev_set_parent_bus(DEVICE(dev), BUS(parent_bus));
901 }
902 }
903 } else {
904 DB_PRINT_NP(1, "orphaning node\n");
905
906 object_property_add_child(
907 object_get_root(),
908 qemu_devtree_get_node_name(fdti->fdt, node_path),
909 OBJECT(dev), NULL);
910 }
911 fdt_init_set_opaque(fdti, node_path, dev);
912
913
914
915 if (global_sync_quantum) {
916 ObjectProperty *p;
917
918 p = object_property_find(OBJECT(dev), "sync-quantum", NULL);
919 if (p) {
920 object_property_set_int(OBJECT(dev), global_sync_quantum,
921 "sync-quantum", &errp);
922 }
923 }
924
925 props = qemu_devtree_get_props(fdti->fdt, node_path);
926 for (prop = props; prop->name; prop++) {
927 const char *propname = trim_vendor(prop->name);
928 int len = prop->len;
929 void *val = prop->value;
930
931 ObjectProperty *p = object_property_find(OBJECT(dev), propname, NULL);
932 if (p) {
933 DB_PRINT_NP(1, "matched property: %s of type %s, len %d\n",
934 propname, p->type, prop->len);
935 }
936 if (!p) {
937 continue;
938 }
939
940 if (!strcmp(propname, "type")) {
941 continue;
942 }
943
944
945 if (!strcmp(p->type, "uint8") || !strcmp(p->type, "uint16") ||
946 !strcmp(p->type, "uint32") || !strcmp(p->type, "uint64")) {
947 object_property_set_int(OBJECT(dev), get_int_be(val, len), propname,
948 &error_abort);
949 DB_PRINT_NP(0, "set property %s to %#llx\n", propname,
950 (unsigned long long)get_int_be(val, len));
951 } else if (!strcmp(p->type, "boolean") || !strcmp(p->type, "bool")) {
952 object_property_set_bool(OBJECT(dev), !!get_int_be(val, len),
953 propname, &error_abort);
954 DB_PRINT_NP(0, "set property %s to %s\n", propname,
955 get_int_be(val, len) ? "true" : "false");
956 } else if (!strcmp(p->type, "string") || !strcmp(p->type, "str")) {
957 object_property_set_str(OBJECT(dev), (const char *)val, propname,
958 &error_abort);
959 DB_PRINT_NP(0, "set property %s to %s\n", propname,
960 (const char *)val);
961 } else if (!strncmp(p->type, "link", 4)) {
962 char target_node_path[DT_PATH_LENGTH];
963 char propname_target[1024];
964 strcpy(propname_target, propname);
965 strcat(propname_target, "-target");
966
967 Object *linked_dev, *proxy;
968
969 if (qemu_devtree_get_node_by_phandle(fdti->fdt, target_node_path,
970 get_int_be(val, len))) {
971 abort();
972 }
973 while (!fdt_init_has_opaque(fdti, target_node_path)) {
974 fdt_init_yield(fdti);
975 }
976 linked_dev = fdt_init_get_opaque(fdti, target_node_path);
977
978 proxy = linked_dev ? object_property_get_link(linked_dev,
979 propname_target,
980 &errp) : NULL;
981 if (!errp && proxy) {
982 DB_PRINT_NP(0, "detected proxy object for %s connection\n",
983 propname);
984 linked_dev = proxy;
985 }
986 errp = NULL;
987 if (linked_dev) {
988 object_property_set_link(OBJECT(dev), linked_dev, propname,
989 &errp);
990 if (errp) {
991
992
993
994 MemoryRegion *alias_mr;
995 int offset = len / 2;
996 alias_mr =
997 sysbus_mmio_get_region(SYS_BUS_DEVICE(linked_dev),
998 get_int_be(val + offset,
999 len - offset));
1000
1001 object_property_set_link(OBJECT(dev), OBJECT(alias_mr),
1002 propname, &error_abort);
1003
1004 errp = NULL;
1005 }
1006 DB_PRINT_NP(0, "set link %s\n", propname);
1007 }
1008 } else {
1009 DB_PRINT_NP(0, "WARNING: property is of unknown type\n");
1010 }
1011 }
1012
1013
1014 if (object_dynamic_cast(dev, TYPE_REMOTE_PORT_DEVICE)) {
1015 int i;
1016
1017 for (i = 0;;++i) {
1018 char adaptor_node_path[DT_PATH_LENGTH];
1019 uint32_t adaptor_phandle, chan;
1020 DeviceState *adaptor;
1021 char *name;
1022
1023 adaptor_phandle = qemu_fdt_getprop_cell(fdti->fdt, node_path,
1024 "remote-ports",
1025 2 * i, false, &errp);
1026 if (errp) {
1027 DB_PRINT_NP(1, "cant get phandle from \"remote-ports\" "
1028 "property\n");
1029 break;
1030 }
1031 if (qemu_devtree_get_node_by_phandle(fdti->fdt, adaptor_node_path,
1032 adaptor_phandle)) {
1033 DB_PRINT_NP(1, "cant get node from phandle\n");
1034 break;
1035 }
1036 adaptor = DEVICE(fdt_init_get_opaque(fdti, adaptor_node_path));
1037 name = g_strdup_printf("rp-adaptor%" PRId32, i);
1038 object_property_set_link(OBJECT(dev), OBJECT(adaptor), name, &errp);
1039 DB_PRINT_NP(0, "connecting RP to adaptor %s channel %d",
1040 object_get_canonical_path(OBJECT(adaptor)), i);
1041 g_free(name);
1042 if (errp) {
1043 DB_PRINT_NP(1, "cant set adaptor link for device property\n");
1044 break;
1045 }
1046
1047 chan = qemu_fdt_getprop_cell(fdti->fdt, node_path, "remote-ports",
1048 2 * i + 1, false, &errp);
1049 if (errp) {
1050 DB_PRINT_NP(1, "cant get channel from \"remote-ports\" "
1051 "property\n");
1052 break;
1053 }
1054
1055 name = g_strdup_printf("rp-chan%" PRId32, i);
1056 object_property_set_int(OBJECT(dev), chan, name, &errp);
1057
1058
1059
1060 if (errp) {
1061 DB_PRINT_NP(1, "cant set %s property %s\n", name, error_get_pretty(errp));
1062 errp = NULL;
1063 }
1064 g_free(name);
1065
1066 name = g_strdup_printf("remote-port-dev%d", chan);
1067 object_property_set_link(OBJECT(adaptor), OBJECT(dev), name,
1068 &errp);
1069 g_free(name);
1070 if (errp) {
1071 DB_PRINT_NP(1, "cant set device link for adaptor\n");
1072 break;
1073 }
1074 }
1075 errp = NULL;
1076 }
1077
1078 if (object_dynamic_cast(dev, TYPE_DEVICE)) {
1079 DeviceClass *dc = DEVICE_GET_CLASS(dev);
1080
1081 static int nics;
1082 const char *short_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
1083
1084 if (object_property_find(OBJECT(dev), "mac", NULL) &&
1085 object_property_find(OBJECT(dev), "netdev", NULL)) {
1086 qdev_set_nic_properties(DEVICE(dev), &nd_table[nics]);
1087 }
1088 if (nd_table[nics].instantiated) {
1089 DB_PRINT_NP(0, "NIC instantiated: %s\n", dev_type);
1090 nics++;
1091 }
1092
1093
1094 DB_PRINT_NP(0, "Short naming node: %s\n", short_name);
1095 (DEVICE(dev))->id = g_strdup(short_name);
1096 qdev_init_nofail(DEVICE(dev));
1097 qemu_register_reset((void (*)(void *))dc->reset, dev);
1098 }
1099
1100 if (object_dynamic_cast(dev, TYPE_SYS_BUS_DEVICE) ||
1101 object_dynamic_cast(dev, TYPE_FDT_GENERIC_MMAP)) {
1102 FDTGenericRegPropInfo reg = {0};
1103 char parent_path[DT_PATH_LENGTH];
1104 int cell_idx = 0;
1105 bool extended = true;
1106
1107 qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg-extended", 0, false,
1108 &errp);
1109 if (errp) {
1110 error_free(errp);
1111 errp = NULL;
1112 extended = false;
1113 qemu_devtree_getparent(fdti->fdt, parent_path, node_path);
1114 }
1115
1116 for (reg.n = 0;; reg.n++) {
1117 char ph_parent[DT_PATH_LENGTH];
1118 const char *pnp = parent_path;
1119
1120 reg.parents = g_renew(Object *, reg.parents, reg.n + 1);
1121 reg.parents[reg.n] = parent;
1122
1123 if (extended) {
1124 int p_ph = qemu_fdt_getprop_cell(fdti->fdt, node_path,
1125 "reg-extended", cell_idx++,
1126 false, &errp);
1127 if (errp) {
1128 error_free(errp);
1129 errp = NULL;
1130 goto exit_reg_parse;
1131 }
1132 if (qemu_devtree_get_node_by_phandle(fdti->fdt, ph_parent,
1133 p_ph)) {
1134 goto exit_reg_parse;
1135 }
1136 while (!fdt_init_has_opaque(fdti, ph_parent)) {
1137 fdt_init_yield(fdti);
1138 }
1139 reg.parents[reg.n] = fdt_init_get_opaque(fdti, ph_parent);
1140 pnp = ph_parent;
1141 }
1142
1143 for (i = 0; i < FDT_GENERIC_REG_TUPLE_LENGTH; ++i) {
1144 const char *size_prop_name = fdt_generic_reg_size_prop_names[i];
1145 int nc = qemu_fdt_getprop_cell(fdti->fdt, pnp, size_prop_name,
1146 0, true, &errp);
1147
1148 if (errp) {
1149 int size_default = fdt_generic_reg_cells_defaults[i];
1150
1151 DB_PRINT_NP(0, "WARNING: no %s for %s container, assuming "
1152 "default of %d\n", size_prop_name, pnp,
1153 size_default);
1154 nc = size_default;
1155 error_free(errp);
1156 errp = NULL;
1157 }
1158
1159 reg.x[i] = g_renew(uint64_t, reg.x[i], reg.n + 1);
1160 reg.x[i][reg.n] = nc ?
1161 qemu_fdt_getprop_sized_cell(fdti->fdt, node_path,
1162 extended ? "reg-extended"
1163 : "reg",
1164 cell_idx, nc, &errp)
1165 : 0;
1166 cell_idx += nc;
1167 if (errp) {
1168 goto exit_reg_parse;
1169 }
1170 }
1171 }
1172exit_reg_parse:
1173
1174 if (object_dynamic_cast(dev, TYPE_FDT_GENERIC_MMAP)) {
1175 FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_GET_CLASS(dev);
1176 if (fmc->parse_reg) {
1177 while (fmc->parse_reg(FDT_GENERIC_MMAP(dev), reg,
1178 &error_abort)) {
1179 fdt_init_yield(fdti);
1180 }
1181 }
1182 }
1183 }
1184
1185 if (object_dynamic_cast(dev, TYPE_SYS_BUS_DEVICE)) {
1186 {
1187 int len;
1188 fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
1189 "interrupt-controller", &len);
1190 is_intc = len >= 0;
1191 DB_PRINT_NP(is_intc ? 0 : 1, "is interrupt controller: %c\n",
1192 is_intc ? 'y' : 'n');
1193 }
1194
1195 j = 0;
1196 for (i = 0;; i++) {
1197 char irq_info[1024];
1198 char *irq_info_p = irq_info;
1199 bool map_mode;
1200 int len = -1;
1201 qemu_irq *irqs = fdt_get_irq_info(fdti, node_path, i, irq_info,
1202 &map_mode);
1203
1204 fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
1205 "interrupts-extended", &len);
1206 if (!irqs && is_intc && i == 0 && len <= 0) {
1207 FDTGenericIntc *id = (FDTGenericIntc *)object_dynamic_cast(
1208 dev, TYPE_FDT_GENERIC_INTC);
1209 FDTGenericIntcClass *idc = FDT_GENERIC_INTC_GET_CLASS(id);
1210 if (id && idc->auto_parent) {
1211 Error *err = NULL;
1212 idc->auto_parent(id, &err);
1213 } else {
1214 irqs = fdti->irq_base;
1215 }
1216 }
1217 if (!irqs) {
1218 break;
1219 }
1220 while (*irqs) {
1221 FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
1222 *irq = (FDTIRQConnection) {
1223 .dev = DEVICE(dev),
1224 .name = SYSBUS_DEVICE_GPIO_IRQ,
1225 .merge_fn = qemu_irq_shared_or_handler,
1226 .i = j,
1227 .irq = *irqs,
1228 .sink_info = g_strdup(irq_info_p),
1229 .next = fdti->irqs
1230 };
1231 if (!map_mode) {
1232 j++;
1233 } else {
1234 irq_info_p += strlen(irq_info_p) + 1;
1235 }
1236 fdti->irqs = irq;
1237 irqs++;
1238 }
1239 if (map_mode) {
1240 j++;
1241 }
1242 }
1243 }
1244
1245 if (object_dynamic_cast(dev, TYPE_FDT_GENERIC_GPIO)) {
1246 fggc = FDT_GENERIC_GPIO_GET_CLASS(dev);
1247 gpio_set = fggc->client_gpios;
1248 }
1249
1250 if (!gpio_set) {
1251 gpio_set = default_gpio_sets;
1252 }
1253
1254 for (; object_dynamic_cast(dev, TYPE_DEVICE) && gpio_set->names;
1255 gpio_set++) {
1256 bool end = false;
1257 int cur_cell = 0;
1258
1259 for (i = 0; !end; i++) {
1260 char *debug_success;
1261 const FDTGenericGPIOConnection *c = gpio_set->gpios;
1262 const char *gpio_name = NULL;
1263 uint16_t named_idx = 0;
1264 qemu_irq input, output;
1265 memset(&input, 0, sizeof(input));
1266
1267 if (c) {
1268 uint16_t range = c->range ? c->range : 1;
1269 while ((c->fdt_index > i || c->fdt_index + range <= i)
1270 && c->name) {
1271 c++;
1272 }
1273 named_idx = i - c->fdt_index;
1274 gpio_name = c->name;
1275 }
1276 if (!gpio_name) {
1277 const char *names_propname = gpio_set->names->names_propname;
1278 gpio_name = qemu_fdt_getprop_string(fdti->fdt, node_path,
1279 names_propname, i, false,
1280 NULL);
1281 }
1282 if (!gpio_name) {
1283 input = qdev_get_gpio_in(DEVICE(dev), i);
1284 } else {
1285 input = qdev_get_gpio_in_named(DEVICE(dev), gpio_name,
1286 named_idx);
1287 }
1288 debug_success = g_strdup_printf("Wiring GPIO input %s[%" PRId16 "] "
1289 "to", gpio_name, named_idx);
1290 output = fdt_get_gpio(fdti, node_path, &cur_cell, input, gpio_set,
1291 debug_success, &end);
1292 g_free(debug_success);
1293 if (output) {
1294 FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
1295 *irq = (FDTIRQConnection) {
1296 .dev = DEVICE(dev),
1297 .name = gpio_name,
1298 .merge_fn = qemu_irq_shared_or_handler,
1299 .i = named_idx,
1300 .irq = output,
1301 .sink_info = NULL,
1302 .next = fdti->irqs
1303 };
1304 fdti->irqs = irq;
1305 DB_PRINT_NP(1, "... GPIO output %s[%" PRId16 "]\n", gpio_name,
1306 named_idx);
1307 }
1308 }
1309 }
1310
1311 if (dev_type) {
1312 g_free(dev_type);
1313 }
1314
1315 return 0;
1316}
1317
1318static const TypeInfo fdt_generic_intc_info = {
1319 .name = TYPE_FDT_GENERIC_INTC,
1320 .parent = TYPE_INTERFACE,
1321 .class_size = sizeof(FDTGenericIntcClass),
1322};
1323
1324static const TypeInfo fdt_generic_mmap_info = {
1325 .name = TYPE_FDT_GENERIC_MMAP,
1326 .parent = TYPE_INTERFACE,
1327 .class_size = sizeof(FDTGenericMMapClass),
1328};
1329
1330static const TypeInfo fdt_generic_gpio_info = {
1331 .name = TYPE_FDT_GENERIC_GPIO,
1332 .parent = TYPE_INTERFACE,
1333 .class_size = sizeof(FDTGenericGPIOClass),
1334};
1335
1336static void fdt_generic_intc_register_types(void)
1337{
1338 type_register_static(&fdt_generic_intc_info);
1339 type_register_static(&fdt_generic_mmap_info);
1340 type_register_static(&fdt_generic_gpio_info);
1341}
1342
1343type_init(fdt_generic_intc_register_types)
1344