Merge pull request #50 from ploetzma/serverwizWorking

Serverwiz2 support for op-build
diff --git a/openpower/package/habanero-xml/habanero-xml.mk b/openpower/package/habanero-xml/habanero-xml.mk
index a028a2b..37af8c3 100644
--- a/openpower/package/habanero-xml/habanero-xml.mk
+++ b/openpower/package/habanero-xml/habanero-xml.mk
@@ -4,7 +4,7 @@
 #
 ################################################################################
 
-HABANERO_XML_VERSION ?= 502536fa76d6d73a9001d1a329a137f4668db4e8
+HABANERO_XML_VERSION ?= 70e508863cef9abd8aab5f5013138a1255a26ee1
 HABANERO_XML_SITE ?= $(call github,open-power,habanero-xml,$(HABANERO_XML_VERSION))
 
 HABANERO_XML_LICENSE = Apache-2.0
@@ -14,42 +14,26 @@
 HABANERO_XML_INSTALL_TARGET = NO
 
 MRW_SCRATCH=$(STAGING_DIR)/openpower_mrw_scratch
-MRW_INSTALL_DIRECTORY=$(STAGING_DIR)/preprocessed_mrw
 MRW_HB_TOOLS=$(STAGING_DIR)/hostboot_build_images
 
-HABANERO_XML_ENV_VARS= \
-    SCHEMA_FILE=$(MRW_SCRATCH)/schema/mrw.xsd \
-    PARSER_PATH=$(STAGING_DIR)/usr/bin \
-    XSL_PATH=$(MRW_SCRATCH)/xslt \
-    OUTPUT_PATH=$(MRW_INSTALL_DIRECTORY)
-
 define HABANERO_XML_BUILD_CMDS
         # copy the habanero xml where the common lives
         bash -c 'mkdir -p $(MRW_SCRATCH) && cp -r $(@D)/* $(MRW_SCRATCH)'
-        mkdir -p $(MRW_INSTALL_DIRECTORY)
 
-        # run the mrw parsers
-        $(HABANERO_XML_ENV_VARS) bash -c 'cd $(MRW_SCRATCH) && $(MAKE) habanero'
-
-        # move the APSS xml to the output area
-        cp $(MRW_SCRATCH)/HABANERO_APSS.xml $(MRW_INSTALL_DIRECTORY)
-
-        # generate the system mrm xml
-        $(MRW_HB_TOOLS)/genHwsvMrwXml.pl \
-            --system=$(BR2_OPENPOWER_CONFIG_NAME) \
-            --mrwdir=$(MRW_INSTALL_DIRECTORY) \
-            --build=hb > $(MRW_INSTALL_DIRECTORY)/$(BR2_HABANERO_MRW_XML_FILENAME)
+        # generate the system mrw xml
+        perl -I $(MRW_HB_TOOLS) \
+        $(MRW_HB_TOOLS)/processMrw.pl -x $(MRW_SCRATCH)/habanero.xml
 endef
 
 define HABANERO_XML_INSTALL_IMAGES_CMDS
 
         # merge in any system specific attributes, hostboot attributes
-        $(MRW_HB_TOOLS)/mergexml.sh $(@D)/$(BR2_HABANERO_SYSTEM_XML_FILENAME) \
+        $(MRW_HB_TOOLS)/mergexml.sh $(MRW_SCRATCH)/$(BR2_HABANERO_SYSTEM_XML_FILENAME) \
             $(MRW_HB_TOOLS)/attribute_types.xml \
             $(MRW_HB_TOOLS)/attribute_types_hb.xml \
             $(MRW_HB_TOOLS)/target_types_merged.xml \
             $(MRW_HB_TOOLS)/target_types_hb.xml \
-            $(MRW_INSTALL_DIRECTORY)/$(BR2_HABANERO_MRW_XML_FILENAME) > $(MRW_HB_TOOLS)/temporary_hb.hb.xml;
+            $(MRW_SCRATCH)/$(BR2_HABANERO_MRW_XML_FILENAME) > $(MRW_HB_TOOLS)/temporary_hb.hb.xml;
 
         # creating the targeting binary
         $(MRW_HB_TOOLS)/xmltohb.pl  \
diff --git a/openpower/package/hostboot/hostboot-0006-Serverwiz2-scripts.patch b/openpower/package/hostboot/hostboot-0006-Serverwiz2-scripts.patch
new file mode 100644
index 0000000..05ab197
--- /dev/null
+++ b/openpower/package/hostboot/hostboot-0006-Serverwiz2-scripts.patch
@@ -0,0 +1,2656 @@
+From 621e841553767416f071e2e5c6a7b8c7e2c59b81 Mon Sep 17 00:00:00 2001
+From: Matt Ploetz <maploetz@us.ibm.com>
+Date: Tue, 10 Feb 2015 11:29:57 -0600
+Subject: [PATCH] Final patchset for serverwiz2 processing
+
+Change-Id: Ic0a7d93a929dcbd6f40aa593833e5b90746bc16f
+---
+ src/build/mkrules/dist.targets.mk      |    3 +-
+ src/usr/targeting/common/Targets.pm    | 1446 ++++++++++++++++++++++++++++++++
+ src/usr/targeting/common/processMrw.pl | 1167 ++++++++++++++++++++++++++
+ 3 files changed, 2615 insertions(+), 1 deletion(-)
+ create mode 100755 src/usr/targeting/common/Targets.pm
+ create mode 100755 src/usr/targeting/common/processMrw.pl
+
+diff --git a/src/build/mkrules/dist.targets.mk b/src/build/mkrules/dist.targets.mk
+index a6fb236..b62e99d 100644
+--- a/src/build/mkrules/dist.targets.mk
++++ b/src/build/mkrules/dist.targets.mk
+@@ -72,7 +72,8 @@ COPY_FILES = \
+     src/usr/hwpf/hwp/initfiles/sample.initfile:tools \
+     src/build/buildpnor/buildSbePart.pl:openpower \
+     src/build/buildpnor/buildpnor.pl:openpower \
+-    src/usr/targeting/common/genHwsvMrwXml.pl:openpower \
++    src/usr/targeting/common/processMrw.pl:openpower \
++    src/usr/targeting/common/Targets.pm:openpower \
+     src/usr/targeting/common/xmltohb/mergexml.sh:openpower \
+     src/usr/targeting/common/xmltohb/attribute_types.xml:openpower \
+     src/usr/targeting/common/xmltohb/attribute_types_hb.xml:openpower \
+diff --git a/src/usr/targeting/common/Targets.pm b/src/usr/targeting/common/Targets.pm
+new file mode 100755
+index 0000000..d4c2bfa
+--- /dev/null
++++ b/src/usr/targeting/common/Targets.pm
+@@ -0,0 +1,1446 @@
++# IBM_PROLOG_BEGIN_TAG
++# This is an automatically generated prolog.
++#
++# $Source: src/usr/targeting/common/Targets.pm $
++#
++# OpenPOWER HostBoot Project
++#
++# Contributors Listed Below - COPYRIGHT 2015
++# [+] International Business Machines Corp.
++#
++#
++# Licensed under the Apache License, Version 2.0 (the "License");
++# you may not use this file except in compliance with the License.
++# You may obtain a copy of the License at
++#
++#     http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
++# implied. See the License for the specific language governing
++# permissions and limitations under the License.
++#
++# IBM_PROLOG_END_TAG
++package Targets;
++
++use strict;
++use XML::Simple;
++use Data::Dumper;
++
++sub new
++{
++    my $class = shift;
++    my $self  = {
++        xml          => undef,
++        data         => undef,
++        targeting    => undef,
++        enumerations => undef,
++        MAX_MCS      => 0,
++        master_proc  => undef,
++        huid_idx     => undef,
++        mru_idx      => undef,
++        force        => 0,
++        debug        => 0,
++        version      => "",
++        errorsExist  => 0,
++        NUM_PROCS    => 0,
++        TOP_LEVEL    => "sys-0",
++        TOPOLOGY     => undef,
++        DMI_FSI_MAP  => {
++            '0' => '3',
++            '1' => '2',
++            '4' => '7',
++            '5' => '6'
++        }
++        # TODO RTC: TBD
++        # DMI_FSI_MAP is a lookup table for DMI channel to FSI and ref clock.
++        # It is processor specific and needs to be pulled from a
++        # processor attribute instead of being hardcoded
++
++    };
++    return bless $self, $class;
++}
++
++sub setVersion
++{
++    my $self    = shift;
++    my $version = shift;
++
++    $self->{version} = $version;
++}
++
++sub getData
++{
++    my $self = shift;
++    return $self->{data};
++}
++
++## loads ServerWiz XML format
++sub loadXML
++{
++    my $self = shift;
++    my $filename = shift;
++    $XML::Simple::PREFERRED_PARSER = 'XML::Parser';
++    print "Loading MRW XML: $filename\n";
++    $self->{xml} =
++      XMLin($filename,forcearray => [ 'child_id', 'hidden_child_id', 'bus',
++                                      'property' ]);
++    $self->storeEnumerations();
++    $self->buildHierarchy($self->{TOP_LEVEL});
++    $self->buildAffinity();
++}
++
++################################################
++## prints out final XML for HOSTBOOT consumption
++
++sub printXML
++{
++    my $self = shift;
++    my $fh   = shift;
++    my $t    = shift;
++
++    my $atTop = 0;
++    if ($t eq "top")
++    {
++        $atTop = 1;
++        $t     = $self->{targeting}->{SYS};
++        print $fh "<attributes>\n";
++        print $fh "<version>" . $self->{version} . "</version>\n";
++    }
++    if (ref($t) ne "ARRAY")
++    {
++        return;
++    }
++    for (my $p = 0; $p < scalar(@{$t}); $p++)
++    {
++        if (ref($t->[$p]) ne "HASH") { next; }
++        my $target = $t->[$p]->{KEY};
++        $self->printTarget($fh, $target);
++        my $children = $t->[$p];
++        foreach my $u (sort(keys %{$children}))
++        {
++            if ($u ne "KEY")
++            {
++                $self->printXML($fh, $t->[$p]->{$u});
++            }
++        }
++    }
++    if ($atTop)
++    {
++        print $fh "</attributes>\n";
++    }
++}
++
++sub printTarget
++{
++    my $self   = shift;
++    my $fh     = shift;
++    my $target = shift;
++
++    my $target_ptr = $self->getTarget($target);
++    print $fh "<targetInstance>\n";
++    my $target_id = $self->getAttribute($target, "PHYS_PATH");
++    $target_id = substr($target_id, 9);
++    $target_id =~ s/\///g;
++    $target_id =~ s/\-//g;
++    print $fh "\t<id>" . $target_id . "</id>\n";
++    print $fh "\t<type>" . $self->getTargetType($target) . "</type>\n";
++
++    ## get attributes
++    foreach my $attr (sort (keys %{ $target_ptr->{ATTRIBUTES} }))
++    {
++        $self->printAttribute($fh, $target_ptr->{ATTRIBUTES}, $attr);
++    }
++    print $fh "</targetInstance>\n";
++}
++
++sub printAttribute
++{
++    my $self       = shift;
++    my $fh         = shift;
++    my $target_ptr = shift;
++    my $attribute  = shift;
++    my $r          = "";
++
++    # TODO RTC: TBD
++    # temporary until we converge attribute types
++    my %filter;
++    $filter{MRW_TYPE}                       = 1;
++    $filter{INSTANCE_PATH}                  = 1;
++    $filter{SYSTEM_NAME}                    = 1;
++    $filter{BUS_TYPE}                       = 1;
++    $filter{DIRECTION}                      = 1;
++    $filter{ENABLE_CAPI}                    = 1;
++    $filter{PCIE_CONFIG_NUM}                = 1;
++    $filter{PCIE_LANE_MASK}                 = 1;
++    $filter{PCIE_LANE_SET}                  = 1;
++    $filter{PCIE_NUM_LANES}                 = 1;
++    $filter{PHB_NUM}                        = 1;
++    $filter{IOP_NUM}                        = 1;
++    $filter{LOCATION_CODE}                  = 1;
++    $filter{MCS_NUM}                        = 1;
++    $filter{SCHEMATIC_INTERFACE}            = 1;
++    $filter{ENTITY_ID}                      = 1;
++    $filter{CLASS}                          = 1;
++    $filter{MODEL}                          = 1;
++    $filter{TYPE}                           = 1;
++    $filter{CDM_POLICIES}                   = 1;
++    $filter{ALL_MCS_IN_INTERLEAVING_GROUP}  = 1;
++    $filter{MSS_INTERLEAVE_ENABLE}          = 1;
++    $filter{CDM_POLICIES_BITMASK}           = 1;
++    $filter{ENTITY_ID_LOOKUP}               = 1;
++    $filter{ENTITY_INSTANCE}                = 1;
++    $filter{MBA_NUM}                        = 1;
++    $filter{IPMI_INSTANCE}                  = 1;
++    $filter{INSTANCE_ID}                    = 1;
++
++    if ($filter{$attribute} == 1)
++    {
++        return;
++    }
++    print $fh "\t<attribute>\n";
++    print $fh "\t\t<id>$attribute</id>\n";
++    my $value = $target_ptr->{$attribute}->{default};
++
++    if (ref($value) eq "HASH")
++    {
++        if (defined($value->{field}))
++        {
++            print $fh "\t\t<default>\n";
++            foreach my $f (sort keys %{ $value->{field} })
++            {
++                my $v = $value->{field}->{$f}->{value};
++                print $fh "\t\t\t<field><id>$f</id><value>$v</value></field>\n";
++            }
++            print $fh "\t\t</default>\n";
++        }
++    }
++    else
++    {
++        print $fh "\t\t<default>$value</default>\n";
++    }
++    print $fh "\t</attribute>\n";
++}
++
++## stores TYPE enumeration values which is used to generate HUIDs
++sub storeEnumerations
++{
++    my $self = shift;
++
++    foreach my $enumType (keys(%{ $self->{xml}->{enumerationType} }))
++    {
++        foreach my $enum (
++            keys(%{$self->{xml}->{enumerationType}->{$enumType}->{enumerator}}))
++        {
++            $self->{enumeration}->{$enumType}->{$enum} =
++              $self->{xml}->{enumerationType}->{$enumType}->{enumerator}
++              ->{$enum}->{value};
++        }
++    }
++}
++
++####################################################
++## build target hierarchy recursively
++##
++## creates convenient data structure
++## for accessing targets and busses
++## Structure:
++##
++##{TARGETS}                                         # location of all targets
++##{NSTANCE_PATH}                                    # keeps track of hierarchy
++##                                                   path while iterating
++##{TARGETS} -> target_name                          # specific target
++##{TARGETS} -> target_name -> {TARGET}              # pointer to target data
++##                                                   from XML data struture
++##{TARGETS} -> target_name -> {TYPE}# special attribute
++##{TARGETS} -> target_name -> {PARENT}              # parent target name
++##{TARGETS} -> target_name -> {CHILDREN}            # array of children targets
++##{TARGETS} -> target_name -> {CONNECTION} -> {DEST} # array of connection
++##                                                     destination targets
++##{TARGETS} -> target_name -> {CONNECTION} -> {BUS} # array of busses
++##{TARGETS} -> target_name -> {CHILDREN}            # array of children targets
++##{TARGETS} -> target_name -> {ATTRIBUTES}          # attributes
++## {ENUMERATION} -> enumeration_type -> enum        # value of enumeration
++## {BUSSES} -> bus_type[]                           # array of busses by
++##                                                   bus_type (I2C, FSI, etc)
++## {BUSSES} -> bus_type[] -> {BUS}                  # pointer to bus target
++##                                                   from xml structure
++## {BUSSES} -> bus_type[] -> {SOURCE_TARGET}        # source target name
++## {BUSSES} -> bus_type[] -> {DEST_TARGET}          # dest target name
++
++sub buildHierarchy
++{
++    my $self   = shift;
++    my $target = shift;
++
++    my $old_path        = $self->{data}->{INSTANCE_PATH};
++    my $target_xml      = $self->{xml}->{'targetInstance'}{$target};
++    my $affinity_target = $target;
++    my $key             = $self->{data}->{INSTANCE_PATH} . "/" . $target;
++
++    my $instance_path = $self->{data}->{INSTANCE_PATH};
++    $instance_path = "instance:" . substr($instance_path, 1);
++    $self->setAttribute($key, "INSTANCE_PATH", $instance_path);
++    $self->{data}->{TARGETS}->{$key}->{TARGET} = $target_xml;
++    $self->{data}->{INSTANCE_PATH} = $old_path . "/" . $target;
++
++    ## copy attributes
++
++    foreach my $attribute (keys %{ $target_xml->{attribute} })
++    {
++        my $value = $target_xml->{attribute}->{$attribute}->{default};
++        if (ref($value) eq "HASH")
++        {
++            if (defined($value->{field}))
++            {
++                foreach my $f (keys %{ $value->{field} })
++                {
++                    my $field_val=$value->{field}{$f}{value};
++                    if (ref($field_val)) {
++                        $self->setAttributeField($key, $attribute, $f,"");
++                    }
++                    else
++                    {
++                        $self->setAttributeField($key, $attribute, $f,
++                            $value->{field}{$f}{value});
++                    }
++                }
++            }
++            else
++            {
++                $self->setAttribute($key, $attribute, "");
++            }
++        }
++        else
++        {
++            $self->setAttribute($key, $attribute, $value);
++        }
++    }
++    ## global attributes overwrite local
++    foreach my $prop (keys %{$self->{xml}->{globalSetting}->{$key}->{property}})
++    {
++        my $val=$self->{xml}->{globalSetting}->{$key}->{property}->
++                       {$prop}->{value};
++        $self->setAttribute($key, $prop, $val);
++    }
++
++    ## Save busses
++    if (defined($target_xml->{bus}))
++    {
++        foreach my $b (@{ $target_xml->{bus} })
++        {
++            my $source_target =
++              $key . "/" . $b->{source_path} . $b->{source_target};
++            my $dest_target = $key . "/" . $b->{dest_path} . $b->{dest_target};
++            my $bus_type    = $b->{bus_type};
++            push(
++                @{
++                    $self->{data}->{TARGETS}->{$source_target}->{CONNECTION}
++                      ->{DEST}
++                  },
++                $dest_target
++            );
++            push(
++                @{
++                    $self->{data}->{TARGETS}->{$source_target}->{CONNECTION}
++                      ->{BUS}
++                  },
++                $b
++            );
++            my %bus_entry;
++            $bus_entry{SOURCE_TARGET} = $source_target;
++            $bus_entry{DEST_TARGET}   = $dest_target;
++            $bus_entry{BUS_TARGET}    = $b;
++            push(@{ $self->{data}->{BUSSES}->{$bus_type} }, \%bus_entry);
++        }
++    }
++
++    foreach my $child (@{ $target_xml->{child_id} })
++    {
++        my $child_key = $self->{data}->{INSTANCE_PATH} . "/" . $child;
++        $self->{data}->{TARGETS}->{$child_key}->{PARENT} = $key;
++        push(@{ $self->{data}->{TARGETS}->{$key}->{CHILDREN} }, $child_key);
++        $self->buildHierarchy($child);
++    }
++    foreach my $child (@{ $target_xml->{hidden_child_id} })
++    {
++        my $child_key = $self->{data}->{INSTANCE_PATH} . "/" . $child;
++        $self->{data}->{TARGETS}->{$child_key}->{PARENT} = $key;
++        push(@{ $self->{data}->{TARGETS}->{$key}->{CHILDREN} }, $child_key);
++        $self->buildHierarchy($child);
++    }
++    $self->{data}->{INSTANCE_PATH} = $old_path;
++
++}
++
++##########################################################
++## traces busses and builds affinity hierarchy
++## HOSTBOOT expected hierarchy: sys/node/proc/<unit>
++##                              sys/node/proc/mcs/membuf/<unit>
++##                              sys/node/proc/mcs/membuf/mba/dimm
++
++sub buildAffinity
++{
++    my $self = shift;
++    my $node      = -1;
++    my $proc      = -1;
++    my $node_phys = "";
++    my $node_aff  = "";
++    my $core_num = 0;
++    $self->{membuf_inst_num}=0;
++    foreach my $target (sort keys %{ $self->{data}->{TARGETS} })
++    {
++        my $target_ptr = $self->{data}->{TARGETS}{$target};
++        my $type       = $self->getType($target);
++        my $type_id    = $self->getEnumValue("TYPE", $type);
++        if ($type_id eq "") { $type_id = 0; }
++
++        if ($type eq "SYS")
++        {
++            $proc = -1;
++            $node = -1;
++
++            $self->{targeting}{SYS}[0]{KEY} = $target;
++            $self->setAttribute($target, "AFFINITY_PATH", "affinity:sys-0");
++            $self->setAttribute($target, "PHYS_PATH",     "physical:sys-0");
++            $self->setAttribute($target, "ENTITY_INSTANCE","0");
++        }
++        elsif ($type eq "NODE")
++        {
++            $core_num = 0;
++            $proc = -1;
++            $self->{dimm_tpos} = 0;
++            $self->{membuf_inst_num}=0;
++            $node++;
++            $node_phys = "physical:sys-0/node-$node";
++            $node_aff  = "affinity:sys-0/node-$node";
++            $self->{targeting}{SYS}[0]{NODES}[$node]{KEY} = $target;
++            $self->setAttribute($target, "AFFINITY_PATH",
++                "affinity:sys-0/node-$node");
++            $self->setAttribute($target, "PHYS_PATH",
++                "physical:sys-0/node-$node");
++            $self->setHuid($target, 0, $node);
++            $self->setAttribute($target, "ENTITY_INSTANCE",$node);
++        }
++        elsif ($type eq "PROC")
++        {
++            $proc++;
++            my $num_mcs = 0;
++            ### count number of MCSs
++            foreach my $unit (@{ $self->{data}->{TARGETS}{$target}{CHILDREN} })
++            {
++                my $unit_type = $self->getType($unit);
++                if ($unit_type eq "MCS")
++                {
++                    $num_mcs++;
++                }
++            }
++            if ($num_mcs > $self->{MAX_MCS})
++            {
++                $self->{MAX_MCS} = $num_mcs;
++            }
++            $self->{NUM_PROCS_PER_NODE} = $proc + 1;
++            $self->{targeting}->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{KEY} =
++              $target;
++
++            $self->setHuid($target, 0, $node);
++            my $socket = $self->getTargetParent(
++                         $self->getTargetParent($target));
++            my $parent_affinity = "affinity:sys-0/node-$node/proc-$proc";
++            my $parent_physical = "physical:sys-0/node-$node/proc-$proc";
++            $self->setAttribute($target, "AFFINITY_PATH",  $parent_affinity);
++            $self->setAttribute($target, "PHYS_PATH",      $parent_physical);
++            $self->setAttribute($target, "POSITION",       $proc);
++            $self->setAttribute($target, "ENTITY_INSTANCE",$proc);
++            $self->setAttribute($target, "FABRIC_NODE_ID",
++                  $self->getAttribute($socket,"FABRIC_NODE_ID"));
++             $self->setAttribute($target, "FABRIC_CHIP_ID",
++                  $self->getAttribute($socket,"FABRIC_CHIP_ID"));
++
++            $self->setAttribute($target, "VPD_REC_NUM",    $proc);
++
++
++            foreach my $unit (@{ $self->{data}->{TARGETS}{$target}{CHILDREN} })
++            {
++                my $unit_ptr     = $self->getTarget($unit);
++                my $unit_type    = $self->getType($unit);
++                my $unit_type_id = $self->getEnumValue("TYPE", $unit_type);
++                if (   $unit_type_id eq "" || $unit_type eq "FSI"
++                    || $unit_type eq "MCS")
++                {
++                    $unit_type_id = 0;
++                }
++
++                ## don't want non-hostboot targets
++                if ($unit_type_id > 0)
++                {
++
++                    push(@{$self->{targeting}
++                            ->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{$unit_type}},
++                            { 'KEY' => $unit });
++                    my $affinity_path =
++                        $parent_affinity . "/"
++                      . $self->getTarget($unit)->{TARGET}->{instance_name};
++                    my $physical_path =
++                        $parent_physical . "/"
++                      . $self->getTarget($unit)->{TARGET}->{instance_name};
++                    $self->setAttribute($unit, "AFFINITY_PATH",$affinity_path);
++                    $self->setAttribute($unit, "PHYS_PATH", $physical_path);
++                    $self->setHuid($unit, 0, $node);
++                    if ($unit_type eq "OCC")
++                    {
++                        $self->setAttribute($unit, "ENTITY_INSTANCE",$proc);
++                    }
++                    ## export core
++                    if ($unit_type eq "EX")
++                    {
++                        my $core_unit_num = $self->getAttribute($unit,
++                            "CHIP_UNIT");
++
++                        my $core_unit =
++                          $self->{data}->{TARGETS}{$unit}{CHILDREN}[0];
++                        push(
++                            @{
++                                $self->{targeting}
++                                  ->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{CORE}
++                              },
++                            { 'KEY' => $core_unit }
++                        );
++                        my $core_affinity_path =
++                            $affinity_path . "/"
++                          . $self->getTarget($core_unit)->{TARGET}
++                          ->{instance_name};
++                        my $core_physical_path =
++                            $physical_path . "/"
++                          . $self->getTarget($core_unit)->{TARGET}
++                          ->{instance_name};
++                        $self->setAttribute($core_unit, "AFFINITY_PATH",
++                            $core_affinity_path);
++                        $self->setAttribute($core_unit, "PHYS_PATH",
++                            $core_physical_path);
++                        $self->setAttribute($core_unit, "CHIP_UNIT",
++                            $core_unit_num);
++                        $self->setHuid($core_unit, 0, $node);
++                        $self->setAttribute($core_unit, "ENTITY_INSTANCE",
++                             $core_num);
++                        $core_num++;
++                    }
++                }
++                elsif ($unit_type eq "MCS")
++                {
++                    $self->processMcs($unit, $node, $proc, $parent_affinity,
++                        $parent_physical, $node_phys);
++                }
++            }
++        }
++    }
++}
++
++sub processMcs
++{
++    my $self            = shift;
++    my $unit            = shift;
++    my $node            = shift;
++    my $proc            = shift;
++    my $parent_affinity = shift;
++    my $parent_physical = shift;
++    my $node_phys       = shift;
++
++    my $mcs = $self->getAttribute($unit, "CHIP_UNIT");
++    my $membufnum = $proc * $self->{MAX_MCS} + $mcs;
++    $self->setAttribute($unit, "AFFINITY_PATH",$parent_affinity . "/mcs-$mcs");
++    $self->setAttribute($unit, "PHYS_PATH", $parent_physical . "/mcs-$mcs");
++    $self->setAttribute($unit, "MCS_NUM",   $mcs);
++    $self->setHuid($unit, 0, $node);
++    $self->{targeting}->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{MCSS}[$mcs]{KEY} =
++      $unit;
++
++        $self->setAttribute($unit, "EI_BUS_TX_LANE_INVERT","0");
++        $self->setAttribute($unit, "EI_BUS_TX_MSBSWAP","0");
++        $self->setAttribute($unit, "DMI_REFCLOCK_SWIZZLE","0");
++
++    ## Find connected membufs
++    my $membuf_dmi = $self->{data}->{TARGETS}{$unit}{CONNECTION}{DEST}[0];
++    if (defined($membuf_dmi))
++    {
++        ## found membuf connected
++        my $membuf =
++          $self->{data}->{TARGETS}{$membuf_dmi}
++          {PARENT};    ## get parent of dmi unit which is membuf
++        my $dmi_bus = $self->{data}->{TARGETS}{$unit}{CONNECTION}{BUS}[0];
++        $self->setAttribute($membuf, "POSITION",$membufnum);
++        $self->setAttribute($membuf, "AFFINITY_PATH",
++            $parent_affinity . "/mcs-$mcs/membuf-$membufnum");
++        $self->setAttribute($membuf, "PHYS_PATH",
++            $node_phys . "/membuf-$membufnum");
++        $self->setAttribute($membuf, "VPD_REC_NUM",
++            $self->getAttribute($membuf, "POSITION"));
++
++        ## copy DMI bus attributes to membuf
++        $self->setAttribute($unit, "EI_BUS_TX_LANE_INVERT",
++            $dmi_bus->{bus_attribute}->{PROC_TX_LANE_INVERT}->{default});
++        $self->setAttribute($unit, "EI_BUS_TX_MSBSWAP",
++            $dmi_bus->{bus_attribute}->{PROC_TX_MSBSWAP}->{default});
++        $self->setAttribute($membuf, "EI_BUS_TX_LANE_INVERT",
++            $dmi_bus->{bus_attribute}->{MEMBUF_TX_LANE_INVERT}->{default});
++        $self->setAttribute($membuf, "EI_BUS_TX_MSBSWAP",
++            $dmi_bus->{bus_attribute}->{MEMBUF_TX_MSBSWAP}->{default});
++
++        ## auto setup FSI assuming schematic symbol.  If FSI busses are
++        ## defined in serverwiz2, this will be overridden
++        ## in the schematic symbol, the fsi port num matches dmi ref clk num
++
++        my $fsi_port = $self->{DMI_FSI_MAP}->{$mcs};
++        my $proc_key =
++            $self->{targeting}->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{KEY};
++        my $proc_path = $self->getAttribute($proc_key,"PHYS_PATH");
++        $self->setFsiAttributes($membuf,"FSICM",0,$proc_path,$fsi_port,0);
++        $self->setAttribute($unit, "DMI_REFCLOCK_SWIZZLE",$fsi_port);
++        my $dmi_swizzle =
++             $dmi_bus->{bus_attribute}->{DMI_REFCLOCK_SWIZZLE}->{default};
++        my $dmi_swizzle =
++             $self->getBusAttribute($unit,0,"DMI_REFCLOCK_SWIZZLE");
++        if ($dmi_swizzle ne "")
++        {
++            $self->setAttribute($unit, "DMI_REFCLOCK_SWIZZLE",$dmi_swizzle);
++        }
++
++        $self->setHuid($membuf, 0, $node);
++        $self->{targeting}
++          ->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{MCSS}[$mcs] {MEMBUFS}[0]{KEY} =
++          $membuf;
++
++        $self->setAttribute($membuf, "ENTITY_INSTANCE",
++               $self->{membuf_inst_num});
++        $self->{membuf_inst_num}++;
++        ## get the mbas
++        foreach my $child (@{ $self->{data}->{TARGETS}{$membuf}{CHILDREN} })
++        {
++            ## need to not hardcard the subunits
++            if ($self->getType($child) eq "L4")
++            {
++                $self->{targeting}
++                  ->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{MCSS}[$mcs]{MEMBUFS}[0]
++                  {L4S}[0] {KEY} = $child;
++                $self->setAttribute($child, "AFFINITY_PATH",
++                    $parent_affinity . "/mcs-$mcs/membuf-$membufnum/l4-0");
++                $self->setAttribute($child, "PHYS_PATH",
++                    $node_phys . "/membuf-$membufnum/l4-0");
++                $self->setHuid($child, 0, $node);
++            }
++
++            if ($self->getType($child) eq "MBA")
++            {
++                my $mba = $self->getAttribute($child,"MBA_NUM");
++                $self->setAttribute($child, "AFFINITY_PATH",
++                    $parent_affinity . "/mcs-$mcs/membuf-$membufnum/mba-$mba");
++                $self->setAttribute($child, "PHYS_PATH",
++                    $node_phys . "/membuf-$membufnum/mba-$mba");
++                $self->setHuid($child, 0, $node);
++                $self->{targeting}
++                  ->{SYS}[0]{NODES}[$node]{PROCS}[$proc]{MCSS}[$mcs]{MEMBUFS}[0]
++                  {MBAS}[$mba]{KEY} = $child;
++
++                ## Trace the DDR busses to find connected DIMM
++                my $ddrs = $self->findConnections($child,"DDR3","");
++                if ($ddrs ne "")
++                {
++                    my $affinitypos=0;
++                    foreach my $dimms (@{$ddrs->{CONN}})
++                    {
++                        my $ddr = $dimms->{SOURCE};
++                        my $port_num = $self->getAttribute($ddr,"MBA_PORT");
++                        my $dimm_num = $self->getAttribute($ddr,"MBA_DIMM");
++                        my $dimm=$dimms->{DEST_PARENT};
++                        $self->setAttribute($dimm,"MBA_PORT",$port_num);
++                        $self->setAttribute($dimm,"MBA_DIMM",$dimm_num);
++
++                        my $aff_pos=16*$proc+$mcs*$self->{MAX_MCS}+4*$mba+
++                                    2*$port_num+$dimm_num;
++                        $self->setAttribute($dimm, "AFFINITY_PATH",
++                            $parent_affinity
++                      . "/mcs-$mcs/membuf-$membufnum/mba-$mba/dimm-$affinitypos"
++                        );
++                        $self->setAttribute($dimm, "PHYS_PATH",
++                            $node_phys . "/dimm-" . $self->{dimm_tpos});
++                        $self->setAttribute($dimm, "POSITION",
++                            $aff_pos);
++                        $self->setAttribute($dimm, "VPD_REC_NUM",
++                            $aff_pos);
++                        $self->setHuid($dimm, 0, $node);
++                        $self->{targeting}
++                          ->{SYS}[0]{NODES}[$node]{PROCS}[$proc] {MCSS}[$mcs]
++                          {MEMBUFS}[0]{MBAS}[$mba]{DIMMS}[$affinitypos]{KEY}
++                                = $dimm;
++                        $self->setAttribute($dimm, "ENTITY_INSTANCE",
++                             $self->{dimm_tpos});
++                        $self->{dimm_tpos}++;
++                        $affinitypos++;
++                    }
++                }
++            }
++        }
++    }
++}
++
++sub setFsiAttributes
++{
++    my $self = shift;
++    my $target = shift;
++    my $type = shift;
++    my $cmfsi = shift;
++    my $phys_path = shift;
++    my $fsi_port = shift;
++    my $flip_port = shift;
++
++    $self->setAttribute($target, "FSI_MASTER_TYPE","NO_MASTER");
++    if ($type eq "FSIM")
++    {
++        $self->setAttribute($target, "FSI_MASTER_TYPE","MFSI");
++    }
++    if ($type eq "FSICM")
++    {
++        $self->setAttribute($target, "FSI_MASTER_TYPE","CMFSI");
++    }
++    $self->setAttribute($target, "FSI_MASTER_CHIP","physical:sys");
++    $self->setAttribute($target, "FSI_MASTER_PORT","0xFF");
++    $self->setAttribute($target, "ALTFSI_MASTER_CHIP","physical:sys");
++    $self->setAttribute($target, "ALTFSI_MASTER_PORT","0xFF");
++    $self->setAttribute($target, "FSI_SLAVE_CASCADE", "0");
++    if ($cmfsi == 0)
++    {
++        $self->setAttribute($target, "FSI_MASTER_CHIP",$phys_path);
++        $self->setAttribute($target, "FSI_MASTER_PORT", $fsi_port);
++    }
++    else
++    {
++        $self->setAttribute($target, "ALTFSI_MASTER_CHIP",$phys_path);
++        $self->setAttribute($target, "ALTFSI_MASTER_PORT", $fsi_port);
++    }
++
++    #my $phys_path = $targetObj->getAttribute($parentTarget, "PHYS_PATH");
++    $self->setAttributeField($target, "FSI_OPTION_FLAGS","flipPort",
++          $flip_port);
++    $self->setAttributeField($target, "FSI_OPTION_FLAGS","reserved", "0");
++
++}
++
++
++## returns pointer to target from target name
++sub getTarget
++{
++    my $self   = shift;
++    my $target = shift;
++    return $self->{data}->{TARGETS}->{$target};
++}
++
++## returns pointer to array of all targets
++sub getAllTargets
++{
++    my $self   = shift;
++    my $target = shift;
++    return $self->{data}->{TARGETS};
++}
++
++## returns the target name of the parent of passed in target
++sub getTargetParent
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $target_ptr = $self->getTarget($target);
++    return $target_ptr->{PARENT};
++}
++
++## returns the number of connections associated with target
++sub getNumConnections
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $target_ptr = $self->getTarget($target);
++    if (!defined($target_ptr->{CONNECTION}->{DEST}))
++    {
++        return 0;
++    }
++    return scalar(@{ $target_ptr->{CONNECTION}->{DEST} });
++}
++
++## returns destination target name of first connection
++## useful for point to point busses with only 1 endpoint
++sub getFirstConnectionDestination
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $target_ptr = $self->getTarget($target);
++    return $target_ptr->{CONNECTION}->{DEST}->[0];
++}
++
++## returns pointer to bus of first connection
++sub getFirstConnectionBus
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $target_ptr = $self->getTarget($target);
++    return $target_ptr->{CONNECTION}->{BUS}->[0];
++}
++## returns target name of $i connection
++sub getConnectionDestination
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $i          = shift;
++    my $target_ptr = $self->getTarget($target);
++    return $target_ptr->{CONNECTION}->{DEST}->[$i];
++}
++
++sub getConnectionBus
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $i          = shift;
++    my $target_ptr = $self->getTarget($target);
++    return $target_ptr->{CONNECTION}->{BUS}->[$i];
++}
++
++sub findFirstEndpoint
++{
++    my $self     = shift;
++    my $target   = shift;
++    my $bus_type = shift;
++    my $end_type = shift;
++
++    my $target_children = $self->getTargetChildren($target);
++    if ($target_children eq "") { return ""; }
++
++    foreach my $child (@{ $self->getTargetChildren($target) })
++    {
++        my $child_bus_type = $self->getBusType($child);
++        if ($child_bus_type eq $bus_type)
++        {
++            for (my $i = 0; $i < $self->getNumConnections($child); $i++)
++            {
++                my $dest_target = $self->getConnectionDestination($child, $i);
++                my $dest_parent = $self->getTargetParent($dest_target);
++                my $type        = $self->getMrwType($dest_parent);
++                my $dest_type   = $self->getType($dest_parent);
++                if ($type eq "NA") { $type = $dest_type; }
++                if ($type eq $end_type)
++                {
++                    return $dest_parent;
++                }
++            }
++        }
++    }
++    return "";
++}
++sub findConnections
++{
++    my $self     = shift;
++    my $target   = shift;
++    my $bus_type = shift;
++    my $end_type = shift;
++
++    my %connections;
++    my $num=0;
++    my $target_children = $self->getTargetChildren($target);
++    if ($target_children eq "")
++    {
++        return "";
++    }
++
++    foreach my $child (@{ $self->getTargetChildren($target) })
++    {
++        my $child_bus_type = $self->getBusType($child);
++        if ($child_bus_type eq $bus_type)
++        {
++            for (my $i = 0; $i < $self->getNumConnections($child); $i++)
++            {
++                my $dest_target = $self->getConnectionDestination($child, $i);
++                my $dest_parent = $self->getTargetParent($dest_target);
++                my $type        = $self->getMrwType($dest_parent);
++                my $dest_type   = $self->getType($dest_parent);
++                if ($type eq "NA")
++                {
++                    $type = $dest_type;
++                }
++
++                if ($type eq $end_type || $end_type eq "")
++                {
++                    $connections{CONN}[$num]{SOURCE}=$child;
++                    $connections{CONN}[$num]{SOURCE_PARENT}=$target;
++                    $connections{CONN}[$num]{DEST}=$dest_target;
++                    $connections{CONN}[$num]{DEST_PARENT}=$dest_parent;
++                    $connections{CONN}[$num]{BUS_NUM}=$i;
++                    $num++;
++                }
++            }
++        }
++    }
++    if ($num==0) { return ""; }
++    return \%connections;
++}
++
++
++## returns BUS_TYPE attribute of target
++sub getBusType
++{
++    my $self   = shift;
++    my $target = shift;
++    my $type   = $self->getAttribute($target, "BUS_TYPE");
++    if ($type eq "") { $type = "NA"; }
++    return $type;
++}
++
++## return target type
++sub getType
++{
++    my $self   = shift;
++    my $target = shift;
++    my $type   = $self->getAttribute($target, "TYPE");
++    if ($type eq "") { $type = "NA"; }
++    return $type;
++}
++
++## return target type
++sub getMrwType
++{
++    my $self   = shift;
++    my $target = shift;
++    my $type   = $self->getAttribute($target, "MRW_TYPE");
++    if ($type eq "") { $type = "NA"; }
++    return $type;
++}
++
++## returns target instance name
++sub getInstanceName
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $target_ptr = $self->getTarget($target);
++    return $target_ptr->{TARGET}->{instance_name};
++}
++
++## returns the parent target type
++sub getTargetType
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $target_ptr = $self->getTarget($target);
++    return $target_ptr->{TARGET}->{type};
++}
++
++## checks if attribute is value
++## must be defined and have a non-empty value
++sub isBadAttribute
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $attribute  = shift;
++    my $badvalue   = shift;
++    my $target_ptr = $self->getTarget($target);
++    if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}))
++    {
++        return 1;
++    }
++    if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}->{default}))
++    {
++        return 1;
++    }
++    if ($target_ptr->{ATTRIBUTES}->{$attribute}->{default} eq "")
++    {
++        return 1;
++    }
++    if ($target_ptr->{ATTRIBUTES}->{$attribute}->{default} eq $badvalue)
++    {
++        return 1;
++    }
++    return 0;
++}
++
++## checks if complex attribute field is
++## defined and non-empty
++sub isBadComplexAttribute
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $attribute  = shift;
++    my $field      = shift;
++    my $badvalue   = shift;
++    my $target_ptr = $self->getTarget($target);
++
++    if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}))
++    {
++        return 1;
++    }
++    if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}->{default}))
++    {
++        return 1;
++    }
++    if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}->{default}->{field}))
++    {
++        return 1;
++    }
++    if ($target_ptr->{ATTRIBUTES}->{$attribute}->{default}->{field}->{$field}
++        ->{value} eq "")
++    {
++        return 1;
++    }
++    if ($target_ptr->{ATTRIBUTES}->{$attribute}->{default}->{field}->{$field}
++        ->{value} eq $badvalue)
++    {
++        return 1;
++    }
++    return 0;
++}
++
++## returns attribute value
++sub getAttribute
++{
++    my $self       = shift;
++    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",
++            $target, $attribute);
++
++        #print Dumper($target_ptr);
++        $self->myExit(4);
++    }
++    return $target_ptr->{ATTRIBUTES}->{$attribute}->{default};
++}
++## renames a target attribute
++sub renameAttribute
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $oldName    = shift;
++    my $newName    = shift;
++    my $target_ptr = $self->{data}->{TARGETS}->{$target};
++    if (!defined($target_ptr->{ATTRIBUTES}->{$oldName}))
++    {
++        return 1;
++    }
++    $target_ptr->{ATTRIBUTES}->{$newName}->{default} =
++      $target_ptr->{ATTRIBUTES}->{$oldName}->{default};
++    delete($target_ptr->{ATTRIBUTES}->{$oldName});
++    $self->log($target, "Renaming attribute: $oldName => $newName");
++    return 0;
++}
++
++## copy an attribute between targets
++sub copyAttribute
++{
++    my $self = shift;
++    my $source_target = shift;
++    my $dest_target = shift;
++    my $attribute = shift;
++
++    my $value=$self->getAttribute($source_target,$attribute);
++    $self->setAttribute($dest_target,$attribute,$value);
++
++    $self->log($dest_target, "Copy Attribute: $attribute=$value");
++}
++
++## sets an attribute
++sub setAttribute
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $attribute  = shift;
++    my $value      = shift;
++    my $target_ptr = $self->getTarget($target);
++    $target_ptr->{ATTRIBUTES}->{$attribute}->{default} = $value;
++    $self->log($target, "Setting Attribute: $attribute=$value");
++}
++## sets the field of a complex attribute
++sub setAttributeField
++{
++    my $self      = shift;
++    my $target    = shift;
++    my $attribute = shift;
++    my $field     = shift;
++    my $value     = shift;
++    $self->{data}->{TARGETS}->{$target}->{ATTRIBUTES}->{$attribute}->{default}
++      ->{field}->{$field}->{value} = $value;
++}
++## returns complex attribute value
++sub getAttributeField
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $attribute  = shift;
++    my $field      = shift;
++    my $target_ptr = $self->getTarget($target);
++    if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}->
++       {default}->{field}->{$field}->{value}))
++    {
++        printf("ERROR: getAttributeField(%s,%s,%s) | Attribute not defined\n",
++            $target, $attribute,$field);
++
++        $self->myExit(4);
++    }
++
++    return $target_ptr->{ATTRIBUTES}->{$attribute}->
++           {default}->{field}->{$field}->{value};
++}
++
++## returns an attribute from a bus
++sub getBusAttribute
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $busnum     = shift;
++    my $attr       = shift;
++    my $target_ptr = $self->getTarget($target);
++
++    if (
++        !defined(
++            $target_ptr->{CONNECTION}->{BUS}->[$busnum]->{bus_attribute}
++              ->{$attr}->{default}
++        )
++      )
++    {
++        printf("ERROR: getBusAttribute(%s,%d,%s) | Attribute not defined\n",
++            $target, $busnum, $attr);
++        $self->myExit(4);
++    }
++   if (ref($target_ptr->{CONNECTION}->{BUS}->[$busnum]->{bus_attribute}->{$attr}
++      ->{default}) eq  "HASH") {
++        return  "";
++    }
++    return $target_ptr->{CONNECTION}->{BUS}->[$busnum]->{bus_attribute}->{$attr}
++      ->{default};
++}
++## returns a pointer to an array of children target names
++sub getTargetChildren
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $target_ptr = $self->getTarget($target);
++    ## this is an array
++    return $target_ptr->{CHILDREN};
++}
++
++sub getEnumValue
++{
++    my $self     = shift;
++    my $enumType = shift;
++    my $enumName = shift;
++    if (!defined($self->{enumeration}->{$enumType}->{$enumName}))
++    {
++        printf("ERROR: getEnumValue(%s,%s) | enumType not defined\n",
++            $enumType, $enumName);
++        $self->myExit(4);
++    }
++    return $self->{enumeration}->{$enumType}->{$enumName};
++}
++
++sub getEnumHash
++{
++    my $self     = shift;
++    my $enumType = shift;
++    my $enumName = shift;
++    if (!defined($self->{enumeration}->{$enumType}))
++    {
++        printf("ERROR: getEnumValue(%s) | enumType not defined\n",
++            $enumType);
++            print Dumper($self->{enumeration});
++        $self->myExit(4);
++    }
++    return $self->{enumeration}->{$enumType};
++}
++
++sub setHuid
++{
++    my $self   = shift;
++    my $target = shift;
++    my $sys    = shift;
++    my $node   = shift;
++
++    my $type    = $self->getType($target);
++    my $type_id = $self->{enumeration}->{TYPE}->{$type};
++    if ($type_id eq "") { $type_id = 0; }
++    if ($type_id == 0) { return; }
++    my $index = 0;
++    if (defined($self->{huid_idx}->{$type}))
++    {
++        $index = $self->{huid_idx}->{$type};
++    }
++    else { $self->{huid_idx}->{$type} = 0; }
++
++    # Format: SSSS NNNN TTTTTTTT iiiiiiiiiiiiiiii
++    my $huid = sprintf("%01x%01x%02x%04x", $sys, $node, $type_id, $index);
++    $huid = "0x" . uc($huid);
++
++    $self->setAttribute($target, "HUID", $huid);
++    $self->{huid_idx}->{$type}++;
++    $self->log($target, "Setting HUID: $huid");
++    $self->setMruid($target, $node);
++}
++
++sub setMruid
++{
++    my $self   = shift;
++    my $target = shift;
++    my $node   = shift;
++
++    my $type          = $self->getType($target);
++    my $mru_prefix_id = $self->{enumeration}->{MRU_PREFIX}->{$type};
++    if ($mru_prefix_id eq "") { $mru_prefix_id = "0xFFFF"; }
++    if ($mru_prefix_id eq "0xFFFF") { return; }
++    my $index = 0;
++    if (defined($self->{mru_idx}->{$node}->{$type}))
++    {
++        $index = $self->{mru_idx}->{$node}->{$type};
++    }
++    else { $self->{mru_idx}->{$node}->{$type} = 0; }
++
++    my $mruid = sprintf("%s%04x", $mru_prefix_id, $index);
++    $self->setAttribute($target, "MRU_ID", $mruid);
++    $self->{mru_idx}->{$node}->{$type}++;
++}
++
++sub getMasterProc
++{
++    my $self = shift;
++    return $self->{master_proc};
++}
++
++sub setMasterProc
++{
++    my $self = shift;
++    my $target = shift;
++    $self->{master_proc}=$target;
++}
++
++sub getSystemName
++{
++    my $self = shift;
++    return $self->getAttribute("/".$self->{TOP_LEVEL}, "SYSTEM_NAME");
++}
++
++sub myExit
++{
++    my $self      = shift;
++    my $exit_code = shift;
++    if ($exit_code eq "") { $exit_code = 0; }
++    $self->{errorsExist} = 1;
++    if ($self->{force} == 0)
++    {
++        exit($exit_code);
++    }
++}
++
++sub log
++{
++    my $self   = shift;
++    my $target = shift;
++    my $msg    = shift;
++    if ($self->{debug})
++    {
++        print "DEBUG: ($target) $msg\n";
++    }
++}
++1;
++
++=head1 NAME
++
++Targets
++
++=head1 SYNOPSIS
++
++    use Targets;
++
++    my $targets = Targets->new;
++    $targets->loadXML("myfile.xml");
++    foreach my $target ( sort keys %{ $targets->getAllTargets() } ) {
++        ## do stuff with targets
++    }
++
++    $targets->printXML( $file_handle, "top" );
++
++=head1 DESCRIPTION
++
++C<Targets> is a class that consumes XML generated by ServerWiz2.  The XML
++describes a POWER system topology including nodes, cards, chips, and busses.
++
++=head1 OVERVIEW
++
++A simple example of a ServerWiz2 topology would be:
++
++=over 4
++
++=item Topology Example:
++
++   -system
++      -node
++         -motherboard
++           -processor
++           -pcie card
++               - daughtercard
++                  - memory buffer
++                  - dimms
++
++=back
++
++Targets->loadXML("myfile.xml") reads this topology and creates 2 data
++structures.  One data structure simply represents the hierarchical system
++topology.  The other data structure represents the hierarchical structure
++that hostboot expects (affinity path).
++
++Unlike hostboot, everything in ServerWiz2 is represented as a target.
++For example, FSI and I2C units are targets under the processor that have a
++bus type and therefore allow connections to be made.
++
++=head1 CONSTRUCTOR
++
++=over 4
++
++=item new ()
++
++There are no arguments for the constructor.
++
++=back
++
++=head1 METHODS
++
++C<TARGET> is a pointer to data structure containing all target information.
++C<TARGET_STRING> is the hierarchical target string used as key for data
++structure.  An example for C<TARGET_STRING> would be:
++C</sys-0/node-0/motherboard-0/dimm-0>
++
++=over 4
++
++=item loadXml (C<FILENAME>)
++
++Reads ServerWiz2 XML C<FILENAME> and stores into a data structure for
++manipulation and printing.
++
++=item getTarget(C<TARGET_STRING>)
++
++Returns pointer to data structure (C<TARGET>)
++
++=item getAllTargets(C<TARGET_STRING>)
++
++Returns array with all existing target data structures
++
++=item getTargetParent(C<TARGET_STRING>)
++
++Returns C<TARGET_STRING> of parent target
++
++=item getNumConnections(C<TARGET_STRING>)
++
++Returns the number of bus connections to this target
++
++=item getFirstConnectionDestination(C<TARGET_STRING>)
++
++Returns the target string of the first target found connected to
++C<TARGET_STRING>.  This is useful because many busses are guaranteed
++to only have one connection because they are point to point.
++
++=item getFirstConnectionBus(C<TARGET_STRING>)
++
++Returns the data structure of the bus of the first target found connected to
++C<TARGET_STRING>.  The bus data structure is also a target with attributes.
++
++=item getConnectionDestination(C<TARGET_STRING>,C<INDEX>)
++
++Returns the target string of the C<INDEX> target found connected to
++C<TARGET_STRING>.
++
++=item getConnectionBus(C<TARGET_STRING>)
++
++Returns the data structure of the C<INDEX> bus target found connected to
++C<TARGET_STRING>.
++
++=item findEndpoint(C<TARGET_STRING>,C<BUS_TYPE>,C<ENDPOINT_MRW_TYPE>)
++
++Searches through all connections to C<TARGET_STRING>
++for a endpoint C<MRW_TYPE> and C<BUS_TYPE>
++
++=item getBusType(C<TARGET_STRING>)
++
++Returns the BUS_TYPE attribute of (C<TARGET_STRING>).  Examples are I2C and DMI.
++
++=item getType(C<TARGET_STRING>)
++
++Returns the TYPE attribute of (C<TARGET_STRING>).
++Examples are PROC and MEMBUF.
++
++=item getMrwType(C<TARGET_STRING>)
++
++Returns the MRW_TYPE attribute of (C<TARGET_STRING>).
++Examples are CARD and PCI_CONFIG.  This
++is an extension to the TYPE attribute and are types that hostboot does
++not care about.
++
++=item getTargetType(C<TARGET_STRING>)
++
++Returns the target type id of (C<TARGET_STRING>).
++This is not the TYPE attribute.  This is the
++<id> from target_types.xml.  Examples are unit-pci-power8 and enc-node-power8.
++
++=item isBadAttribute(C<TARGET_STRING>,C<ATTRIBUTE_NAME>)
++
++Tests where attribute (C<ATTRIBUTE_NAME>) has been set in
++target (C<TARGET_STRING>).  Returns true if attribute is undefined or empty
++and false if attribute is defined and not empty.
++
++=item getAttribute(C<TARGET_STRING>,C<ATTRIBUTE_NAME>)
++
++Returns the value of attribute C<ATTRIBUTE_NAME> in target C<TARGET_STRING>.
++
++=item renameAttribute(C<TARGET_STRING>,C<ATTRIBUTE_OLDNAME>,
++C<ATTRIBUTE_OLDNAME>)
++
++Renames attribute C<ATTRIBUTE_OLDNAME> to C<ATTRIBUTE_NEWNAME> in target
++C<TARGET_STRING>.
++
++=item setAttribute(C<TARGET_STRING>,C<ATTRIBUTE_NAME>,C<VALUE>)
++
++Sets attribute C<ATTRIBUTE_NAME> of target C<TARGET_STRING> to value C<VALUE>.
++
++=item setAttributeField(C<TARGET_STRING>,C<ATTRIBUTE_NAME>,C<FIELD>,C<VALUE>)
++
++Sets attribute C<ATTRIBUTE_NAME> and field C<FIELD> of target C<TARGET_STRING>
++to value C<VALUE>.  This is for complex attributes.
++
++=item getBusAttribute(C<TARGET_STRING>,C<INDEX>,C<ATTRIBUTE_NAME>)
++
++Gets the attribute C<ATTRIBUTE_NAME> from bus C<TARGET_STRING> bus number
++C<INDEX>.
++
++=item getTargetChildren(C<TARGET_STRING>)
++
++Returns an array of target strings representing all the children of target
++C<TARGET_STRING>.
++
++=item getEnumValue(C<ENUM_TYPE>,C<ENUM_NAME>)
++
++Returns the enum value of type C<ENUM_TYPE> and name C<ENUM_NAME>.  The
++enumerations are also defined in ServerWiz2 XML output and are directly
++copied from attribute_types.xml.
++
++=item getMasterProc()
++
++Returns the target string of the master processor.
++
++=item myExit(C<EXIT_NUM>)
++
++Calls exit(C<EXIT_NUM>) when force flag is not set.
++
++=item log(C<TARGET_STRING>,C<MESSAGE>)
++
++Prints to stdout log message is debug mode is turned on.
++
++
++=back
++
++=head1 CREDITS
++
++Norman James <njames@us.ibm.com>
++
++=cut
++
+diff --git a/src/usr/targeting/common/processMrw.pl b/src/usr/targeting/common/processMrw.pl
+new file mode 100755
+index 0000000..18107df
+--- /dev/null
++++ b/src/usr/targeting/common/processMrw.pl
+@@ -0,0 +1,1167 @@
++#! /usr/bin/perl
++# IBM_PROLOG_BEGIN_TAG
++# This is an automatically generated prolog.
++#
++# $Source: src/usr/targeting/common/processMrw.pl $
++#
++# OpenPOWER HostBoot Project
++#
++# Contributors Listed Below - COPYRIGHT 2015
++# [+] International Business Machines Corp.
++#
++#
++# Licensed under the Apache License, Version 2.0 (the "License");
++# you may not use this file except in compliance with the License.
++# You may obtain a copy of the License at
++#
++#     http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
++# implied. See the License for the specific language governing
++# permissions and limitations under the License.
++#
++# IBM_PROLOG_END_TAG
++
++use strict;
++use XML::Simple;
++use Data::Dumper;
++use Targets;
++use Math::BigInt;
++use Getopt::Long;
++use File::Basename;
++
++my $VERSION = "1.0.0";
++
++my $force          = 0;
++my $serverwiz_file = "";
++my $version        = 0;
++my $debug          = 0;
++my $report         = 0;
++my $sdr_file       = "";
++
++GetOptions(
++    "f"   => \$force,             # numeric
++    "x=s" => \$serverwiz_file,    # string
++    "d"   => \$debug,
++    "v"   => \$version,
++    "r"   => \$report,
++  )                               # flag
++  or printUsage();
++
++if ($version == 1)
++{
++    die "\nprocessMrw.pl\tversion $VERSION\n";
++}
++
++if ($serverwiz_file eq "")
++{
++    printUsage();
++}
++
++$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
++
++my $targetObj = Targets->new;
++if ($force == 1)
++{
++    $targetObj->{force} = 1;
++}
++if ($debug == 1)
++{
++    $targetObj->{debug} = 1;
++}
++
++$targetObj->setVersion($VERSION);
++my $xmldir = dirname($serverwiz_file);
++$targetObj->loadXML($serverwiz_file);
++
++#--------------------------------------------------
++## loop through all targets and do stuff
++foreach my $target (sort keys %{ $targetObj->getAllTargets() })
++{
++    my $type = $targetObj->getType($target);
++    if ($type eq "SYS")
++    {
++        processSystem($targetObj, $target);
++    }
++    elsif ($type eq "PROC")
++    {
++        processProcessor($targetObj, $target);
++    }
++    elsif ($type eq "MEMBUF")
++    {
++        processMembuf($targetObj, $target);
++    }
++    elsif ($type eq "FSP")
++    {
++        processBmc($targetObj, $target);
++    }
++}
++
++
++## check topology
++foreach my $n (keys %{$targetObj->{TOPOLOGY}}) {
++    foreach my $p (keys %{$targetObj->{TOPOLOGY}->{$n}}) {
++        if ($targetObj->{TOPOLOGY}->{$n}->{$p} > 1) {
++            print "ERROR: Fabric topology invalid.  2 targets have same ".
++                  "FABRIC_NODE_ID,FABRIC_CHIP_ID ($n,$p)\n";
++            $targetObj->myExit(3);
++        }
++    }
++}
++## check for errors
++if ($targetObj->getMasterProc() eq "")
++{
++    print "ERROR: Master Processor not defined.  Please instaitant a BMC
++ and connect LPC bus\n";
++    $targetObj->myExit(3);
++}
++foreach my $target (keys %{ $targetObj->getAllTargets() })
++{
++    errorCheck($targetObj, $target);
++}
++
++#--------------------------------------------------
++## write out final XML
++my $xml_fh;
++my $filename = $xmldir . "/" . $targetObj->getSystemName() . "_hb.mrw.xml";
++print "Creating XML: $filename\n";
++open($xml_fh, ">$filename") || die "Unable to create: $filename";
++$targetObj->printXML($xml_fh, "top");
++close $xml_fh;
++if (!$targetObj->{errorsExist})
++{
++    print "MRW created successfully!\n";
++}
++
++
++## optionally print out report
++if ($report)
++{
++    my $report_file = $xmldir . "/" . $targetObj->getSystemName() . ".rpt";
++    open(SUM,">$report_file") || die "Unable to create: $report_file\n";
++    my $ref = $targetObj->{targeting}->{SYS}[0]{NODES}[0]{PROCS};
++    foreach my $proc (@{$ref})
++    {
++        foreach my $mcs (@{$proc->{MCSS}})
++        {
++            my $mcs_target = $mcs->{KEY};
++            my $membuf=$mcs->{MEMBUFS}[0];
++            my $membuf_target = $membuf->{KEY};
++
++            my $sch = $targetObj->getAttribute($mcs_target,
++                      "SCHEMATIC_INTERFACE");
++            my $aff = $targetObj->getAttribute($mcs_target,"AFFINITY_PATH");
++            my $huid = $targetObj->getAttribute($mcs_target,"HUID");
++            print SUM "$sch | $huid | $mcs_target | $aff\n";
++            if ($membuf_target ne "") {
++                foreach my $mba (@{$membuf->{MBAS}}) {
++                    my $mba_target = $mba->{KEY};
++
++                    $huid = $targetObj->getAttribute($mba_target,"HUID");
++                    $aff = $targetObj->getAttribute($mcs_target,
++                                   "AFFINITY_PATH");
++                    print SUM "\t | $huid | $mba_target | $aff\n";
++                    foreach my $dimm (@{$mba->{DIMMS}}) {
++                        my $dimm_target = $dimm->{KEY};
++                        $aff = $targetObj->getAttribute($dimm_target,
++                                   "AFFINITY_PATH");
++                        $huid = $targetObj->getAttribute($dimm_target,"HUID");
++                        my $p = $targetObj->getAttribute($dimm_target,
++                                  "MBA_PORT");
++                        my $d = $targetObj->getAttribute($dimm_target,
++                                   "MBA_DIMM");
++                        my $i2c = $targetObj->getAttributeField($dimm_target,
++                                  "EEPROM_VPD_PRIMARY_INFO","devAddr");
++                        my $sens = $targetObj->getAttribute($dimm_target,
++                                  "IPMI_SENSORS");
++                        my @s = split(/\,/,$sens);
++
++                        print SUM "\t\t$huid | $dimm_target".
++                                  " | $aff | $p | $d | $i2c | ".
++                                  "$s[0],$s[1] | $s[2],$s[3]\n";
++                    }
++                }
++            }
++        }
++    }
++    close SUM;
++}
++
++#--------------------------------------------------
++#--------------------------------------------------
++## Processing subroutines
++
++#--------------------------------------------------
++## SDRs
++##
++
++sub processSdr
++{
++    my $targetObj = shift;
++    my $target = shift;
++    my $sdrObj = shift;
++
++    my @ipmi_sensors;
++    my %id_lu;
++
++    if ($targetObj->isBadAttribute($target,"ENTITY_ID_LOOKUP")==1)
++    {
++        return;
++    }
++    my $entity_id_lookup = $targetObj->getAttribute($target,"ENTITY_ID_LOOKUP");
++    if ($entity_id_lookup ne "") {
++        my $pos=0;
++        if ($targetObj->isBadAttribute($target,"IPMI_INSTANCE")==1)
++        {
++            $pos = $targetObj->getAttribute($target,"ENTITY_INSTANCE");
++        }
++        else
++        {
++            $pos = $targetObj->getAttribute($target,"IPMI_INSTANCE");
++        }
++        print  "$entity_id_lookup,$pos\n";
++        my @ids = split(/,/,$entity_id_lookup);
++        foreach my $i (@ids)
++        {
++            my $i_int = oct($i);
++            if ($i_int>0)
++            {
++                $id_lu{$i_int}=1;
++            }
++        }
++        foreach my $s (@{$sdrObj->{data}})
++        {
++            my $sdr_entity_id = oct($s->{entity_id});
++            if ($s->{name}=~/Core/) {
++                $sdr_entity_id=208;
++            }
++            if ($id_lu{$sdr_entity_id}>0)
++            {
++                my $sensor_id=$s->{sensor_id};
++                my $instance_id=oct($s->{entity_instance});
++                my $sensor_type=oct($s->{sensor_type});
++                if ($instance_id==$pos)
++                {
++                    print "IMPORTING: $target; pos=$pos; entity_id=".
++                           "$sdr_entity_id; ".
++                           "sensor_id=$sensor_id; sensor_type=$sensor_type\n";
++                    my $eid=sprintf("0x%02x%02x",$sensor_type,$sdr_entity_id);
++                    my $sid=sprintf("0x%02x",$s->{sensor_id});
++                    push(@ipmi_sensors,$eid.",".$sid);
++                    $id_lu{$sdr_entity_id}++;
++                }
++            }
++        }
++        foreach my $k (keys(%id_lu)) {
++            if ($id_lu{$k}==1)
++            {
++                print "WARNING: $target; pos=$pos; entity_id=$k; ".
++                      "not imported\n";
++                #$targetObj->myExit(3);
++            }
++        }
++        for (my $i=@ipmi_sensors;$i<16;$i++)
++        {
++            push(@ipmi_sensors,"0xFFFF,0xFF");
++        }
++        my $ipmi = join(',',@ipmi_sensors);
++        $targetObj->setAttribute($target,"IPMI_SENSORS",$ipmi);
++    }
++}
++
++#--------------------------------------------------
++## System
++##
++
++sub processSystem
++{
++    my $targetObj = shift;
++    my $target    = shift;
++
++    $targetObj->setAttribute($target, "MAX_MCS_PER_SYSTEM",
++        $targetObj->{NUM_PROCS_PER_NODE} * $targetObj->{MAX_MCS});
++    $targetObj->setAttribute($target, "MAX_PROC_CHIPS_PER_NODE",
++        $targetObj->{NUM_PROCS_PER_NODE});
++    parseBitwise($targetObj,$target,"CDM_POLICIES");
++}
++sub processBmc
++{
++    my $targetObj = shift;
++    my $target    = shift;
++    my $i2cs=$targetObj->findConnections($target,"I2C","PROC");
++    if ($i2cs ne "")
++    {
++       foreach my $i2c (@{$i2cs->{CONN}})
++       {
++           my $addr=$targetObj->getBusAttribute(
++                $i2c->{SOURCE},$i2c->{BUS_NUM},"I2C_ADDRESS");
++           $targetObj->setAttribute(
++                $i2c->{DEST_PARENT},"I2C_SLAVE_ADDRESS",$addr);
++       }
++    }
++    my $lpcs=$targetObj->findConnections($target,"LPC","PROC");
++    if ($lpcs ne "")
++    {
++       my $lpc=$lpcs->{CONN}->[0];
++       $targetObj->setMasterProc($lpc->{DEST_PARENT});
++    }
++}
++
++
++sub parseBitwise
++{
++    my $targetObj = shift;
++    my $target = shift;
++    my $attribute = shift;
++
++    my $mask = 0;
++    foreach my $e (keys %{ $targetObj->getEnumHash($attribute) }) {
++        my $field = $targetObj->getAttributeField(
++                    $target,$attribute."_BITMASK",$e);
++        my $val=hex($targetObj->getEnumValue($attribute,$e));
++        if ($field eq "true")
++        {
++            $mask=$mask | $val;
++        }
++    }
++    $targetObj->setAttribute($target,$attribute,$mask);
++ }
++#--------------------------------------------------
++## Processor
++##
++
++sub processProcessor
++{
++    my $targetObj = shift;
++    my $target    = shift;
++
++    #########################
++    ## Copy PCIE attributes from socket
++    ## In serverwiz, processor instances are not unique
++    ## because plugged into socket
++    ## so processor instance unique attributes are socket level.
++    ## The grandparent is guaranteed to be socket.
++    my $socket_target =
++       $targetObj->getTargetParent($targetObj->getTargetParent($target));
++    $targetObj->copyAttribute($socket_target,$target,"LOCATION_CODE");
++    $targetObj->copyAttribute($socket_target,$target,"FRU_ID");
++
++
++    foreach my $attr (sort (keys
++           %{ $targetObj->getTarget($socket_target)->{TARGET}->{attribute} }))
++    {
++        if ($attr =~ /PROC\_PCIE/)
++        {
++            $targetObj->copyAttribute($socket_target,$target,$attr);
++        }
++    }
++    $targetObj->log($target, "Processing PROC");
++    foreach my $child (@{ $targetObj->getTargetChildren($target) })
++    {
++        $targetObj->log($target, "Processing PROC child: $child");
++        my $child_type = $targetObj->getType($child);
++        if ($child_type eq "NA" || $child_type eq "FSI")
++        {
++            $child_type = $targetObj->getMrwType($child);
++        }
++        if ($child_type eq "ABUS")
++        {
++            processAbus($targetObj, $child);
++        }
++        elsif ($child_type eq "XBUS")
++        {
++            processXbus($targetObj, $child);
++        }
++        elsif ($child_type eq "FSIM" || $child_type eq "FSICM")
++        {
++            processFsi($targetObj, $child, $target);
++        }
++        elsif ($child_type eq "PCI_CONFIGS")
++        {
++            foreach my $pci_child (@{ $targetObj->getTargetChildren($child) })
++            {
++               processPcie($targetObj, $pci_child, $target);
++            }
++        }
++        elsif ($child_type eq "MCS")
++        {
++            processMcs($targetObj, $child, $target);
++        }
++        elsif ($child_type eq "OCC")
++        {
++            processOcc($targetObj, $child, $target);
++        }
++    }
++
++    ## update path for mvpd's and sbe's
++    my $path  = $targetObj->getAttribute($target, "PHYS_PATH");
++    my $model = $targetObj->getAttribute($target, "MODEL");
++
++    $targetObj->setAttributeField($target,
++        "EEPROM_VPD_PRIMARY_INFO","i2cMasterPath",$path);
++    $targetObj->setAttributeField($target,
++        "EEPROM_VPD_BACKUP_INFO","i2cMasterPath",$path);
++    $targetObj->setAttributeField($target,
++        "EEPROM_SBE_PRIMARY_INFO","i2cMasterPath",$path);
++    $targetObj->setAttributeField($target,
++        "EEPROM_SBE_BACKUP_INFO","i2cMasterPath",$path);
++    $targetObj->setAttributeField($target,
++        "EEPROM_VPD_FRU_INFO","i2cMasterPath",$path);
++
++    ## initialize master processor FSI's
++    $targetObj->setAttributeField($target, "FSI_OPTION_FLAGS", "flipPort", "0");
++
++    if ($target eq $targetObj->getMasterProc())
++    {
++        $targetObj->setAttributeField($target, "FSI_OPTION_FLAGS", "reserved",
++            "0");
++        $targetObj->setAttribute($target, "FSI_MASTER_CHIP",    "physical:sys");
++        $targetObj->setAttribute($target, "FSI_MASTER_PORT",    "0xFF");
++        $targetObj->setAttribute($target, "ALTFSI_MASTER_CHIP", "physical:sys");
++        $targetObj->setAttribute($target, "ALTFSI_MASTER_PORT", "0xFF");
++        $targetObj->setAttribute($target, "FSI_MASTER_TYPE",    "NO_MASTER");
++        $targetObj->setAttribute($target, "FSI_SLAVE_CASCADE",  "0");
++        $targetObj->setAttribute($target, "PROC_MASTER_TYPE", "ACTING_MASTER");
++    }
++    else
++    {
++        $targetObj->setAttribute($target, "PROC_MASTER_TYPE",
++            "MASTER_CANDIDATE");
++    }
++    ## Update bus speeds
++    processI2cSpeeds($targetObj,$target);
++
++    ## these are hardcoded because code sets them properly
++    $targetObj->setAttributeField($target, "SCOM_SWITCHES", "reserved",   "0");
++    $targetObj->setAttributeField($target, "SCOM_SWITCHES", "useFsiScom", "1");
++    $targetObj->setAttributeField($target, "SCOM_SWITCHES", "useInbandScom",
++        "0");
++    $targetObj->setAttributeField($target, "SCOM_SWITCHES", "useXscom", "0");
++
++    processMembufVpdAssociation($targetObj,$target);
++    setupBars($targetObj,$target);
++}
++
++
++sub processI2cSpeeds
++{
++    my $targetObj = shift;
++    my $target    = shift;
++
++    my @bus_speeds;
++    my $bus_speed_attr=$targetObj->getAttribute($target,"I2C_BUS_SPEED_ARRAY");
++    my @bus_speeds2 = split(/,/,$bus_speed_attr);
++    $bus_speeds[0][0] = $bus_speeds2[0];
++    $bus_speeds[0][1] = $bus_speeds2[1];
++    $bus_speeds[0][2] = $bus_speeds2[2];
++    $bus_speeds[1][0] = $bus_speeds2[3];
++    $bus_speeds[1][1] = $bus_speeds2[4];
++    $bus_speeds[1][2] = $bus_speeds2[5];
++
++    my $i2cs=$targetObj->findConnections($target,"I2C","");
++    if ($i2cs ne "") {
++        foreach my $i2c (@{$i2cs->{CONN}}) {
++            my $port=oct($targetObj->getAttribute($i2c->{SOURCE},"I2C_PORT"));
++            my $engine=oct($targetObj->getAttribute(
++                           $i2c->{SOURCE},"I2C_ENGINE"));
++            my $bus_speed=$targetObj->getBusAttribute(
++                  $i2c->{SOURCE},$i2c->{BUS_NUM},"I2C_SPEED");
++            if ($bus_speed eq "" || $bus_speed==0) {
++                print "ERROR: I2C bus speed not defined for $i2c->{SOURCE}\n";
++                $targetObj->myExit(3);
++            }
++            ## choose lowest bus speed
++            if ($bus_speeds[$engine][$port] eq "" ||
++                  $bus_speeds[$engine][$port]==0  ||
++                  $bus_speed < $bus_speeds[$engine][$port]) {
++                $bus_speeds[$engine][$port] = $bus_speed;
++            }
++        }
++    }
++    $bus_speed_attr = $bus_speeds[0][0].",".
++                      $bus_speeds[0][1].",".
++                      $bus_speeds[0][2].",".
++                      $bus_speeds[1][0].",".
++                      $bus_speeds[1][1].",".
++                      $bus_speeds[1][2];
++
++    $targetObj->setAttribute($target,"I2C_BUS_SPEED_ARRAY",$bus_speed_attr);
++}
++
++################################
++## Setup address map
++
++sub setupBars
++{
++    my $targetObj = shift;
++    my $target = shift;
++    #--------------------------------------------------
++    ## Setup BARs
++
++    my $node = $targetObj->getAttribute($target, "FABRIC_NODE_ID");
++    my $proc   = $targetObj->getAttribute($target, "FABRIC_CHIP_ID");
++    $targetObj->{TOPOLOGY}->{$node}->{$proc}++;
++
++    my @bars=("FSP_BASE_ADDR","PSI_BRIDGE_BASE_ADDR",
++              "INTP_BASE_ADDR","PHB_BASE_ADDRS","PCI_BASE_ADDRS_32",
++              "PCI_BASE_ADDRS_64","RNG_BASE_ADDR","IBSCOM_PROC_BASE_ADDR");
++
++    foreach my $bar (@bars)
++    {
++        my ($num,$base,$node_offset,$proc_offset,$offset) = split(/,/,
++               $targetObj->getAttribute($target,$bar));
++        my $i_base = Math::BigInt->new($base);
++        my $i_node_offset = Math::BigInt->new($node_offset);
++        my $i_proc_offset = Math::BigInt->new($proc_offset);
++        my $i_offset = Math::BigInt->new($offset);
++
++        my $value="";
++        if ($num==0)
++        {
++            $value=$base;
++        }
++        else
++        {
++            for (my $i=0;$i<$num;$i++)
++            {
++                my $b=sprintf("0x%016X",
++         $i_base+$i_node_offset*$node+$i_proc_offset*$proc+$i_offset*$i);
++                my $sep=",";
++                if ($i==$num-1)
++                {
++                    $sep="";
++                }
++                $value=$value.$b.$sep;
++            }
++        }
++        $targetObj->setAttribute($target,$bar,$value);
++    }
++}
++
++#--------------------------------------------------
++## MCS
++##
++sub processMcs
++{
++    my $targetObj    = shift;
++    my $target       = shift;
++    my $parentTarget = shift;
++
++    my $node = $targetObj->getAttribute($parentTarget, "FABRIC_NODE_ID");
++    my $proc   = $targetObj->getAttribute($parentTarget, "FABRIC_CHIP_ID");
++
++    my ($base,$node_offset,$proc_offset,$offset) = split(/,/,
++               $targetObj->getAttribute($target,"IBSCOM_MCS_BASE_ADDR"));
++    my $i_base = Math::BigInt->new($base);
++    my $i_node_offset = Math::BigInt->new($node_offset);
++    my $i_proc_offset = Math::BigInt->new($proc_offset);
++    my $i_offset = Math::BigInt->new($offset);
++
++    my $mcs = $targetObj->getAttribute($target, "MCS_NUM");
++    my $mcsStr=sprintf("0x%016X",
++         $i_base+$i_node_offset*$node+$i_proc_offset*$proc+$i_offset*$mcs);
++    $targetObj->setAttribute($target, "IBSCOM_MCS_BASE_ADDR", $mcsStr);
++}
++
++
++#--------------------------------------------------
++## XBUS
++##
++## Finds XBUS connections and creates PEER TARGET attributes
++
++sub processXbus
++{
++    my $targetObj = shift;
++    my $target    = shift;
++
++    # $targetObj->setAttribute($target, "PEER_TARGET","");
++
++}
++
++#--------------------------------------------------
++## ABUS
++##
++## Finds ABUS connections and creates PEER TARGET attributes
++
++sub processAbus
++{
++    my $targetObj = shift;
++    my $target    = shift;
++
++    my $found_abus = 0;
++   $targetObj->setAttribute($target, "PEER_PATH","physical:na");
++   $targetObj->setAttribute($target, "EI_BUS_TX_LANE_INVERT","0");
++   $targetObj->setAttribute($target, "EI_BUS_TX_MSBSWAP","0");
++   # $targetObj->setAttribute($target, "PEER_TARGET","");
++
++    my $abus_child_conn = $targetObj->getFirstConnectionDestination($target);
++    if ($abus_child_conn ne "")
++    {
++        ## set attributes for both directions
++        my $aff1 = $targetObj->getAttribute($target, "AFFINITY_PATH");
++        my $aff2 = $targetObj->getAttribute($abus_child_conn, "AFFINITY_PATH");
++
++        $targetObj->setAttribute($abus_child_conn, "PEER_TARGET",
++            $targetObj->getAttribute($target, "PHYS_PATH"));
++        $targetObj->setAttribute($target, "PEER_TARGET",
++            $targetObj->getAttribute($abus_child_conn, "PHYS_PATH"));
++
++        $targetObj->setAttribute($abus_child_conn, "PEER_PATH",
++            $targetObj->getAttribute($target, "PHYS_PATH"));
++        $targetObj->setAttribute($target, "PEER_PATH",
++            $targetObj->getAttribute($abus_child_conn, "PHYS_PATH"));
++
++        # copy Abus attributes to proc
++        my $abus = $targetObj->getFirstConnectionBus($target);
++        $targetObj->setAttribute($target, "EI_BUS_TX_LANE_INVERT",
++            $abus->{bus_attribute}->{SOURCE_TX_LANE_INVERT}->{default});
++        $targetObj->setAttribute($target, "EI_BUS_TX_MSBSWAP",
++            $abus->{bus_attribute}->{SOURCE_TX_MSBSWAP}->{default});
++        $targetObj->setAttribute($abus_child_conn, "EI_BUS_TX_LANE_INVERT",
++            $abus->{bus_attribute}->{DEST_TX_LANE_INVERT}->{default});
++        $targetObj->setAttribute($abus_child_conn, "EI_BUS_TX_MSBSWAP",
++            $abus->{bus_attribute}->{DEST_TX_MSBSWAP}->{default});
++        $found_abus = 1;
++    }
++}
++
++#--------------------------------------------------
++## FSI
++##
++## Finds FSI connections and creates FSI MASTER attributes at endpoint target
++
++sub processFsi
++{
++    my $targetObj    = shift;
++    my $target       = shift;
++    my $parentTarget = shift;
++    my $type         = $targetObj->getBusType($target);
++
++    ## fsi can only have 1 connection
++    my $fsi_child_conn = $targetObj->getFirstConnectionDestination($target);
++
++    ## found something on other end
++    if ($fsi_child_conn ne "")
++    {
++        my $fsi_link = $targetObj->getAttribute($target, "FSI_LINK");
++        my $fsi_port = $targetObj->getAttribute($target, "FSI_PORT");
++        my $cmfsi = $targetObj->getAttribute($target, "CMFSI");
++        my $flip_port         = 0;
++        my $proc_path = $targetObj->getAttribute($parentTarget,"PHYS_PATH");
++        my $fsi_child_target = $targetObj->getTargetParent($fsi_child_conn);
++        $targetObj->setFsiAttributes($fsi_child_target,
++                    $type,$cmfsi,$proc_path,$fsi_port,$flip_port);
++    }
++}
++
++#--------------------------------------------------
++## PCIE
++##
++## Creates attributes from abstract PCI attributes on bus
++
++sub processPcie
++{
++    my $targetObj    = shift;
++    my $target       = shift;
++    my $parentTarget = shift;
++
++
++    ## process pcie config target
++    ## this is a special target whose children are the different ways
++    ## to configure iop/phb's
++
++    # TODO RTC: TBD
++    # add a 3rd IOP for Naples
++
++    ## Get config children
++    my @lane_swap;
++    $lane_swap[0][0] = 0;
++    $lane_swap[0][1] = 0;
++    $lane_swap[1][0] = 0;
++    $lane_swap[1][1] = 0;
++
++    my @lane_mask;
++    $lane_mask[0][0] = "0x0000";
++    $lane_mask[0][1] = "0x0000";
++    $lane_mask[1][0] = "0x0000";
++    $lane_mask[1][1] = "0x0000";
++
++    my @lane_rev;
++    $lane_rev[0][0] = "";
++    $lane_rev[0][1] = "";
++    $lane_rev[1][0] = "";
++    $lane_rev[1][1] = "";
++
++    my @is_slot;
++    $is_slot[0][0] = 0;
++    $is_slot[0][1] = 0;
++    $is_slot[1][0] = 0;
++    $is_slot[1][1] = 0;
++
++    my $phb_config = "00000000";
++
++    my %cfg_check;
++    my @equalization;
++
++    my $wiring_table = $targetObj->getAttribute($target,"PCIE_LANE_SWAP_TABLE");
++    $wiring_table=~s/\s+//g;
++    $wiring_table=~s/\t+//g;
++    $wiring_table=~s/\n+//g;
++
++    my @t = split(/,/,$wiring_table);
++    my %iop_swap;
++
++    #iop_swap{iop}{clk swap}{clk group reversal}
++    $iop_swap{0}{0}{'00'}=$t[0];
++    $iop_swap{0}{0}{'01'}=$t[1];
++    $iop_swap{0}{0}{'10'}=$t[2];
++    $iop_swap{0}{0}{'11'}=$t[3];
++    $iop_swap{0}{1}{'00'}=$t[4];
++    $iop_swap{0}{1}{'01'}=$t[5];
++    $iop_swap{0}{1}{'10'}=$t[6];
++    $iop_swap{0}{1}{'11'}=$t[7];
++
++    $iop_swap{1}{0}{'00'}=$t[8];
++    $iop_swap{1}{0}{'01'}=$t[9];
++    $iop_swap{1}{0}{'10'}=$t[10];
++    $iop_swap{1}{0}{'11'}=$t[11];
++    $iop_swap{1}{1}{'00'}=$t[12];
++    $iop_swap{1}{1}{'01'}=$t[13];
++    $iop_swap{1}{1}{'10'}=$t[14];
++    $iop_swap{1}{1}{'11'}=$t[15];
++
++    my @lane_eq;
++    my $NUM_PHBS=4;
++    for (my $p=0;$p<$NUM_PHBS;$p++)
++    {
++        for (my $lane=0;$lane<16;$lane++)
++        {
++           $equalization[$p][$lane] = "0x00,0x00";
++        }
++    }
++    my $found=0;
++    foreach my $child (@{ $targetObj->getTargetChildren($target) })
++    {
++        my $num_connections = $targetObj->getNumConnections($child);
++        if ($num_connections > 0)
++        {
++            $found=1;
++            my $pci_endpoint=$targetObj->getFirstConnectionDestination($child);
++
++            my $bus = $targetObj->getConnectionBus($target, 0);
++            my $iop_num = $targetObj->getAttribute($child, "IOP_NUM");
++            my $swap_clks=$targetObj->getBusAttribute($child, 0,
++                         "PCIE_SWAP_CLKS");
++
++            my $lane_rev=$targetObj->getBusAttribute($child, 0,
++                         "LANE_REVERSAL");
++
++            my $phb_num = $targetObj->getAttribute($child, "PHB_NUM");
++            my $lane_set = $targetObj->getAttribute($child, "PCIE_LANE_SET");
++            my $capi = $targetObj->getAttribute($child, "ENABLE_CAPI");
++
++            my $pci_endpoint_type =
++              $targetObj->getAttribute(
++                $targetObj->getTargetParent($pci_endpoint), "CLASS");
++
++            if ($pci_endpoint_type eq "CARD")
++            {
++                $is_slot[$iop_num][$lane_set] = 1;
++            }
++            $lane_swap[$iop_num][$lane_set] =
++              $targetObj->getBusAttribute($child, 0, "PCIE_SWAP_CLKS");
++            $lane_mask[$iop_num][$lane_set] =
++              $targetObj->getAttribute($child, "PCIE_LANE_MASK");
++            $lane_rev[$iop_num][$lane_set] =
++              $targetObj->getBusAttribute($child, 0, "LANE_REVERSAL");
++            my $eq = $targetObj->getBusAttribute($child, 0,
++              "PCIE_LANE_EQUALIZATION");
++            my @eqs = split(/\,/,$eq);
++            for (my $e=0;$e<@eqs;$e=$e+3)
++            {
++                if ($eqs[$e] eq "all")
++                {
++                    for (my $lane=0;$lane<16;$lane++)
++                    {
++                        $equalization[$phb_num][$lane]=$eqs[$e+1].",".
++                              $eqs[$e+2];
++                    }
++                }
++                else
++                {
++                    $equalization[$phb_num][$eqs[$e]] = $eqs[$e+1].",".
++                              $eqs[$e+2];
++                }
++            }
++            substr($phb_config, $phb_num, 1, "1");
++        }
++    }
++    if ($found)
++    {
++    my $hex = sprintf('%X', oct("0b$phb_config"));
++
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_PHB_ACTIVE","0x" . $hex);
++    my $lane_mask_attr = sprintf("%s,%s,%s,%s",
++        $lane_mask[0][0], $lane_mask[0][1],
++        $lane_mask[1][0], $lane_mask[1][1]);
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_LANE_MASK",
++        $lane_mask_attr);
++    $targetObj->setAttribute($parentTarget,"PROC_PCIE_LANE_MASK_NON_BIFURCATED",
++        $lane_mask_attr);
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_LANE_MASK_BIFURCATED",
++        "0,0,0,0");
++
++    my @iop_swap_lu;
++    my @iop_lane_swap;
++    for (my $iop=0;$iop<2;$iop++)
++    {
++        $iop_lane_swap[$iop] = $lane_swap[$iop][0] | $lane_swap[$iop][1];
++        my $lane_rev = $lane_rev[$iop][0].$lane_rev[$iop][1];
++        $iop_swap_lu[$iop]=
++                 "0b".$iop_swap{$iop}{$iop_lane_swap[$iop]}{$lane_rev};
++        if ($iop_swap_lu[$iop] eq "") {
++          die "PCIE config for $iop,$iop_lane_swap[$iop],$lane_rev not found\n";
++        }
++    }
++    my $lane_swap_attr0 = sprintf("%s,%s",$iop_lane_swap[0],
++                          $iop_lane_swap[1]);
++    my $lane_swap_attr1 = sprintf("%s,0,%s,0",$iop_lane_swap[0],
++                          $iop_lane_swap[1]);
++
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_IOP_SWAP",
++        $lane_swap_attr0);
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_IOP_SWAP_NON_BIFURCATED",
++        $lane_swap_attr1);
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_IOP_SWAP_BIFURCATED",
++        "0,0,0,0");
++
++    my $lane_rev_attr = sprintf("%s,0,%s,0",
++                         oct($iop_swap_lu[0]),oct($iop_swap_lu[1]));
++
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_IOP_REVERSAL",
++        $lane_rev_attr);
++    $targetObj->setAttribute($parentTarget,
++        "PROC_PCIE_IOP_REVERSAL_NON_BIFURCATED",$lane_rev_attr);
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_IOP_REVERSAL_BIFURCATED",
++        "0,0,0,0");
++
++    my $is_slot_attr = sprintf("%s,%s,%s,%s",
++        $is_slot[0][0], $is_slot[0][1], $is_slot[1][0], $is_slot[1][1]);
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_IS_SLOT", $is_slot_attr);
++
++    ## don't support DSMP
++    $targetObj->setAttribute($parentTarget, "PROC_PCIE_DSMP_CAPABLE","0,0,0,0");
++    my $eq_str="";
++    for (my $p=0;$p<$NUM_PHBS;$p++)
++    {
++        for (my $lane=0;$lane<16;$lane++)
++        {
++            $eq_str=$eq_str.$equalization[$p][$lane].",";
++        }
++    }
++    $eq_str = substr($eq_str,0,length($eq_str)-1);
++    $targetObj->setAttribute($parentTarget,"PROC_PCIE_LANE_EQUALIZATION",
++         $eq_str);
++    }
++}
++#--------------------------------------------------
++## OCC
++##
++sub processOcc
++{
++    my $targetObj    = shift;
++    my $target       = shift;
++    my $parentTarget = shift;
++    my $master_capable=0;
++    if ($parentTarget eq $targetObj->getMasterProc())
++    {
++        $master_capable=1;
++    }
++    $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);
++                setEepromAttributes($targetObj,
++                       "EEPROM_VPD_FRU_INFO",$membuf_target,$vpd,"0++");
++                my $index = $targetObj->getBusAttribute($membuf_assoc->{SOURCE},
++                                $membuf_assoc->{BUS_NUM}, "ISDIMM_MBVPD_INDEX");
++                $targetObj->setAttribute(
++                            $membuf_target,"ISDIMM_MBVPD_INDEX",$index);
++            }
++        }
++    }
++}
++
++#--------------------------------------------------
++## 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 $target    = shift;
++    if ($targetObj->isBadAttribute($target, "PHYS_PATH", ""))
++    {
++        ##dmi is probably not connected.  will get caught in error checking
++        return;
++    }
++
++    processMembufVpdAssociation($targetObj,$target);
++
++    ## finds which gpio expander that controls vddr regs for membufs
++    my $gpioexp=$targetObj->findConnections($target,"I2C","GPIO_EXPANDER");
++    if ($gpioexp ne "" ) {
++        my $vreg=$targetObj->findConnections(
++            $gpioexp->{CONN}->[0]->{DEST_PARENT},"GPIO","VOLTAGE_REGULATOR");
++        if ($vreg ne "") {
++            my $vddPin = $targetObj->getAttribute(
++                 $vreg->{CONN}->[0]->{SOURCE},"CHIP_UNIT");
++            my $membufs=$targetObj->findConnections(
++               $vreg->{CONN}->[0]->{DEST_PARENT},"POWER","MEMBUF");
++            if ($membufs ne "") {
++                foreach my $membuf (@{$membufs->{CONN}}) {
++                    my $aff = $targetObj->getAttribute($membuf->{DEST_PARENT},
++                        "PHYS_PATH");
++                    setGpioAttributes($targetObj,$membuf->{DEST_PARENT},
++                        $gpioexp->{CONN}->[0],$vddPin);
++
++                }
++            }
++        }
++    }
++    ## Process MEMBUF to DIMM I2C connections
++    my $dimms=$targetObj->findConnections($target,"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);
++            setEepromAttributes($targetObj,
++                       "EEPROM_VPD_FRU_INFO",$dimm_target,
++                       $dimm,"0++");
++        }
++    }
++    ## Update bus speeds
++    processI2cSpeeds($targetObj,$target);
++
++    ## Do MBA port mapping
++    my %mba_port_map;
++    my $ddrs=$targetObj->findConnections($target,"DDR3","DIMM");
++    if ($ddrs ne "") {
++        my %portmap;
++        foreach my $ddr (@{$ddrs->{CONN}}) {
++            my $mba=$ddr->{SOURCE};
++            my $dimm=$ddr->{DEST_PARENT};
++            my ($dimmnum,$port)=split(//,sprintf("%02b\n",$portmap{$mba}));
++            $targetObj->setAttribute($dimm, "MBA_DIMM",$dimmnum);
++            $targetObj->setAttribute($dimm, "MBA_PORT",$port);
++            $portmap{$mba}++;
++
++            ## Copy connector attributes
++            my $dimmconn=$targetObj->getTargetParent($dimm);
++        }
++    }
++}
++
++
++sub setEepromAttributes
++{
++    my $targetObj = shift;
++    my $name = shift;
++    my $target = shift;
++    my $conn_target = shift;
++    my $fru = shift;
++
++    my $port = $targetObj->getAttribute($conn_target->{SOURCE}, "I2C_PORT");
++    my $engine = $targetObj->getAttribute($conn_target->{SOURCE}, "I2C_ENGINE");
++    my $addr = $targetObj->getBusAttribute($conn_target->{SOURCE},
++            $conn_target->{BUS_NUM}, "I2C_ADDRESS");
++
++    my $path = $targetObj->getAttribute($conn_target->{SOURCE_PARENT},
++               "PHYS_PATH");
++    my $mem  = $targetObj->getAttribute($conn_target->{DEST_PARENT},
++               "MEMORY_SIZE_IN_KB");
++    my $cycle  = $targetObj->getAttribute($conn_target->{DEST_PARENT},
++               "WRITE_CYCLE_TIME");
++    my $page  = $targetObj->getAttribute($conn_target->{DEST_PARENT},
++               "WRITE_PAGE_SIZE");
++    my $offset  = $targetObj->getAttribute($conn_target->{DEST_PARENT},
++               "BYTE_ADDRESS_OFFSET");
++
++    $targetObj->setAttributeField($target, $name, "i2cMasterPath", $path);
++    $targetObj->setAttributeField($target, $name, "port", $port);
++    $targetObj->setAttributeField($target, $name, "devAddr", $addr);
++    $targetObj->setAttributeField($target, $name, "engine", $engine);
++    $targetObj->setAttributeField($target, $name, "byteAddrOffset", $offset);
++    $targetObj->setAttributeField($target, $name, "maxMemorySizeKB", $mem);
++    $targetObj->setAttributeField($target, $name, "writePageSize", $page);
++    $targetObj->setAttributeField($target, $name, "writeCycleTime", $cycle);
++
++    if ($fru ne "")
++    {
++        $targetObj->setAttributeField($target, $name, "fruId", $fru);
++    }
++}
++
++
++sub setGpioAttributes
++{
++    my $targetObj = shift;
++    my $target = shift;
++    my $conn_target = shift;
++    my $vddrPin = shift;
++
++    my $port = $targetObj->getAttribute($conn_target->{SOURCE}, "I2C_PORT");
++    my $engine = $targetObj->getAttribute($conn_target->{SOURCE}, "I2C_ENGINE");
++    my $addr = $targetObj->getBusAttribute($conn_target->{SOURCE},
++            $conn_target->{BUS_NUM}, "I2C_ADDRESS");
++    my $path = $targetObj->getAttribute($conn_target->{SOURCE_PARENT},
++               "PHYS_PATH");
++
++
++    my $name="GPIO_INFO";
++    $targetObj->setAttributeField($target, $name, "i2cMasterPath", $path);
++    $targetObj->setAttributeField($target, $name, "port", $port);
++    $targetObj->setAttributeField($target, $name, "devAddr", $addr);
++    $targetObj->setAttributeField($target, $name, "engine", $engine);
++    $targetObj->setAttributeField($target, $name, "vddrPin", $vddrPin);
++}
++
++#--------------------------------------------------
++## ERROR checking
++sub errorCheck
++{
++    my $targetObj = shift;
++    my $target    = shift;
++    my $type      = $targetObj->getType($target);
++
++    ## error checking even for connections are done with attribute checks
++    ##  since connections simply create attributes at source and/or destination
++    ##
++    ## also error checking after processing is complete vs during
++    ## processing is easier
++    my %attribute_checks = (
++        SYS         => ['SYSTEM_NAME','OPAL_MODEL'],
++        PROC_MASTER => ['I2C_SLAVE_ADDRESS'],
++        PROC        => ['FSI_MASTER_CHIP','I2C_SLAVE_ADDRESS'],
++        MEMBUF => [ 'PHYS_PATH', 'EI_BUS_TX_MSBSWAP', 'FSI_MASTER_PORT|0xFF' ],
++        DIMM   => ['EEPROM_VPD_PRIMARY_INFO/devAddr'],
++    );
++    my %error_msg = (
++        'EEPROM_VPD_PRIMARY_INFO/devAddr' =>
++          'I2C connection to target is not defined',
++        'FSI_MASTER_PORT' => 'This target is missing a required FSI connection',
++        'FSI_MASTER_CHIP' => 'This target is missing a required FSI connection',
++        'EI_BUS_TX_MSBSWAP' =>
++          'DMI connection is missing to this membuf from processor',
++        'PHYS_PATH' =>'DMI connection is missing to this membuf from processor',
++        'I2C_SLAVE_ADDRESS' =>'I2C connection is missing from BMC to processor',
++    );
++
++    my @errors;
++    if ($targetObj->getMasterProc() eq $target)
++    {
++        $type = "PROC_MASTER";
++    }
++    foreach my $attr (@{ $attribute_checks{$type} })
++    {
++        my ($a,         $v)     = split(/\|/, $attr);
++        my ($a_complex, $field) = split(/\//, $a);
++        if ($field ne "")
++        {
++            if ($targetObj->isBadComplexAttribute(
++                    $target, $a_complex, $field, $v) )
++            {
++                push(@errors,sprintf(
++                        "$a attribute is invalid (Target=%s)\n\t%s\n",
++                        $target, $error_msg{$a}));
++            }
++        }
++        else
++        {
++            if ($targetObj->isBadAttribute($target, $a, $v))
++            {
++                push(@errors,sprintf(
++                        "$a attribute is invalid (Target=%s)\n\t%s\n",
++                        $target, $error_msg{$a}));
++            }
++        }
++    }
++    if ($type eq "PROC")
++    {
++        ## note: DMI is checked on membuf side so don't need to check that here
++        ## this checks if at least 1 abus is connected
++        my $found_abus = 0;
++        my $abus_error = "";
++        foreach my $child (@{ $targetObj->getTargetChildren($target) })
++        {
++            my $child_type = $targetObj->getBusType($child);
++            if ($child_type eq "ABUS" || $child_type eq "XBUS")
++            {
++                if ($targetObj->getMasterProc() ne $target)
++                {
++                    if (!$targetObj->isBadAttribute($child, "PEER_TARGET"))
++                    {
++                        $found_abus = 1;
++                    }
++                    else
++                    {
++                        $abus_error = sprintf(
++"proc not connected to proc via Abus or Xbus (Target=%s)",$child);
++                    }
++                }
++            }
++        }
++        if ($found_abus)
++        {
++            $abus_error = "";
++        }
++        else
++        {
++            push(@errors, $abus_error);
++        }
++    }
++    if ($errors[0])
++    {
++        foreach my $err (@errors)
++        {
++            print "ERROR: $err\n";
++        }
++        $targetObj->myExit(3);
++    }
++}
++
++sub printUsage
++{
++    print "
++processMrwl.pl -x [XML filename] [OPTIONS]
++Options:
++        -f = force output file creation even when errors
++        -d = debug mode
++        -s [SDR XML file] = import SDRs
++        -r = create report and save to [system_name].rpt
++        -v = version
++";
++    exit(1);
++}
+-- 
+1.8.2.2
+
diff --git a/openpower/package/palmetto-xml/palmetto-xml.mk b/openpower/package/palmetto-xml/palmetto-xml.mk
index af0b8b8..e165c13 100644
--- a/openpower/package/palmetto-xml/palmetto-xml.mk
+++ b/openpower/package/palmetto-xml/palmetto-xml.mk
@@ -4,7 +4,7 @@
 #
 ################################################################################
 
-PALMETTO_XML_VERSION = 227fdb14b0f03a422964ddc19563fdfd3a38e909
+PALMETTO_XML_VERSION = a3fc5ca767f0447a80442bbed70eec16f67fc7f4
 PALMETTO_XML_SITE = $(call github,open-power,palmetto-xml,$(PALMETTO_XML_VERSION))
 
 PALMETTO_XML_LICENSE = Apache-2.0
@@ -14,43 +14,26 @@
 PALMETTO_XML_INSTALL_TARGET = NO
 
 MRW_SCRATCH=$(STAGING_DIR)/openpower_mrw_scratch
-MRW_INSTALL_DIRECTORY=$(STAGING_DIR)/preprocessed_mrw
 MRW_HB_TOOLS=$(STAGING_DIR)/hostboot_build_images
 
-PALMETTO_XML_ENV_VARS= \
-    SCHEMA_FILE=$(MRW_SCRATCH)/schema/mrw.xsd \
-    PARSER_PATH=$(STAGING_DIR)/usr/bin \
-    XSL_PATH=$(MRW_SCRATCH)/xslt \
-    OUTPUT_PATH=$(MRW_INSTALL_DIRECTORY)
-
 define PALMETTO_XML_BUILD_CMDS
         # copy the palmetto xml where the common lives
         bash -c 'mkdir -p $(MRW_SCRATCH) && cp -r $(@D)/* $(MRW_SCRATCH)'
-        mkdir -p $(MRW_INSTALL_DIRECTORY)
 
-        # run the mrw parsers
-        $(PALMETTO_XML_ENV_VARS) bash -c 'cd $(MRW_SCRATCH) && $(MAKE) palmetto'
-
-        # move the APSS xml to the output area
-        cp $(MRW_SCRATCH)/PALMETTO_APSS.xml $(MRW_INSTALL_DIRECTORY)
-
-        # generate the system mrm xml
-        $(MRW_HB_TOOLS)/genHwsvMrwXml.pl \
-            --system=$(BR2_OPENPOWER_CONFIG_NAME) \
-            --mrwdir=$(MRW_INSTALL_DIRECTORY) \
-            --build=hb > $(MRW_INSTALL_DIRECTORY)/$(BR2_PALMETTO_MRW_XML_FILENAME)
-
+        # generate the system mrw xml
+        perl -I $(MRW_HB_TOOLS) \
+        $(MRW_HB_TOOLS)/processMrw.pl -x $(MRW_SCRATCH)/palmetto.xml
 endef
 
 define PALMETTO_XML_INSTALL_IMAGES_CMDS
 
         # merge in any system specific attributes, hostboot attributes
-        $(MRW_HB_TOOLS)/mergexml.sh $(@D)/$(BR2_PALMETTO_SYSTEM_XML_FILENAME) \
+        $(MRW_HB_TOOLS)/mergexml.sh $(MRW_SCRATCH)/$(BR2_PALMETTO_SYSTEM_XML_FILENAME) \
             $(MRW_HB_TOOLS)/attribute_types.xml \
             $(MRW_HB_TOOLS)/attribute_types_hb.xml \
             $(MRW_HB_TOOLS)/target_types_merged.xml \
             $(MRW_HB_TOOLS)/target_types_hb.xml \
-            $(MRW_INSTALL_DIRECTORY)/$(BR2_PALMETTO_MRW_XML_FILENAME) > $(MRW_HB_TOOLS)/temporary_hb.hb.xml;
+            $(MRW_SCRATCH)/$(BR2_PALMETTO_MRW_XML_FILENAME) > $(MRW_HB_TOOLS)/temporary_hb.hb.xml;
 
         # creating the targeting binary
         $(MRW_HB_TOOLS)/xmltohb.pl  \