blob: dc8fba4582ba4a70c83c9669af0b5c101f340845 [file] [log] [blame]
Matt Spinlerbfd10b12016-12-09 10:16:54 -06001package Inventory;
2
3use strict;
Matt Spinler39a033b2016-12-21 14:08:59 -06004use warnings;
Matt Spinlerbfd10b12016-12-09 10:16:54 -06005
Matt Spinler39a033b2016-12-21 14:08:59 -06006#Target types to always include in the inventory if present
7my %TYPES = (SYS => 1, NODE => 1, PROC => 1, BMC => 1, GPU => 1);
8
9#RU_TYPES of cards to include
10#FRU = field replaceable unit, CRU = customer replaceable unit
11my %RU_TYPES = (FRU => 1, CRU => 1);
12
Matt Spinlerfe759642016-12-21 14:13:59 -060013#Chips that are modeled as modules (card-chip together)
14my %MODULE_TYPES = (PROC => 1, GPU => 1);
15
Matt Spinler39a033b2016-12-21 14:08:59 -060016#Returns an array of hashes that represents the inventory
17#for a system. The hash elements are:
18#TARGET: The MRW target of the item
19#OBMC_NAME: The OpenBMC name for the item. This is usually
20# a simplified version of the target.
Matt Spinlerbfd10b12016-12-09 10:16:54 -060021sub getInventory
22{
23 my $targetObj = shift;
24 my @inventory;
25
Matt Spinler39a033b2016-12-21 14:08:59 -060026 if (ref($targetObj) ne "Targets") {
27 die "Invalid Targets object passed to getInventory\n";
28 }
29
30 findItems($targetObj, \@inventory);
31
Matt Spinlerfe759642016-12-21 14:13:59 -060032 pruneModuleCards($targetObj, \@inventory);
33
Matt Spinlerc119a902016-12-21 14:19:25 -060034 makeOBMCNames($targetObj, \@inventory);
35
Matt Spinlerbfd10b12016-12-09 10:16:54 -060036 return @inventory;
37}
38
Matt Spinler39a033b2016-12-21 14:08:59 -060039
40#Finds the inventory targets in the MRW.
41#It selects them if the target's type is in %TYPES
42#or the target's RU_TYPE is in %RU_TYPES.
43#This will pick up FRUs and other chips like the BMC and processor.
44sub findItems
45{
46 my ($targetObj, $inventory) = @_;
47
48 for my $target (sort keys %{$targetObj->getAllTargets()}) {
49 my $type = "";
50 my $ruType = "";
51
52 if (!$targetObj->isBadAttribute($target, "TYPE")) {
53 $type = $targetObj->getAttribute($target, "TYPE");
54 }
55
56 if (!$targetObj->isBadAttribute($target, "RU_TYPE")) {
57 $ruType = $targetObj->getAttribute($target, "RU_TYPE");
58 }
59
60 if ((exists $TYPES{$type}) || (exists $RU_TYPES{$ruType})) {
61 my %item;
62 $item{TARGET} = $target;
63 $item{OBMC_NAME} = $target; #Will fixup later
64 push @$inventory, { %item };
65 }
66 }
67}
68
69
Matt Spinlerfe759642016-12-21 14:13:59 -060070#Removes entries from the inventory for the card target of a module.
71#Needed because processors and GPUs are modeled as a package which
72#is a card-chip instance that plugs into a connector on the
73#backplane/processor card. Since we already include the chip target
74#in the inventory (that's how we can identify what it is), we don't
75#need the entry for the card target.
76#
77#For example, we'll already have .../module-0/proc-0 so we don't
78#need a separate .../module-0 entry.
79sub pruneModuleCards
80{
81 my ($targetObj, $inventory) = @_;
82 my @toRemove;
83
84 #Find the parent (a card) of items of type %type
85 for my $item (@$inventory) {
86
87 if (exists $MODULE_TYPES{$targetObj->getType($item->{TARGET})}) {
88 my $card = $targetObj->getTargetParent($item->{TARGET});
89 push @toRemove, $card;
90 }
91 }
92
93 #Remove these parent cards
94 for my $c (@toRemove) {
95 for my $i (0 .. (scalar @$inventory) - 1) {
96 if ($c eq $inventory->[$i]{TARGET}) {
97 splice(@$inventory, $i, 1);
98 last;
99 }
100 }
101 }
102}
103
Matt Spinlerc119a902016-12-21 14:19:25 -0600104
105#Makes the OpenBMC name for the targets in the inventory.
106#Removes unnecessary segments of the path name, renames
107#some segments to match standard conventions, and numbers
108#segments based on their position attribute.
109sub makeOBMCNames
110{
111 my ($targetObj, $inventory) = @_;
112
113 #Remove connector segments from the OBMC_NAME
114 removeConnectors($targetObj, $inventory);
115
116}
117
118
119#Removes connectors from the OBMC_NAME element. Also
120#takes the POSITION value of the connector and adds it
121#to the card segment that plugs into the connector.
122#For example:
123# /motherboard/card-conn-5/card-0 ->
124# /motherobard/card-5
125sub removeConnectors
126{
127 my ($targetObj, $inventory) = @_;
128
129 #Find the connectors embedded in the segments
130 for my $item (@$inventory) {
131
132 #Split the target into segments, then start
133 #adding segments in to make new targets
134 my @segments = split('/', $item->{TARGET});
135 my $target = "";
136 for my $s (@segments) {
137 next if (length($s) == 0);
138
139 $target .= "/$s";
140 my $class = $targetObj->getAttribute($target, "CLASS");
141 next unless ($class eq "CONNECTOR");
142
143 my ($segment) = $target =~ /\b(\w+-\d+)$/;
144 my $pos = $targetObj->getAttribute($target, "POSITION");
145
146 #change /connector-11/card-2/ to /card-11/
147 $item->{OBMC_NAME} =~ s/\b$segment\/(\w+)-\d+/$1-$pos/;
148
149 }
150 }
151}
152
Matt Spinlerbfd10b12016-12-09 10:16:54 -06001531;
154
155=head1 NAME
156
157Inventory
158
159=head1 DESCRIPTION
160
161Retrieves the OpenBMC inventory from the MRW.
162
163The inventory contains:
164
165=over 4
166
167=item * The system target
168
169=item * The chassis target(s) (Called a 'node' in the MRW.)
170
171=item * All targets of class CARD or CHIP that are FRUs.
172
173=item * All targets of type PROC
174
175=item * All targets of type BMC
176
177=item * All targets of type GPU
178
179=back
180
181=head2 Notes:
182
183The processor and GPU chips are usually modeled in the MRW as a
184card->chip package that would plug into a connector on the motherboard
185or other parent card. So, even if both card and chip are marked as a FRU,
186there will only be 1 entry in the inventory for both, and the MRW
187target associated with it will be for the chip and not the card.
188
189In addition, this intermediate card will be removed from the path name:
190 /system/chassis/motheboard/cpu and not
191 /system/chassis/motherboard/cpucard/cpu
192
193=head2 Inventory naming conventions
194
195The inventory names returned in the OBMC_NAME hash element will follow
196the conventions listed below. An example of an inventory name is:
197/system/chassis/motherboard/cpu5
198
199=over 4
200
201=item * If there is only 1 instance of any segment in the system, then
202 it won't have an instance number, otherwise there will be one.
203
204=item * The root of the name is '/system'.
205
206=item * After system is 'chassis', of which there can be 1 or more.
207
208=item * The name is based on the MRW card plugging order, and not what
209 the system looks like from the outside. For example, a power
210 supply that plugs into a motherboard (maybe via a non-fru riser
211 or cable, see the item below), would be:
212 /system/chassis/motherboard/psu2 and not
213 /system/chassis/psu2.
214
215=item * If a card is not a FRU so isn't in the inventory itself, then it
216 won't show up in the name of any child cards that are FRUs.
217 For example, if fan-riser isn't a FRU, it would be
218 /system/chassis/motherboard/fan3 and not
219 /system/chassis/motherboard/fan-riser/fan3.
220
221=item * The MRW models connectors between cards, but these never show up
222 in the inventory name.
223
224=item * If there is a motherboard, it is always called 'motherboard'.
225
226=item * Processors, GPUs, and BMCs are always called: 'cpu', 'gpu' and
227 'bmc' respectively.
228
229=back
230
231=head1 METHODS
232
233=over 4
234
235=item getInventory (C<TargetsObj>)
236
237Returns an array of hashes representing inventory items.
238
239The Hash contains:
240
241* TARGET: The MRW target of the item, for example:
242
243 /sys-0/node-0/motherboard-0/proc_socket-0/module-0/p9_proc_m
244
245* OBMC_NAME: The OpenBMC name of the item, for example:
246
247 /system/chassis/motherboard/cpu2
248
249=back
250
251=cut