1*b7041c07Sderaadt /* $OpenBSD: optree.c,v 1.11 2021/10/24 21:24:18 deraadt Exp $ */
2ab95fc2fSfgsch
3ab95fc2fSfgsch /*
4ab95fc2fSfgsch * Copyright (c) 2007 Federico G. Schwindt <fgsch@openbsd.org>
5ab95fc2fSfgsch *
6d9d4c371Sfgsch * Permission to use, copy, modify, and distribute this software for
7d9d4c371Sfgsch * any purpose with or without fee is hereby granted, provided that
8d9d4c371Sfgsch * the above copyright notice and this permission notice appear in all
9d9d4c371Sfgsch * copies.
10ab95fc2fSfgsch *
11d9d4c371Sfgsch * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12d9d4c371Sfgsch * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13d9d4c371Sfgsch * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14d9d4c371Sfgsch * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15d9d4c371Sfgsch * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
16d9d4c371Sfgsch * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17d9d4c371Sfgsch * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18d9d4c371Sfgsch * PERFORMANCE OF THIS SOFTWARE.
19ab95fc2fSfgsch */
20ab95fc2fSfgsch
21ab95fc2fSfgsch #include <sys/ioctl.h>
22ab95fc2fSfgsch #include <err.h>
23c0b08a13Smiod #include <errno.h>
24ab95fc2fSfgsch #include <fcntl.h>
25ab95fc2fSfgsch #include <stdio.h>
26ab95fc2fSfgsch #include <string.h>
27ab95fc2fSfgsch #include <unistd.h>
28ab95fc2fSfgsch
29fa530530Skettenis #include <machine/openpromio.h>
30fa530530Skettenis
31fa530530Skettenis #include "defs.h"
32fa530530Skettenis
33ab95fc2fSfgsch extern char *path_openprom;
34ab95fc2fSfgsch
35ab95fc2fSfgsch static void
op_print(struct opiocdesc * opio,int depth)36ab95fc2fSfgsch op_print(struct opiocdesc *opio, int depth)
37ab95fc2fSfgsch {
38ab95fc2fSfgsch char *p;
399081d4b3Skettenis int i, multi, special;
40addda549Skettenis uint32_t cell;
41ab95fc2fSfgsch
42ab95fc2fSfgsch opio->op_name[opio->op_namelen] = '\0';
43ab95fc2fSfgsch printf("%*s%s: ", depth * 4, " ", opio->op_name);
44ab95fc2fSfgsch if (opio->op_buflen > 0) {
45ab95fc2fSfgsch opio->op_buf[opio->op_buflen] = '\0';
469081d4b3Skettenis multi = special = 0;
47ab95fc2fSfgsch
48c15362c8Skettenis /*
499081d4b3Skettenis * On macppc we have string-values properties that end
509081d4b3Skettenis * with multiple NUL characters, and the serial number
519081d4b3Skettenis * has them embedded within the string.
52c15362c8Skettenis */
53c3448910Sfgsch if (opio->op_buf[0] != '\0') {
54ab95fc2fSfgsch for (i = 0; i < opio->op_buflen; i++) {
55ab95fc2fSfgsch p = &opio->op_buf[i];
56c15362c8Skettenis if (*p >= ' ' && *p <= '~')
57c15362c8Skettenis continue;
58c15362c8Skettenis if (*p == '\0') {
59c15362c8Skettenis if (i + 1 < opio->op_buflen)
60c15362c8Skettenis p++;
619081d4b3Skettenis if (*p >= ' ' && *p <= '~') {
629081d4b3Skettenis special = multi;
63c15362c8Skettenis continue;
649081d4b3Skettenis }
659081d4b3Skettenis if (*p == '\0') {
669081d4b3Skettenis multi = 1;
67c15362c8Skettenis continue;
68c15362c8Skettenis }
699081d4b3Skettenis }
70c15362c8Skettenis
71ab95fc2fSfgsch special = 1;
72ab95fc2fSfgsch break;
73ab95fc2fSfgsch }
74c3448910Sfgsch } else {
75c3448910Sfgsch if (opio->op_buflen > 1)
76c3448910Sfgsch special = 1;
77c3448910Sfgsch }
78ab95fc2fSfgsch
799081d4b3Skettenis if (special && strcmp(opio->op_name, "serial-number") != 0) {
80ab95fc2fSfgsch for (i = 0; opio->op_buflen - i >= sizeof(int);
81ab95fc2fSfgsch i += sizeof(int)) {
82ab95fc2fSfgsch if (i)
83ab95fc2fSfgsch printf(".");
84addda549Skettenis cell = *(uint32_t *)&opio->op_buf[i];
85addda549Skettenis printf("%08x", betoh32(cell));
86ab95fc2fSfgsch }
87ab95fc2fSfgsch if (i < opio->op_buflen) {
88c3448910Sfgsch if (i)
89ab95fc2fSfgsch printf(".");
90ab95fc2fSfgsch for (; i < opio->op_buflen; i++) {
91ab95fc2fSfgsch printf("%02x",
92ab95fc2fSfgsch *(u_char *)&opio->op_buf[i]);
93ab95fc2fSfgsch }
94ab95fc2fSfgsch }
95ab95fc2fSfgsch } else {
96ab95fc2fSfgsch for (i = 0; i < opio->op_buflen;
97ab95fc2fSfgsch i += strlen(&opio->op_buf[i]) + 1) {
98c15362c8Skettenis if (i && strlen(&opio->op_buf[i]) == 0)
99c15362c8Skettenis continue;
100ab95fc2fSfgsch if (i)
101ab95fc2fSfgsch printf(" + ");
102ab95fc2fSfgsch printf("'%s'", &opio->op_buf[i]);
103ab95fc2fSfgsch }
104ab95fc2fSfgsch }
105c0b08a13Smiod } else if(opio->op_buflen < 0)
106c0b08a13Smiod printf("too large");
107ab95fc2fSfgsch printf("\n");
108ab95fc2fSfgsch }
109ab95fc2fSfgsch
110ab95fc2fSfgsch void
op_nodes(int fd,int node,int depth)111ab95fc2fSfgsch op_nodes(int fd, int node, int depth)
112ab95fc2fSfgsch {
113fa530530Skettenis char op_buf[BUFSIZE * 8];
114fa530530Skettenis char op_name[BUFSIZE];
115ab95fc2fSfgsch struct opiocdesc opio;
116ab95fc2fSfgsch
11786989bc3Skettenis memset(op_name, 0, sizeof(op_name));
118ab95fc2fSfgsch opio.op_nodeid = node;
119ab95fc2fSfgsch opio.op_buf = op_buf;
120ab95fc2fSfgsch opio.op_name = op_name;
121ab95fc2fSfgsch
122ab95fc2fSfgsch if (!node) {
123df69c215Sderaadt if (ioctl(fd, OPIOCGETNEXT, &opio) == -1)
124ab95fc2fSfgsch err(1, "OPIOCGETNEXT");
125ab95fc2fSfgsch node = opio.op_nodeid;
126ab95fc2fSfgsch } else
127ab95fc2fSfgsch printf("\n%*s", depth * 4, " ");
128ab95fc2fSfgsch
129ab95fc2fSfgsch printf("Node 0x%x\n", node);
130ab95fc2fSfgsch
131ab95fc2fSfgsch for (;;) {
132ab95fc2fSfgsch opio.op_buflen = sizeof(op_buf);
133ab95fc2fSfgsch opio.op_namelen = sizeof(op_name);
134ab95fc2fSfgsch
135ab95fc2fSfgsch /* Get the next property. */
136df69c215Sderaadt if (ioctl(fd, OPIOCNEXTPROP, &opio) == -1)
137ab95fc2fSfgsch err(1, "OPIOCNEXTPROP");
138ab95fc2fSfgsch
139ab95fc2fSfgsch op_buf[opio.op_buflen] = '\0';
140ab95fc2fSfgsch (void)strlcpy(op_name, op_buf, sizeof(op_name));
141ab95fc2fSfgsch opio.op_namelen = strlen(op_name);
142ab95fc2fSfgsch
143ab95fc2fSfgsch /* If it's the last, punt. */
144ab95fc2fSfgsch if (opio.op_namelen == 0)
145ab95fc2fSfgsch break;
146ab95fc2fSfgsch
147ab95fc2fSfgsch bzero(op_buf, sizeof(op_buf));
148ab95fc2fSfgsch opio.op_buflen = sizeof(op_buf);
149ab95fc2fSfgsch
150ab95fc2fSfgsch /* And its value. */
151df69c215Sderaadt if (ioctl(fd, OPIOCGET, &opio) == -1) {
152c0b08a13Smiod if (errno != ENOMEM)
153ab95fc2fSfgsch err(1, "OPIOCGET");
154ab95fc2fSfgsch
155c0b08a13Smiod opio.op_buflen = -1; /* for op_print */
156c0b08a13Smiod }
157c0b08a13Smiod
158ab95fc2fSfgsch op_print(&opio, depth + 1);
159ab95fc2fSfgsch }
160ab95fc2fSfgsch
161ab95fc2fSfgsch /* Get next child. */
162df69c215Sderaadt if (ioctl(fd, OPIOCGETCHILD, &opio) == -1)
163ab95fc2fSfgsch err(1, "OPIOCGETCHILD");
164ab95fc2fSfgsch if (opio.op_nodeid)
165ab95fc2fSfgsch op_nodes(fd, opio.op_nodeid, depth + 1);
166ab95fc2fSfgsch
167ab95fc2fSfgsch /* Get next node/sibling. */
168ab95fc2fSfgsch opio.op_nodeid = node;
169df69c215Sderaadt if (ioctl(fd, OPIOCGETNEXT, &opio) == -1)
170ab95fc2fSfgsch err(1, "OPIOCGETNEXT");
171ab95fc2fSfgsch if (opio.op_nodeid)
172ab95fc2fSfgsch op_nodes(fd, opio.op_nodeid, depth);
173ab95fc2fSfgsch }
174ab95fc2fSfgsch
175ab95fc2fSfgsch void
op_tree(void)176ab95fc2fSfgsch op_tree(void)
177ab95fc2fSfgsch {
178ab95fc2fSfgsch int fd;
179ab95fc2fSfgsch
180*b7041c07Sderaadt if ((fd = open(path_openprom, O_RDONLY)) == -1)
181ab95fc2fSfgsch err(1, "open: %s", path_openprom);
182ab95fc2fSfgsch op_nodes(fd, 0, 0);
183ab95fc2fSfgsch (void)close(fd);
184ab95fc2fSfgsch }
185