diff options
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 15 | ||||
-rw-r--r-- | include/linux/ipmi_smi.h | 36 |
2 files changed, 30 insertions, 21 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index da09eb0ef788..4f560d0bb808 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -2380,20 +2380,9 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
2380 | /* Otherwise, we got some data. */ | 2380 | /* Otherwise, we got some data. */ |
2381 | resp_len = smi_info->handlers->get_result(smi_info->si_sm, | 2381 | resp_len = smi_info->handlers->get_result(smi_info->si_sm, |
2382 | resp, IPMI_MAX_MSG_LENGTH); | 2382 | resp, IPMI_MAX_MSG_LENGTH); |
2383 | if (resp_len < 14) { | ||
2384 | /* That's odd, it should be longer. */ | ||
2385 | rv = -EINVAL; | ||
2386 | goto out; | ||
2387 | } | ||
2388 | |||
2389 | if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0)) { | ||
2390 | /* That's odd, it shouldn't be able to fail. */ | ||
2391 | rv = -EINVAL; | ||
2392 | goto out; | ||
2393 | } | ||
2394 | 2383 | ||
2395 | /* Record info from the get device id, in case we need it. */ | 2384 | /* Check and record info from the get device id, in case we need it. */ |
2396 | ipmi_demangle_device_id(resp+3, resp_len-3, &smi_info->device_id); | 2385 | rv = ipmi_demangle_device_id(resp, resp_len, &smi_info->device_id); |
2397 | 2386 | ||
2398 | out: | 2387 | out: |
2399 | kfree(resp); | 2388 | kfree(resp); |
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index c0633108d05d..efa292a52e7e 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h | |||
@@ -148,26 +148,46 @@ struct ipmi_device_id { | |||
148 | 148 | ||
149 | /* Take a pointer to a raw data buffer and a length and extract device | 149 | /* Take a pointer to a raw data buffer and a length and extract device |
150 | id information from it. The first byte of data must point to the | 150 | id information from it. The first byte of data must point to the |
151 | byte from the get device id response after the completion code. | 151 | netfn << 2, the data should be of the format: |
152 | The caller is responsible for making sure the length is at least | 152 | netfn << 2, cmd, completion code, data |
153 | 11 and the command completed without error. */ | 153 | as normally comes from a device interface. */ |
154 | static inline void ipmi_demangle_device_id(unsigned char *data, | 154 | static inline int ipmi_demangle_device_id(const unsigned char *data, |
155 | unsigned int data_len, | 155 | unsigned int data_len, |
156 | struct ipmi_device_id *id) | 156 | struct ipmi_device_id *id) |
157 | { | 157 | { |
158 | if (data_len < 9) | ||
159 | return -EINVAL; | ||
160 | if (data[0] != IPMI_NETFN_APP_RESPONSE << 2 || | ||
161 | data[1] != IPMI_GET_DEVICE_ID_CMD) | ||
162 | /* Strange, didn't get the response we expected. */ | ||
163 | return -EINVAL; | ||
164 | if (data[2] != 0) | ||
165 | /* That's odd, it shouldn't be able to fail. */ | ||
166 | return -EINVAL; | ||
167 | |||
168 | data += 3; | ||
169 | data_len -= 3; | ||
158 | id->device_id = data[0]; | 170 | id->device_id = data[0]; |
159 | id->device_revision = data[1]; | 171 | id->device_revision = data[1]; |
160 | id->firmware_revision_1 = data[2]; | 172 | id->firmware_revision_1 = data[2]; |
161 | id->firmware_revision_2 = data[3]; | 173 | id->firmware_revision_2 = data[3]; |
162 | id->ipmi_version = data[4]; | 174 | id->ipmi_version = data[4]; |
163 | id->additional_device_support = data[5]; | 175 | id->additional_device_support = data[5]; |
164 | id->manufacturer_id = data[6] | (data[7] << 8) | (data[8] << 16); | 176 | if (data_len >= 6) { |
165 | id->product_id = data[9] | (data[10] << 8); | 177 | id->manufacturer_id = (data[6] | (data[7] << 8) | |
178 | (data[8] << 16)); | ||
179 | id->product_id = data[9] | (data[10] << 8); | ||
180 | } else { | ||
181 | id->manufacturer_id = 0; | ||
182 | id->product_id = 0; | ||
183 | } | ||
166 | if (data_len >= 15) { | 184 | if (data_len >= 15) { |
167 | memcpy(id->aux_firmware_revision, data+11, 4); | 185 | memcpy(id->aux_firmware_revision, data+11, 4); |
168 | id->aux_firmware_revision_set = 1; | 186 | id->aux_firmware_revision_set = 1; |
169 | } else | 187 | } else |
170 | id->aux_firmware_revision_set = 0; | 188 | id->aux_firmware_revision_set = 0; |
189 | |||
190 | return 0; | ||
171 | } | 191 | } |
172 | 192 | ||
173 | /* Add a low-level interface to the IPMI driver. Note that if the | 193 | /* Add a low-level interface to the IPMI driver. Note that if the |