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