fruadm.c revision 821a83dbe7cba700cd57da95bf981850118f369e
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#include <libfru.h>
#include <errno.h>
#include <math.h>
#include <alloca.h>
#include <assert.h>
#include <sys/systeminfo.h>
#define NUM_OF_SEGMENT 1
#define SEGMENT_NAME_SIZE 2
#define FD_SEGMENT_SIZE 2949
/* DataElement supported in the customer operation */
static char *cust_data_list[] = {"Customer_DataR"};
/* DataElement supported in the service operation */
/* currently supported segment name */
static char *segment_name[] = {"FD"};
static void
usage(void)
{
gettext("Usage: %s [ -l ] | [ [ -r ] frupath [ text ] ]\n"),
command);
}
static int
{
char *fieldname;
for (i = 0; i < argc; i += 2) {
if (argv[i][0] == '/') {
} else {
}
match = 0;
for (j = 0; j < num; j++) {
strlen(serv_data_list[j])) == 0) {
match = 1;
}
}
if (!match) {
gettext("\"%s\" is not a supported field\n"),
argv[i]);
return (1);
}
!= FRU_SUCCESS) {
argv[i],
return (1);
return (1);
}
}
return (0);
}
static int
{
char *match;
found_frupath = 1;
return (1);
}
return (0);
}
static void
{
int i = 0;
for (i = 0; i < length; i++) {
}
return;
}
case FDISP_Binary:
{
mask = 0x8000000000000000ULL;
for (i = 0; i < (sizeof (uint64_t) *8); i++) {
(void) printf("1");
} else {
(void) printf("0");
}
}
return;
}
case FDISP_Octal:
{
return;
}
case FDISP_Decimal:
{
return;
}
case FDISP_Time:
{
return;
}
}
}
static void
{
int i;
unsigned char mask;
for (i = 0; i < length; i++) {
/*
* make a mask for the high order bit and adjust down through
* all the bits.
*/
(void) printf("1");
else /* bit is off... */
(void) printf("0");
}
}
(void) printf("\n");
}
static void
{
int i = 0;
if (data == 0x00) {
(void) printf("\n");
return;
}
case FDTYPE_Binary:
{
return;
}
case FDTYPE_ByteArray:
{
case FDISP_Binary:
return;
case FDISP_Hex:
for (i = 0; i < length; i++) {
}
return;
}
return;
}
case FDTYPE_Unicode:
break;
case FDTYPE_ASCII:
{
for (i = 0; i < length; i++)
disp_str[i] = '\0';
return;
}
case FDTYPE_Enumeration:
{
for (i = 0; i < def->enum_count; i++) {
/* strdup such that map_... can realloc if necessary. */
return;
}
}
for (i = 0; i < sizeof (uint64_t); i++)
break;
}
default:
break;
}
}
static void
{
int iter_cnt = 0;
int iter;
int numseg;
int list_cnt;
unsigned char *data;
int total_cnt;
char *found_path = NULL;
int instance = 0;
char **ptr;
char **tmp_ptr;
int count = 0;
if (service_mode) {
} else {
}
continue;
}
iter_cnt = 0;
}
iter = 0;
do {
count++) {
if (def.iteration_type !=
sizeof (elem_name),
} else {
sizeof (elem_name),
}
if ((fru_read_field(cont_hdl,
break;
}
if ((fru_get_definition(
break;
}
(void) printf(" %s: ",\
(void) printf("\n");
}
iter ++;
ptr++;
}
}
}
static char *
convertBinaryToDecimal(char *ptr)
{
int cnt = 0;
char *data;
int str_len;
while (str_len >= 1) {
str_len -= 1;
}
}
cnt++;
}
return (ret);
}
/*
* called update_field() to update the field with specific field value.
* nodehdl represents the fru, segment represents the segment name in the fru.
* field_name represents the field to be updated with the value field_value.
*/
static int
char *field_value)
{
int i;
gettext("Failed to get definition %s: %s\n"),
return (1);
}
if (field_value == NULL) {
return (1);
}
case FDTYPE_Binary:
if (field_value[0] == 'b') {
}
return (1);
}
}
break;
case FDTYPE_ByteArray:
return (1);
case FDTYPE_Unicode:
return (1);
case FDTYPE_ASCII:
data = (void *) field_value;
dataLen++;
}
break;
case FDTYPE_Enumeration:
for (i = 0; i < def.enum_count; i++) {
field_value) == 0) {
break;
}
}
return (1);
case FDTYPE_Record:
if (def.iteration_count == 0) {
return (1);
}
dataLen = 0;
break;
case FDTYPE_UNDEFINED:
return (1);
}
dataLen)) != FRU_SUCCESS) {
fru_strerror(err));
return (1);
}
return (0);
}
/*
* called by update_field() when a new data element is created.
* it updates the UNIX_Timestamp32 field with the current system time.
*/
static int
{
char *field_name;
fru_strerror(err));
return (1);
}
return (0);
}
/*
* create segment on the specified fru represented by nodehdl.
*/
static int
{
int cnt;
int status;
if (cnt == 0) {
}
!= FRU_SUCCESS) {
continue;
}
return (cnt);
}
if (status != FRU_SUCCESS)
return (1);
}
/*
* called from update_field() when service flag is ON. currently
* supported iterated record is InstallationR and fields supported for
* update are Geo_North, Geo_East, Geo_Alt, Geo_Location.
*/
static int
char *field_name, char *field_value)
{
int iter_cnt = 0;
char rec_name[512];
char **elem_ptr;
int found = 0;
int index;
int total_cnt;
"/Geo_Alt", "/Geo_Location"};
gettext("Error: Data Element not known\n"));
return (1);
}
elem_ptr++;
continue;
}
found = 1;
break;
}
if (found == 0) {
gettext("Error: Update not allowed for field: %s\n"),
return (1);
}
return (1);
}
/* add a new Iterated Record if complete path is not given */
if (iter_cnt == 0) {
gettext("fru_update_field(): %s\n"),
fru_strerror(err));
return (1);
}
iter_cnt = 1;
}
field_value)) != 0) {
return (1);
}
/* update success now update the unix timestamp */
/* update UNIX_Timestamp32 with creation time */
&tmpptr)) != 0) {
return (1);
}
return (0);
}
static int
{
unsigned char *data;
char *found_path = NULL;
int cnt;
char **ptr;
int elem_cnt;
int add_flag = 1;
int total_cnt;
int status;
if (service_mode) {
ptr++;
add_flag = 0;
continue;
}
add_flag = 1;
break;
}
} else {
}
/* look for the field in either of the segment if found update it */
continue;
}
if (def.iteration_count != 0) {
field_name, field_value)) != 0) {
return (1);
}
return (0);
}
}
field_name, field_value)) != 0) {
return (1);
}
/* update UNIX_Timestamp32 with update time */
ptr)) != 0) {
return (1);
}
return (0);
}
/* field not found add the the record in one of the segment */
add_flag = 0;
}
}
if (add_flag) {
*ptr)) != FRU_SUCCESS) {
continue;
}
}
if (def.iteration_count != 0) {
field_name, field_value)) != 0) {
return (1);
}
return (0);
}
}
/* update UNIX_Timestamp32 with creation time */
ptr)) != 0) {
return (1);
}
/* record added update the field with the value */
field_value)) != 0) {
return (1);
}
return (0);
}
/* segment not present, create one and add the record */
if (cnt == 1) {
return (1);
}
!= FRU_SUCCESS) {
return (1);
}
if (def.iteration_count != 0) {
field_name, field_value)) != 0) {
return (1);
}
return (0);
}
}
/* update UNIX_Timestamp32 with creation time */
ptr)) != 0) {
return (1);
}
field_value)) != 0) {
return (1);
}
return (0);
}
static void
{
int i;
if (service_mode) {
for (i = 0; i < svcargc; i += 2)
} else {
}
}
static void
{
gettext("Error getting FRU tree node type: %s\n"),
exit(1);
}
gettext("Error getting name of FRU tree node: %s\n"),
exit(1);
}
/*
* Build the current path
*/
>= sizeof (path)) {
gettext("FRU tree path would overflow buffer\n"));
exit(1);
}
/*
* Process the node
*/
if (list_only) {
" (container)" : "")));
(type == FRU_NODE_CONTAINER)) {
} else if (process_self && !recursive) {
exit(1);
}
/*
* Recurse
*/
}
static int
{
int size;
return (-1);
return (1);
}
return (0);
}
int
{
opterr = 0; /* "getopt" should not print to "stderr" */
switch (option) {
case 'l':
list_only = 1;
break;
case 'r':
recursive = 1;
break;
case 's':
service_mode = 1;
break;
default:
usage();
return (1);
}
}
if (argc == 0) {
process_tree = 1;
recursive = 1;
} else {
if (list_only) {
usage();
return (1);
}
if (*frupath == 0) {
usage();
gettext("\"frupath\" should not be empty\n"));
return (1);
}
argc--;
argv++;
if (argc > 0) {
update = 1;
if (service_mode) {
if ((argc % 2) != 0) {
gettext("Must specify "
"field-value pairs "
"for update\n"));
return (1);
}
return (1);
}
} else if (argc == 1)
customer_data = argv[0];
else {
usage();
return (1);
}
}
}
gettext("Unable to access FRU data source: %s\n"),
return (1);
}
if (has_system_controller() == 1) {
gettext("Access FRUs from the "
"System Controller\n"));
} else {
gettext("This system does not provide "
"FRU ID data\n"));
}
return (1);
} else if (status != FRU_SUCCESS) {
gettext("Unable to access FRU ID data "
"due to data source error\n"));
return (1);
}
gettext("\"%s\" not found\n"),
frupath);
return (1);
}
return (0);
}