xref: /titanic_52/usr/src/cmd/picl/plugins/sun4u/lw8/fruaccess/libfruaccess.c (revision 03831d35f7499c87d51205817c93e9a8d42c4bae)
1  /*
2   * CDDL HEADER START
3   *
4   * The contents of this file are subject to the terms of the
5   * Common Development and Distribution License (the "License").
6   * You may not use this file except in compliance with the License.
7   *
8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9   * or http://www.opensolaris.org/os/licensing.
10   * See the License for the specific language governing permissions
11   * and limitations under the License.
12   *
13   * When distributing Covered Code, include this CDDL HEADER in each
14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15   * If applicable, add the following below this CDDL HEADER, with the
16   * fields enclosed by brackets "[]" replaced with your own identifying
17   * information: Portions Copyright [yyyy] [name of copyright owner]
18   *
19   * CDDL HEADER END
20   */
21  
22  /*
23   * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24   * Use is subject to license terms.
25   */
26  
27  #pragma ident	"%Z%%M%	%I%	%E% SMI"
28  
29  #include <stdio.h>
30  #include <errno.h>
31  #include <fcntl.h>
32  #include <unistd.h>
33  #include <stdlib.h>
34  #include <stdarg.h>
35  #include <strings.h>
36  #include <limits.h>
37  #include <syslog.h>
38  #include <sys/open.h>
39  #include <string.h>
40  #include <alloca.h>
41  #include <libintl.h>
42  #include <sys/stat.h>
43  #include <sys/systeminfo.h>
44  #include <picl.h>
45  #include <picltree.h>
46  #include <fru_access.h>
47  #include <sys/sgfrutree.h>
48  
49  /*
50   * these functions will overlay the symbol table of libfruaccess
51   * at runtime
52   */
53  container_hdl_t	fru_open_container(picl_nodehdl_t fru);
54  int		fru_close_container(container_hdl_t fru);
55  int		fru_get_num_sections(container_hdl_t container,
56  		    door_cred_t *cred);
57  int		fru_get_sections(container_hdl_t container, section_t *section,
58  		    int max_sections, door_cred_t *cred);
59  int		fru_get_num_segments(section_hdl_t section, door_cred_t *cred);
60  int		fru_get_segments(section_hdl_t section, segment_t *segment,
61  		    int max_segments, door_cred_t *cred);
62  int		fru_add_segment(section_hdl_t section, segment_t *segment,
63  		    section_hdl_t *newsection, door_cred_t *cred);
64  int		fru_delete_segment(segment_hdl_t segment,
65  		    section_hdl_t *newsection, door_cred_t *cred);
66  ssize_t		fru_read_segment(segment_hdl_t segment, void *buffer,
67  		    size_t nbytes, door_cred_t *cred);
68  ssize_t		fru_write_segment(segment_hdl_t segment, const void *data,
69  		    size_t nbytes, segment_hdl_t *newsegment,
70  		    door_cred_t *cred);
71  int		fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred);
72  int		fru_get_packets(segment_hdl_t segment, packet_t *packet,
73  		    int max_packets, door_cred_t *cred);
74  int		fru_update_payload(packet_hdl_t packet, const void *data,
75  		    size_t nbytes, packet_hdl_t *newpacket, door_cred_t *cred);
76  int		fru_append_packet(segment_hdl_t segment, packet_t *packet,
77  		    const void *payload, size_t nbytes,
78  		    segment_hdl_t *newsegment, door_cred_t *cred);
79  int		fru_delete_packet(packet_hdl_t packet,
80  		    segment_hdl_t *newsegment, door_cred_t *cred);
81  int 		fru_is_data_available(picl_nodehdl_t fru);
82  
83  #define	PICL_PROP_SC_HANDLE	"SC_handle"
84  #define	PICL_PROP_DATA_AVAIL	"FRUDataAvailable"
85  #define	MAX_LINE_SIZE		1024
86  
87  #define	OPENDEVFRU gettext("fru_open_dev: open of %s failed %s")
88  #define	GETPV gettext("fru_open_container: ptree_get_propval_by_name failed %s")
89  
90  static int
91  fru_open_dev(void)
92  {
93  	static int opendevfru = 0;
94  	static int frufd = 0;
95  
96  	if ((opendevfru == 0) && (frufd == 0)) {
97  		if ((frufd = open(FRU_PSEUDO_DEV, O_RDWR, access)) == -1) {
98  			syslog(LOG_ERR, OPENDEVFRU, FRU_PSEUDO_DEV,
99  			    strerror(errno));
100  			return (-1);
101  		}
102  		opendevfru = 1;
103  	}
104  	return (frufd);
105  }
106  
107  /*
108   * Look up the container_hdl in the PICL tree.
109   */
110  container_hdl_t
111  fru_open_container(picl_nodehdl_t fruh)
112  {
113  	int err;
114  	container_hdl_t container_hdl;
115  
116  	if (fru_open_dev() == -1) {
117  		return (NULL);
118  	}
119  
120  	err = ptree_get_propval_by_name(fruh, PICL_PROP_DATA_AVAIL, NULL, NULL);
121  	if (err != PICL_SUCCESS) {
122  		syslog(LOG_ERR, GETPV, PICL_PROP_DATA_AVAIL, err);
123  		return (NULL);
124  	}
125  	err = ptree_get_propval_by_name(fruh, PICL_PROP_SC_HANDLE,
126  	    &container_hdl, sizeof (container_hdl_t));
127  	if (err != PICL_SUCCESS) {
128  		syslog(LOG_ERR, GETPV, PICL_PROP_SC_HANDLE, err);
129  		return (NULL);
130  	}
131  	return (container_hdl);
132  }
133  
134  /*
135   * Note : fru_open_container and fru_close_container do not map onto the opens
136   * and closes of the sgfru device on lw8. There is one sgfru device which
137   * handles all containers.
138   */
139  /*ARGSUSED*/
140  int
141  fru_close_container(container_hdl_t fru)
142  {
143  	if (fru_open_dev() == -1) {
144  		return (-1);
145  	}
146  	return (0);
147  }
148  
149  /*ARGSUSED*/
150  int
151  fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
152  {
153  	section_info_t numsections;
154  	int fd;
155  
156  	if ((fd = fru_open_dev()) == -1) {
157  		return (-1);
158  	}
159  	numsections.hdl = container;
160  	numsections.cnt = 0;
161  	if (ioctl(fd, SGFRU_GETNUMSECTIONS, &numsections) != 0) {
162  		return (-1);
163  	}
164  	return (numsections.cnt);
165  }
166  
167  /*ARGSUSED*/
168  int
169  fru_get_sections(container_hdl_t container, section_t *section,
170      int max_sections, door_cred_t *cred)
171  {
172  	sections_t sections;
173  	int fd;
174  
175  	if ((fd = fru_open_dev()) == -1) {
176  		return (-1);
177  	}
178  	sections.fru_hdl = container;
179  	sections.fru_cnt = max_sections;
180  	sections.frus = section;
181  	if (ioctl(fd, SGFRU_GETSECTIONS, &sections) != 0) {
182  		return (-1);
183  	}
184  	return (sections.fru_cnt);
185  }
186  
187  /*ARGSUSED*/
188  int
189  fru_get_num_segments(section_hdl_t section, door_cred_t *cred)
190  {
191  	segment_info_t numsegments;
192  	int fd;
193  
194  	if ((fd = fru_open_dev()) == -1) {
195  		return (-1);
196  	}
197  	numsegments.hdl = section;
198  	numsegments.cnt = 0;
199  	if (ioctl(fd, SGFRU_GETNUMSEGMENTS, &numsegments) != 0) {
200  		return (-1);
201  	}
202  	return (numsegments.cnt);
203  }
204  
205  /*ARGSUSED*/
206  int
207  fru_get_segments(section_hdl_t section, segment_t *segment, int max_segments,
208      door_cred_t *cred)
209  {
210  	segments_t segments;
211  	int fd;
212  
213  	if ((fd = fru_open_dev()) == -1) {
214  		return (-1);
215  	}
216  	segments.fru_hdl = section;
217  	segments.fru_cnt = max_segments;
218  	segments.frus = segment;
219  	if (ioctl(fd, SGFRU_GETSEGMENTS, &segments) != 0) {
220  		return (-1);
221  	}
222  	return (segments.fru_cnt);
223  }
224  
225  /*ARGSUSED*/
226  int
227  fru_add_segment(section_hdl_t section, segment_t *segment,
228      section_hdl_t *newsection, door_cred_t *cred)
229  {
230  	segments_t newsegment;
231  	int fd;
232  
233  	/* check the effective uid of the client */
234  	if (cred->dc_euid != 0) {
235  		errno = EPERM;
236  		return (-1);	/* not a root */
237  	}
238  
239  	if ((fd = fru_open_dev()) == -1) {
240  		return (-1);
241  	}
242  	newsegment.fru_hdl = section;
243  	newsegment.fru_cnt = 1;
244  	newsegment.frus = segment;
245  	if (ioctl(fd, SGFRU_ADDSEGMENT, &newsegment) != 0) {
246  		return (-1);
247  	}
248  	/*
249  	 * The new segment handle is returned in segment,
250  	 * return the updated section handle in newsection.
251  	 */
252  	*newsection = newsegment.fru_hdl;
253  	return (0);
254  }
255  
256  int
257  fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection,
258      door_cred_t *cred)
259  {
260  	segment_info_t delsegment;
261  	int fd;
262  
263  	/* check the effective uid of the client */
264  	if (cred->dc_euid != 0) {
265  		errno = EPERM;
266  		return (-1);	/* not a root */
267  	}
268  
269  	if ((fd = fru_open_dev()) == -1) {
270  		return (-1);
271  	}
272  	delsegment.hdl = segment;
273  	if (ioctl(fd, SGFRU_DELETESEGMENT, &delsegment) != 0) {
274  		return (-1);
275  	}
276  	/* Return the updated section handle in newsection. */
277  	*newsection = delsegment.hdl;
278  	return (0);
279  }
280  
281  /*ARGSUSED*/
282  ssize_t
283  fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
284      door_cred_t *cred)
285  {
286  	segments_t readsegment;
287  	int fd;
288  
289  	if ((fd = fru_open_dev()) == -1) {
290  		return (-1);
291  	}
292  	readsegment.fru_hdl = segment;
293  	readsegment.fru_cnt = nbytes;
294  	readsegment.frus = buffer;
295  	if (ioctl(fd, SGFRU_READRAWSEGMENT, &readsegment) != 0) {
296  		return (-1);
297  	}
298  	return ((ssize_t)readsegment.fru_cnt);
299  }
300  
301  /*ARGSUSED*/
302  ssize_t
303  fru_write_segment(segment_hdl_t segment, const void *buffer, size_t nbytes,
304      segment_hdl_t *newsegment, door_cred_t *cred)
305  {
306  	segments_t writesegment;
307  	int fd;
308  
309  	if ((fd = fru_open_dev()) == -1) {
310  		return (-1);
311  	}
312  	writesegment.fru_hdl = segment;
313  	writesegment.fru_cnt = nbytes;
314  	writesegment.frus = (void *)buffer;
315  	if (ioctl(fd, SGFRU_WRITERAWSEGMENT, &writesegment) != 0) {
316  		return (-1);
317  	}
318  	/* Return the updated segment handle in newsegment. */
319  	*newsegment = writesegment.fru_hdl;
320  	return ((ssize_t)writesegment.fru_cnt);
321  }
322  
323  /*ARGSUSED*/
324  int
325  fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
326  {
327  	packet_info_t numpackets;
328  	int fd;
329  
330  	if ((fd = fru_open_dev()) == -1) {
331  		return (-1);
332  	}
333  	numpackets.hdl = segment;
334  	numpackets.cnt = 0;
335  	if (ioctl(fd, SGFRU_GETNUMPACKETS, &numpackets) != 0) {
336  		return (-1);
337  	}
338  	return (numpackets.cnt);
339  }
340  
341  /*ARGSUSED*/
342  int
343  fru_get_packets(segment_hdl_t segment, packet_t *packet, int max_packets,
344      door_cred_t *cred)
345  {
346  	packets_t packets;
347  	int fd;
348  
349  	if ((fd = fru_open_dev()) == -1) {
350  		return (-1);
351  	}
352  	packets.fru_hdl = segment;
353  	packets.fru_cnt = max_packets;
354  	packets.frus = packet;
355  	if (ioctl(fd, SGFRU_GETPACKETS, &packets) != 0) {
356  		return (-1);
357  	}
358  	return (packets.fru_cnt);
359  }
360  
361  /*ARGSUSED*/
362  ssize_t
363  fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
364      door_cred_t *cred)
365  {
366  	payload_t payload;
367  	int fd;
368  
369  	if ((fd = fru_open_dev()) == -1) {
370  		return (-1);
371  	}
372  	payload.fru_hdl = packet;
373  	payload.fru_cnt = nbytes;
374  	payload.frus = buffer;
375  	if (ioctl(fd, SGFRU_GETPAYLOAD, &payload) != 0) {
376  		return (-1);
377  	}
378  	return ((ssize_t)payload.fru_cnt);
379  }
380  
381  int
382  fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes,
383      packet_hdl_t *newpacket, door_cred_t *cred)
384  {
385  	payload_t payload;
386  	int fd;
387  
388  	/* check the effective uid of the client */
389  	if (cred->dc_euid != 0) {
390  		errno = EPERM;
391  		return (-1);	/* not a root */
392  	}
393  
394  	if ((fd = fru_open_dev()) == -1) {
395  		return (-1);
396  	}
397  	payload.fru_hdl = packet;
398  	payload.fru_cnt = nbytes;
399  	payload.frus = (void *)data;
400  	if (ioctl(fd, SGFRU_UPDATEPAYLOAD, &payload) != 0) {
401  		return (-1);
402  	}
403  	/* Return the updated packet handle in newpacket. */
404  	*newpacket = payload.fru_hdl;
405  	return (0);
406  }
407  
408  int
409  fru_append_packet(segment_hdl_t segment, packet_t *packet, const void *payload,
410      size_t nbytes, segment_hdl_t *newsegment, door_cred_t *cred)
411  {
412  	append_info_t appendpkt;
413  	int fd;
414  
415  	/* check the effective uid of the client */
416  	if (cred->dc_euid != 0) {
417  		errno = EPERM;
418  		return (-1);	/* not a root */
419  	}
420  
421  	if ((fd = fru_open_dev()) == -1) {
422  		return (-1);
423  	}
424  	appendpkt.packet = *packet;
425  	appendpkt.payload_hdl = segment;
426  	appendpkt.payload_cnt = nbytes;
427  	appendpkt.payload_data = (void *)payload;
428  	if (ioctl(fd, SGFRU_APPENDPACKET, &appendpkt) != 0) {
429  		return (-1);
430  	}
431  	/*
432  	 * The new packet handle is returned in packet,
433  	 * return the updated segment handle in newsegment.
434  	 */
435  	packet->handle = appendpkt.packet.handle;
436  	*newsegment = appendpkt.payload_hdl;
437  	return (0);
438  }
439  
440  int
441  fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment,
442      door_cred_t *cred)
443  {
444  	packet_info_t delpacket;
445  	int fd;
446  
447  	/* check the effective uid of the client */
448  	if (cred->dc_euid != 0) {
449  		errno = EPERM;
450  		return (-1);	/* not a root */
451  	}
452  
453  	if ((fd = fru_open_dev()) == -1) {
454  		return (-1);
455  	}
456  	delpacket.hdl = packet;
457  	if (ioctl(fd, SGFRU_DELETEPACKET, &delpacket) != 0) {
458  		return (-1);
459  	}
460  	/* Return the updated segment handle in newsegment. */
461  	*newsegment = delpacket.hdl;
462  	return (0);
463  }
464  
465  /*
466   * Description :
467   *		fru_is_data_available() checks to see if the frudata
468   *		is available on a fru.
469   *
470   * Arguments   :
471   *		picl_nodehdl_t holds the picl node handle of the fru.
472   *
473   * Return      :
474   *		int
475   *		return 1: if FRUID information is available
476   *		return 0: if FRUID information is not present
477   *
478   */
479  
480  /* ARGSUSED */
481  int
482  fru_is_data_available(picl_nodehdl_t fru)
483  {
484  	return (0);
485  }
486