#!/usr/bin/perl -w # # dumpdmi 0.2 # Chip Salzenberg # use strict; (my $ME = $0) =~ s#.*/##; my $DEBUG; if (@ARGV && $ARGV[0] eq '-d') { ++$DEBUG; shift; } my $BIOS; open MEM, '/dev/mem' or die "$ME: Can't open /dev/mem: $!\n"; sysseek MEM, 0xE0000, 0; sysread MEM, $BIOS, 0x20000 or die "$ME: Can't read BIOS from /dev/mem?\n"; while ( $BIOS =~ /_DMI_/g && (pos($BIOS) & 0x0F) != 5 ) {} die "$ME: Can't find DMI in BIOS\n" unless pos($BIOS); my $info = substr($BIOS, pos($BIOS) + 1, 10); my ($DSIZE, $DBASE, $DCOUNT, $DVER) = unpack('v V v C', $info); $DVER = ($DVER >> 4) . '.' . ($DVER & 0x0F); print "DMI Version: $DVER\n"; printf "DMI table at 0x%X contains %d structures occupying %d bytes.\n", $DBASE, $DCOUNT, $DSIZE if $DEBUG; sysseek MEM, $DBASE, 0; sysread MEM, $_, $DSIZE or die "$ME: Can't read DMI table: $!\n"; my $n = 0; my $last_type = 0; while (my $header = substr($_, 0, 4, '')) { my ($type, $dlen, $handle) = unpack('CCv', $header); last if $type < $last_type || $dlen < 4; my $data = substr($_, 0, $dlen - 4, ''); my @data = unpack 'C*', $data; my @str = m{ \G ([^\0]+) \0 }xg; if ($DEBUG) { printf "DMI type=%02X data=%s\n", $type, join(':', map { sprintf '%02X', $_ } @data); if (my @s = @str) { for (@s) { s/\\/\\\\/g; s/"/\\"/g; } printf " strings={ %s }\n", join(', ', map { '"'.$_.'"' } @s); } } my $str = sub { my $n = $data[+shift]; (defined($n) && $n > 0 && $n <= @str) or return ''; local $_ = $str[$n - 1]; s/^\s+//; s/\s+$//; $_; }; if ($type == 0) { print "BIOS Vendor: ", $str->(0), "\n"; print "BIOS Version: ", $str->(1), "\n"; print "BIOS Release: ", $str->(4), "\n"; } elsif ($type == 1) { print "System Vendor: ", $str->(0), "\n"; print "System Name: ", $str->(1), "\n"; print "System Version: ", $str->(2), "\n"; print "System Serial Number: ", $str->(3), "\n"; } elsif ($type == 2) { print "Board Vendor: ", $str->(0), "\n"; print "Board Name: ", $str->(1), "\n"; print "Board Version: ", $str->(2), "\n"; print "Board Serial Number: ", $str->(3), "\n"; } elsif ($type == 3) { print "Asset Tag: ", $str->(4), "\n"; } last unless s/^.*?\0\0//; last if ++$n >= $DCOUNT; $last_type = $type; }