diff options
Diffstat (limited to 'lib/ipmi_picmg.c')
| -rw-r--r-- | lib/ipmi_picmg.c | 147 | 
1 files changed, 76 insertions, 71 deletions
diff --git a/lib/ipmi_picmg.c b/lib/ipmi_picmg.c index 7a66aa5..f47577e 100644 --- a/lib/ipmi_picmg.c +++ b/lib/ipmi_picmg.c @@ -417,27 +417,6 @@ is_led_color(const char *argv_ptr, uint8_t *led_color_ptr)  	lprintf(LOG_ERR, "LED Color must be from ranges: <1..6>, <0xE..0xF>");  	return (-1);  } -/* is_led_duration - wrapper to convert user input into integer. - * LED duration range is <1..127> - * - * @argv_ptr: source string to convert from; usually argv - * @enable_ptr: pointer where to store result - * returns: zero on success, other values mean error - */ -int -is_led_duration(const char *argv_ptr, uint8_t *led_duration_ptr) -{ -	if (!argv_ptr || !led_duration_ptr) { -		lprintf(LOG_ERR, "is_led_duration(): invalid argument(s)."); -		return (-1); -	} -	if (str2uchar(argv_ptr, led_duration_ptr) == 0 -			&& *led_duration_ptr > 0 && *led_duration_ptr <= 127) { -		return 0; -	} -	lprintf(LOG_ERR, "Given LED Duration '%s' is invalid", argv_ptr); -	return (-1); -}  /* is_led_function - wrapper to convert user input into integer.   * LED functions, however, might differ by OEM:   * - 0x00 - off override @@ -772,21 +751,19 @@ ipmi_picmg_fru_activation_policy_set(struct ipmi_intf * intf, int argc, char **  	if (is_fru_id(argv[0], &msg_data[1]) != 0) {  		return (-1);  	} -	if (str2uchar(argv[1], &msg_data[2]) != 0 || msg_data[2] > 1) { +	if (str2uchar(argv[1], &msg_data[2]) != 0 || msg_data[2] > 3) {  		/* FRU Lock Mask */  		lprintf(LOG_ERR, "Given FRU Lock Mask '%s' is invalid.",  				argv[1]);  		return (-1);  	} -	if (str2uchar(argv[2], &msg_data[3]) != 0 || msg_data[3] > 1) { +	if (str2uchar(argv[2], &msg_data[3]) != 0 || msg_data[3] > 3) {  		/* FRU Act Policy */  		lprintf(LOG_ERR,  				"Given FRU Activation Policy '%s' is invalid.",  				argv[2]);  		return (-1);  	} -	msg_data[2]&= 0x03; -	msg_data[3]&= 0x03;  	rsp = intf->sendrecv(intf, &req); @@ -1363,19 +1340,55 @@ ipmi_picmg_set_led_state(struct ipmi_intf * intf, int argc, char ** argv)  	memset(&req, 0, sizeof(req));  	req.msg.netfn = IPMI_NETFN_PICMG; -	req.msg.cmd	  = PICMG_SET_FRU_LED_STATE_CMD; -	req.msg.data  = msg_data; +	req.msg.cmd = PICMG_SET_FRU_LED_STATE_CMD; +	req.msg.data = msg_data;  	req.msg.data_len = 6;  	msg_data[0] = 0x00;									/* PICMG identifier */  	if (is_fru_id(argv[0], &msg_data[1]) != 0  			|| is_led_id(argv[1], &msg_data[2]) != 0  			|| is_led_function(argv[2], &msg_data[3]) != 0 -			|| is_led_duration(argv[3], &msg_data[4]) != 0  			|| is_led_color(argv[4], &msg_data[5]) != 0) {  		return (-1);  	} +	/* Validating the LED duration is not as simple as the other arguments, as +	 * the range of valid durations depends on the LED function.  From the spec: +	 * +	 * ``On-duration: LED on-time in tens of milliseconds if (1 <= Byte 4 <= FAh) +	 * Lamp Test time in hundreds of milliseconds if (Byte 4 = FBh). Lamp Test +	 * time value must be less than 128. Other values when Byte 4 = FBh are +	 * reserved. Otherwise, this field is ignored and shall be set to 0h.'' +	 * +	 * If we're doing a lamp test, then the allowed values are 0 -> 127. +	 * Otherwise, the allowed values are 0 -> 255.  However, if the function is +	 * not a lamp test (0xFB) and outside the range 0x01 -> 0xFA then the value +	 * should be set to 0. +	 * +	 * Start by checking we have a parameter. +	 */ +	if (!argv[3]) { +		lprintf(LOG_ERR, "LED Duration: invalid argument(s)."); +		return (-1); +	} +	/* Next check we have a number. */ +	if (str2uchar(argv[3], &msg_data[4]) != 0) { +		lprintf(LOG_ERR, "Given LED Duration '%s' is invalid", argv[3]); +		return (-1); +	} +	/* If we have a lamp test, ensure it's not too long a duration. */ +	if (msg_data[3] == 0xFB && msg_data[4] > 127) { +		lprintf(LOG_ERR, "Given LED Duration '%s' is invalid", argv[3]); +		return (-1); +	} +	/* If we're outside the range that allows durations, set the duration to 0. +	 * Warn the user that we're doing this. +	 */ +	if (msg_data[4] != 0 && (msg_data[3] == 0 || msg_data[3] > 0xFB)) { +		lprintf(LOG_WARN, "Setting LED Duration '%s' to '0'", argv[3]); +		msg_data[4] = 0; +	} +  	rsp = intf->sendrecv(intf, &req);  	if (!rsp) { @@ -1745,18 +1758,8 @@ ipmi_picmg_clk_set(struct ipmi_intf * intf, int argc, char ** argv)        }     } -#if 1 -printf("## ID:      %d\n", msg_data[1]); -printf("## index:   %d\n", msg_data[2]); -printf("## setting: 0x%02x\n", msg_data[3]); -printf("## family:  %d\n", msg_data[4]); -printf("## acc:     %d\n", msg_data[5]); -printf("## freq:    %ld\n", freq ); -printf("## res:     %d\n", msg_data[10]); -#endif  	rsp = intf->sendrecv(intf, &req); -  	if (!rsp) {  		lprintf(LOG_ERR, "No valid response received.");  		return -1; @@ -2137,8 +2140,8 @@ ipmi_picmg_main (struct ipmi_intf * intf, int argc, char ** argv)  					lprintf(LOG_NOTICE,  							"               252:     LED restore to local control");  					lprintf(LOG_NOTICE, "               255:     LED ON override"); -					lprintf(LOG_NOTICE, -							"   <duration>  1 - 127: LED Lamp Test / on duration"); +					lprintf(LOG_NOTICE, "   <duration>  0 - 127: LED Lamp Test duration"); +					lprintf(LOG_NOTICE, "               0 - 255: LED Lamp ON duration");  					lprintf(LOG_NOTICE, "   <color>     0:   reserved");  					lprintf(LOG_NOTICE, "               1:   BLUE");  					lprintf(LOG_NOTICE, "               2:   RED"); @@ -2335,37 +2338,39 @@ picmg_discover(struct ipmi_intf *intf) {  	struct ipmi_rq req;  	struct ipmi_rs *rsp;  	char msg_data; +	uint8_t picmg_avail = 0; -	if (intf->picmg_avail == 0) { -		memset(&req, 0, sizeof(req)); -		req.msg.netfn = IPMI_NETFN_PICMG; -		req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD; -		msg_data    = 0x00; -		req.msg.data = &msg_data; -		req.msg.data_len = 1; -		msg_data = 0; - -		lprintf(LOG_DEBUG, "Running Get PICMG Properties my_addr %#x, transit %#x, target %#x", -			intf->my_addr, intf->transit_addr, intf->target_addr); -		rsp = intf->sendrecv(intf, &req); -		if (rsp && !rsp->ccode) { -			if ( (rsp->data[0] == 0) && -					((rsp->data[1] & 0x0F) == PICMG_ATCA_MAJOR_VERSION -					|| (rsp->data[1] & 0x0F) == PICMG_AMC_MAJOR_VERSION) )	{ -				intf->picmg_avail = 1; -				lprintf(LOG_DEBUG, "Discovered PICMG Extension %d.%d", -						(rsp->data[1] & 0x0f), (rsp->data[1] >> 4)); -			} -		} else { -			if (rsp == NULL) { -				lprintf(LOG_DEBUG,"No Response from Get PICMG Properties"); -			} else { -				lprintf(LOG_DEBUG,"Error Response %#x from Get PICMG Properities", rsp->ccode); -			} -		} -	} -	if (intf->picmg_avail == 0) { -		lprintf(LOG_DEBUG, "No PICMG Extenstion discovered"); +	memset(&req, 0, sizeof(req)); +	req.msg.netfn = IPMI_NETFN_PICMG; +	req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD; +	msg_data    = 0x00; +	req.msg.data = &msg_data; +	req.msg.data_len = 1; +	msg_data = 0; + +	lprintf(LOG_INFO, "Running Get PICMG Properties my_addr %#x, transit %#x, target %#x", +		intf->my_addr, intf->transit_addr, intf->target_addr); +	rsp = intf->sendrecv(intf, &req); +	if (rsp == NULL) { +	    lprintf(LOG_INFO,"No response from Get PICMG Properties"); +	} else if (rsp->ccode != 0) { +	    lprintf(LOG_INFO,"Error response %#x from Get PICMG Properities", +		    rsp->ccode); +	} else if (rsp->data_len < 4) { +	    lprintf(LOG_INFO,"Invalid Get PICMG Properties response length %d", +		    rsp->data_len); +	} else if (rsp->data[0] != 0) { +	    lprintf(LOG_INFO,"Invalid Get PICMG Properties group extension %#x", +		    rsp->data[0]); +	} else if ((rsp->data[1] & 0x0F) != PICMG_ATCA_MAJOR_VERSION +		&& (rsp->data[1] & 0x0F) != PICMG_AMC_MAJOR_VERSION) { +	    lprintf(LOG_INFO,"Unknown PICMG Extension Version %d.%d", +		    (rsp->data[1] & 0x0F), (rsp->data[1] >> 4)); +	} else { +	    picmg_avail = 1; +	    lprintf(LOG_INFO, "Discovered PICMG Extension Version %d.%d", +		    (rsp->data[1] & 0x0f), (rsp->data[1] >> 4));  	} -	return intf->picmg_avail; + +	return picmg_avail;  }  | 
