/**
 * 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;
}
示例#5
0
/**
 * 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;
}