Solaris-DeviceTree
view release on metacpan or search on metacpan
scripts/devtree view on Meta::CPAN
my $devtree;
my $bootinfo;
my $aliases;
my $disk;
my $tape;
my $network;
my $businfo;
my $slots;
my %devtree_options = (
attr => undef,
prop => undef,
promprop => undef,
minor => undef,
);
my %dpOptions = (
);
GetOptions( 'help|?' => \$help, man => \$man,
'p|print' => \$devtree,
'w|attr:s' => \$devtree_options{attr},
'o|prop:s' => \$devtree_options{prop},
'r|promprop:s' => \$devtree_options{promprop},
'm|minor' => \$devtree_options{minor},
'v|all' => sub { @devtree_options{ qw(attr prop promprop minor) } = ('', '', '', '') },
'a|aliases:s' => \$aliases,
'd|disks' => \$disk,
'n|networks' => \$network,
't|tapes' => \$tape,
'b|bootinfo' => \$bootinfo,
'u|businfo' => \$businfo,
) or pod2usage( 2 );
pod2usage( 1 ) if( $help );
pod2usage( -exitstatus => 0, -verbose => 2 ) if( $man );
if( $devtree ) {
print_tree( %devtree_options );
} elsif( defined $aliases ) {
my %options;
$options{aliases} = $aliases if( $aliases ne '' );
print_aliases( %options );
} elsif( defined $disk ) {
print_disk();
} elsif( defined $tape ) {
print_tape();
} elsif( defined $network ) {
print_network();
} elsif( defined $bootinfo ) {
print_bootinfo();
} elsif( defined $businfo ) {
require Solaris::DeviceTree::Libdevinfo;
my $libdevinfo_tree = Solaris::DeviceTree::Libdevinfo->new;
require Solaris::DeviceTree::Filesystem;
my $filesystem_tree = Solaris::DeviceTree::Filesystem->new;
require Solaris::DeviceTree::PathToInst;
my $path_to_inst_tree = Solaris::DeviceTree::PathToInst->new;
print_businfo( indent => 1, node => make_overlay_tree() );
} else {
pod2usage( 1 );
}
sub make_overlay_tree {
require Solaris::DeviceTree::Libdevinfo;
my $libdevinfo_tree = Solaris::DeviceTree::Libdevinfo->new;
require Solaris::DeviceTree::Filesystem;
my $filesystem_tree = Solaris::DeviceTree::Filesystem->new;
require Solaris::DeviceTree::PathToInst;
my $path_to_inst_tree = Solaris::DeviceTree::PathToInst->new;
my $overlay_tree = Solaris::DeviceTree::Overlay->new(
sources => {
libdevinfo => $libdevinfo_tree,
filesystem => $filesystem_tree,
path_to_inst => $path_to_inst_tree,
},
);
return $overlay_tree;
}
# -- Utility functions --
# Returns maximal length of all strings in the array.
sub maxlen {
return 0 if( @_ == 0 );
my $max = length shift;
foreach (@_) {
$max = length if( $max < length );
}
return $max;
}
# -- Print device tree --
# Print the line $line with current width and prepend the first line
# with $prefix1 and all following lines with $prefix2.
# $line must not contain any newlines.
sub print_tree_prefix1 {
my ($prefix1, $prefix2, $line) = @_;
my $width = $ENV{COLUMNS} || 80;
my $maxlen = $width - length( $prefix1 ) - 1;
if( !defined $line || $line eq '' ) {
print $prefix1, "\n";
return;
}
my $first;
my $line2;
($first, $line2) = ($line =~ /^(.{0,${maxlen}})(?:\s+(.*))?$/);
if( !defined $first ) {
($first, $line) = ($line =~ /^(.{0,${maxlen}})(.*)$/);
} else {
$line = $line2;
}
print $prefix1, $first, "\n";
while( $line ) {
($first, $line2) = ($line =~ /^(.{0,${maxlen}} )(.*)$/);
if( !defined $first ) {
($first, $line) = ($line =~ /^(.{0,${maxlen}})(.*)$/);
} else {
$line = $line2;
}
print $prefix2, $first, "\n" if( $first );
}
}
# Print the line $line with current width and prepend the first line
# with $prefix1 and all following lines with $prefix2.
sub print_tree_prefix {
my ($prefix1, $prefix2, $line) = @_;
my @lines = split( /\n/, $line );
print_tree_prefix1( $prefix1, $prefix2, shift @lines );
foreach my $line (@lines) {
print_tree_prefix1( $prefix2, $prefix2, $line );
}
scripts/devtree view on Meta::CPAN
my @list_props = (ref $options{prop} ? @{$options{prop}} : keys %$props);
my $headline_printed = 0;
my $maxlen = maxlen( @list_props );
foreach my $prop_name (sort @list_props) {
next if( !exists $props->{$prop_name} );
my $p = $props->{$prop_name};
my ($major, $minor) = $p->devt;
my $majMinString = (defined $major ? "($major,$minor) " : "" );
if( !$headline_printed ) {
print " Properties:\n" if( keys %$props > 0 && @list_props > 0 );
$headline_printed = 1;
}
print_tree_prefix( sprintf( " %-${maxlen}s -> ", $p->name ), " " x ($maxlen + 8),
$majMinString . join( " ", map { "'" . $_ . "'" } $p->data ) );
}
}
if( defined $options{promprop} ) {
my $pprops = $node->prom_props;
my @list_props = (ref $options{promprop} ? @{$options{promprop}} : keys %$pprops);
my $headline_printed = 0;
my $maxlen = maxlen( @list_props );
foreach my $ppropname (sort @list_props) {
next if( !exists $pprops->{$ppropname} );
my $string = $pprops->{$ppropname}->string;
if( !$headline_printed ) {
print " PROM-Properties:\n" if( keys %$pprops > 0 && @list_props > 0 );
$headline_printed = 1;
}
print_tree_prefix( sprintf( " %-${maxlen}s -> ", $ppropname ), " " x ($maxlen + 8), $string );
}
}
if( defined $options{minor} ) {
my $mn = $node->minor_nodes;
print " Minor-Nodes:\n" if( $mn && @$mn > 0 );
foreach my $m (sort { $a->name cmp $b->name } @$mn) {
print " * Name: ", $m->name || "<undefined>", "\n";
my ($major, $minor) = $m->devt;
print " Devt: (", defined $major ? $major : "<undefined>", ",", defined $minor ? $minor : "<undefined>", ")\n";
print " Nodetype: ", $m->nodetype || "<undefined>", "\n";
print " Spectype: ", $m->spectype || "<undefined>", "\n";
}
}
foreach my $child (sort { $a->devfs_path cmp $b->devfs_path } $node->child_nodes) {
print_tree_recursive( $child, %options );
}
}
# Print the device tree.
sub print_tree {
my %options = @_;
# require Solaris::DeviceTree::Libdevinfo;
# require Solaris::DeviceTree::PathToInst;
# require Solaris::DeviceTree::Filesystem;
# my $tree = new Solaris::DeviceTree::Libdevinfo;
# my $tree = new Solaris::DeviceTree::PathToInst;
# my $tree = new Solaris::DeviceTree::Filesystem;
# TODO: -> Implement has_data_source
my $tree = make_overlay_tree;
if( defined $options{attr} && $options{attr} ne '' ) {
$options{attr} = [ split( /,/, $options{attr} ) ];
}
if( defined $options{prop} && $options{prop} ne '' ) {
$options{prop} = [ split( /,/, $options{prop} ) ];
}
#print Dumper( %options );
if( defined $options{promprop} ) {
# Check if we can expect a result
my $prom_props = $tree->prom_props;
if( !defined $prom_props ) {
print STDERR "We failed to access the PROM properties. Please note that therefore\n";
print STDERR "no PROM properties can be displayed. For proper display read access to\n";
print STDERR "/dev/openprom is needed.\n\n";
delete $options{promprop};
} elsif( $options{promprop} ne '' ) {
$options{promprop} = [ split( /,/, $options{promprop} ) ];
}
}
print_tree_recursive( $tree, %options );
}
# -- Alias --
sub print_aliases {
my %options = @_;
require Solaris::DeviceTree::Libdevinfo;
require Solaris::DeviceTree::OBP;
import Solaris::DeviceTree::OBP qw( :aliases );
my $tree = new Solaris::DeviceTree::Libdevinfo;
# Check if we have the permissions to continue
{
my $prom_props = $tree->prom_props;
if( !defined $prom_props ) {
die "Cannot access PROM properties. Check the read permissions on /dev/openprom.\n";
}
}
my %aliases = %{obp_aliases($tree)};
if( exists $options{aliases} ) {
my $name = $options{aliases};
if( exists $aliases{$name} ) {
print $aliases{$name}, "\n";
} else {
print STDERR "The alias with the name '$name' could not be found.\n";
}
} else {
my $len = maxlen( keys %aliases );
foreach my $alias (sort keys %aliases) {
scripts/devtree view on Meta::CPAN
}
}
my $aliases = obp_aliases( $tree );
print "Bootpath information\n";
print "--------------------\n\n";
my $chosen_boot_device = obp_chosen_boot_device( $tree );
print "Last boot device:\n";
print " Boot device: ",
defined $chosen_boot_device ? $chosen_boot_device->string : "(unknown)", "\n";
my $obp_path;
if( defined $aliases && defined $chosen_boot_device ) {
$obp_path = obp_resolve_path( aliases => $aliases, path => $chosen_boot_device->string );
}
print " OBP path: ", defined $obp_path ? $obp_path : "(unknown)", "\n";
# my $node = $tree->__solarisPath( $obpPath );
# print " Solaris path: ", $node->string, "\n";
print "\n";
# my $diag_prop = $tree->find_prop( devfs_path => '/options',
# prom_prop_name => 'diag-switch?' );
# my $diag_switch = $diag_prop->string;
# print "Diag-Switch: $diag_switch";
# if( $diag_switch eq 'true' ) {
# print " -> Booting from diag-device\n";
# } elsif( $diag_switch eq 'false' ) {
# print " -> Booting from boot-device\n";
# } else {
# print " -> Unknown state\n";
# }
print "Boot-devices in normal mode:\n";
foreach my $boot_device (obp_boot_devices($tree)) {
print " Boot device: $boot_device\n";
my $obp_path = obp_resolve_path( aliases => $aliases, path => $boot_device );
print " OBP path: ", $obp_path, "\n";
# my $node = $tree->solarisPath( $obp_path );
# print " Solaris path: ", $node->string, "\n";
}
print "\n";
print "Boot-devices in diagnostic mode:\n";
foreach my $diag_device (obp_diag_devices($tree)) {
print " Diag device: $diag_device\n";
my $obp_path = obp_resolve_path( aliases => $aliases, path => $diag_device );
print " OBP path: ", $obp_path, "\n";
# my $node = $tree->solarisPath( $obp_path );
# print " Solaris path: ", $node->string, "\n";
}
print "\n";
}
# -- disk --
sub print_disk {
require Solaris::DeviceTree::Overlay;
my $tree = make_overlay_tree;
# -> TODO: Select wheter all or only accessible disks should be printed
# Criteria:
# o has instance in the kernel
# o has ctds
foreach my $c (sort { $a->controller <=> $b->controller } $tree->controller_nodes) {
print "+-";
print "c", $c->controller if( defined $c->controller );
print " (", $c->devfs_path, ")\n";
foreach my $disk (sort { ($a->target || 0)*2 + ($a->lun || 0) <=>
($b->target || 0)*2 + ($b->lun || 0) }
$c->block_nodes) {
next if( !defined $disk->target && !defined $disk->lun );
print "| +-";
print $disk->solaris_device || '';
print " (", $disk->devfs_path, ")\n";
}
}
}
# -- tape --
sub print_tape {
my $tree = make_overlay_tree;
# -> TODO: Select wheter all or only accessible tapes should be printed
# Criteria:
# o has instance in the kernel
# o has /dev/rmt
# foreach my $disk ($tree->block_nodes) {
# print $disk->devfs_path, "\n";
# }
}
# -- Network --
sub print_network {
my $tree = make_overlay_tree;
# -> TODO: Historical network nodes only in /etc/path_to_inst should be honored
print "The following network devices have been found:\n";
foreach my $node (sort { $a->driver_name . $a->instance cmp $b->driver_name . $b->instance }
$tree->network_nodes) {
# my $interface = $node->driver_name . $node->instance;
my $interface = $node->solaris_device || '';
print "+-", $interface, " (", $node->devfs_path, ")\n";
}
}
# -- businfo --
sub iaToInt {
my $result = 0;
foreach my $i (@_) {
$result = $result * 256 + $i;
}
$result;
}
sub getSpeed {
my ($props) = @_;
my $freqstr = undef;
if( exists $props->{'clock-frequency'} ) {
my $freq = iaToInt( unpack( "C*", ${$props->{'clock-frequency'}} ) );
if( $freq < 1000 ) {
$freqstr = sprintf( "%d Hz", $freq );
} elsif( $freq >= 1000 && $freq <= 1000000 ) {
$freqstr = sprintf( "%d KHz", $freq / 1000 );
} else {
$freqstr = sprintf( "%d MHz", int( $freq / 1000 ) / 1000 );
}
}
return $freqstr;
}
sub getUPAAddress {
my $node = shift;
my $props = $node->prom_props;
my $portid;
# From
# "source/osnet_volume/usr/src/lib/libprtdiag/common/pdevinfo_sun4u.c" #102 (get_id)
if( exists $props->{'upa-portid'} ) {
# Devices on the UPA bus should have a portid
$portid = iaToInt( unpack( "C*", ${$props->{'upa-portid'}} ) );
} elsif( exists $props->{'portid'} ) {
# Devices on the UPA bus should have a portid
$portid = iaToInt( unpack( "C*", ${$props->{'portid'}} ) );
} elsif( defined $node->bus_addr ) {
# If not, use the well known bus adress as a last resort
# Please note, that the bus address can be undefined (device not on bus)
# or the empty string (device on the bus but with no specific address).
$portid = $node->bus_addr;
} else {
# Dammit, this device is not on the bus!
$portid = undef;
( run in 1.436 second using v1.01-cache-2.11-cpan-e1769b4cff6 )