diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/fruadm | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/fruadm')
| -rw-r--r-- | usr/src/cmd/fruadm/Makefile | 60 | ||||
| -rw-r--r-- | usr/src/cmd/fruadm/fruadm.c | 960 |
2 files changed, 1020 insertions, 0 deletions
diff --git a/usr/src/cmd/fruadm/Makefile b/usr/src/cmd/fruadm/Makefile new file mode 100644 index 0000000000..c41aab5218 --- /dev/null +++ b/usr/src/cmd/fruadm/Makefile @@ -0,0 +1,60 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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. +# +# ident "%Z%%M% %I% %E% SMI" +# + +PROG = fruadm +PLATFORM = sun4u +CLASS = 32 # so ParallelMake isn't confused by empty rules + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/Makefile.psm + +FRULIBS = -L$(SRC)/lib/libfru/$(MACH) -lfru + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -I$(SRC)/lib/libfru/include +LINTFLAGS += -u +LDLIBS += $(FRULIBS) -lm + +lint := FRULIBS = + +FILEMODE = 755 +OWNER = root +GROUP = sys + +.KEEP_STATE: + +all: $(PROG) + +install: all $(USR_PSM_SBIN_DIR) $(USR_PSM_SBIN_PROG) + +clean: + +lint: lint_PROG + +include $(SRC)/cmd/Makefile.targ +include $(SRC)/Makefile.psm.targ diff --git a/usr/src/cmd/fruadm/fruadm.c b/usr/src/cmd/fruadm/fruadm.c new file mode 100644 index 0000000000..6a1e533c08 --- /dev/null +++ b/usr/src/cmd/fruadm/fruadm.c @@ -0,0 +1,960 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2002-2003 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 + +static char *command, *customer_data = NULL, *frupath = NULL, **svcargv; + +/* DataElement supported in the customer operation */ +static char *cust_data_list[] = {"Customer_DataR"}; + +/* DataElement supported in the service operation */ +static char *serv_data_list[] = {"InstallationR", "ECO_CurrentR"}; + +/* currently supported segment name */ +static char *segment_name[] = {"FD"}; + +static int found_frupath = 0, list_only = 0, recursive = 0, + service_mode = 0, svcargc, update = 0; + + +static void +usage(void) +{ + (void) fprintf(stderr, + gettext("Usage: %s [ -l ] | [ [ -r ] frupath [ text ] ]\n"), + command); +} + +static int +validate_fieldnames(int argc, char *argv[]) +{ + static int num = sizeof (serv_data_list)/sizeof (*serv_data_list); + + char *fieldname; + + int i, j, match, status; + + fru_elemdef_t definition; + + + for (i = 0; i < argc; i += 2) { + if (argv[i][0] == '/') { + fieldname = &argv[i][1]; + } else { + fieldname = &argv[i][0]; + } + + match = 0; + for (j = 0; j < num; j++) { + if (strncmp(fieldname, serv_data_list[j], + strlen(serv_data_list[j])) == 0) { + match = 1; + } + } + if (!match) { + (void) fprintf(stderr, + gettext("\"%s\" is not a supported field\n"), + argv[i]); + return (1); + } + + if ((status = fru_get_definition(argv[i], &definition)) + != FRU_SUCCESS) { + (void) fprintf(stderr, gettext("\"%s\": %s\n"), + argv[i], + fru_strerror(status)); + return (1); + } else if ((definition.data_type == FDTYPE_Record) || + (definition.data_type == FDTYPE_UNDEFINED)) { + (void) fprintf(stderr, + gettext("\"%s\" is not a field\n"), argv[i]); + return (1); + } + } + + return (0); +} + +static int +pathmatch(const char *path) +{ + char *match; + + if ((frupath != NULL) && + ((match = strstr(path, frupath)) != NULL) && + ((match + strlen(frupath)) == (path + strlen(path))) && + ((match == path) || (*(match - 1) == '/'))) { + found_frupath = 1; + return (1); + } + + return (0); +} + +static void +displayBinary(unsigned char *data, size_t length, fru_elemdef_t *def) +{ + int i = 0; + uint64_t lldata; + uint64_t mask; + + if (def->disp_type == FDISP_Hex) { + for (i = 0; i < length; i++) { + (void) printf("%02X", data[i]); + } + return; + } + + (void) memcpy(&lldata, data, sizeof (lldata)); + switch (def->disp_type) { + case FDISP_Binary: + { + mask = 0x8000000000000000; + for (i = 0; i < (sizeof (uint64_t) *8); i++) { + if (lldata & (mask >> i)) { + (void) printf("1"); + } else { + (void) printf("0"); + } + } + return; + } + case FDISP_Octal: + { + (void) printf("%llo", lldata); + return; + } + case FDISP_Decimal: + { + (void) printf("%lld", lldata); + return; + } + case FDISP_Time: + { + char buffer[PATH_MAX]; + time_t time; + time = (time_t)lldata; + (void) strftime(buffer, PATH_MAX, "%C", + localtime(&time)); + (void) printf("%s", buffer); + return; + } + } +} + +static void +displayBAasBinary(unsigned char *data, size_t length) +{ + 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. + */ + for (mask = 0x80; mask > 0; mask /= 2) { + if ((data[i] & mask) != 0) /* bit must be on */ + (void) printf("1"); + else /* bit is off... */ + (void) printf("0"); + } + } + (void) printf("\n"); +} + +static void +display_data(unsigned char *data, size_t length, fru_elemdef_t *def) +{ + int i = 0; + uint64_t lldata; + + if (data == 0x00) { + (void) printf("\n"); + return; + } + + switch (def->data_type) { + case FDTYPE_Binary: + { + displayBinary(data, length, def); + return; + } + + case FDTYPE_ByteArray: + { + switch (def->disp_type) { + case FDISP_Binary: + displayBAasBinary(data, length); + return; + case FDISP_Hex: + for (i = 0; i < length; i++) { + (void) printf("%02X", data[i]); + } + return; + } + return; + } + case FDTYPE_Unicode: + assert(gettext("Unicode not yet supported") == 0); + break; + case FDTYPE_ASCII: + { + char *disp_str = (char *)alloca(length+1); + for (i = 0; i < length; i++) + disp_str[i] = data[i]; + disp_str[i] = '\0'; + (void) printf("%s", disp_str); + return; + } + + case FDTYPE_Enumeration: + { + lldata = strtoull((const char *)data, NULL, 0); + for (i = 0; i < def->enum_count; i++) { + if (def->enum_table[i].value == lldata) { + /* strdup such that map_... can realloc if necessary. */ + char *tmp = strdup(def->enum_table[i].text); + (void) printf("%s", tmp); + free(tmp); + return; + } + } + (void) printf(gettext("Unrecognized Value: 0x")); + for (i = 0; i < sizeof (uint64_t); i++) + (void) printf("%02X", data[i]); + break; + } + default: + break; + } +} + +static void +print_node_data(fru_nodehdl_t cont_hdl) +{ + int iter_cnt = 0; + int iter; + int numseg; + int list_cnt; + unsigned char *data; + size_t dataLen; + int total_cnt; + char *found_path = NULL; + fru_elemdef_t def, def1; + int instance = 0; + char **ptr; + char **tmp_ptr; + int count = 0; + char elem_name[PATH_MAX]; + + if (service_mode) { + total_cnt = sizeof (serv_data_list)/sizeof (*serv_data_list); + ptr = serv_data_list; + } else { + total_cnt = sizeof (cust_data_list)/sizeof (*cust_data_list); + ptr = cust_data_list; + } + tmp_ptr = ptr; + + for (numseg = 0; numseg < NUM_OF_SEGMENT; numseg++) { + ptr = tmp_ptr; + for (list_cnt = 0; list_cnt < total_cnt; list_cnt++) { + if ((fru_get_definition(*ptr, &def)) != FRU_SUCCESS) { + continue; + } + if ((fru_get_num_iterations(cont_hdl, + &segment_name[numseg], 0, *ptr, + &iter_cnt, NULL)) != FRU_SUCCESS) { + iter_cnt = 0; + } + iter = 0; + do { + for (count = 0; count < def.enum_count; + count++) { + if (def.iteration_type != + FRU_NOT_ITERATED) { + (void) snprintf(elem_name, + sizeof (elem_name), + "/%s[%d]/%s", *ptr, iter, def.enum_table[count].text); + } else { + (void) snprintf(elem_name, + sizeof (elem_name), + "/%s/%s", *ptr, def.enum_table[count].text); + } + + if ((fru_read_field(cont_hdl, + &segment_name[numseg], instance, elem_name, (void**)&data, + &dataLen, &found_path)) != FRU_SUCCESS) { + break; + } + + if ((fru_get_definition( + def.enum_table[count].text, &def1)) != FRU_SUCCESS) { + break; + } + (void) printf(" %s: ",\ + elem_name); + display_data(data, dataLen, &def1); + (void) printf("\n"); + } + iter ++; + } while (iter < iter_cnt); + ptr++; + } + } +} + +static char * +convertBinaryToDecimal(char *ptr) +{ + int cnt = 0; + char *data; + int str_len; + char *ret = NULL; + uint64_t result = 0; + + str_len = strlen(ptr); + data = ptr; + + while (str_len >= 1) { + str_len -= 1; + if (data[str_len] == '0') { + result += (0 * pow(2, cnt)); + } + if (data[str_len] == '1') { + result += (1 * pow(2, cnt)); + } + cnt++; + } + ret = (char *)lltostr(result, "\n"); + 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 +convert_update(fru_nodehdl_t nodehdl, char *segment, char *field_name, + char *field_value) +{ + uint64_t num = 0; + fru_elemdef_t def; + fru_errno_t err; + void *data = NULL; + size_t dataLen = 0; + int i; + + if ((err = fru_get_definition(field_name, &def)) != FRU_SUCCESS) { + (void) fprintf(stderr, + gettext("Failed to get definition %s: %s\n"), + field_name, fru_strerror(err)); + return (1); + } + + if (field_value == NULL) { + return (1); + } + + switch (def.data_type) { + case FDTYPE_Binary: + if (def.disp_type != FDISP_Time) { + if (field_value[0] == 'b') { + field_value = + convertBinaryToDecimal((field_value+1)); + } + num = strtoll(field_value, (char **)NULL, 0); + if ((num == 0) && (errno == 0)) { + return (1); + } + data = (void*)# + dataLen = sizeof (uint64_t); + } + break; + case FDTYPE_ByteArray: + return (1); + case FDTYPE_Unicode: + return (1); + case FDTYPE_ASCII: + data = (void *) field_value; + dataLen = strlen(field_value); + if (dataLen < def.data_length) { + dataLen++; + } + break; + case FDTYPE_Enumeration: + for (i = 0; i < def.enum_count; i++) { + if (strcmp(def.enum_table[i].text, + field_value) == 0) { + data = (void *)def.enum_table[i].value; + dataLen = sizeof (uint64_t); + break; + } + } + return (1); + case FDTYPE_Record: + if (def.iteration_count == 0) { + return (1); + } + data = NULL; + dataLen = 0; + break; + case FDTYPE_UNDEFINED: + return (1); + } + + if ((err = fru_update_field(nodehdl, segment, 0, field_name, data, + dataLen)) != FRU_SUCCESS) { + (void) fprintf(stderr, gettext("fru_update_field(): %s\n"), + 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 +update_unixtimestamp(fru_nodehdl_t nodehdl, char *segment, char **ptr) +{ + char *field_name; + time_t clock; + struct tm *sp_tm; + fru_errno_t err = FRU_SUCCESS; + uint64_t time_data; + size_t len; + + len = strlen(*ptr) + strlen("UNIX_Timestamp32") + 3; + field_name = alloca(len); + + (void) snprintf(field_name, len, "/%s/UNIX_Timestamp32", *ptr); + + clock = time(NULL); + sp_tm = localtime(&clock); + time_data = (uint64_t)mktime(sp_tm); + + if ((err = fru_update_field(nodehdl, segment, 0, field_name, + (void *)&time_data, sizeof (time_data))) != FRU_SUCCESS) { + (void) fprintf(stderr, gettext("fru_update_field(): %s\n"), + fru_strerror(err)); + return (1); + } + return (0); +} + +/* + * create segment on the specified fru represented by nodehdl. + */ + +static int +create_segment(fru_nodehdl_t nodehdl) +{ + fru_segdesc_t seg_desc; + fru_segdef_t def; + int cnt; + + seg_desc.field.field_perm = 0x6; + seg_desc.field.operations_perm = 0x6; + seg_desc.field.engineering_perm = 0x6; + seg_desc.field.repair_perm = 0x6; + + def.address = 0; + def.desc.raw_data = seg_desc.raw_data; + def.hw_desc.all_bits = 0; + + for (cnt = 0; cnt < NUM_OF_SEGMENT; cnt++) { + (void) strncpy(def.name, segment_name[cnt], SEGMENT_NAME_SIZE); + if (cnt == 0) { + def.size = FD_SEGMENT_SIZE; + } + if ((fru_create_segment(nodehdl, &def)) != FRU_SUCCESS) { + continue; + } + return (cnt); + } + 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 +updateiter_record(fru_nodehdl_t nodehdl, int cnt, char **ptr, + char *field_name, char *field_value) +{ + int iter_cnt = 0; + char rec_name[512]; + void *data = NULL; + char *tmpptr = NULL; + size_t dataLen = 0; + char **elem_ptr; + int found = 0; + int index; + int total_cnt; + + static char *elem_list[] = {"/Geo_North", "/Geo_East",\ + "/Geo_Alt", "/Geo_Location"}; + + elem_ptr = elem_list; + total_cnt = sizeof (elem_list)/sizeof (*elem_list); + + for (index = 0; index < total_cnt; index++) { + tmpptr = strrchr(field_name, '/'); + if (tmpptr == NULL) { + (void) fprintf(stderr, + gettext("Error: Data Element not known\n")); + return (1); + } + if ((strncmp(*elem_ptr, tmpptr, strlen(*elem_ptr)) != 0)) { + elem_ptr++; + continue; + } + found = 1; + break; + } + + if (found == 0) { + (void) fprintf(stderr, + gettext("Error: Update not allowed for field: %s\n"), + field_name); + return (1); + } + + if ((fru_get_num_iterations(nodehdl, &segment_name[cnt], 0, + *ptr, &iter_cnt, NULL)) != FRU_SUCCESS) { + return (1); + } + + /* add a new Iterated Record if complete path is not given */ + if (iter_cnt == 0) { + (void) snprintf(rec_name, sizeof (rec_name), "/%s[+]", *ptr); + if ((fru_update_field(nodehdl, segment_name[cnt], 0, + rec_name, data, dataLen)) != FRU_SUCCESS) { + return (1); + } + + iter_cnt = 1; + } + + (void) snprintf(rec_name, sizeof (rec_name), "/%s[%d]%s", + *ptr, iter_cnt-1, strrchr(field_name, '/')); + + if ((convert_update(nodehdl, segment_name[cnt], rec_name, + field_value)) != 0) { + return (1); + } + + /* update success now update the unix timestamp */ + + (void) snprintf(rec_name, sizeof (rec_name), "/%s[%d]", + *ptr, iter_cnt-1); + tmpptr = rec_name; + + /* update UNIX_Timestamp32 with creation time */ + if ((update_unixtimestamp(nodehdl, segment_name[cnt], + &tmpptr)) != 0) { + return (1); + } + + return (0); +} + +static int +update_field(fru_nodehdl_t nodehdl, char *field_name, char *field_value) +{ + fru_elemdef_t def; + unsigned char *data; + size_t dataLen; + char *found_path = NULL; + int cnt; + char **ptr; + fru_strlist_t elem; + int elem_cnt; + int add_flag = 1; + int total_cnt; + + if (service_mode) { + ptr = serv_data_list; + total_cnt = sizeof (serv_data_list)/sizeof (*serv_data_list); + + for (cnt = 0; cnt < total_cnt; cnt++) { + if ((strncmp(*ptr, &field_name[1], strlen(*ptr)) \ + != 0) && (strncmp(*ptr, &field_name[0], + strlen(*ptr)) != 0)) { + ptr++; + add_flag = 0; + continue; + } + add_flag = 1; + break; + } + } else { + ptr = cust_data_list; + } + + /* look for the field in either of the segment if found update it */ + for (cnt = 0; cnt < NUM_OF_SEGMENT; cnt++) { + if ((fru_read_field(nodehdl, &segment_name[cnt], 0, field_name, + (void **) &data, &dataLen, &found_path)) != FRU_SUCCESS) { + continue; + } + if ((fru_get_definition(*ptr, &def)) == FRU_SUCCESS) { + if (def.iteration_count != 0) { + if ((updateiter_record(nodehdl, cnt, ptr, + field_name, field_value)) != 0) { + return (1); + } + return (0); + } + } + + if ((convert_update(nodehdl, segment_name[cnt], + field_name, field_value)) != 0) { + return (1); + } + + /* update UNIX_Timestamp32 with update time */ + if ((update_unixtimestamp(nodehdl, segment_name[cnt], + ptr)) != 0) { + return (1); + } + return (0); + } + + elem.num = 0; + + /* field not found add the the record in one of the segment */ + for (cnt = 0; cnt < NUM_OF_SEGMENT; cnt++) { + fru_list_elems_in(nodehdl, segment_name[cnt], &elem); + for (elem_cnt = 0; elem_cnt < elem.num; elem_cnt++) { + if ((strcmp(*ptr, elem.strs[elem_cnt])) == 0) { + add_flag = 0; + } + } + + if (add_flag) { + if ((fru_add_element(nodehdl, segment_name[cnt], + *ptr)) != FRU_SUCCESS) { + continue; + } + } + + if ((fru_get_definition(*ptr, &def)) == FRU_SUCCESS) { + if (def.iteration_count != 0) { + if ((updateiter_record(nodehdl, cnt, ptr, + field_name, field_value)) != 0) { + return (1); + } + return (0); + } + } + + /* update UNIX_Timestamp32 with creation time */ + if ((update_unixtimestamp(nodehdl, segment_name[cnt], + ptr)) != 0) { + return (1); + } + + /* record added update the field with the value */ + if ((convert_update(nodehdl, segment_name[cnt], field_name, + field_value)) != 0) { + return (1); + } + return (0); + } + + /* segment not present, create one and add the record */ + cnt = create_segment(nodehdl); + if (cnt == 1) { + return (1); + } + + if ((fru_add_element(nodehdl, segment_name[cnt], *ptr)) + != FRU_SUCCESS) { + return (1); + } + + if ((fru_get_definition(*ptr, &def)) == FRU_SUCCESS) { + if (def.iteration_count != 0) { + if ((updateiter_record(nodehdl, cnt, ptr, + field_name, field_value)) != 0) { + return (1); + } + return (0); + } + } + + /* update UNIX_Timestamp32 with creation time */ + if ((update_unixtimestamp(nodehdl, segment_name[cnt], + ptr)) != 0) { + return (1); + } + + if ((convert_update(nodehdl, segment_name[cnt], field_name, + field_value)) != 0) { + return (1); + } + return (0); +} + +static void +update_node_data(fru_nodehdl_t node) +{ + int i; + + if (service_mode) { + for (i = 0; i < svcargc; i += 2) + (void) update_field(node, svcargv[i], svcargv[i + 1]); + } else { + (void) update_field(node, "/Customer_DataR/Cust_Data", + customer_data); + } +} + +static void +walk_tree(fru_nodehdl_t node, const char *prior_path, int process_tree) +{ + char *name, path[PATH_MAX]; + int process_self = process_tree, status; + fru_nodehdl_t next_node; + fru_node_t type; + + if ((status = fru_get_node_type(node, &type)) != FRU_SUCCESS) { + (void) fprintf(stderr, + gettext("Error getting FRU tree node type: %s\n"), + fru_strerror(status)); + exit(1); + } + + if ((status = fru_get_name_from_hdl(node, &name)) != FRU_SUCCESS) { + (void) fprintf(stderr, + gettext("Error getting name of FRU tree node: %s\n"), + fru_strerror(status)); + exit(1); + } + + + /* + * Build the current path + */ + if (snprintf(path, sizeof (path), "%s/%s", prior_path, name) + >= sizeof (path)) { + (void) fprintf(stderr, + gettext("FRU tree path would overflow buffer\n")); + exit(1); + } + + free(name); + + /* + * Process the node + */ + if (list_only) { + (void) printf("%s%s\n", path, ((type == FRU_NODE_FRU) ? + " (fru)" : ((type == FRU_NODE_CONTAINER) ? + " (container)" : ""))); + } else if ((process_tree || (process_self = pathmatch(path))) && + (type == FRU_NODE_CONTAINER)) { + (void) printf("%s\n", path); + if (update) update_node_data(node); + print_node_data(node); + if (!recursive) exit(0); + } else if (process_self && !recursive) { + (void) fprintf(stderr, + gettext("\"%s\" is not a container\n"), path); + exit(1); + } + + + /* + * Recurse + */ + if (fru_get_child(node, &next_node) == FRU_SUCCESS) + walk_tree(next_node, path, process_self); + + if (fru_get_peer(node, &next_node) == FRU_SUCCESS) + walk_tree(next_node, prior_path, process_tree); +} + +static int +has_system_controller() +{ + char platform[PATH_MAX]; + + int size; + + if (((size = sysinfo(SI_PLATFORM, platform, sizeof (platform))) + < 0) || (size > sizeof (platform))) + return (-1); + + if ((strcmp("SUNW,Sun-Fire", platform) == 0) || + (strcmp("SUNW,Sun-Fire-15000", platform) == 0)) { + return (1); + } + + return (0); +} + +int +main(int argc, char *argv[]) +{ + int process_tree = 0, option, status; + + fru_nodehdl_t root; + + + command = argv[0]; + + opterr = 0; /* "getopt" should not print to "stderr" */ + while ((option = getopt(argc, argv, "lrs")) != EOF) { + switch (option) { + case 'l': + list_only = 1; + break; + case 'r': + recursive = 1; + break; + case 's': + service_mode = 1; + break; + default: + usage(); + return (1); + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) { + process_tree = 1; + recursive = 1; + } else { + if (list_only) { + usage(); + return (1); + } + + frupath = argv[0]; + if (*frupath == 0) { + usage(); + (void) fprintf(stderr, + gettext("\"frupath\" should not be empty\n")); + return (1); + } + + argc--; + argv++; + + if (argc > 0) { + update = 1; + if (service_mode) { + if ((argc % 2) != 0) { + (void) fprintf(stderr, + gettext("Must specify " + "field-value pairs " + "for update\n")); + return (1); + } + + if (validate_fieldnames(argc, argv) != 0) { + return (1); + } + + svcargc = argc; + svcargv = argv; + } else if (argc == 1) + customer_data = argv[0]; + else { + usage(); + return (1); + } + } + } + + if ((status = fru_open_data_source("picl", NULL)) != FRU_SUCCESS) { + (void) fprintf(stderr, + gettext("Unable to access FRU data source: %s\n"), + fru_strerror(status)); + return (1); + } + + if ((status = fru_get_root(&root)) == FRU_NODENOTFOUND) { + if (has_system_controller() == 1) { + (void) fprintf(stderr, + gettext("Access FRUs from the " + "System Controller\n")); + } else { + (void) fprintf(stderr, + gettext("This system does not provide " + "FRU ID data\n")); + + } + return (1); + } else if (status != FRU_SUCCESS) { + (void) fprintf(stderr, + gettext("Unable to access FRU ID data " + "due to data source error\n")); + return (1); + } + + walk_tree(root, "", process_tree); + + if ((frupath != NULL) && (!found_frupath)) { + (void) fprintf(stderr, + gettext("\"%s\" not found\n"), + frupath); + return (1); + } + + return (0); +} |
