1 /* $NetBSD: mdesc.c,v 1.7 2023/12/20 05:33:59 thorpej Exp $ */
2 /* $OpenBSD: mdesc.c,v 1.7 2014/11/30 22:26:15 kettenis Exp $ */
3 /*
4 * Copyright (c) 2009 Mark Kettenis
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/device.h>
21 #include <sys/systm.h>
22
23 #include <uvm/uvm_extern.h>
24 #include <uvm/uvm_page.h>
25
26 #include <machine/autoconf.h>
27 #include <machine/hypervisor.h>
28 #include <machine/mdesc.h>
29 #include <machine/sparc64.h>
30
31 vaddr_t mdesc;
32 paddr_t mdesc_pa;
33 size_t mdesc_len;
34
35 psize_t
mdesc_get_len(void)36 mdesc_get_len(void)
37 {
38 psize_t len = 0;
39
40 len = 0;
41 hv_mach_desc(0, &len);
42 KASSERT(len != 0);
43
44 return len;
45 }
46
47 void
mdesc_init(vaddr_t va,paddr_t pa,psize_t avail_len)48 mdesc_init(vaddr_t va, paddr_t pa, psize_t avail_len)
49 {
50 psize_t len;
51 int64_t err;
52
53 len = avail_len;
54 err = hv_mach_desc(pa, &len);
55 if (err != H_EOK)
56 panic("hv_mach_desc() failed - err = %" PRId64 "\n", err);
57 KASSERT(len <= avail_len);
58 mdesc = (vaddr_t)va;
59 mdesc_pa = pa;
60 mdesc_len = len;
61
62 return;
63 }
64
65 uint64_t
mdesc_get_prop_val(int idx,const char * name)66 mdesc_get_prop_val(int idx, const char *name)
67 {
68 struct md_header *hdr;
69 struct md_element *elem;
70 const char *name_blk;
71 const char *str;
72
73 hdr = (struct md_header *)mdesc;
74 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
75 name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
76
77 while (elem[idx].tag != 'E') {
78 str = name_blk + elem[idx].name_offset;
79 if (elem[idx].tag == 'v' && strcmp(str, name) == 0)
80 return (elem[idx].d.val);
81 idx++;
82 }
83
84 return (-1);
85 }
86
87 const char *
mdesc_get_prop_str(int idx,const char * name)88 mdesc_get_prop_str(int idx, const char *name)
89 {
90 struct md_header *hdr;
91 struct md_element *elem;
92 const char *name_blk;
93 const char *data_blk;
94 const char *str;
95
96 hdr = (struct md_header *)mdesc;
97 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
98 name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
99 data_blk = name_blk + hdr->name_blk_sz;
100
101 while (elem[idx].tag != 'E') {
102 str = name_blk + elem[idx].name_offset;
103 if (elem[idx].tag == 's' && strcmp(str, name) == 0)
104 return (data_blk + elem[idx].d.y.data_offset);
105 idx++;
106 }
107
108 return (NULL);
109 }
110
111 const char *
mdesc_get_prop_data(int idx,const char * name,size_t * len)112 mdesc_get_prop_data(int idx, const char *name, size_t *len)
113 {
114 struct md_header *hdr;
115 struct md_element *elem;
116 const char *name_blk;
117 const char *data_blk;
118 const char *str;
119
120 hdr = (struct md_header *)mdesc;
121 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
122 name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
123 data_blk = name_blk + hdr->name_blk_sz;
124
125 while (elem[idx].tag != 'E') {
126 str = name_blk + elem[idx].name_offset;
127 if (elem[idx].tag == 'd' && strcmp(str, name) == 0) {
128 *len = elem[idx].d.y.data_len;
129 return (data_blk + elem[idx].d.y.data_offset);
130 }
131 idx++;
132 }
133
134 return (NULL);
135 }
136
137 int
mdesc_find(const char * name,uint64_t cfg_handle)138 mdesc_find(const char *name, uint64_t cfg_handle)
139 {
140 struct md_header *hdr;
141 struct md_element *elem;
142 const char *str;
143 uint64_t val;
144 int idx;
145
146 hdr = (struct md_header *)mdesc;
147 (void)hdr; /* XXX avoid compiler warning */
148 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
149
150 for (idx = 0; elem[idx].tag == 'N'; idx = elem[idx].d.val) {
151 str = mdesc_get_prop_str(idx, "name");
152 val = mdesc_get_prop_val(idx, "cfg-handle");
153 if (str && strcmp(str, name) == 0 && val == cfg_handle)
154 return (idx);
155 }
156
157 return (-1);
158 }
159
160 int
mdesc_find_child(int idx,const char * name,uint64_t cfg_handle)161 mdesc_find_child(int idx, const char *name, uint64_t cfg_handle)
162 {
163 struct md_header *hdr;
164 struct md_element *elem;
165 const char *name_blk;
166 const char *str;
167 uint64_t val;
168 int arc;
169
170 hdr = (struct md_header *)mdesc;
171 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
172 name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
173
174 for (; elem[idx].tag != 'E'; idx++) {
175 str = name_blk + elem[idx].name_offset;
176 if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
177 continue;
178
179 arc = elem[idx].d.val;
180 str = mdesc_get_prop_str(arc, "name");
181 val = mdesc_get_prop_val(arc, "cfg-handle");
182 if (str && strcmp(str, name) == 0 && val == cfg_handle)
183 return (arc);
184 }
185
186 return (-1);
187 }
188
189 int
mdesc_find_node_by_idx(int idx,const char * name)190 mdesc_find_node_by_idx(int idx, const char *name)
191 {
192 struct md_header *hdr;
193 struct md_element *elem;
194 const char *name_blk;
195 const char *str;
196
197 hdr = (struct md_header *)mdesc;
198 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
199 name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
200
201 for ( ; elem[idx].tag == 'N'; idx = elem[idx].d.val) {
202 str = name_blk + elem[idx].name_offset;
203 if (str && strcmp(str, name) == 0)
204 return (idx);
205 }
206
207 return (-1);
208 }
209
210 int
mdesc_find_node(const char * name)211 mdesc_find_node(const char *name)
212 {
213 return mdesc_find_node_by_idx(0, name);
214 }
215
216 int
mdesc_next_node(int idx)217 mdesc_next_node(int idx)
218 {
219 struct md_element *elem;
220
221 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
222
223 return elem[idx].d.val;
224 }
225
226 const char *
mdesc_name_by_idx(int idx)227 mdesc_name_by_idx(int idx)
228 {
229 struct md_header *hdr;
230 struct md_element *elem;
231 const char *name_blk;
232 const char *str;
233
234 hdr = (struct md_header *)mdesc;
235 elem = (struct md_element *)(mdesc + sizeof(struct md_header));
236 name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
237
238 str = name_blk + elem[idx].name_offset;
239
240 return str;
241
242 }
243
244
245
246