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#include "qemu/osdep.h"
28#include "hw/fdt_generic.h"
29#include "qemu/coroutine.h"
30#include "qemu/log.h"
31
32#ifndef FDT_GENERIC_ERR_DEBUG
33#define FDT_GENERIC_ERR_DEBUG 0
34#endif
35#define DB_PRINT(lvl, ...) do { \
36 if (FDT_GENERIC_ERR_DEBUG > (lvl)) { \
37 qemu_log_mask(lvl, ": %s: ", __func__); \
38 qemu_log_mask(lvl, ## __VA_ARGS__); \
39 } \
40} while (0);
41
42#define FDT_GENERIC_MAX_PATTERN_LEN 1024
43
44typedef struct TableListNode {
45 void *next;
46 char key[FDT_GENERIC_MAX_PATTERN_LEN];
47 FDTInitFn fdt_init;
48 void *opaque;
49} TableListNode;
50
51
52
53static void add_to_table(
54 FDTInitFn fdt_init,
55 const char *key,
56 void *opaque,
57 TableListNode **head_p)
58{
59 TableListNode *nn = malloc(sizeof(*nn));
60 nn->next = (void *)(*head_p);
61 strcpy(nn->key, key);
62 nn->fdt_init = fdt_init;
63 nn->opaque = opaque;
64 *head_p = nn;
65}
66
67
68
69
70
71
72
73static int fdt_init_search_table(
74 char *node_path,
75 FDTMachineInfo *fdti,
76 const char *key,
77 TableListNode **head)
78{
79 TableListNode *c = *head;
80 if (c == NULL) {
81 return 1;
82 } else if (!strcmp(key, c->key)) {
83 return c->fdt_init ? c->fdt_init(node_path, fdti, c->opaque) : 0;
84 }
85 return fdt_init_search_table(node_path, fdti, key,
86 (TableListNode **)(&(*head)->next));
87}
88
89TableListNode *compat_list_head;
90
91void add_to_compat_table(FDTInitFn fdt_init, const char *compat, void *opaque)
92{
93 add_to_table(fdt_init, compat, opaque, &compat_list_head);
94}
95
96int fdt_init_compat(char *node_path, FDTMachineInfo *fdti, const char *compat)
97{
98 return fdt_init_search_table(node_path, fdti, compat, &compat_list_head);
99}
100
101TableListNode *inst_bind_list_head;
102
103void add_to_inst_bind_table(FDTInitFn fdt_init, const char *name, void *opaque)
104{
105 add_to_table(fdt_init, name, opaque, &inst_bind_list_head);
106}
107
108int fdt_init_inst_bind(char *node_path, FDTMachineInfo *fdti,
109 const char *name)
110{
111 return fdt_init_search_table(node_path, fdti, name, &inst_bind_list_head);
112}
113
114static void dump_table(TableListNode *head)
115{
116 if (head == NULL) {
117 return;
118 }
119 printf("key : %s, opaque data %p\n", head->key, head->opaque);
120 dump_table(head->next);
121}
122
123void dump_compat_table(void)
124{
125 printf("FDT COMPATIBILITY TABLE:\n");
126 dump_table(compat_list_head);
127}
128
129void dump_inst_bind_table(void)
130{
131 printf("FDT INSTANCE BINDING TABLE:\n");
132 dump_table(inst_bind_list_head);
133}
134
135void fdt_init_yield(FDTMachineInfo *fdti)
136{
137 static int yield_index;
138 int this_yield = yield_index++;
139
140 DB_PRINT(1, "Yield #%d\n", this_yield);
141 qemu_co_queue_wait(fdti->cq);
142 DB_PRINT(1, "Unyield #%d\n", this_yield);
143}
144
145void fdt_init_set_opaque(FDTMachineInfo *fdti, char *node_path, void *opaque)
146{
147 FDTDevOpaque *dp;
148 for (dp = fdti->dev_opaques;
149 dp->node_path && strcmp(dp->node_path, node_path);
150 dp++);
151 if (!dp->node_path) {
152 dp->node_path = strdup(node_path);
153 }
154 dp->opaque = opaque;
155}
156
157int fdt_init_has_opaque(FDTMachineInfo *fdti, char *node_path)
158{
159 FDTDevOpaque *dp;
160 for (dp = fdti->dev_opaques; dp->node_path; dp++) {
161 if (!strcmp(dp->node_path, node_path)) {
162 return 1;
163 }
164 }
165 return 0;
166}
167
168void *fdt_init_get_opaque(FDTMachineInfo *fdti, char *node_path)
169{
170 FDTDevOpaque *dp;
171 for (dp = fdti->dev_opaques; dp->node_path; dp++) {
172 if (!strcmp(dp->node_path, node_path)) {
173 return dp->opaque;
174 }
175 }
176 return NULL;
177}
178
179FDTMachineInfo *fdt_init_new_fdti(void *fdt)
180{
181 FDTMachineInfo *fdti = g_malloc0(sizeof(*fdti));
182 fdti->fdt = fdt;
183 fdti->cq = g_malloc0(sizeof(*(fdti->cq)));
184 qemu_co_queue_init(fdti->cq);
185 fdti->dev_opaques = g_malloc0(sizeof(*(fdti->dev_opaques)) *
186 (devtree_get_num_nodes(fdt) + 1));
187 return fdti;
188}
189
190void fdt_init_destroy_fdti(FDTMachineInfo *fdti)
191{
192 FDTDevOpaque *dp;
193 for (dp = fdti->dev_opaques; dp->node_path; dp++) {
194 g_free(dp->node_path);
195 }
196 g_free(fdti->dev_opaques);
197 g_free(fdti);
198}
199