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.
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
43 #include <sys/systeminfo.h>
46 #include <fru_access.h>
47 #include <sys/sgfrutree.h>
50 * these functions will overlay the symbol table of libfruaccess
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
,
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
,
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
);
83 #define PICL_PROP_SC_HANDLE "SC_handle"
84 #define PICL_PROP_DATA_AVAIL "FRUDataAvailable"
85 #define MAX_LINE_SIZE 1024
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")
93 static int opendevfru
= 0;
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
,
108 * Look up the container_hdl in the PICL tree.
111 fru_open_container(picl_nodehdl_t fruh
)
114 container_hdl_t container_hdl
;
116 if (fru_open_dev() == -1) {
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
);
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
);
131 return (container_hdl
);
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.
141 fru_close_container(container_hdl_t fru
)
143 if (fru_open_dev() == -1) {
151 fru_get_num_sections(container_hdl_t container
, door_cred_t
*cred
)
153 section_info_t numsections
;
156 if ((fd
= fru_open_dev()) == -1) {
159 numsections
.hdl
= container
;
161 if (ioctl(fd
, SGFRU_GETNUMSECTIONS
, &numsections
) != 0) {
164 return (numsections
.cnt
);
169 fru_get_sections(container_hdl_t container
, section_t
*section
,
170 int max_sections
, door_cred_t
*cred
)
175 if ((fd
= fru_open_dev()) == -1) {
178 sections
.fru_hdl
= container
;
179 sections
.fru_cnt
= max_sections
;
180 sections
.frus
= section
;
181 if (ioctl(fd
, SGFRU_GETSECTIONS
, §ions
) != 0) {
184 return (sections
.fru_cnt
);
189 fru_get_num_segments(section_hdl_t section
, door_cred_t
*cred
)
191 segment_info_t numsegments
;
194 if ((fd
= fru_open_dev()) == -1) {
197 numsegments
.hdl
= section
;
199 if (ioctl(fd
, SGFRU_GETNUMSEGMENTS
, &numsegments
) != 0) {
202 return (numsegments
.cnt
);
207 fru_get_segments(section_hdl_t section
, segment_t
*segment
, int max_segments
,
213 if ((fd
= fru_open_dev()) == -1) {
216 segments
.fru_hdl
= section
;
217 segments
.fru_cnt
= max_segments
;
218 segments
.frus
= segment
;
219 if (ioctl(fd
, SGFRU_GETSEGMENTS
, &segments
) != 0) {
222 return (segments
.fru_cnt
);
227 fru_add_segment(section_hdl_t section
, segment_t
*segment
,
228 section_hdl_t
*newsection
, door_cred_t
*cred
)
230 segments_t newsegment
;
233 /* check the effective uid of the client */
234 if (cred
->dc_euid
!= 0) {
236 return (-1); /* not a root */
239 if ((fd
= fru_open_dev()) == -1) {
242 newsegment
.fru_hdl
= section
;
243 newsegment
.fru_cnt
= 1;
244 newsegment
.frus
= segment
;
245 if (ioctl(fd
, SGFRU_ADDSEGMENT
, &newsegment
) != 0) {
249 * The new segment handle is returned in segment,
250 * return the updated section handle in newsection.
252 *newsection
= newsegment
.fru_hdl
;
257 fru_delete_segment(segment_hdl_t segment
, section_hdl_t
*newsection
,
260 segment_info_t delsegment
;
263 /* check the effective uid of the client */
264 if (cred
->dc_euid
!= 0) {
266 return (-1); /* not a root */
269 if ((fd
= fru_open_dev()) == -1) {
272 delsegment
.hdl
= segment
;
273 if (ioctl(fd
, SGFRU_DELETESEGMENT
, &delsegment
) != 0) {
276 /* Return the updated section handle in newsection. */
277 *newsection
= delsegment
.hdl
;
283 fru_read_segment(segment_hdl_t segment
, void *buffer
, size_t nbytes
,
286 segments_t readsegment
;
289 if ((fd
= fru_open_dev()) == -1) {
292 readsegment
.fru_hdl
= segment
;
293 readsegment
.fru_cnt
= nbytes
;
294 readsegment
.frus
= buffer
;
295 if (ioctl(fd
, SGFRU_READRAWSEGMENT
, &readsegment
) != 0) {
298 return ((ssize_t
)readsegment
.fru_cnt
);
303 fru_write_segment(segment_hdl_t segment
, const void *buffer
, size_t nbytes
,
304 segment_hdl_t
*newsegment
, door_cred_t
*cred
)
306 segments_t writesegment
;
309 if ((fd
= fru_open_dev()) == -1) {
312 writesegment
.fru_hdl
= segment
;
313 writesegment
.fru_cnt
= nbytes
;
314 writesegment
.frus
= (void *)buffer
;
315 if (ioctl(fd
, SGFRU_WRITERAWSEGMENT
, &writesegment
) != 0) {
318 /* Return the updated segment handle in newsegment. */
319 *newsegment
= writesegment
.fru_hdl
;
320 return ((ssize_t
)writesegment
.fru_cnt
);
325 fru_get_num_packets(segment_hdl_t segment
, door_cred_t
*cred
)
327 packet_info_t numpackets
;
330 if ((fd
= fru_open_dev()) == -1) {
333 numpackets
.hdl
= segment
;
335 if (ioctl(fd
, SGFRU_GETNUMPACKETS
, &numpackets
) != 0) {
338 return (numpackets
.cnt
);
343 fru_get_packets(segment_hdl_t segment
, packet_t
*packet
, int max_packets
,
349 if ((fd
= fru_open_dev()) == -1) {
352 packets
.fru_hdl
= segment
;
353 packets
.fru_cnt
= max_packets
;
354 packets
.frus
= packet
;
355 if (ioctl(fd
, SGFRU_GETPACKETS
, &packets
) != 0) {
358 return (packets
.fru_cnt
);
363 fru_get_payload(packet_hdl_t packet
, void *buffer
, size_t nbytes
,
369 if ((fd
= fru_open_dev()) == -1) {
372 payload
.fru_hdl
= packet
;
373 payload
.fru_cnt
= nbytes
;
374 payload
.frus
= buffer
;
375 if (ioctl(fd
, SGFRU_GETPAYLOAD
, &payload
) != 0) {
378 return ((ssize_t
)payload
.fru_cnt
);
382 fru_update_payload(packet_hdl_t packet
, const void *data
, size_t nbytes
,
383 packet_hdl_t
*newpacket
, door_cred_t
*cred
)
388 /* check the effective uid of the client */
389 if (cred
->dc_euid
!= 0) {
391 return (-1); /* not a root */
394 if ((fd
= fru_open_dev()) == -1) {
397 payload
.fru_hdl
= packet
;
398 payload
.fru_cnt
= nbytes
;
399 payload
.frus
= (void *)data
;
400 if (ioctl(fd
, SGFRU_UPDATEPAYLOAD
, &payload
) != 0) {
403 /* Return the updated packet handle in newpacket. */
404 *newpacket
= payload
.fru_hdl
;
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
)
412 append_info_t appendpkt
;
415 /* check the effective uid of the client */
416 if (cred
->dc_euid
!= 0) {
418 return (-1); /* not a root */
421 if ((fd
= fru_open_dev()) == -1) {
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) {
432 * The new packet handle is returned in packet,
433 * return the updated segment handle in newsegment.
435 packet
->handle
= appendpkt
.packet
.handle
;
436 *newsegment
= appendpkt
.payload_hdl
;
441 fru_delete_packet(packet_hdl_t packet
, segment_hdl_t
*newsegment
,
444 packet_info_t delpacket
;
447 /* check the effective uid of the client */
448 if (cred
->dc_euid
!= 0) {
450 return (-1); /* not a root */
453 if ((fd
= fru_open_dev()) == -1) {
456 delpacket
.hdl
= packet
;
457 if (ioctl(fd
, SGFRU_DELETEPACKET
, &delpacket
) != 0) {
460 /* Return the updated segment handle in newsegment. */
461 *newsegment
= delpacket
.hdl
;
467 * fru_is_data_available() checks to see if the frudata
468 * is available on a fru.
471 * picl_nodehdl_t holds the picl node handle of the fru.
475 * return 1: if FRUID information is available
476 * return 0: if FRUID information is not present
482 fru_is_data_available(picl_nodehdl_t fru
)