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 "qemu/error-report.h"
37#include "sysemu/sysemu.h"
38#include "sysemu/reset.h"
39#include "qemu/cutils.h"
40#include "sysemu/blockdev.h"
41#include "sysemu/block-backend.h"
42#include "chardev/char.h"
43#include "qemu/log.h"
44#include "qemu/config-file.h"
45#include "block/block.h"
46#include "hw/ssi/ssi.h"
47#include "hw/boards.h"
48#include "qemu/option.h"
49#include "hw/qdev-properties.h"
50
51#ifndef FDT_GENERIC_UTIL_ERR_DEBUG
52#define FDT_GENERIC_UTIL_ERR_DEBUG 3
53#endif
54#define DB_PRINT(lvl, ...) do { \
55 if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
56 qemu_log_mask(LOG_FDT, ": %s: ", __func__); \
57 qemu_log_mask(LOG_FDT, ## __VA_ARGS__); \
58 } \
59} while (0);
60
61#define DB_PRINT_NP(lvl, ...) do { \
62 if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
63 qemu_log_mask(LOG_FDT, "%s", node_path); \
64 DB_PRINT((lvl), ## __VA_ARGS__); \
65 } \
66} while (0);
67
68#include "hw/remote-port-device.h"
69#include "hw/remote-port.h"
70
71
72
73#include <libfdt.h>
74#include <stdlib.h>
75
76int fdt_serial_ports;
77
78static int simple_bus_fdt_init(char *bus_node_path, FDTMachineInfo *fdti);
79
80static void fdt_get_irq_info_from_intc(FDTMachineInfo *fdti, qemu_irq *ret,
81 char *intc_node_path,
82 uint32_t *cells, uint32_t num_cells,
83 uint32_t max, Error **errp);
84
85
86typedef struct QEMUIRQSharedState {
87 qemu_irq sink;
88 int num;
89 bool (*merge_fn)(bool *, int);
90
91#define MAX_IRQ_SHARED_INPUTS 128
92 bool inputs[MAX_IRQ_SHARED_INPUTS];
93} QEMUIRQSharedState;
94
95static bool qemu_irq_shared_or_handler(bool *inputs, int n)
96{
97 int i;
98
99 assert(n < MAX_IRQ_SHARED_INPUTS);
100
101 for (i = 0; i < n; ++i) {
102 if (inputs[i]) {
103 return true;
104 }
105 }
106 return false;
107}
108
109static bool qemu_irq_shared_and_handler(bool *inputs, int n)
110{
111 int i;
112
113 assert(n < MAX_IRQ_SHARED_INPUTS);
114
115 for (i = 0; i < n; ++i) {
116 if (!inputs[i]) {
117 return false;
118 }
119 }
120 return true;
121}
122
123static void qemu_irq_shared_handler(void *opaque, int n, int level)
124{
125 QEMUIRQSharedState *s = opaque;
126
127 assert(n < MAX_IRQ_SHARED_INPUTS);
128 s->inputs[n] = level;
129 qemu_set_irq(s->sink, s->merge_fn(s->inputs, s->num));
130}
131
132static void fdt_init_all_irqs(FDTMachineInfo *fdti)
133{
134 while (fdti->irqs) {
135 FDTIRQConnection *first = fdti->irqs;
136 qemu_irq sink = first->irq;
137 bool (*merge_fn)(bool *, int) = first->merge_fn;
138 int num_sources = 0;
139 FDTIRQConnection *irq;
140
141 for (irq = first; irq; irq = irq->next) {
142 if (irq->irq == sink) {
143 num_sources++;
144 }
145 }
146 if (num_sources > 1) {
147 QEMUIRQSharedState *s = g_malloc0(sizeof *s);
148 s->sink = sink;
149 s->merge_fn = merge_fn;
150 qemu_irq *sources = qemu_allocate_irqs(qemu_irq_shared_handler, s,
151 num_sources);
152 for (irq = first; irq; irq = irq->next) {
153 if (irq->irq == sink) {
154 char *shared_irq_name = g_strdup_printf("shared-irq-%p",
155 *sources);
156
157 if (irq->merge_fn != merge_fn) {
158 fprintf(stderr, "ERROR: inconsistent IRQ merge fns\n");
159 exit(1);
160 }
161
162 object_property_add_child(OBJECT(irq->dev), shared_irq_name,
163 OBJECT(*sources));
164 g_free(shared_irq_name);
165 irq->irq = *(sources++);
166 s->num++;
167 }
168 }
169 }
170 DB_PRINT(0, "%s: connected to %s irq line %d (%s)\n",
171 first->sink_info ? first->sink_info : "",
172 object_get_canonical_path(OBJECT(first->dev)),
173 first->i, first->name ? first->name : "");
174
175 qdev_connect_gpio_out_named(DEVICE(first->dev), first->name, first->i,
176 first->irq);
177 fdti->irqs = first->next;
178 g_free(first);
179 }
180}
181
182static void fdt_init_cpu_clusters(FDTMachineInfo *fdti)
183{
184 FDTCPUCluster *cl = fdti->clusters;
185
186 while (cl) {
187 qdev_init_nofail(DEVICE(cl->cpu_cluster));
188 cl = cl->next;
189 }
190}
191
192FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq)
193{
194 char node_path[DT_PATH_LENGTH];
195 FDTMachineInfo *fdti = fdt_init_new_fdti(fdt);
196
197 fdti->irq_base = cpu_irq;
198
199 fdt_serial_ports = 0;
200
201
202 if (!qemu_devtree_get_root_node(fdt, node_path)) {
203 memory_region_transaction_begin();
204 fdt_init_set_opaque(fdti, node_path, NULL);
205 simple_bus_fdt_init(node_path, fdti);
206 while (qemu_co_enter_next(fdti->cq, NULL));
207 fdt_init_cpu_clusters(fdti);
208 fdt_init_all_irqs(fdti);
209 memory_region_transaction_commit();
210 } else {
211 fprintf(stderr, "FDT: ERROR: cannot get root node from device tree %s\n"
212 , node_path);
213 }
214
215
216 current_machine->smp.cores = fdt_generic_num_cpus;
217 current_machine->smp.cpus = fdt_generic_num_cpus;
218 current_machine->smp.max_cpus = fdt_generic_num_cpus;
219
220 bdrv_drain_all();
221 DB_PRINT(0, "FDT: Device tree scan complete\n");
222 return fdti;
223}
224
225struct FDTInitNodeArgs {
226 char *node_path;
227 char *parent_path;
228 FDTMachineInfo *fdti;
229};
230
231static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat);
232
233static int check_compat(const char *prefix, const char *compat,
234 char *node_path, FDTMachineInfo *fdti)
235{
236 char *compat_prefixed = g_strconcat(prefix, compat, NULL);
237 const int done = !fdt_init_compat(node_path, fdti, compat_prefixed);
238 g_free(compat_prefixed);
239 return done;
240}
241
242static void fdt_init_node(void *args)
243{
244 struct FDTInitNodeArgs *a = args;
245 char *node_path = a->node_path;
246 FDTMachineInfo *fdti = a->fdti;
247 g_free(a);
248
249 simple_bus_fdt_init(node_path, fdti);
250
251 char *all_compats = NULL, *node_name;
252 char *device_type = NULL;
253 int compat_len;
254
255 DB_PRINT_NP(1, "enter\n");
256
257
258 node_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
259 DB_PRINT_NP(1, "node with name: %s\n", node_name ? node_name : "(none)");
260 if (!node_name) {
261 printf("FDT: ERROR: nameless node: %s\n", node_path);
262 }
263 if (!fdt_init_inst_bind(node_path, fdti, node_name)) {
264 DB_PRINT_NP(0, "instance bind successful\n");
265 goto exit;
266 }
267
268
269 all_compats = qemu_fdt_getprop(fdti->fdt, node_path, "compatible",
270 &compat_len, false, NULL);
271 if (all_compats) {
272 char *compat = all_compats;
273 char * const end = &all_compats[compat_len - 1];
274
275 while (compat < end) {
276 if (check_compat("compatible:", compat, node_path, fdti)) {
277 goto exit;
278 }
279
280 if (!fdt_init_qdev(node_path, fdti, compat)) {
281 goto exit;
282 }
283
284
285 while (compat < end && *compat) {
286 ++compat;
287 }
288
289
290 if (compat < end) {
291 *compat++ = ' ';
292 }
293 };
294 } else {
295 DB_PRINT_NP(0, "no compatibility found\n");
296 }
297
298
299
300
301
302 device_type = qemu_fdt_getprop(fdti->fdt, node_path,
303 "device_type", NULL, false, NULL);
304 if (device_type) {
305 if (check_compat("device_type:", device_type, node_path, fdti)) {
306 goto exit;
307 }
308
309 if (!fdt_init_qdev(node_path, fdti, device_type)) {
310 goto exit;
311 }
312 }
313
314 if (all_compats) {
315 DB_PRINT_NP(0, "FDT: Unsupported peripheral invalidated - "
316 "compatibilities %s\n", all_compats);
317 qemu_fdt_setprop_string(fdti->fdt, node_path, "compatible",
318 "invalidated");
319 }
320exit:
321
322 DB_PRINT_NP(1, "exit\n");
323
324 if (!fdt_init_has_opaque(fdti, node_path)) {
325 fdt_init_set_opaque(fdti, node_path, NULL);
326 }
327 g_free(node_path);
328 g_free(all_compats);
329 g_free(device_type);
330 return;
331}
332
333static int simple_bus_fdt_init(char *node_path, FDTMachineInfo *fdti)
334{
335 int i;
336 int num_children = qemu_devtree_get_num_children(fdti->fdt, node_path,
337 1);
338 char **children;
339
340 if (num_children == 0) {
341 return 0;
342 }
343 children = qemu_devtree_get_children(fdti->fdt, node_path, 1);
344
345 DB_PRINT_NP(num_children ? 0 : 1, "num child devices: %d\n", num_children);
346
347 for (i = 0; i < num_children; i++) {
348 struct FDTInitNodeArgs *init_args = g_malloc0(sizeof(*init_args));
349 init_args->node_path = children[i];
350 init_args->fdti = fdti;
351 qemu_coroutine_enter(qemu_coroutine_create(fdt_init_node, init_args));
352 }
353
354 g_free(children);
355 return 0;
356}
357
358static qemu_irq fdt_get_gpio(FDTMachineInfo *fdti, char *node_path,
359 int* cur_cell, qemu_irq input,
360 const FDTGenericGPIOSet *gpio_set,
361 const char *debug_success, bool *end) {
362 void *fdt = fdti->fdt;
363 uint32_t parent_phandle, parent_cells = 0, cells[32];
364 char parent_node_path[DT_PATH_LENGTH];
365 DeviceState *parent;
366 int i;
367 Error *errp = NULL;
368 const char *reason = NULL;
369 bool free_reason = false;
370 const char *propname = gpio_set->names->propname;
371 const char *cells_propname = gpio_set->names->cells_propname;
372
373 cells[0] = 0;
374
375 parent_phandle = qemu_fdt_getprop_cell(fdt, node_path, propname,
376 (*cur_cell)++, false, &errp);
377 if (errp) {
378 reason = g_strdup_printf("Cant get phandle from \"%s\" property\n",
379 propname);
380 *end = true;
381 free_reason = true;
382 goto fail_silent;
383 }
384 if (qemu_devtree_get_node_by_phandle(fdt, parent_node_path,
385 parent_phandle)) {
386 *end = true;
387 reason = "cant get node from phandle\n";
388 goto fail;
389 }
390 parent_cells = qemu_fdt_getprop_cell(fdt, parent_node_path,
391 cells_propname, 0, false, &errp);
392 if (errp) {
393 *end = true;
394 reason = g_strdup_printf("cant get the property \"%s\" from the " \
395 "parent \"%s\"\n",
396 cells_propname, parent_node_path);
397 free_reason = true;
398 goto fail;
399 }
400
401 for (i = 0; i < parent_cells; ++i) {
402 cells[i] = qemu_fdt_getprop_cell(fdt, node_path, propname,
403 (*cur_cell)++, false, &errp);
404 if (errp) {
405 *end = true;
406 reason = "cant get cell value";
407 goto fail;
408 }
409 }
410
411 while (!fdt_init_has_opaque(fdti, parent_node_path)) {
412 fdt_init_yield(fdti);
413 }
414 parent = DEVICE(fdt_init_get_opaque(fdti, parent_node_path));
415
416 if (!parent) {
417 reason = "parent is not a device";
418 goto fail_silent;
419 }
420
421 while (!parent->realized) {
422 fdt_init_yield(fdti);
423 }
424
425 {
426 const FDTGenericGPIOConnection *fgg_con = NULL;
427 uint16_t range, idx;
428 const char *gpio_name = NULL;
429 qemu_irq ret;
430
431 if (object_dynamic_cast(OBJECT(parent), TYPE_FDT_GENERIC_GPIO)) {
432 const FDTGenericGPIOSet *set;
433 FDTGenericGPIOClass *parent_fggc =
434 FDT_GENERIC_GPIO_GET_CLASS(parent);
435
436 for (set = parent_fggc->controller_gpios; set && set->names;
437 set++) {
438 if (!strcmp(gpio_set->names->cells_propname,
439 set->names->cells_propname)) {
440 fgg_con = set->gpios;
441 break;
442 }
443 }
444 }
445
446
447 idx = cells[0] & ~(1ul << 31);
448 if (fgg_con) {
449 range = fgg_con->range ? fgg_con->range : 1;
450 while (!(idx >= fgg_con->fdt_index
451 && idx < (fgg_con->fdt_index + range))
452 && fgg_con->name) {
453 fgg_con++;
454 range = fgg_con->range ? fgg_con->range : 1;
455 }
456
457 idx -= fgg_con->fdt_index;
458 gpio_name = fgg_con->name;
459 }
460
461 if (input) {
462 FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
463 bool (*merge_fn)(bool *, int) = qemu_irq_shared_or_handler;
464
465
466
467
468
469 if (cells[0] & (1 << 31)) {
470 merge_fn = qemu_irq_shared_and_handler;
471 }
472
473 DB_PRINT_NP(1, "%s GPIO output %s[%d] on %s\n", debug_success,
474 gpio_name ? gpio_name : "unnamed", idx,
475 parent_node_path);
476 *irq = (FDTIRQConnection) {
477 .dev = parent,
478 .name = gpio_name,
479 .merge_fn = merge_fn,
480 .i = idx,
481 .irq = input,
482 .sink_info = NULL,
483 .next = fdti->irqs
484 };
485 fdti->irqs = irq;
486 }
487
488 if (!strcmp(propname, "interrupts-extended") &&
489 object_dynamic_cast(OBJECT(parent), TYPE_FDT_GENERIC_INTC) &&
490 parent_cells > 1) {
491 qemu_irq *irqs = g_new0(qemu_irq, fdt_generic_num_cpus);
492 int i;
493
494 fdt_get_irq_info_from_intc(fdti, irqs, parent_node_path, cells,
495 parent_cells, fdt_generic_num_cpus, &errp);
496 if (errp) {
497 reason = "failed to create gpio connection";
498 goto fail;
499 }
500
501 ret = NULL;
502 for (i = 0; i < fdt_generic_num_cpus; i++) {
503 if (irqs[i]) {
504 ret = irqs[i];
505 break;
506 }
507 }
508 g_free(irqs);
509 } else {
510 ret = qdev_get_gpio_in_named(parent, gpio_name, idx);
511 }
512
513 if (ret) {
514 DB_PRINT_NP(1, "wiring GPIO input %s on %s ...\n",
515 fgg_con ? fgg_con->name : "unnamed", parent_node_path);
516 }
517 return ret;
518 }
519fail:
520 if (reason) {
521 fprintf(stderr, "%s Failed: %s\n", node_path, reason);
522 }
523
524fail_silent:
525 if (free_reason) {
526 g_free((void *)reason);
527 }
528 return NULL;
529}
530
531static void fdt_get_irq_info_from_intc(FDTMachineInfo *fdti, qemu_irq *ret,
532 char *intc_node_path,
533 uint32_t *cells, uint32_t num_cells,
534 uint32_t max, Error **errp)
535{
536 FDTGenericIntcClass *intc_fdt_class;
537 DeviceState *intc;
538
539 while (!fdt_init_has_opaque(fdti, intc_node_path)) {
540 fdt_init_yield(fdti);
541 }
542 intc = DEVICE(fdt_init_get_opaque(fdti, intc_node_path));
543
544 if (!intc) {
545 goto fail;
546 }
547
548 while (!intc->realized) {
549 fdt_init_yield(fdti);
550 }
551
552 intc_fdt_class = FDT_GENERIC_INTC_GET_CLASS(intc);
553 if (!intc_fdt_class) {
554 goto fail;
555 }
556
557 intc_fdt_class->get_irq(FDT_GENERIC_INTC(intc), ret, cells, num_cells,
558 max, errp);
559
560 return;
561fail:
562 error_setg(errp, "%s", __func__);
563}
564
565static uint32_t imap_cache[32 * 1024];
566static bool imap_cached = false;
567
568qemu_irq *fdt_get_irq_info(FDTMachineInfo *fdti, char *node_path, int irq_idx,
569 char *info, bool *map_mode) {
570 void *fdt = fdti->fdt;
571 uint32_t intc_phandle, intc_cells, cells[32];
572 char intc_node_path[DT_PATH_LENGTH];
573 qemu_irq *ret = NULL;
574 int i;
575 Error *errp = NULL;
576
577 intc_phandle = qemu_fdt_getprop_cell(fdt, node_path, "interrupt-parent",
578 0, true, &errp);
579 if (errp) {
580 errp = NULL;
581 intc_cells = qemu_fdt_getprop_cell(fdt, node_path,
582 "#interrupt-cells", 0, true, &errp);
583 *map_mode = true;
584 } else {
585 if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
586 intc_phandle)) {
587 goto fail;
588 }
589
590
591 qemu_fdt_getprop_cell(fdt, node_path, "interrupt-map-mask", 0,
592 false, &errp);
593 if (!errp) {
594 errp = NULL;
595 intc_cells = qemu_fdt_getprop_cell(fdt, node_path,
596 "#interrupt-cells", 0,
597 true, &errp);
598 *map_mode = true;
599 } else {
600 errp = NULL;
601 intc_cells = qemu_fdt_getprop_cell(fdt, intc_node_path,
602 "#interrupt-cells", 0,
603 true, &errp);
604 *map_mode = false;
605 }
606 }
607
608 if (errp) {
609 goto fail;
610 }
611
612 DB_PRINT_NP(2, "%s intc_phandle: %d\n", node_path, intc_phandle);
613
614 for (i = 0; i < intc_cells; ++i) {
615 cells[i] = qemu_fdt_getprop_cell(fdt, node_path, "interrupts",
616 intc_cells * irq_idx + i, false, &errp);
617 if (errp) {
618 goto fail;
619 }
620 }
621
622 if (*map_mode) {
623 int k;
624 ret = g_new0(qemu_irq, 1);
625 int num_matches = 0;
626 int len;
627 uint32_t imap_mask[intc_cells];
628 uint32_t *imap_p;
629 uint32_t *imap;
630 bool use_parent = false;
631
632 for (k = 0; k < intc_cells; ++k) {
633 imap_mask[k] = qemu_fdt_getprop_cell(fdt, node_path,
634 "interrupt-map-mask", k + 2,
635 true, &errp);
636 if (errp) {
637 goto fail;
638 }
639 }
640
641
642 imap = qemu_fdt_getprop(fdt, node_path, "interrupt-map", &len,
643 use_parent, &errp);
644
645 if (!imap || errp) {
646
647
648
649 use_parent = true;
650 errp = NULL;
651
652 imap_p = qemu_fdt_getprop(fdt, node_path, "interrupt-map",
653 &len, use_parent, &errp);
654 if (!imap_cached) {
655 memcpy(imap_cache, imap_p, len);
656 imap_cached = true;
657 }
658 imap = imap_cache;
659
660 if (errp) {
661 goto fail;
662 }
663 }
664
665 len /= sizeof(uint32_t);
666
667 i = 0;
668 assert(imap);
669 while (i < len) {
670 if (!use_parent) {
671
672
673
674 imap = qemu_fdt_getprop(fdt, node_path, "interrupt-map", &len,
675 use_parent, &errp);
676
677 if (errp) {
678 goto fail;
679 }
680
681 len /= sizeof(uint32_t);
682 }
683
684 bool match = true;
685 uint32_t new_intc_cells, new_cells[32];
686 i++; i++;
687 for (k = 0; k < intc_cells; ++k) {
688 uint32_t map_val = be32_to_cpu(imap[i++]);
689 if ((cells[k] ^ map_val) & imap_mask[k]) {
690 match = false;
691 }
692 }
693
694
695
696
697 intc_phandle = be32_to_cpu(imap[i++]);
698 if (intc_phandle & (0xffu << 24)) {
699 new_intc_cells = (intc_phandle >> 24) - 1;
700 } else {
701 if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
702 intc_phandle)) {
703 goto fail;
704 }
705 new_intc_cells = qemu_fdt_getprop_cell(fdt, intc_node_path,
706 "#interrupt-cells", 0,
707 false, &errp);
708 imap[i - 1] = cpu_to_be32(intc_phandle |
709 (new_intc_cells + 1) << 24);
710 if (errp) {
711 goto fail;
712 }
713 }
714 for (k = 0; k < new_intc_cells; ++k) {
715 new_cells[k] = be32_to_cpu(imap[i++]);
716 }
717 if (match) {
718 num_matches++;
719 ret = g_renew(qemu_irq, ret, num_matches + 1);
720 if (intc_phandle & (0xffu << 24)) {
721 if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
722 intc_phandle &
723 ((1 << 24) - 1))) {
724 goto fail;
725 }
726 }
727
728 DB_PRINT_NP(2, "Getting IRQ information: %s -> 0x%x (%s)\n",
729 node_path, intc_phandle, intc_node_path);
730
731 memset(&ret[num_matches], 0, sizeof(*ret));
732 fdt_get_irq_info_from_intc(fdti, &ret[num_matches-1], intc_node_path,
733 new_cells, new_intc_cells, 1, &errp);
734 if (info) {
735 sprintf(info, "%s", intc_node_path);
736 info += strlen(info) + 1;
737 }
738 if (errp) {
739 goto fail;
740 }
741 }
742 }
743 return ret;
744 }
745
746 DB_PRINT_NP(2, "Getting IRQ information: %s -> %s\n",
747 node_path, intc_node_path);
748
749 ret = g_new0(qemu_irq, fdt_generic_num_cpus + 2);
750 fdt_get_irq_info_from_intc(fdti, ret, intc_node_path, cells, intc_cells,
751 fdt_generic_num_cpus, &errp);
752
753 if (errp) {
754 goto fail;
755 }
756
757
758 if (info) {
759 sprintf(info, "%s", intc_node_path);
760 }
761
762 return ret;
763
764fail:
765 if (errp) {
766 sprintf(info, "%s", error_get_pretty(errp));
767 } else {
768 sprintf(info, "(none)");
769 }
770 return NULL;
771}
772
773qemu_irq *fdt_get_irq(FDTMachineInfo *fdti, char *node_path, int irq_idx,
774 bool *map_mode)
775{
776 return fdt_get_irq_info(fdti, node_path, irq_idx, NULL, map_mode);
777}
778
779
780
781#define DIGIT(a) ((a) >= '0' && (a) <= '9')
782#define LOWER_CASE(a) ((a) >= 'a' && (a) <= 'z')
783
784static void trim_version(char *x)
785{
786 long result;
787
788 for (;;) {
789 x = strchr(x, '-');
790 if (!x) {
791 return;
792 }
793 if (DIGIT(x[1])) {
794
795 const char *p;
796
797 qemu_strtol(x + 1, &p, 0, &result);
798
799 if ( *p == '.') {
800 *x = 0;
801 return;
802 } else if ( *p == 0) {
803 return;
804 }
805 } else if (x[1] == 'r' && x[3] == 'p') {
806
807 if (DIGIT(x[2]) && DIGIT(x[4])) {
808 *x = 0;
809 return;
810 }
811 }
812 x++;
813 }
814}
815
816static void substitute_char(char *s, char a, char b)
817{
818 for (;;) {
819 s = strchr(s, a);
820 if (!s) {
821 return;
822 }
823 *s = b;
824 s++;
825 }
826}
827
828static inline const char *trim_vendor(const char *s)
829{
830
831 const char *ret = memchr(s, ',', strlen(s));
832 return ret ? ret + 1 : s;
833}
834
835
836
837
838
839
840
841
842
843
844
845
846
847static bool fdt_attach_blockdev(FDTMachineInfo *fdti,
848 char *node_path, Object *dev)
849{
850 static const char propname[] = "blockdev-node-name";
851 BlockBackend *bdev = NULL;
852 char *label;
853
854
855 label = qemu_fdt_getprop(fdti->fdt, node_path, propname,
856 NULL, false, NULL);
857
858
859 if (!label) {
860 return false;
861 }
862
863
864
865
866
867
868 if (!label[0]) {
869 error_setg(&error_abort, "FDT-node '%s': property '%s' = <empty>",
870 node_path, propname);
871 goto ret;
872 }
873
874 bdev = blk_by_name(label);
875 if (!bdev) {
876 goto ret;
877 }
878
879 if (blk_legacy_dinfo(bdev)) {
880 error_setg(&error_abort,
881 "FDT-node '%s': property '%s' = \"%s\" matched to"
882 " a '-drive' option. Must use -blockdev instead.",
883 node_path, propname, label);
884 goto ret;
885 }
886
887 qdev_prop_set_drive(DEVICE(dev), "drive", bdev, &error_abort);
888
889 ret:
890 g_free(label);
891 return true;
892}
893
894static void fdt_attach_drive(FDTMachineInfo *fdti, char *node_path,
895 Object *dev, BlockInterfaceType drive_type)
896{
897 DriveInfo *dinfo = NULL;
898 uint32_t *di_val = NULL;
899 int di_len = 0;
900
901
902 if (!object_property_find(OBJECT(dev), "drive", NULL)) {
903 return;
904 }
905
906
907 if (fdt_attach_blockdev(fdti, node_path, dev)) {
908 return;
909 }
910
911
912
913
914
915 di_val = qemu_fdt_getprop(fdti->fdt, node_path, "drive-index",
916 &di_len, false, NULL);
917
918 if (di_val && (di_len == sizeof(*di_val))) {
919 dinfo = drive_get_by_index(drive_type, be32_to_cpu(*di_val));
920 } else {
921 dinfo = drive_get_next(drive_type);
922 }
923
924 if (dinfo) {
925 qdev_prop_set_drive(DEVICE(dev), "drive",
926 blk_by_legacy_dinfo(dinfo), &error_abort);
927 }
928
929 return;
930}
931
932static Object *fdt_create_from_compat(const char *compat, char **dev_type)
933{
934 Object *ret = NULL;
935 char *c = g_strdup(compat);
936
937
938 ret = object_new(c);
939
940 if (!ret) {
941
942 trim_version(c);
943 ret = object_new(c);
944
945 if (!ret) {
946
947 substitute_char(c, ',', '.');
948 ret = object_new(c);
949 }
950 }
951
952 if (!ret) {
953
954
955
956 g_free(c);
957 c = g_strdup(compat);
958 substitute_char(c, ',', '.');
959 ret = object_new(c);
960 }
961
962 if (dev_type) {
963 *dev_type = c;
964 } else {
965 g_free(c);
966 }
967
968 if (!ret) {
969 const char *no_vendor = trim_vendor(compat);
970
971 if (no_vendor != compat) {
972 return fdt_create_from_compat(no_vendor, dev_type);
973 }
974 }
975 return ret;
976}
977
978
979
980static inline uint64_t get_int_be(const void *p, int len)
981{
982 switch (len) {
983 case 1:
984 return *((uint8_t *)p);
985 case 2:
986 return be16_to_cpu(*((uint16_t *)p));
987 case 4:
988 return be32_to_cpu(*((uint32_t *)p));
989 case 8:
990 return be32_to_cpu(*((uint64_t *)p));
991 default:
992 fprintf(stderr, "unsupported integer length\n");
993 abort();
994 }
995}
996
997
998
999static const char *fdt_generic_reg_size_prop_names[] = {
1000 "#address-cells",
1001 "#size-cells",
1002 "#bus-cells",
1003 "#priority-cells",
1004};
1005
1006static const int fdt_generic_reg_cells_defaults[] = {
1007 1,
1008 1,
1009 0,
1010 0,
1011};
1012
1013
1014
1015
1016
1017
1018
1019static void fdt_dev_error(FDTMachineInfo *fdti, char *node_path, char *compat)
1020{
1021 char *abort_on_error;
1022 char *warn_on_error;
1023
1024 warn_on_error = qemu_fdt_getprop(fdti->fdt, node_path,
1025 "qemu-fdt-warn-on-error", 0,
1026 true, NULL);
1027 abort_on_error = qemu_fdt_getprop(fdti->fdt, node_path,
1028 "qemu-fdt-abort-on-error", 0,
1029 true, NULL);
1030 if (warn_on_error) {
1031 if (strncmp("device_type", compat, strlen("device_type"))) {
1032 warn_report("%s: %s", compat, warn_on_error);
1033 }
1034 }
1035
1036 if (abort_on_error) {
1037 error_report("Failed to create %s", compat);
1038 error_setg(&error_fatal, "%s", abort_on_error);
1039 }
1040}
1041
1042static void fdt_init_qdev_array_prop(Object *obj, QEMUDevtreeProp *prop)
1043{
1044 const char *propname = prop->name;
1045 const uint32_t *v32 = prop->value;
1046 int nr = prop->len;
1047 Error *local_err = NULL;
1048 char *len_name;
1049
1050 if (!v32 || !nr || (nr % 4)) {
1051 return;
1052 }
1053 nr /= 4;
1054
1055
1056
1057
1058
1059
1060
1061 len_name = g_strconcat(PROP_ARRAY_LEN_PREFIX, propname, NULL);
1062 object_property_set_int(obj, nr, len_name, &local_err);
1063 g_free(len_name);
1064
1065 if (local_err) {
1066 error_free(local_err);
1067 return;
1068 }
1069
1070 while (nr--) {
1071 char *elem_name = g_strdup_printf("%s[%d]", propname, nr);
1072
1073 object_property_set_int(obj, get_int_be(&v32[nr], 4), elem_name,
1074 &error_abort);
1075 g_free(elem_name);
1076 }
1077}
1078
1079static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat)
1080{
1081 Object *dev, *parent;
1082 char *dev_type = NULL;
1083 int is_intc;
1084 Error *errp = NULL;
1085 int i, j;
1086 QEMUDevtreeProp *prop, *props;
1087 char parent_node_path[DT_PATH_LENGTH];
1088 const FDTGenericGPIOSet *gpio_set = NULL;
1089 FDTGenericGPIOClass *fggc = NULL;
1090
1091 if (!compat) {
1092 return 1;
1093 }
1094 dev = fdt_create_from_compat(compat, &dev_type);
1095 if (!dev) {
1096 DB_PRINT_NP(1, "no match found for %s\n", compat);
1097 fdt_dev_error(fdti, node_path, compat);
1098 return 1;
1099 }
1100 DB_PRINT_NP(1, "matched compat %s\n", compat);
1101
1102
1103 if (object_dynamic_cast(dev, TYPE_CPU)) {
1104 fdt_generic_num_cpus++;
1105 DB_PRINT_NP(0, "is a CPU - total so far %d\n", fdt_generic_num_cpus);
1106 }
1107
1108 if (qemu_devtree_getparent(fdti->fdt, parent_node_path, node_path)) {
1109 abort();
1110 }
1111 while (!fdt_init_has_opaque(fdti, parent_node_path)) {
1112 fdt_init_yield(fdti);
1113 }
1114 if (object_dynamic_cast(dev, TYPE_CPU)) {
1115 parent = fdt_init_get_cpu_cluster(fdti, compat);
1116 } else {
1117 parent = fdt_init_get_opaque(fdti, parent_node_path);
1118 }
1119 if (dev->parent) {
1120 DB_PRINT_NP(0, "Node already parented - skipping node\n");
1121 } else if (parent) {
1122 DB_PRINT_NP(1, "parenting node\n");
1123 object_property_add_child(OBJECT(parent),
1124 qemu_devtree_get_node_name(fdti->fdt, node_path),
1125 OBJECT(dev));
1126 if (object_dynamic_cast(dev, TYPE_DEVICE)) {
1127 Object *parent_bus = parent;
1128 unsigned int depth = 0;
1129
1130 DB_PRINT_NP(1, "bus parenting node\n");
1131
1132 while (parent_bus && !object_dynamic_cast(parent_bus, TYPE_BUS)) {
1133
1134
1135
1136
1137 assert(depth < 4096);
1138
1139 parent_bus = parent_bus->parent;
1140 depth++;
1141 }
1142
1143 if (!parent_bus
1144 && object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) {
1145
1146
1147
1148
1149
1150 parent_bus = OBJECT(sysbus_get_default());
1151 }
1152
1153 if (parent_bus) {
1154 qdev_set_parent_bus(DEVICE(dev), BUS(parent_bus));
1155 }
1156 }
1157 } else {
1158 DB_PRINT_NP(1, "orphaning node\n");
1159
1160 object_property_add_child(
1161 object_get_root(),
1162 qemu_devtree_get_node_name(fdti->fdt, node_path),
1163 OBJECT(dev));
1164 }
1165 fdt_init_set_opaque(fdti, node_path, dev);
1166
1167
1168
1169 if (global_sync_quantum) {
1170 ObjectProperty *p;
1171
1172 p = object_property_find(OBJECT(dev), "sync-quantum", NULL);
1173 if (p) {
1174 object_property_set_int(OBJECT(dev), global_sync_quantum,
1175 "sync-quantum", &errp);
1176 }
1177 }
1178
1179
1180 if (object_dynamic_cast(dev, TYPE_FDT_GENERIC_PROPS)) {
1181 FDTGenericPropsClass *k = FDT_GENERIC_PROPS_GET_CLASS(dev);
1182
1183 assert(k->set_props);
1184 k->set_props(OBJECT(dev), &error_fatal);
1185 }
1186
1187 props = qemu_devtree_get_props(fdti->fdt, node_path);
1188 for (prop = props; prop->name; prop++) {
1189 const char *propname = trim_vendor(prop->name);
1190 int len = prop->len;
1191 void *val = prop->value;
1192 ObjectProperty *p = NULL;
1193#ifdef _WIN32
1194 QEMUDevtreeProp *wp;
1195 char *winPropname = g_strdup_printf("windows-%s", propname);
1196 wp = qemu_devtree_prop_search(props, winPropname);
1197 if (wp) {
1198 g_free(prop->value);
1199 prop->len = wp->len;
1200 prop->value = g_memdup(wp->value, wp->len);
1201 val = prop->value;
1202 len = prop->len;
1203 DB_PRINT_NP(1, "Found windows property match: %s\n",
1204 winPropname);
1205 }
1206 g_free(winPropname);
1207#endif
1208 p = object_property_find(OBJECT(dev), propname, NULL);
1209 if (p) {
1210 DB_PRINT_NP(1, "matched property: %s of type %s, len %d\n",
1211 propname, p->type, prop->len);
1212 }
1213 if (!p) {
1214 fdt_init_qdev_array_prop(dev, prop);
1215 continue;
1216 }
1217
1218 if (!strcmp(propname, "type")) {
1219 continue;
1220 }
1221
1222
1223 if (!strcmp(propname, "chardev") && !strcmp(p->type, "str")) {
1224 const char *chardev = val;
1225 const char *chardevs_end = chardev + len;
1226
1227 assert(errp == NULL);
1228 while (chardev < chardevs_end) {
1229 object_property_set_str(OBJECT(dev), (const char *)chardev,
1230 propname, &errp);
1231 if (!errp) {
1232 DB_PRINT_NP(0, "set property %s to %s\n", propname,
1233 chardev);
1234 break;
1235 }
1236 chardev += strlen(chardev) + 1;
1237 errp = NULL;
1238 }
1239 assert(errp == NULL);
1240 continue;
1241 }
1242
1243
1244 if (!strcmp(p->type, "uint8") || !strcmp(p->type, "uint16") ||
1245 !strcmp(p->type, "uint32") || !strcmp(p->type, "uint64")) {
1246 object_property_set_int(OBJECT(dev), get_int_be(val, len), propname,
1247 &error_abort);
1248 DB_PRINT_NP(0, "set property %s to %#llx\n", propname,
1249 (unsigned long long)get_int_be(val, len));
1250 } else if (!strcmp(p->type, "boolean") || !strcmp(p->type, "bool")) {
1251 object_property_set_bool(OBJECT(dev), !!get_int_be(val, len),
1252 propname, &error_abort);
1253 DB_PRINT_NP(0, "set property %s to %s\n", propname,
1254 get_int_be(val, len) ? "true" : "false");
1255 } else if (!strcmp(p->type, "string") || !strcmp(p->type, "str")) {
1256 object_property_set_str(OBJECT(dev), (const char *)val, propname,
1257 &error_abort);
1258 DB_PRINT_NP(0, "set property %s to %s\n", propname,
1259 (const char *)val);
1260 } else if (!strncmp(p->type, "link", 4)) {
1261 char target_node_path[DT_PATH_LENGTH];
1262 char propname_target[1024];
1263 strcpy(propname_target, propname);
1264 strcat(propname_target, "-target");
1265
1266 Object *linked_dev, *proxy;
1267
1268 if (qemu_devtree_get_node_by_phandle(fdti->fdt, target_node_path,
1269 get_int_be(val, len))) {
1270 abort();
1271 }
1272 while (!fdt_init_has_opaque(fdti, target_node_path)) {
1273 fdt_init_yield(fdti);
1274 }
1275 linked_dev = fdt_init_get_opaque(fdti, target_node_path);
1276
1277 proxy = linked_dev ? object_property_get_link(linked_dev,
1278 propname_target,
1279 &errp) : NULL;
1280 if (!errp && proxy) {
1281 DB_PRINT_NP(0, "detected proxy object for %s connection\n",
1282 propname);
1283 linked_dev = proxy;
1284 }
1285 errp = NULL;
1286 if (linked_dev) {
1287 object_property_set_link(OBJECT(dev), linked_dev, propname,
1288 &errp);
1289 if (errp) {
1290
1291
1292
1293 MemoryRegion *alias_mr;
1294 int offset = len / 2;
1295 alias_mr =
1296 sysbus_mmio_get_region(SYS_BUS_DEVICE(linked_dev),
1297 get_int_be(val + offset,
1298 len - offset));
1299
1300 object_property_set_link(OBJECT(dev), OBJECT(alias_mr),
1301 propname, &error_abort);
1302
1303 errp = NULL;
1304 }
1305 DB_PRINT_NP(0, "set link %s\n", propname);
1306 }
1307 } else {
1308 DB_PRINT_NP(0, "WARNING: property is of unknown type\n");
1309 }
1310 }
1311
1312
1313 if (object_dynamic_cast(dev, TYPE_REMOTE_PORT_DEVICE)) {
1314 int i;
1315
1316 for (i = 0;;++i) {
1317 char adaptor_node_path[DT_PATH_LENGTH];
1318 uint32_t adaptor_phandle, chan;
1319 DeviceState *adaptor;
1320 char *name;
1321
1322 adaptor_phandle = qemu_fdt_getprop_cell(fdti->fdt, node_path,
1323 "remote-ports",
1324 2 * i, false, &errp);
1325 if (errp) {
1326 DB_PRINT_NP(1, "cant get phandle from \"remote-ports\" "
1327 "property\n");
1328 break;
1329 }
1330 if (qemu_devtree_get_node_by_phandle(fdti->fdt, adaptor_node_path,
1331 adaptor_phandle)) {
1332 DB_PRINT_NP(1, "cant get node from phandle\n");
1333 break;
1334 }
1335 while (!fdt_init_has_opaque(fdti, adaptor_node_path)) {
1336 fdt_init_yield(fdti);
1337 }
1338 adaptor = DEVICE(fdt_init_get_opaque(fdti, adaptor_node_path));
1339 name = g_strdup_printf("rp-adaptor%" PRId32, i);
1340 object_property_set_link(OBJECT(dev), OBJECT(adaptor), name, &errp);
1341 DB_PRINT_NP(0, "connecting RP to adaptor %s channel %d",
1342 object_get_canonical_path(OBJECT(adaptor)), i);
1343 g_free(name);
1344 if (errp) {
1345 DB_PRINT_NP(1, "cant set adaptor link for device property\n");
1346 break;
1347 }
1348
1349 chan = qemu_fdt_getprop_cell(fdti->fdt, node_path, "remote-ports",
1350 2 * i + 1, false, &errp);
1351 if (errp) {
1352 DB_PRINT_NP(1, "cant get channel from \"remote-ports\" "
1353 "property\n");
1354 break;
1355 }
1356
1357 name = g_strdup_printf("rp-chan%" PRId32, i);
1358 object_property_set_int(OBJECT(dev), chan, name, &errp);
1359
1360
1361
1362 if (errp) {
1363 DB_PRINT_NP(1, "cant set %s property %s\n", name, error_get_pretty(errp));
1364 errp = NULL;
1365 }
1366 g_free(name);
1367
1368 name = g_strdup_printf("remote-port-dev%d", chan);
1369 object_property_set_link(OBJECT(adaptor), OBJECT(dev), name,
1370 &errp);
1371 g_free(name);
1372 if (errp) {
1373 DB_PRINT_NP(1, "cant set device link for adaptor\n");
1374 break;
1375 }
1376 }
1377 errp = NULL;
1378 }
1379
1380 if (object_dynamic_cast(dev, TYPE_DEVICE)) {
1381 DeviceClass *dc = DEVICE_GET_CLASS(dev);
1382
1383 static int nics;
1384 const char *short_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
1385
1386 if (object_property_find(OBJECT(dev), "mac", NULL) &&
1387 object_property_find(OBJECT(dev), "netdev", NULL)) {
1388 qdev_set_nic_properties(DEVICE(dev), &nd_table[nics]);
1389 }
1390 if (nd_table[nics].instantiated) {
1391 DB_PRINT_NP(0, "NIC instantiated: %s\n", dev_type);
1392 nics++;
1393 }
1394
1395
1396
1397
1398 if (!object_dynamic_cast(dev, TYPE_REMOTE_PORT)) {
1399
1400 if (fdt_serial_ports < serial_max_hds() && serial_hd(fdt_serial_ports)) {
1401 Chardev *value = (Chardev*) serial_hd(fdt_serial_ports);
1402 char *chardev;
1403
1404
1405 chardev = object_property_get_str(dev, "chardev", &errp);
1406 if (!errp && !strcmp(chardev, "")) {
1407 object_property_set_str(dev, value->label,
1408 "chardev", &errp);
1409 if (!errp) {
1410
1411 fdt_serial_ports++;
1412 }
1413 }
1414 errp = NULL;
1415 }
1416 }
1417
1418
1419
1420
1421 if (object_dynamic_cast(dev, TYPE_SSI_SLAVE)) {
1422 fdt_attach_drive(fdti, node_path, dev, IF_MTD);
1423 }
1424
1425
1426 DB_PRINT_NP(0, "Short naming node: %s\n", short_name);
1427 (DEVICE(dev))->id = g_strdup(short_name);
1428 qdev_init_nofail(DEVICE(dev));
1429 qemu_register_reset((void (*)(void *))dc->reset, dev);
1430 }
1431
1432 if (object_dynamic_cast(dev, TYPE_SYS_BUS_DEVICE) ||
1433 object_dynamic_cast(dev, TYPE_FDT_GENERIC_MMAP)) {
1434 FDTGenericRegPropInfo reg = {0};
1435 char parent_path[DT_PATH_LENGTH];
1436 int cell_idx = 0;
1437 bool extended = true;
1438
1439 qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg-extended", 0, false,
1440 &errp);
1441 if (errp) {
1442 error_free(errp);
1443 errp = NULL;
1444 extended = false;
1445 qemu_devtree_getparent(fdti->fdt, parent_path, node_path);
1446 }
1447
1448 for (reg.n = 0;; reg.n++) {
1449 char ph_parent[DT_PATH_LENGTH];
1450 const char *pnp = parent_path;
1451
1452 reg.parents = g_renew(Object *, reg.parents, reg.n + 1);
1453 reg.parents[reg.n] = parent;
1454
1455 if (extended) {
1456 int p_ph = qemu_fdt_getprop_cell(fdti->fdt, node_path,
1457 "reg-extended", cell_idx++,
1458 false, &errp);
1459 if (errp) {
1460 error_free(errp);
1461 errp = NULL;
1462 goto exit_reg_parse;
1463 }
1464 if (qemu_devtree_get_node_by_phandle(fdti->fdt, ph_parent,
1465 p_ph)) {
1466 goto exit_reg_parse;
1467 }
1468 while (!fdt_init_has_opaque(fdti, ph_parent)) {
1469 fdt_init_yield(fdti);
1470 }
1471 reg.parents[reg.n] = fdt_init_get_opaque(fdti, ph_parent);
1472 pnp = ph_parent;
1473 }
1474
1475 for (i = 0; i < FDT_GENERIC_REG_TUPLE_LENGTH; ++i) {
1476 const char *size_prop_name = fdt_generic_reg_size_prop_names[i];
1477 int nc = qemu_fdt_getprop_cell(fdti->fdt, pnp, size_prop_name,
1478 0, true, &errp);
1479
1480 if (errp) {
1481 int size_default = fdt_generic_reg_cells_defaults[i];
1482
1483 DB_PRINT_NP(0, "WARNING: no %s for %s container, assuming "
1484 "default of %d\n", size_prop_name, pnp,
1485 size_default);
1486 nc = size_default;
1487 error_free(errp);
1488 errp = NULL;
1489 }
1490
1491 reg.x[i] = g_renew(uint64_t, reg.x[i], reg.n + 1);
1492 reg.x[i][reg.n] = nc ?
1493 qemu_fdt_getprop_sized_cell(fdti->fdt, node_path,
1494 extended ? "reg-extended"
1495 : "reg",
1496 cell_idx, nc, &errp)
1497 : 0;
1498 cell_idx += nc;
1499 if (errp) {
1500 goto exit_reg_parse;
1501 }
1502 }
1503 }
1504exit_reg_parse:
1505
1506 if (object_dynamic_cast(dev, TYPE_FDT_GENERIC_MMAP)) {
1507 FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_GET_CLASS(dev);
1508 if (fmc->parse_reg) {
1509 while (fmc->parse_reg(FDT_GENERIC_MMAP(dev), reg,
1510 &error_abort)) {
1511 fdt_init_yield(fdti);
1512 }
1513 }
1514 }
1515 }
1516
1517 if (object_dynamic_cast(dev, TYPE_SYS_BUS_DEVICE)) {
1518 {
1519 int len;
1520 fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
1521 "interrupt-controller", &len);
1522 is_intc = len >= 0;
1523 DB_PRINT_NP(is_intc ? 0 : 1, "is interrupt controller: %c\n",
1524 is_intc ? 'y' : 'n');
1525 }
1526
1527 j = 0;
1528 for (i = 0;; i++) {
1529 char irq_info[6 * 1024];
1530 char *irq_info_p = irq_info;
1531 bool map_mode;
1532 int len = -1;
1533 qemu_irq *irqs = fdt_get_irq_info(fdti, node_path, i, irq_info,
1534 &map_mode);
1535
1536 fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
1537 "interrupts-extended", &len);
1538 if (!irqs && is_intc && i == 0 && len <= 0) {
1539 FDTGenericIntc *id = (FDTGenericIntc *)object_dynamic_cast(
1540 dev, TYPE_FDT_GENERIC_INTC);
1541 FDTGenericIntcClass *idc = FDT_GENERIC_INTC_GET_CLASS(id);
1542 if (id && idc->auto_parent) {
1543
1544
1545
1546
1547
1548
1549 while (!DEVICE(first_cpu)) {
1550 fdt_init_yield(fdti);
1551 }
1552 Error *err = NULL;
1553 idc->auto_parent(id, &err);
1554 } else {
1555 irqs = fdti->irq_base;
1556 }
1557 }
1558 if (!irqs) {
1559 break;
1560 }
1561 while (*irqs) {
1562 FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
1563 *irq = (FDTIRQConnection) {
1564 .dev = DEVICE(dev),
1565 .name = SYSBUS_DEVICE_GPIO_IRQ,
1566 .merge_fn = qemu_irq_shared_or_handler,
1567 .i = j,
1568 .irq = *irqs,
1569 .sink_info = g_strdup(irq_info_p),
1570 .next = fdti->irqs
1571 };
1572 if (!map_mode) {
1573 j++;
1574 } else {
1575 irq_info_p += strlen(irq_info_p) + 1;
1576 }
1577 fdti->irqs = irq;
1578 irqs++;
1579 }
1580 if (map_mode) {
1581 j++;
1582 }
1583 }
1584 }
1585
1586 if (object_dynamic_cast(dev, TYPE_FDT_GENERIC_GPIO)) {
1587 fggc = FDT_GENERIC_GPIO_GET_CLASS(dev);
1588 gpio_set = fggc->client_gpios;
1589 }
1590
1591 if (!gpio_set) {
1592 gpio_set = default_gpio_sets;
1593 }
1594
1595 for (; object_dynamic_cast(dev, TYPE_DEVICE) && gpio_set->names;
1596 gpio_set++) {
1597 bool end = false;
1598 int cur_cell = 0;
1599
1600 for (i = 0; !end; i++) {
1601 char *debug_success;
1602 const FDTGenericGPIOConnection *c = gpio_set->gpios;
1603 const char *gpio_name = NULL;
1604 uint16_t named_idx = 0;
1605 qemu_irq input, output;
1606 memset(&input, 0, sizeof(input));
1607
1608 if (c) {
1609 uint16_t range = c->range ? c->range : 1;
1610 while ((c->fdt_index > i || c->fdt_index + range <= i)
1611 && c->name) {
1612 c++;
1613 }
1614 named_idx = i - c->fdt_index;
1615 gpio_name = c->name;
1616 }
1617 if (!gpio_name) {
1618 const char *names_propname = gpio_set->names->names_propname;
1619 gpio_name = qemu_fdt_getprop_string(fdti->fdt, node_path,
1620 names_propname, i, false,
1621 NULL);
1622 }
1623 if (!gpio_name) {
1624 input = qdev_get_gpio_in(DEVICE(dev), i);
1625 } else {
1626 input = qdev_get_gpio_in_named(DEVICE(dev), gpio_name,
1627 named_idx);
1628 }
1629 debug_success = g_strdup_printf("Wiring GPIO input %s[%" PRId16 "] "
1630 "to", gpio_name, named_idx);
1631 output = fdt_get_gpio(fdti, node_path, &cur_cell, input, gpio_set,
1632 debug_success, &end);
1633 g_free(debug_success);
1634 if (output) {
1635 FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
1636 *irq = (FDTIRQConnection) {
1637 .dev = DEVICE(dev),
1638 .name = gpio_name,
1639 .merge_fn = qemu_irq_shared_or_handler,
1640 .i = named_idx,
1641 .irq = output,
1642 .sink_info = NULL,
1643 .next = fdti->irqs
1644 };
1645 fdti->irqs = irq;
1646 DB_PRINT_NP(1, "... GPIO output %s[%" PRId16 "]\n", gpio_name,
1647 named_idx);
1648 }
1649 }
1650 }
1651
1652 if (dev_type) {
1653 g_free(dev_type);
1654 }
1655
1656 return 0;
1657}
1658
1659static const TypeInfo fdt_generic_intc_info = {
1660 .name = TYPE_FDT_GENERIC_INTC,
1661 .parent = TYPE_INTERFACE,
1662 .class_size = sizeof(FDTGenericIntcClass),
1663};
1664
1665static const TypeInfo fdt_generic_mmap_info = {
1666 .name = TYPE_FDT_GENERIC_MMAP,
1667 .parent = TYPE_INTERFACE,
1668 .class_size = sizeof(FDTGenericMMapClass),
1669};
1670
1671static const TypeInfo fdt_generic_gpio_info = {
1672 .name = TYPE_FDT_GENERIC_GPIO,
1673 .parent = TYPE_INTERFACE,
1674 .class_size = sizeof(FDTGenericGPIOClass),
1675};
1676
1677static const TypeInfo fdt_generic_props_info = {
1678 .name = TYPE_FDT_GENERIC_PROPS,
1679 .parent = TYPE_INTERFACE,
1680 .class_size = sizeof(FDTGenericPropsClass),
1681};
1682
1683static void fdt_generic_intc_register_types(void)
1684{
1685 type_register_static(&fdt_generic_intc_info);
1686 type_register_static(&fdt_generic_mmap_info);
1687 type_register_static(&fdt_generic_gpio_info);
1688 type_register_static(&fdt_generic_props_info);
1689}
1690
1691type_init(fdt_generic_intc_register_types)
1692