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, §ions) != 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