Support building p10 PNOR images
Implements initial experimental support for building P10 PNOR images using
GCC8 (host and cross compiler) as the toolchain
- Introduced rainier configuration files
- Added p10 specific packages for sbe, hcode, hostboot, occ
- Pointed at starting commits for various pacakges to build op-build for p10
- Created various patches to fully compile all packages, to be removed
when package owners have time to address them
- Generally updated package configurations to support p10 and p10 package
variants
Signed-off-by: Nick Bofferding <bofferdn@us.ibm.com>
diff --git a/openpower/package/hostboot-p10/0001-mrw-parser-initial-fixes.patch b/openpower/package/hostboot-p10/0001-mrw-parser-initial-fixes.patch
new file mode 100644
index 0000000..e014d7d
--- /dev/null
+++ b/openpower/package/hostboot-p10/0001-mrw-parser-initial-fixes.patch
@@ -0,0 +1,2216 @@
+From c69095d5359b800068c258819014f0bb684046f6 Mon Sep 17 00:00:00 2001
+From: Roland Veloz <rveloz@us.ibm.com>
+Date: Fri, 6 Sep 2019 13:52:32 -0500
+Subject: [PATCH] P10 MRW parsing: Changes to the parser scripts
+
+This commit deals with refactoring and modularizing the processMrw.pl
+and Targets.pm scripts. This commit is not about the artifact that
+gets produced by these files but the act of parsing an MRW file.
+
+Change-Id: I359afeebd9aa00ec6db2857a03ba0d9684c0858e
+RTC: 215164
+---
+ src/usr/targeting/common/Targets.pm | 637 +++++++++++------
+ src/usr/targeting/common/processMrw.pl | 1183 +++++++++++++++++++++-----------
+ 2 files changed, 1218 insertions(+), 602 deletions(-)
+
+diff --git a/src/usr/targeting/common/Targets.pm b/src/usr/targeting/common/Targets.pm
+index dfd65d6..fb0bcbb 100644
+--- a/src/usr/targeting/common/Targets.pm
++++ b/src/usr/targeting/common/Targets.pm
+@@ -91,10 +91,29 @@ my %maxInstance = (
+ "SMPGROUP" => 8,
+ "OMIC" => 6,
+ );
++
++#--------------------------------------------------
++# @brief The constructor for the object Target
++#--------------------------------------------------
+ sub new
+ {
+ my $class = shift;
+ my $self = {
++ # The following data are associated with the
++ # user command line options
++ build => "hb", # default to HB
++ force => 0,
++ serverwiz_file => "", # input xml file
++ serverwiz_dir => "", # directory of input xml file
++ debug => 0,
++ system_config => "",
++ output_file => "",
++ version => 0,
++ report => 0,
++ run_self_test => 0, # run internal test
++
++ # The following data are associated with the
++ # xml itself
+ xml => undef,
+ data => undef,
+ targeting => undef,
+@@ -103,13 +122,11 @@ sub new
+ UNIT_COUNTS => undef,
+ huid_idx => undef,
+ mru_idx => undef,
+- force => 0,
+- debug => 0,
+- version => "",
+ xml_version => 0,
+ errorsExist => 0,
+ NUM_PROCS => 0,
+ TOP_LEVEL => "",
++ TOP_LEVEL_HANDLE => undef,
+ TOPOLOGY => undef,
+ report_log => "",
+ vpd_num => 0,
+@@ -388,6 +405,162 @@ sub storeGroups
+ }
+ }
+
++#--------------------------------------------------
++# @brief Initialize a handle to the target instance.
++#
++# @details This method locates where the target instance
++# resides and caches it for fast retrieval.
++#
++# @post A handle to the target instance is cached or exit
++# stating that the target instance cannot be found.
++#
++# @param [in] $self - The global target object.
++#--------------------------------------------------
++sub initializeTargetInstanceHandle
++{
++ my $self = shift;
++
++ if ( (!defined $self->{TARGET_INST_HANDLE}) ||
++ ($self->{TARGET_INST_HANDLE} eq "") )
++ {
++ # Find the location of where target instances reside
++ my $targetInstances = $self->{xml}->{'targetInstance'};
++ if (!defined $targetInstances)
++ {
++ # Check one more level for the target instances
++ $targetInstances = $self->{xml}->{'targetInstances'}
++ ->{'targetInstance'};
++ }
++
++ # If can't find the target instances, then state so and exit
++ if (!defined $targetInstances)
++ {
++ die "No target instances defined\n";
++ }
++
++ $self->setTargetInstanceHandle($targetInstances);
++ } # end if ( (!defined $self->{TARGET_INST_HANDLE}) || ...
++}
++
++#--------------------------------------------------
++# @brief Return a handle to the target instances.
++#
++# @details This method will initialize the target instances
++# if has not been already initialized.
++#
++# @param [in] $self - The global target object.
++#
++# @return - A handle to the target instance.
++#--------------------------------------------------
++sub getTargetInstanceHandle
++{
++ my $self = shift;
++
++ # If handle to target instances is not already cached, then initialize it
++ if ( (!defined $self->{TARGET_INST_HANDLE}) ||
++ ($self->{TARGET_INST_HANDLE} eq "") )
++ {
++ $self->initializeTargetInstanceHandle();
++ }
++
++ return ($self->{TARGET_INST_HANDLE});
++}
++
++#--------------------------------------------------
++# @brief Set the target instance handle to the given target handle
++#
++# @param [in] $self - The global target object.
++# @param [in] $targetHndl - The value the target instance handle is set to.
++#--------------------------------------------------
++sub setTargetInstanceHandle
++{
++ my $self = shift;
++ my $targetHndl = shift;
++
++ # Dynamically create and cache a handle to the target instance
++ $self->{TARGET_INST_HANDLE} = $targetHndl;
++}
++
++#--------------------------------------------------
++# @brief Initialize the top level target.
++#
++# @details This method locate the top level target
++# and cache it for fast retrieval.
++#
++# @post The top level target is cached or exit stating that
++# top level target not found.
++#
++# @param [in] $self - The global target object.
++#--------------------------------------------------
++sub initalizeTopLevel
++{
++ my $self = shift;
++
++ # If the top level target instance has not been found and set,
++ # then find that target and set top level to it
++ if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++ {
++ # Get a handle to the target instances
++ my $targetInstancesHandle = $self->getTargetInstanceHandle();
++
++ # Find the system target which is the top level target
++ foreach my $target (keys(%{$targetInstancesHandle}))
++ {
++ # If target is of type 'SYS' then we found the top level target
++ if ($targetInstancesHandle->{$target}->{attribute}
++ ->{TYPE}->{default} eq "SYS")
++ {
++ # Set the top level target and search no more
++ $self->setTopLevel($target);
++ # YOU SHALL NOT PASS!!!
++ last;
++ }
++ }
++
++ # If unable to find top level target, then state so and exit
++ if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++ {
++ die "Unable to find system top level target\n";
++ }
++ } # end if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++}
++
++#--------------------------------------------------
++# @brief Return the top level target.
++#
++# @details This method will initialize the top level
++# target if has not been already initialized.
++#
++# @param [in] $self - The global target object.
++#
++# @return - The top level target.
++#--------------------------------------------------
++sub getTopLevel
++{
++ my $self = shift;
++
++ # If the top level target is not already cached, then initialize it
++ if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++ {
++ $self->initalizeTopLevel();
++ }
++ return ($self->{TOP_LEVEL});
++}
++
++#--------------------------------------------------
++# @brief Set the top level target to the given target.
++#
++# @param [in] $self - The global target object.
++# @param [in] $target - The value the top level target is set to.
++#--------------------------------------------------
++sub setTopLevel
++{
++ my $self = shift;
++ my $target = shift;
++
++ $self->{TOP_LEVEL} = $target;
++}
++
+ ####################################################
+ ## build target hierarchy recursively
+ ##
+@@ -422,34 +595,23 @@ sub buildHierarchy
+ my $self = shift;
+ my $target = shift;
+
+- my $instance_path = $self->{data}->{INSTANCE_PATH};
+- if (!defined $instance_path)
+- {
+- $instance_path = "";
+- }
+- my $baseptr = $self->{xml}->{'targetInstance'};
+- if ($self->{xml_version} == 1)
+- {
+- $baseptr = $self->{xml}->{'targetInstances'}->{'targetInstance'};
+- }
++ # Get a handle to the target instances
++ my $targetInstanceRef = $self->getTargetInstanceHandle();
++
++ # If caller did not provide a target, then use the top level target
+ if ($target eq "")
+ {
+- ## find system target
+- foreach my $t (keys(%{$baseptr}))
+- {
+- if ($baseptr->{$t}->{attribute}->{TYPE}->{default} eq "SYS")
+- {
+- $self->{TOP_LEVEL} = $t;
+- $target = $t;
+- }
+- }
++ $target = $self->getTopLevel();
+ }
+- if ($target eq "")
++
++ my $instance_path = $self->{data}->{INSTANCE_PATH};
++ if (!defined $instance_path)
+ {
+- die "Unable to find system top level target\n";
++ $instance_path = "";
+ }
++
+ my $old_path = $instance_path;
+- my $target_xml = $baseptr->{$target};
++ my $target_xml = $targetInstanceRef->{$target};
+ my $affinity_target = $target;
+ my $key = $instance_path . "/" . $target;
+
+@@ -466,7 +628,6 @@ sub buildHierarchy
+ $self->{data}->{INSTANCE_PATH} = $old_path . "/" . $target;
+
+ ## copy attributes
+-
+ foreach my $attribute (keys %{ $target_xml->{attribute} })
+ {
+ my $value = $target_xml->{attribute}->{$attribute}->{default};
+@@ -2448,192 +2609,6 @@ sub findDestConnections
+
+ }
+
+-sub setEepromAttributesForAxone
+-{
+- my $self = shift;
+- my $targetObj = shift;
+- # Expects ocmb target
+- my $target = shift;
+-
+- my %connections;
+- my $num=0;
+-
+- my $eeprom_name = "EEPROM_VPD_PRIMARY_INFO";
+- my $fapi_name = "FAPI_I2C_CONTROL_INFO";
+- # SPD contains data for EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO
+- # SPD is the child of ocmb's parent, so get ocmb's parent
+- # then look for the SPD child
+- # With the resulting info, we populate pmic0, pmic1, ocmb, and dimm
+- my $target_parent = $self->getTargetParent($target);
+-
+- # Need to store pmic targets because they get parsed before we
+- # do calculations for engine, port, and muxBusSelector
+- # pmics need these values, so we store them until we need them later
+- my $address = 0;
+- my @pmic_array;
+- foreach my $child (@{ $self->getTargetChildren($target_parent) })
+- {
+- my $type = $self->getTargetType($child);
+- if ($type eq "chip-spd-device")
+- {
+- my $offset = $self->getAttribute($child, "BYTE_ADDRESS_OFFSET");
+- my $memory_size = $self->getAttribute($child, "MEMORY_SIZE_IN_KB");
+- my $cycle_time = $self->getAttribute($child, "WRITE_CYCLE_TIME");
+- my $page_size = $self->getAttribute($child, "WRITE_PAGE_SIZE");
+-
+- # Populate EEPROM for ocmb
+- $targetObj->setAttributeField($target, $eeprom_name, "byteAddrOffset",
+- $offset);
+- $targetObj->setAttributeField($target, $eeprom_name, "maxMemorySizeKB",
+- $memory_size);
+- $targetObj->setAttributeField($target, $eeprom_name, "writeCycleTime",
+- $cycle_time);
+- $targetObj->setAttributeField($target, $eeprom_name, "writePageSize",
+- $page_size);
+-
+- # Populate EEPROM for dimm
+- $targetObj->setAttributeField($target_parent, $eeprom_name, "byteAddrOffset",
+- $offset);
+- $targetObj->setAttributeField($target_parent, $eeprom_name, "maxMemorySizeKB",
+- $memory_size);
+- $targetObj->setAttributeField($target_parent, $eeprom_name, "writeCycleTime",
+- $cycle_time);
+- $targetObj->setAttributeField($target_parent, $eeprom_name, "writePageSize",
+- $page_size);
+-
+- # spd only child is i2c-slave, which contains devAddr info
+- foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
+- {
+- $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
+- # Populate EEPROM for dimm
+- $targetObj->setAttributeField($target_parent, $eeprom_name, "devAddr",
+- $address);
+-
+- # Populate EEPROM for ocmb
+- $targetObj->setAttributeField($target, $eeprom_name, "devAddr",
+- $address);
+- }
+- }
+- elsif ($type eq "chip-vreg-generic")
+- {
+- push(@pmic_array, $child);
+- foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
+- {
+- $type = $self->getTargetType($i2c_slave);
+- # pmic has child i2c_slave which contains the device address
+- if ($type eq "unit-i2c-slave")
+- {
+- $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
+-
+- # Populate FAPI for pmic
+- $targetObj->setAttributeField($child, $fapi_name, "devAddr",
+- $address);
+- last;
+- }
+- }
+- }
+- elsif ($type eq "chip-ocmb")
+- {
+- foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
+- {
+- # ocmb has multiple i2c-slaves, so we query with instance_name
+- my $instance_name = $self->getInstanceName($i2c_slave);
+- if ($instance_name eq "i2c-ocmb")
+- {
+- $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
+-
+- # Populate FAPI for ocmb
+- $targetObj->setAttributeField($target, $fapi_name, "devAddr",
+- $address);
+- last;
+- }
+- }
+- }
+- }
+-
+- # Get data from i2c-master-omi, which connects to the i2c_mux PCA9847
+- my $conn = $self->findConnectionsByDirection($target, "I2C", "", 1);
+- if ($conn ne "")
+- {
+- # There exists multiple i2c bus connections with chip-ocmb
+- # They are all the same connections so we just take the first one
+- # The mux channel has the i2cMuxBusSelector
+- my $conn_source = @{$conn->{CONN}}[0]->{SOURCE};
+- my $mux = $self->getAttribute($conn_source, "MUX_CHANNEL");
+-
+- # Parent PCA9848 determines the mux path
+- my $parent = $self->getTargetParent($conn_source);
+- my $parent_pos = $self->getAttribute($parent, "POSITION");
+- my $i2c_mux_path = "physical:sys-0/node-0/i2c_mux-$parent_pos";
+-
+- # pmics and ocmb all grab FRU_ID from parent dimm
+- my $fru = $self->getAttribute($target_parent, "FRU_ID");
+-
+- my $master_i2c = $self->findConnectionsByDirection($self->getTargetParent($conn_source), "I2C", "", 1);
+- if ($master_i2c ne "")
+- {
+- # There exists multiple i2c bus connections with the PCA9847 i2c_mux
+- # They are all the same connections so we just take the first one
+- $master_i2c = @{$master_i2c->{CONN}}[0];
+- # i2c-master-omi source which has data we need
+- my $source = $master_i2c->{SOURCE};
+- my $dest = $master_i2c->{DEST};
+- my $engine = $self->getAttribute($source, "I2C_ENGINE");
+- my $port = $self->getAttribute($source, "I2C_PORT");
+-
+- # Populate FAPI for ocmb
+- $self->setAttributeField($target, $fapi_name, "engine",
+- $engine);
+- $self->setAttributeField($target, $fapi_name, "port",
+- $port);
+- $self->setAttributeField($target, $fapi_name, "i2cMuxBusSelector",
+- $mux);
+- $self->setAttributeField($target, $fapi_name, "i2cMuxPath",
+- $i2c_mux_path);
+- $self->setAttribute($target, "FRU_ID",
+- $fru);
+-
+- # Populate EEPROM for ocmb
+- $self->setAttributeField($target, $eeprom_name, "i2cMuxPath",
+- $i2c_mux_path);
+- $self->setAttributeField($target, $eeprom_name, "engine",
+- $engine);
+- $self->setAttributeField($target, $eeprom_name, "port",
+- $port);
+- $self->setAttributeField($target, $eeprom_name, "i2cMuxBusSelector",
+- $mux);
+-
+-
+- # Populate FAPI for pmics
+- foreach my $pmic (@pmic_array)
+- {
+- $self->setAttributeField($pmic, $fapi_name, "engine",
+- $engine);
+- $self->setAttributeField($pmic, $fapi_name, "port",
+- $port);
+- $self->setAttributeField($pmic, $fapi_name, "i2cMuxBusSelector",
+- $mux);
+- $self->setAttributeField($pmic, $fapi_name, "i2cMuxPath",
+- $i2c_mux_path);
+- $self->setAttribute($pmic, "FRU_ID",
+- $fru);
+- }
+-
+- # Populate EEPROM for dimm
+- $self->setAttributeField($target_parent, $eeprom_name, "engine",
+- $engine);
+- $self->setAttributeField($target_parent, $eeprom_name, "port",
+- $port);
+- $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxBusSelector",
+- $mux);
+- $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxPath",
+- $i2c_mux_path);
+- $self->setAttribute($target_parent, "FRU_ID",
+- $fru);
+- }
+- }
+-}
+-
+ # Find connections from/to $target (and it's children)
+ # $to_this_target indicates the direction to find.
+ sub findConnectionsByDirection
+@@ -2792,6 +2767,41 @@ sub getTargetType
+ return $target_ptr->{TARGET}->{type};
+ }
+
++
++#--------------------------------------------------
++# @brief Checks the given target for given attribute
++#
++# @details Will check the target for the given attribute.
++# If attribute does not exist for target then
++# return 0 (false), else if attribute does exist
++# for target then return 1 (true). This methods
++# does not check the validity of the attribute
++# or it's value.
++#
++# @param [in] $self - The global target object.
++# @param [in] $target - target to locate attribute on
++# @param [in] $attribut - attribute to locate
++#
++# @return true if attribute found, else false
++#--------------------------------------------------
++sub doesAttributeExistForTarget
++{
++ my $self = shift;
++ my $target = shift;
++ my $attribute = shift;
++
++ my $target_ptr = $self->getTarget($target);
++
++ # If can't locate attribute for target then return back 0 (false)
++ if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}))
++ {
++ return 0;
++ }
++
++ # Attribute for target was found, return back 1 (true)
++ return 1;
++}
++
+ ## checks if attribute is value
+ ## must be defined and have a non-empty value
+ sub isBadAttribute
+@@ -2818,6 +2828,7 @@ sub isBadAttribute
+ {
+ return 1;
+ }
++
+ return 0;
+ }
+
+@@ -2864,6 +2875,7 @@ sub getAttribute
+ my $target = shift;
+ my $attribute = shift;
+ my $target_ptr = $self->getTarget($target);
++
+ if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}->{default}))
+ {
+ printf("ERROR: getAttribute(%s,%s) | Attribute not defined\n",
+@@ -3296,6 +3308,207 @@ sub writeReportFile
+ close R;
+ }
+
++#--------------------------------------------------
++# @brief Populates the EEPROM attributes for DDIMS
++#
++# @param [in] $self - The global target object.
++# @param [in] $target - An OCMB target
++#--------------------------------------------------
++sub setEepromAttributesForDDIMs
++{
++ my $self = shift;
++ my $target = shift; # Expects ocmb target
++
++ my %connections;
++ my $num=0;
++
++ my $eeprom_name = "EEPROM_VPD_PRIMARY_INFO";
++ my $fapi_name = "FAPI_I2C_CONTROL_INFO";
++ # SPD contains data for EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO
++ # SPD is the child of ocmb's parent, so get ocmb's parent
++ # then look for the SPD child
++ # With the resulting info, we populate pmic0, pmic1, ocmb, and dimm
++ my $target_parent = $self->getTargetParent($target);
++
++ # Need to store pmic targets because they get parsed before we
++ # do calculations for engine, port, etc
++ # pmics need these values, so we store them until we need them later
++ my $address = 0;
++ my @pmic_array;
++ foreach my $child (@{ $self->getTargetChildren($target_parent) })
++ {
++ my $type = $self->getTargetType($child);
++ if ($type eq "chip-spd-device")
++ {
++ my $offset = $self->getAttribute($child, "BYTE_ADDRESS_OFFSET");
++ my $memory_size = $self->getAttribute($child, "MEMORY_SIZE_IN_KB");
++ my $cycle_time = $self->getAttribute($child, "WRITE_CYCLE_TIME");
++ my $page_size = $self->getAttribute($child, "WRITE_PAGE_SIZE");
++
++ # Populate EEPROM for ocmb
++ $self->setAttributeField($target, $eeprom_name, "byteAddrOffset",
++ $offset);
++ $self->setAttributeField($target, $eeprom_name, "maxMemorySizeKB",
++ $memory_size);
++ $self->setAttributeField($target, $eeprom_name, "writeCycleTime",
++ $cycle_time);
++ $self->setAttributeField($target, $eeprom_name, "writePageSize",
++ $page_size);
++
++ # Populate EEPROM for dimm
++ $self->setAttributeField($target_parent, $eeprom_name, "byteAddrOffset",
++ $offset);
++ $self->setAttributeField($target_parent, $eeprom_name, "maxMemorySizeKB",
++ $memory_size);
++ $self->setAttributeField($target_parent, $eeprom_name, "writeCycleTime",
++ $cycle_time);
++ $self->setAttributeField($target_parent, $eeprom_name, "writePageSize",
++ $page_size);
++
++ # spd only child is i2c-slave, which contains devAddr info
++ foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
++ {
++ $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
++ # Populate EEPROM for dimm
++ $self->setAttributeField($target_parent, $eeprom_name, "devAddr",
++ $address);
++
++ # Populate EEPROM for ocmb
++ $self->setAttributeField($target, $eeprom_name, "devAddr",
++ $address);
++ }
++ } # end if ($type eq "chip-spd-device") ...
++ elsif ($type eq "chip-vreg-generic")
++ {
++ push(@pmic_array, $child);
++ foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
++ {
++ $type = $self->getTargetType($i2c_slave);
++ # pmic has child i2c_slave which contains the device address
++ if ($type eq "unit-i2c-slave")
++ {
++ $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
++
++ # Populate FAPI for pmic
++ $self->setAttributeField($child, $fapi_name, "devAddr",
++ $address);
++ last;
++ }
++ }
++ } # end elsif ($type eq "chip-vreg-generic")
++ elsif ($type eq "chip-ocmb")
++ {
++ foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
++ {
++ # ocmb has multiple i2c-slaves, so we query with instance_name
++ my $instance_name = $self->getInstanceName($i2c_slave);
++ if ($instance_name eq "i2c-ocmb")
++ {
++ $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
++
++ # Populate FAPI for ocmb
++ $self->setAttributeField($target, $fapi_name, "devAddr",
++ $address);
++ last;
++ }
++ }
++ } # end elsif ($type eq "chip-ocmb")
++ } # end foreach my $child ...
++
++ # Get data from i2c-master-omi, which connects to the i2c_mux PCA9847
++ my $conn = $self->findConnectionsByDirection($target, "I2C", "", 1);
++ if ($conn ne "")
++ {
++ # There exists multiple i2c bus connections with chip-ocmb
++ # They are all the same connections so we just take the first one
++ # The mux channel has the i2cMuxBusSelector
++ my $conn_source = @{$conn->{CONN}}[0]->{SOURCE};
++# TODO FIX ROLAND
++# Will fix later in the process
++# ROLAND causing errors:
++# ERROR: getAttribute(/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0/i2c-master-op3b,MUX_CHANNEL) | Attribute not defined
++# I only found MUX_CHANNEL on attributes /sys-0/node-0/nisqually-0/PCA9849-[0-7]/PCA9849.i2cm-[0..3]
++#
++# my $mux = $self->getAttribute($conn_source, "MUX_CHANNEL");
++ my $mux = 0;
++
++ # Parent PCA9848 determines the mux path
++ my $parent = $self->getTargetParent($conn_source);
++ my $parent_pos = $self->getAttribute($parent, "POSITION");
++ my $i2c_mux_path = "physical:sys-0/node-0/i2c_mux-$parent_pos";
++
++ # pmics and ocmb all grab FRU_ID from parent dimm
++ my $fru = $self->getAttribute($target_parent, "FRU_ID");
++
++ my $master_i2c = $self->findConnectionsByDirection($self->getTargetParent($conn_source), "I2C", "", 1);
++ if ($master_i2c ne "")
++ {
++ # There exists multiple i2c bus connections with the PCA9847 i2c_mux
++ # They are all the same connections so we just take the first one
++ $master_i2c = @{$master_i2c->{CONN}}[0];
++ # i2c-master-omi source which has data we need
++ my $source = $master_i2c->{SOURCE};
++ my $dest = $master_i2c->{DEST};
++ my $engine = $self->getAttribute($source, "I2C_ENGINE");
++ my $port = $self->getAttribute($source, "I2C_PORT");
++
++ # Populate FAPI for ocmb
++ $self->setAttributeField($target, $fapi_name, "engine",
++ $engine);
++ $self->setAttributeField($target, $fapi_name, "port",
++ $port);
++ $self->setAttributeField($target, $fapi_name, "i2cMuxBusSelector",
++ $mux);
++ $self->setAttributeField($target, $fapi_name, "i2cMuxPath",
++ $i2c_mux_path);
++ $self->setAttribute($target, "FRU_ID",
++ $fru);
++
++ # Populate EEPROM for ocmb
++ $self->setAttributeField($target, $eeprom_name, "i2cMuxPath",
++ $i2c_mux_path);
++ $self->setAttributeField($target, $eeprom_name, "engine",
++ $engine);
++ $self->setAttributeField($target, $eeprom_name, "port",
++ $port);
++ $self->setAttributeField($target, $eeprom_name, "i2cMuxBusSelector",
++ $mux);
++
++ # Populate FAPI for pmics
++ foreach my $pmic (@pmic_array)
++ {
++ $self->setAttributeField($pmic, $fapi_name, "engine",
++ $engine);
++ $self->setAttributeField($pmic, $fapi_name, "port",
++ $port);
++ $self->setAttributeField($pmic, $fapi_name, "i2cMuxBusSelector",
++ $mux);
++ $self->setAttributeField($pmic, $fapi_name, "i2cMuxPath",
++ $i2c_mux_path);
++ $self->setAttribute($pmic, "FRU_ID",
++ $fru);
++ }
++
++ # Populate EEPROM for dimm
++ $self->setAttributeField($target_parent, $eeprom_name, "engine",
++ $engine);
++ $self->setAttributeField($target_parent, $eeprom_name, "port",
++ $port);
++ $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxBusSelector",
++ $mux);
++ $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxPath",
++ $i2c_mux_path);
++ $self->setAttribute($target_parent, "FRU_ID",
++ $fru);
++ } # end if ($master_i2c ne "")
++ } # end if ($conn ne "")
++}
++
++#--------------------------------------------------
++# @brief The end of the executable elements of this PERL module
++#
++# @details Don't forget to return the true value from this file
++#--------------------------------------------------
+ 1;
+
+ =head1 NAME
+diff --git a/src/usr/targeting/common/processMrw.pl b/src/usr/targeting/common/processMrw.pl
+index 7a63791..cd84b14 100755
+--- a/src/usr/targeting/common/processMrw.pl
++++ b/src/usr/targeting/common/processMrw.pl
+@@ -24,6 +24,9 @@
+ #
+ # IBM_PROLOG_END_TAG
+
++###############################################################################
++# Include these libraries
++###############################################################################
+ use strict;
+ use XML::Simple;
+ use Data::Dumper;
+@@ -32,112 +35,168 @@ use Math::BigInt;
+ use Getopt::Long;
+ use File::Basename;
+
+-use constant HZ_PER_KHZ=>1000;
+-use constant MAX_MCS_PER_PROC => 4; # 4 MCS per Nimbus
+
++###############################################################################
++# Define some global constants
++###############################################################################
+ my $VERSION = "1.0.0";
++my $targetObj = Targets->new;
+
+-my $force = 0;
+-my $serverwiz_file = "";
+-my $version = 0;
+-my $debug = 0;
+-my $report = 0;
+-my $sdr_file = "";
+-my $build = "hb";
+-my $system_config = "";
+-my $output_filename = "";
+-
+-# Map the OMI instance to its corresponding OMIC parent
+-my %omi_map = (4 => "omic-0",
+- 5 => "omic-0",
+- 6 => "omic-0",
+- 7 => "omic-1",
+- 2 => "omic-1",
+- 3 => "omic-1",
+- 0 => "omic-2",
+- 1 => "omic-2",
+- 12 => "omic-0",
+- 13 => "omic-0",
+- 14 => "omic-0",
+- 15 => "omic-1",
+- 10 => "omic-1",
+- 11 => "omic-1",
+- 8 => "omic-2",
+- 9 => "omic-2");
++# Define a true an false keyword
++use constant { true => 1, false => 0 };
++
++use constant HZ_PER_KHZ=>1000;
++use constant MAX_MCS_PER_PROC => 4; # 4 MCS per Nimbus
+
+ # TODO RTC:170860 - Remove this after dimm connector defines VDDR_ID
+-my $num_voltage_rails_per_proc = 1;
+-
+-GetOptions(
+- "build=s" => \$build,
+- "f" => \$force, # numeric
+- "x=s" => \$serverwiz_file, # string
+- "d" => \$debug,
+- "c=s" => \$system_config, #string
+- "o=s" => \$output_filename, #string
+- "v" => \$version,
+- "r" => \$report,
+- ) # flag
+- or printUsage();
+-
+-if ($version == 1)
+-{
+- die "\nprocessMrw.pl\tversion $VERSION\n";
+-}
++my $NUM_VOLTAGE_RAILS_PER_PROC = 1;
+
+-if ($serverwiz_file eq "")
+-{
+- printUsage();
+-}
++## Used to setup GPU sensors on processors
++# key: OBUS slot target,
++# value: (GPU#, Function, Temp, MemTemp IPMI name/ids,
++my %GPU_SENSORS;
+
+-$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
++# key: OBUS slot string
++# value: processor target string
++my %SLOT_TO_PROC;
+
+-my $targetObj = Targets->new;
+-if ($force == 1)
++our %hwsvmrw_plugins;
++
++###############################################################################
++# The starting point for this script
++###############################################################################
++main($targetObj);
++
++sub main
+ {
+- $targetObj->{force} = 1;
++ my $targetObj = shift;
++
++ # Extract the caller's options off the command and validate.
++ # Will exit if options are not valid.
++ getAndValidateCallerInputOptions();
++
++
++ # Run tests if asked to do so
++ if ($targetObj->{run_self_test} == 1)
++ {
++ runTests($targetObj);
++ return 0;
++ }
++
++ # Load the XML and process the file, extracting targets and associating
++ # attributes, with their data, to the targets
++ loadXmlFile();
++
++ if ($targetObj->{build} eq "fsp")
++ {
++ doFspBuild();
++ }
++
++ # Process the targets - set some needed attribute values
++ processTargets();
++
++ # Check for errors in the targets
++ errorCheckTheTargets($targetObj);
++
++ # Write the results of processing the targets to an XML file
++ writeResultsToXml($targetObj);
+ }
+-if ($debug == 1)
++
++###############################################################################
++# Supporting subroutines
++###############################################################################
++#--------------------------------------------------
++# @brief Extract caller's command line options
++#
++# @details Extract caller's command line options and
++# validate them. If valid then store in the
++# global Target object for easy retrieval.
++# If options are not valid, then print
++# usage statement and exit script.
++#--------------------------------------------------
++sub getAndValidateCallerInputOptions
+ {
+- $targetObj->{debug} = 1;
+-}
++ # Local variables, and their defaults, to cache the command line options to
++ my $build = "hb";
++ my $force = 0;
++ my $serverwiz_file = "";
++ my $debug = 0;
++ my $system_config = "";
++ my $output_file = "";
++ my $version = 0;
++ my $report = 0;
++ my $run_self_test = 0;
++
++ # Grab the user's command line options. If options not recognized
++ # print usage statement and exit script.
++ GetOptions(
++ "build=s" => \$build, # string
++ "f" => \$force, # numeric
++ "x=s" => \$serverwiz_file, # string
++ "d" => \$debug, # flag
++ "c=s" => \$system_config, # string
++ "o=s" => \$output_file, # string
++ "v" => \$version, # flag
++ "r" => \$report, # flag
++ "t" => \$run_self_test, # flag
++ )
++ or printUsage();
++
++ # Display current version of file
++ if ($version == 1)
++ {
++ die "\nprocessMrw.pl\tversion $VERSION\n";
++ }
++
++ # If caller did not specify an input file, then print usage and die
++ if ($serverwiz_file eq "")
++ {
++ printUsage();
++ }
++
++ # Save the caller's input options to global storage for easy retrieval
++ $targetObj->{build} = $build;
++ $targetObj->{force} = $force;
++ $targetObj->{serverwiz_file} = $serverwiz_file;
++ $targetObj->{serverwiz_dir} = dirname($serverwiz_file);
++ $targetObj->{debug} = $debug;
++ $targetObj->{system_config} = $system_config;
++ $targetObj->{output_file} = $output_file;
++ $targetObj->setVersion($VERSION);
++ $targetObj->{report} = $report;
++ $targetObj->{run_self_test} = $run_self_test;
++
++} # end getAndValidateCallerInputOptions
++
++# loadXmlFile
++sub loadXmlFile
++{
++ $XML::Simple::PREFERRED_PARSER = 'XML::Parser';
++ $targetObj->loadXML($targetObj->{serverwiz_file});
+
+-$targetObj->setVersion($VERSION);
+-my $xmldir = dirname($serverwiz_file);
+-$targetObj->loadXML($serverwiz_file);
++ my $str=sprintf(
++ " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
++ "Sensor Name","FRU Name","Ent ID","Type","Evt Type","ID","Inst","FRU",
++ "HUID","Target");
++
++ $targetObj->writeReport($str);
++ my $str=sprintf(
++ " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
++ "------------------------------","----------",
++ "------","----","---------","----","----","----","----------",
++ "----------");
++
++ $targetObj->writeReport($str);
++} # end loadXmlFile
+
+-our %hwsvmrw_plugins;
+ # FSP-specific functions
+-if ($build eq "fsp")
++sub doFspBuild
+ {
+ eval ("use processMrw_fsp; return 1;");
+ processMrw_fsp::return_plugins();
+-}
+-
+-my $str=sprintf(
+- " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
+- "Sensor Name","FRU Name","Ent ID","Type","Evt Type","ID","Inst","FRU",
+- "HUID","Target");
++} # end doFspBuild
+
+-$targetObj->writeReport($str);
+-my $str=sprintf(
+- " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
+- "------------------------------","----------",
+- "------","----","---------","----","----","----","----------",
+- "----------");
+-
+-$targetObj->writeReport($str);
+-
+-########################
+-## Used to setup GPU sensors on processors
+-my %G_gpu_sensors;
+-# key: obusslot target,
+-# value: (GPU#, Function, Temp, MemTemp IPMI name/ids,
+
+-my %G_slot_to_proc;
+-# key: obusslot string
+-# value: processor target string
+-#########################
+
+ # convert a number string into a bit-position number
+ # example: "0x02" --> 0b0100 = 4
+@@ -151,7 +210,7 @@ sub numToBitPositionNum
+ return $newNum;
+ }
+
+-# Used to populate G_gpu_sensors hash of array references
++# Used to populate GPU_SENSORS hash of array references
+ #
+ # Each array reference will be composed of 3 sensors +
+ # board cfg ID which together makes up a GPU.
+@@ -167,7 +226,7 @@ sub addSensorToGpuSensors
+ my $GPU_SENSORS_TEMP_OFFSET = 2;
+ my $GPU_SENSORS_MEM_TEMP_OFFSET = 4;
+
+- my $rSensorArray = $G_gpu_sensors{$obusslot_str};
++ my $rSensorArray = $GPU_SENSORS{$obusslot_str};
+ unless ($rSensorArray) {
+ $rSensorArray = [ "0xFFFF","0xFF","0xFFFF","0xFF",
+ "0xFFFF","0xFF","0x00" ];
+@@ -192,11 +251,11 @@ sub addSensorToGpuSensors
+ $rSensorArray->[$GPU_SENSORS_TEMP_OFFSET+1] = $sensorID;
+ }
+
+- $G_gpu_sensors{$obusslot_str} = $rSensorArray;
++ $GPU_SENSORS{$obusslot_str} = $rSensorArray;
+ }
+
+
+-# Populates the G_slot_to_proc hash and updates the cfgID in G_gpu_sensors
++# Populates the SLOT_TO_PROC hash and updates the cfgID in GPU_SENSORS
+ # This is how we map the obusslot to the GPU sensors
+ sub addObusCfgToGpuSensors
+ {
+@@ -205,14 +264,14 @@ sub addObusCfgToGpuSensors
+
+ my $foundSlot = 0;
+
+- $G_slot_to_proc{$obusslot_str} = $proc_target;
++ $SLOT_TO_PROC{$obusslot_str} = $proc_target;
+
+- foreach my $obusslot (keys %G_gpu_sensors)
++ foreach my $obusslot (keys %GPU_SENSORS)
+ {
+ if ($obusslot =~ m/$obusslot_str/)
+ {
+ # Add in the cfg number
+- my $rSensorArray = $G_gpu_sensors{$obusslot_str};
++ my $rSensorArray = $GPU_SENSORS{$obusslot_str};
+ $rSensorArray->[$GPU_SENSORS_OBUS_CFG_OFFSET] =
+ sprintf("0x%02X",
+ (oct($rSensorArray->[$GPU_SENSORS_OBUS_CFG_OFFSET]) |
+@@ -225,10 +284,10 @@ sub addObusCfgToGpuSensors
+ {
+ print STDOUT sprintf("%s:%d ", __FILE__,__LINE__);
+ print STDOUT "Found obus slot ($obusslot_str - processor $proc_target)".
+- " not in G_gpu_sensors hash\n";
++ " not in GPU_SENSORS hash\n";
+
+ my $cfg_bit_num = numToBitPositionNum($cfg);
+- $G_gpu_sensors{$obusslot_str} =
++ $GPU_SENSORS{$obusslot_str} =
+ ["0xFFFF","0xFF","0xFFFF","0xFF","0xFFFF",
+ "0xFF", sprintf("0x02X",oct($cfg_bit_num))];
+ }
+@@ -273,17 +332,207 @@ sub isMultiTpmSystem
+ }
+
+ #--------------------------------------------------
+-## loop through all targets and do stuff
+-my @targets = sort keys %{ $targetObj->getAllTargets() };
+-my $isMultiTpmSys = isMultiTpmSystem(\@targets);
+-foreach my $target (@targets)
++# @brief Loop through all targets and set attributes as needed
++#
++# @param [in] $targetObj - The global target object.
++#--------------------------------------------------
++sub processTargets
++{
++ my @targets = sort keys %{ $targetObj->getAllTargets() };
++ my $isMultiTpmSys = isMultiTpmSystem(\@targets);
++ foreach my $target (@targets)
++{
++ my $type = $targetObj->getType($target);
++ if ($type eq "SYS")
++ {
++ processSystem($targetObj, $target);
++
++ my $maxComputeNodes = get_max_compute_nodes($targetObj , $target);
++ $targetObj->setAttribute($target, "MAX_COMPUTE_NODES_PER_SYSTEM", $maxComputeNodes);
++
++ #handle enumeration changes
++ my $enum_val = $targetObj->getAttribute($target,"PROC_FABRIC_PUMP_MODE");
++ if ( $enum_val =~ /MODE1/i)
++ {
++ $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_NODE");
++ }
++ elsif ( $enum_val =~ /MODE2/i)
++ {
++ $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_GROUP");
++ }
++ }
++ elsif ($type eq "PROC")
++ {
++ processProcessor($targetObj, $target);
++ if ($targetObj->{build} eq "fsp")
++ {
++ do_plugin("fsp_proc", $targetObj, $target);
++ }
++ }
++ elsif ($type eq "APSS")
++ {
++ processApss($targetObj, $target);
++ }
++
++ # @TODO RTC: 189374 Remove multiple TPMs filter when all platforms' MRW
++ # supports dynamically determining the processor driving it.
++ elsif (($type eq "TPM") && $isMultiTpmSys)
++ {
++ processTpm($targetObj, $target);
++ }
++ elsif ($type eq "POWER_SEQUENCER")
++ {
++ my $target_type = $targetObj->getTargetType($target);
++
++ # Strip off the chip- part of the target type name
++ $target_type =~ s/chip\-//g;
++
++ # Currently only UCD9090 and UCD90120A on FSP systems are supported.
++ # All other UCD types are skipped.
++ if (($target_type eq "UCD9090")
++ || ($target_type eq "UCD90120A"))
++ {
++ processUcd($targetObj, $target);
++ }
++ }
++ elsif ($type eq "OCMB_CHIP")
++ {
++ processOcmbChip($targetObj, $target);
++ }
++
++ # Once processing of the target type is complete, remove
++ # deprecated and un-needed attributes for this type
++ pruneTargetAttributes($targetObj, $target, $type);
++
++ processIpmiSensors($targetObj,$target);
++ } # end foreach my $target (@targets)
++
++
++ if ($targetObj->{build} eq "fsp")
++ {
++ processMrw_fsp::loadFSP($targetObj);
++ }
++} # end processTargets
++
++#--------------------------------------------------
++# @brief Check the processed targets for errors
++#
++# @param [in] $targetObj - The global target object.
++#--------------------------------------------------
++sub errorCheckTheTargets
+ {
+- my $type = $targetObj->getType($target);
++ my $targetObj = shift;
++
++# TODO FIX ROLAND
++# Will fix later in the process
++# check topology
++# ROLAND Having issues with the topology:
++# ERROR: Fabric topology invalid. 2 targets have same FABRIC_TOPOLOGY_ID (0x0)
++# Once resolved, add this check back in
++# The MRW XML has 2 procs: power10-0 of type chip-processor-power10 and
++# power10-1 of type chip-processor-power10 and
++# In the loadXmlFile method, it produces 4 procs, 2 on a socket:
++# '/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0';
++# '/sys-0/node-0/nisqually-0/proc_socket-1/godel-0/power10-0';
++# '/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-1';
++# '/sys-0/node-0/nisqually-0/proc_socket-1/godel-0/power10-1';
++# For both power10-0 procs it uses topologoy ID 0
++# For both power10-1 procs it uses topologoy ID 1
++# So this end up in duplicates being used
++
++# foreach my $n (keys %{$targetObj->{TOPOLOGY}})
++# {
++# if ($targetObj->{TOPOLOGY}->{$n} > 1)
++# {
++# print "ERROR: Fabric topology invalid. 2 targets have same ".
++# "FABRIC_TOPOLOGY_ID ($n)\n";
++# $targetObj->myExit(3);
++# }
++# }
++
++ foreach my $target (keys %{ $targetObj->getAllTargets() })
++ {
++ # TODO FIX ROLAND
++ # Will fix later in the process
++ # ROLAND Having issues with power10-0 so wrapped errorCheck with if statement:
++ # ERROR: EEPROM_VPD_PRIMARY_INFO/devAddr attribute is invalid (Target=/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0)
++ # I2C connection to target is not defined
++ ## Once resolved, will remove if statement
++ if ($target != "/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0")
++ {
++ errorCheck($targetObj, $target);
++ }
++ }
++} # end sub errorCheckTheTargets
++
++#--------------------------------------------------
++# @brief Write out the results to an XML file
++#
++# @param [in] $targetObj - The global target object.
++#--------------------------------------------------
++sub writeResultsToXml
++{
++ my $targetObj = shift;
++
++ my $xml_fh;
++ my $filename;
++ my $config_str = $targetObj->{system_config};
++
++ #If user did not specify the output filename, then build one up by using
++ #config and build parameters
++ if ($targetObj->{output_file} eq "")
++ {
++ if ($config_str ne "")
++ {
++ $config_str = "_" . $config_str;
++ }
++
++ $filename = $targetObj->{serverwiz_dir} . "/" . $targetObj->getSystemName() . $config_str . "_" . $targetObj->{build} . ".mrw.xml";
++ }
++ else
++ {
++ $filename = $targetObj->{output_file};
++ }
++
++ print "Creating XML: $filename\n";
++ open($xml_fh, ">$filename") || die "Unable to create: $filename";
++
++ $targetObj->printXML($xml_fh, "top", $targetObj->{build});
++ close $xml_fh;
++ if (!$targetObj->{errorsExist})
++ {
++ ## optionally print out report
++ if ($targetObj->{report})
++ {
++ print "Writing report to: ".$targetObj->{report_filename}."\n";
++ $targetObj->writeReportFile();
++ }
++ print "MRW created successfully!\n";
++ }
++} # end sub writeResultsToXml
++
++#--------------------------------------------------
++# @brief Remove attributes associated with target.
++# Either because they have been deprecated
++# or simply not used/needed.
++# @param[in] $targetObj - The global target object
++# blob
++# @param[in] $target - The target to remove attributes
++# from
++# @param[in] $type - The type of the target
++#
++# TODO RTC: 178351 Remove depricated Attribute from HB XML
++# these are obsolete
++#
++#--------------------------------------------------
++sub pruneTargetAttributes
++{
++ my $targetObj = shift;
++ my $target = shift;
++ my $type = shift;
++
+ if ($type eq "SYS")
+ {
+- processSystem($targetObj, $target);
+- #TODO RTC: 178351 Remove depricated Attribute from HB XML
+- #these are obsolete
+ $targetObj->deleteAttribute($target,"FUSED_CORE_MODE");
+ $targetObj->deleteAttribute($target,"MRW_CDIMM_MASTER_I2C_TEMP_SENSOR_ENABLE");
+ $targetObj->deleteAttribute($target,"MRW_CDIMM_SPARE_I2C_TEMP_SENSOR_ENABLE");
+@@ -302,31 +551,9 @@ foreach my $target (@targets)
+ $targetObj->deleteAttribute($target,"SYSTEM_WOF_ENABLED");
+ $targetObj->deleteAttribute($target,"VDM_ENABLE");
+ $targetObj->deleteAttribute($target,"CHIP_HAS_SBE");
+-
+- my $maxComputeNodes = get_max_compute_nodes($targetObj , $target);
+- $targetObj->setAttribute($target, "MAX_COMPUTE_NODES_PER_SYSTEM", $maxComputeNodes);
+-
+- #handle enumeration changes
+- my $enum_val = $targetObj->getAttribute($target,"PROC_FABRIC_PUMP_MODE");
+- if ( $enum_val =~ /MODE1/i)
+- {
+- $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_NODE");
+- }
+- elsif ( $enum_val =~ /MODE2/i)
+- {
+- $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_GROUP");
+- }
+-
+ }
+ elsif ($type eq "PROC")
+ {
+- processProcessor($targetObj, $target);
+- if ($build eq "fsp")
+- {
+- do_plugin("fsp_proc", $targetObj, $target);
+- }
+- #TODO RTC: 178351 Remove depricated Attribute from HB XML
+- #these are obsolete
+ $targetObj->deleteAttribute($target,"CHIP_HAS_SBE");
+ $targetObj->deleteAttribute($target,"FSI_GP_REG_SCOM_ACCESS");
+ $targetObj->deleteAttribute($target,"I2C_SLAVE_ADDRESS");
+@@ -349,18 +576,8 @@ foreach my $target (@targets)
+ $targetObj->deleteAttribute($target,"PROC_SECURITY_SETUP_VECTOR");
+ $targetObj->deleteAttribute($target,"SBE_SEEPROM_I2C_ADDRESS_BYTES");
+ }
+- elsif ($type eq "APSS")
+- {
+- processApss($targetObj, $target);
+- }
+- elsif ($type eq "MEMBUF")
+- {
+- processMembuf($targetObj, $target);
+- $targetObj->deleteAttribute($target,"CEN_MSS_VREF_CAL_CNTL");
+- }
+ elsif ($type eq "PHB")
+ {
+- #TODO RTC: 178351 Remove depricated Attribute from HB XML
+ $targetObj->deleteAttribute($target,"DEVICE_ID");
+ $targetObj->deleteAttribute($target,"HDDW_ORDER");
+ $targetObj->deleteAttribute($target,"MAX_POWER");
+@@ -376,91 +593,7 @@ foreach my $target (@targets)
+ $targetObj->deleteAttribute($target,"SLOT_NAME");
+ $targetObj->deleteAttribute($target,"VENDOR_ID");
+ }
+- # @TODO RTC: 189374 Remove multiple TPMs filter when all platforms' MRW
+- # supports dynamically determining the processor driving it.
+- elsif (($type eq "TPM") && $isMultiTpmSys)
+- {
+- processTpm($targetObj, $target);
+- }
+- elsif ($type eq "POWER_SEQUENCER")
+- {
+- my $target_type = $targetObj->getTargetType($target);
+-
+- # Strip off the chip- part of the target type name
+- $target_type =~ s/chip\-//g;
+-
+- # Currently only UCD9090 and UCD90120A on FSP systems are supported.
+- # All other UCD types are skipped.
+- if (($target_type eq "UCD9090")
+- || ($target_type eq "UCD90120A"))
+- {
+- processUcd($targetObj, $target);
+- }
+- }
+- elsif ($type eq "OCMB_CHIP")
+- {
+- processOcmbChip($targetObj, $target);
+- }
+-
+- processIpmiSensors($targetObj,$target);
+-}
+-
+-if ($build eq "fsp")
+-{
+- processMrw_fsp::loadFSP($targetObj);
+-}
+-## check topology
+-foreach my $n (keys %{$targetObj->{TOPOLOGY}}) {
+- if ($targetObj->{TOPOLOGY}->{$n} > 1) {
+- print "ERROR: Fabric topology invalid. 2 targets have same ".
+- "FABRIC_TOPOLOGY_ID ($n)\n";
+- $targetObj->myExit(3);
+- }
+-}
+-## check for errors
+-foreach my $target (keys %{ $targetObj->getAllTargets() })
+-{
+- errorCheck($targetObj, $target);
+-}
+-
+-#--------------------------------------------------
+-## write out final XML
+-my $xml_fh;
+-my $filename;
+-my $config_str = $system_config;
+-
+-#If user did not specify the output filename, then build one up by using
+-#config and build parameters
+-if ($output_filename eq "")
+-{
+- if ($config_str ne "")
+- {
+- $config_str = "_" . $config_str;
+- }
+-
+- $filename = $xmldir . "/" . $targetObj->getSystemName() . $config_str . "_" . $build . ".mrw.xml";
+-}
+-else
+-{
+- $filename = $output_filename;
+-}
+-
+-print "Creating XML: $filename\n";
+-open($xml_fh, ">$filename") || die "Unable to create: $filename";
+-
+-$targetObj->printXML($xml_fh, "top", $build);
+-close $xml_fh;
+-if (!$targetObj->{errorsExist})
+-{
+- ## optionally print out report
+- if ($report)
+- {
+- print "Writing report to: ".$targetObj->{report_filename}."\n";
+- $targetObj->writeReportFile();
+- }
+- print "MRW created successfully!\n";
+-}
+-
++} # end pruneTargetAttributes
+
+ #--------------------------------------------------
+ #--------------------------------------------------
+@@ -493,7 +626,7 @@ sub processSystem
+ my $system_name = $targetObj->getAttribute($target,"SYSTEM_NAME");
+ if ($system_name =~ /ZAIUS/i)
+ {
+- $num_voltage_rails_per_proc = 2;
++ $NUM_VOLTAGE_RAILS_PER_PROC = 2;
+ }
+
+ # TODO RTC:182764 -- right now there is no support for CDIMMs. So,
+@@ -940,9 +1073,9 @@ sub processUcd
+ }
+
+ #--------------------------------------------------
+-## Processor
+-##
+-
++# @brief Process processors
++#
++#--------------------------------------------------
+ sub processProcessor
+ {
+ my $targetObj = shift;
+@@ -998,7 +1131,6 @@ sub processProcessor
+ }
+ }
+
+-
+ # I2C arrays
+ my @engine = ();
+ my @port = ();
+@@ -1051,11 +1183,11 @@ sub processProcessor
+ # contain this information and this can be removed
+ my $socket_pos = $targetObj->getAttribute($socket_target,
+ "POSITION");
+- if ($num_voltage_rails_per_proc > 1)
++ if ($NUM_VOLTAGE_RAILS_PER_PROC > 1)
+ {
+ my $mcbist_pos = $targetObj->getAttribute($child, "CHIP_UNIT");
+ $targetObj->setAttribute($child, "VDDR_ID",
+- $socket_pos*$num_voltage_rails_per_proc + $mcbist_pos);
++ $socket_pos*$NUM_VOLTAGE_RAILS_PER_PROC + $mcbist_pos);
+ }
+ else
+ {
+@@ -1097,16 +1229,16 @@ sub processProcessor
+
+ # Add GPU sensors to processor
+ my @aGpuSensors = ();
+- foreach my $obusslot (sort keys %G_gpu_sensors)
++ foreach my $obusslot (sort keys %GPU_SENSORS)
+ {
+ # find matching obusslot to processor
+- my $proc_target = $G_slot_to_proc{$obusslot};
++ my $proc_target = $SLOT_TO_PROC{$obusslot};
+
+ # if a processor target is found and it is the same as this target
+ if ($proc_target && ($target =~ m/$proc_target/))
+ {
+ # Add this GPU's sensors to the processor's array of GPU sensors
+- push (@aGpuSensors, @{ $G_gpu_sensors{$obusslot} });
++ push (@aGpuSensors, @{ $GPU_SENSORS{$obusslot} });
+ }
+ }
+ if (@aGpuSensors)
+@@ -1216,10 +1348,11 @@ sub processProcessor
+ $targetObj->getAttribute($target,
+ "FABRIC_CHIP_ID"));
+
+- processMembufVpdAssociation($targetObj,$target);
++
+ #TODO RTC: 191762 -- Need a generic way to source FABRIC_GROUP_ID and
+ #FABRIC_CHIP_ID from the MRW and select the right value in processMRW
+ #based on the system configuration we are compiling for.
++ my $system_config = $targetObj->{system_config};
+ if ($system_config eq "w")
+ {
+ my $huid_str = $targetObj->getAttribute($target, "HUID");
+@@ -1412,36 +1545,21 @@ sub processI2cSpeeds
+ $targetObj->setAttribute($target,"I2C_BUS_SPEED_ARRAY",$bus_speed_attr);
+ }
+
+-################################
+-## Setup address map
+-
++#--------------------------------------------------
++# @brief Setup address map
++#--------------------------------------------------
+ sub setupBars
+ {
+ my $targetObj = shift;
+ my $target = shift;
+- #--------------------------------------------------
+- ## Setup BARs
+-
+- #The topology ID is a 4 bit value that must be converted to
+- #a 5-bit topology index before we can use it to calculate the
+- #address offset.
+- #The conversion method depends on the topology mode.
+- my $topoId = $targetObj->getAttribute($target, "PROC_FABRIC_TOPOLOGY_ID");
+- my $topoMode = $targetObj->getAttribute($target, "PROC_FABRIC_TOPOLOGY_MODE");
+-
+- #Assume topo mode 1 (GGCC -> 0GGCC)
+- my $topoIndex = $topoId;
+-
+- #Check for topo mode 0
+- if ($topoMode == 0)
+- {
+- # GGGC -> GGG0C
+- $topoIndex = (($topoIndex & 0xE) << 1) | ($topoIndex & 0x1);
+- }
+
+- #keep track of which topology ID's have been used
++ # Keep track of which topology ID's have been used
++ my $topoId = getTopologyId($targetObj, $target);
+ $targetObj->{TOPOLOGY}->{$topoId}++;
+
++ # Get the topology index
++ my $topologyIndex = getTopologyIndex($targetObj, $target);
++
+ #P10 has a defined memory map for all configurations,
+ #these are the base addresses for topology ID 0 (group0-chip0).
+ my %bars=( "FSP_BASE_ADDR" => 0x0006030100000000,
+@@ -1466,9 +1584,147 @@ sub setupBars
+ {
+ my $i_base = Math::BigInt->new($bars{$bar});
+ my $value=sprintf("0x%016s",substr((
+- $i_base+$topoIndexOffset*$topoIndex)->as_hex(),2));
++ $i_base+$topoIndexOffset*$topologyIndex)->as_hex(),2));
+ $targetObj->setAttribute($target,$bar,$value);
+ }
++} # end setupBars
++
++#--------------------------------------------------
++# @brief Retrieve the fabric topolgy mode
++#
++# @details The fabric topology mode, attribute PROC_FABRIC_TOPOLOGY_MODE,
++# is an attribute of the top level target (sys-0), but retrieving
++# the value from the attribute returns a string (MODE0 or MODE1).
++# This string is used to get the actual value, tied that mode,
++# within the enumeration types.
++#
++# @param[in] $targetObj - The global target object, needed to get topology mode
++#
++# @return the numerical value of the topology mode in base 10
++#--------------------------------------------------
++sub getTopologyMode
++{
++ my $targetObj = shift;
++
++ use constant TOPOLOGY_MODE_ATTRIBUTE => "PROC_FABRIC_TOPOLOGY_MODE";
++
++ # Get topology mode from top level target
++ # Need to prepend "/" to the returned top level target because targets
++ # are mapped slightly different in the TARGETS hash vs the xml hash.
++ my $topologoyMode = $targetObj->getAttribute("/".$targetObj->{TOP_LEVEL},
++ TOPOLOGY_MODE_ATTRIBUTE);
++
++ # Return the value of the mode as defined in
++ # enumeration type PROC_FABRIC_TOPOLOGY_MODE
++ # Convert the value from hex to base 10
++ return hex($targetObj->{xml}->{enumerationTypes}->{enumerationType}
++ ->{PROC_FABRIC_TOPOLOGY_MODE}
++ ->{enumerator}->{$topologoyMode}->{value});
++}
++
++#--------------------------------------------------
++# @brief Convert the topology ID to a topology index.
++#
++# @details The topology ID is a 4 bit value that will be converted to a 5 bit
++# topology index. The topology index is an index into the topology
++# table.
++# The conversion method depends on the topology mode.
++# Mode ID index
++# MODE 0 => GGGC --> GGG0C
++# MODE 1 => GGCC --> GG0CC
++#
++# @param[in] $topologyId - The topology ID to convert to an index
++# @param[in] $topologyMode - The topology mode that determines the conversion
++# method. Needs to be a base 10 numeral value.
++#
++# @return a toplogy index, that is a base 10 numeral value.
++#--------------------------------------------------
++sub convertTopologyIdToIndex
++{
++ my $topologyId = shift;
++ my $topologyMode = shift;
++
++ use constant TOPOLOGY_MODE_1 => 1;
++
++ # Assume topology mode 0 (GGGC -> GGG0C)
++ my $groupMask = 0xE; # Use 0xE, 1110b, to extract 'GGG' from 'GGGC'
++ my $chipMask = 0x1; # Use 0x1, 0001b, to extract 'C' from 'GGGC'
++
++ # If topology mode 1 (GGCC -> GG0CC)
++ if (TOPOLOGY_MODE_1 == $topologyMode)
++ {
++ $groupMask = 0xC; # Use 0xC, 1100b, to extract 'GG' from 'GGCC'
++ $chipMask = 0x3; # Use 0x3, 0011b, to extract 'CC' from 'GGCC'
++ }
++
++ # Set topology index to topology ID before doing conversion
++ my $topologyIndex = $topologyId;
++
++ ## Turn the 4 bit topology ID into a 5 bit index
++ ## convert GGGC to GGG0C
++ ## OR GGCC to GG0CC
++ # If group mask equal to 0xE (mode 0) then extract 'GGG' from 'GGGC':
++ # 1) GGGC & 0xE (1110b) returns GGG0 then shift to left (<< 1) to get GGG00
++ # 2) extract C from GGGC: GGGC & 0x1 (0001b) returns C
++ # If group mask equal to 0xC (mode 1) then extract 'GG' from 'GGCC':
++ # 1) GGCC & 0xC (1100b) returns GG00 then shift to left (<< 1) to get GG000
++ # 2) extract CC from GGCC: GGCC & 0x3 (0011b) returns CC
++ # Bitwise 'OR' 1 and 2 together to produce a 5 bit index value: GGG0C OR GG0CC
++ # Index = 1 'OR' 2
++ $topologyIndex = (($topologyIndex & $groupMask) << 1) | ($topologyIndex & $chipMask);
++
++ return ($topologyIndex);
++}
++
++#--------------------------------------------------
++# @brief Get the topology ID from processor
++#
++#
++# @param[in] $targetObj - The global target object, needed to get topology mode
++# @param[in] $processorTarget - The processor target, has the attribute topology ID
++#
++# @return topology ID, that is a base 10 numeral value.
++#--------------------------------------------------
++sub getTopologyId
++{
++ my $targetObj = shift;
++ my $processorTarget = shift;
++
++ use constant TOPOLOGY_ID_ATTRIBUTE => "PROC_FABRIC_TOPOLOGY_ID";
++
++ # Get the topology ID from the processor.
++ # Convert hex value to base 10 numerical value
++ return hex($targetObj->getAttribute($processorTarget,
++ TOPOLOGY_ID_ATTRIBUTE));
++
++}
++
++#--------------------------------------------------
++# @brief Get the topology index, an index into the topology table.
++#
++# @details The topology index needs to be calculated using the topology mode
++# and the topology ID. @see convertTopologyIdToIndex for
++# more details
++#
++# @param[in] $targetObj - The global target object, needed to get topology mode
++# @param[in] $processorTarget - The processor target has the attribute topology ID
++#
++# @return a topology index, that is base 10 numeral value.
++#--------------------------------------------------
++sub getTopologyIndex
++{
++ my $targetObj = shift;
++ my $processorTarget = shift;
++
++ # Get the topology mode: MODE 0 (0) or MODE 1 (1)
++ my $topologyMode = getTopologyMode($targetObj);
++
++ # Get the topology ID from the processor.
++ my $topologyId = getTopologyId($targetObj, $processorTarget);
++
++ # Convert the topology ID to a topology index. The conversion method is
++ # based on the topology mode.
++ return (convertTopologyIdToIndex($topologyId, $topologyMode));
+ }
+
+ #--------------------------------------------------
+@@ -1572,10 +1828,14 @@ sub processEq
+ $targetObj->log($target,
+ "Processing EQ child: $child Type: $child_type");
+
+- if ($child_type eq "EX")
++ if ($child_type eq "EQ")
+ {
+ processEx($targetObj, $child, $chip_unit);
+ }
++ elsif ($child_type eq "FC")
++ {
++ processFc($targetObj, $child, $chip_unit);
++ }
+ }
+
+ my $value = sprintf("0x%x",
+@@ -1584,6 +1844,35 @@ sub processEq
+ $targetObj->setAttribute( $target, "CHIPLET_ID", $value);
+ }
+
++## FC
++sub processFc
++{
++ my $targetObj = shift;
++ my $target = shift;
++ my $parent_chip_unit = shift;
++
++ foreach my $child (@{ $targetObj->getTargetChildren($target) })
++ {
++ my $child_type = $targetObj->getType($child);
++
++ $targetObj->log($target,
++ "Processing EX child: $child Type: $child_type");
++
++ if ($child_type eq "CORE")
++ {
++ processCore($targetObj, $child);
++ }
++ }
++
++ my $value = sprintf("0x%x",
++ Targets::PERVASIVE_PARENT_EQ_OFFSET
++ + $parent_chip_unit);
++
++ $targetObj->setAttribute( $target, "CHIPLET_ID", $value);
++}
++
++
++
+ ## EX
+ sub processEx
+ {
+@@ -1672,9 +1961,9 @@ sub processMcbist
+ ##
+ sub processMc
+ {
+- # NOTE: OMI_INBAND_BAR_BASE_ADDR_OFFSET will be set for the MC
+- # targets via a specific child OMI Target. View the
+- # processOmi function for further details.
++ # NOTE: OMI_INBAND_BAR_BASE_ADDR_OFFSET will be set for the MC
++ # targets via a specific child OMI Target. View the
++ # processOmi function for further details.
+ my $targetObj = shift;
+ my $target = shift;
+
+@@ -1751,8 +2040,28 @@ sub processMcc
+ ##
+ sub processOmi
+ {
+- my $mrwObj = shift;
+- my $omitarg = shift;
++ my $mrwObj = shift;
++ my $omitarg = shift;
++
++# TODO This may need to be updated if layout is different
++# ROLAND investigate this
++ # Map the OMI instance to its corresponding OMIC parent
++ my %omi_map = (4 => "omic-0",
++ 5 => "omic-0",
++ 6 => "omic-0",
++ 7 => "omic-1",
++ 2 => "omic-1",
++ 3 => "omic-1",
++ 0 => "omic-2",
++ 1 => "omic-2",
++ 12 => "omic-0",
++ 13 => "omic-0",
++ 14 => "omic-0",
++ 15 => "omic-1",
++ 10 => "omic-1",
++ 11 => "omic-1",
++ 8 => "omic-2",
++ 9 => "omic-2");
+
+ use integer;
+ # There are a total of eight OMI units on an MC unit. So, to
+@@ -1834,15 +2143,15 @@ sub processOmic
+ }
+
+ #--------------------------------------------------
+-## OCMB_CHIP
+-##
+-##
++# @brief OCMB_CHIP
++#
++#--------------------------------------------------
+ sub processOcmbChip
+ {
+ my $targetObj = shift;
+ my $target = shift;
+
+- $targetObj->setEepromAttributesForAxone($targetObj, $target);
++ $targetObj->setEepromAttributesForDDIMs($target);
+ }
+
+ #-------------------------------------------------g
+@@ -2032,6 +2341,7 @@ sub processXbus
+ #For example, in wrap config, CONFIG_APPLY is expected to have "w"
+ #If "w" is not there, then we skip the connection and mark peers
+ #as NULL
++ my $system_config = $targetObj->{system_config};
+ if (($system_config eq $wrap_config && $config =~ /$wrap_config/) ||
+ ($system_config ne $wrap_config && $config =~ /$default_config/))
+ {
+@@ -2098,7 +2408,7 @@ sub processAbus
+ # A-bus connection has to be conisdered or not
+ # If user has passed 2N as argument, then we consider only those
+ # A-bus connections where token "2" is present
+-
++ my $system_config = $targetObj->{system_config};
+ if($system_config eq "2N" && $config =~ /$twonode/)
+ {
+ #Looking for Abus connections pertaining to 2 node system only
+@@ -2634,123 +2944,6 @@ sub processOcc
+ $targetObj->setAttribute($target,"OCC_MASTER_CAPABLE",$master_capable);
+ }
+
+-sub processMembufVpdAssociation
+-{
+- my $targetObj = shift;
+- my $target = shift;
+-
+- my $vpds=$targetObj->findConnections($target,"I2C","VPD");
+- if ($vpds ne "" ) {
+- my $vpd = $vpds->{CONN}->[0];
+- my $membuf_assocs=$targetObj->findConnections($vpd->{DEST_PARENT},
+- "LOGICAL_ASSOCIATION","MEMBUF");
+-
+- if ($membuf_assocs ne "") {
+- foreach my $membuf_assoc (@{$membuf_assocs->{CONN}}) {
+- my $membuf_target = $membuf_assoc->{DEST_PARENT};
+- setEepromAttributes($targetObj,
+- "EEPROM_VPD_PRIMARY_INFO",$membuf_target,$vpd);
+- my $index = $targetObj->getBusAttribute($membuf_assoc->{SOURCE},
+- $membuf_assoc->{BUS_NUM}, "ISDIMM_MBVPD_INDEX");
+- $targetObj->setAttribute(
+- $membuf_target,"ISDIMM_MBVPD_INDEX",$index);
+- $targetObj->setAttribute($membuf_target,
+- "VPD_REC_NUM",$targetObj->{vpd_num});
+- }
+- }
+- my $group_assocs=$targetObj->findConnections($vpd->{DEST_PARENT},
+- "LOGICAL_ASSOCIATION","CARD");
+-
+- if ($group_assocs ne "") {
+- foreach my $group_assoc (@{$group_assocs->{CONN}}) {
+- my $mb_target = $group_assoc->{DEST_PARENT};
+- my $group_target = $targetObj->getTargetParent($mb_target);
+- $targetObj->setAttribute($group_target,
+- "VPD_REC_NUM",$targetObj->{vpd_num});
+- }
+- }
+- $targetObj->{vpd_num}++;
+- }
+-}
+-
+-#--------------------------------------------------
+-## MEMBUF
+-##
+-## Finds I2C connections to DIMM and creates EEPROM attributes
+-## FYI: I had to handle DMI busses in framework because they
+-## define affinity path
+-sub processMembuf
+-{
+- my $targetObj = shift;
+- my $membufTarg = shift;
+- if ($targetObj->isBadAttribute($membufTarg, "PHYS_PATH", ""))
+- {
+- ##dmi is probably not connected. will get caught in error checking
+- return;
+- }
+-
+- processMembufVpdAssociation($targetObj,$membufTarg);
+-
+- ## find port mapping
+- my %dimm_portmap;
+- foreach my $child (@{$targetObj->getTargetChildren($membufTarg)})
+- {
+- if ($targetObj->getType($child) eq "MBA")
+- {
+- # find this MBA's position relative to the membuf
+- my $mba_num = $targetObj->getAttribute($child,"MBA_NUM");
+- # follow the DDR4 bus connection to find the 'ddr' targets
+- my $ddrs = $targetObj->findConnections($child,"DDR4","");
+-
+- if($ddrs eq "")
+- {
+- # on multi node system there is a possibility that either
+- # DDR4 or DDR3 dimms are connected under a node
+- my $ddrs = $targetObj->findConnections($child,"DDR3","");
+- }
+-
+- if ($ddrs ne "")
+- {
+- foreach my $ddr (@{$ddrs->{CONN}})
+- {
+- my $port_num = $targetObj->getDimmPort($ddr->{SOURCE});
+- my $dimm_num = $targetObj->getDimmPos($ddr->{SOURCE});
+- my $map = oct("0b".$mba_num.$port_num.$dimm_num);
+- $dimm_portmap{$ddr->{DEST_PARENT}} = $map;
+- }
+- }
+- }
+- }
+-
+-
+- ## Process MEMBUF to DIMM I2C connections
+- my @addr_map=('0','0','0','0','0','0','0','0');
+- my $dimms=$targetObj->findConnections($membufTarg,"I2C","SPD");
+- if ($dimms ne "") {
+- foreach my $dimm (@{$dimms->{CONN}}) {
+- my $dimm_target = $targetObj->getTargetParent($dimm->{DEST_PARENT});
+- setEepromAttributes($targetObj,
+- "EEPROM_VPD_PRIMARY_INFO",$dimm_target,
+- $dimm);
+-
+- my $field=getI2cMapField($targetObj,$dimm_target,$dimm);
+- my $map = $dimm_portmap{$dimm_target};
+-
+- if ($map eq "") {
+- print "ERROR: $dimm_target doesn't map to a dimm/port\n";
+- $targetObj->myExit(3);
+- }
+- $addr_map[$map] = $field;
+- }
+- }
+- $targetObj->setAttribute($membufTarg,
+- "MRW_MEM_SENSOR_CACHE_ADDR_MAP","0x".join("",@addr_map));
+-
+- ## Update bus speeds
+- processI2cSpeeds($targetObj,$membufTarg);
+-
+- processPowerRails($targetObj, $membufTarg);
+-}
+
+ sub getI2cMapField
+ {
+@@ -2794,7 +2987,7 @@ sub getI2cMapField
+ return $hexfield;
+ }
+
+-#------------------------------------------------------------------------------
++#--------------------------------------------------
+ # I2C
+ #
+ sub processI2C
+@@ -3253,7 +3446,9 @@ sub get_max_compute_nodes
+ }
+
+ #--------------------------------------------------
+-## ERROR checking
++# @brief Error checking
++#
++#--------------------------------------------------
+ sub errorCheck
+ {
+ my $targetObj = shift;
+@@ -3363,9 +3558,9 @@ Options:
+ 2N = special 2 node config with extra ABUS links
+ w = Special MST wrap config
+ -o = output filename
+- -s [SDR XML file] = import SDRs
+ -r = create report and save to [system_name].rpt
+- -v = version
++ -v = display current version
++ -t = run self test
+ ";
+ exit(1);
+ }
+@@ -3380,8 +3575,216 @@ sub do_plugin
+ {
+ $hwsvmrw_plugins{$step}(@_);
+ }
+- elsif ($debug && ($build eq "fsp"))
++ elsif ($targetObj->{debug} && ($targetObj->{build} eq "fsp"))
++ {
++ print STDERR "build is $targetObj->{build} but no plugin for $step\n";
++ }
++}
++
++###############################################################################
++# Self tests
++###############################################################################
++#--------------------------------------------------
++# @brief The main procedure to run the tests
++#
++# @param[in] $targetObj - The global target object
++#--------------------------------------------------
++sub runTests
++{
++ print "\nRunning tests: \n\n";
++ my $targetObj = shift;
++
++ # Load the XML and process the file, extracting targets and associating
++ # attributes, with their data, to the targets
++ loadXmlFile();
++
++ # Process the targets, setting the targets attributes.
++ processTargets();
++
++ # Each one of the test build on each other, if one fails then no point in
++ # running the other
++ testGetTopologyMode($targetObj) &&
++ testTopologyIdToTopologyIndex() &&
++ testGetTopologyIndex($targetObj);
++}
++
++#--------------------------------------------------
++# @brief Test the method that gets the topology mode.
++#
++# @param[in] $targetObj - The global target object
++#
++# @return true if test passed, false other wise
++#--------------------------------------------------
++sub testGetTopologyMode
++{
++ print ">> Running testgetTopologyMode \n";
++ my $targetObj = shift;
++
++ my $testPassed = true;
++
++ use constant TOPOLOGY_MODE_ATTRIBUTE => "PROC_FABRIC_TOPOLOGY_MODE";
++ use constant TOPOLOGY_MODES => qw/ MODE0 MODE1 /;
++ my @topologyModes = (TOPOLOGY_MODES);
++
++ # Cache the current mode to restore later
++ my $persistMode = $targetObj->getAttribute("/".$targetObj->{TOP_LEVEL},
++ TOPOLOGY_MODE_ATTRIBUTE);
++
++ # Test getting the topology mode
++ foreach my $topologyMode (@topologyModes)
+ {
+- print STDERR "build is $build but no plugin for $step\n";
++ $targetObj->setAttribute("/".$targetObj->{TOP_LEVEL},
++ TOPOLOGY_MODE_ATTRIBUTE,
++ $topologyMode);
++ my $topologyModeNumber = chop($topologyMode);
++ if (getTopologyMode($targetObj) != $topologyModeNumber)
++ {
++
++ $testPassed = false;
++ print "ERROR: Expected topology mode '$topologyModeNumber' but got " .
++ getTopologyMode($targetObj) . "\n";
++ }
+ }
++
++ # Restore mode
++ $targetObj->setAttribute("/".$targetObj->{TOP_LEVEL},
++ TOPOLOGY_MODE_ATTRIBUTE,
++ $persistMode);
++
++ print "<< Running testgetTopologyMode: test " .
++ getPassFailString($testPassed) . "\n";
++
++ return $testPassed;
+ }
++
++#--------------------------------------------------
++# @brief Tests the conversion method that converts the topology ID,
++# with given topology mode, to the topology index.
++#
++# @return true if test passed, false other wise
++#--------------------------------------------------
++sub testTopologyIdToTopologyIndex
++{
++ print ">> Running testTopologyIdToTopologyIndex \n";
++
++ my $testPassed = true;
++
++ # The different values expected when mode is 0 or 1
++ use constant TOPOLOGY_MODE_0_ARRAY => qw/ 0 1 4 5 8 9 12 13 16 17 20 21 24 25 28 29 /;
++ use constant TOPOLOGY_MODE_1_ARRAY => qw/ 0 1 2 3 8 9 10 11 16 17 18 19 24 25 26 27 /;
++
++ # The different topology modes
++ use constant TOPOLOGY_MODES => qw/ MODE0 MODE1 /;
++ my @topologyModes = (TOPOLOGY_MODES);
++
++ # Default with mode 0
++ my @toplogyModeArray = (TOPOLOGY_MODE_0_ARRAY);
++
++ # Test the conversion on the different IDs and modes
++ for my $topologyMode (@topologyModes)
++ {
++ my $topologyModeNumber = chop($topologyMode);
++ if (1 == $topologyModeNumber)
++ {
++ @toplogyModeArray = (TOPOLOGY_MODE_1_ARRAY);
++ }
++
++ # Needed variable
++ my $topologyIndex = 0;
++
++ # Iterate thru each permutation of the topology ID and
++ # test conversion to index
++ for (my $topologyId = 0; $topologyId < 16; ++$topologyId)
++ {
++ $topologyIndex = convertTopologyIdToIndex($topologyId,
++ $topologyModeNumber);
++ if ($topologyIndex != $toplogyModeArray[$topologyId])
++ {
++ $testPassed = false;
++ print "ERROR: conversion on topology Id($topologyId) with ";
++ print "topology mode($topologyMode) returned ";
++ print "topology index($topologyIndex), but expected ";
++ print "topology index($toplogyModeArray[$topologyId]) \n";
++ }
++ } # end for (my $topologyId = 0 ...
++ } # end foreach my $topologyMode (@topologyModes)
++
++ print "<< Running testTopologyIdToTopologyIndex: test " .
++ getPassFailString($testPassed) . "\n";
++
++ return $testPassed;
++}
++
++#--------------------------------------------------
++# @brief Test the method that gets the topology index based
++# based on the current processors within the MRW XML
++#
++# @param[in] $targetObj - The global target object
++#
++# @return true if test passed, false other wise
++#--------------------------------------------------
++sub testGetTopologyIndex
++{
++ my $targetObj = shift;
++
++ my $testPassed = true;
++
++ my $system_name = $targetObj->getAttribute('/sys-0',"SYSTEM_NAME");
++ if ($system_name =~ /RAINIER/i)
++ {
++ print ">> Running testGetTopologyIndex \n";
++
++ # The different procs available
++ use constant PROC_0 => "/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0";
++ use constant PROC_1 => "/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-1";
++
++ # Get processor 1's index
++ my $processorTarget = PROC_0;
++ my $topologyIndex = getTopologyIndex($targetObj, $processorTarget);
++
++ # For the current MRW, proc 0 has index 0 with mode 0
++ my $expectedTopologyIndex = 0;
++ if ($topologyIndex != $expectedTopologyIndex)
++ {
++ $testPassed = false;
++ my @fullProc = split(/\//, $processorTarget);
++ print "ERROR: retrieved topology index $topologyIndex for processor " .
++ "@fullProc[-1] but expected $expectedTopologyIndex \n";
++ }
++
++ # Get processor 2's index
++ $processorTarget = PROC_1;
++ $topologyIndex = getTopologyIndex($targetObj, $processorTarget);
++
++ # For the current MRW, proc 1 has index 4 with mode 0
++ $expectedTopologyIndex = 4;
++ if ($topologyIndex != $expectedTopologyIndex)
++ {
++ $testPassed = false;
++ my @fullProc = split(/\//, $processorTarget);
++ print "ERROR: retrieved topology index $topologyIndex for processor " .
++ "@fullProc[-1] but expected $expectedTopologyIndex \n";
++ }
++
++ print "<< Running testGetTopologyIndex: test " .
++ getPassFailString($testPassed) . "\n";
++
++ } # end if ($system_name =~ /RAINIER/i)
++
++ return $testPassed;
++}
++
++sub getPassFailString
++{
++ my $passFailBoolean = shift;
++ my $failPassString = "passed";
++
++ if ($passFailBoolean == false)
++ {
++ $failPassString = "failed";
++ }
++
++ return $failPassString;
++}
++
++
+--
+1.8.2.2
+