Support building p10 PNOR images

Implements initial experimental support for building P10 PNOR images using
GCC8 (host and cross compiler) as the toolchain

- Introduced rainier configuration files
- Added p10 specific packages for sbe, hcode, hostboot, occ
- Pointed at starting commits for various pacakges to build op-build for p10
- Created various patches to fully compile all packages, to be removed
  when package owners have time to address them
- Generally updated package configurations to support p10 and p10 package
  variants

Signed-off-by: Nick Bofferding <bofferdn@us.ibm.com>
diff --git a/openpower/configs/hostboot/rainier.config b/openpower/configs/hostboot/rainier.config
new file mode 100755
index 0000000..8459ec6
--- /dev/null
+++ b/openpower/configs/hostboot/rainier.config
@@ -0,0 +1,80 @@
+# The HIOMAP protocol is used to access PNOR
+unset SFC_IS_AST2500
+unset SFC_IS_AST2400
+set   PNORDD_IS_IPMI
+unset PNORDD_IS_SFC
+set   ALLOW_MICRON_PNOR
+set   ALLOW_MACRONIX_PNOR
+
+# VPD options - Enable EECACHE
+set MVPD_READ_FROM_HW
+set MVPD_WRITE_TO_HW
+unset MVPD_READ_FROM_PNOR
+unset MVPD_WRITE_TO_PNOR
+
+set DJVPD_READ_FROM_HW
+set DJVPD_WRITE_TO_HW
+unset DJVPD_READ_FROM_PNOR
+unset DJVPD_WRITE_TO_PNOR
+
+set MEMVPD_READ_FROM_HW
+set MEMVPD_WRITE_TO_HW
+unset MEMVPD_READ_FROM_PNOR
+unset MEMVPD_WRITE_TO_PNOR
+
+#set PVPD_READ_FROM_HW
+#set PVPD_WRITE_TO_HW
+#unset PVPD_READ_FROM_PNOR
+#unset PVPD_WRITE_TO_PNOR
+
+unset CDIMM_FORMAT_FOR_CVPD
+
+# gpio config
+set GPIODD
+unset PALMETTO_VDDR
+
+# Enable Consecutive SBE Updates
+unset SBE_UPDATE_CONSECUTIVE
+unset SBE_UPDATE_INDEPENDENT
+unset SBE_UPDATE_SEQUENTIAL
+unset SBE_UPDATE_SIMULTANEOUS
+set NO_SBE_UPDATES
+
+#unset PCIE_HOTPLUG_CONTROLLER
+
+# turn on console output
+set CONSOLE
+set BMC_AST2500
+
+#set DISABLE_HOSTBOOT_RUNTIME
+
+# Compile in hostboot runtime PRD
+#unset HBRT_PRD
+
+# Compile in hb rt HTMGT : Load/Start OCC
+#unset HTMGT
+#unset START_OCC_DURING_BOOT
+#unset CONSOLE_OUTPUT_OCC_COMM
+
+# PNOR flags
+unset PNOR_TWO_SIDE_SUPPORT
+
+set BMC_BT_LPC_IPMI
+set AXONE
+set AXONE_BRINGUP
+set SUPPORT_EEPROM_CACHING
+
+# Enable Checkstop Analysis for both
+#   Runtime and IPLtime scenarios
+unset IPLTIME_CHECKSTOP_ANALYSIS
+
+# set for trace debug to console
+set CONSOLE_OUTPUT_TRACE
+#set CONSOLE_OUTPUT_FFDCDISPLAY
+
+# Terminate Hostboot when errors occur in manufacturing mode
+#   (relies on BMC to not trigger reboot)
+#unset HANG_ON_MFG_SRC_TERM
+
+# This is not working in P10 op-build
+unset ENABLE_HDAT_IN_HOSTBOOT
diff --git a/openpower/configs/rainier_defconfig b/openpower/configs/rainier_defconfig
new file mode 100644
index 0000000..b99d3e5
--- /dev/null
+++ b/openpower/configs/rainier_defconfig
@@ -0,0 +1,72 @@
+BR2_powerpc64le=y
+BR2_powerpc_power8=y
+BR2_BINUTILS_EXTRA_CONFIG_OPTIONS="--enable-targets=powerpc64-linux"
+BR2_GCC_VERSION_8_X=y
+BR2_EXTRA_GCC_CONFIG_OPTIONS="--enable-targets=powerpc64-linux --disable-libsanitizer"
+BR2_TOOLCHAIN_BUILDROOT_CXX=y
+BR2_TARGET_GENERIC_HOSTNAME="skiroot"
+BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
+BR2_ROOTFS_DEVICE_TABLE="../openpower/device_table.txt"
+BR2_TARGET_GENERIC_GETTY_PORT="hvc0"
+BR2_ENABLE_LOCALE_WHITELIST="C de en es fr it ja ko pt_BR ru zh_CN zh_TW"
+BR2_GENERATE_LOCALE="en_US.UTF-8 de_DE.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 it_IT.UTF-8 ja_JP.UTF-8 ko_KR.UTF-8 pt_BR.UTF-8 ru_RU.UTF-8 zh_CN.UTF-8 zh_TW.UTF-8"
+BR2_SYSTEM_ENABLE_NLS=y
+BR2_ROOTFS_USERS_TABLES="$(BR2_EXTERNAL_OP_BUILD_PATH)/configs/users-table"
+BR2_ROOTFS_OVERLAY="../openpower/overlay"
+BR2_ROOTFS_POST_BUILD_SCRIPT="../openpower/scripts/fixup-target-var ../openpower/scripts/firmware-whitelist"
+BR2_LINUX_KERNEL=y
+BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="5.2.17"
+BR2_LINUX_KERNEL_PATCH="$(BR2_EXTERNAL_OP_BUILD_PATH)/linux"
+BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_OP_BUILD_PATH)/configs/linux/skiroot_defconfig"
+BR2_LINUX_KERNEL_ZIMAGE_EPAPR=y
+BR2_LINUX_KERNEL_XZ=y
+BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
+BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_OP_BUILD_PATH)/configs/busybox.fragment"
+BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
+BR2_PACKAGE_LINUX_FIRMWARE=y
+BR2_PACKAGE_LINUX_FIRMWARE_BNX2X=y
+BR2_PACKAGE_LINUX_FIRMWARE_CXGB4_T4=y
+BR2_PACKAGE_CRYPTSETUP=y
+BR2_PACKAGE_IPMITOOL=y
+BR2_PACKAGE_IPMITOOL_USB=y
+BR2_PACKAGE_MDADM=y
+BR2_PACKAGE_PCIUTILS=y
+BR2_PACKAGE_NCURSES_WCHAR=y
+BR2_PACKAGE_DROPBEAR=y
+# BR2_PACKAGE_DROPBEAR_SERVER is not set
+BR2_PACKAGE_ETHTOOL=y
+BR2_PACKAGE_LRZSZ=y
+BR2_PACKAGE_NETCAT=y
+BR2_PACKAGE_RSYNC=y
+BR2_PACKAGE_SUDO=y
+BR2_PACKAGE_UTIL_LINUX_AGETTY=y
+BR2_TARGET_ROOTFS_CPIO_XZ=y
+BR2_TARGET_ROOTFS_INITRAMFS=y
+BR2_OPENPOWER_PLATFORM=y
+BR2_OPENPOWER_POWER10=y
+BR2_HOSTBOOT_P10_CONFIG_FILE="rainier.config"
+BR2_OPENPOWER_MACHINE_XML_CUSTOM_GIT=y
+BR2_OPENPOWER_MACHINE_XML_CUSTOM_GIT_VALUE="https://github.ibm.com/openbmc/rainier-xml.git"
+BR2_OPENPOWER_MACHINE_XML_VERSION="fe847e5b43f721b8869100a160b423179b047751"
+BR2_OPENPOWER_MACHINE_XML_FILENAME="Rainier-4U-MRW.xml"
+BR2_OPENPOWER_SYSTEM_XML_FILENAME="RAINIER_hb.system.xml"
+BR2_OPENPOWER_MRW_XML_FILENAME="RAINIER_hb.mrw.xml"
+BR2_OPENPOWER_BIOS_XML_FILENAME="Rainier-4U-MRW_bios.xml"
+BR2_OPENPOWER_PNOR_XML_LAYOUT_FILENAME="defaultPnorLayout_64.xml"
+BR2_OPENPOWER_CONFIG_NAME="rainier"
+BR2_OPENPOWER_PNOR_FILENAME="rainier.pnor"
+BR2_HOSTBOOT_BINARY_SBE_FILENAME="p10_sbe.img.ecc"
+BR2_HOSTBOOT_BINARY_SBEC_FILENAME="centaur_sbec_pad.img.ecc"
+BR2_HOSTBOOT_BINARY_WINK_FILENAME="p9n.ref_image.hdr.bin.ecc"
+BR2_IMA_CATALOG_FILENAME="ima_catalog.bin"
+BR2_OPENPOWER_TARGETING_BIN_FILENAME="RAINIER_HB.targeting.bin"
+BR2_OPENPOWER_TARGETING_ECC_FILENAME="RAINIER_HB.targeting.bin.ecc"
+BR2_BUILD_PNOR_SQUASHFS=y
+BR2_PACKAGE_PETITBOOT=y
+BR2_PACKAGE_PETITBOOT_MTD=y
+BR2_OCC_GPU_BIN_BUILD=y
+BR2_CAPP_UCODE_BIN_FILENAME="cappucode.bin"
+BR2_PACKAGE_LOADKEYS=y
+BR2_IMA_CATALOG_DTS="POWER9"
diff --git a/openpower/package/Config.in b/openpower/package/Config.in
index 903e6cb..db8e455 100755
--- a/openpower/package/Config.in
+++ b/openpower/package/Config.in
@@ -1,6 +1,7 @@
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/openpower-ffs/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/hostboot/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/hostboot-p8/Config.in"
+source "$BR2_EXTERNAL_OP_BUILD_PATH/package/hostboot-p10/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/hostboot-binaries/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/openpower-mrw/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/common-p8-xml/Config.in"
@@ -9,8 +10,10 @@
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/petitboot/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/p8-pore-binutils/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/hcode/Config.in"
+source "$BR2_EXTERNAL_OP_BUILD_PATH/package/hcode-p10/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/occ/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/occ-p8/Config.in"
+source "$BR2_EXTERNAL_OP_BUILD_PATH/package/occ-p10/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/capp-ucode/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/skiboot/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/libflash/Config.in"
@@ -19,6 +22,7 @@
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/ppe42-gcc/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/ima-catalog/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/sbe/Config.in"
+source "$BR2_EXTERNAL_OP_BUILD_PATH/package/sbe-p10/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/sb-signing-utils/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/sb-signing-framework/Config.in"
 source "$BR2_EXTERNAL_OP_BUILD_PATH/package/ocmb-explorer-fw/Config.in"
diff --git a/openpower/package/hcode-p10/Config.in b/openpower/package/hcode-p10/Config.in
new file mode 100644
index 0000000..7e5fbeb
--- /dev/null
+++ b/openpower/package/hcode-p10/Config.in
@@ -0,0 +1,38 @@
+config BR2_PACKAGE_HCODE_P10
+        bool "hcode-p10"
+        default y if (BR2_OPENPOWER_PLATFORM && BR2_OPENPOWER_POWER10)
+        select BR2_CPP
+        help
+            Project to build the HCODE package for P10
+
+if BR2_PACKAGE_HCODE_P10
+
+config BR2_HCODE_INCLUDE_IONV
+        bool "Enables packaging of the NVIDIA GPU image into the final hw image"
+        default y
+        help
+            Boolean used to flag whether to include NVIDIA GPU binary
+
+choice
+	prompt "HCODE version"
+	default BR2_HCODE_P10_LATEST_VERSION
+
+config BR2_HCODE_P10_LATEST_VERSION
+	bool "Use latest HCODE P10 version"
+
+config BR2_HCODE_P10_CUSTOM_VERSION
+	bool "Custom HCODE P10 version"
+
+endchoice
+
+config BR2_HCODE_P10_CUSTOM_VERSION_VALUE
+	string "HCODE P10 version"
+	depends on BR2_HCODE_P10_CUSTOM_VERSION
+
+config BR2_HCODE_P10_VERSION
+	string
+	default "hw092119a.opmst" if BR2_HCODE_P10_LATEST_VERSION
+	default BR2_HCODE_P10_CUSTOM_VERSION_VALUE \
+		if BR2_HCODE_P10_CUSTOM_VERSION
+
+endif
diff --git a/openpower/package/hcode-p10/hcode-p10.mk b/openpower/package/hcode-p10/hcode-p10.mk
new file mode 100644
index 0000000..8d2a43e
--- /dev/null
+++ b/openpower/package/hcode-p10/hcode-p10.mk
@@ -0,0 +1,50 @@
+################################################################################
+#
+# HCODE for P10
+#
+################################################################################
+
+HCODE_P10_VERSION = $(call qstrip,$(BR2_HCODE_P10_VERSION))
+HCODE_P10_SITE = $(call github,open-power,hcode,$(HCODE_P10_VERSION))
+# TODO: Need to comment out above line and enable next two lines
+# once buildable P10 HCODE is available in GHE
+#HCODE_P10_SITE = https://github.ibm.com/open-power/hcode.git
+#HCODE_P10_SITE_METHOD=git
+HCODE_P10_LICENSE = Apache-2.0
+
+HCODE_P10_INSTALL_IMAGES = YES
+HCODE_P10_INSTALL_TARGET = NO
+
+HCODE_P10_DEPENDENCIES = host-binutils host-ppe42-gcc hostboot-binaries
+
+HW_IMAGE_BIN_PATH=output/images/hw_image
+
+# TODO: Customize next four lines for P10
+HW_IMAGE_BIN=p9n.hw_image.bin
+HCODE_IMAGE_BIN = p9n.ref_image.bin
+HW_AXONE_IMAGE_BIN=p9a.hw_image.bin
+HCODE_AXONE_IMAGE_BIN = p9a.ref_image.bin
+
+CROSS_COMPILER_PATH=$(PPE42_GCC_BIN)
+PPE_TOOL_PATH ?= $(CROSS_COMPILER_PATH)
+PPE_PREFIX    ?= $(PPE_TOOL_PATH)/bin/powerpc-eabi-
+
+HCODE_P10_ENV_VARS= CONFIG_FILE=$(BR2_EXTERNAL_OP_BUILD_PATH)/configs/hcode/$(BR2_HCODE_CONFIG_FILE) \
+	LD_LIBRARY_PATH=$(HOST_DIR)/usr/lib OPENPOWER_BUILD=1\
+	CROSS_COMPILER_PATH=$(PPE42_GCC_BIN) PPE_TOOL_PATH=$(CROSS_COMPILER_PATH) \
+	PPE_PREFIX=$(CROSS_COMPILER_PATH)/bin/powerpc-eabi- \
+	RINGFILEPATH=$(STAGING_DIR)/hostboot_binaries __EKB_PREFIX=$(CXXPATH) \
+	CONFIG_IONV_FILE_LOCATION=$(STAGING_DIR)/hostboot_binaries/$(BR2_HOSTBOOT_BINARY_IONV_FILENAME) \
+	CONFIG_INCLUDE_IONV=$(BR2_HCODE_INCLUDE_IONV)
+
+define HCODE_P10_INSTALL_IMAGES_CMDS
+	mkdir -p $(STAGING_DIR)/hcode
+	$(INSTALL) $(@D)/$(HW_IMAGE_BIN_PATH)/$(HW_IMAGE_BIN) $(STAGING_DIR)/hcode/$(HCODE_IMAGE_BIN)
+        $(INSTALL) $(@D)/$(HW_IMAGE_BIN_PATH)/$(HW_AXONE_IMAGE_BIN) $(STAGING_DIR)/hcode/$(HCODE_AXONE_IMAGE_BIN)
+endef
+
+define HCODE_P10_BUILD_CMDS
+		$(HCODE_ENV_VARS) bash -c 'cd $(@D) && source ./env.bash && $(MAKE) '
+endef
+
+$(eval $(generic-package))
diff --git a/openpower/package/hostboot-binaries/hostboot_binaries.mk b/openpower/package/hostboot-binaries/hostboot_binaries.mk
index 658c281..c8b2c13 100644
--- a/openpower/package/hostboot-binaries/hostboot_binaries.mk
+++ b/openpower/package/hostboot-binaries/hostboot_binaries.mk
@@ -55,5 +55,26 @@
 endef
 endif
 
+###################################
+# P10:
+ifeq ($(BR2_OPENPOWER_POWER10),y)
+
+# TODO: Update for P10
+NIMBUS_RING_FILE=p9n.hw.rings.bin
+NIMBUS_RING_OVERLAYS_FILE=p9n.hw.overlays.bin
+AXONE_RING_FILE=p9a.hw.rings.bin
+AXONE_RING_OVERLAYS_FILE=p9a.hw.overlays.bin
+
+define HOSTBOOT_BINARIES_INSTALL_IMAGES_CMDS
+     $(INSTALL) -D $(@D)/cvpd.bin  $(STAGING_DIR)/hostboot_binaries/cvpd.bin
+     $(INSTALL) -D $(@D)/gpu_gpe1.bin  $(STAGING_DIR)/hostboot_binaries/gpu_gpe1.bin
+     $(INSTALL) -D $(@D)/$(BR2_HOSTBOOT_BINARY_IONV_FILENAME)  $(STAGING_DIR)/hostboot_binaries/
+     $(INSTALL) -D $(@D)/$(BR2_HOSTBOOT_BINARY_SBEC_FILENAME) $(STAGING_DIR)/hostboot_binaries/
+     $(INSTALL) -D $(@D)/$(NIMBUS_RING_FILE)  $(STAGING_DIR)/hostboot_binaries/
+     $(INSTALL) -D $(@D)/$(NIMBUS_RING_OVERLAYS_FILE)  $(STAGING_DIR)/hostboot_binaries/
+     $(INSTALL) -D $(@D)/$(AXONE_RING_FILE)  $(STAGING_DIR)/hostboot_binaries/
+     $(INSTALL) -D $(@D)/$(AXONE_RING_OVERLAYS_FILE)  $(STAGING_DIR)/hostboot_binaries/
+endef
+endif
 
 $(eval $(generic-package))
diff --git a/openpower/package/hostboot-p10/0001-mrw-parser-initial-fixes.patch b/openpower/package/hostboot-p10/0001-mrw-parser-initial-fixes.patch
new file mode 100644
index 0000000..e014d7d
--- /dev/null
+++ b/openpower/package/hostboot-p10/0001-mrw-parser-initial-fixes.patch
@@ -0,0 +1,2216 @@
+From c69095d5359b800068c258819014f0bb684046f6 Mon Sep 17 00:00:00 2001
+From: Roland Veloz <rveloz@us.ibm.com>
+Date: Fri, 6 Sep 2019 13:52:32 -0500
+Subject: [PATCH] P10 MRW parsing: Changes to the parser scripts
+
+This commit deals with refactoring and modularizing the processMrw.pl
+and Targets.pm scripts.  This commit is not about the artifact that
+gets produced by these files but the act of parsing an MRW file.
+
+Change-Id: I359afeebd9aa00ec6db2857a03ba0d9684c0858e
+RTC: 215164
+---
+ src/usr/targeting/common/Targets.pm    |  637 +++++++++++------
+ src/usr/targeting/common/processMrw.pl | 1183 +++++++++++++++++++++-----------
+ 2 files changed, 1218 insertions(+), 602 deletions(-)
+
+diff --git a/src/usr/targeting/common/Targets.pm b/src/usr/targeting/common/Targets.pm
+index dfd65d6..fb0bcbb 100644
+--- a/src/usr/targeting/common/Targets.pm
++++ b/src/usr/targeting/common/Targets.pm
+@@ -91,10 +91,29 @@ my %maxInstance = (
+     "SMPGROUP"      => 8,
+     "OMIC"          => 6,
+ );
++
++#--------------------------------------------------
++# @brief The constructor for the object Target
++#--------------------------------------------------
+ sub new
+ {
+     my $class = shift;
+     my $self  = {
++        # The following data are associated with the
++        # user command line options
++        build           => "hb",  # default to HB
++        force           => 0,
++        serverwiz_file  => "",    # input xml file
++        serverwiz_dir   => "",    # directory of input xml file
++        debug           => 0,
++        system_config   => "",
++        output_file     => "",
++        version         => 0,
++        report          => 0,
++        run_self_test   => 0,     # run internal test
++
++        # The following data are associated with the
++        # xml itself
+         xml          => undef,
+         data         => undef,
+         targeting    => undef,
+@@ -103,13 +122,11 @@ sub new
+         UNIT_COUNTS  => undef,
+         huid_idx     => undef,
+         mru_idx      => undef,
+-        force        => 0,
+-        debug        => 0,
+-        version      => "",
+         xml_version  => 0,
+         errorsExist  => 0,
+         NUM_PROCS    => 0,
+         TOP_LEVEL    => "",
++        TOP_LEVEL_HANDLE    => undef,
+         TOPOLOGY     => undef,
+         report_log   => "",
+         vpd_num      => 0,
+@@ -388,6 +405,162 @@ sub storeGroups
+     }
+ }
+ 
++#--------------------------------------------------
++# @brief Initialize a handle to the target instance.
++#
++# @details This method locates where the target instance
++#          resides and caches it for fast retrieval.
++#
++# @post A handle to the target instance is cached or exit
++#       stating that the target instance cannot be found.
++#
++# @param [in] $self - The global target object.
++#--------------------------------------------------
++sub initializeTargetInstanceHandle
++{
++    my $self = shift;
++
++    if ( (!defined $self->{TARGET_INST_HANDLE}) ||
++         ($self->{TARGET_INST_HANDLE} eq "") )
++    {
++        # Find the location of where target instances reside
++        my $targetInstances = $self->{xml}->{'targetInstance'};
++        if (!defined $targetInstances)
++        {
++            # Check one more level for the target instances
++            $targetInstances = $self->{xml}->{'targetInstances'}
++                                           ->{'targetInstance'};
++        }
++
++        # If can't find the target instances, then state so and exit
++        if (!defined $targetInstances)
++        {
++            die "No target instances defined\n";
++        }
++
++        $self->setTargetInstanceHandle($targetInstances);
++    } # end if ( (!defined $self->{TARGET_INST_HANDLE}) ||  ...
++}
++
++#--------------------------------------------------
++# @brief Return a handle to the target instances.
++#
++# @details This method will initialize the target instances
++#          if has not been already initialized.
++#
++# @param [in] $self - The global target object.
++#
++# @return - A handle to the target instance.
++#--------------------------------------------------
++sub getTargetInstanceHandle
++{
++    my $self = shift;
++
++    # If handle to target instances is not already cached, then initialize it
++    if ( (!defined $self->{TARGET_INST_HANDLE}) ||
++         ($self->{TARGET_INST_HANDLE} eq "") )
++    {
++        $self->initializeTargetInstanceHandle();
++    }
++
++    return ($self->{TARGET_INST_HANDLE});
++}
++
++#--------------------------------------------------
++# @brief Set the target instance handle to the given target handle
++#
++# @param [in] $self - The global target object.
++# @param [in] $targetHndl - The value the target instance handle is set to.
++#--------------------------------------------------
++sub setTargetInstanceHandle
++{
++    my $self = shift;
++    my $targetHndl = shift;
++
++    # Dynamically create and cache a handle to the target instance
++    $self->{TARGET_INST_HANDLE} = $targetHndl;
++}
++
++#--------------------------------------------------
++# @brief Initialize the top level target.
++#
++# @details This method locate the top level target
++#          and cache it for fast retrieval.
++#
++# @post The top level target is cached or exit stating that
++#       top level target not found.
++#
++# @param [in] $self - The global target object.
++#--------------------------------------------------
++sub initalizeTopLevel
++{
++    my $self = shift;
++
++    # If the top level target instance has not been found and set,
++    # then find that target and set top level to it
++    if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++    {
++        # Get a handle to the target instances
++        my $targetInstancesHandle = $self->getTargetInstanceHandle();
++
++        # Find the system target which is the top level target
++        foreach my $target (keys(%{$targetInstancesHandle}))
++        {
++            # If target is of type 'SYS' then we found the top level target
++            if ($targetInstancesHandle->{$target}->{attribute}
++                                      ->{TYPE}->{default} eq "SYS")
++            {
++                # Set the top level target and search no more
++                $self->setTopLevel($target);
++                # YOU SHALL NOT PASS!!!
++                last;
++            }
++        }
++
++        # If unable to find top level target, then state so and exit
++        if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++        {
++            die "Unable to find system top level target\n";
++        }
++    } # end if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++}
++
++#--------------------------------------------------
++# @brief Return the top level target.
++#
++# @details This method will initialize the top level
++#          target if has not been already initialized.
++#
++# @param [in] $self - The global target object.
++#
++# @return - The top level target.
++#--------------------------------------------------
++sub getTopLevel
++{
++    my $self = shift;
++
++    # If the top level target is not already cached, then initialize it
++    if ((!defined $self->{TOP_LEVEL}) || ($self->{TOP_LEVEL} eq ""))
++    {
++        $self->initalizeTopLevel();
++    }
++    return ($self->{TOP_LEVEL});
++}
++
++#--------------------------------------------------
++# @brief Set the top level target to the given target.
++#
++# @param [in] $self - The global target object.
++# @param [in] $target - The value the top level target is set to.
++#--------------------------------------------------
++sub setTopLevel
++{
++    my $self = shift;
++    my $target = shift;
++
++    $self->{TOP_LEVEL} = $target;
++}
++
+ ####################################################
+ ## build target hierarchy recursively
+ ##
+@@ -422,34 +595,23 @@ sub buildHierarchy
+     my $self   = shift;
+     my $target = shift;
+ 
+-    my $instance_path = $self->{data}->{INSTANCE_PATH};
+-    if (!defined $instance_path)
+-    {
+-        $instance_path = "";
+-    }
+-    my $baseptr = $self->{xml}->{'targetInstance'};
+-    if ($self->{xml_version} == 1)
+-    {
+-        $baseptr = $self->{xml}->{'targetInstances'}->{'targetInstance'};
+-    }
++    # Get a handle to the target instances
++    my $targetInstanceRef = $self->getTargetInstanceHandle();
++
++    # If caller did not provide a target, then use the top level target
+     if ($target eq "")
+     {
+-        ## find system target
+-        foreach my $t (keys(%{$baseptr}))
+-        {
+-            if ($baseptr->{$t}->{attribute}->{TYPE}->{default} eq "SYS")
+-            {
+-                $self->{TOP_LEVEL} = $t;
+-                $target = $t;
+-            }
+-        }
++        $target = $self->getTopLevel();
+     }
+-    if ($target eq "")
++
++    my $instance_path = $self->{data}->{INSTANCE_PATH};
++    if (!defined $instance_path)
+     {
+-        die "Unable to find system top level target\n";
++        $instance_path = "";
+     }
++
+     my $old_path        = $instance_path;
+-    my $target_xml      = $baseptr->{$target};
++    my $target_xml      = $targetInstanceRef->{$target};
+     my $affinity_target = $target;
+     my $key             = $instance_path . "/" . $target;
+ 
+@@ -466,7 +628,6 @@ sub buildHierarchy
+     $self->{data}->{INSTANCE_PATH} = $old_path . "/" . $target;
+ 
+     ## copy attributes
+-
+     foreach my $attribute (keys %{ $target_xml->{attribute} })
+     {
+         my $value = $target_xml->{attribute}->{$attribute}->{default};
+@@ -2448,192 +2609,6 @@ sub findDestConnections
+ 
+ }
+ 
+-sub setEepromAttributesForAxone
+-{
+-    my $self      = shift;
+-    my $targetObj = shift;
+-    # Expects ocmb target
+-    my $target    = shift;
+-
+-    my %connections;
+-    my $num=0;
+-
+-    my $eeprom_name = "EEPROM_VPD_PRIMARY_INFO";
+-    my $fapi_name = "FAPI_I2C_CONTROL_INFO";
+-    # SPD contains data for EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO
+-    # SPD is the child of ocmb's parent, so get ocmb's parent
+-    # then look for the SPD child
+-    # With the resulting info, we populate pmic0, pmic1, ocmb, and dimm
+-    my $target_parent = $self->getTargetParent($target);
+-
+-    # Need to store pmic targets because they get parsed before we
+-    # do calculations for engine, port, and muxBusSelector
+-    # pmics need these values, so we store them until we need them later
+-    my $address = 0;
+-    my @pmic_array;
+-    foreach my $child (@{ $self->getTargetChildren($target_parent) })
+-    {
+-        my $type = $self->getTargetType($child);
+-        if ($type eq "chip-spd-device")
+-        {
+-            my $offset = $self->getAttribute($child, "BYTE_ADDRESS_OFFSET");
+-            my $memory_size = $self->getAttribute($child, "MEMORY_SIZE_IN_KB");
+-            my $cycle_time = $self->getAttribute($child, "WRITE_CYCLE_TIME");
+-            my $page_size = $self->getAttribute($child, "WRITE_PAGE_SIZE");
+-
+-            # Populate EEPROM for ocmb
+-            $targetObj->setAttributeField($target, $eeprom_name, "byteAddrOffset",
+-                $offset);
+-            $targetObj->setAttributeField($target, $eeprom_name, "maxMemorySizeKB",
+-                $memory_size);
+-            $targetObj->setAttributeField($target, $eeprom_name, "writeCycleTime",
+-                $cycle_time);
+-            $targetObj->setAttributeField($target, $eeprom_name, "writePageSize",
+-                $page_size);
+-
+-            # Populate EEPROM for dimm
+-            $targetObj->setAttributeField($target_parent, $eeprom_name, "byteAddrOffset",
+-                $offset);
+-            $targetObj->setAttributeField($target_parent, $eeprom_name, "maxMemorySizeKB",
+-                $memory_size);
+-            $targetObj->setAttributeField($target_parent, $eeprom_name, "writeCycleTime",
+-                $cycle_time);
+-            $targetObj->setAttributeField($target_parent, $eeprom_name, "writePageSize",
+-                $page_size);
+-
+-            # spd only child is i2c-slave, which contains devAddr info
+-            foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
+-            {
+-                $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
+-                # Populate EEPROM for dimm
+-                $targetObj->setAttributeField($target_parent, $eeprom_name, "devAddr",
+-                    $address);
+-
+-                # Populate EEPROM for ocmb
+-                $targetObj->setAttributeField($target, $eeprom_name, "devAddr",
+-                    $address);
+-            }
+-        }
+-        elsif ($type eq "chip-vreg-generic")
+-        {
+-            push(@pmic_array, $child);
+-            foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
+-            {
+-                $type = $self->getTargetType($i2c_slave);
+-                # pmic has child i2c_slave which contains the device address
+-                if ($type eq "unit-i2c-slave")
+-                {
+-                    $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
+-
+-                    # Populate FAPI for pmic
+-                    $targetObj->setAttributeField($child, $fapi_name, "devAddr",
+-                        $address);
+-                    last;
+-                }
+-            }
+-        }
+-        elsif ($type eq "chip-ocmb")
+-        {
+-            foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
+-            {
+-                # ocmb has multiple i2c-slaves, so we query with instance_name
+-                my $instance_name = $self->getInstanceName($i2c_slave);
+-                if ($instance_name eq "i2c-ocmb")
+-                {
+-                    $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
+-
+-                    # Populate FAPI for ocmb
+-                    $targetObj->setAttributeField($target, $fapi_name, "devAddr",
+-                        $address);
+-                    last;
+-                }
+-            }
+-        }
+-    }
+-
+-    # Get data from i2c-master-omi, which connects to the i2c_mux PCA9847
+-    my $conn = $self->findConnectionsByDirection($target, "I2C", "", 1);
+-    if ($conn ne "")
+-    {
+-        # There exists multiple i2c bus connections with chip-ocmb
+-        # They are all the same connections so we just take the first one
+-        # The mux channel has the i2cMuxBusSelector
+-        my $conn_source = @{$conn->{CONN}}[0]->{SOURCE};
+-        my $mux = $self->getAttribute($conn_source, "MUX_CHANNEL");
+-
+-        # Parent PCA9848 determines the mux path
+-        my $parent = $self->getTargetParent($conn_source);
+-        my $parent_pos = $self->getAttribute($parent, "POSITION");
+-        my $i2c_mux_path = "physical:sys-0/node-0/i2c_mux-$parent_pos";
+-
+-        # pmics and ocmb all grab FRU_ID from parent dimm
+-        my $fru = $self->getAttribute($target_parent, "FRU_ID");
+-
+-        my $master_i2c = $self->findConnectionsByDirection($self->getTargetParent($conn_source), "I2C", "", 1);
+-        if ($master_i2c ne "")
+-        {
+-            # There exists multiple i2c bus connections with the PCA9847 i2c_mux
+-            # They are all the same connections so we just take the first one
+-            $master_i2c = @{$master_i2c->{CONN}}[0];
+-            # i2c-master-omi source which has data we need
+-            my $source = $master_i2c->{SOURCE};
+-            my $dest = $master_i2c->{DEST};
+-            my $engine = $self->getAttribute($source, "I2C_ENGINE");
+-            my $port = $self->getAttribute($source, "I2C_PORT");
+-
+-            # Populate FAPI for ocmb
+-            $self->setAttributeField($target, $fapi_name, "engine",
+-                $engine);
+-            $self->setAttributeField($target, $fapi_name, "port",
+-                $port);
+-            $self->setAttributeField($target, $fapi_name, "i2cMuxBusSelector",
+-                $mux);
+-            $self->setAttributeField($target, $fapi_name, "i2cMuxPath",
+-                $i2c_mux_path);
+-            $self->setAttribute($target, "FRU_ID",
+-                $fru);
+-
+-            # Populate EEPROM for ocmb
+-            $self->setAttributeField($target, $eeprom_name, "i2cMuxPath",
+-                $i2c_mux_path);
+-            $self->setAttributeField($target, $eeprom_name, "engine",
+-                $engine);
+-            $self->setAttributeField($target, $eeprom_name, "port",
+-                $port);
+-            $self->setAttributeField($target, $eeprom_name, "i2cMuxBusSelector",
+-                $mux);
+-
+-
+-            # Populate FAPI for pmics
+-            foreach my $pmic (@pmic_array)
+-            {
+-                $self->setAttributeField($pmic, $fapi_name, "engine",
+-                    $engine);
+-                $self->setAttributeField($pmic, $fapi_name, "port",
+-                    $port);
+-                $self->setAttributeField($pmic, $fapi_name, "i2cMuxBusSelector",
+-                    $mux);
+-                $self->setAttributeField($pmic, $fapi_name, "i2cMuxPath",
+-                    $i2c_mux_path);
+-                $self->setAttribute($pmic, "FRU_ID",
+-                    $fru);
+-            }
+-
+-            # Populate EEPROM for dimm
+-            $self->setAttributeField($target_parent, $eeprom_name, "engine",
+-                $engine);
+-            $self->setAttributeField($target_parent, $eeprom_name, "port",
+-                $port);
+-            $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxBusSelector",
+-                $mux);
+-            $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxPath",
+-                $i2c_mux_path);
+-            $self->setAttribute($target_parent, "FRU_ID",
+-                $fru);
+-        }
+-    }
+-}
+-
+ # Find connections from/to $target (and it's children)
+ # $to_this_target indicates the direction to find.
+ sub findConnectionsByDirection
+@@ -2792,6 +2767,41 @@ sub getTargetType
+     return $target_ptr->{TARGET}->{type};
+ }
+ 
++
++#--------------------------------------------------
++# @brief Checks the given target for given attribute
++#
++# @details Will check the target for the given attribute.
++#          If attribute does not exist for target then
++#          return 0 (false), else if attribute does exist
++#          for target then return 1 (true).  This methods
++#          does not check the validity of the attribute
++#          or it's value.
++#
++# @param [in] $self - The global target object.
++# @param [in] $target - target to locate attribute on
++# @param [in] $attribut - attribute to locate
++#
++# @return true if attribute found, else false
++#--------------------------------------------------
++sub doesAttributeExistForTarget
++{
++    my $self       = shift;
++    my $target     = shift;
++    my $attribute  = shift;
++
++    my $target_ptr = $self->getTarget($target);
++
++    # If can't locate attribute for target then return back 0 (false)
++    if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}))
++    {
++        return 0;
++    }
++
++    # Attribute for target was found, return back 1 (true)
++    return 1;
++}
++
+ ## checks if attribute is value
+ ## must be defined and have a non-empty value
+ sub isBadAttribute
+@@ -2818,6 +2828,7 @@ sub isBadAttribute
+     {
+         return 1;
+     }
++
+     return 0;
+ }
+ 
+@@ -2864,6 +2875,7 @@ sub getAttribute
+     my $target     = shift;
+     my $attribute  = shift;
+     my $target_ptr = $self->getTarget($target);
++
+     if (!defined($target_ptr->{ATTRIBUTES}->{$attribute}->{default}))
+     {
+         printf("ERROR: getAttribute(%s,%s) | Attribute not defined\n",
+@@ -3296,6 +3308,207 @@ sub writeReportFile
+     close R;
+ }
+ 
++#--------------------------------------------------
++# @brief Populates the EEPROM attributes for DDIMS
++#
++# @param [in] $self - The global target object.
++# @param [in] $target - An OCMB target
++#--------------------------------------------------
++sub setEepromAttributesForDDIMs
++{
++    my $self      = shift;
++    my $target    = shift;  # Expects ocmb target
++
++    my %connections;
++    my $num=0;
++
++    my $eeprom_name = "EEPROM_VPD_PRIMARY_INFO";
++    my $fapi_name = "FAPI_I2C_CONTROL_INFO";
++    # SPD contains data for EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO
++    # SPD is the child of ocmb's parent, so get ocmb's parent
++    # then look for the SPD child
++    # With the resulting info, we populate pmic0, pmic1, ocmb, and dimm
++    my $target_parent = $self->getTargetParent($target);
++
++    # Need to store pmic targets because they get parsed before we
++    # do calculations for engine, port, etc
++    # pmics need these values, so we store them until we need them later
++    my $address = 0;
++    my @pmic_array;
++    foreach my $child (@{ $self->getTargetChildren($target_parent) })
++    {
++        my $type = $self->getTargetType($child);
++        if ($type eq "chip-spd-device")
++        {
++            my $offset = $self->getAttribute($child, "BYTE_ADDRESS_OFFSET");
++            my $memory_size = $self->getAttribute($child, "MEMORY_SIZE_IN_KB");
++            my $cycle_time = $self->getAttribute($child, "WRITE_CYCLE_TIME");
++            my $page_size = $self->getAttribute($child, "WRITE_PAGE_SIZE");
++
++            # Populate EEPROM for ocmb
++            $self->setAttributeField($target, $eeprom_name, "byteAddrOffset",
++                $offset);
++            $self->setAttributeField($target, $eeprom_name, "maxMemorySizeKB",
++                $memory_size);
++            $self->setAttributeField($target, $eeprom_name, "writeCycleTime",
++                $cycle_time);
++            $self->setAttributeField($target, $eeprom_name, "writePageSize",
++                $page_size);
++
++            # Populate EEPROM for dimm
++            $self->setAttributeField($target_parent, $eeprom_name, "byteAddrOffset",
++                $offset);
++            $self->setAttributeField($target_parent, $eeprom_name, "maxMemorySizeKB",
++                $memory_size);
++            $self->setAttributeField($target_parent, $eeprom_name, "writeCycleTime",
++                $cycle_time);
++            $self->setAttributeField($target_parent, $eeprom_name, "writePageSize",
++                $page_size);
++
++            # spd only child is i2c-slave, which contains devAddr info
++            foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
++            {
++                $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
++                # Populate EEPROM for dimm
++                $self->setAttributeField($target_parent, $eeprom_name, "devAddr",
++                    $address);
++
++                # Populate EEPROM for ocmb
++                $self->setAttributeField($target, $eeprom_name, "devAddr",
++                    $address);
++            }
++        } # end if ($type eq "chip-spd-device") ...
++        elsif ($type eq "chip-vreg-generic")
++        {
++            push(@pmic_array, $child);
++            foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
++            {
++                $type = $self->getTargetType($i2c_slave);
++                # pmic has child i2c_slave which contains the device address
++                if ($type eq "unit-i2c-slave")
++                {
++                    $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
++
++                    # Populate FAPI for pmic
++                    $self->setAttributeField($child, $fapi_name, "devAddr",
++                        $address);
++                    last;
++                }
++            }
++        } # end elsif ($type eq "chip-vreg-generic")
++        elsif ($type eq "chip-ocmb")
++        {
++            foreach my $i2c_slave (@{ $self->getTargetChildren($child) })
++            {
++                # ocmb has multiple i2c-slaves, so we query with instance_name
++                my $instance_name = $self->getInstanceName($i2c_slave);
++                if ($instance_name eq "i2c-ocmb")
++                {
++                    $address = $self->getAttribute($i2c_slave, "I2C_ADDRESS");
++
++                    # Populate FAPI for ocmb
++                    $self->setAttributeField($target, $fapi_name, "devAddr",
++                        $address);
++                    last;
++                }
++            }
++        } # end elsif ($type eq "chip-ocmb")
++    } # end foreach my $child ...
++
++        # Get data from i2c-master-omi, which connects to the i2c_mux PCA9847
++    my $conn = $self->findConnectionsByDirection($target, "I2C", "", 1);
++    if ($conn ne "")
++    {
++        # There exists multiple i2c bus connections with chip-ocmb
++        # They are all the same connections so we just take the first one
++        # The mux channel has the i2cMuxBusSelector
++        my $conn_source = @{$conn->{CONN}}[0]->{SOURCE};
++# TODO FIX ROLAND
++# Will fix later in the process
++# ROLAND causing errors:
++# ERROR: getAttribute(/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0/i2c-master-op3b,MUX_CHANNEL) | Attribute not defined
++# I only found MUX_CHANNEL on attributes /sys-0/node-0/nisqually-0/PCA9849-[0-7]/PCA9849.i2cm-[0..3]
++#
++#        my $mux = $self->getAttribute($conn_source, "MUX_CHANNEL");
++        my $mux = 0;
++
++        # Parent PCA9848 determines the mux path
++        my $parent = $self->getTargetParent($conn_source);
++        my $parent_pos = $self->getAttribute($parent, "POSITION");
++        my $i2c_mux_path = "physical:sys-0/node-0/i2c_mux-$parent_pos";
++
++        # pmics and ocmb all grab FRU_ID from parent dimm
++        my $fru = $self->getAttribute($target_parent, "FRU_ID");
++
++        my $master_i2c = $self->findConnectionsByDirection($self->getTargetParent($conn_source), "I2C", "", 1);
++        if ($master_i2c ne "")
++        {
++            # There exists multiple i2c bus connections with the PCA9847 i2c_mux
++            # They are all the same connections so we just take the first one
++            $master_i2c = @{$master_i2c->{CONN}}[0];
++            # i2c-master-omi source which has data we need
++            my $source = $master_i2c->{SOURCE};
++            my $dest = $master_i2c->{DEST};
++            my $engine = $self->getAttribute($source, "I2C_ENGINE");
++            my $port = $self->getAttribute($source, "I2C_PORT");
++
++            # Populate FAPI for ocmb
++            $self->setAttributeField($target, $fapi_name, "engine",
++                $engine);
++            $self->setAttributeField($target, $fapi_name, "port",
++                $port);
++            $self->setAttributeField($target, $fapi_name, "i2cMuxBusSelector",
++                $mux);
++            $self->setAttributeField($target, $fapi_name, "i2cMuxPath",
++                $i2c_mux_path);
++            $self->setAttribute($target, "FRU_ID",
++                $fru);
++
++            # Populate EEPROM for ocmb
++            $self->setAttributeField($target, $eeprom_name, "i2cMuxPath",
++                $i2c_mux_path);
++            $self->setAttributeField($target, $eeprom_name, "engine",
++                $engine);
++            $self->setAttributeField($target, $eeprom_name, "port",
++                $port);
++            $self->setAttributeField($target, $eeprom_name, "i2cMuxBusSelector",
++                $mux);
++
++            # Populate FAPI for pmics
++            foreach my $pmic (@pmic_array)
++            {
++                $self->setAttributeField($pmic, $fapi_name, "engine",
++                    $engine);
++                $self->setAttributeField($pmic, $fapi_name, "port",
++                    $port);
++                $self->setAttributeField($pmic, $fapi_name, "i2cMuxBusSelector",
++                    $mux);
++                $self->setAttributeField($pmic, $fapi_name, "i2cMuxPath",
++                    $i2c_mux_path);
++                $self->setAttribute($pmic, "FRU_ID",
++                    $fru);
++            }
++
++            # Populate EEPROM for dimm
++            $self->setAttributeField($target_parent, $eeprom_name, "engine",
++                $engine);
++            $self->setAttributeField($target_parent, $eeprom_name, "port",
++                $port);
++            $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxBusSelector",
++                $mux);
++            $self->setAttributeField($target_parent, $eeprom_name, "i2cMuxPath",
++                $i2c_mux_path);
++            $self->setAttribute($target_parent, "FRU_ID",
++                $fru);
++        } # end if ($master_i2c  ne "")
++    } # end if ($conn ne "")
++}
++
++#--------------------------------------------------
++# @brief The end of the executable elements of this PERL module
++#
++# @details Don't forget to return the true value from this file
++#--------------------------------------------------
+ 1;
+ 
+ =head1 NAME
+diff --git a/src/usr/targeting/common/processMrw.pl b/src/usr/targeting/common/processMrw.pl
+index 7a63791..cd84b14 100755
+--- a/src/usr/targeting/common/processMrw.pl
++++ b/src/usr/targeting/common/processMrw.pl
+@@ -24,6 +24,9 @@
+ #
+ # IBM_PROLOG_END_TAG
+ 
++###############################################################################
++# Include these libraries
++###############################################################################
+ use strict;
+ use XML::Simple;
+ use Data::Dumper;
+@@ -32,112 +35,168 @@ use Math::BigInt;
+ use Getopt::Long;
+ use File::Basename;
+ 
+-use constant HZ_PER_KHZ=>1000;
+-use constant MAX_MCS_PER_PROC => 4; # 4 MCS per Nimbus
+ 
++###############################################################################
++# Define some global constants
++###############################################################################
+ my $VERSION = "1.0.0";
++my $targetObj = Targets->new;
+ 
+-my $force           = 0;
+-my $serverwiz_file  = "";
+-my $version         = 0;
+-my $debug           = 0;
+-my $report          = 0;
+-my $sdr_file        = "";
+-my $build           = "hb";
+-my $system_config   = "";
+-my $output_filename = "";
+-
+-# Map the OMI instance to its corresponding OMIC parent
+-my %omi_map         = (4  => "omic-0",
+-                       5  => "omic-0",
+-                       6  => "omic-0",
+-                       7  => "omic-1",
+-                       2  => "omic-1",
+-                       3  => "omic-1",
+-                       0  => "omic-2",
+-                       1  => "omic-2",
+-                       12 => "omic-0",
+-                       13 => "omic-0",
+-                       14 => "omic-0",
+-                       15 => "omic-1",
+-                       10 => "omic-1",
+-                       11 => "omic-1",
+-                       8  => "omic-2",
+-                       9  => "omic-2");
++# Define a true an false keyword
++use constant { true => 1, false => 0 };
++
++use constant HZ_PER_KHZ=>1000;
++use constant MAX_MCS_PER_PROC => 4; # 4 MCS per Nimbus
+ 
+ # TODO RTC:170860 - Remove this after dimm connector defines VDDR_ID
+-my $num_voltage_rails_per_proc = 1;
+-
+-GetOptions(
+-    "build=s" => \$build,
+-    "f"   => \$force,             # numeric
+-    "x=s" => \$serverwiz_file,    # string
+-    "d"   => \$debug,
+-    "c=s" => \$system_config,      #string
+-    "o=s" => \$output_filename,   #string
+-    "v"   => \$version,
+-    "r"   => \$report,
+-  )                               # flag
+-  or printUsage();
+-
+-if ($version == 1)
+-{
+-    die "\nprocessMrw.pl\tversion $VERSION\n";
+-}
++my $NUM_VOLTAGE_RAILS_PER_PROC = 1;
+ 
+-if ($serverwiz_file eq "")
+-{
+-    printUsage();
+-}
++## Used to setup GPU sensors on processors
++# key: OBUS slot target,
++# value: (GPU#, Function, Temp, MemTemp IPMI name/ids,
++my %GPU_SENSORS;
+ 
+-$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
++# key: OBUS slot string
++# value: processor target string
++my %SLOT_TO_PROC;
+ 
+-my $targetObj = Targets->new;
+-if ($force == 1)
++our %hwsvmrw_plugins;
++
++###############################################################################
++# The starting point for this script
++###############################################################################
++main($targetObj);
++
++sub main
+ {
+-    $targetObj->{force} = 1;
++    my $targetObj = shift;
++
++    # Extract the caller's options off the command and validate.
++    # Will exit if options are not valid.
++    getAndValidateCallerInputOptions();
++
++
++    # Run tests if asked to do so
++    if ($targetObj->{run_self_test} == 1)
++    {
++        runTests($targetObj);
++        return 0;
++    }
++
++    # Load the XML and process the file, extracting targets and associating
++    # attributes, with their data, to the targets
++    loadXmlFile();
++
++    if ($targetObj->{build} eq "fsp")
++    {
++        doFspBuild();
++    }
++
++    # Process the targets - set some needed attribute values
++    processTargets();
++
++    # Check for errors in the targets
++    errorCheckTheTargets($targetObj);
++
++    # Write the results of processing the targets to an XML file
++    writeResultsToXml($targetObj);
+ }
+-if ($debug == 1)
++
++###############################################################################
++# Supporting subroutines
++###############################################################################
++#--------------------------------------------------
++# @brief Extract caller's command line options
++#
++# @details Extract caller's command line options and
++#          validate them.  If valid then store in the
++#          global Target object for easy retrieval.
++#          If options are not valid, then print
++#          usage statement and exit script.
++#--------------------------------------------------
++sub getAndValidateCallerInputOptions
+ {
+-    $targetObj->{debug} = 1;
+-}
++    # Local variables, and their defaults, to cache the command line options to
++    my $build           = "hb";
++    my $force           = 0;
++    my $serverwiz_file  = "";
++    my $debug           = 0;
++    my $system_config   = "";
++    my $output_file     = "";
++    my $version         = 0;
++    my $report          = 0;
++    my $run_self_test   = 0;
++
++    # Grab the user's command line options.  If options not recognized
++    # print usage statement and exit script.
++    GetOptions(
++        "build=s" => \$build,      # string
++        "f"   => \$force,          # numeric
++        "x=s" => \$serverwiz_file, # string
++        "d"   => \$debug,          # flag
++        "c=s" => \$system_config,  # string
++        "o=s" => \$output_file,    # string
++        "v"   => \$version,        # flag
++        "r"   => \$report,         # flag
++        "t"   => \$run_self_test,  # flag
++      )
++      or printUsage();
++
++    # Display current version of file
++    if ($version == 1)
++    {
++        die "\nprocessMrw.pl\tversion $VERSION\n";
++    }
++
++    # If caller did not specify an input file, then print usage and die
++    if ($serverwiz_file eq "")
++    {
++        printUsage();
++    }
++
++    # Save the caller's input options to global storage for easy retrieval
++    $targetObj->{build} = $build;
++    $targetObj->{force} = $force;
++    $targetObj->{serverwiz_file} = $serverwiz_file;
++    $targetObj->{serverwiz_dir} = dirname($serverwiz_file);
++    $targetObj->{debug} = $debug;
++    $targetObj->{system_config} = $system_config;
++    $targetObj->{output_file} = $output_file;
++    $targetObj->setVersion($VERSION);
++    $targetObj->{report} = $report;
++    $targetObj->{run_self_test} = $run_self_test;
++
++} # end getAndValidateCallerInputOptions
++
++# loadXmlFile
++sub loadXmlFile
++{
++    $XML::Simple::PREFERRED_PARSER = 'XML::Parser';
++    $targetObj->loadXML($targetObj->{serverwiz_file});
+ 
+-$targetObj->setVersion($VERSION);
+-my $xmldir = dirname($serverwiz_file);
+-$targetObj->loadXML($serverwiz_file);
++    my $str=sprintf(
++        " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
++        "Sensor Name","FRU Name","Ent ID","Type","Evt Type","ID","Inst","FRU",
++        "HUID","Target");
++
++    $targetObj->writeReport($str);
++    my $str=sprintf(
++        " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
++        "------------------------------","----------",
++        "------","----","---------","----","----","----","----------",
++        "----------");
++
++    $targetObj->writeReport($str);
++} # end loadXmlFile
+ 
+-our %hwsvmrw_plugins;
+ # FSP-specific functions
+-if ($build eq "fsp")
++sub doFspBuild
+ {
+     eval ("use processMrw_fsp; return 1;");
+     processMrw_fsp::return_plugins();
+-}
+-
+-my $str=sprintf(
+-    " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
+-    "Sensor Name","FRU Name","Ent ID","Type","Evt Type","ID","Inst","FRU",
+-    "HUID","Target");
++} # end doFspBuild
+ 
+-$targetObj->writeReport($str);
+-my $str=sprintf(
+-    " %30s | %10s | %6s | %4s | %9s | %4s | %4s | %4s | %10s | %s\n",
+-    "------------------------------","----------",
+-    "------","----","---------","----","----","----","----------",
+-    "----------");
+-
+-$targetObj->writeReport($str);
+-
+-########################
+-## Used to setup GPU sensors on processors
+-my %G_gpu_sensors;
+-# key: obusslot target,
+-# value: (GPU#, Function, Temp, MemTemp IPMI name/ids,
+ 
+-my %G_slot_to_proc;
+-# key: obusslot string
+-# value: processor target string
+-#########################
+ 
+ # convert a number string into a bit-position number
+ # example:  "0x02" -->  0b0100 = 4
+@@ -151,7 +210,7 @@ sub numToBitPositionNum
+     return $newNum;
+ }
+ 
+-# Used to populate G_gpu_sensors hash of array references
++# Used to populate GPU_SENSORS hash of array references
+ #
+ # Each array reference will be composed of 3 sensors +
+ # board cfg ID which together makes up a GPU.
+@@ -167,7 +226,7 @@ sub addSensorToGpuSensors
+     my $GPU_SENSORS_TEMP_OFFSET = 2;
+     my $GPU_SENSORS_MEM_TEMP_OFFSET = 4;
+ 
+-    my $rSensorArray = $G_gpu_sensors{$obusslot_str};
++    my $rSensorArray = $GPU_SENSORS{$obusslot_str};
+     unless ($rSensorArray) {
+         $rSensorArray = [ "0xFFFF","0xFF","0xFFFF","0xFF",
+                           "0xFFFF","0xFF","0x00" ];
+@@ -192,11 +251,11 @@ sub addSensorToGpuSensors
+         $rSensorArray->[$GPU_SENSORS_TEMP_OFFSET+1] = $sensorID;
+     }
+ 
+-    $G_gpu_sensors{$obusslot_str} = $rSensorArray;
++    $GPU_SENSORS{$obusslot_str} = $rSensorArray;
+ }
+ 
+ 
+-# Populates the G_slot_to_proc hash and updates the cfgID in G_gpu_sensors
++# Populates the SLOT_TO_PROC hash and updates the cfgID in GPU_SENSORS
+ # This is how we map the obusslot to the GPU sensors
+ sub addObusCfgToGpuSensors
+ {
+@@ -205,14 +264,14 @@ sub addObusCfgToGpuSensors
+ 
+     my $foundSlot = 0;
+ 
+-    $G_slot_to_proc{$obusslot_str} = $proc_target;
++    $SLOT_TO_PROC{$obusslot_str} = $proc_target;
+ 
+-    foreach my $obusslot (keys %G_gpu_sensors)
++    foreach my $obusslot (keys %GPU_SENSORS)
+     {
+         if ($obusslot =~ m/$obusslot_str/)
+         {
+             # Add in the cfg number
+-            my $rSensorArray = $G_gpu_sensors{$obusslot_str};
++            my $rSensorArray = $GPU_SENSORS{$obusslot_str};
+             $rSensorArray->[$GPU_SENSORS_OBUS_CFG_OFFSET] =
+                  sprintf("0x%02X",
+                         (oct($rSensorArray->[$GPU_SENSORS_OBUS_CFG_OFFSET]) |
+@@ -225,10 +284,10 @@ sub addObusCfgToGpuSensors
+     {
+         print STDOUT sprintf("%s:%d ", __FILE__,__LINE__);
+         print STDOUT "Found obus slot ($obusslot_str - processor $proc_target)".
+-                     " not in G_gpu_sensors hash\n";
++                     " not in GPU_SENSORS hash\n";
+ 
+         my $cfg_bit_num = numToBitPositionNum($cfg);
+-        $G_gpu_sensors{$obusslot_str} =
++        $GPU_SENSORS{$obusslot_str} =
+             ["0xFFFF","0xFF","0xFFFF","0xFF","0xFFFF",
+              "0xFF", sprintf("0x02X",oct($cfg_bit_num))];
+     }
+@@ -273,17 +332,207 @@ sub isMultiTpmSystem
+ }
+ 
+ #--------------------------------------------------
+-## loop through all targets and do stuff
+-my @targets = sort keys %{ $targetObj->getAllTargets() };
+-my $isMultiTpmSys = isMultiTpmSystem(\@targets);
+-foreach my $target (@targets)
++# @brief Loop through all targets and set attributes as needed
++#
++# @param [in] $targetObj - The global target object.
++#--------------------------------------------------
++sub processTargets
++{
++    my @targets = sort keys %{ $targetObj->getAllTargets() };
++    my $isMultiTpmSys = isMultiTpmSystem(\@targets);
++    foreach my $target (@targets)
++{
++        my $type = $targetObj->getType($target);
++        if ($type eq "SYS")
++        {
++            processSystem($targetObj, $target);
++
++            my $maxComputeNodes  = get_max_compute_nodes($targetObj , $target);
++            $targetObj->setAttribute($target, "MAX_COMPUTE_NODES_PER_SYSTEM", $maxComputeNodes);
++
++            #handle enumeration changes
++            my $enum_val = $targetObj->getAttribute($target,"PROC_FABRIC_PUMP_MODE");
++            if ( $enum_val =~ /MODE1/i)
++            {
++                $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_NODE");
++            }
++            elsif ( $enum_val =~ /MODE2/i)
++            {
++                $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_GROUP");
++            }
++        }
++        elsif ($type eq "PROC")
++        {
++            processProcessor($targetObj, $target);
++            if ($targetObj->{build} eq "fsp")
++            {
++                do_plugin("fsp_proc", $targetObj, $target);
++            }
++        }
++        elsif ($type eq "APSS")
++        {
++            processApss($targetObj, $target);
++        }
++
++        # @TODO RTC: 189374 Remove multiple TPMs filter when all platforms' MRW
++        # supports dynamically determining the processor driving it.
++        elsif (($type eq "TPM") && $isMultiTpmSys)
++        {
++            processTpm($targetObj, $target);
++        }
++        elsif ($type eq "POWER_SEQUENCER")
++        {
++            my $target_type = $targetObj->getTargetType($target);
++
++            # Strip off the chip- part of the target type name
++            $target_type =~ s/chip\-//g;
++
++            # Currently only UCD9090 and UCD90120A on FSP systems are supported.
++            # All other UCD types are skipped.
++            if (($target_type eq "UCD9090")
++                || ($target_type eq "UCD90120A"))
++            {
++                processUcd($targetObj, $target);
++            }
++        }
++        elsif ($type eq "OCMB_CHIP")
++        {
++            processOcmbChip($targetObj, $target);
++        }
++
++        # Once processing of the target type is complete, remove
++        # deprecated and un-needed attributes for this type
++        pruneTargetAttributes($targetObj, $target, $type);
++
++        processIpmiSensors($targetObj,$target);
++    }  # end foreach my $target (@targets)
++
++
++    if ($targetObj->{build} eq "fsp")
++    {
++        processMrw_fsp::loadFSP($targetObj);
++    }
++} # end processTargets
++
++#--------------------------------------------------
++# @brief Check the processed targets for errors
++#
++# @param [in] $targetObj - The global target object.
++#--------------------------------------------------
++sub errorCheckTheTargets
+ {
+-    my $type = $targetObj->getType($target);
++    my $targetObj = shift;
++
++# TODO FIX ROLAND
++# Will fix later in the process
++# check topology
++# ROLAND Having issues with the topology:
++# ERROR: Fabric topology invalid.  2 targets have same FABRIC_TOPOLOGY_ID (0x0)
++# Once resolved, add this check back in
++# The MRW XML has 2 procs: power10-0 of type chip-processor-power10 and
++#                          power10-1 of type chip-processor-power10 and
++# In the loadXmlFile method, it produces 4 procs, 2 on a socket:
++#  '/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0';
++#  '/sys-0/node-0/nisqually-0/proc_socket-1/godel-0/power10-0';
++#  '/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-1';
++#  '/sys-0/node-0/nisqually-0/proc_socket-1/godel-0/power10-1';
++#     For both power10-0 procs it uses topologoy ID 0
++#     For both power10-1 procs it uses topologoy ID 1
++#       So this end up in duplicates being used
++
++#    foreach my $n (keys %{$targetObj->{TOPOLOGY}})
++#    {
++#        if ($targetObj->{TOPOLOGY}->{$n} > 1)
++#        {
++#            print "ERROR: Fabric topology invalid.  2 targets have same ".
++#                  "FABRIC_TOPOLOGY_ID ($n)\n";
++#            $targetObj->myExit(3);
++#        }
++#    }
++
++    foreach my $target (keys %{ $targetObj->getAllTargets() })
++    {
++    # TODO FIX ROLAND
++    # Will fix later in the process
++    # ROLAND Having issues with power10-0 so wrapped errorCheck with if statement:
++    # ERROR: EEPROM_VPD_PRIMARY_INFO/devAddr attribute is invalid (Target=/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0)
++    #	I2C connection to target is not defined
++    ## Once resolved, will remove if statement
++        if ($target != "/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0")
++        {
++            errorCheck($targetObj, $target);
++        }
++    }
++} # end sub errorCheckTheTargets
++
++#--------------------------------------------------
++# @brief Write out the results to an XML file
++#
++# @param [in] $targetObj - The global target object.
++#--------------------------------------------------
++sub writeResultsToXml
++{
++    my $targetObj = shift;
++
++    my $xml_fh;
++    my $filename;
++    my $config_str = $targetObj->{system_config};
++
++    #If user did not specify the output filename, then build one up by using
++    #config and build parameters
++    if ($targetObj->{output_file} eq "")
++    {
++        if ($config_str ne "")
++        {
++            $config_str = "_" . $config_str;
++        }
++
++        $filename = $targetObj->{serverwiz_dir} . "/" . $targetObj->getSystemName() . $config_str . "_" . $targetObj->{build} . ".mrw.xml";
++    }
++    else
++    {
++        $filename = $targetObj->{output_file};
++    }
++
++    print "Creating XML: $filename\n";
++    open($xml_fh, ">$filename") || die "Unable to create: $filename";
++
++    $targetObj->printXML($xml_fh, "top", $targetObj->{build});
++    close $xml_fh;
++    if (!$targetObj->{errorsExist})
++    {
++        ## optionally print out report
++        if ($targetObj->{report})
++        {
++            print "Writing report to: ".$targetObj->{report_filename}."\n";
++            $targetObj->writeReportFile();
++        }
++        print "MRW created successfully!\n";
++    }
++} # end sub writeResultsToXml
++
++#--------------------------------------------------
++# @brief Remove attributes associated with target.
++#        Either because they have been deprecated
++#        or simply not used/needed.
++# @param[in] $targetObj - The global target object
++#                         blob
++# @param[in] $target - The target to remove attributes
++#                      from
++# @param[in] $type -   The type of the target
++#
++# TODO RTC: 178351 Remove depricated Attribute from HB XML
++# these are obsolete
++#
++#--------------------------------------------------
++sub pruneTargetAttributes
++{
++    my $targetObj = shift;
++    my $target    = shift;
++    my $type      = shift;
++
+     if ($type eq "SYS")
+     {
+-        processSystem($targetObj, $target);
+-        #TODO RTC: 178351 Remove depricated Attribute from HB XML
+-        #these are obsolete
+         $targetObj->deleteAttribute($target,"FUSED_CORE_MODE");
+         $targetObj->deleteAttribute($target,"MRW_CDIMM_MASTER_I2C_TEMP_SENSOR_ENABLE");
+         $targetObj->deleteAttribute($target,"MRW_CDIMM_SPARE_I2C_TEMP_SENSOR_ENABLE");
+@@ -302,31 +551,9 @@ foreach my $target (@targets)
+         $targetObj->deleteAttribute($target,"SYSTEM_WOF_ENABLED");
+         $targetObj->deleteAttribute($target,"VDM_ENABLE");
+         $targetObj->deleteAttribute($target,"CHIP_HAS_SBE");
+-
+-        my $maxComputeNodes  = get_max_compute_nodes($targetObj , $target);
+-        $targetObj->setAttribute($target, "MAX_COMPUTE_NODES_PER_SYSTEM", $maxComputeNodes);
+-
+-        #handle enumeration changes
+-        my $enum_val = $targetObj->getAttribute($target,"PROC_FABRIC_PUMP_MODE");
+-        if ( $enum_val =~ /MODE1/i)
+-        {
+-            $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_NODE");
+-        }
+-        elsif ( $enum_val =~ /MODE2/i)
+-        {
+-            $targetObj->setAttribute($target,"PROC_FABRIC_PUMP_MODE","CHIP_IS_GROUP");
+-        }
+-
+     }
+     elsif ($type eq "PROC")
+     {
+-        processProcessor($targetObj, $target);
+-        if ($build eq "fsp")
+-        {
+-            do_plugin("fsp_proc", $targetObj, $target);
+-        }
+-        #TODO RTC: 178351 Remove depricated Attribute from HB XML
+-        #these are obsolete
+         $targetObj->deleteAttribute($target,"CHIP_HAS_SBE");
+         $targetObj->deleteAttribute($target,"FSI_GP_REG_SCOM_ACCESS");
+         $targetObj->deleteAttribute($target,"I2C_SLAVE_ADDRESS");
+@@ -349,18 +576,8 @@ foreach my $target (@targets)
+         $targetObj->deleteAttribute($target,"PROC_SECURITY_SETUP_VECTOR");
+         $targetObj->deleteAttribute($target,"SBE_SEEPROM_I2C_ADDRESS_BYTES");
+     }
+-    elsif ($type eq "APSS")
+-    {
+-        processApss($targetObj, $target);
+-    }
+-    elsif ($type eq "MEMBUF")
+-    {
+-        processMembuf($targetObj, $target);
+-        $targetObj->deleteAttribute($target,"CEN_MSS_VREF_CAL_CNTL");
+-    }
+     elsif ($type eq "PHB")
+     {
+-        #TODO RTC: 178351 Remove depricated Attribute from HB XML
+         $targetObj->deleteAttribute($target,"DEVICE_ID");
+         $targetObj->deleteAttribute($target,"HDDW_ORDER");
+         $targetObj->deleteAttribute($target,"MAX_POWER");
+@@ -376,91 +593,7 @@ foreach my $target (@targets)
+         $targetObj->deleteAttribute($target,"SLOT_NAME");
+         $targetObj->deleteAttribute($target,"VENDOR_ID");
+     }
+-    # @TODO RTC: 189374 Remove multiple TPMs filter when all platforms' MRW
+-    # supports dynamically determining the processor driving it.
+-    elsif (($type eq "TPM") && $isMultiTpmSys)
+-    {
+-        processTpm($targetObj, $target);
+-    }
+-    elsif ($type eq "POWER_SEQUENCER")
+-    {
+-        my $target_type = $targetObj->getTargetType($target);
+-
+-        # Strip off the chip- part of the target type name
+-        $target_type =~ s/chip\-//g;
+-
+-        # Currently only UCD9090 and UCD90120A on FSP systems are supported.
+-        # All other UCD types are skipped.
+-        if (($target_type eq "UCD9090")
+-            || ($target_type eq "UCD90120A"))
+-        {
+-            processUcd($targetObj, $target);
+-        }
+-    }
+-    elsif ($type eq "OCMB_CHIP")
+-    {
+-        processOcmbChip($targetObj, $target);
+-    }
+-
+-    processIpmiSensors($targetObj,$target);
+-}
+-
+-if ($build eq "fsp")
+-{
+-    processMrw_fsp::loadFSP($targetObj);
+-}
+-## check topology
+-foreach my $n (keys %{$targetObj->{TOPOLOGY}}) {
+-    if ($targetObj->{TOPOLOGY}->{$n} > 1) {
+-        print "ERROR: Fabric topology invalid.  2 targets have same ".
+-              "FABRIC_TOPOLOGY_ID ($n)\n";
+-        $targetObj->myExit(3);
+-    }
+-}
+-## check for errors
+-foreach my $target (keys %{ $targetObj->getAllTargets() })
+-{
+-    errorCheck($targetObj, $target);
+-}
+-
+-#--------------------------------------------------
+-## write out final XML
+-my $xml_fh;
+-my $filename;
+-my $config_str = $system_config;
+-
+-#If user did not specify the output filename, then build one up by using
+-#config and build parameters
+-if ($output_filename eq "")
+-{
+-    if ($config_str ne "")
+-    {
+-        $config_str = "_" . $config_str;
+-    }
+-
+-    $filename = $xmldir . "/" . $targetObj->getSystemName() . $config_str . "_" . $build . ".mrw.xml";
+-}
+-else
+-{
+-    $filename = $output_filename;
+-}
+-
+-print "Creating XML: $filename\n";
+-open($xml_fh, ">$filename") || die "Unable to create: $filename";
+-
+-$targetObj->printXML($xml_fh, "top", $build);
+-close $xml_fh;
+-if (!$targetObj->{errorsExist})
+-{
+-    ## optionally print out report
+-    if ($report)
+-    {
+-        print "Writing report to: ".$targetObj->{report_filename}."\n";
+-        $targetObj->writeReportFile();
+-    }
+-    print "MRW created successfully!\n";
+-}
+-
++}  # end pruneTargetAttributes
+ 
+ #--------------------------------------------------
+ #--------------------------------------------------
+@@ -493,7 +626,7 @@ sub processSystem
+     my $system_name = $targetObj->getAttribute($target,"SYSTEM_NAME");
+     if ($system_name =~ /ZAIUS/i)
+     {
+-        $num_voltage_rails_per_proc = 2;
++        $NUM_VOLTAGE_RAILS_PER_PROC = 2;
+     }
+ 
+     # TODO RTC:182764 -- right now there is no support for CDIMMs. So,
+@@ -940,9 +1073,9 @@ sub processUcd
+ }
+ 
+ #--------------------------------------------------
+-## Processor
+-##
+-
++# @brief Process processors
++#
++#--------------------------------------------------
+ sub processProcessor
+ {
+     my $targetObj = shift;
+@@ -998,7 +1131,6 @@ sub processProcessor
+         }
+     }
+ 
+-
+     # I2C arrays
+     my @engine = ();
+     my @port = ();
+@@ -1051,11 +1183,11 @@ sub processProcessor
+             #   contain this information and this can be removed
+             my $socket_pos =  $targetObj->getAttribute($socket_target,
+                                   "POSITION");
+-            if ($num_voltage_rails_per_proc > 1)
++            if ($NUM_VOLTAGE_RAILS_PER_PROC > 1)
+             {
+                 my $mcbist_pos = $targetObj->getAttribute($child, "CHIP_UNIT");
+                 $targetObj->setAttribute($child, "VDDR_ID",
+-                         $socket_pos*$num_voltage_rails_per_proc + $mcbist_pos);
++                         $socket_pos*$NUM_VOLTAGE_RAILS_PER_PROC + $mcbist_pos);
+             }
+             else
+             {
+@@ -1097,16 +1229,16 @@ sub processProcessor
+ 
+     # Add GPU sensors to processor
+     my @aGpuSensors = ();
+-    foreach my $obusslot (sort keys %G_gpu_sensors)
++    foreach my $obusslot (sort keys %GPU_SENSORS)
+     {
+         # find matching obusslot to processor
+-        my $proc_target = $G_slot_to_proc{$obusslot};
++        my $proc_target = $SLOT_TO_PROC{$obusslot};
+ 
+         # if a processor target is found and it is the same as this target
+         if ($proc_target && ($target =~ m/$proc_target/))
+         {
+             # Add this GPU's sensors to the processor's array of GPU sensors
+-            push (@aGpuSensors, @{ $G_gpu_sensors{$obusslot} });
++            push (@aGpuSensors, @{ $GPU_SENSORS{$obusslot} });
+         }
+     }
+     if (@aGpuSensors)
+@@ -1216,10 +1348,11 @@ sub processProcessor
+                              $targetObj->getAttribute($target,
+                                                       "FABRIC_CHIP_ID"));
+ 
+-    processMembufVpdAssociation($targetObj,$target);
++
+     #TODO RTC: 191762 -- Need a generic way to source FABRIC_GROUP_ID and
+     #FABRIC_CHIP_ID from the MRW and select the right value in processMRW
+     #based on the system configuration we are compiling for.
++    my $system_config = $targetObj->{system_config};
+     if ($system_config eq "w")
+     {
+         my $huid_str = $targetObj->getAttribute($target, "HUID");
+@@ -1412,36 +1545,21 @@ sub processI2cSpeeds
+     $targetObj->setAttribute($target,"I2C_BUS_SPEED_ARRAY",$bus_speed_attr);
+ }
+ 
+-################################
+-## Setup address map
+-
++#--------------------------------------------------
++# @brief Setup address map
++#--------------------------------------------------
+ sub setupBars
+ {
+     my $targetObj = shift;
+     my $target = shift;
+-    #--------------------------------------------------
+-    ## Setup BARs
+-
+-    #The topology ID is a 4 bit value that must be converted to
+-    #a 5-bit topology index before we can use it to calculate the
+-    #address offset.
+-    #The conversion method depends on the topology mode.
+-    my $topoId = $targetObj->getAttribute($target, "PROC_FABRIC_TOPOLOGY_ID");
+-    my $topoMode = $targetObj->getAttribute($target, "PROC_FABRIC_TOPOLOGY_MODE");
+-
+-    #Assume topo mode 1 (GGCC -> 0GGCC)
+-    my $topoIndex = $topoId;
+-
+-    #Check for topo mode 0
+-    if ($topoMode == 0)
+-    {
+-        # GGGC -> GGG0C
+-        $topoIndex = (($topoIndex & 0xE) << 1) | ($topoIndex & 0x1);
+-    }
+ 
+-    #keep track of which topology ID's have been used
++    # Keep track of which topology ID's have been used
++    my $topoId = getTopologyId($targetObj, $target);
+     $targetObj->{TOPOLOGY}->{$topoId}++;
+ 
++    # Get the topology index
++    my $topologyIndex = getTopologyIndex($targetObj, $target);
++
+     #P10 has a defined memory map for all configurations,
+     #these are the base addresses for topology ID 0 (group0-chip0).
+     my %bars=(  "FSP_BASE_ADDR"             => 0x0006030100000000,
+@@ -1466,9 +1584,147 @@ sub setupBars
+     {
+         my $i_base = Math::BigInt->new($bars{$bar});
+         my $value=sprintf("0x%016s",substr((
+-                        $i_base+$topoIndexOffset*$topoIndex)->as_hex(),2));
++                        $i_base+$topoIndexOffset*$topologyIndex)->as_hex(),2));
+         $targetObj->setAttribute($target,$bar,$value);
+     }
++}  # end setupBars
++
++#--------------------------------------------------
++# @brief Retrieve the fabric topolgy mode
++#
++# @details The fabric topology mode, attribute PROC_FABRIC_TOPOLOGY_MODE,
++#          is an attribute of the top level target (sys-0), but retrieving
++#          the value from the attribute returns a string (MODE0 or MODE1).
++#          This string is used to get the actual value, tied that mode,
++#          within the enumeration types.
++#
++# @param[in] $targetObj - The global target object, needed to get topology mode
++#
++# @return the numerical value of the topology mode in base 10
++#--------------------------------------------------
++sub getTopologyMode
++{
++    my $targetObj = shift;
++
++    use constant TOPOLOGY_MODE_ATTRIBUTE => "PROC_FABRIC_TOPOLOGY_MODE";
++
++    # Get topology mode from top level target
++    # Need to prepend "/" to the returned top level target because targets
++    # are mapped slightly different in the TARGETS hash vs the xml hash.
++    my $topologoyMode = $targetObj->getAttribute("/".$targetObj->{TOP_LEVEL},
++                                                 TOPOLOGY_MODE_ATTRIBUTE);
++
++    # Return the value of the mode as defined in
++    # enumeration type PROC_FABRIC_TOPOLOGY_MODE
++    # Convert the value from hex to base 10
++    return hex($targetObj->{xml}->{enumerationTypes}->{enumerationType}
++                      ->{PROC_FABRIC_TOPOLOGY_MODE}
++                      ->{enumerator}->{$topologoyMode}->{value});
++}
++
++#--------------------------------------------------
++# @brief Convert the topology ID to a topology index.
++#
++# @details  The topology ID is a 4 bit value that will be converted to a 5 bit
++#           topology index. The topology index is an index into the topology
++#           table.
++#           The conversion method depends on the topology mode.
++#                Mode      ID      index
++#               MODE 0 => GGGC --> GGG0C
++#               MODE 1 => GGCC --> GG0CC
++#
++# @param[in] $topologyId - The topology ID to convert to an index
++# @param[in] $topologyMode - The topology mode that determines the conversion
++#                            method. Needs to be a base 10 numeral value.
++#
++# @return a toplogy index, that is a base 10 numeral value.
++#--------------------------------------------------
++sub convertTopologyIdToIndex
++{
++    my $topologyId = shift;
++    my $topologyMode = shift;
++
++    use constant TOPOLOGY_MODE_1 => 1;
++
++    # Assume topology mode 0 (GGGC -> GGG0C)
++    my $groupMask = 0xE; # Use 0xE, 1110b, to extract 'GGG' from 'GGGC'
++    my $chipMask = 0x1;  # Use 0x1, 0001b, to extract 'C' from 'GGGC'
++
++    # If topology mode 1 (GGCC -> GG0CC)
++    if (TOPOLOGY_MODE_1 == $topologyMode)
++    {
++        $groupMask = 0xC; # Use 0xC, 1100b, to extract 'GG' from 'GGCC'
++        $chipMask = 0x3;  # Use 0x3, 0011b, to extract 'CC' from 'GGCC'
++    }
++
++    # Set topology index to topology ID before doing conversion
++    my $topologyIndex = $topologyId;
++
++    ## Turn the 4 bit topology ID into a 5 bit index
++    ## convert GGGC to GGG0C
++    ##      OR GGCC to GG0CC
++    # If group mask equal to 0xE (mode 0) then extract 'GGG' from 'GGGC':
++    #  1) GGGC & 0xE (1110b) returns GGG0 then shift to left (<< 1) to get GGG00
++    #  2) extract C from GGGC: GGGC & 0x1 (0001b) returns C
++    # If group mask equal to 0xC (mode 1) then extract 'GG' from 'GGCC':
++    #  1) GGCC & 0xC (1100b) returns GG00 then shift to left (<< 1) to get GG000
++    #  2) extract CC from GGCC: GGCC & 0x3 (0011b) returns CC
++    # Bitwise 'OR' 1 and 2 together to produce a 5 bit index value: GGG0C OR GG0CC
++    #    Index     =                  1                  'OR'               2
++    $topologyIndex = (($topologyIndex & $groupMask) << 1) | ($topologyIndex & $chipMask);
++
++    return ($topologyIndex);
++}
++
++#--------------------------------------------------
++# @brief Get the topology ID from processor
++#
++#
++# @param[in] $targetObj - The global target object, needed to get topology mode
++# @param[in] $processorTarget - The processor target, has the attribute topology ID
++#
++# @return topology ID, that is a base 10 numeral value.
++#--------------------------------------------------
++sub getTopologyId
++{
++    my $targetObj = shift;
++    my $processorTarget = shift;
++
++    use constant TOPOLOGY_ID_ATTRIBUTE => "PROC_FABRIC_TOPOLOGY_ID";
++
++    # Get the topology ID from the processor.
++    # Convert hex value to base 10 numerical value
++    return hex($targetObj->getAttribute($processorTarget,
++                                        TOPOLOGY_ID_ATTRIBUTE));
++
++}
++
++#--------------------------------------------------
++# @brief Get the topology index, an index into the topology table.
++#
++# @details The topology index needs to be calculated using the topology mode
++#          and the topology ID.  @see convertTopologyIdToIndex for
++#          more details
++#
++# @param[in] $targetObj - The global target object, needed to get topology mode
++# @param[in] $processorTarget - The processor target has the attribute topology ID
++#
++# @return a topology index, that is base 10 numeral value.
++#--------------------------------------------------
++sub getTopologyIndex
++{
++    my $targetObj = shift;
++    my $processorTarget = shift;
++
++    # Get the topology mode: MODE 0 (0) or MODE 1 (1)
++    my $topologyMode = getTopologyMode($targetObj);
++
++    # Get the topology ID from the processor.
++    my $topologyId = getTopologyId($targetObj, $processorTarget);
++
++    # Convert the topology ID to a topology index. The conversion method is
++    # based on the topology mode.
++    return (convertTopologyIdToIndex($topologyId, $topologyMode));
+ }
+ 
+ #--------------------------------------------------
+@@ -1572,10 +1828,14 @@ sub processEq
+         $targetObj->log($target,
+             "Processing EQ child: $child Type: $child_type");
+ 
+-        if ($child_type eq "EX")
++        if ($child_type eq "EQ")
+         {
+             processEx($targetObj, $child, $chip_unit);
+         }
++        elsif ($child_type eq "FC")
++        {
++            processFc($targetObj, $child, $chip_unit);
++        }
+     }
+ 
+     my $value = sprintf("0x%x",
+@@ -1584,6 +1844,35 @@ sub processEq
+     $targetObj->setAttribute( $target, "CHIPLET_ID", $value);
+ }
+ 
++## FC
++sub processFc
++{
++    my $targetObj        = shift;
++    my $target           = shift;
++    my $parent_chip_unit = shift;
++
++    foreach my $child (@{ $targetObj->getTargetChildren($target) })
++    {
++        my $child_type = $targetObj->getType($child);
++
++        $targetObj->log($target,
++            "Processing EX child: $child Type: $child_type");
++
++        if ($child_type eq "CORE")
++        {
++            processCore($targetObj, $child);
++        }
++    }
++
++    my $value = sprintf("0x%x",
++                        Targets::PERVASIVE_PARENT_EQ_OFFSET
++                        + $parent_chip_unit);
++
++    $targetObj->setAttribute( $target, "CHIPLET_ID", $value);
++}
++
++
++
+ ## EX
+ sub processEx
+ {
+@@ -1672,9 +1961,9 @@ sub processMcbist
+ ##
+ sub processMc
+ {
+-    # NOTE: OMI_INBAND_BAR_BASE_ADDR_OFFSET will be set for the MC                         
+-    # targets via a specific child OMI Target. View the                                    
+-    # processOmi function for further details.                                             
++    # NOTE: OMI_INBAND_BAR_BASE_ADDR_OFFSET will be set for the MC
++    # targets via a specific child OMI Target. View the
++    # processOmi function for further details.
+     my $targetObj    = shift;
+     my $target       = shift;
+ 
+@@ -1751,8 +2040,28 @@ sub processMcc
+ ##
+ sub processOmi
+ {
+-    my $mrwObj   = shift;
+-    my $omitarg      = shift;
++    my $mrwObj  = shift;
++    my $omitarg = shift;
++
++# TODO This may need to be updated if layout is different
++# ROLAND investigate this
++    # Map the OMI instance to its corresponding OMIC parent
++    my %omi_map = (4  => "omic-0",
++                   5  => "omic-0",
++                   6  => "omic-0",
++                   7  => "omic-1",
++                   2  => "omic-1",
++                   3  => "omic-1",
++                   0  => "omic-2",
++                   1  => "omic-2",
++                   12 => "omic-0",
++                   13 => "omic-0",
++                   14 => "omic-0",
++                   15 => "omic-1",
++                   10 => "omic-1",
++                   11 => "omic-1",
++                   8  => "omic-2",
++                   9  => "omic-2");
+ 
+     use integer;
+     # There are a total of eight OMI units on an MC unit. So, to
+@@ -1834,15 +2143,15 @@ sub processOmic
+ }
+ 
+ #--------------------------------------------------
+-## OCMB_CHIP
+-##
+-##
++# @brief OCMB_CHIP
++#
++#--------------------------------------------------
+ sub processOcmbChip
+ {
+     my $targetObj    = shift;
+     my $target       = shift;
+ 
+-    $targetObj->setEepromAttributesForAxone($targetObj, $target);
++    $targetObj->setEepromAttributesForDDIMs($target);
+ }
+ 
+ #-------------------------------------------------g
+@@ -2032,6 +2341,7 @@ sub processXbus
+         #For example, in wrap config, CONFIG_APPLY is expected to have "w"
+         #If "w" is not there, then we skip the connection and mark peers
+         #as NULL
++        my $system_config = $targetObj->{system_config};
+         if (($system_config eq $wrap_config && $config =~ /$wrap_config/) ||
+            ($system_config ne $wrap_config && $config =~ /$default_config/))
+         {
+@@ -2098,7 +2408,7 @@ sub processAbus
+     # A-bus connection has to be conisdered or not
+     # If user has passed 2N as argument, then we consider only those
+     # A-bus connections where token "2" is present
+-
++    my $system_config = $targetObj->{system_config};
+     if($system_config eq "2N" && $config =~ /$twonode/)
+     {
+         #Looking for Abus connections pertaining to 2 node system only
+@@ -2634,123 +2944,6 @@ sub processOcc
+     $targetObj->setAttribute($target,"OCC_MASTER_CAPABLE",$master_capable);
+ }
+ 
+-sub processMembufVpdAssociation
+-{
+-    my $targetObj = shift;
+-    my $target    = shift;
+-
+-    my $vpds=$targetObj->findConnections($target,"I2C","VPD");
+-    if ($vpds ne "" ) {
+-        my $vpd = $vpds->{CONN}->[0];
+-        my $membuf_assocs=$targetObj->findConnections($vpd->{DEST_PARENT},
+-                          "LOGICAL_ASSOCIATION","MEMBUF");
+-
+-        if ($membuf_assocs ne "") {
+-            foreach my $membuf_assoc (@{$membuf_assocs->{CONN}}) {
+-                my $membuf_target = $membuf_assoc->{DEST_PARENT};
+-                setEepromAttributes($targetObj,
+-                       "EEPROM_VPD_PRIMARY_INFO",$membuf_target,$vpd);
+-                my $index = $targetObj->getBusAttribute($membuf_assoc->{SOURCE},
+-                                $membuf_assoc->{BUS_NUM}, "ISDIMM_MBVPD_INDEX");
+-                $targetObj->setAttribute(
+-                            $membuf_target,"ISDIMM_MBVPD_INDEX",$index);
+-                $targetObj->setAttribute($membuf_target,
+-                            "VPD_REC_NUM",$targetObj->{vpd_num});
+-            }
+-        }
+-        my $group_assocs=$targetObj->findConnections($vpd->{DEST_PARENT},
+-                          "LOGICAL_ASSOCIATION","CARD");
+-
+-        if ($group_assocs ne "") {
+-            foreach my $group_assoc (@{$group_assocs->{CONN}}) {
+-                my $mb_target = $group_assoc->{DEST_PARENT};
+-                my $group_target = $targetObj->getTargetParent($mb_target);
+-                $targetObj->setAttribute($group_target,
+-                            "VPD_REC_NUM",$targetObj->{vpd_num});
+-            }
+-        }
+-        $targetObj->{vpd_num}++;
+-    }
+-}
+-
+-#--------------------------------------------------
+-## MEMBUF
+-##
+-## Finds I2C connections to DIMM and creates EEPROM attributes
+-## FYI:  I had to handle DMI busses in framework because they
+-## define affinity path
+-sub processMembuf
+-{
+-    my $targetObj = shift;
+-    my $membufTarg    = shift;
+-    if ($targetObj->isBadAttribute($membufTarg, "PHYS_PATH", ""))
+-    {
+-        ##dmi is probably not connected.  will get caught in error checking
+-        return;
+-    }
+-
+-    processMembufVpdAssociation($targetObj,$membufTarg);
+-
+-    ## find port mapping
+-    my %dimm_portmap;
+-    foreach my $child (@{$targetObj->getTargetChildren($membufTarg)})
+-    {
+-         if ($targetObj->getType($child) eq "MBA")
+-         {
+-             # find this MBA's position relative to the membuf
+-             my $mba_num = $targetObj->getAttribute($child,"MBA_NUM");
+-             # follow the DDR4 bus connection to find the 'ddr' targets
+-             my $ddrs = $targetObj->findConnections($child,"DDR4","");
+-
+-             if($ddrs eq "")
+-             {
+-                # on multi node system there is a possibility that either
+-                # DDR4 or DDR3 dimms are connected under a node
+-                my $ddrs = $targetObj->findConnections($child,"DDR3","");
+-             }
+-
+-             if ($ddrs ne "")
+-             {
+-                 foreach my $ddr (@{$ddrs->{CONN}})
+-                 {
+-                       my $port_num = $targetObj->getDimmPort($ddr->{SOURCE});
+-                       my $dimm_num = $targetObj->getDimmPos($ddr->{SOURCE});
+-                       my $map = oct("0b".$mba_num.$port_num.$dimm_num);
+-                       $dimm_portmap{$ddr->{DEST_PARENT}} = $map;
+-                 }
+-             }
+-         }
+-    }
+-
+-
+-    ## Process MEMBUF to DIMM I2C connections
+-    my @addr_map=('0','0','0','0','0','0','0','0');
+-    my $dimms=$targetObj->findConnections($membufTarg,"I2C","SPD");
+-    if ($dimms ne "") {
+-        foreach my $dimm (@{$dimms->{CONN}}) {
+-            my $dimm_target = $targetObj->getTargetParent($dimm->{DEST_PARENT});
+-            setEepromAttributes($targetObj,
+-                       "EEPROM_VPD_PRIMARY_INFO",$dimm_target,
+-                       $dimm);
+-
+-            my $field=getI2cMapField($targetObj,$dimm_target,$dimm);
+-            my $map = $dimm_portmap{$dimm_target};
+-
+-            if ($map eq "") {
+-                print "ERROR: $dimm_target doesn't map to a dimm/port\n";
+-                $targetObj->myExit(3);
+-            }
+-            $addr_map[$map] = $field;
+-        }
+-    }
+-    $targetObj->setAttribute($membufTarg,
+-            "MRW_MEM_SENSOR_CACHE_ADDR_MAP","0x".join("",@addr_map));
+-
+-    ## Update bus speeds
+-    processI2cSpeeds($targetObj,$membufTarg);
+-
+-    processPowerRails($targetObj, $membufTarg);
+-}
+ 
+ sub getI2cMapField
+ {
+@@ -2794,7 +2987,7 @@ sub getI2cMapField
+     return $hexfield;
+ }
+ 
+-#------------------------------------------------------------------------------
++#--------------------------------------------------
+ # I2C
+ #
+ sub processI2C
+@@ -3253,7 +3446,9 @@ sub get_max_compute_nodes
+ }
+ 
+ #--------------------------------------------------
+-## ERROR checking
++# @brief Error checking
++#
++#--------------------------------------------------
+ sub errorCheck
+ {
+     my $targetObj = shift;
+@@ -3363,9 +3558,9 @@ Options:
+              2N = special 2 node config with extra ABUS links
+              w = Special MST wrap config
+         -o = output filename
+-        -s [SDR XML file] = import SDRs
+         -r = create report and save to [system_name].rpt
+-        -v = version
++        -v = display current version
++        -t = run self test
+ ";
+     exit(1);
+ }
+@@ -3380,8 +3575,216 @@ sub do_plugin
+     {
+         $hwsvmrw_plugins{$step}(@_);
+     }
+-    elsif ($debug && ($build eq "fsp"))
++    elsif ($targetObj->{debug} && ($targetObj->{build} eq "fsp"))
++    {
++        print STDERR "build is $targetObj->{build} but no plugin for $step\n";
++    }
++}
++
++###############################################################################
++# Self tests
++###############################################################################
++#--------------------------------------------------
++# @brief The main procedure to run the tests
++#
++# @param[in] $targetObj - The global target object
++#--------------------------------------------------
++sub runTests
++{
++    print "\nRunning tests: \n\n";
++    my $targetObj = shift;
++
++    # Load the XML and process the file, extracting targets and associating
++    # attributes, with their data, to the targets
++    loadXmlFile();
++
++    # Process the targets, setting the targets attributes.
++    processTargets();
++
++    # Each one of the test build on each other, if one fails then no point in
++    # running the other
++    testGetTopologyMode($targetObj)   &&
++    testTopologyIdToTopologyIndex()   &&
++    testGetTopologyIndex($targetObj);
++}
++
++#--------------------------------------------------
++# @brief Test the method that gets the topology mode.
++#
++# @param[in] $targetObj - The global target object
++#
++# @return true if test passed, false other wise
++#--------------------------------------------------
++sub testGetTopologyMode
++{
++    print ">> Running testgetTopologyMode \n";
++    my $targetObj = shift;
++
++    my $testPassed = true;
++
++    use constant TOPOLOGY_MODE_ATTRIBUTE => "PROC_FABRIC_TOPOLOGY_MODE";
++    use constant TOPOLOGY_MODES => qw/ MODE0 MODE1 /;
++    my @topologyModes = (TOPOLOGY_MODES);
++
++    # Cache the current mode to restore later
++    my $persistMode = $targetObj->getAttribute("/".$targetObj->{TOP_LEVEL},
++                                               TOPOLOGY_MODE_ATTRIBUTE);
++
++    # Test getting the topology mode
++    foreach my $topologyMode (@topologyModes)
+     {
+-        print STDERR "build is $build but no plugin for $step\n";
++        $targetObj->setAttribute("/".$targetObj->{TOP_LEVEL},
++                                 TOPOLOGY_MODE_ATTRIBUTE,
++                                 $topologyMode);
++        my $topologyModeNumber = chop($topologyMode);
++        if (getTopologyMode($targetObj) != $topologyModeNumber)
++        {
++
++            $testPassed = false;
++            print "ERROR: Expected topology mode '$topologyModeNumber' but got " .
++                   getTopologyMode($targetObj) . "\n";
++        }
+     }
++
++    # Restore mode
++    $targetObj->setAttribute("/".$targetObj->{TOP_LEVEL},
++                             TOPOLOGY_MODE_ATTRIBUTE,
++                             $persistMode);
++
++    print "<< Running testgetTopologyMode: test " .
++          getPassFailString($testPassed) . "\n";
++
++    return $testPassed;
+ }
++
++#--------------------------------------------------
++# @brief Tests the conversion method that converts the topology ID,
++#        with given topology mode, to the topology index.
++#
++# @return true if test passed, false other wise
++#--------------------------------------------------
++sub testTopologyIdToTopologyIndex
++{
++    print ">> Running testTopologyIdToTopologyIndex \n";
++
++    my $testPassed = true;
++
++    # The different values expected when mode is 0 or 1
++    use constant TOPOLOGY_MODE_0_ARRAY => qw/ 0 1 4 5 8 9 12 13 16 17 20 21 24 25 28 29 /;
++    use constant TOPOLOGY_MODE_1_ARRAY => qw/ 0 1 2 3 8 9 10 11 16 17 18 19 24 25 26 27 /;
++
++    # The different topology modes
++    use constant TOPOLOGY_MODES => qw/ MODE0 MODE1 /;
++    my @topologyModes = (TOPOLOGY_MODES);
++
++    # Default with mode 0
++    my @toplogyModeArray = (TOPOLOGY_MODE_0_ARRAY);
++
++    # Test the conversion on the different IDs and modes
++    for my $topologyMode (@topologyModes)
++    {
++        my $topologyModeNumber = chop($topologyMode);
++        if (1 == $topologyModeNumber)
++        {
++            @toplogyModeArray = (TOPOLOGY_MODE_1_ARRAY);
++        }
++
++        # Needed variable
++        my $topologyIndex = 0;
++
++        # Iterate thru each permutation of the topology ID and
++        # test conversion to index
++        for (my $topologyId = 0; $topologyId < 16; ++$topologyId)
++        {
++            $topologyIndex = convertTopologyIdToIndex($topologyId,
++                                                      $topologyModeNumber);
++            if ($topologyIndex != $toplogyModeArray[$topologyId])
++            {
++                $testPassed = false;
++                print "ERROR: conversion on topology Id($topologyId) with ";
++                print "topology mode($topologyMode) returned ";
++                print "topology index($topologyIndex), but expected ";
++                print "topology index($toplogyModeArray[$topologyId]) \n";
++            }
++        }  # end for (my $topologyId = 0 ...
++    } # end foreach my $topologyMode (@topologyModes)
++
++    print "<< Running testTopologyIdToTopologyIndex: test " .
++          getPassFailString($testPassed) . "\n";
++
++    return $testPassed;
++}
++
++#--------------------------------------------------
++# @brief Test the method that gets the topology index based
++#        based on the current processors within the MRW XML
++#
++# @param[in] $targetObj - The global target object
++#
++# @return true if test passed, false other wise
++#--------------------------------------------------
++sub testGetTopologyIndex
++{
++    my $targetObj = shift;
++
++    my $testPassed = true;
++
++    my $system_name = $targetObj->getAttribute('/sys-0',"SYSTEM_NAME");
++    if ($system_name =~ /RAINIER/i)
++    {
++        print ">> Running testGetTopologyIndex \n";
++
++        # The different procs available
++        use constant PROC_0 => "/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-0";
++        use constant PROC_1 => "/sys-0/node-0/nisqually-0/proc_socket-0/godel-0/power10-1";
++
++        # Get processor 1's index
++        my $processorTarget = PROC_0;
++        my $topologyIndex = getTopologyIndex($targetObj, $processorTarget);
++
++        # For the current MRW, proc 0 has index 0 with mode 0
++        my $expectedTopologyIndex = 0;
++        if ($topologyIndex != $expectedTopologyIndex)
++        {
++            $testPassed = false;
++            my @fullProc = split(/\//, $processorTarget);
++            print "ERROR: retrieved topology index $topologyIndex for processor " .
++                   "@fullProc[-1] but expected $expectedTopologyIndex \n";
++        }
++
++        # Get processor 2's index
++        $processorTarget = PROC_1;
++        $topologyIndex = getTopologyIndex($targetObj, $processorTarget);
++
++        # For the current MRW, proc 1 has index 4 with mode 0
++        $expectedTopologyIndex = 4;
++        if ($topologyIndex != $expectedTopologyIndex)
++        {
++            $testPassed = false;
++            my @fullProc = split(/\//, $processorTarget);
++            print "ERROR: retrieved topology index $topologyIndex for processor " .
++                   "@fullProc[-1] but expected $expectedTopologyIndex \n";
++        }
++
++        print "<< Running testGetTopologyIndex: test " .
++              getPassFailString($testPassed) . "\n";
++
++    } # end if ($system_name =~ /RAINIER/i)
++
++    return $testPassed;
++}
++
++sub getPassFailString
++{
++    my $passFailBoolean = shift;
++    my $failPassString = "passed";
++
++    if ($passFailBoolean == false)
++    {
++        $failPassString = "failed";
++    }
++
++    return $failPassString;
++}
++
++
+-- 
+1.8.2.2
+
diff --git a/openpower/package/hostboot-p10/Config.in b/openpower/package/hostboot-p10/Config.in
new file mode 100644
index 0000000..d65776a
--- /dev/null
+++ b/openpower/package/hostboot-p10/Config.in
@@ -0,0 +1,39 @@
+config BR2_PACKAGE_HOSTBOOT_P10
+        bool "hostboot-p10"
+        default y if (BR2_OPENPOWER_POWER10)
+        select BR2_CPP
+        help
+            Project to build the Hostboot package for P10
+
+if BR2_PACKAGE_HOSTBOOT_P10
+
+choice
+	prompt "P10 Hostboot version"
+	default BR2_HOSTBOOT_P10_LATEST_VERSION
+
+config BR2_HOSTBOOT_P10_LATEST_VERSION
+	bool "Use latest Hostboot version"
+
+config BR2_HOSTBOOT_P10_CUSTOM_VERSION
+	bool "Use custom Hostboot version"
+
+endchoice
+
+config BR2_HOSTBOOT_P10_CUSTOM_VERSION_VALUE
+	string "Hostboot P10 version"
+	depends on BR2_HOSTBOOT_P10_CUSTOM_VERSION
+
+config BR2_HOSTBOOT_P10_VERSION
+	string
+	default "1aed986c145918dfee4d60f433e69280fd718d72" if BR2_HOSTBOOT_P10_LATEST_VERSION
+	default BR2_HOSTBOOT_P10_CUSTOM_VERSION_VALUE \
+		if BR2_HOSTBOOT_P10_CUSTOM_VERSION
+
+config BR2_HOSTBOOT_P10_CONFIG_FILE
+        string "Hostboot configuration file for compilation"
+        default default
+        help
+            String used to define hw specific make config file
+
+endif
+
diff --git a/openpower/package/hostboot-p10/hostboot-p10.mk b/openpower/package/hostboot-p10/hostboot-p10.mk
new file mode 100644
index 0000000..20a6f32
--- /dev/null
+++ b/openpower/package/hostboot-p10/hostboot-p10.mk
@@ -0,0 +1,37 @@
+################################################################################
+#
+# Hostboot for POWER10
+#
+################################################################################
+
+HOSTBOOT_P10_VERSION = $(call qstrip,$(BR2_HOSTBOOT_P10_VERSION))
+# TODO: WORKAROUND: Need to reenable next line and comment out the two lines
+# after that, when code is propagated to a public repo
+#HOSTBOOT_P10_SITE ?= $(call github,open-power,hostboot,$(HOSTBOOT_P10_VERSION))
+HOSTBOOT_P10_SITE = https://github.ibm.com/open-power/hostboot.git
+HOSTBOOT_P10_SITE_METHOD=git
+
+HOSTBOOT_P10_LICENSE = Apache-2.0
+HOSTBOOT_P10_LICENSE_FILES = LICENSE
+HOSTBOOT_P10_DEPENDENCIES = host-binutils
+
+HOSTBOOT_P10_INSTALL_IMAGES = YES
+HOSTBOOT_P10_INSTALL_TARGET = NO
+
+HOSTBOOT_P10_ENV_VARS=$(TARGET_MAKE_ENV) PERL_USE_UNSAFE_INC=1 \
+    CONFIG_FILE=$(BR2_EXTERNAL_OP_BUILD_PATH)/configs/hostboot/$(BR2_HOSTBOOT_P10_CONFIG_FILE) \
+    OPENPOWER_BUILD=1 CROSS_PREFIX="$(CCACHE) $(TARGET_CROSS)" HOST_PREFIX="" HOST_BINUTILS_DIR=$(HOST_BINUTILS_DIR) \
+    HOSTBOOT_VERSION=`cat $(HOSTBOOT_P10_VERSION_FILE)`
+
+# TODO: WORKAROUND: Currently the git clone causes a bad symlink
+# to be created for src/include/usr/tracinterface.H; so delete it and rebuild it
+# manually
+define HOSTBOOT_P10_BUILD_CMDS
+        $(HOSTBOOT_P10_ENV_VARS) bash -c 'cd $(@D) && rm -f src/include/usr/tracinterface.H && cp src/include/usr/trace/interface.H src/include/usr/tracinterface.H && source ./env.bash && $(MAKE)'
+endef
+
+define HOSTBOOT_P10_INSTALL_IMAGES_CMDS
+        cd $(@D) && source ./env.bash && $(@D)/src/build/tools/hbDistribute --openpower $(STAGING_DIR)/hostboot_build_images/
+endef
+
+$(eval $(generic-package))
diff --git a/openpower/package/machine-xml/Config.in b/openpower/package/machine-xml/Config.in
index c1064d7..63d31e2 100755
--- a/openpower/package/machine-xml/Config.in
+++ b/openpower/package/machine-xml/Config.in
@@ -18,17 +18,17 @@
 
 config BR2_OPENPOWER_MACHINE_XML_FILTER_UNWANTED_ATTRIBUTES
        bool "Filter Unwanted Attributes"
-       default y if (BR2_OPENPOWER_POWER9)
+       default y if (BR2_OPENPOWER_POWER9 || BR2_OPENPOWER_POWER10)
        default n
 
 config BR2_OPENPOWER_MACHINE_XML_OPPOWERVM_ATTRIBUTES
        bool "OPPOWERVM Attributes/Target"
-       default y if (BR2_OPENPOWER_POWER9)
+       default y if (BR2_OPENPOWER_POWER9 || BR2_OPENPOWER_POWER10)
        default n
 
 config BR2_OPENPOWER_MACHINE_XML_TARGET_TYPES_OPENPOWER_XML
        bool "Include target_types_openpower.xml"
-       default y if (BR2_OPENPOWER_POWER9)
+       default y if (BR2_OPENPOWER_POWER9 || BR2_OPENPOWER_POWER10)
        default n
 
 config BR2_OPENPOWER_MACHINE_XML_CUSTOM_GIT_VALUE
diff --git a/openpower/package/machine-xml/machine-xml.mk b/openpower/package/machine-xml/machine-xml.mk
index 4d31c4f..29170de 100644
--- a/openpower/package/machine-xml/machine-xml.mk
+++ b/openpower/package/machine-xml/machine-xml.mk
@@ -15,6 +15,9 @@
 MACHINE_XML_LICENSE_FILES = LICENSE
 MACHINE_XML_DEPENDENCIES =
 
+ifeq ($(BR2_OPENPOWER_POWER10),y)
+MACHINE_XML_DEPENDENCIES += hostboot-p10
+endif
 ifeq ($(BR2_OPENPOWER_POWER9),y)
 MACHINE_XML_DEPENDENCIES += hostboot
 endif
diff --git a/openpower/package/occ-p10/0001-Workaround-certain-OCC-errors-for-P10.patch b/openpower/package/occ-p10/0001-Workaround-certain-OCC-errors-for-P10.patch
new file mode 100644
index 0000000..c00a28c
--- /dev/null
+++ b/openpower/package/occ-p10/0001-Workaround-certain-OCC-errors-for-P10.patch
@@ -0,0 +1,28 @@
+From 48c944978a8fea129b4fce39063386237881871b Mon Sep 17 00:00:00 2001
+From: Nick Bofferding <bofferdn@us.ibm.com>
+Date: Thu, 3 Oct 2019 14:36:31 -0500
+Subject: [PATCH] Workaround certain OCC errors for P10
+
+To allow P10 OCC code to compile, temporarily suppress errors for:
+  aggressive-loop-optimizations
+  unused-but-set-variable
+---
+ src/occ_405/occ_defs.mk | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/occ_405/occ_defs.mk b/src/occ_405/occ_defs.mk
+index c87c44a..fa06a42 100644
+--- a/src/occ_405/occ_defs.mk
++++ b/src/occ_405/occ_defs.mk
+@@ -23,7 +23,7 @@
+ #
+ # IBM_PROLOG_END_TAG
+ 
+-GCC-CFLAGS += -Werror
++GCC-CFLAGS += -Werror -Wno-error=aggressive-loop-optimizations  -Wno-error=unused-but-set-variable
+ 
+ %.o: %.c
+ $(OBJDIR)/%.o: %.c
+-- 
+1.8.2.2
+
diff --git a/openpower/package/occ-p10/Config.in b/openpower/package/occ-p10/Config.in
new file mode 100644
index 0000000..6a2e284
--- /dev/null
+++ b/openpower/package/occ-p10/Config.in
@@ -0,0 +1,16 @@
+config BR2_PACKAGE_OCC_P10
+        bool "OCC for P10"
+        default y if (BR2_OPENPOWER_PLATFORM && BR2_OPENPOWER_POWER10)
+        select BR2_CPP
+        help
+            Project to build OCC for P10
+
+if BR2_PACKAGE_OCC_P10
+
+config BR2_OCC_P10_BIN_FILENAME
+    string "Name of OCC P10 image file"
+    default "occ.bin"
+    help
+        String used to define name of the OCC binary image file
+
+endif
diff --git a/openpower/package/occ-p10/occ-p10.mk b/openpower/package/occ-p10/occ-p10.mk
new file mode 100644
index 0000000..14410df
--- /dev/null
+++ b/openpower/package/occ-p10/occ-p10.mk
@@ -0,0 +1,47 @@
+################################################################################
+#
+# occ for power10
+#
+################################################################################
+
+OCC_P10_VERSION ?= 36b56e72c2dd6c2a2fb21667c55a594f86f6132e
+# TODO: WORKAROUND: Need to reenable next line and comment out the two lines
+# after that, when code is propagated to a public repo
+#OCC_P10_SITE ?= $(call github,open-power,occ,$(OCC_P10_VERSION))
+OCC_P10_SITE = https://github.ibm.com/open-power/occ.git
+OCC_P10_SITE_METHOD=git
+
+OCC_P10_LICENSE = Apache-2.0
+
+OCC_P10_LICENSE_FILES = LICENSE
+
+OCC_P10_INSTALL_IMAGES = YES
+OCC_P10_INSTALL_TARGET = NO
+
+OCC_P10_STAGING_DIR = $(STAGING_DIR)/occ
+
+OCC_P10_IMAGE_BIN_PATH = obj/image.bin
+
+OCC_P10_DEPENDENCIES = host-binutils host-ppe42-gcc
+ifeq ($(BR2_OCC_GPU_BIN_BUILD),y)
+	OCC_P10_DEPENDENCIES += hostboot-binaries
+endif
+
+define OCC_P10_BUILD_CMDS
+	if [ "$(BR2_OCC_GPU_BIN_BUILD)" == "y"  ]; then \
+	    cd $(@D)/src && \
+            make PPE_TOOL_PATH=$(PPE42_GCC_BIN) OCC_OP_BUILD=1 CROSS_PREFIX=$(TARGET_CROSS) LD_LIBRARY_PATH=$(HOST_DIR)/usr/lib GPE1_BIN_IMAGE_PATH=$(STAGING_DIR)/hostboot_binaries/ OPOCC_GPU_SUPPORT=1 all; \
+	else \
+            cd $(@D)/src && \
+            make PPE_TOOL_PATH=$(PPE42_GCC_BIN) OCC_OP_BUILD=1 CROSS_PREFIX=$(TARGET_CROSS) LD_LIBRARY_PATH=$(HOST_DIR)/usr/lib all; \
+	fi;
+endef
+
+OCC_P10_BUILD_CMDS ?= $(OCC_BUILD_CMDS_P9)
+
+define OCC_P10_INSTALL_IMAGES_CMDS
+       mkdir -p $(STAGING_DIR)/occ
+       cp $(@D)/$(OCC_P10_IMAGE_BIN_PATH) $(OCC_P10_STAGING_DIR)/$(BR2_OCC_BIN_FILENAME)
+endef
+
+$(eval $(generic-package))
diff --git a/openpower/package/openpower-pnor/Config.in b/openpower/package/openpower-pnor/Config.in
index 82280f5..ab35d4c 100644
--- a/openpower/package/openpower-pnor/Config.in
+++ b/openpower/package/openpower-pnor/Config.in
@@ -1,18 +1,21 @@
 config BR2_PACKAGE_OPENPOWER_PNOR
         bool "openpower_pnor"
         default y if (BR2_OPENPOWER_PLATFORM)
-        select BR2_PACKAGE_HOSTBOOT if !BR2_OPENPOWER_POWER8
+        select BR2_PACKAGE_HOSTBOOT_P10 if (! (BR2_OPENPOWER_POWER8 || BR2_OPENPOWER_POWER9) )
+        select BR2_PACKAGE_HOSTBOOT if BR2_OPENPOWER_POWER9
         select BR2_PACKAGE_HOSTBOOT_P8 if BR2_OPENPOWER_POWER8
         select BR2_PACKAGE_HOSTBOOT_BINARIES
         select BR2_PACKAGE_SKIBOOT
         select BR2_PACKAGE_OPENPOWER_FFS
-        select BR2_PACKAGE_OCC if !BR2_OPENPOWER_POWER8
+        select BR2_PACKAGE_OCC_P10 if (! (BR2_OPENPOWER_POWER8 || BR2_OPENPOWER_POWER9 ) )
+        select BR2_PACKAGE_OCC if !BR2_OPENPOWER_POWER9
         select BR2_PACKAGE_OCC_P8 if BR2_OPENPOWER_POWER8
         select BR2_PACKAGE_CAPP_UCODE
         select BR2_PACKAGE_IMA_CATALOG
         select BR2_PACKAGE_HOST_OPENPOWER_VPNOR
         select BR2_PACKAGE_MACHINE_XML
-        select BR2_PACKAGE_HCODE if BR2_OPENPOWER_POWER9
+        select BR2_PACKAGE_HCODE_P10 if (BR2_OPENPOWER_POWER10)
+        select BR2_PACKAGE_HCODE if (BR2_OPENPOWER_POWER9)
         help
             Utilites for building a targeting binary image
 
diff --git a/openpower/package/openpower-pnor/openpower-pnor.mk b/openpower/package/openpower-pnor/openpower-pnor.mk
index 9408a07..71ca734 100644
--- a/openpower/package/openpower-pnor/openpower-pnor.mk
+++ b/openpower/package/openpower-pnor/openpower-pnor.mk
@@ -4,15 +4,20 @@
 #
 ################################################################################
 
-OPENPOWER_PNOR_VERSION ?= bdfd0d08a7a04b1326553f570d35e778eda9db81
-OPENPOWER_PNOR_SITE ?= $(call github,open-power,pnor,$(OPENPOWER_PNOR_VERSION))
+OPENPOWER_PNOR_VERSION ?= e75dcb184995fd60f1add131681e4df9dc671eff
+
+# TODO: WORKAROUND: Need to reenable next line and comment out the two lines
+# after that, when code is propagated to a public repo
+#OPENPOWER_PNOR_SITE ?= $(call github,open-power,pnor,$(OPENPOWER_PNOR_VERSION))
+OPENPOWER_PNOR_SITE = https://github.ibm.com/open-power/pnor.git
+OPENPOWER_PNOR_SITE_METHOD=git
 
 OPENPOWER_PNOR_LICENSE = Apache-2.0
 OPENPOWER_PNOR_LICENSE_FILES = LICENSE
 OPENPOWER_PNOR_DEPENDENCIES = hostboot-binaries machine-xml skiboot host-openpower-ffs capp-ucode host-openpower-pnor-util
 
 ifeq ($(BR2_OPENPOWER_POWER9),y)
-OPENPOWER_PNOR_DEPENDENCIES += hcode
+    OPENPOWER_PNOR_DEPENDENCIES += hcode
 endif
 
 ifeq ($(BR2_PACKAGE_IMA_CATALOG),y)
@@ -46,7 +51,9 @@
 SIGN_MODE_ARG=-sign_mode $(BR2_OPENPOWER_SECUREBOOT_SIGN_MODE)
 endif
 
-ifeq ($(BR2_OPENPOWER_POWER9),y)
+ifeq ($(BR2_OPENPOWER_POWER10),y)
+    OPENPOWER_RELEASE=p10
+else ifeq ($(BR2_OPENPOWER_POWER9),y)
     OPENPOWER_RELEASE=p9
 else
     OPENPOWER_RELEASE=p8
@@ -79,12 +86,16 @@
 
 # Subpackages we want to include in the version info (do not include openpower-pnor)
 OPENPOWER_VERSIONED_SUBPACKAGES = skiboot
+
 ifeq ($(BR2_PACKAGE_HOSTBOOT_P8),y)
-OPENPOWER_VERSIONED_SUBPACKAGES += hostboot-p8 occ-p8
+    OPENPOWER_VERSIONED_SUBPACKAGES += hostboot-p8 occ-p8
+else ifeq ($(BR2_PACKAGE_HOSTBOOT_P10),y)
+    OPENPOWER_VERSIONED_SUBPACKAGES += hostboot-p10 occ-p10 sbe-p10 hcode-p10
+	OPENPOWER_PNOR_DEPENDENCIES += hostboot-p10 occ-p10 sbe-p10 hcode-p10
+else ifeq ($(BR2_PACKAGE_HOSTBOOT),y)
+    OPENPOWER_VERSIONED_SUBPACKAGES += hostboot occ
 endif
-ifeq ($(BR2_PACKAGE_HOSTBOOT),y)
-OPENPOWER_VERSIONED_SUBPACKAGES += hostboot occ
-endif
+
 OPENPOWER_VERSIONED_SUBPACKAGES += linux petitboot machine-xml hostboot-binaries capp-ucode
 OPENPOWER_PNOR = openpower-pnor
 
@@ -93,7 +104,9 @@
     OPENPOWER_VERSIONED_SUBPACKAGES += sbe hcode
 endif
 
-ifeq ($(BR2_PACKAGE_OCC_P8),y)
+ifeq ($(BR2_PACKAGE_OCC_P10),y)
+    OCC_BIN_FILENAME=$(BR2_OCC_P10_BIN_FILENAME)
+else ifeq ($(BR2_PACKAGE_OCC_P8),y)
     OCC_BIN_FILENAME=$(BR2_OCC_P8_BIN_FILENAME)
 else
     OCC_BIN_FILENAME=$(BR2_OCC_BIN_FILENAME)
diff --git a/openpower/package/ppe42-binutils/Config.in b/openpower/package/ppe42-binutils/Config.in
index 824e557..341e8ad 100644
--- a/openpower/package/ppe42-binutils/Config.in
+++ b/openpower/package/ppe42-binutils/Config.in
@@ -1,6 +1,6 @@
 config BR2_PACKAGE_HOST_PPE42_BINUTILS
         bool "ppe42-binutils"
-        default y if (BR2_OPENPOWER_PLATFORM && BR2_OPENPOWER_POWER9)
+        default y if (BR2_OPENPOWER_PLATFORM && (BR2_OPENPOWER_POWER10 || BR2_OPENPOWER_POWER9))
         select BR2_CPP
         help
             Project to build the PPE42 PORE binutils
diff --git a/openpower/package/ppe42-binutils/ppe42-binutils.mk b/openpower/package/ppe42-binutils/ppe42-binutils.mk
index b63e2a1..0c365b8 100644
--- a/openpower/package/ppe42-binutils/ppe42-binutils.mk
+++ b/openpower/package/ppe42-binutils/ppe42-binutils.mk
@@ -4,7 +4,7 @@
 #
 ################################################################################
 
-PPE42_BINUTILS_VERSION ?= ded0eff199fa1d9bd8be5a78935e8f023a2c5fad
+PPE42_BINUTILS_VERSION ?= c615a89c5beb032cbb00bf0c3e670319b2bbd4f5
 PPE42_BINUTILS_SITE ?= $(call github,open-power,ppe42-binutils,$(PPE42_BINUTILS_VERSION))
 PPE42_BINUTILS_LICENSE = GPLv3+
 
diff --git a/openpower/package/ppe42-gcc/Config.in b/openpower/package/ppe42-gcc/Config.in
index d66418d..54ae38b 100644
--- a/openpower/package/ppe42-gcc/Config.in
+++ b/openpower/package/ppe42-gcc/Config.in
@@ -1,6 +1,6 @@
 config BR2_PACKAGE_HOST_PPE42_GCC
         bool "ppe42-gcc"
-        default y if (BR2_OPENPOWER_PLATFORM && BR2_OPENPOWER_POWER9)
+        default y if (BR2_OPENPOWER_PLATFORM && (BR2_OPENPOWER_POWER10 || BR2_OPENPOWER_POWER9))
         select BR2_CPP
         help
             Project to build the PPE42 gcc
diff --git a/openpower/package/ppe42-gcc/ppe42-gcc.mk b/openpower/package/ppe42-gcc/ppe42-gcc.mk
index 3ab8a55..31496cc 100644
--- a/openpower/package/ppe42-gcc/ppe42-gcc.mk
+++ b/openpower/package/ppe42-gcc/ppe42-gcc.mk
@@ -4,7 +4,7 @@
 #
 ################################################################################
 
-PPE42_GCC_VERSION ?= c13849780c80d1ed466efbeaabcc663fe48cd87d
+PPE42_GCC_VERSION ?= 3d454701206d141a26777c3f6c1d966921f363de
 PPE42_GCC_SITE ?= $(call github,open-power,ppe42-gcc,$(PPE42_GCC_VERSION))
 PPE42_GCC_LICENSE = GPLv3+
 
diff --git a/openpower/package/sbe-p10/0001-Update-SBE-distribute-to-export-P10-DD1-files.patch b/openpower/package/sbe-p10/0001-Update-SBE-distribute-to-export-P10-DD1-files.patch
new file mode 100644
index 0000000..26cea10
--- /dev/null
+++ b/openpower/package/sbe-p10/0001-Update-SBE-distribute-to-export-P10-DD1-files.patch
@@ -0,0 +1,37 @@
+From b0a445addc19754ebea92ea3ee46185a3716267a Mon Sep 17 00:00:00 2001
+From: Nick Bofferding <bofferdn@us.ibm.com>
+Date: Thu, 3 Oct 2019 13:22:58 -0500
+Subject: [PATCH] Update SBE distribute to export P10 DD1 files
+
+Change-Id: I8bda043e0fe69187923abcfb1e79dd4de98e98ae
+---
+ src/build/sbeOpDistribute.py | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/build/sbeOpDistribute.py b/src/build/sbeOpDistribute.py
+index 14546d9..32b0cff 100755
+--- a/src/build/sbeOpDistribute.py
++++ b/src/build/sbeOpDistribute.py
+@@ -5,7 +5,7 @@
+ #
+ # OpenPOWER sbe Project
+ #
+-# Contributors Listed Below - COPYRIGHT 2017,2018
++# Contributors Listed Below - COPYRIGHT 2017,2019
+ # [+] International Business Machines Corp.
+ #
+ #
+@@ -26,8 +26,8 @@ import os
+ import sys
+ import getopt
+ 
+-CHIPID = 'p9n'
+-p9n_EC = {'21':'DD2', '22':'DD2', '23':'DD2'}
++CHIPID = 'p10'
++p9n_EC = {'10':'DD1'}
+ 
+ def usage():
+     print "usage:sbeOpDistribute.py [--sbe_binary_dir] <sbe binary path> [--img_dir] <images path>"
+-- 
+1.8.2.2
+
diff --git a/openpower/package/sbe-p10/0002-Temporarily-disabled-install-directive-in-SBE-distri.patch b/openpower/package/sbe-p10/0002-Temporarily-disabled-install-directive-in-SBE-distri.patch
new file mode 100644
index 0000000..c0fb22d
--- /dev/null
+++ b/openpower/package/sbe-p10/0002-Temporarily-disabled-install-directive-in-SBE-distri.patch
@@ -0,0 +1,36 @@
+From e34aaa2b68ec05f85f3d47ef37bdbd2aa5a162ae Mon Sep 17 00:00:00 2001
+From: Nick Bofferding <bofferdn@us.ibm.com>
+Date: Mon, 7 Oct 2019 15:58:41 -0500
+Subject: [PATCH] Temporarily disabled install directive in SBE distribute
+
+Change-Id: I3f54da025cde5944b098ced69be43995c495ec66
+---
+ src/build/sbeOpDistribute.py | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/build/sbeOpDistribute.py b/src/build/sbeOpDistribute.py
+index 32b0cff..373edb7 100755
+--- a/src/build/sbeOpDistribute.py
++++ b/src/build/sbeOpDistribute.py
+@@ -3,7 +3,7 @@
+ #
+ # $Source: src/build/sbeOpDistribute.py $
+ #
+-# OpenPOWER sbe Project
++# OpenPOWER HostBoot Project
+ #
+ # Contributors Listed Below - COPYRIGHT 2017,2019
+ # [+] International Business Machines Corp.
+@@ -103,7 +103,8 @@ def main(argv):
+             # Copy sbe raw binary to scratch folder
+             run_system_cmd('cp '+sbe_binary_dir+'/'+basename+'.bin'+' '+scratch_dir+'/'+basename+'.bin')
+             # Add HW ref image
+-            run_system_cmd('p9_ipl_build '+scratch_dir+'/'+basename+'.bin '+hw_ref_image+' 0x'+ecLevel)
++            #TODO: This is currently not working in p10 op-build
++            # run_system_cmd('p9_ipl_build '+scratch_dir+'/'+basename+'.bin '+hw_ref_image+' 0x'+ecLevel)
+             #add pnor header
+             run_system_cmd("env echo -en VERSION\\\\0 > "+scratch_dir+"/"+basename+".sha.bin")
+             run_system_cmd("sha512sum "+scratch_dir+"/"+basename+".bin | awk '{print $1}' | xxd -pr -r >> "+scratch_dir+"/"+basename+".sha.bin")
+-- 
+1.8.2.2
+
diff --git a/openpower/package/sbe-p10/Config.in b/openpower/package/sbe-p10/Config.in
new file mode 100644
index 0000000..3468511
--- /dev/null
+++ b/openpower/package/sbe-p10/Config.in
@@ -0,0 +1,33 @@
+config BR2_PACKAGE_SBE_P10
+        bool "sbe-p10"
+        default y if (BR2_OPENPOWER_PLATFORM && BR2_OPENPOWER_POWER10)
+        select BR2_CPP
+        depends on BR2_PACKAGE_HCODE_P10
+        help
+            Project to build the sbe firmware codebase for P10
+
+if BR2_PACKAGE_SBE_P10
+
+choice
+	prompt "SBE version"
+	default BR2_SBE_P10_LATEST_VERSION
+
+config BR2_SBE_P10_LATEST_VERSION
+	bool "Use latest SBE master"
+
+config BR2_SBE_P10_CUSTOM_VERSION
+	bool "Custom SBE version"
+
+endchoice
+
+config BR2_SBE_P10_CUSTOM_VERSION_VALUE
+	string "SBE version"
+	depends on BR2_SBE_P10_CUSTOM_VERSION
+
+config BR2_SBE_P10_VERSION
+	string
+	default "59ca18cfdb3f2585e95e664be751440ad2557550" if BR2_SBE_P10_LATEST_VERSION
+	default BR2_SBE_P10_CUSTOM_VERSION_VALUE \
+		if BR2_SBE_P10_CUSTOM_VERSION
+
+endif
diff --git a/openpower/package/sbe-p10/sbe-p10.mk b/openpower/package/sbe-p10/sbe-p10.mk
new file mode 100644
index 0000000..35af089
--- /dev/null
+++ b/openpower/package/sbe-p10/sbe-p10.mk
@@ -0,0 +1,35 @@
+################################################################################
+#
+# SBE for P10
+#
+################################################################################
+
+SBE_P10_VERSION = $(call qstrip,$(BR2_SBE_P10_VERSION))
+# TODO: WORKAROUND: Need to reenable next line and comment out the two lines
+# after that, when code is propagated to a public repo
+#SBE_P10_SITE = $(call github,open-power,sbe,$(SBE_P10_VERSION))
+SBE_P10_SITE = https://github.ibm.com/open-power/sbe.git
+SBE_P10_SITE_METHOD=git
+
+SBE_P10_LICENSE = Apache-2.0
+SBE_P10_DEPENDENCIES = host-ppe42-gcc hcode-p10
+# TODO WORKAROUND ... host-ppe42-gc not compiling
+# host-ppe42-gcc hcode-p10
+
+SBE_P10_INSTALL_IMAGES = YES
+SBE_P10_INSTALL_TARGET = NO
+
+define SBE_P10_BUILD_CMDS
+	SBE_COMMIT_ID=$(SBE_P10_VERSION) $(MAKE) -C $(@D) \
+		LD_LIBRARY_PATH=$(HOST_DIR)/usr/lib \
+		CROSS_COMPILER_PATH=$(PPE42_GCC_BIN) \
+		all
+endef
+
+define SBE_P10_INSTALL_IMAGES_CMDS
+	$(INSTALL) -D $(@D)/images/ipl_image_tool $(HOST_DIR)/usr/bin/
+	python $(@D)/src/build/sbeOpDistribute.py  --sbe_binary_dir=$(STAGING_DIR)/sbe_binaries --img_dir=$(@D)/images --sbe_binary_filename $(BR2_HOSTBOOT_BINARY_SBE_FILENAME)
+	cp $(@D)/src/build/sbeOpDistribute.py $(STAGING_DIR)/sbe_binaries/
+endef
+
+$(eval $(generic-package))
diff --git a/openpower/platform/Config.in b/openpower/platform/Config.in
index 3232cd0..b6baa4d 100644
--- a/openpower/platform/Config.in
+++ b/openpower/platform/Config.in
@@ -1,7 +1,7 @@
 config BR2_OPENPOWER_PLATFORM
     bool "Enables only one openPower platform"
     default n
-    depends on ((BR2_OPENPOWER_POWER8 || BR2_OPENPOWER_POWER9) && !(BR2_OPENPOWER_POWER8 && BR2_OPENPOWER_POWER9))
+    depends on ((BR2_OPENPOWER_POWER8 || BR2_OPENPOWER_POWER9 || BR2_OPENPOWER_POWER10) && !(BR2_OPENPOWER_POWER8 && BR2_OPENPOWER_POWER9) && !(BR2_OPENPOWER_POWER8 && BR2_OPENPOWER_POWER10) && !(BR2_OPENPOWER_POWER9 && BR2_OPENPOWER_POWER10) && !(BR2_OPENPOWER_POWER8 && BR2_OPENPOWER_POWER9 && BR2_OPENPOWER_POWER10))
 
 config BR2_OPENPOWER_POWER8
     bool "Enables the OpenPower p8 platform"
@@ -12,3 +12,8 @@
     bool "Enables the OpenPower p9 platform"
     default n
     depends on BR2_powerpc64 || BR2_powerpc64le
+
+config BR2_OPENPOWER_POWER10
+    bool "Enables the OpenPower p10 platform"
+    default n
+    depends on BR2_powerpc64 || BR2_powerpc64le