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 fac_enum => 1, 58 provider => "fac_prov_ipmi", 59 count => 3, 60 label => "FT %d FM %d", 61 entity_ref => "ft%d.fm%d.led", 62 entity_ref_nparams => 2, 63 fm_service_indctr => "ft%d.fm%d.led", 64 fru => "self" 65 } 66 ] 67 }, 68 69 # 70 # Thumper platforms 71 # 72 # These systems have 5 fan modules, with each fan module containing 2 fans. 73 # The FRUs for the individual fans are the containing fan module. 74 # 75 { 76 set => "Sun-Fire-X4500|Sun-Fire-X4540", 77 topology => [ 78 { 79 fac_enum => 0, 80 provider => "fac_prov_ipmi", 81 label => "FT %d", 82 count => 5, 83 fru => "self", 84 entity_ref => "ft%d.prsnt", 85 entity_ref_nparams => 1, 86 fm_service_indctr => "ft%d.service.led", 87 fm_ok2rm_indctr => "ft%d.ok2rm.led", 88 }, { 89 fac_enum => 1, 90 provider => "fac_prov_ipmi", 91 count => 2, 92 entity_ref => "ft%d.f%d.speed", 93 entity_ref_nparams => 2, 94 fru => "parent" 95 } 96 ] 97 }, 98 99 # 100 # Fan Module/Fan topology for all G1N/G2N platforms. 101 # 102 # There are two fan boards, which are FRU's. Each fan board has 103 # 3 fan modules for a total of 6 fan modules, with each fan module 104 # containing 2 fans. The FRU's for the individual fans are the 105 # containing fan module. 106 # 107 # Unfortunately, the IPMI topology on these systems is rather broken, and 108 # all the SDRs that should be separate entities in fact refer to the same 109 # entity IDs. So we have to use the alternative 'entity_present' option 110 # using a single SDR record. 111 # 112 { 113 set => "Sun-Fire-X4240|Sun-Fire-X4440", 114 topology => [ 115 { 116 count => 2, 117 label => "FANBD%d", 118 fru => "self" 119 }, { 120 fac_enum => 1, 121 provider => "fac_prov_ipmi", 122 label => "FANBD%d FM%d", 123 count => 3, 124 fru => "self", 125 entity_present => "fb%d.fm%d.prsnt", 126 entity_ref => "fb%d.fm%d.prsnt", 127 entity_ref_nparams => 2, 128 fm_service_indctr_ => "fb%d.fm%d.led", 129 }, { 130 count => 2, 131 fru => "parent" 132 } 133 134 ] 135 }, 136 137 # 138 # Fan Module/Fan topology for G4F platforms. 139 # 140 # These systems have 4 fan assemblies with a single fan per assembly. 141 # Each fan assembly is a FRU. The fan assemblies have a service LED 142 # but no other indicators. 143 # 144 { 145 set => "Sun-Fire-X4600-M2", 146 topology => [ 147 { 148 fac_enum => 1, 149 provider => "fac_prov_ipmi", 150 count => 4, 151 label => "FT %d", 152 fru => "self", 153 entity_ref => "ft%d.fm0.prsnt", 154 entity_ref_nparams => 1, 155 fm_service_indctr => "ft%d.fm0.led" 156 } 157 ] 158 } 159); 160 161sub usage 162{ 163 print STDERR "Usage: xml-gen -p <platform> -i <input_xml_file> -o <output_xml_file>\n"; 164} 165 166# 167# Process an entry in the topology list. We are passed the indentation level, 168# the current topology array, and any pushed indices. This is called 169# recursively. 170# 171sub process_topology 172{ 173 my ($indent, $toporef, @indices) = @_; 174 my @topo = @$toporef; 175 my $level = shift @topo; 176 my $type = $#topo == -1 ? "fan" : "fanmodule"; 177 178 printf(OFILE "%*s<range name='%s' min='%d' max='%d'>\n", 179 $indent, "", $type, 0, $level->{count} - 1); 180 $indent += 2; 181 182 for (my $i = 0; $i < $level->{count}; $i++) { 183 push @indices, $i; 184 185 printf(OFILE "%*s<node instance='%d'>\n", $indent, "", $i); 186 187 $indent += 2; 188 189 # Facility enumerator 190 if ($level->{fac_enum}) { 191 printf(OFILE "%*s<fac-enum provider='", 192 $indent, ""); 193 printf(OFILE $level->{provider}, @indices); 194 printf(OFILE "' />\n"); 195 } 196 197 # Facility nodes for service and ok2rm LED's 198 if ($level->{fm_service_indctr}) { 199 printf(OFILE "%*s<facility name='service' type='indicator' ". 200 "provider='fac_prov_ipmi' >\n", $indent+2, ""); 201 printf(OFILE "%*s<propgroup name='facility' version='1' ". 202 "name-stability='Private' data-stability='Private' >\n", 203 $indent+4, ""); 204 printf(OFILE "%*s<propval name='type' type='uint32' ". 205 "value='1' />\n", $indent+6, ""); 206 printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ". 207 "propname='entity_ref' proptype='string' >\n", 208 $indent+6, ""); 209 printf(OFILE "%*s<argval name='format' type='string' ". 210 "value='%s' />\n", $indent+8, "", 211 $level->{fm_service_indctr}); 212 printf(OFILE "%*s<argval name='offset' type='uint32' ". 213 "value='0' />\n", $indent+8, ""); 214 printf(OFILE "%*s<argval name='nparams' type='uint32' ". 215 "value='%d' />\n", $indent+8, "", 216 $level->{entity_ref_nparams}); 217 printf(OFILE "%*s</propmethod>\n", $indent+6, ""); 218 printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ". 219 "version='0' propname='mode' proptype='uint32' ". 220 "mutable='1' >\n", $indent+6, ""); 221 printf(OFILE "%*s</propmethod>\n", $indent+6, ""); 222 printf(OFILE "%*s</propgroup>\n", $indent+4, ""); 223 printf(OFILE "%*s</facility>\n", $indent+2, ""); 224 } 225 if ($level->{fm_ok2rm_indctr}) { 226 printf(OFILE "%*s<facility name='ok2rm' type='indicator' ". 227 "provider='fac_prov_ipmi' >\n", $indent+2, ""); 228 printf(OFILE "%*s<propgroup name='facility' version='1' ". 229 "name-stability='Private' data-stability='Private' >\n", 230 $indent+4, ""); 231 printf(OFILE "%*s<propval name='type' type='uint32' ". 232 "value='2' />\n", $indent+6, ""); 233 printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ". 234 "propname='entity_ref' proptype='string' >\n", 235 $indent+6, ""); 236 printf(OFILE "%*s<argval name='format' type='string' ". 237 "value='%s' />\n", $indent+8, "", 238 $level->{fm_ok2rm_indctr}); 239 printf(OFILE "%*s<argval name='offset' type='uint32' ". 240 "value='0' />\n", $indent+8, ""); 241 printf(OFILE "%*s<argval name='nparams' type='uint32' ". 242 "value='%d' />\n", $indent+8, "", 243 $level->{entity_ref_nparams}); 244 printf(OFILE "%*s</propmethod>\n", $indent+6, ""); 245 printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ". 246 "version='0' propname='mode' proptype='uint32' mutable='1' >\n", 247 $indent+6, ""); 248 printf(OFILE "%*s</propmethod>\n", $indent+6, ""); 249 printf(OFILE "%*s</propgroup>\n", $indent+4, ""); 250 printf(OFILE "%*s</facility>\n", $indent+2, ""); 251 } 252 # Protocol properties (label, fmri) 253 printf(OFILE "%*s<propgroup name='protocol' version='1' " . 254 "name-stability='Private' data-stability='Private'>\n", 255 $indent, ""); 256 257 $indent += 2; 258 259 if ($level->{label}) { 260 printf(OFILE "%*s<propval name='label' type='string' " . 261 "value='", $indent, ""); 262 printf(OFILE $level->{label}, @indices); 263 printf(OFILE "' />\n"); 264 } 265 266 printf(OFILE "%*s<propmethod name='ipmi_fru_fmri' " . 267 "version='0' propname='FRU' proptype='fmri'>\n", 268 $indent, ""); 269 printf(OFILE "%*s<argval name='entity' type='string' " . 270 "value='%s' />\n", $indent + 2, "", $level->{fru}); 271 printf(OFILE "%*s</propmethod>\n", $indent, ""); 272 273 $indent -= 2; 274 275 printf(OFILE "%*s</propgroup>\n", $indent, ""); 276 277 # 278 # Entity references (if any) 279 # 280 if ($level->{entity_ref} || $level->{entity_present}) { 281 my $name = $level->{entity_ref} ? "entity_ref" : 282 "entity_present"; 283 my $val = $level->{$name}; 284 printf(OFILE "%*s<propgroup name='ipmi' version='1' " . 285 "name-stability='Private' " . 286 "data-stability='Private' >\n", $indent, ""); 287 printf(OFILE "%*s<propval name='%s' " . 288 "type='string' value='", $indent + 2, "", $name); 289 printf(OFILE $val, @indices); 290 printf(OFILE "' />\n"); 291 printf(OFILE "%*s</propgroup>\n", $indent, ""); 292 } 293 294 # 295 # Post-process IPMI enumerator method 296 # 297 if ($level->{provider}) { 298 printf(OFILE "%*s<enum-method name='ipmi' version='1' ". 299 "/>\n", $indent, ""); 300 } 301 302 # 303 # Children (if any) 304 # 305 if ($#topo != -1) { 306 printf(OFILE "%*s<dependents grouping='children'>\n", 307 $indent, ""); 308 process_topology($indent + 2, \@topo, @indices); 309 printf(OFILE "%*s</dependents>\n", $indent, ""); 310 } 311 312 $indent -= 2; 313 314 printf(OFILE "%*s</node>\n", $indent, ""); 315 pop @indices; 316 } 317 318 $indent -= 2; 319 printf(OFILE "%*s</range>\n", $indent, ""); 320} 321 322# 323# Process a single platform file. 324# 325sub process_platform 326{ 327 my ($desc) = @_; 328 my $indent = 2; 329 330 printf(OFILE "%*s<set type='product' setlist='%s'>\n", $indent, "", 331 $desc->{set}); 332 333 process_topology($indent + 2, $desc->{topology}); 334 335 printf(OFILE "%*s</set>\n", $indent, ""); 336} 337 338my %options; 339getopts("p:i:o:h", \%options); 340if ($options{'h'}) { 341 usage(); 342 exit (1); 343} 344 345my $platform = $options{'p'}; 346my $input_file = $options{'i'}; 347my $output_file = $options{'o'}; 348 349if (!$platform || !$input_file || !$output_file) { 350 usage(); 351 exit (1); 352} 353 354open(IFILE, "< $input_file") || die("$input_file cannot be opened."); 355open(OFILE, "> $output_file") || die("$output_file cannot be opened."); 356 357# 358# Open the file and read in the header until we reach the <topology> node. 359# 360while (<IFILE>) { 361 last if /<topology/; 362 print OFILE; 363} 364 365# 366# Construct the framework. 367# 368print OFILE "<topology name='fan' scheme='hc'>\n"; 369 370my $desc; 371foreach $desc (@platforms) { 372 my $set = $desc->{set}; 373 process_platform($desc); 374} 375 376print OFILE "</topology>\n"; 377