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