xref: /openbsd/usr.sbin/eeprom/optree.c (revision b7041c07)
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