Hi,Here's a small patch for the decode-dimms script to make it work on OS X. Instead of device nodes, the EEPROM content can be read with the ioreg(8) command there.
Tested on a G5 iMac and a G4 PowerBook, both running OS X 10.4.11. Regards, Michael -- Message composed with VIM - Vi IMproved 7.2 (2008 Aug 9, compiled Jan 10 2009 20:59:41)
--- decode-dimms.orig 2009-05-13 12:16:44.000000000 +0200 +++ decode-dimms 2009-05-14 21:36:57.000000000 +0200 @@ -47,6 +47,8 @@ use constant LITTLEENDIAN => "little-endian"; use constant BIGENDIAN => "big-endian"; +use constant DARWIN => $^O eq "darwin"; + $revision = '$Revision$ ($Date$)'; $revision =~ s/\$\w+: (.*?) \$/$1/g; $revision =~ s/ \([^()]*\)//; @@ -1549,25 +1551,28 @@ { my ($offset, $size, $dimm_i) = @_; my @bytes; + my $dimm_file = $dimm_i->{file}; if ($use_hexdump) { - @bytes = read_hexdump($dimm_i); + @bytes = read_hexdump($dimm_file); return @bytes[$offset..($offset + $size - 1)]; + } elsif (DARWIN) { + return @{$dimm_i->{bytes}}[$offset..($offset + $size - 1)]; } elsif ($use_sysfs) { # Kernel 2.6 with sysfs - sysopen(HANDLE, "$dimm_i/eeprom", O_RDONLY) - or die "Cannot open $dimm_i/eeprom"; + sysopen(HANDLE, "$dimm_file/eeprom", O_RDONLY) + or die "Cannot open $dimm_file/eeprom"; binmode HANDLE; sysseek(HANDLE, $offset, SEEK_SET) - or die "Cannot seek $dimm_i/eeprom"; + or die "Cannot seek $dimm_file/eeprom"; sysread(HANDLE, my $eeprom, $size) - or die "Cannot read $dimm_i/eeprom"; + or die "Cannot read $dimm_file/eeprom"; close HANDLE; @bytes = unpack("C*", $eeprom); } else { # Kernel 2.4 with procfs for my $i (0 .. ($size-1)/16) { my $hexoff = sprintf('%02x', $offset + $i * 16); - push @bytes, split(" ", `cat $dimm_i/$hexoff`); + push @bytes, split(" ", `cat $dimm_file/$hexoff`); } } return @bytes; @@ -1700,7 +1705,29 @@ { my ($dir, $file, @files); - if ($use_sysfs) { + if (DARWIN) { + # On OS X we query the I/O registry to get the EEPROM data + my (@dimm_info, @slot_names); + + open IOREG, "ioreg -n memory -w 0 -p IODeviceTree |" + or die "Cannot read device tree: $!"; + while(<IOREG>) { + if(m/"dimm-info"\s*=\s*<(.*)>/) { + @dimm_info = unpack "(a256)*", $1; + } elsif(m/"slot-names"\s*=\s*<[\da-fA-F]{8}(.*)>/) { + @slot_names = split(/\0/, pack("H*", $1)); + } + } + close IOREG; + foreach my $i (0..$#dimm_info) { + my @bytes = unpack("C*", pack("H*", $dimm_info[$i])); + push @files, { + file => $slot_names[$i], + eeprom => $slot_names[$i], + bytes => \@bytes } + } + return @files; + } elsif ($use_sysfs) { $dir = '/sys/bus/i2c/drivers/eeprom'; } else { $dir = '/proc/sys/dev/sensors'; @@ -1735,7 +1762,7 @@ @dimm = get_dimm_list() unless $use_hexdump; for my $i (0 .. $#dimm) { - my @bytes = readspd(0, 128, $dimm[$i]->{file}); + my @bytes = readspd(0, 128, $dimm[$i]); $dimm[$i]->{bytes} = \@bytes; $dimm[$i]->{is_rambus} = $bytes[0] < 4; # Simple heuristic if ($dimm[$i]->{is_rambus} || $bytes[2] < 9) { @@ -1801,8 +1828,7 @@ # read it now. DDR3 will need this data. if ($spd_used > @bytes) { push (@bytes, - readspd(@bytes, $spd_used - @bytes, - $dimm[$current]->{file})); + readspd(@bytes, $spd_used - @bytes, $dimm[$current])); } }