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