-Begin overhaul of IPMI standard FRU parsing to be more thorough and robust
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@2192 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
d6e89916a6
commit
d3705c844e
@ -31,6 +31,7 @@ sub handled_commands {
|
||||
rsetboot => 'nodehm:mgt',
|
||||
rbeacon => 'nodehm:mgt',
|
||||
reventlog => 'nodehm:mgt',
|
||||
writefru => 'nodehm:mgt',
|
||||
}
|
||||
}
|
||||
|
||||
@ -2165,10 +2166,115 @@ sub frudump {
|
||||
return(0,@fru_data);
|
||||
}
|
||||
|
||||
sub parsefru {
|
||||
my $bytes = shift;
|
||||
my $structure;
|
||||
my $curridx; #store indexes as needed for convenience
|
||||
my $currsize; #store current size
|
||||
my $subidx;
|
||||
my @currarea;
|
||||
unless ($bytes->[0]==1) {
|
||||
if ($bytes->[0]==0 or $bytes->[0]==0xff) { #not in spec, but probably unitialized, xCAT probably will rewrite fresh
|
||||
return "clear",undef;
|
||||
} else { #some meaning suggested, but not parsable, xCAT shouldn't meddle
|
||||
return "unknown",undef;
|
||||
}
|
||||
}
|
||||
if ($bytes->[1]) { #The FRU spec, unfortunately, gave no easy way to tell the size of internal area
|
||||
#consequently, will find the next defined field and preserve the addressing and size of current FRU
|
||||
#area until then
|
||||
my $internal_size;
|
||||
if ($bytes->[2]) {
|
||||
$internal_size=$bytes->[2]*8-($bytes->[1]*8);
|
||||
} elsif ($bytes->[3]) {
|
||||
$internal_size=$bytes->[3]*8-($bytes->[1]*8);
|
||||
} elsif ($bytes->[4]) {
|
||||
$internal_size=$bytes->[4]*8-($bytes->[1]*8);
|
||||
} elsif ($bytes->[5]) {
|
||||
$internal_size=$bytes->[5]*8-($bytes->[1]*8);
|
||||
} else { #The FRU area is intact enough to signify xCAT can't safely manipulate contents
|
||||
return "unknown-winternal",undef;
|
||||
}
|
||||
#capture slice of bytes
|
||||
$structure->{internal}=[@{$bytes}[($bytes->[1]*8)..($bytes->[1]*8+$internal_size)]]; #,$bytes->[1]*8,$internal_size];
|
||||
}
|
||||
if ($bytes->[2]) { #Chassis info area, xCAT will preserve fields, not manipulate them
|
||||
$curridx=$bytes->[2]*8;
|
||||
unless ($bytes->[$curridx]==1) { #definitely unparsable, but the section is preservable
|
||||
return "unknown-COULDGUESS",undef; #be lazy for now, TODO revisit this and add guessing if it ever matters
|
||||
}
|
||||
$currsize=($bytes->[$curridx+1])*8;
|
||||
@currarea=@{$bytes}[$curridx..($curridx+$currsize)]; #splice @$bytes,$curridx,$currsize;
|
||||
parsechassis(@currarea);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sub parsechassis {
|
||||
my @chassarea=@_;
|
||||
my %chassisinf;
|
||||
my $currsize;
|
||||
my $idx=3;
|
||||
$chassisinf{type}="unknown";
|
||||
if ($chassis_types{$chassarea[2]}) {
|
||||
$chassisinf{type}=$chassis_types{$chassarea[2]};
|
||||
}
|
||||
if ($chassarea[$idx] == 0xc1) {
|
||||
return \%chassisinf;
|
||||
}
|
||||
if ($chassarea[$idx++] & 0b00111111) {
|
||||
$currsize=$chassarea[3] & 0b00111111;
|
||||
$chassisinf{partenc}=($chassarea[3] & 0b11000000)>>6;
|
||||
if ($chassisinf{partenc}==3) {
|
||||
$chassisinf{partnum}=getascii(@chassarea[$idx..($idx+$currsize-1)]);
|
||||
} else { #preserve the raw bytes that we don't understand
|
||||
$chassisinf{partnum}=[@chassarea[$idx..($idx+$currsize-1)]];
|
||||
}
|
||||
$idx=$idx+$currsize; #advance index to next candidate field, chassis serial #
|
||||
}
|
||||
if ($chassarea[$idx] == 0xc1) {
|
||||
return \%chassisinf;
|
||||
}
|
||||
if ($chassarea[$idx++] & 0b00111111) {
|
||||
$currsize=$chassarea[$idx-1] & 0b00111111;
|
||||
$chassisinf{serialenc}=($chassarea[$idx-1] & 0b11000000)>>6;
|
||||
if ($chassisinf{serialenc}==3) {
|
||||
$chassisinf{serialnum}=getascii(@chassarea[$idx..($currsize+$idx-1)]);
|
||||
} else {
|
||||
$chassisinf{serialnum}=[@chassarea[$idx..($currsize+$idx-1)]];
|
||||
}
|
||||
$idx=$idx+$currsize;
|
||||
}
|
||||
if ($chassarea[$idx] == 0xc1) {
|
||||
return \%chassisinf;
|
||||
} else {
|
||||
die "Malformed FRU area";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sub writefru {
|
||||
my $serial = shift;
|
||||
my $model = shift;
|
||||
my $netfun = 0x28; # Storage (0x0A << 2)
|
||||
my @cmd=(0x10,0);
|
||||
my @bytes;
|
||||
my $error = docmd($netfun,\@cmd,\@bytes);
|
||||
@bytes=splice @bytes,36-$authoffset;
|
||||
pop @bytes;
|
||||
unless (defined $bytes[0] and $bytes[0] == 0) {
|
||||
return (1,"FRU device 0 inaccessible");
|
||||
}
|
||||
my $frusize=($bytes[2]<<8)+$bytes[1];
|
||||
($error,@bytes) = frudump(0,$frusize,16);
|
||||
my $fruhash = parsefru(\@bytes);
|
||||
return;
|
||||
my $serial;
|
||||
my $model;
|
||||
|
||||
my $rc;
|
||||
my $text;
|
||||
|
||||
@ -4673,7 +4779,11 @@ sub getascii {
|
||||
my $c = 0;
|
||||
|
||||
foreach(@_) {
|
||||
$alpha[$c] = sprintf("%c",$_);
|
||||
if (defined $_ and $_ < 128 and $_ > 0x20) {
|
||||
$alpha[$c] = sprintf("%c",$_);
|
||||
} else {
|
||||
$alpha[$c]=" ";
|
||||
}
|
||||
if($alpha[$c] !~ /[\/\w\-:]/) {
|
||||
if ($alpha[($c-1)] !~ /\s/) {
|
||||
$alpha[$c] = " ";
|
||||
|
Loading…
Reference in New Issue
Block a user