aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2009-05-30 12:25:05 -0400
committerLen Brown <len.brown@intel.com>2009-06-17 22:45:30 -0400
commit050df107c408a3df048524b3783a5fc6d4dccfdb (patch)
tree7e7faa2af1fc4098b12044eca3f5e204a54832e7
parent07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (diff)
thinkpad-acpi: store fw version with strict checking
Extend the thinkpad model and firmware identification data with the release serial number for the BIOS and firmware (when available), as that is easier to parse and compare than the version strings. We're going to greatly extend the use of the ThinkPad DMI data through quirk lists, so it is best to be quite strict and make sure what we get from DMI is exactly what we expect, otherwise quirk matching may result in quite insane things. IBM (and Lenovo, at least for the ThinkPad line) uses this schema for firmware versioning and model: Firmware model: Two digits, [0-9A-Z] Firmware version: AABBCCDD, where AA = firmware model, see above BB = "ET" for BIOS, "HT" for EC CC = release version, two digits, [0-9A-Z], "00" < "09" < "0A" < "10" < "A0" < "ZZ" DD = "WW" Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 912be65b6261..d2a0ef83fbb5 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -284,8 +284,10 @@ struct thinkpad_id_data {
284 char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ 284 char *bios_version_str; /* Something like 1ZET51WW (1.03z) */
285 char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ 285 char *ec_version_str; /* Something like 1ZHT51WW-1.04a */
286 286
287 u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ 287 u16 bios_model; /* 1Y = 0x5931, 0 = unknown */
288 u16 ec_model; 288 u16 ec_model;
289 u16 bios_release; /* 1ZETK1WW = 0x314b, 0 = unknown */
290 u16 ec_release;
289 291
290 char *model_str; /* ThinkPad T43 */ 292 char *model_str; /* ThinkPad T43 */
291 char *nummodel_str; /* 9384A9C for a 9384-A9C model */ 293 char *nummodel_str; /* 9384A9C for a 9384-A9C model */
@@ -7357,6 +7359,24 @@ err_out:
7357 7359
7358/* Probing */ 7360/* Probing */
7359 7361
7362static bool __pure __init tpacpi_is_fw_digit(const char c)
7363{
7364 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z');
7365}
7366
7367/* Most models: xxyTkkWW (#.##c); Ancient 570/600 and -SL lacks (#.##c) */
7368static bool __pure __init tpacpi_is_valid_fw_id(const char* const s,
7369 const char t)
7370{
7371 return s && strlen(s) >= 8 &&
7372 tpacpi_is_fw_digit(s[0]) &&
7373 tpacpi_is_fw_digit(s[1]) &&
7374 s[2] == t && s[3] == 'T' &&
7375 tpacpi_is_fw_digit(s[4]) &&
7376 tpacpi_is_fw_digit(s[5]) &&
7377 s[6] == 'W' && s[7] == 'W';
7378}
7379
7360/* returns 0 - probe ok, or < 0 - probe error. 7380/* returns 0 - probe ok, or < 0 - probe error.
7361 * Probe ok doesn't mean thinkpad found. 7381 * Probe ok doesn't mean thinkpad found.
7362 * On error, kfree() cleanup on tp->* is not performed, caller must do it */ 7382 * On error, kfree() cleanup on tp->* is not performed, caller must do it */
@@ -7383,10 +7403,15 @@ static int __must_check __init get_thinkpad_model_data(
7383 tp->bios_version_str = kstrdup(s, GFP_KERNEL); 7403 tp->bios_version_str = kstrdup(s, GFP_KERNEL);
7384 if (s && !tp->bios_version_str) 7404 if (s && !tp->bios_version_str)
7385 return -ENOMEM; 7405 return -ENOMEM;
7386 if (!tp->bios_version_str) 7406
7407 /* Really ancient ThinkPad 240X will fail this, which is fine */
7408 if (!tpacpi_is_valid_fw_id(tp->bios_version_str, 'E'))
7387 return 0; 7409 return 0;
7410
7388 tp->bios_model = tp->bios_version_str[0] 7411 tp->bios_model = tp->bios_version_str[0]
7389 | (tp->bios_version_str[1] << 8); 7412 | (tp->bios_version_str[1] << 8);
7413 tp->bios_release = (tp->bios_version_str[4] << 8)
7414 | tp->bios_version_str[5];
7390 7415
7391 /* 7416 /*
7392 * ThinkPad T23 or newer, A31 or newer, R50e or newer, 7417 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
@@ -7405,8 +7430,21 @@ static int __must_check __init get_thinkpad_model_data(
7405 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); 7430 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
7406 if (!tp->ec_version_str) 7431 if (!tp->ec_version_str)
7407 return -ENOMEM; 7432 return -ENOMEM;
7408 tp->ec_model = ec_fw_string[0] 7433
7409 | (ec_fw_string[1] << 8); 7434 if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) {
7435 tp->ec_model = ec_fw_string[0]
7436 | (ec_fw_string[1] << 8);
7437 tp->ec_release = (ec_fw_string[4] << 8)
7438 | ec_fw_string[5];
7439 } else {
7440 printk(TPACPI_NOTICE
7441 "ThinkPad firmware release %s "
7442 "doesn't match the known patterns\n",
7443 ec_fw_string);
7444 printk(TPACPI_NOTICE
7445 "please report this to %s\n",
7446 TPACPI_MAIL);
7447 }
7410 break; 7448 break;
7411 } 7449 }
7412 } 7450 }