/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0: * * Copyright (C) 2005 Dell Inc. * by Michael Brown * Licensed under the Open Software License version 2.1 * * Alternatively, you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ #define LIBSMBIOS_C_SOURCE #include "smbios_c/compat.h" #include #include #include "smbios_c/system_info.h" #include "smbios_c/memory.h" #include "smbios_c/smbios.h" #include "dell_magic.h" #include "sysinfo_impl.h" // // // ID Byte functions // // __hidden u16 get_id_byte_from_mem () { u16 tempWord = 0; u16 idWord = 0; char strBuf[DELL_SYSTEM_STRING_LEN] = { 0, }; int ret; struct two_byte_structure tbs; // Step 1: Check that "Dell System" is present at the proper offset ret = memory_read(strBuf, DELL_SYSTEM_STRING_LOC, DELL_SYSTEM_STRING_LEN-1); if (ret<0) goto out; if( strncmp( strBuf, DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) != 0 ) goto out; // Step 2: fill the id structs ret = memory_read(&tbs, TWO_BYTE_STRUCT_LOC, sizeof(struct two_byte_structure) ); if (ret<0) goto out; // Step 3: check the checksum of one-byte struct // update: checksum is not reliable, so don't use it... // Step 4: Check one byte ID tempWord = tbs.system_id; // Step 5: if 0xFE, then it is a double byte (word) ID. // * -- byte at 0xFE845 is 0xFE if (0xFE == tempWord) { // Step 6: check two byte struct checksum // * -- three bytes at 0xFE845 sum to 0x00 but are not all 0x00. //* -- extension checksum is 0 // Step 7: get ID. tempWord = tbs.two_byte_id; } idWord = tempWord; out: return idWord; } __hidden u16 get_id_byte_from_mem_diamond() { u16 idWord = 0; char strBuf[DELL_SYSTEM_STRING_LEN] = { 0, }; int ret; // Step 1: Check that "Dell System" is present at the proper offset ret = memory_read(strBuf, DELL_SYSTEM_STRING_LOC_DIAMOND_1, DELL_SYSTEM_STRING_LEN - 1); if( ret>=0 && strncmp( strBuf, DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 ) { u8 idByte = 0; ret = memory_read(&idByte, ID_BYTE_LOC_DIAMOND_1, sizeof(idByte)); if( ret>=0 && SYSTEM_ID_DIAMOND == idByte ) { idWord = SYSTEM_ID_DIAMOND; goto out; } } ret = memory_read(strBuf, DELL_SYSTEM_STRING_LOC_DIAMOND_2, DELL_SYSTEM_STRING_LEN - 1); if( (ret>=0) && (strncmp( strBuf, DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 )) { u8 idByte = 0; ret = memory_read(&idByte, ID_BYTE_LOC_DIAMOND_2, sizeof(idByte)); if( ret>=0 && SYSTEM_ID_DIAMOND == idByte ) { idWord = SYSTEM_ID_DIAMOND; goto out; } } out: return idWord; } __hidden const char * get_dell_oem_string_by_tag (int tag) { // search through 0x0B (OEM_Strings_Structure) items smbios_for_each_struct_type( s, OEM_Strings ) { // first string must be "Dell System" per spec const char *str = smbios_struct_get_string_number(s, 1); if ((!str) || (0 != strncmp (str, DELL_SYSTEM_STRING, strlen(DELL_SYSTEM_STRING)))) { str = 0; continue; } int i=2; // start searching string table from second string (first was searched above) while ( (str = smbios_struct_get_string_number(s, i++)) ){ char *endptr = 0; long strtag = strtol(str, &endptr, 10); if(strlen(str) > 3 && strtag == tag && endptr[0] == '[') return str; } } return 0; } __hidden u16 get_dell_id_byte_from_oem_item () { u16 idWord = 0; // Tag # for oem string table Dell ID tag is '1' // see docs for dell oem strings table (0x0b) const char *str = get_dell_oem_string_by_tag(1); // Id byte is in second string in table 0x0B // the format is "1[NN]", where NN is the idbyte; // note the &str[2] below to skip the 'n[' if(str && strlen(str) > 3 && str[0] == '1' && str[1] == '[') idWord = strtol( &str[2], NULL, 16 ); return idWord; } __hidden u16 get_oem_id_byte_from_oem_item () { u16 idWord = 0; // Tag # for oem string table reseller ID tag is '7' // see docs for dell oem strings table (0x0b) const char *str = get_dell_oem_string_by_tag(7); // Id byte is in second string in table 0x0B // the format is "1[NN]", where NN is the idbyte; // note the &str[2] below to skip the 'n[' if(str && strlen(str) > 3 && str[0] == '7' && str[1] == '[') idWord = strtol( &str[2], NULL, 16 ); return idWord; } __hidden u16 get_id_byte_from_rev_and_id_structure () { u16 idWord = 0; // search through 0x0B (Revisions_and_IDs_Structure) smbios_for_each_struct_type( s, Dell_Revisions_and_IDs ) { //If byte field is 0xFE, we need to look in the extension field smbios_struct_get_data(s, &idWord, 0x06, 1); if( 0xFE == idWord ) { smbios_struct_get_data(s, &idWord, 0x08, 2); } } return idWord; } static struct DellIdByteFunctions { const char *const name; u16 (*f_ptr)(); } DellIdByteFunctions[] = { {"get_id_byte_from_mem_diamond", &get_id_byte_from_mem_diamond,}, {"get_dell_id_byte_from_oem_item", &get_dell_id_byte_from_oem_item,}, // 0x0b structure, tag 1 {"get_id_byte_from_rev_and_id_structure", &get_id_byte_from_rev_and_id_structure,}, // 0xd0 structure {"get_id_byte_from_mem", &get_id_byte_from_mem,}, }; static struct DellIdByteFunctions DellOemIdByteFunctions[] = { {"get_id_byte_from_mem_diamond", &get_id_byte_from_mem_diamond,}, // diamond is old and never oem, so this is safe // try to get OEM ID first {"get_oem_id_byte_from_oem_item", &get_oem_id_byte_from_oem_item,}, // 0x0b structure, tag 7 // on older systems, the id in the rev and id structure got replaced with OEM ID {"get_id_byte_from_rev_and_id_structure", &get_id_byte_from_rev_and_id_structure,}, // 0xd0 structure // on older systems, the id in mem structure got replaced with OEM ID {"get_id_byte_from_mem", &get_id_byte_from_mem,}, // then fall back to Dell ID if OEM ID not present // This will never hit, as one of the previous two functions will always // return a value before we get to here. But better safe than sorry {"get_dell_id_byte_from_oem_item", &get_oem_id_byte_from_oem_item,}, // 0x0b structure, tag 1 }; LIBSMBIOS_C_DLL_SPEC int sysinfo_get_dell_oem_system_id() { int systemId = 0; int numEntries = sizeof (DellOemIdByteFunctions) / sizeof (DellOemIdByteFunctions[0]); sysinfo_clearerr(); for (int i = 0; i < numEntries; ++i) { fnprintf("calling id_byte function: %s\n", DellOemIdByteFunctions[i].name); // first function to return non-zero id wins. systemId = DellOemIdByteFunctions[i].f_ptr (); if (systemId) break; } return systemId; } LIBSMBIOS_C_DLL_SPEC int sysinfo_get_dell_system_id() { int systemId = 0; int numEntries = sizeof (DellIdByteFunctions) / sizeof (DellIdByteFunctions[0]); sysinfo_clearerr(); for (int i = 0; i < numEntries; ++i) { fnprintf("calling id_byte function: %s\n", DellIdByteFunctions[i].name); // first function to return non-zero id wins. systemId = DellIdByteFunctions[i].f_ptr (); if (systemId) break; } return systemId; }