/** * parse_work_area - Parse the working buffer * * @loc list to add new data to * @buf working area to parse * * Returns : * pointer to new loc_code list */ static struct loc_code * parse_rtas_workarea(struct loc_code *loc, const char *buf) { int i; uint32_t num = be32toh(*(uint32_t *)buf); struct loc_code *curr = loc; if (curr) while (curr->next) curr = curr->next; buf += sizeof(uint32_t); for (i = 0; i < num; i++) { if (!curr) { curr = calloc(1, sizeof(struct loc_code)); loc = curr; } else { curr->next = calloc(1, sizeof(struct loc_code)); curr = curr->next; } if (!curr) { log_msg("Out of memory"); /* free up previously allocated memory */ free_indicator_list(loc); return NULL; } /* * NOTE: Location code length and location code string combined * is given as the input to LED indicator related rtas calls. So * the buffer representation of the location code length and * location code string must be PAPR compliant and big endian at * all times. Convert the location code length to host format when * ever required on the need basis. */ curr->index = be32toh(*(uint32_t *)buf); buf += sizeof(uint32_t); /* Includes NULL char */ curr->length = be32toh(*(uint32_t *)buf); buf += sizeof(uint32_t); /* Corrupted work area */ if (curr->length > LOCATION_LENGTH) { free_indicator_list(loc); return NULL; } strncpy(curr->code, buf, curr->length); buf += curr->length; curr->code[curr->length] = '\0'; curr->length = strlen(curr->code) + 1; curr->length = htobe32(curr->length); curr->type = TYPE_RTAS; curr->next = NULL; } return loc; }
/* * opal_indicator_probe_marvell - Probe Marvell indicator support on * OPAL based platform * * Returns: * 0 if indicator is supported, else -1 */ static int opal_indicator_probe_marvell(void) { struct loc_code *list = NULL; get_mv_indices(LED_TYPE_IDENT, &list); if (list) { free_indicator_list(list); return 0; } return -1; }
/** * get_rtas_indicator_mode - Gets the service indicator operating mode * * Note: There is no defined property in PAPR+ to determine the indicator * operating mode. There is some work being done to get property * into PAPR. When that is done we will check for that property. * * At present, we will query RTAS fault indicators. It should return * at least one fault indicator, that is check log indicator. If only * one indicator is returned, then Guiding Light mode else Light Path * mode. * * Returns : * operating mode value */ static int get_rtas_indicator_mode(void) { int rc; struct loc_code *list = NULL; rc = get_rtas_indices(LED_TYPE_FAULT, &list); if (rc) return -1; if (!list) /* failed */ return -1; else if (!list->next) operating_mode = LED_MODE_GUIDING_LIGHT; else operating_mode = LED_MODE_LIGHT_PATH; free_indicator_list(list); return 0; }
/** * get_rtas_list - Gets rtas indicator list * * @indicator identification or attention indicator * @loc pointer to loc_code structure * * Returns : * rtas call return value */ static int get_rtas_indices(int indicator, struct loc_code **loc) { int rc; int index = 1; int next_index; int rtas_token; char workarea[BUF_SIZE]; char err_buf[RTAS_ERROR_BUF_SIZE]; struct loc_code *list = NULL; rtas_token = get_rtas_token(indicator); if (rtas_token == -1) return -3; /* Indicator type not supported */ do { rc = rtas_get_indices(0, rtas_token, workarea, BUF_SIZE, index, &next_index); switch (rc) { case 1: /* more data available */ index = next_index; /* fall through */ case 0: /* success */ list = parse_rtas_workarea(list, workarea); if (!list) return -99; /* Out of heap memory */ break; case -1: /* hardware error */ log_msg("Hardware error retrieving indicator indices"); free_indicator_list(list); break; case RTAS_UNKNOWN_OP: /* Yes, this is a librtas return code but it should * be treated the same as a -3 return code, both * indicate that functionality is not supported */ librtas_error(rc, err_buf, RTAS_ERROR_BUF_SIZE); /* fall through */ case -3: /* indicator type not supported. */ log_msg("The %s indicators are not supported on this " "system", get_indicator_desc(indicator)); if (rc == RTAS_UNKNOWN_OP) log_msg(",\n%s", err_buf); free_indicator_list(list); break; case -4: /* list changed; start over */ free_indicator_list(list); list = NULL; index = 1; break; default: librtas_error(rc, err_buf, RTAS_ERROR_BUF_SIZE); log_msg("Could not retrieve data for %s " "indicators,\n%s", get_indicator_desc(indicator), err_buf); free_indicator_list(list); break; } } while ((rc == 1) || (rc == -4)); *loc = list; return rc; }
/** * main - */ int main(int argc, char **argv) { int c; int state; int index; int indicator; int rc = 0; int trunc = 0; int truncated = 0; int platform = 0; char temp[LOCATION_LENGTH]; char dloc[LOCATION_LENGTH]; char *dvalue = NULL; char *lvalue = NULL; char *svalue = NULL; char *othervalue = NULL; struct loc_code *current; struct loc_code *list = NULL; platform = get_platform(); if (platform != PLATFORM_PSERIES_LPAR) { fprintf(stderr, "%s is not supported on the %s platform\n", argv[0], __power_platform_name(platform)); return 1; } opterr = 0; while ((c = getopt(argc, argv, CMD_LINE_OPTIONS)) != -1) { switch (c) { case 'd': /* Device name */ dvalue = optarg; break; case 'l': /* Location code */ lvalue = optarg; break; case 's': /* Enable/disable */ svalue = optarg; break; case '-': /* All location code */ othervalue = optarg; break; case 't': /* truncate location code */ trunc = 1; break; case 'V': fprintf(stdout, "%s %s\n", argv[0], VERSION); fflush(stdout); return 0; case 'h': print_usage(argv[0]); return 0; case '?': if (isprint(optopt)) fprintf(stderr, "Unrecognized option: -%c\n\n", optopt); else fprintf(stderr, "Unrecognized option character %x\n\n", optopt); print_usage(argv[0]); return 1; default: print_usage(argv[0]); return 1; } } /* Option checking */ for (index = optind; index < argc; index++) { fprintf(stderr, "Unrecognized argument : %s\n\n", argv[index]); print_usage(argv[0]); return 1; } if (dvalue && !strstr(argv[0], CMD_IDENTIFY)) { fprintf(stderr, "Unrecognized option: -d\n\n"); print_usage(argv[0]); return 1; } if (dvalue && lvalue) { fprintf(stderr, "The -d and -l options cannot be used together.\n\n"); print_usage(argv[0]); return 1; } if (svalue && strstr(argv[0], CMD_IDENTIFY)) { if (!strcmp(svalue, "identify")) c = INDICATOR_ON; else if (!strcmp(svalue, "normal")) c = INDICATOR_OFF; else { fprintf(stderr, "The -s option must be either " "\"identify\" or \"normal\".\n\n"); print_usage(argv[0]); return 1; } } if (svalue && (strstr(argv[0], CMD_FAULT) || strstr(argv[0], CMD_ATTN))) { if (!strcmp(svalue, "normal")) c = INDICATOR_OFF; else { fprintf(stderr, "The -s option must be \"normal\".\n\n"); print_usage(argv[0]); return 1; } } if (svalue && !(dvalue || lvalue)) { if (strstr(argv[0], CMD_IDENTIFY)) fprintf(stderr, "The -s option requires the -d or -l " "option to also be used.\n\n"); else fprintf(stderr, "The -s option requires the -l " "option to also be used.\n\n"); print_usage(argv[0]); return 1; } if (svalue && geteuid() != 0) { fprintf(stderr, "%s: Turning indicator on/off requires " "superuser privileges.\n\n", argv[0]); return 1; } if (trunc && !(dvalue || lvalue)) { if (strstr(argv[0], CMD_IDENTIFY)) fprintf(stderr, "The -t option requires the -d or -l " "option to also be used.\n\n"); else fprintf(stderr, "The -t option requires the -l " "option to also be used.\n\n"); print_usage(argv[0]); return 1; } if (othervalue && strstr(argv[0], CMD_IDENTIFY)) { if (!strcmp(othervalue, "all-on")) c = INDICATOR_ON; else if (!strcmp(othervalue, "all-off")) c = INDICATOR_OFF; else { fprintf(stderr, "Unrecognized option: --%s\n\n", othervalue); print_usage(argv[0]); return 1; } } if (othervalue && (strstr(argv[0], CMD_ATTN) || strstr(argv[0], CMD_FAULT))) { if (!strcmp(othervalue, "all-off")) c = INDICATOR_OFF; else { fprintf(stderr, "Unrecognized option: --%s\n\n", othervalue); print_usage(argv[0]); return 1; } } if (othervalue && argc > 2) { fprintf(stderr, "\"--%s\" cannot be used with any other options.\n\n", othervalue); print_usage(argv[0]); return 1; } if (strstr(argv[0], CMD_IDENTIFY)) indicator = IDENT_INDICATOR; else if (strstr(argv[0], CMD_FAULT) || strstr(argv[0], CMD_ATTN)) indicator = ATTN_INDICATOR; else return 1; /* initialize */ program_name = argv[0]; lp_error_log_fd = 1; /* log message to stdout */ rc = init_files(); if (rc) { fprintf(stderr, "Unable to open log file.\n"); return 1; } /* Light Path operating mode */ if (indicator == ATTN_INDICATOR) { rc = check_operating_mode(); if (rc) return rc; } /* get indicator list */ rc = get_indicator_list(indicator, &list); if (rc) goto file_cleanup; if (argc == 1) { current = list; while (current) { /* get and print all indicators current state */ rc = get_indicator_state(indicator, current, &state); if (rc) /* failed to get indicator state */ current->state = -1; else current->state = state; print_indicator_state(current); current = current->next; } } /* Turn on/off indicator based on device name */ if (dvalue) { if (get_loc_code_for_dev(dvalue, dloc, LOCATION_LENGTH) != 0) { fprintf(stderr, "\"%s\" is not a valid device or " "it does not have location code.\n", dvalue); rc = 2; } else { lvalue = dloc; fprintf(stdout, "%s is at location code %s.\n", dvalue, lvalue); } } /* Turn on/off indicator based on location code */ if (lvalue) { strncpy(temp, lvalue, LOCATION_LENGTH); retry: current = get_indicator_for_loc_code(list, lvalue); if (!current) { if (trunc) { if (truncate_loc_code(lvalue)) { truncated = 1; goto retry; } } fprintf(stdout, "There is no %s indicator at location " "code %s.\n", INDICATOR_TYPE(indicator), temp); rc = 1; } else { /* Found location code */ if (truncated) fprintf(stdout, "Truncated location code : " "%s\n", lvalue); if (svalue) { rc = get_indicator_state(indicator, current, &state); if (rc || state != c) { rc = set_indicator_state(indicator, current, c); if (rc) goto indicator_cleanup; indicator_log_state(indicator, current->code, c); } } rc = get_indicator_state(indicator, current, &state); if (!rc) { if (dvalue) fprintf(stdout, "%s\t[%s]\n", lvalue, state ? "on" : "off"); else fprintf(stdout, "%s\n", state ? "on" : "off"); } } /* if-else end */ } /* lvalue end */ /* Turn on/off all indicators */ if (othervalue) { current = list; while (current) { rc = get_indicator_state(indicator, current, &state); if (rc) /* failed to get indicator state */ current->state = -1; else current->state = state; if (state != c) { set_indicator_state(indicator, current, c); rc = get_indicator_state(indicator, current, &state); if (rc) /* failed to get indicator state */ current->state = -1; else current->state = state; } print_indicator_state(current); current = current->next; } /* If enclosure ident indicator is turned ON explicitly, * then turning OFF all components ident indicator inside * enclosure does not turn OFF enclosure ident indicator. */ if (indicator == IDENT_INDICATOR && c == INDICATOR_OFF) set_indicator_state(indicator, &list[0], c); indicator_log_write("All %s Indicators : %s", indicator == IDENT_INDICATOR ? "Identify" : "Fault", c == INDICATOR_ON ? "ON" : "OFF"); } indicator_cleanup: free_indicator_list(list); file_cleanup: close_files(); return rc; }