1#!/usr/bin/perl -w 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# 23# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26#ident "%Z%%M% %I% %E% SMI" 27 28# 29# The fan topologies can be quite complicated, but are ultimately regular. This 30# perl file uses some simplified internal structures to generate an .xml file 31# without the maintenance overhead. 32# 33 34use Getopt::Std; 35use strict; 36 37# 38# Master table of platforms. 39# 40my @platforms = ( 41 # 42 # Galaxy 1/2 platforms. 43 # 44 # These systems have 2 fan-connector boards. Each fan-connector board has 3 45 # fan modules. Each fan module is an individual FRU. The fan-connector 46 # boards are also FRUs. 47 # 48 { 49 set => "Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|" . 50 "Sun-Fire-X4100-M2|Sun-Fire-X4200-M2", 51 topology => [ 52 { 53 label => "FT %d", 54 count => 2, 55 fru => "self" 56 }, { 57 count => 3, 58 label => "FT %d FM %d", 59 entity_ref => "ft%d.fm%d.led", 60 fru => "self" 61 } 62 ] 63 }, 64 65 # 66 # Thumper platforms 67 # 68 # These systems have 5 fan modules, with each fan module containing 2 fans. 69 # The FRUs for the individual fans are the containing fan module. 70 # 71 { 72 set => "Sun-Fire-X4500|Sun-Fire-X4540", 73 topology => [ 74 { 75 label => "FT %d", 76 count => 5, 77 fru => "self", 78 entity_ref => "ft%d.prsnt", 79 }, { 80 count => 2, 81 fru => "parent" 82 } 83 ] 84 }, 85 86 # 87 # Fan Module/Fan topology for all G1N/G2N platforms. 88 # 89 # These systems have 6 fan modules, with each fan module containing 2 fans. 90 # The FRU's for the individual fans are the containing fan module. 91 # 92 # Unfortunately, the IPMI topology on these systems is rather broken, and 93 # all the SDRs that should be separate entities in fact refer to the same 94 # entity IDs. So we have to use the alternative 'entity_present' option 95 # using a single SDR record. 96 # 97 { 98 set => "Sun-Fire-X4240|Sun-Fire-X4440", 99 topology => [ 100 { 101 count => 2, 102 label => "FT %d", 103 fru => "self" 104 }, { 105 label => "FT %d FM %d", 106 count => 3, 107 fru => "self", 108 entity_present => "fb%d.fm%d.prsnt", 109 }, { 110 count => 2, 111 fru => "parent" 112 } 113 114 ] 115 } 116); 117 118sub usage 119{ 120 print STDERR "Usage: xml-gen -p <platform> -i <input_xml_file> -o <output_xml_file>\n"; 121} 122 123# 124# Process an entry in the topology list. We are passed the indentation level, 125# the current topology array, and any pushed indices. This is called 126# recursively. 127# 128sub process_topology 129{ 130 my ($indent, $toporef, @indices) = @_; 131 my @topo = @$toporef; 132 my $level = shift @topo; 133 my $type = $#topo == -1 ? "fan" : "fanmodule"; 134 135 printf(OFILE "%*s<range name='%s' min='%d' max='%d'>\n", 136 $indent, "", $type, 0, $level->{count} - 1); 137 $indent += 2; 138 139 for (my $i = 0; $i < $level->{count}; $i++) { 140 push @indices, $i; 141 142 printf(OFILE "%*s<node instance='%d'>\n", $indent, "", $i); 143 144 $indent += 2; 145 146 # Protocol properties (label, fmri) 147 printf(OFILE "%*s<propgroup name='protocol' version='1' " . 148 "name-stability='Private' data-stability='Private'>\n", 149 $indent, ""); 150 151 $indent += 2; 152 153 if ($level->{label}) { 154 printf(OFILE "%*s<propval name='label' type='string' " . 155 "value='", $indent, ""); 156 printf(OFILE $level->{label}, @indices); 157 printf(OFILE "' />\n"); 158 } 159 160 printf(OFILE "%*s<propmethod name='ipmi_fru_fmri' " . 161 "version='0' propname='FRU' proptype='fmri'>\n", 162 $indent, ""); 163 printf(OFILE "%*s<argval name='entity' type='string' " . 164 "value='%s' />\n", $indent + 2, "", $level->{fru}); 165 printf(OFILE "%*s</propmethod>\n", $indent, ""); 166 167 $indent -= 2; 168 169 printf(OFILE "%*s</propgroup>\n", $indent, ""); 170 171 # 172 # Entity reference (if any) 173 # 174 if ($level->{entity_ref} || $level->{entity_present}) { 175 my $name = $level->{entity_ref} ? "entity_ref" : 176 "entity_present"; 177 my $val = $level->{$name}; 178 printf(OFILE "%*s<propgroup name='ipmi' version='1' " . 179 "name-stability='Private' " . 180 "data-stability='Private' >\n", $indent, ""); 181 printf(OFILE "%*s<propval name='%s' " . 182 "type='string' value='", $indent + 2, "", $name); 183 printf(OFILE $val, @indices); 184 printf(OFILE "' />\n"); 185 printf(OFILE "%*s</propgroup>\n", $indent, ""); 186 } 187 188 189 # 190 # Children (if any) 191 # 192 if ($#topo != -1) { 193 printf(OFILE "%*s<dependents grouping='children'>\n", 194 $indent, ""); 195 process_topology($indent + 2, \@topo, @indices); 196 printf(OFILE "%*s</dependents>\n", $indent, ""); 197 } 198 199 # 200 # Post-process IPMI enumerator method 201 # 202 printf(OFILE "%*s<enum-method name='ipmi' version='1' />\n", 203 $indent, ""); 204 205 $indent -= 2; 206 207 printf(OFILE "%*s</node>\n", $indent, ""); 208 pop @indices; 209 } 210 211 $indent -= 2; 212 printf(OFILE "%*s</range>\n", $indent, ""); 213} 214 215# 216# Process a single platform file. 217# 218sub process_platform 219{ 220 my ($desc) = @_; 221 my $indent = 2; 222 223 printf(OFILE "%*s<set type='product' setlist='%s'>\n", $indent, "", 224 $desc->{set}); 225 226 process_topology($indent + 2, $desc->{topology}); 227 228 printf(OFILE "%*s</set>\n", $indent, ""); 229} 230 231my %options; 232getopts("p:i:o:h", \%options); 233if ($options{'h'}) { 234 usage(); 235 exit (1); 236} 237 238my $platform = $options{'p'}; 239my $input_file = $options{'i'}; 240my $output_file = $options{'o'}; 241 242if (!$platform || !$input_file || !$output_file) { 243 usage(); 244 exit (1); 245} 246 247open(IFILE, "< $input_file") || die("$input_file cannot be opened."); 248open(OFILE, "> $output_file") || die("$output_file cannot be opened."); 249 250# 251# Open the file and read in the header until we reach the <topology> node. 252# 253while (<IFILE>) { 254 last if /<topology/; 255 print OFILE; 256} 257 258# 259# Construct the framework. 260# 261print OFILE "<topology name='fan' scheme='hc'>\n"; 262 263my $desc; 264foreach $desc (@platforms) { 265 my $set = $desc->{set}; 266 process_platform($desc); 267} 268 269print OFILE "</topology>\n"; 270