From 26f501d7a573c82d1357f6859e933cc838c1c63e Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 3 Aug 2023 14:41:09 +0200 Subject: [statistics] Add even more more weird JEDEC encodings --- .../statistics/inc/hardwareparser.inc.php | 61 ++++++++++++++-------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/modules-available/statistics/inc/hardwareparser.inc.php b/modules-available/statistics/inc/hardwareparser.inc.php index 036b0431..d8ef575f 100644 --- a/modules-available/statistics/inc/hardwareparser.inc.php +++ b/modules-available/statistics/inc/hardwareparser.inc.php @@ -45,44 +45,61 @@ class HardwareParser { // JEDEC ID:7F 7F 9E 00 00 00 00 00 // or the ID as 8 hex digits with no spacing and prefix - if (preg_match('/JEDEC(?:\s*ID)?\s*:?\s*([0-9a-f\s]+)/i', $string, $out) + $id = null; + if (preg_match('/JEDEC(?:\s*ID)?\s*:?\s*([0-9a-f\s]{8,23})\s*$/i', $string, $out) || preg_match('/^([0-9a-f]{14}00)$/i', $string, $out)) { preg_match_all('/[0-9a-f]{2}/i', $out[1], $out); $bank = 0; - $id = 0; foreach ($out[0] as $id) { $bank++; $id = hexdec($id) & 0x7f; // Let's just ignore the parity bit, and any potential error if ($id !== 0x7f) break; } - if ($id !== 0) { + if ($id !== null) { $id = self::lookupJedec($bank, $id); - if ($id !== null) - return $id; } - } elseif (preg_match('/Unknown.{0,16}[\[(](?:0x)?([0-9a-fA-F]{2,4})[\])]/', $string, $out) - || (preg_match('/^([0-9A-F]{4})([0-9A-F]{4})([0-9A-F]{4})$/', $string, $out) && $out[1] === $out[3])) { - // 16bit encoding from DDR3+: lower byte is number of 0x7f bytes, upper byte is id within bank - $id = hexdec($out[1]); - // Our bank counting starts at one. Also ignore parity bit. - $bank = ($id & 0x7f); - // Shift down id, get rid of parity bit - $id = ($id >> 8) & 0x7f; - if (count($out) === 4) { - // Observed second case, on OptiPlex 5050, is 80AD000080AD, but here endianness is reversed - $tmp = $id; - $id = $bank; - $bank = $tmp; + } elseif (preg_match('/Unknown.{0,16}[\[(](?:0x)?([0-9a-fA-F]{2,4})[\])]/', $string, $out)) { + // First byte (big endian) is id-in-bank, low byte is bank + $id = self::decodeBankAndId($out, false); + } elseif (preg_match('/JEDEC(?:\s*ID)?\s*:?\s*([0-9a-f]{2}\s?[0-9a-f]{2})/i', $string, $out) + || (preg_match('/^([0-9A-F]{4})([0-9A-F]{4})([0-9A-F]{4})$/', $string, $out) && $out[2] === '0000')) { + // First byte is bank, second byte is id-in-bank + $id = self::decodeBankAndId($out, true); + } elseif (preg_match('/^([0-9a-f]{4})$/i', $string, $out)) { + // This one was seen with both endianesses + $id = self::decodeBankAndId($out, true); + if ($id === null) { + $id = self::decodeBankAndId($out, false); } - $bank++; - $id = self::lookupJedec($bank, $id); - if ($id !== null) - return $id; } + + if ($id !== null) + return $id; return $string; } + /** + * @return ?string + */ + private static function decodeBankAndId(array $out, bool $bankFirst) + { + // 16bit encoding from DDR3+: lower byte is number of 0x7f bytes, upper byte is id within bank + $id = hexdec(str_replace(' ', '', $out[1])); + // Our bank counting starts at one. Also ignore parity bit. + $bank = ($id & 0x7f); + // Shift down id, get rid of parity bit + $id = ($id >> 8) & 0x7f; + if ($bankFirst) { + // Observed second case, on OptiPlex 5050, is 80AD000080AD, but here endianness is reversed + $tmp = $id; + $id = $bank; + $bank = $tmp; + } + $bank++; + return self::lookupJedec($bank, $id); + } + /** * @return ?string */ -- cgit v1.2.3-55-g7522