1openprom(7D) Devices openprom(7D)
2
3
4
6 openprom - PROM monitor configuration interface
7
9 #include <sys/fcntl.h>
10
11
12 #include <sys/types.h>
13
14
15 #include <sys/openpromio.h>
16
17
18 open("/dev/openprom", mode);
19
20
22 The internal encoding of the configuration information stored in EEPROM
23 or NVRAM varies from model to model, and on some systems the encoding
24 is "hidden" by the firmware. The openprom driver provides a consistent
25 interface that allows a user or program to inspect and modify that con‐
26 figuration, using ioctl(2) requests. These requests are defined in
27 <sys/openpromio.h>:
28
29 struct openpromio {
30 uint_t oprom_size; /* real size of following data */
31 union {
32 char b[1]; /* NB: Adjacent, Null terminated */
33 int i;
34 } opio_u;
35 };
36 #define oprom_array opio_u.b /* property name/value array */
37 #define oprom_node opio_u.i /* nodeid from navigation config-ops */
38 #define oprom_len opio_u.i /* property len from OPROMGETPROPLEN */
39 #define OPROMMAXPARAM 32768 /* max size of array (advisory) */
40
41
42
43 For all ioctl(2) requests, the third parameter is a pointer to a struct
44 openpromio. All property names and values are null-terminated strings;
45 the value of a numeric option is its ASCII representation.
46
47
48 For the raw ioctl(2) operations shown below that explicitly or implic‐
49 itly specify a nodeid, an error may be returned. This is due to the
50 removal of the node from the firmware device tree by a Dynamic Recon‐
51 figuration operation. Programs should decide if the appropriate
52 response is to restart the scanning operation from the beginning or
53 terminate, informing the user that the tree has changed.
54
56 OPROMGETOPT This ioctl takes the null-terminated name of a prop‐
57 erty in the oprom_array and returns its null-termi‐
58 nated value (overlaying its name). oprom_size should
59 be set to the size of oprom_array; on return it will
60 contain the size of the returned value. If the named
61 property does not exist, or if there is not enough
62 space to hold its value, then oprom_size will be set
63 to zero. See BUGS below.
64
65
66 OPROMSETOPT This ioctl takes two adjacent strings in
67 oprom_array; the null-terminated property name fol‐
68 lowed by the null-terminated value.
69
70
71 OPROMSETOPT2 This ioctl is similar to OPROMSETOPT, except that
72 it uses the difference between the actual user array
73 size and the length of the property name plus its
74 null terminator.
75
76
77 OPROMNXTOPT This ioctl is used to retrieve properties sequen‐
78 tially. The null-terminated name of a property is
79 placed into oprom_array and on return it is replaced
80 with the null-terminated name of the next property
81 in the sequence, with oprom_size set to its length.
82 A null string on input means return the name of the
83 first property; an oprom_size of zero on output
84 means there are no more properties.
85
86
87 OPROMNXT These ioctls provide an interface to the raw con‐
88 OPROMCHILD fig_ops operations in the PROM monitor. One can use
89 OPROMGETPROP them to traverse the system device tree; see prt‐
90 OPROMNXTPROP conf(1M).
91
92
93 OPROMGETPROPLEN This ioctl provides an interface to the property
94 length raw config op. It takes the name of a prop‐
95 erty in the buffer, and returns an integer in the
96 buffer. It returns the integer -1 if the property
97 does not exist; 0 if the property exists, but has no
98 value (a boolean property); or a positive integer
99 which is the length of the property as reported by
100 the PROM monitor. See BUGS below.
101
102
103 OPROMGETVERSION This ioctl returns an arbitrary and platform-depen‐
104 dent NULL-terminated string in oprom_array, repre‐
105 senting the underlying version of the firmware.
106
107
109 EAGAIN There are too many opens of the /dev/openprom device.
110
111
112 EFAULT A bad address has been passed to an ioctl(2) routine.
113
114
115 EINVAL The size value was invalid, or (for OPROMSETOPT) the
116 property does not exist, or an invalid ioctl is being issued,
117 or the ioctl is not supported by the firmware, or the nodeid
118 specified does not exist in the firmware device tree.
119
120
121 ENOMEM The kernel could not allocate space to copy the user's struc‐
122 ture.
123
124
125 EPERM Attempts have been made to write to a read-only entity, or
126 read from a write only entity.
127
128
129 ENXIO Attempting to open a non-existent device.
130
131
133 Example 1 oprom_array Data Allocation and Reuse
134
135
136 The following example shows how the oprom_array is allocated and reused
137 for data returned by the driver.
138
139
140 /*
141 * This program opens the openprom device and prints the platform
142 * name (root node name property) and the prom version.
143 *
144 * NOTE: /dev/openprom is readable only by user 'root' or group 'sys'.
145 */
146 #include <stdio.h>
147 #include <string.h>
148 #include <fcntl.h>
149 #include <errno.h>
150 #include <unistd.h>
151 #include <stdlib.h>
152 #include <sys/openpromio.h>
153 #define min(a, b) (a < b ? a : b)
154 #define max(a, b) (a > b ? a : b)
155 #define MAXNAMESZ 32 /* Maximum property *name* size */
156 #define BUFSZ 1024 /* A Handly default buffer size */
157 #define MAXVALSZ (BUFSZ - sizeof (int))
158 static char *promdev = "/dev/openprom";
159 /*
160 * Allocate an openpromio structure big enough to contain
161 * a bufsize'd oprom_array. Zero out the structure and
162 * set the oprom_size field to bufsize.
163 */
164 static struct openpromio *
165 opp_zalloc(size_t bufsize)
166 {
167 struct openpromio *opp;
168 opp = malloc(sizeof (struct openpromio) + bufsize);
169 (void) memset(opp, 0, sizeof (struct openpromio) + bufsize);
170 opp->oprom_size = bufsize;
171 return (opp);
172 }
173 /*
174 * Free a 'struct openpromio' allocated by opp_zalloc
175 */
176 static void
177 opp_free(struct openpromio *opp)
178 {
179 free(opp);
180 }
181 /*
182 * Get the peer node of the given node. The root node is the peer of zero.
183 * After changing nodes, property lookups apply to that node. The driver
184 * 'remembers' what node you are in.
185 */
186 static int
187 peer(int nodeid, int fd)
188 {
189 struct openpromio *opp;
190 int i;
191 opp = opp_zalloc(sizeof (int));
192 opp->oprom_node = nodeid;
193 if (ioctl(fd, OPROMNEXT, opp) < 0) {
194 perror("OPROMNEXT");
195 exit(1);
196 }
197 i = opp->oprom_node;
198 opp_free(opp);
199 return(i);
200 }
201 int
202 main(void)
203 {
204 struct openpromio *opp;
205 int fd, proplen;
206 size_t buflen;
207 if ((fd = open(promdev, O_RDONLY)) < 0) {
208 fprintf(stderr, "Cannot open openprom device\n");
209 exit(1);
210 }
211 /*
212 * Get and print the length and value of the
213 * root node 'name' property
214 */
215 (void) peer(0, fd); /* Navigate to the root node */
216 /*
217 * Allocate an openpromio structure sized big enough to
218 * take the string "name" as input and return the int-sized
219 * length of the 'name' property.
220 * Then, get the length of the 'name' property.
221 */
222 buflen = max(sizeof (int), strlen("name") + 1);
223 opp = opp_zalloc(buflen);
224 (void) strcpy(opp->oprom_array, "name");
225 if (ioctl(fd, OPROMGETPROPLEN, opp) < 0) {
226 perror("OPROMGETPROPLEN");
227 /* exit(1); */
228 proplen = 0; /* down-rev driver? */
229 } else
230 proplen = opp->oprom_len;
231 opp_free(opp);
232 if (proplen == -1) {
233 printf("'name' property does not exist!\n");
234 exit (1);
235 }
236 /*
237 * Allocate an openpromio structure sized big enough
238 * to take the string 'name' as input and to return
239 * 'proplen + 1' bytes. Then, get the value of the
240 * 'name' property. Note how we make sure to size the
241 * array at least one byte more than the returned length
242 * to guarantee NULL termination.
243 */
244 buflen = (proplen ? proplen + 1 : MAXVALSZ);
245 buflen = max(buflen, strlen("name") + 1);
246 opp = opp_zalloc(buflen);
247 (void) strcpy(opp->oprom_array, "name");
248 if (ioctl(fd, OPROMGETPROP, opp) < 0) {
249 perror("OPROMGETPROP");
250 exit(1);
251 }
252 if (opp->oprom_size != 0)
253 printf("Platform name <%s> property len <%d>\n",
254 opp->oprom_array, proplen);
255 opp_free(opp);
256 /*
257 * Allocate an openpromio structure assumed to be
258 * big enough to get the 'prom version string'.
259 * Get and print the prom version.
260 */
261 opp_zalloc(MAXVALSZ);
262 opp->oprom_size = MAXVALSZ;
263 if (ioctl(fd, OPROMGETVERSION, opp) < 0) {
264 perror("OPROMGETVERSION");
265 exit(1);
266 }
267 printf("Prom version <%s>\n", opp->oprom_array);
268 opp_free(opp);
269 (void) close(fd);
270 return (0);
271 }
272
273
275 /dev/openprom PROM monitor configuration interface
276
277
279 eeprom(1M), monitor(1M), prtconf(1M), ioctl(2), mem(7D)
280
282 There should be separate return values for non-existent properties as
283 opposed to not enough space for the value.
284
285
286 An attempt to set a property to an illegal value results in the PROM
287 setting it to some legal value, with no error being returned. An
288 OPROMGETOPT should be performed after an OPROMSETOPT to verify that the
289 set worked.
290
291
292 Some PROMS lie about the property length of some string properties,
293 omitting the NULL terminator from the property length. The openprom
294 driver attempts to transparently compensate for these bugs when return‐
295 ing property values by NULL terminating an extra character in the user
296 buffer if space is available in the user buffer. This extra character
297 is excluded from the oprom_size field returned from OPROMGETPROP and
298 OPROMGETOPT and excluded in the oprom_len field returned from OPROMGET‐
299 PROPLEN but is returned in the user buffer from the calls that return
300 data, if the user buffer is allocated at least one byte larger than the
301 property length.
302
303
304
305SunOS 5.11 13 Jan 1997 openprom(7D)