#!/usr/bin/perl -w # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # # The fan topologies can be quite complicated, but are ultimately regular. This # perl file uses some simplified internal structures to generate an .xml file # without the maintenance overhead. # use Getopt::Std; use strict; # # Master table of platforms. # my @platforms = ( # # Galaxy 1/2 platforms. # # These systems have 2 fan-connector boards. Each fan-connector board has 3 # fan modules. Each fan module is an individual FRU. The fan-connector # boards are also FRUs. # { set => "Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|" . "Sun-Fire-X4100-M2|Sun-Fire-X4200-M2", topology => [ { label => "FT %d", count => 2, fru => "self" }, { fac_enum => 1, provider => "fac_prov_ipmi", count => 3, label => "FT %d FM %d", entity_ref => "ft%d.fm%d.led", entity_ref_nparams => 2, fm_service_indctr => "ft%d.fm%d.led", fru => "self" } ] }, # # Thumper platforms # # These systems have 5 fan modules, with each fan module containing 2 fans. # The FRUs for the individual fans are the containing fan module. # { set => "Sun-Fire-X4500|Sun-Fire-X4540", topology => [ { fac_enum => 0, provider => "fac_prov_ipmi", label => "FT %d", count => 5, fru => "self", entity_ref => "ft%d.prsnt", entity_ref_nparams => 1, fm_service_indctr => "ft%d.service.led", fm_ok2rm_indctr => "ft%d.ok2rm.led", }, { fac_enum => 1, provider => "fac_prov_ipmi", count => 2, entity_ref => "ft%d.f%d.speed", entity_ref_nparams => 2, fru => "parent" } ] }, # # Fan Module/Fan topology for all G1N/G2N platforms. # # There are two fan boards, which are FRU's. Each fan board has # 3 fan modules for a total of 6 fan modules, with each fan module # containing 2 fans. The FRU's for the individual fans are the # containing fan module. # # Unfortunately, the IPMI topology on these systems is rather broken, and # all the SDRs that should be separate entities in fact refer to the same # entity IDs. So we have to use the alternative 'entity_present' option # using a single SDR record. # { set => "Sun-Fire-X4240|Sun-Fire-X4440", topology => [ { count => 2, label => "FANBD%d", fru => "self" }, { fac_enum => 1, provider => "fac_prov_ipmi", label => "FANBD%d FM%d", count => 3, fru => "self", entity_present => "fb%d.fm%d.prsnt", entity_ref => "fb%d.fm%d.prsnt", entity_ref_nparams => 2, fm_service_indctr_ => "fb%d.fm%d.led", }, { count => 2, fru => "parent" } ] }, # # Fan Module/Fan topology for G4F platforms. # # These systems have 4 fan assemblies with a single fan per assembly. # Each fan assembly is a FRU. The fan assemblies have a service LED # but no other indicators. # { set => "Sun-Fire-X4600-M2", topology => [ { fac_enum => 1, provider => "fac_prov_ipmi", count => 4, label => "FT %d", fru => "self", entity_ref => "ft%d.fm0.prsnt", entity_ref_nparams => 1, fm_service_indctr => "ft%d.fm0.led" } ] } ); sub usage { print STDERR "Usage: xml-gen -p -i -o \n"; } # # Process an entry in the topology list. We are passed the indentation level, # the current topology array, and any pushed indices. This is called # recursively. # sub process_topology { my ($indent, $toporef, @indices) = @_; my @topo = @$toporef; my $level = shift @topo; my $type = $#topo == -1 ? "fan" : "fanmodule"; printf(OFILE "%*s\n", $indent, "", $type, 0, $level->{count} - 1); $indent += 2; for (my $i = 0; $i < $level->{count}; $i++) { push @indices, $i; printf(OFILE "%*s\n", $indent, "", $i); $indent += 2; # Facility enumerator if ($level->{fac_enum}) { printf(OFILE "%*s\n"); } # Facility nodes for service and ok2rm LED's if ($level->{fm_service_indctr}) { printf(OFILE "%*s\n", $indent+2, ""); printf(OFILE "%*s\n", $indent+4, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+8, "", $level->{fm_service_indctr}); printf(OFILE "%*s\n", $indent+8, ""); printf(OFILE "%*s\n", $indent+8, "", $level->{entity_ref_nparams}); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+4, ""); printf(OFILE "%*s\n", $indent+2, ""); } if ($level->{fm_ok2rm_indctr}) { printf(OFILE "%*s\n", $indent+2, ""); printf(OFILE "%*s\n", $indent+4, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+8, "", $level->{fm_ok2rm_indctr}); printf(OFILE "%*s\n", $indent+8, ""); printf(OFILE "%*s\n", $indent+8, "", $level->{entity_ref_nparams}); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+6, ""); printf(OFILE "%*s\n", $indent+4, ""); printf(OFILE "%*s\n", $indent+2, ""); } # Protocol properties (label, fmri) printf(OFILE "%*s\n", $indent, ""); $indent += 2; if ($level->{label}) { printf(OFILE "%*s\n"); } printf(OFILE "%*s\n", $indent, ""); printf(OFILE "%*s\n", $indent + 2, "", $level->{fru}); printf(OFILE "%*s\n", $indent, ""); $indent -= 2; printf(OFILE "%*s\n", $indent, ""); # # Entity references (if any) # if ($level->{entity_ref} || $level->{entity_present}) { my $name = $level->{entity_ref} ? "entity_ref" : "entity_present"; my $val = $level->{$name}; printf(OFILE "%*s\n", $indent, ""); printf(OFILE "%*s\n"); printf(OFILE "%*s\n", $indent, ""); } # # Post-process IPMI enumerator method # if ($level->{provider}) { printf(OFILE "%*s\n", $indent, ""); } # # Children (if any) # if ($#topo != -1) { printf(OFILE "%*s\n", $indent, ""); process_topology($indent + 2, \@topo, @indices); printf(OFILE "%*s\n", $indent, ""); } $indent -= 2; printf(OFILE "%*s\n", $indent, ""); pop @indices; } $indent -= 2; printf(OFILE "%*s\n", $indent, ""); } # # Process a single platform file. # sub process_platform { my ($desc) = @_; my $indent = 2; printf(OFILE "%*s\n", $indent, "", $desc->{set}); process_topology($indent + 2, $desc->{topology}); printf(OFILE "%*s\n", $indent, ""); } my %options; getopts("p:i:o:h", \%options); if ($options{'h'}) { usage(); exit (1); } my $platform = $options{'p'}; my $input_file = $options{'i'}; my $output_file = $options{'o'}; if (!$platform || !$input_file || !$output_file) { usage(); exit (1); } open(IFILE, "< $input_file") || die("$input_file cannot be opened."); open(OFILE, "> $output_file") || die("$output_file cannot be opened."); # # Open the file and read in the header until we reach the node. # while () { last if /\n"; my $desc; foreach $desc (@platforms) { my $set = $desc->{set}; process_platform($desc); } print OFILE "\n";