/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <limits.h>
#include <alloca.h>
#include "fru_access_impl.h"
/*
* seeprom is the driver_name for the SEEPROM device drivers in excalibur
* Define the devfsadm command to load the seeprom drivers if open fails.
*/
/* this routine initialize the hash table. */
static void
initialize_fruaccess(void)
{
int count;
}
}
/*
* called to lookup hash object for specified handle in the hash table.
*
*/
static hash_obj_t *
{
return (next_hash_obj);
}
}
return (NULL);
}
/* called to allocate container hash object */
static hash_obj_t *
{
return (NULL);
}
return (NULL);
}
return (hash_obj);
}
/* called to allocate section hash object */
static hash_obj_t *
{
return (NULL);
}
return (NULL);
}
return (hash_obj);
}
/* called to allocate segment hash object */
static hash_obj_t *
{
return (NULL);
}
return (NULL);
}
return (hash_obj);
}
/* called to allocate packet hash object */
static hash_obj_t *
{
return (NULL);
}
return (NULL);
}
return (hash_obj);
}
/* called to add allocated hash object into the hash table */
static void
{
/* where to add ? */
}
}
/* called to add section object list into the section list */
static void
{
return;
}
;
}
}
/* called to add segment object list into segment list */
static void
{
return;
}
;
}
}
/* called to add packet object list into packet list */
static void
{
/* add the packet object in the end of list */
return;
}
;
}
}
static void
{
}
static hash_obj_t *
{
switch (object_type) {
case CONTAINER_TYPE :
break;
case SECTION_TYPE :
return (NULL);
}
break;
case SEGMENT_TYPE :
return (NULL);
}
break;
case PACKET_TYPE :
break;
default :
return (NULL);
}
return (hash_obj);
}
static void
{
int cntx;
int cnty;
sizeof (seg_info_t));
sizeof (seg_info_t));
}
}
}
}
/*
* Description : move_segment_data() reads the segment data and writes it
* back to the new segment offset.
*/
static void
{
int ret;
char *buffer;
return;
}
return;
}
return;
}
}
/*
* Description : pack_segment_data() moves the segment data if there is
* a hole between two segments.
*/
static void
{
int cnt;
int diff;
int newoffset;
+ diff;
contfd);
}
}
}
}
/*
* Description : build_offset_tbl() builds the offset table by reading all the
* segment header. it makes two more entry into the table one for
* section size and another with start of the section after the
* segment header.
*/
static int
{
int cnt;
sizeof (uint32_t));
}
/* upper boundary of segment area (lower address bytes) */
* sizeof (segment_layout_t));
/* lower boundary of segment area (higher address bytes) */
return (0);
}
static int
{
int cnt = 0;
*totsize = 0;
}
}
return (0);
}
/*
* Description : segment_hdr_present() verify space for new segment header to
* be added.
*/
static int
{
return (0);
else
return (-1);
}
/*
* Description : find_offset() is called from fru_add_segment routine to find
* a valid offset.
*/
static int
{
int ret;
int newoffset;
int totsize = 0;
if (segcnt == 0) {
if (!fix) { /* if not fixed segment */
}
return (0);
}
/*
* two extra segment info structure are allocated for start of segment
* and other end of segment. first segment offset is first available
* space and length is 0. second segment offset is is segment length and
* offset is 0. build_offset_tbl() explains how upper boundary and lower
* boudary segment area are initialized in seg_info_t table.
*/
if (offset_tbl == NULL) {
return (-1);
}
/* read all the segment header to make offset table */
if (ret != 0) {
return (-1);
}
/* sort the table */
/* new segment header offset */
sizeof (segment_layout_t);
/* do? new segment header overlap any existing data */
if (ret != 0) { /* make room for new segment if possible */
/* look for hole in order to move segment data */
return (-1);
}
if (newoffset != 0) { /* found new offset */
/* now new offset */
/* move the segment data */
/* again sort the offset table */
} else {
/* pack the existing hole */
contfd, offset_tbl);
} else {
return (-1);
}
}
}
totsize = 0;
if (newoffset == 0) { /* No hole found */
&totsize, offset_tbl);
if (newoffset != 0) {
return (0);
}
}
} else {
return (0);
}
return (-1);
}
static char *
{
int i = 0;
int j = 0;
for (i = 0; buf[i] != '\0'; i++) {
buf[i] = '\0';
return (buf);
}
}
}
*matched = '\0';
return (NULL);
}
static int
{
char *item;
char *token;
char *field;
char matched;
int foundIt = 0;
return (-1);
cont_info->num_sections = 0;
/* ignore all comments */
/* find the names */
if (token != 0x00) {
while (token != 0x00) {
foundIt = 1;
goto found;
}
}
/* check the last remaining item */
if ((item != 0x00) &&
foundIt = 1;
goto found;
}
}
}
found :
if (foundIt == 1) {
if (token == 0x00) {
return (-1);
}
while (token != 0x00) {
if (token == 0x00) {
return (-1);
}
} else {
return (-1);
}
if (token == 0x00) {
return (-1);
}
} else {
return (-1);
}
if (token == 0x00) {
return (-1);
}
if (item == '\0') {
return (-1);
}
(cont_info->num_sections)++;
}
}
return (0);
}
/*
* Description :fru_open_container() opens the container associated with a fru.
* it's called by data plugin module before creating container
* property. it calls picltree library routine to get the
* device path and driver binding name for the fru to get the
* corresponding fru name that describe the fru layout.
*
* Arguments :picl_hdl_t fru
* A handle for PICL tree node of class "fru" representing the
* FRU with the container to open.
*
* Return :
* On Success, a Positive integer container handle. is returned
* for use in subsequent fru operations;on error, 0 is returned
* and "errno" is set appropriately.
*/
{
int retval;
int count;
char *bname;
/* Get property handle of _seeprom_source under fru node */
if (retval != PICL_SUCCESS) {
return (NULL);
}
/* Get the device path of the fru */
if (retval != PICL_SUCCESS) {
return (NULL);
}
&prophdl);
if (retval != PICL_SUCCESS) {
return (NULL);
}
if (retval != PICL_SUCCESS) {
return (NULL);
}
return (NULL);
}
/* get the driver binding name */
if (retval != PICL_SUCCESS) {
return (NULL);
}
if (cont_hash_obj == NULL) {
return (NULL);
}
sizeof (devpath));
/* takes driver binding name as to get container information */
if (retval < 0) {
return (NULL);
}
if (sec_hash_obj == NULL) {
return (NULL);
}
}
return (cont_hash_obj->obj_hdl);
}
static int
{
int crc_offset = 0;
unsigned char orig_crc8 = 0;
unsigned char calc_crc8 = 0;
switch (head_ver) {
case SECTION_HDR_VER:
crc_offset = 4;
break;
default:
return (0);
}
}
/*
* Description :
* fru_get_num_sections() returns number of sections in a
* container. it calls get_container_index() to get the container
* index number in the container list.
*
* Arguments :
* container_hdl_t : container handle.
*
* Return :
* int
* On success, returns number of sections in a container.
*
*/
/*ARGSUSED*/
int
{
if (hash_object == NULL) {
return (-1);
}
}
/*
* called from fru_get_sections()
*/
static void
{
int retval;
int size;
int count;
unsigned char *buffer;
return;
}
/* populate section_t */
sec_obj->num_of_segment = 0;
/* read section header layout */
return;
}
return;
}
/* size = section layout + total sizeof segment header */
* sizeof (segment_layout_t));
return;
}
/* segment header buffer */
return;
}
/* read segment header */
return;
}
/* copy section header layout */
/* copy segment header layout */
sizeof (sec_hdr));
/* verify crc8 */
return;
}
return;
}
}
}
static int
call_devfsadm(void)
{
char *phys_path;
return (-1);
}
if (f_node != DI_NODE_NIL) {
!= DI_NODE_NIL) {
return (0);
}
}
return (-1);
}
/*
* Description :
* fru_get_sections() fills an array of section structures passed
* as an argument.
*
* Arguments :
* container_hdl_t : container handle(device descriptor).
* section_t : array of section structure.
* int : maximum number of section in a container.
*
* Returns :
* int
* On success,the number of section structures written is returned;
* on error, -1 is returned and "errno" is set appropriately.
*
*/
/* ARGSUSED */
int
{
int device_fd;
int count;
if (cont_object == NULL) {
return (-1);
}
return (-1);
}
return (-1);
}
do {
O_RDWR);
if (device_fd >= 0) {
break;
}
} while ((retrys-- > 0) && (call_devfsadm() == 0));
if (device_fd < 0) {
return (-1);
}
/* populate section_t */
}
return (count);
}
/*
* Description :
* fru_get_num_segments() returns the current number of segments
* in a section.
*
* Arguments :
* section_hdl_t : section header holding section information.
*
* Return :
* int
* On success, the number of segments in the argument section is
* returned; on error -1 is returned.
*/
/*ARGSUSED*/
int
{
if (sec_object == NULL) {
return (-1);
}
return (-1);
}
return (sec_obj->num_of_segment);
}
/*
* Description :
* fru_get_segments() fills an array of structures representing the
* segments in a section.
*
* Arguments :
* section_hdl_t : holds section number.
* segment_t : on success will hold segment information.
* int : maximum number of segment.
*
* Return :
* int
* On success, the number of segment structures written is
* returned; on errno -1 is returned.
*/
/* ARGSUSED */
int
{
int count;
if (sec_object == NULL) {
return (-1);
}
return (-1);
}
return (-1);
}
if (seg_object == NULL) {
return (-1);
}
/* populate segment_t */
segment++;
}
return (0);
}
/*
* Description :
* fru_add_segment() adds a segment to a section.
*
* Arguments :
* section_hdl_t section
* A handle for the section in which to add the segment.
*
* segment_t *segment
* On entry, the "handle" component of "segment" is ignored and the
* remaining components specify the parameters of the segment to be
* added. On return, the "handle" component is set to the handle
* for the added segment. The segment offset is mandatory for FIXED
* segments; otherwise, the offset is advisory.
*
* Return :
* int
* On success, 0 is returned; on error -1 is returned.
*
*/
int
{
int fd;
int retval;
int offset;
int sec_size;
int seg_cnt;
int bufsize;
int new_seg_offset;
int new_seg_length;
int fixed_segment;
unsigned char *crcbuf;
/* check the effective uid of the client */
return (-1); /* not a root */
}
/* section hash */
return (-1);
}
/* check for read-only section */
return (-1);
}
/* look for duplicate segment */
SEG_NAME_LEN) == 0) {
return (-1); /* can't add duplicate segment */
}
}
/* get the container hash */
return (-1);
}
/* open the container */
if (fd < 0) {
return (-1);
}
/* section start here */
/* read section header layout */
if (retval != sizeof (sec_layout)) {
return (-1);
}
/* check for valid section header */
/* write a new one */
sec_layout.segmentcount = 0;
}
/* section size */
/* number of segment in the section */
/* total sizeof segment + new segment */
if (segment_buf == NULL) {
return (-1);
}
/* read entire segment header */
offset + sizeof (section_layout_t));
return (-1);
}
/* get new offset for new segment to be addedd */
if (retval != 0) {
return (-1);
}
/* copy new segment data in segment layout */
sizeof (uint32_t));
return (-1);
}
sec_layout.headercrc8 = 0;
sizeof (section_layout_t));
/* write section header */
if (retval != sizeof (section_layout_t)) {
return (-1);
}
/* write segment header */
sizeof (section_layout_t));
return (-1);
}
/* write segment trailer */
return (-1);
}
/* create new segment hash object */
return (-1);
}
return (0);
}
static void
{
/* if prev is NULL it's the first object in the list */
}
} else {
}
}
}
}
static void
{
return;
}
} else {
return;
}
}
}
}
} else {
}
}
}
/*
* Description :
* fru_delete_segment() deletes a segment from a section; the
* associated container data is not altered.
*
* Arguments : segment_hdl_t segment handle.
* section_hdl_t new section handle.
*
* Return :
* int
* On success, 0 returned; On error -1 is returned.
*/
int
{
int num_of_seg;
int bufsize;
int count;
int retval;
int fd;
int segnum;
unsigned char *buffer;
/* check the effective uid of the client */
return (-1); /* not a root */
}
return (-1);
}
return (-1); /* can't delete this segment */
}
return (-1);
}
return (-1);
}
return (-1);
}
segnum = 0;
break;
}
segnum++;
}
return (-1);
}
if (fd < 0) {
return (-1);
}
if (sec_layout == NULL) {
return (-1);
}
/* read section layout header */
if (retval != sizeof (section_layout_t)) {
return (-1);
}
/* read segment header layout */
sizeof (section_layout_t));
return (-1);
}
count++) {
next_layout++;
sizeof (segment_layout_t));
seg_layout++;
}
sec_layout->headercrc8 = 0;
return (-1);
}
- sizeof (segment_layout_t));
/* write section header with update crc8 and header length */
if (retval != sizeof (section_layout_t)) {
return (-1);
}
/* write the update segment header */
sizeof (section_layout_t));
return (-1);
}
return (0);
}
/*
* Description :
* fru_read_segment() reads the raw contents of a segment.
*
* Arguments : segment_hdl_t : segment handle.
* void * : buffer containing segment data when function returns.
* size_t :number of bytes.
*
* Return :
* int
* On success, the number of bytes read is returned;
*
* Notes :
* Segments containing packets can be read in structured fashion
* using the fru_get_packets() and fru_get_payload() primitives;the
* entire byte range of a segment can be read using
* fru_read_segment().
*/
/*ARGSUSED*/
{
int fd;
int retval;
/* segment hash object */
return (-1);
}
/* section hash object */
return (-1);
}
/* container hash object */
return (-1);
}
return (-1);
}
if (fd < 0) {
return (-1);
}
return (-1);
}
return (nbytes);
}
/*
* Description :
* fru_write_segment() writes a raw segment.
*
* Arguments : segment_hdl_t :segment handle.
* const void * : data buffer.
* size_t : number of bytes.
* segment_hdl_t : new segment handle.
*
* Returns :
* int
* On success, the number of bytes written is returned
*
*/
/*ARGSUSED*/
int
{
return (ENOTSUP);
}
static int
{
int retval;
if (retval != -1) {
return (0);
}
return (-1);
}
/*
* Description :
* get_payload() populates a buffer with the packets payload
*
* Arguments : hash_obj_t : packet.
* int : device file descriptor
* uint8_t* : pointer to a pre allocated buffer
*
*
* Return :
* int
* On success, 0 is returned; on failure
* -1 returned.
*/
int
{
int retval;
if (packet_object == NULL) {
return (-1);
}
/* Get the data */
return (-1);
}
return (0);
}
static uint32_t
{
int checksum;
int offset = 0;
int retval;
unsigned char *buffer;
return ((uint32_t)-1);
}
return ((uint32_t)-1);
}
/* traverse the packet object list for all the tags and payload */
/* read packet payload */
return ((uint32_t)-1);
}
if (retval == -1) {
return ((uint32_t)-1);
}
}
}
return (crc); /* computed crc */
}
static int
{
int tag_size;
int paylen;
int retval;
int seg_limit = 0;
int pktcnt = 0;
char *data;
if (retval == -1) {
return (-1);
}
while (data[0] != SEG_TRAILER_TAG) {
if (tagtype == -1) {
return (-1);
}
if (tag_size == -1) {
return (-1);
}
return (-1);
}
if (paylen == -1) {
return (-1);
}
return (-1);
}
if (pkt_hash_obj == NULL) {
return (-1);
}
/* don't change this */
pktcnt++;
offset);
if (retval == -1) {
return (retval);
}
}
return (-1);
}
return (-1);
}
}
return (pktcnt);
}
/*
* Description :
* fru_get_num_packets() returns the current number of packets
* in a segment.
*
* Arguments : segment_hdl_t : segment handle.
*
* Return :
* int
* On success, the number of packets is returned;
* -1 on failure.
*/
/*ARGSUSED*/
int
{
int device_fd;
int pktcnt;
int length;
return (-1);
}
if (segment_object == NULL) {
return (-1);
}
return (0);
}
if (cont_hash_obj == NULL) {
return (-1);
}
return (segment_object->num_of_packets);
}
segment_object->num_of_packets = 0;
O_RDWR);
if (device_fd < 0) {
return (-1);
}
length);
if (pktcnt == -1) {
}
return (segment_object->num_of_packets);
}
/*
* Description :
* fru_get_packets() fills an array of structures representing the
* packets in a segment.
*
* Arguments : segment_hdl_t : segment handle.
* packet_t : packet buffer.
* int : maximum number of packets.
*
* Return :
* int
* On success, the number of packet structures written is returned;
* On failure -1 is returned;
*
*/
/*ARGSUSED*/
int
{
int count;
/* segment hash object */
if (seg_hash_obj == NULL) {
return (-1);
}
return (-1);
}
if (pkt_hash_obj == NULL) {
return (-1);
}
}
return (0);
}
/*
* Description :
* fru_get_payload() copies the contents of a packet's payload.
*
* Arguments : packet_hdl_t : packet handle.
* void * : payload buffer.
* size_t : sizeof the buffer.
*
* Return :
* int
* On success, the number of bytes copied is returned; On error
* -1 returned.
*/
/*ARGSUSED*/
{
int retval;
int device_fd;
/* packet hash object */
if (packet_hash_obj == NULL) {
return (-1);
}
return (-1);
}
/* lookup the segment hash object */
if (segment_hash_obj == NULL) {
return (-1);
}
/* Get the container hash object to get the seeprom device path */
if (container_hash_obj == NULL) {
return (-1);
}
/* Open the seeprom device */
O_RDWR);
if (device_fd < 0) {
return (-1);
}
/* Call to get the payload */
if (retval == -1) {
return (-1);
}
/* verify payload length */
return (-1);
}
return (nbytes);
}
/*
* Description :
* fru_update_payload() writes the contents of a packet's payload.
*
* Arguments : packet_hdl_t : packet handle.
* const void * : data buffer.
* size_t : buffer size.
* packet_hdl_t : new packet handle.
*
* Return :
* int
* On success, 0 is returned; on failure
* -1 is returned.
*/
int
{
int fd;
int segment_offset;
int trailer_offset;
int retval;
/* check the effective uid of the client */
return (-1); /* not a root */
}
/* packet hash object */
return (-1);
}
/* segment hash object */
return (-1);
}
/* check for write perm. */
return (-1); /* write not allowed */
}
return (-1);
}
return (-1); /* read-only section */
}
return (-1);
}
return (-1);
}
if (fd < 0) {
return (-1);
}
return (-1);
}
return (-1);
}
return (0);
}
/*
* Description :
* fru_append_packet() appends a packet to a segment.
*
* Arguments :
* segment_hdl_t segment
* A handle for the segment to which the packet will be appended.
*
* packet_t *packet
* On entry, the "tag" component of "packet" specifies the tag
* value for the added packet; the "handle" component is ignored.
* On return, the "handle" component is set to the handle of the
* appended packet.
*
* const void *payload
* A pointer to the caller's buffer containing the payload data for
* the appended packet.
*
* size_t nbytes
* The size of the caller buffer.
*
* Return :
* int
* On success, 0 is returned; on error -1 is returned;
*/
int
{
int trailer_offset;
int tag_size;
int fd;
int retval;
/* check the effective uid of the client */
return (-1); /* not a root */
}
return (-1);
}
/* check for write perm. */
return (-1); /* write not allowed */
}
return (-1);
}
return (-1); /* read-only section */
}
/*
* if trailer offset is 0 than parse the segment data to get the trailer
* offset to compute the remaining space left in the segment area for
* new packet to be added.
*/
if (trailer_offset == 0) {
}
if (tagtype == -1) {
return (-1);
}
if (tag_size == -1) {
return (-1);
}
+ sizeof (uint32_t))) {
/* create new packet hash */
return (-1);
}
/* tag initialization */
tag_size);
/* add to hash table */
return (-1);
}
if (fd < 0) {
return (-1);
}
/* update the trailer offset */
/* calculate new checksum */
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (0);
} else {
}
return (-1);
}
static void
{
int retval;
return;
}
if (retval == -1) {
return;
}
return;
}
return;
}
}
}
static void
{
return;
}
} else {
return;
}
}
}
}
} else {
}
}
}
/*
* Description :
* fru_delete_packet() deletes a packet from a segment.
*
* Arguments : packet_hdl_t : packet number to be deleted.
* segment_hdl_t : new segment handler.
*
* Return :
* int
* On success, 0 is returned; on error, -1.
*
* NOTES
* Packets are adjacent; thus, deleting a packet requires moving
* succeeding packets to compact the resulting hole.
*/
int
{
int retval;
int fd;
/* check the effective uid of the client */
return (-1); /* not a root */
}
/* packet hash object */
return (-1);
}
/* segment hash object */
return (-1);
}
/* check for write perm. */
return (-1); /* write not allowed */
}
/* section hash object */
return (-1);
}
return (-1); /* read-only section */
}
return (-1);
}
/* container hash object */
return (-1);
}
if (fd < 0) {
return (-1);
}
} else {
/* found the object */
}
}
}
/* calculate checksum */
/* write trailer at new offset */
return (-1);
}
/* write the checksum value */
return (-1);
}
return (0);
}
/*
* Description :
* fru_close_container() removes the association between a
* container and its handle. this routines free's up all the
* hash object contained under container.
*
* Arguments :
* container_hdl_t holds the file descriptor of the fru.
*
* Return :
* int
* return 0.
*
*/
/* ARGSUSED */
int
{
/* lookup for container hash object */
return (0);
}
/* points to section object list */
/* traverse section object list */
while (sec_hash_obj != NULL) {
/* traverse segment hash object in the section */
/* object handle of the segment hash object */
obj_hdl =
}
/* going to free section hash object, relink the hash object */
= sec_hash_obj->next;
}
} else {
}
}
}
/* free container hash object */
}
} else {
}
}
return (0);
}
/*
* Description :
* fru_is_data_available() checks to see if the frudata
* is available on a fru.
*
* Arguments :
* picl_nodehdl_t holds the picl node handle of the fru.
*
* Return :
* int
* return 1: if FRUID information is available
* return 0: if FRUID information is not present
*
*/
/* ARGSUSED */
int
{
return (0);
}