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
31vaddr_t mdesc;
32paddr_t mdesc_pa;
33size_t mdesc_len;
34
35psize_t
36mdesc_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
47void
48mdesc_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
65uint64_t
66mdesc_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
87const char *
88mdesc_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
111const char *
112mdesc_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
137int
138mdesc_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
160int
161mdesc_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
189int
190mdesc_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
210int
211mdesc_find_node(const char *name)
212{
213	return mdesc_find_node_by_idx(0, name);
214}
215
216int
217mdesc_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
226const char *
227mdesc_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