xref: /illumos-gate/usr/src/cmd/amdzen/usmn.c (revision 6f1fa39e3cf1b335f342bbca41590e9d76ab29b7)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2020 Oxide Computer Company
14  */
15 
16 /*
17  * Read and write to the AMD SMN.
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <err.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <usmn.h>
29 
30 static boolean_t
31 usmn_read(int fd, const char *addr)
32 {
33 	unsigned long long l;
34 	char *eptr;
35 	usmn_reg_t usr;
36 
37 	errno = 0;
38 	l = strtoull(addr, &eptr, 16);
39 	if (errno != 0 || *eptr != '\0' || l > UINT32_MAX) {
40 		warnx("failed to parse %s: invalid string or address", addr);
41 		return (B_FALSE);
42 	}
43 
44 	usr.usr_addr = (uint32_t)l;
45 	usr.usr_data = 0;
46 
47 	if (ioctl(fd, USMN_READ, &usr) != 0) {
48 		warn("failed to read SMN at 0x%x", usr.usr_addr);
49 		return (B_FALSE);
50 	}
51 
52 	(void) printf("0x%x: 0x%x\n", usr.usr_addr, usr.usr_data);
53 	return (B_TRUE);
54 }
55 
56 int
57 main(int argc, char *argv[])
58 {
59 	int i, c, fd, ret;
60 	const char *device = NULL;
61 
62 	while ((c = getopt(argc, argv, "d:")) != -1) {
63 		switch (c) {
64 		case 'd':
65 			device = optarg;
66 			break;
67 		default:
68 			(void) fprintf(stderr, "Usage: usmn -d device addr "
69 			    "[addr]...\n"
70 			    "Note: All addresses are interpreted as hex\n");
71 			return (2);
72 		}
73 	}
74 
75 	if (device == NULL) {
76 		errx(EXIT_FAILURE, "missing required device");
77 	}
78 
79 	argc -= optind;
80 	argv += optind;
81 
82 	if (argc == 0) {
83 		errx(EXIT_FAILURE, "missing registers to read");
84 	}
85 
86 	if ((fd = open(device, O_RDONLY)) < 0) {
87 		err(EXIT_FAILURE, "failed to open %s", device);
88 	}
89 
90 	ret = EXIT_SUCCESS;
91 	for (i = 0; i < argc; i++) {
92 		if (!usmn_read(fd, argv[i])) {
93 			ret = EXIT_FAILURE;
94 		}
95 	}
96 
97 	(void) close(fd);
98 
99 	return (ret);
100 }
101