/*
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <alloca.h>
#include <picl.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include "picldefs.h"
#include "fru_data.h"
#include "libfruds.h"
#include "libfrup.h"
/* ========================================================================= */
/* Cache of the root node for quick checks */
/* ========================================================================= */
/*
* Map the PICL errors the plugin would give me to FRU errors
*/
static fru_errno_t
{
switch (picl_err) {
case PICL_SUCCESS:
return (FRU_SUCCESS);
case PICL_PERMDENIED:
return (FRU_INVALPERM);
case PICL_PROPEXISTS:
return (FRU_DUPSEG);
case PICL_NOSPACE:
return (FRU_NOSPACE);
case PICL_NORESPONSE:
return (FRU_NORESPONSE);
case PICL_PROPNOTFOUND:
return (FRU_NODENOTFOUND);
case PICL_ENDOFLIST:
return (FRU_DATANOTFOUND);
}
return (FRU_IOERROR);
}
/* ========================================================================= */
/*
* cause a refresh of the sub-nodes by writing anything to the container
* property of the node.
*/
static fru_errno_t
{
PICL_PROP_CONTAINER, (void *)&container,
sizeof (container))) != PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
/*
* picl like function which gets a string property with the proper length
* NOTE: returns picl errno values NOT fru_errno_t
*/
static int
{
return (picl_err);
}
return (PICL_FAILURE);
}
!= PICL_SUCCESS) {
return (picl_err);
}
return (PICL_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
/* get the name */
&tmp_name)) != PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
/* get the label, if any */
&label)) != PICL_SUCCESS) {
if (picl_err != PICL_PROPNOTFOUND) {
return (map_plugin_err(picl_err));
}
/* else PICL_PROPNOTFOUND is OK because not all nodes */
/* will have a label. */
}
/* construct the name as nessecary */
} else {
return (FRU_FAILURE);
}
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
/* compare the node name to the name passed */
static fru_errno_t
{
!= PICL_SUCCESS) {
return (FRU_FAILURE);
}
return (FRU_SUCCESS);
}
return (FRU_FAILURE);
}
/* ========================================================================= */
/* compare the node class name to the name passed */
static fru_errno_t
{
!= PICL_SUCCESS) {
return (FRU_FAILURE);
}
return (FRU_SUCCESS);
}
return (FRU_FAILURE);
}
/* ========================================================================= */
/* get the "frutree" root node */
static fru_errno_t
{
!= PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
!= FRU_SUCCESS) {
PICL_PROP_PEER, (void *)&picl_node,
sizeof (picl_node))) == PICL_PROPNOTFOUND) {
return (FRU_NODENOTFOUND);
} else if (picl_err != PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
if (rc != PICL_SUCCESS) {
return (map_plugin_err(rc));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
if (rc != PICL_SUCCESS) {
return (map_plugin_err(rc));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
/* do not allow the libfru users to see the parent of the root */
return (FRU_NODENOTFOUND);
}
if (rc != PICL_SUCCESS) {
return (map_plugin_err(rc));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
return (map_plugin_err(rc));
}
return (FRU_SUCCESS);
/* check for the CONTAINER_PROP property which indicates */
/* there is data for this node. (ie fru is a container) */
return (FRU_SUCCESS);
}
*type = FRU_NODE_FRU;
return (FRU_SUCCESS);
}
*type = FRU_NODE_UNKNOWN;
return (FRU_SUCCESS);
}
/* ========================================================================= */
/* find the next section or return NODENOTFOUND */
static fru_errno_t
{
return (FRU_NODENOTFOUND);
}
/* Make sure this is a "Section" node */
== FRU_SUCCESS) {
return (FRU_SUCCESS);
}
/* and if this is not good keep trying to find a peer which */
/* is a section */
}
/* ========================================================================= */
/* find the first section or return NODENOTFOUND */
static fru_errno_t
{
return (FRU_NODENOTFOUND);
}
/* Make sure this is a "Section" node */
== FRU_SUCCESS) {
*section = rc_section;
return (FRU_SUCCESS);
}
/* and if this is not good keep trying to find a peer which */
/* is a section */
}
/* ========================================================================= */
/*
* Find the handle of the segment node "segment".
* also returns the hardware description of this segment. (read from the
* section this was found in.)
* If the ign_cor_flg is set this will still succeed even if the segment is
* corrupt, otherwise it will return FRU_SEGCORRUPT for corrupt segments
*/
#define IGN_CORRUPT_NO 0
static fru_errno_t
{
return (err);
}
return (err);
}
/* while there are sections. */
while (err == FRU_SUCCESS) {
/* do this just in case the Segments have not been built. */
(void *)&num_segs,
sizeof (num_segs))) != PICL_SUCCESS) {
return (map_plugin_err(rc));
}
/* while there are segments. */
while (rc == PICL_SUCCESS) {
int dummy = 0;
int protection = 0;
/* NUM_TAGS prop exists iff segment is OK */
if ((ign_cor_flg == IGN_CORRUPT_NO) &&
(void *)&dummy,
sizeof (dummy)) != PICL_SUCCESS)) {
return (FRU_SEGCORRUPT);
}
/* get the HW protections of this section. */
(void *)&protection,
sizeof (protection)))
!= PICL_SUCCESS) {
return (map_plugin_err(rc));
}
return (FRU_SUCCESS);
}
}
/* Peer property not found is ok */
if (rc != PICL_PROPNOTFOUND) {
return (map_plugin_err(rc));
}
}
return (FRU_INVALSEG);
}
/* ========================================================================= */
/*
* For the section handle passed add to list all the segment names found.
* Also incriments total by the number found.
*/
static fru_errno_t
{
(void *)&num_segments,
sizeof (num_segments))) != PICL_SUCCESS) {
return (map_plugin_err(rc));
}
if (num_segments != 0) {
return (FRU_FAILURE);
}
/* get the first segment */
PICL_PROP_CHILD, (void *)&seg_node,
sizeof (seg_node));
/* while there are more segments. */
while (rc == PICL_SUCCESS) {
sizeof (name))) != PICL_SUCCESS) {
break;
}
/* check array bounds */
/* PICL reported incorrect number of segs */
return (FRU_IOERROR);
}
PICL_PROP_PEER, (void *)&seg_node,
sizeof (seg_node));
}
/* Peer property not found is ok */
if (rc != PICL_PROPNOTFOUND) {
return (map_plugin_err(rc));
}
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
!= FRU_SUCCESS) {
return (err);
}
!= FRU_SUCCESS) {
return (err);
}
/* while there are sections. */
while (err == FRU_SUCCESS) {
!= FRU_SUCCESS) {
return (err);
}
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
/* LINTED */
return (err);
return (map_plugin_err(picl_err));
}
return (map_plugin_err(picl_err));
}
return (map_plugin_err(picl_err));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
/*
* for every section which has a ADD_SEGMENT_PROP try and add the segment
*/
!= FRU_SUCCESS) {
return (err);
}
do {
== PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
return (map_plugin_err(picl_err));
}
/* ========================================================================= */
static fru_errno_t
{
return (err);
}
return (map_plugin_err(rc));
}
/* ========================================================================= */
static fru_errno_t
{
return (err);
}
/* get the length of the buffer required. */
&add_prop)) != PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
!= PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
return (FRU_NOSPACE);
}
return (FRU_FAILURE);
}
/* write the tag and data into the buffer */
return (map_plugin_err(picl_err));
}
/* ========================================================================= */
static fru_errno_t
{
unsigned int total_tags = 0;
/* return variables */
unsigned int rc_num = 0;
return (err);
}
/* get the number of tags and allocate array for them */
(void *)&total_tags,
sizeof (total_tags))) != PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
if (total_tags == 0) {
return (FRU_SUCCESS);
}
return (FRU_FAILURE);
}
/* go through the tagTable and fill in the array */
return (map_plugin_err(picl_err));
}
while (picl_err == PICL_SUCCESS) {
/* check array bounds */
if (rc_num >= total_tags) {
return (FRU_FAILURE);
}
/* fill in the array */
sizeof (fru_tag_t))) != PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
/* get the next tag */
}
if (picl_err == PICL_ENDOFLIST) {
return (FRU_SUCCESS);
}
return (map_plugin_err(picl_err));
}
/* ========================================================================= */
/*
* From the handle, segment name, tag, and instance of the tag get me:
* segHdl: The segment handle for this segment.
* tagHdl: tag property handle in the tag table for this instance "tag"
*/
static fru_errno_t
{
return (err);
}
return (map_plugin_err(picl_err));
}
while ((picl_err != PICL_ENDOFLIST) &&
(picl_err == PICL_SUCCESS)) {
sizeof (foundTag))) != PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
return (FRU_SUCCESS);
}
}
return (map_plugin_err(picl_err));
}
/* ========================================================================= */
static fru_errno_t
{
int buf_len = 0;
return (err);
}
!= PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
return (FRU_FAILURE);
}
!= PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
{
return (rc);
}
!= PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
!= PICL_SUCCESS) {
return (map_plugin_err(picl_err));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
int instance)
{
/* get tag handle */
return (rc);
}
/* set up key */
/* Write back */
return (map_plugin_err(picl_err));
}
/* ========================================================================= */
static fru_errno_t
void *args)
{
return (status);
/* process each section */
status == PICL_SUCCESS;
§ion,
sizeof (section))) {
continue;
sizeof (num_segments)))
== PICL_PROPNOTFOUND) {
continue;
} else if (status != PICL_SUCCESS) {
continue;
} else if (num_segments == 0) {
continue;
}
/* process each segment */
&segment,
sizeof (segment));
status == PICL_SUCCESS;
&segment,
sizeof (segment))) {
!= FRU_SUCCESS) continue;
args))
!= FRU_SUCCESS) return (status);
}
if (status != PICL_PROPNOTFOUND)
}
if (status != PICL_PROPNOTFOUND)
return (saved_status);
}
/* ========================================================================= */
static fru_errno_t
{
char *propval;
int status;
!= PICL_SUCCESS)
return (map_plugin_err(status));
return (FRU_INVALDATASIZE);
return (FRU_NOSPACE);
!= PICL_SUCCESS) {
return (map_plugin_err(status));
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
void *args),
void *args)
{
int status;
sizeof (descriptor)))
return (FRU_SUCCESS);
return (FRU_SUCCESS);
return (FRU_SUCCESS);
else if (status != PICL_SUCCESS)
return (map_plugin_err(status));
== PICL_SUCCESS) {
!= PICL_SUCCESS) ||
!= PICL_SUCCESS) ||
!= PICL_SUCCESS))
return (map_plugin_err(status));
} else {
}
!= FRU_SUCCESS)) return status;
!= FRU_SUCCESS) return (status);
}
if (status == PICL_ENDOFLIST)
return (FRU_SUCCESS);
else
return (map_plugin_err(status));
}
/* ========================================================================= */
/* ARGSUSED0 */
static fru_errno_t
{
/* LINTED */
return (FRU_FAILURE);
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
static fru_errno_t
shutdown(void)
{
if (picl_shutdown() != PICL_SUCCESS) {
return (FRU_FAILURE);
}
return (FRU_SUCCESS);
}
/* ========================================================================= */
/* object for libfru to link to */
{
};