summaryrefslogtreecommitdiffstats
path: root/src/build
diff options
context:
space:
mode:
Diffstat (limited to 'src/build')
-rw-r--r--src/build/beam/core/assert.C6
-rw-r--r--src/build/beam/core/pagemgr.C5
-rw-r--r--src/build/beam/core/stacksegment.C5
-rw-r--r--src/build/beam/hwp/mvpdRingFuncs.C5
-rw-r--r--src/build/beam/i2c/i2c.C6
-rw-r--r--src/build/beam/prdf/prdfBitKey.C5
-rw-r--r--src/build/beam/prdf/prdfPegasusConfigurator.C5
-rw-r--r--src/build/beam/targeting/targetservice.C5
-rw-r--r--src/build/buildpnor/PnorUtils.pm134
-rw-r--r--src/build/buildpnor/bpm-utils/LICENSE_PROLOG24
-rw-r--r--src/build/buildpnor/bpm-utils/imageCrc.c479
-rwxr-xr-xsrc/build/buildpnor/bpm-utils/insertBpmFwCrc.py191
-rwxr-xr-xsrc/build/buildpnor/buildBpmFlashImages.pl878
-rwxr-xr-xsrc/build/buildpnor/buildpnor.pl11
-rw-r--r--src/build/buildpnor/defaultPnorLayout.xml36
-rwxr-xr-xsrc/build/buildpnor/genPnorImages.pl68
-rwxr-xr-xsrc/build/buildpnor/memd_creation.pl2
-rwxr-xr-xsrc/build/buildpnor/pkgOcmbFw.pl7
-rw-r--r--src/build/buildpnor/pnorLayoutAxone.xml91
-rw-r--r--src/build/buildpnor/pnorLayoutFSP.xml30
-rwxr-xr-xsrc/build/citest/autocitest64
-rwxr-xr-xsrc/build/citest/build-script185
-rwxr-xr-xsrc/build/citest/create-sandbox4
-rwxr-xr-xsrc/build/citest/cxxtest-start.sh2
-rw-r--r--src/build/citest/etc/bbuild2
-rw-r--r--src/build/citest/etc/cppcheck27
-rw-r--r--src/build/citest/etc/eecache_prebuilt1
-rw-r--r--src/build/citest/etc/simbuild2
-rwxr-xr-xsrc/build/citest/etc/workarounds.postsimsetup7
-rwxr-xr-xsrc/build/citest/setup-env1
-rw-r--r--src/build/configs/simics_axone.config40
-rw-r--r--src/build/debug/Hostboot/BlTrace.pm1
-rwxr-xr-xsrc/build/debug/Hostboot/Dump.pm14
-rwxr-xr-xsrc/build/debug/Hostboot/Gcov.pm464
-rw-r--r--src/build/debug/Hostboot/GcovModuleUnload.pm69
-rw-r--r--src/build/debug/Hostboot/PrintVMM.pm4
-rwxr-xr-xsrc/build/debug/Hostboot/_DebugFrameworkVMM.pm4
-rwxr-xr-xsrc/build/debug/eSEL.pl44
-rwxr-xr-xsrc/build/debug/ffdcExpander727
-rw-r--r--src/build/debug/simics-debug-framework.py23
-rw-r--r--src/build/linker/genlist.C71
-rw-r--r--src/build/linker/linker.C30
-rw-r--r--src/build/mkrules/cc.rules.mk71
-rw-r--r--src/build/mkrules/cflags.env.mk4
-rwxr-xr-xsrc/build/mkrules/dist.targets.mk6
-rw-r--r--src/build/mkrules/gcov.env.mk50
-rwxr-xr-xsrc/build/mkrules/hbfw/img/makefile58
-rw-r--r--src/build/mkrules/images.rules.mk39
-rwxr-xr-xsrc/build/simics/standalone.simics92
-rwxr-xr-xsrc/build/simics/startup.simics32
-rwxr-xr-xsrc/build/tools/addCopyright6
-rwxr-xr-xsrc/build/tools/build-cppcheck95
-rwxr-xr-xsrc/build/tools/cflags.sh68
-rwxr-xr-xsrc/build/tools/eecache_editor.pl802
-rwxr-xr-xsrc/build/tools/hb22
-rwxr-xr-xsrc/build/tools/listdeps.pl1
-rwxr-xr-xsrc/build/tools/pre-commit49
57 files changed, 4695 insertions, 479 deletions
diff --git a/src/build/beam/core/assert.C b/src/build/beam/core/assert.C
index c7186668f..183e1847d 100644
--- a/src/build/beam/core/assert.C
+++ b/src/build/beam/core/assert.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,5 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>ERROR5___assert_d9b551657c952063
+
>>>ERROR5___assert_941b08c17c952063
diff --git a/src/build/beam/core/pagemgr.C b/src/build/beam/core/pagemgr.C
index 54779d750..2cde4394d 100644
--- a/src/build/beam/core/pagemgr.C
+++ b/src/build/beam/core/pagemgr.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,5 +22,6 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>MISTAKE5__initialize_7639026bb95510e7
>>>MISTAKE5__initialize_2d381016b95510e7
diff --git a/src/build/beam/core/stacksegment.C b/src/build/beam/core/stacksegment.C
index cfc2cf308..e7bd9eb21 100644
--- a/src/build/beam/core/stacksegment.C
+++ b/src/build/beam/core/stacksegment.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,4 +22,5 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>ERROR8_~StackSegment_b791f4a2ac177b6
diff --git a/src/build/beam/hwp/mvpdRingFuncs.C b/src/build/beam/hwp/mvpdRingFuncs.C
index 5c113e990..50f58dc83 100644
--- a/src/build/beam/hwp/mvpdRingFuncs.C
+++ b/src/build/beam/hwp/mvpdRingFuncs.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012,2014 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,5 +22,6 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>MISTAKE17_mbvpdValidateRecordKeyword_d149f58f1505
>>>MISTAKE5_mbvpdRingFunc_b48fca4f6c313e21
diff --git a/src/build/beam/i2c/i2c.C b/src/build/beam/i2c/i2c.C
index 6bc1a97f4..1d2632b8f 100644
--- a/src/build/beam/i2c/i2c.C
+++ b/src/build/beam/i2c/i2c.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,4 +22,6 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>MISTAKE17_i2cSetupMasters_8697e17e1505
+
diff --git a/src/build/beam/prdf/prdfBitKey.C b/src/build/beam/prdf/prdfBitKey.C
index b1618ebe9..0d9d67938 100644
--- a/src/build/beam/prdf/prdfBitKey.C
+++ b/src/build/beam/prdf/prdfBitKey.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,5 +22,6 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>MISTAKE17_operator==_f7028aed1505
>>>MISTAKE17_operator==_70cd34271505
diff --git a/src/build/beam/prdf/prdfPegasusConfigurator.C b/src/build/beam/prdf/prdfPegasusConfigurator.C
index 956ed90b2..e19a1b881 100644
--- a/src/build/beam/prdf/prdfPegasusConfigurator.C
+++ b/src/build/beam/prdf/prdfPegasusConfigurator.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,5 +22,6 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>MISTAKE17_addPllDomainsToSystem_954f5e401505
>>>MISTAKE17_addPllDomainsToSystem_c01c04751505
diff --git a/src/build/beam/targeting/targetservice.C b/src/build/beam/targeting/targetservice.C
index 4e069351d..029876273 100644
--- a/src/build/beam/targeting/targetservice.C
+++ b/src/build/beam/targeting/targetservice.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2019 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,5 +22,6 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+// cppcheck-suppress syntaxError
>>>MISTAKE5_queryMasterProcChipTargetHandle_2745d8d11505
>>>MISTAKE5_queryMasterProcChipTargetHandle_da38b67e1505
diff --git a/src/build/buildpnor/PnorUtils.pm b/src/build/buildpnor/PnorUtils.pm
index 3a8d22df2..e5ecbb150 100644
--- a/src/build/buildpnor/PnorUtils.pm
+++ b/src/build/buildpnor/PnorUtils.pm
@@ -39,6 +39,7 @@ my $TRAC_ERR = 0;
my $g_trace = 1;
use XML::Simple;
+
################################################################################
# Set PREFERRED_PARSER to XML::Parser. Otherwise it uses XML::SAX which contains
# bugs that result in XML parse errors that can be fixed by adjusting white-
@@ -53,7 +54,8 @@ use constant PAGE_SIZE => 4096;
################################################################################
sub loadPnorLayout
{
- my ($i_pnorFile, $i_pnorLayoutRef, $i_physicalOffsets, $i_testRun) = @_;
+ my ($i_pnorFile, $i_pnorLayoutRef, $i_physicalOffsets, $i_testRun,
+ $i_outputLayoutLocation) = @_;
my $this_func = (caller(0))[3];
unless(-e $i_pnorFile)
@@ -90,6 +92,10 @@ sub loadPnorLayout
my $numOfSides = scalar (@{$metadataEl->{side}});
my $sideSize = ($imageSize)/($numOfSides);
+ my $currOffset = 0;
+ my $sectionNum = 0;
+ my $isStartingPartition = 1;
+
trace(2, " $this_func: metadata: imageSize = $imageSize, blockSize=$blockSize, arrangement = $arrangement, numOfSides: $numOfSides, sideSize: $sideSize, tocSize: $tocSize");
#determine the TOC offsets from the arrangement and side Information
@@ -170,9 +176,44 @@ sub loadPnorLayout
$physicalOffset = getNumber($physicalOffset);
$physicalRegionSize = getNumber($physicalRegionSize);
+ # if at first section, set starting offset
+ if ($isStartingPartition == 1)
+ {
+ $currOffset = $physicalOffset;
+ $isStartingPartition = 0;
+ }
+
+ # if physical offset does not exist, calculate it and create new element
+ my $hexOffset;
+ if ($physicalOffset == 0)
+ {
+ $physicalOffset = $currOffset;
+ $hexOffset = sprintf("0x%X", $physicalOffset);
+ trace(3, "$this_func: Calculated physicalOffset = $physicalOffset, for eyeCatch = $eyeCatch");
+ push @{$xml->{section}->[$sectionNum]->{physicalOffset}}, $hexOffset;
+ $currOffset = $currOffset + $physicalRegionSize;
+ }
+ else
+ {
+ # if sections overlap, throw error
+ if ($physicalOffset < $currOffset)
+ {
+ $hexOffset = sprintf("0x%X", $physicalOffset);
+ die "ERROR: Collision between sections detected at offset ".$hexOffset."";
+ }
+ $currOffset = $physicalOffset + $physicalRegionSize;
+ }
+ $sectionNum = $sectionNum + 1;
+
+ # align partition by minimum boundary
+ if ($currOffset % PAGE_SIZE != 0)
+ {
+ $currOffset = $currOffset + (PAGE_SIZE - $currOffset % PAGE_SIZE);
+ }
+
if($physicalRegionSize + $physicalOffset > $imageSize)
{
- die "ERROR: $this_func: Image size ($imageSize) smaller than $eyeCatch's offset + $eyeCatch's size (".($physicalOffset + $physicalRegionSize)."). Aborting! ";
+ die "ERROR: $this_func: Image size ($imageSize) smaller than ".$eyeCatch."'s offset + ".$eyeCatch."'s size (".($physicalOffset + $physicalRegionSize)."). Aborting! ";
}
if (exists $$i_pnorLayoutRef{sections}{$physicalOffset})
@@ -215,6 +256,42 @@ sub loadPnorLayout
checkForOverlap($i_pnorLayoutRef);
}
+ # Write xml with offsets to new file if $i_outputLayoutLocation
+ # argument is supplied
+ if (defined $i_outputLayoutLocation && $i_outputLayoutLocation ne "")
+ {
+ my $filename = basename($i_pnorFile, ".xml");
+ $filename = "${i_outputLayoutLocation}/${filename}WithOffsets.xml";
+
+ # writing to new file with error handling
+ eval
+ {
+ print XMLout($xml, RootName => "pnor", OutputFile => $filename);
+ 1;
+ }
+ or do
+ {
+ my $err = $@;
+ die "ERROR: $this_func: Failed to create new XML file with corrected offsets, error = $err";
+ };
+
+ # Write out a helper file for our simics scripts
+ print "\nlocation = " . ${i_outputLayoutLocation} . "\n";
+ my $simfilename = "${i_outputLayoutLocation}/simpnor.py";
+ open(SIM_FILE,'>',$simfilename) or die("($simfilename) could not be opened.");
+ print SIM_FILE "def hb_get_pnor_offset(partname):\n";
+ print SIM_FILE " toc_dict={}\n";
+ #Iterate over the <section> elements.
+ foreach my $sectionEl (@{$xml->{section}})
+ {
+ my $eyeCatch = $sectionEl->{eyeCatch}[0];
+ my $physicalOffset = $sectionEl->{physicalOffset}[0];
+ print SIM_FILE " toc_dict[\"$eyeCatch\"]=$physicalOffset\n";
+ }
+ print SIM_FILE " return toc_dict[partname]\n";
+ close SIM_FILE;
+ }
+
return 0;
}
@@ -353,6 +430,8 @@ sub checkSpaceConstraints
my %sectionHash = %{$$i_pnorLayoutRef{sections}};
+ print "Note: the following metrics are not a true representation of section utilization, since some sections are substantially padded before applying ECC\n";
+
for $key ( keys %{$i_binFiles})
{
my $filesize = -s $$i_binFiles{$key};
@@ -366,18 +445,17 @@ sub checkSpaceConstraints
my $eyeCatch = $sectionHash{$layoutKey}{eyeCatch};
my $physicalRegionSize = $sectionHash{$layoutKey}{physicalRegionSize};
- my $pctUtilized = sprintf("%.2f", $filesize / $physicalRegionSize * 100);
my $freeBytes = $physicalRegionSize - $filesize;
- print "$eyeCatch is $pctUtilized% utilized ($freeBytes of $physicalRegionSize bytes free)\n";
+ print "$eyeCatch section size: $physicalRegionSize, bytes used: $filesize, bytes unused: $freeBytes\n";
if($filesize > $physicalRegionSize)
{
# If this is a test run increase HBI size by PAGE_SIZE until all test
# cases fit
- if ($testRun && $eyeCatch eq "HBI")
+ if ( $testRun && ($eyeCatch eq "HBI") )
{
- print "$this_func: Adjusting HBI size - ran out of space for test cases\n";
- adjustHbiPhysSize(\%sectionHash, $layoutKey, $filesize);
+ print "Adjusting HBI size - ran out of space for test cases\n";
+ adjustSecPhysSize(\%sectionHash, $layoutKey, $filesize);
}
else
{
@@ -388,36 +466,43 @@ sub checkSpaceConstraints
trace(1, "Done checkSpaceConstraints");
}
-
-###############################################################################
-# adjustHbiPhysSize - Adjust HBI physical size when running test cases and fix
-# up physical offsets of partitions after it
-################################################################################
-sub adjustHbiPhysSize
+# sub adjustSecPhysSize
+#
+# Adjust section physical size when running test cases and fix up physical
+# offsets between partitions (for example HBI and all partitions that follow)
+#
+# @param [in] i_sectionHashRef - PNOR layout as a hash table reference
+# @param [in] i_initPartKey - key of initial partition whose physical size will
+# be adjusted
+# @param [in] i_filesize - final file size of partition (note: actual final size
+# may be larger than this as the size is adjusted by increments of PAGE_SIZE)
+# @return - N/A
+#
+sub adjustSecPhysSize
{
- my ($i_sectionHashRef, $i_hbiKey, $i_filesize) = @_;
+ my ($i_sectionHashRef, $i_initPartKey, $i_filesize) = @_;
my $this_func = (caller(0))[3];
my %sectionHash = %$i_sectionHashRef;
- # Increment HBI physical size by PAGE_SIZE until the HBI file can fit
- my $hbi_old = $sectionHash{$i_hbiKey}{physicalRegionSize};
- while ($i_filesize > $sectionHash{$i_hbiKey}{physicalRegionSize})
+ # Increment initial partition physical size by PAGE_SIZE until the initial
+ # partition file can fit
+ my $initPart_old = $sectionHash{$i_initPartKey}{physicalRegionSize};
+ while ($i_filesize > $sectionHash{$i_initPartKey}{physicalRegionSize})
{
- $sectionHash{$i_hbiKey}{physicalRegionSize} += PAGE_SIZE;
+ $sectionHash{$i_initPartKey}{physicalRegionSize} += PAGE_SIZE;
}
- my $hbi_move = $sectionHash{$i_hbiKey}{physicalRegionSize} - $hbi_old;
- my $hbi_end = $sectionHash{$i_hbiKey}{physicalRegionSize} + $hbi_move;
+ my $initPart_move = $sectionHash{$i_initPartKey}{physicalRegionSize} - $initPart_old;
- # Fix up physical offset affected by HBI size change
+ # Fix up physical offsets affected by initial partition size change
foreach my $section (keys %sectionHash)
{
- # Only fix partitions after HBI
+ # Only fix partitions after initial partition
if ( $sectionHash{$section}{physicalOffset} >
- $sectionHash{$i_hbiKey}{physicalOffset} )
+ $sectionHash{$i_initPartKey}{physicalOffset} )
{
my $origoffset = $sectionHash{$section}{physicalOffset};
- $sectionHash{$section}{physicalOffset} += $hbi_move;
+ $sectionHash{$section}{physicalOffset} += $initPart_move;
trace(3, "$this_func: Section $sectionHash{$section}{eyeCatch} : " . sprintf("%X",$origoffset) . " --> " . sprintf("%X",$sectionHash{$section}{physicalOffset}));
}
else
@@ -562,7 +647,6 @@ sub checkForOverlap
}
}
-
###############################################################################
# Display Pnor Layout - Display XML pnor layout more simply
################################################################################
diff --git a/src/build/buildpnor/bpm-utils/LICENSE_PROLOG b/src/build/buildpnor/bpm-utils/LICENSE_PROLOG
new file mode 100644
index 000000000..e57b55f75
--- /dev/null
+++ b/src/build/buildpnor/bpm-utils/LICENSE_PROLOG
@@ -0,0 +1,24 @@
+This is an automatically generated prolog.
+
+$SOURCE_BEGIN_TAG $filename $SOURCE_END_TAG
+
+OpenPOWER $projectName Project
+
+$copyrightStr $copyrightYear
+$copyright_Contributors
+
+Copyright (c) 2019 SMART Modular Technologies, Inc.
+All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
diff --git a/src/build/buildpnor/bpm-utils/imageCrc.c b/src/build/buildpnor/bpm-utils/imageCrc.c
new file mode 100644
index 000000000..8df98a2d3
--- /dev/null
+++ b/src/build/buildpnor/bpm-utils/imageCrc.c
@@ -0,0 +1,479 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/build/buildpnor/bpm-utils/imageCrc.c $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Copyright (c) 2019 SMART Modular Technologies, Inc. */
+/* All Rights Reserved. */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
+/* See the License for the specific language governing permissions and */
+/* limitations under the License. */
+/* */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+//#define DEBUG
+
+//
+// The BPM / SCAP firmware images always will be in one of
+// the two address ranges:
+//
+// Range:(0xA000 - 0xFFFF). Start = 0xA000; Length = 0x6000 (24K)
+// Range:(0x8000 - 0xFFFF). Start = 0x8000; Length = 0x8000 (32K)
+//
+#define FW_MAINIMAGE_START_ADDRESS_8000 (0x8000)
+#define FW_MAINIMAGE_START_ADDRESS_A000 (0xA000)
+#define FW_MAINIMAGE_LAST_ADDRESS (0xFFFF)
+
+//
+// Maximum possible length of the firmware image
+//
+#define FW_MAINIMAGE_MAX_LENGTH (0x8000)
+#define CRC_SIGNATURE_LO (0xAA)
+#define CRC_SIGNATURE_HI (0x55)
+
+#define ADDRESS_CRC_SIGNATURE (0xFF7A) // @FF7A = 0xAA, @FF7B = 0x55
+#define ADDRESS_IMAGE_START (0xFF7C) // @FF7C = Start_Lo, @FF7D = Start_Hi
+#define ADDRESS_IMAGE_CRC (0xFF7E) // @FF7E = CRC_Lo, @FF7F = CRC_Hi
+#define ADDRESS_RESET_VECTOR (0xFFFE) // @FFFE, FFFF
+#define LENGTH_IMAGE_CRC (0x2)
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+
+typedef struct _CRC_CONTEXT {
+ uint16_t mainImageStartAddress;
+ uint16_t mainImageTotalLength;
+} CRC_CONTEXT;
+
+typedef struct _OFFSET_LIST {
+ uint32_t count;
+ uint32_t offset[4];
+} OFFSET_LIST;
+
+char* readNextHex(const char* pLine, uint32_t *value);
+
+uint16_t resetCrc(void);
+
+uint16_t updateCrc(uint8_t byte);
+
+uint16_t calculateCrc(uint8_t* pData, int length);
+
+bool
+parseLine(const char* pLine,
+ uint32_t *mMemoryAddress,
+ CRC_CONTEXT *context,
+ uint8_t *mainImageData);
+
+uint16_t mCrc = 0;
+
+void
+dumpImageData(uint8_t *data, uint32_t dataLength, OFFSET_LIST *offsetToSkipList)
+{
+ bool dontPrint = false;
+
+ uint32_t i, c;
+ uint32_t offsetToSkipCount = 0;
+
+ if (offsetToSkipList != NULL) {
+ offsetToSkipCount = offsetToSkipList->count;
+ }
+
+ printf("MainImageData:\n");
+
+ for (i = 1; i < dataLength - 1; ++i) {
+
+ //
+ // Don't print some of the offsets, when requested
+ //
+ dontPrint = false;
+ for (c = 0; c < offsetToSkipCount; c++) {
+ if ((i - 1) == offsetToSkipList->offset[c]) {
+ dontPrint = true;
+ break;
+ }
+ }
+
+ if (dontPrint) {
+ printf(" ");
+ } else {
+ printf(" %02x", data[i - 1]);
+ }
+
+ if ((i % 16) == 0) {
+ printf("\n");
+ }
+ }
+
+ printf("\n");
+}
+
+uint16_t
+resetCrc(void)
+{
+ mCrc = 0xFFFF;
+ return mCrc;
+}
+
+uint16_t
+updateCrc(uint8_t byte)
+{
+ bool x;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ x = ((mCrc & 0x8000 ? 1 : 0) ^ (byte & 0x80 ? 1 : 0)) ? true : false;
+ mCrc <<= 1;
+ if (x)
+ mCrc ^= 0x1021;
+ byte <<= 1;
+ }
+ return mCrc;
+}
+
+uint16_t
+calculateCrc(uint8_t* pData, int length)
+{
+ //resetCrc();
+ for (; length; --length, ++pData) {
+ updateCrc(*pData);
+ }
+ return mCrc;
+}
+
+char*
+readNextHex(const char* pLine, uint32_t *pValue)
+{
+ uint32_t value = 0;
+
+ // Skip leading white space
+ while (*pLine != '\0' && *pLine <= ' ') {
+ ++pLine;
+ }
+
+ if (*pLine == '\0')
+ return NULL;
+
+ while (true) {
+ if (*pLine >= '0' && *pLine <= '9') {
+ value <<= 4;
+ value += *pLine - '0';
+ } else if (*pLine >= 'a' && *pLine <= 'f') {
+ value <<= 4;
+ value += 0xa + *pLine - 'a';
+ } else if (*pLine >= 'A' && *pLine <= 'F') {
+ value <<= 4;
+ value += 0xA + *pLine - 'A';
+ } else {
+ break;
+ }
+ ++pLine;
+ }
+
+ *pValue = value;
+ return (char*)pLine;
+}
+
+bool
+parseLine(const char* pLine,
+ uint32_t *mMemoryAddress,
+ CRC_CONTEXT *context,
+ uint8_t *mainImageData)
+{
+ uint8_t data[0x100];
+ int dataLength = 0;
+ uint32_t value;
+
+ uint32_t offsetToCopy = 0;
+#ifdef DEBUG
+ int i;
+#endif
+
+ if (*pLine == '@') {
+ // This is a memory address
+ if (readNextHex(pLine + 1, &value) != NULL) {
+ *mMemoryAddress = (uint16_t) value;
+#ifdef DEBUG
+ printf("@Memory Address: 0x%x\n", *mMemoryAddress);
+#endif // DEBUG
+
+ //
+ // Initialize the Context when the firmware image
+ // start address is detected.
+ //
+ if ((*mMemoryAddress == FW_MAINIMAGE_START_ADDRESS_8000) ||
+ (*mMemoryAddress == FW_MAINIMAGE_START_ADDRESS_A000)) {
+
+ context->mainImageStartAddress = value;
+ context->mainImageTotalLength = (FW_MAINIMAGE_LAST_ADDRESS - value) + 1;
+
+ printf("Context: Image Start Address = 0x%x; Image Length = %d (0x%x) \n",
+ context->mainImageStartAddress, context->mainImageTotalLength, context->mainImageTotalLength);
+ }
+ }
+
+ } else if (*pLine == 'q' || *pLine == 'Q') {
+#ifdef DEBUG
+ printf("Done\n");
+ printf("Memory Address: 0x%x\n", *mMemoryAddress);
+#endif // DEBUG
+ return true;
+ } else {
+ do {
+ pLine = readNextHex(pLine, &value);
+
+ if (pLine != NULL) {
+ data[dataLength++] = value;
+ }
+
+ } while (pLine != NULL);
+
+ if (dataLength & 1) {
+ // Keep even byte alignment by padding
+ data[dataLength++] = 0xFF;
+ }
+
+#ifdef DEBUG
+ printf("Write data (%04x) dataLength (0x%x):",
+ *mMemoryAddress, dataLength);
+ for (i = 0; i < dataLength; ++i) {
+ printf(" %02x", data[i]);
+ }
+ printf("\n");
+#endif // DEBUG
+
+ //
+ // added by rananth to calculate the CRC of the main image data.
+ //
+ if ((*mMemoryAddress >= context->mainImageStartAddress) &&
+ (*mMemoryAddress <
+ (context->mainImageStartAddress + context->mainImageTotalLength)))
+ {
+
+ if ( (context->mainImageStartAddress != 0)
+ && (context->mainImageTotalLength != 0) &&
+ (mainImageData != NULL)) {
+
+ //
+ // Copy the main image data bytes (Range: @8000, 0x8000) to the
+ // passed in data buffer.
+ //
+ offsetToCopy = *mMemoryAddress - context->mainImageStartAddress;
+ memcpy(mainImageData + offsetToCopy, data, dataLength);
+
+#ifdef DEBUG
+ printf("Copy data (%04x) dataLength (0x%x):",
+ offsetToCopy, dataLength);
+ printf("\n");
+#endif // DEBUG
+
+ }
+ }
+
+ *mMemoryAddress += dataLength;
+ }
+
+ return true;
+}
+
+
+int
+ProcessFile(char *pFilename, bool verbose)
+{
+ char buffer[0x100];
+ int length;
+ int line;
+
+ uint8_t *mainImageData = 0;
+
+ uint32_t mMemoryAddress = 0;
+ uint32_t crc = 0;
+ uint32_t offsetToSkip;
+ uint32_t offsetToInsert;
+ uint32_t firstPortion = 0;
+ uint32_t secondPortion = 0;
+
+ CRC_CONTEXT context;
+ OFFSET_LIST offsetList;
+
+ // Count the number of lines in the file and use that for progress
+ FILE* pFile = fopen(pFilename, "r");
+ if (!pFile) {
+ printf("Unable to open file %s\n", pFilename);
+ return false;
+ }
+ for (line = 0; !feof(pFile); ++line) {
+ if (fgets(buffer, sizeof(buffer), pFile) == NULL) {
+ break;
+ }
+ }
+
+
+ // Rewind to the beginning of the file
+ fseek(pFile, 0, SEEK_SET);
+
+ //
+ // allocate memory for the main image data
+ //
+ mainImageData = (uint8_t *) malloc(FW_MAINIMAGE_MAX_LENGTH);
+ memset(mainImageData, 0xFF, FW_MAINIMAGE_MAX_LENGTH);
+
+ memset(&context, 0, sizeof(CRC_CONTEXT));
+
+ // Process the lines
+ for (line = 0; !feof(pFile); ++line) {
+ if (fgets(buffer, sizeof(buffer), pFile) == NULL) {
+ break;
+ }
+
+ length = strlen(buffer);
+
+ // Strip off any terminating carriage return/line feed
+ for (; length > 0 && buffer[length - 1] < ' '; --length);
+ buffer[length] = '\0';
+
+ if ( !parseLine((const char*) buffer,
+ &mMemoryAddress,
+ &context,
+ mainImageData) ) {
+ printf("False returned by parseLine \n");
+ break;
+ }
+ }
+
+ if (verbose) {
+
+ printf("==============================================\n");
+ printf("Dump & CRC before selective skip (@FF7E, 2) (@FFFE, 2) \n");
+ printf("==============================================\n");
+
+ dumpImageData(mainImageData, context.mainImageTotalLength, NULL);
+
+ crc = calculateCrc(mainImageData, context.mainImageTotalLength);
+
+ printf("Total Length = %d (0x%x). Final CRC = 0x%x \n",
+ context.mainImageTotalLength, context.mainImageTotalLength, crc);
+
+ }
+
+ //
+ // Insert the Signature (if not already present)
+ //
+ offsetToInsert = ADDRESS_CRC_SIGNATURE - context.mainImageStartAddress;
+ if (mainImageData[offsetToInsert] != CRC_SIGNATURE_LO) {
+ mainImageData[offsetToInsert] = CRC_SIGNATURE_LO;
+ }
+
+ if (mainImageData[offsetToInsert + 1] = CRC_SIGNATURE_HI) {
+ mainImageData[offsetToInsert + 1] = CRC_SIGNATURE_HI;
+ }
+
+ offsetToInsert = ADDRESS_IMAGE_START - context.mainImageStartAddress;
+ mainImageData[offsetToInsert] = (context.mainImageStartAddress & 0xFF); // Lo Byte
+ mainImageData[offsetToInsert + 1] = (context.mainImageStartAddress & 0xFF00) >> 8; // Hi Byte
+
+ //
+ // Skip the following locations for CRC calculation.
+ //
+ // 1. @FF7E, 2
+ // 2. @FFFE, 2
+ //
+ offsetToSkip = ADDRESS_IMAGE_CRC - context.mainImageStartAddress;
+ mainImageData[offsetToSkip] = 0xFF;
+ mainImageData[offsetToSkip + 1] = 0xFF;
+
+ offsetToSkip = ADDRESS_RESET_VECTOR - context.mainImageStartAddress;
+ mainImageData[offsetToSkip] = 0xFF;
+ mainImageData[offsetToSkip + 1] = 0xFF;
+
+ printf("\n");
+ printf("====================================================================================\n");
+ printf("Dump & CRC after Insert (@FF7A, 2) (@FF7C, 2) & Selective skip (@FF7E, 2) (@FFFE, 2) \n");
+ printf("====================================================================================\n");
+
+ memset(&offsetList, 0, sizeof(OFFSET_LIST));
+ offsetList.count = 4;
+ offsetList.offset[0] = ADDRESS_IMAGE_CRC - context.mainImageStartAddress;
+ offsetList.offset[1] = ADDRESS_IMAGE_CRC - context.mainImageStartAddress + 1;
+ offsetList.offset[2] = ADDRESS_RESET_VECTOR - context.mainImageStartAddress;
+ offsetList.offset[3] = ADDRESS_RESET_VECTOR - context.mainImageStartAddress + 1;
+
+ if (verbose) {
+ dumpImageData(mainImageData, context.mainImageTotalLength, &offsetList);
+ }
+
+ // Reset
+ resetCrc();
+
+ firstPortion = ADDRESS_IMAGE_CRC - context.mainImageStartAddress;
+ secondPortion = ADDRESS_RESET_VECTOR - (ADDRESS_IMAGE_CRC + LENGTH_IMAGE_CRC);
+
+ printf("firstPortion: Start = 0x%x Length = %d (0x%x)\n", 0, firstPortion, firstPortion);
+ printf("secondPortion: Start = 0x%x Length = %d (0x%x)\n", firstPortion + 2, secondPortion, secondPortion);
+
+ crc = calculateCrc(mainImageData, firstPortion);
+ crc = calculateCrc(mainImageData + firstPortion + 2, secondPortion);
+
+ printf("Total Length = %d (0x%x). Final CRC = 0x%x \n",
+ (firstPortion + secondPortion), (firstPortion + secondPortion), crc);
+
+ //
+ // Generate the CRC signature lines to be inserted to the firmware image file
+ //
+ printf("---\n");
+ printf("@%x\n", ADDRESS_CRC_SIGNATURE);
+ printf("%02x %02x %02x %02x %02x %02x \n",
+ mainImageData[ADDRESS_CRC_SIGNATURE - context.mainImageStartAddress],
+ mainImageData[ADDRESS_CRC_SIGNATURE - context.mainImageStartAddress + 1],
+ mainImageData[ADDRESS_IMAGE_START - context.mainImageStartAddress],
+ mainImageData[ADDRESS_IMAGE_START - context.mainImageStartAddress + 1],
+ (crc & 0xFF),
+ ((crc & 0xFF00) >> 8));
+ printf("---\n");
+
+
+ free(mainImageData);
+ fclose(pFile);
+}
+
+
+int main(int argc, char *argv[])
+{
+ bool verbose = false;
+
+ if (argc < 2) {
+ printf("Usage: %s <filename> [-v]\n", argv[0]);
+ return -1;
+ }
+
+ if (argc > 2) {
+ if (!strcmp(argv[2], "-v")) {
+ verbose = true;
+ }
+ }
+
+ printf("Processing %s. Verbose=%d \n", argv[1], verbose);
+
+ resetCrc();
+ ProcessFile(argv[1], verbose);
+ return 0;
+}
diff --git a/src/build/buildpnor/bpm-utils/insertBpmFwCrc.py b/src/build/buildpnor/bpm-utils/insertBpmFwCrc.py
new file mode 100755
index 000000000..0631ec5d2
--- /dev/null
+++ b/src/build/buildpnor/bpm-utils/insertBpmFwCrc.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/buildpnor/bpm-utils/insertBpmFwCrc.py $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2019
+# [+] International Business Machines Corp.
+#
+#
+# Copyright (c) 2019 SMART Modular Technologies, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# IBM_PROLOG_END_TAG
+
+import os, sys, time, datetime, glob
+from subprocess import Popen, PIPE
+import shlex
+
+#
+# Function to insert the CRC signature in the
+# firmware image file, inFile, and to generate the
+# signature file, outFile.
+#
+def InsertCrcSignature(inFile, outFile, crcProgram):
+
+ #
+ # Open the outFile
+ #
+ try:
+ print("\nOpening outFile = %s" % outFile)
+ outFileObj = open(outFile, "w")
+ except Exception as e:
+ print "\nException {0} occured, args: {1!r}".format(type(e).__name__, e.args)
+ sys.exit(999)
+
+ #
+ # Read from the inFile and copy the data to the outFile.
+ #
+ # At the right address, insert the SignatureFile data
+ # @FF7A
+ # AA 55 [Start_Lo] [Start_Hi] [Crc_Lo] [Crc_Hi]
+ #
+ # generated from the imageCrc tool, to the outFile.
+ #
+ # The address insertion has to be in the proper ascending order of
+ # addresses given in the inFile in to the outFile.
+ #
+ # For example the outFile should have the following:
+ # =================================================
+ # ...
+ # @8000 / @A000 << The firmware start address is always either one of them.
+ # ....
+ # ....
+ # @FF7A <<<< The "@" addresses must be in ascending order in the Firmware Image file.
+ # AA 55 [Start_Lo] [Start_Hi] [Crc_Lo] [Crc_Hi]
+ #
+ # ....
+ # @FFDA
+ # ....
+
+ # Call imageCrc here
+ proc = Popen([crcProgram, inFile], stdout=PIPE, stderr=PIPE)
+ out,err = proc.communicate()
+ exitCode = proc.returncode
+
+ if exitCode:
+ print "\nCRC generation using imageCrc utility for {0} failed, below are stdout and stderr".format(inFile)
+ print "Command stdout - \n{0}".format(out)
+ print "Command stderr - \n{0}".format(err)
+ sys.exit(999)
+ else:
+ print "\nCRC generation using imageCrc utility successful"
+ print "Command output - \n{0}".format(out)
+
+ # Parse through output of imageCrc and get addr and signature
+ splitLines_crc = out.splitlines()
+ for counter in range(0, len(splitLines_crc)):
+
+ if splitLines_crc[counter].startswith("@"):
+ crcAddressLine = splitLines_crc[counter]
+ crcSignature = splitLines_crc[counter+1].strip().upper()
+
+ # Open infile here
+ # Keep reading infile lines, when read address > the address in signature,
+ # insert signature there
+ try:
+ crcWritten = 0
+ print("\nOpening inFile = %s and writing to outFile now..." % inFile)
+ with open(inFile, "r") as ins:
+ #
+ # TODO: Have the logic to insert the signature from the
+ # SignatureFile inserted at the correct location in the
+ # outFile.
+ #
+
+ for line in ins:
+ if line.startswith("@"):
+ inputFileAddr = line.strip()
+ # If crc already in input file, check if it is equal to calculate value
+ # If equal, write only once, if not equal, write calculated value
+ if crcWritten == 0 and inputFileAddr == crcAddressLine:
+ outFileObj.write(line.strip()+' \n')
+ if ins.next().upper() == crcSignature:
+ print "Correct crc already present at {0} in input file, will skip writing calculated crc again to output file".format(inputFileAddr)
+ else:
+ print "Incorrect crc present at {0} in input file, will write calculated crc {1} to output file".format(inputFileAddr, crcSignature)
+ outFileObj.write(crcSignature+' \n')
+ crcWritten = 1
+ continue
+ # If crc not present, then write calculated value
+ elif crcWritten == 0 and inputFileAddr > crcAddressLine:
+ outFileObj.write(crcAddressLine+'\n')
+ outFileObj.write(crcSignature+' \n')
+ crcWritten = 1
+ outFileObj.write(inputFileAddr.strip()+'\n')
+ else:
+ outFileObj.write(line.strip()+' \n')
+
+ except Exception as e:
+ print "\nException {0} occured, args: {1!r}".format(type(e).__name__, e.args)
+ sys.exit(999)
+
+ print("\nClosing Files\n")
+ outFileObj.close()
+
+## End of insertCrcSignature #########
+
+
+#
+# Main
+#
+if __name__ == '__main__':
+
+ inFile=""
+ outFile=""
+ crcProgram=""
+
+ if (len(sys.argv) < 4):
+ print "\nUsage: %s <IN FILE> <OUT FILE> <CRC PROGRAM>\n" % sys.argv[0]
+ sys.exit(1)
+ else:
+ #
+ # Name of the firmware image file without the signature
+ #
+ inFile = sys.argv[1]
+ if '/' not in inFile:
+ inFile = os.getcwd() + '/' + inFile
+
+ if not os.path.exists(inFile) or os.path.getsize(inFile) == 0:
+ print "\nInput File {0} does not exist or is zero in size".format(inFile)
+ #
+ # Name of the firmware image file to be generated with the signature
+ #
+ outFile = sys.argv[2]
+ if '/' not in outFile:
+ outFile = os.getcwd() + '/' + outFile
+
+ if os.path.exists(outFile):
+ print "\nOutput File {0} already exists, will be overwritten".format(outFile)
+
+ #
+ # Name of the CRC calculation program to be used to calculate the
+ # firmware image CRC
+ #
+ crcProgram = sys.argv[3]
+ if '/' not in crcProgram:
+ crcProgram = os.getcwd() + '/' + crcProgram
+
+ if not os.path.exists(crcProgram) or os.path.getsize(crcProgram) == 0:
+ print "\nCRC Program {0} does not exist or is zero in size".format(crcProgram)
+
+ #
+ # Call the function to insert the CRC signature
+ #
+ InsertCrcSignature(inFile, outFile, crcProgram)
diff --git a/src/build/buildpnor/buildBpmFlashImages.pl b/src/build/buildpnor/buildBpmFlashImages.pl
new file mode 100755
index 000000000..72219e3d9
--- /dev/null
+++ b/src/build/buildpnor/buildBpmFlashImages.pl
@@ -0,0 +1,878 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/buildpnor/buildBpmFlashImages.pl $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2019
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+use strict;
+use warnings;
+use File::Basename;
+use Getopt::Long;
+use Pod::Usage;
+
+my $progName = File::Basename::basename $0;
+my $outputDir=".";
+my $bpmUtilScript="./bpm-utils/insertBpmFwCrc.py";
+my $bpmCrcProgram="./bpm-utils/imageCrc";
+my @files;
+my $cfgHelp=0;
+my $cfgMan=0;
+my $verbose=0;
+
+GetOptions("output-dir=s" => \$outputDir,
+ "bpm-util-script=s" => \$bpmUtilScript,
+ "bpm-crc-program=s" => \$bpmCrcProgram,
+ "image=s" => \@files,
+ "help" => \$cfgHelp,
+ "verbose" => \$verbose,
+ "man" => \$cfgMan ) || pod2usage(-verbose => 0);
+
+pod2usage(-verbose => 1) if $cfgHelp;
+pod2usage(-verbose => 2) if $cfgMan;
+
+# Verify that there aren't any duplicate files in the array of input file names.
+# This is done by creating an anonymous hash of all the file names and comparing
+# the number of keys in the hash to the number of files in @files. If they are
+# not equal then there is a duplicate file of the same name in the input file
+# array.
+if (keys %{{ map {$_, 1} @files }} != @files)
+{
+ die "One or more non-unique --image arguments supplied";
+}
+
+# Verify that there are no duplicate image files of different versions in the
+# input --image arguments. This is done by creating an anonymous hash of all the
+# output file names that would be generated based on the images given and then
+# comparing the number of keys in that hash to the number of original file
+# names. If the number keys and elements of @files aren't equal then there are
+# two images for the same NVDIMM type of different versions present in the
+# input and this is not allowed.
+if (keys %{{map { (generateOutputNameAndVersion($_))[0], 1} @files}} != @files)
+{
+ die "One or more --image arguments are different versions of the same ".
+ "image. Please remove the unused versions.";
+}
+
+if($verbose)
+{
+ print "Output dir = $outputDir\n";
+ print "Input images:\n";
+}
+
+for my $file (@files)
+{
+ if ($verbose)
+ {
+ print " $file\n";
+ }
+
+ generateConfigImage($file,$outputDir);
+ generateFirmwareImage($file,$outputDir);
+}
+
+################################################################################
+# @brief Processes an input file to pull information from its name and content
+# to be used when preparing the output file's binary image. This function
+# will only emit the binaries for the firmware portion of the BPM update.
+# The final binary will be organized in the following way:
+# Byte 1: Major version number (MM)
+# Byte 2: Minor version number (mm)
+# Byte 3-4: N number of blocks in the file (NN NN)
+# Byte 5-EOF: Blocks of the form:
+# BLOCK_SIZE Byte 1: X number of bytes in block excluding
+# this byte. (XX)
+# ADDRESS_OFFSET Byte 2-3: Original address offset of the
+# first data byte. (AD DR)
+# DATA_BYTES Byte 4-X: Firmware data bytes (DD)
+#
+# Example file output:
+# 01 03 00 01 06 80 00 6a 14 31 80
+# MM mm NN NN XX AD DR DD DD DD DD
+#
+# @param[in] i_fileName Name of file
+# @param[in] i_outputDir Dir to emit binary to
+#
+# @return N/A
+################################################################################
+sub generateFirmwareImage
+{
+ my ($i_fileName, $i_outputDir) = @_;
+ my $this_func = (caller(0))[3];
+
+ my $intermediateFileName = generateIntermediateImage($i_fileName,$i_outputDir);
+
+ open my $inputFileHandle, '<:encoding(UTF-8)', $intermediateFileName
+ or die "Failed to open $intermediateFileName";
+
+ my ($name, @version) = generateOutputNameAndVersion($i_fileName);
+
+ my $imageFile = $i_outputDir . "/" . $name . "FW.bin";
+
+ open my $outputFileHandle, '>:raw', $imageFile
+ or die "Failed to open $imageFile";
+
+ # Indicates whether or not we're in the firmware section of the image file.
+ my $inFirmwareSection = undef;
+
+ # Keep track of the number of blocks we'll be writing to the output file.
+ my $numberOfBlocks = 0;
+
+ # This is the starting address of the first byte of the payload data.
+ my $currentAddress = 0;
+
+ # The address offsets in the file are prefixed with the @ symbol.
+ use constant ADDRESS_LINE => "\@";
+ use constant FW_START_ADDRESS_8000 => "\@8000";
+ use constant FW_START_ADDRESS_A000 => "\@A000";
+
+ # Spec for BPM updates says that the maximum size for the data portion of
+ # the payload is 16 bytes
+ use constant MAXIMUM_DATA_BYTES_FOR_PAYLOAD => 16;
+
+ # Ensure that the diamond operator ( <> ) is searching for \n to determine
+ # where the end of a line is in the image file.
+ local $/ = "\n";
+
+ my $blocks = undef;
+ while (my $line = <$inputFileHandle>)
+ {
+ # Strip off the end-of-line character \n and optionally \r if it exists.
+ # Since the image files were created on a windows OS and this script
+ # runs on linux this will not be handled properly by chomp.
+ $line =~ s/\r?\n$//;
+
+ # The end of the firmware data section is marked by a 'q'
+ if (substr($line, 0, 1) eq "q")
+ {
+ last;
+ }
+
+ # There are two possible addresses where the firmware data section can
+ # start: @8000 or @A000. Ignore all data until we reach either of those
+ # addresses since it's only after that, that the firmware data begins.
+ if (substr($line, 0, 1) eq ADDRESS_LINE)
+ {
+ $currentAddress = hex substr($line, 1, 4);
+ if ($verbose)
+ {
+ printf("Found address offset: 0x%04x\n", $currentAddress);
+ }
+
+ if ( ($line eq FW_START_ADDRESS_8000)
+ || ($line eq FW_START_ADDRESS_A000))
+ {
+ $inFirmwareSection = 1;
+ }
+ next;
+ }
+
+ # Don't process lines that aren't firmware data.
+ if (not $inFirmwareSection)
+ {
+ next;
+ }
+
+ # Process the line into blocks of the form: size, address offset, bytes
+ # Size: The size of the block.
+ # Note: The size here is only the size of the block itself. It does not
+ # have any correspondence to the final payload size which will be
+ # calculated during payload construction in hostboot code.
+ # Address offset: The address offset of the first byte of payload data.
+ # This will be reused during payload construction in
+ # hostboot code.
+ # Bytes: The payload data. This is the firmware data to be written to
+ # the BPM.
+
+ # The length of the payload data. The maximum size of payload data is 16
+ # bytes which is conveniently the maximum size of any line in the file
+ # minus spaces and carriage return/line feeds.
+ my $dataLength = calculateDataLength($line);
+
+ if ($dataLength > MAXIMUM_DATA_BYTES_FOR_PAYLOAD)
+ {
+ die "$dataLength exceeds the maximum size for the data portion of" .
+ "the payload (". MAXIMUM_DATA_BYTES_FOR_PAYLOAD .")";
+ }
+
+ # total size of the block is the number of bytes from the dataLength
+ # plus two more for the address size.
+ my $blockSize = $dataLength + 2;
+
+ # Pack the block size
+ # uint8_t
+ $blocks .= pack("C", $blockSize);
+
+ # Pack the starting address offset of the firmware data bytes
+ # uint16_t
+ $blocks .= pack("n", $currentAddress);
+
+ # Pack the payload data.
+ # Since the line is a string where each byte is an ASCII representation
+ # of the hex data separated by spaces, we must split the line by the
+ # space character and then write each byte string one at a time. Hence,
+ # the template "(H2)*". Each element is processed with the H2 part and
+ # the * just says to do this for all elements in the array emitted by
+ # split.
+ $blocks .= pack("(H2)*", split(/ /, $line));
+
+ # Increment the address offset by the number of firmware data
+ # bytes processed.
+ $currentAddress += $dataLength;
+
+ ++$numberOfBlocks;
+ }
+
+ if ($verbose)
+ {
+ print "number of blocks: $numberOfBlocks\n";
+ }
+
+ if (!defined($blocks))
+ {
+ die "Unable to process image file: $intermediateFileName";
+ }
+
+ # Write the version information to the file.
+ print $outputFileHandle pack("(H2)*", @version)
+ or die "Failed to write to output file: $imageFile";
+
+ # Write the number of blocks in the file.
+ # uint16_t
+ print $outputFileHandle pack("n", $numberOfBlocks)
+ or die "Failed to write to output file: $imageFile";
+
+ # Write the blocks to the file
+ print $outputFileHandle $blocks
+ or die "Failed to write to output file: $imageFile";
+
+ close $inputFileHandle
+ or die "Failed to close input file: $intermediateFileName";
+ unlink $intermediateFileName
+ or die "Failed to remove temporary file $intermediateFileName";
+ close $outputFileHandle
+ or die "Failed to close output file: $imageFile";
+}
+
+################################################################################
+# @brief Processes an input file to pull information from its name and content
+# to be used when preparing the output file's binary image. This function
+# will only emit the binaries for the configuration data portion of the
+# BPM update.
+# The final binary will be organized in the following way:
+# Byte 1: Major version number (MM)
+# Byte 2: Minor version number (mm)
+# Byte 3: N number of fragments in the file (NN)
+# Byte 4-EOF: Fragments of the form:
+# FRAGMENT_SIZE Byte 1: X number of bytes in fragment data
+# section. (XX)
+# INDEX_OFFSET Byte 2-3: Each BPM's config section is unique
+# to itself. So, during update the
+# contents of a BPM's config data
+# will be dumped into a buffer.
+# These bytes will be used as an
+# offset into that buffer from which
+# overwritting will take place.
+# (IN DX)
+# DATA_BYTES Byte 4-X: Configuration data bytes (DD)
+#
+# Example file output:
+# 01 05 01 04 01 28 6a 14 31 80
+# MM mm NN XX IN DX DD DD DD DD
+#
+# @algorithm Each BPM has a config data section unique to itself so the data
+# on each BPM must be dumped into a buffer and then "merged" with
+# the config data from the update. The config data section is
+# divided into 4 segments. A, B, C, and D. These segments appear
+# in reverse order. Since it is known which "fragments" of each
+# segment has to be updated this function will extract those
+# fragments from the update file and organize them as described
+# above so that hostboot can handle the rest.
+#
+# SegmentDataFromBPM: Copy of the segment data taken from the BPM (dump)
+#
+# SegmentDataFromFWImage: Copy of the segment data from the firmware image file.
+# This could be the firmware image to be upgraded to or
+# to be downgraded to. These are what will become
+# fragments.
+#
+# Segment Address Data Source
+# =====================================
+# D 1800 - 187F <---- [SegmentDataFromFWImage: 1800 - 187F]
+#
+# C 1880 - 18FF <---- [SegmentDataFromBPM: 1880 - 18FF]
+#
+# B 1900 - 197F <---- [SegmentDataFromBPM: 1900 - 1927]
+# [SegmentDataFromFWImage: 1928 - 1979]
+# [SegmentDataFromBPM: 197A - 197D]
+# [SegmentDataFromFWImage: 197E - 197F]
+#
+# A 1980 - 19FF <---- [SegmentDataFromBPM: 1980 - 19FF]
+#
+# @param[in] i_fileName Name of file
+# @param[in] i_outputDir Dir to emit binary to
+#
+# @return N/A
+################################################################################
+sub generateConfigImage
+{
+ my ($i_fileName, $i_outputDir) = @_;
+ my $this_func = (caller(0))[3];
+
+ open my $inputFileHandle, '<:encoding(UTF-8)', $i_fileName
+ or die "Failed to open $i_fileName";
+
+ my ($name, @version) = generateOutputNameAndVersion($i_fileName);
+
+ my $imageFile = $i_outputDir . "/" . $name . "CONFIG.bin";
+
+ open my $outputFileHandle, '>:raw', $imageFile
+ or die "Failed to open $imageFile";
+
+ # Indicates whether or not we're in the config section of the image file.
+ my $inConfigSection = undef;
+
+ # Keep track of the number of fragments we'll be writing to the output file.
+ my $numberOfFragments = 0;
+
+ # Used to keep track of which byte is the current byte being looked at in
+ # the file.
+ my $currentAddress = 0;
+
+ # The address offsets in the file are prefixed with the @ symbol.
+ use constant ADDRESS_LINE => "\@";
+ use constant CONFIG_START_ADDRESS_MARKER => "\@1800";
+ use constant CONFIG_START_ADDRESS => 0x1800;
+
+ # Segment data start addresses relative to config data start address.
+ use constant SEGMENT_D_START_ADDRESS => 0x000;
+ use constant SEGMENT_C_START_ADDRESS => 0x080;
+ use constant SEGMENT_B_START_ADDRESS => 0x100;
+ use constant SEGMENT_A_START_ADDRESS => 0x180;
+
+ # Spec for BPM updates says that the maximum size for the data portion of
+ # the payload is 16 bytes
+ use constant MAXIMUM_DATA_BYTES_FOR_PAYLOAD => 16;
+
+ my $fragments = undef;
+ my $fragmentData = undef;
+ my $fragmentSize = 0;
+
+ # The offset into the segment data where the fragment data will be written.
+ # In hostboot code, this will be a 512 byte buffer that holds a dump of the
+ # BPM's unique segment data.
+ my $fragmentOffset = SEGMENT_D_START_ADDRESS;
+
+ # Ensure that the diamond operator ( <> ) is searching for \n to determine
+ # where the end of a line is in the image file.
+ local $/ = "\n";
+
+ while (my $line = <$inputFileHandle>)
+ {
+ # Strip off the end-of-line character \n and optionally \r if it exists.
+ # Since the image files were created on a windows OS and this script
+ # runs on linux this will not be handled properly by chomp.
+ $line =~ s/\r?\n$//;
+
+ # Look for @1800 starting address marker.
+ #
+ # If found, start reading the data from the file until the next "@"
+ # marker or "q" starting markers are found.
+ #
+ # It is possible that the input file might not have the distinct @1800
+ # marker. In that case, the [currentAddress] variable is used to track
+ # the 0x1800 address in the input file.
+ if (substr($line, 0, 1) eq "q")
+ {
+ last;
+ }
+
+ if (substr($line, 0, 1) eq ADDRESS_LINE)
+ {
+ $currentAddress = hex substr($line, 1);
+ if ($verbose)
+ {
+ printf("Found address offset: 0x%04x\n", $currentAddress);
+ }
+
+ if ($line eq CONFIG_START_ADDRESS_MARKER)
+ {
+ $inConfigSection = 1;
+ }
+ next;
+ }
+
+ # Process the line into fragments of the form: size, address offset,
+ # and bytes.
+ #
+ # Size: The size of the fragment data.
+ # Note: The size only corresponds to the size of the fragment data
+ # itself. In hostboot code, this size will indicate how much of
+ # the BPM's segment data will be overwritten for the given
+ # fragment.
+ # Address offset: The address offset of the start byte of segment data.
+ # This will be used to determine where to start
+ # overwritting segment data from the BPM config dump.
+ # Bytes: The bytes to write to the BPM config data dump buffer.
+
+ # The length of the line. The maximum size of any line is 16 bytes.
+ my $dataLength = calculateDataLength($line);
+
+ if ($dataLength > MAXIMUM_DATA_BYTES_FOR_PAYLOAD)
+ {
+ die "$dataLength exceeds the maximum size for the data portion of" .
+ "the payload (". MAXIMUM_DATA_BYTES_FOR_PAYLOAD .")";
+ }
+
+ # If the CONFIG_START_ADDRESS_MARKER is missing from the file then this
+ # will serve as the backup method to locating the config data within the
+ # image file. Otherwise, this will always evaluate to false.
+ if (($currentAddress + $dataLength) == CONFIG_START_ADDRESS)
+ {
+ # The next line is the start of the config data section of the
+ # image. So, skip the current line and move into the config section.
+ $inConfigSection = 1;
+ $currentAddress += $dataLength;
+ next;
+ }
+
+ # Don't process lines that aren't config data.
+ if (not $inConfigSection)
+ {
+ next;
+ }
+
+ # Create Segment D fragment. For Segment D, the entire segment is
+ # required to be updated during the firmware update. So, create a
+ # fragment that encompasses the whole segment.
+ if ($currentAddress < CONFIG_START_ADDRESS + SEGMENT_C_START_ADDRESS)
+ {
+ # Increase the fragmentSize by the amount being appended to the
+ # fragment.
+ $fragmentSize += $dataLength;
+
+ # Pack the fragment data.
+ # Since the line is a string where each byte is an ASCII
+ # representation of the hex data separated by spaces, we
+ # must split the line by the space character and then write
+ # each byte string one at a time. Hence, the template
+ # "(H2)*". Each element is processed with the H2 part and
+ # the * just says to do this for all elements in the array
+ # emitted by split.
+ $fragmentData .= pack("(H2)*", split(/ /, $line));
+
+ if($currentAddress ==
+ (CONFIG_START_ADDRESS + SEGMENT_C_START_ADDRESS - 0x10))
+ {
+ $fragments .= createFragment($fragmentSize,
+ $fragmentOffset,
+ $fragmentData,
+ $numberOfFragments);
+ }
+ }
+ # Segment C is skipped over implicitly since there is no segment data in
+ # segment C that needs to be applied to the BPM.
+ elsif ( ($currentAddress >=
+ (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS))
+ && ($currentAddress <
+ (CONFIG_START_ADDRESS + SEGMENT_A_START_ADDRESS)))
+ {
+ # Work on Segment B data. There will be two fragments created for
+ # this segment.
+ # Fragment 1: [0x1928 - 0x1979]
+ # Fragment 2: [0x197E - 0x197F]
+ my $createFragment = 0;
+
+ # According to SMART's documentation, each segment must be 8 lines
+ # of 16 byte rows. Since we are searching for a specific region in
+ # segment B to create a fragment from we bound the fragment packing
+ # code by the borders of that region.
+ if ( ($currentAddress >=
+ (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x20))
+ && ($currentAddress <
+ (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x80)))
+ {
+ # Only need bytes from [0x1928 to 0x1979] to form Fragment 1.
+ # If we are not on the bounds of the fragment then we can simply
+ # pack the data and update the size.
+ # Otherwise, we must do some extra trimming.
+ if ($currentAddress ==
+ (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x20))
+ {
+ # This is the begining of Fragment 1's range. Trim off the
+ # bytes with offsets less than 0x1928.
+
+ # Set the fragmentOffset to the start of the range
+ $fragmentOffset = SEGMENT_B_START_ADDRESS
+ + 0x28;
+
+ # Split the line into individual bytes and only pack
+ # required bytes.
+ my @bytes = split(/ /, $line);
+
+ # Drop the first eight bytes since they aren't in the range.
+ splice @bytes, 0, 8;
+
+ $fragmentSize += scalar @bytes;
+
+ $fragmentData .= pack("(H2)*", @bytes);
+
+ # Since this is the begining of Fragment 1, there is still
+ # data left to be appended to this fragment. So don't call
+ # createFragment().
+ }
+ elsif ($currentAddress ==
+ (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x70))
+ {
+ # This is the last line in the range of Fragment 1 and the
+ # only line where Fragment 2 data is. So, trimming is
+ # required to finalize Fragment 1 and create Fragment 2.
+
+ # Start by finishing off Fragment 1.
+ # Split the line into individual bytes and only pack
+ # required bytes.
+ my @bytes = split(/ /, $line);
+
+ # Drop the last six bytes since they aren't
+ # in range [0x1928-0x1979]
+ splice @bytes, 10, 6;
+
+ $fragmentSize += scalar @bytes;
+
+ $fragmentData .= pack("(H2)*", @bytes);
+
+ # Now that Fragment 1 is completed, create the fragment and
+ # append it to the list of fragments.
+ $fragments .= createFragment($fragmentSize,
+ $fragmentOffset,
+ $fragmentData,
+ $numberOfFragments);
+
+ # Now work on Fragment 2.
+ # Only need bytes from [0x197E to 0x197F] to form Fragment 2
+
+ # Set the fragmentOffset
+ $fragmentOffset = SEGMENT_B_START_ADDRESS
+ + 0x7E;
+
+ # Split the line into individual bytes and only pack
+ # required bytes.
+ @bytes = split(/ /, $line);
+
+ # Drop the first 14 bytes since they aren't in
+ # range [0x197E to 0x197F]
+ splice @bytes, 0, 14;
+
+ $fragmentSize += scalar @bytes;
+
+ $fragmentData .= pack("(H2)*", @bytes);
+
+ # Fragment 2 is complete. Create the fragment and append to
+ # list of fragments.
+ $fragments .= createFragment($fragmentSize,
+ $fragmentOffset,
+ $fragmentData,
+ $numberOfFragments);
+
+ }
+ else
+ {
+ # We are not on a fragment boundary, so append the full line
+ # of data to Fragment 1.
+
+ # Increase the fragmentSize by the amount being appended to
+ # the fragment.
+ $fragmentSize += $dataLength;
+
+ # Pack the fragment data.
+ # Since the line is a string where each byte is an ASCII
+ # representation of the hex data separated by spaces, we
+ # must split the line by the space character and then write
+ # each byte string one at a time. Hence, the template
+ # "(H2)*". Each element is processed with the H2 part and
+ # the * just says to do this for all elements in the array
+ # emitted by split.
+ $fragmentData .= pack("(H2)*", split(/ /, $line));
+ }
+ }
+ }
+ elsif ($currentAddress >=
+ (CONFIG_START_ADDRESS + SEGMENT_A_START_ADDRESS))
+ {
+ # Don't need to create fragments in Segment A.
+ last;
+ }
+
+ # Increment the address offset by the number of firmware data
+ # bytes processed.
+ $currentAddress += $dataLength;
+ }
+
+ if ($verbose)
+ {
+ print "number of fragments: $numberOfFragments\n";
+ }
+
+ if (!defined($fragments))
+ {
+ die "Unable to process image file: $i_fileName";
+ }
+
+ # Write the version information to the file.
+ print $outputFileHandle pack("(H2)*", @version)
+ or die "Failed to write to output file: $imageFile";
+
+ # Write the number of fragments in the file.
+ # uint16_t
+ print $outputFileHandle pack("n", $numberOfFragments)
+ or die "Failed to write to output file: $imageFile";
+
+ # Write the fragments to the file
+ print $outputFileHandle $fragments
+ or die "Failed to write to output file: $imageFile";
+
+ close $inputFileHandle
+ or die "Failed to close input file: $i_fileName";
+ close $outputFileHandle
+ or die "Failed to close output file: $imageFile";
+}
+
+################################################################################
+# @brief Transforms the input file name into the output file name and extracts
+# the version info from the file name since that info is not present in
+# the image file itself.
+#
+# @param[in] i_fileName Name of file
+#
+# @return An array that contains the filename as the first
+# element and the version info array as the second.
+################################################################################
+sub generateOutputNameAndVersion
+{
+ # Input Parameter
+ my $i_fileName = shift;
+
+ # Parse the file name into its filename, path, and suffix.
+ my ($name, $path, $suffix) = fileparse($i_fileName, ".txt");
+
+ # Split the filename by underscore to access the information contained in
+ # the file name.
+ # According to the spec an example filename would be of the form:
+ # S R C A80 6 2 IBM H 01 1 B _FULL_ FW_Rev1.03_02282019.txt
+ # ^ ^ ^
+ # 1: Number of NVDIMM interfaces (1 = 32GB, 2 = 16GB)
+ # _FULL_: The image contains the firmware and configuration data.
+ # Rev1.03: Version of this image file
+ my @fileNameComponents = split(/_/, $name);
+
+ # The NVDIMM interface types supported
+ my %nvdimmTypes = ( 1 => "32GB",
+ 2 => "16GB", );
+
+ # Extract the NVDIMM Interface number from filename
+ my $nvdimmInterfaceNumber = substr($fileNameComponents[0], -2, 1);
+
+ # Convert interface number to the appropriate human-readable type
+ my $nvdimmType = "";
+ if (exists($nvdimmTypes{$nvdimmInterfaceNumber}))
+ {
+ $nvdimmType = $nvdimmTypes{$nvdimmInterfaceNumber};
+ }
+ else
+ {
+ die "NVDIMM Interface Type $nvdimmInterfaceNumber Unsupported";
+ }
+
+ # Extract the version from the filename and convert it to a two one byte hex
+ # strings.
+ my @versionComponents = split(/\./, $name);
+ my @version =
+ sprintf("%.2X", substr($versionComponents[0], -2, 2) =~ /([0-9]+)/g);
+ push(@version,
+ sprintf("%.2X", substr($versionComponents[1], 0, 2) =~ /([0-9]+)/g));
+
+
+ if ($verbose)
+ {
+ print "\tNVDIMM Type -> ". $nvdimmType ."\n";
+ print "\tVersion Info -> Major: " . $version[0] .
+ " Minor: " . $version[1] . "\n";
+ }
+
+ return ($nvdimmType."-NVDIMM-BPM-", @version);
+
+}
+
+################################################################################
+# @brief Processes input image file to generate CRC signature, firmware start
+# address, and calculated CRC bytes at address marker @FF7A. This
+# function simply calls SMART's supplied python script to perform the
+# operations. This intermediate file is only used during the firmware
+# binary generation.
+#
+# @param[in] i_fileName Name of file
+#
+# @return txt file name The temporary file that has the calculated CRC
+################################################################################
+sub generateIntermediateImage
+{
+ my ($i_fileName, $i_outputDir) = @_;
+
+ # Parse the file name into its filename, path, and suffix.
+ my ($name, $path, $suffix) = fileparse($i_fileName, ".txt");
+
+ # Parse the file name into its filename, path, and suffix.
+ my ($utilName, $utilPath, $utilSuffix) = fileparse($bpmUtilScript, ".txt");
+
+ my $intermediateFileName = $i_outputDir . $name . ".crc";
+
+ # Call the python script which will insert the CRC
+ my $pythonReturn = system($bpmUtilScript,
+ $i_fileName,
+ $intermediateFileName,
+ $bpmCrcProgram);
+
+ return $intermediateFileName;
+
+}
+
+################################################################################
+# @brief Creates a new fragment by packing the fragment size, offset, and data;
+# then it cleans up the fragment parameters so that the caller doesn't
+# have to.
+#
+# @param[in] io_fragmentSize The size of the fragment data section.
+# @param[in] i_fragmentOffset The offset into the BPM config dump buffer
+# that this fragment should begin overwritting
+# at.
+# @param[in] io_fragmentData The partial config segment data from the
+# flash image to be written to the BPM during
+# the update procedure.
+# @param[in] io_numberOfFragments This parameter incremented by this function
+# so the caller can keep track of how many
+# fragments have been created so far. However,
+# due to the messiness of perl syntax this
+# parameter is created as a visual reference
+# only and not used directly.
+#
+# @return The created fragment
+################################################################################
+sub createFragment
+{
+ my ($io_fragmentSize,
+ $i_fragmentOffset,
+ $io_fragmentData,
+ $io_numberOfFragments) = @_;
+
+ # Pack the fragment size
+ # uint8_t
+ my $fragment .= pack("C", $io_fragmentSize);
+
+ # Pack the BPM dump offset.
+ # uint16_t
+ $fragment .= pack("n", $i_fragmentOffset);
+
+ # Pack the fragment data
+ $fragment .= $io_fragmentData;
+
+ # Keep track of number of fragments in output
+ $_[3]++; # $io_numberOfFragments
+
+ # Reset variables
+ $_[2] = undef; # $io_fragmentData
+ $_[0] = 0; # $io_fragmentSize
+
+ return $fragment;
+}
+
+################################################################################
+# @brief Calculates the data length of the line by stripping all spaces for it
+# dividing by the number of bytes on the line.
+#
+# @param[in] i_line The line to calculate the length on.
+#
+# @return The number of bytes on the line (length).
+################################################################################
+sub calculateDataLength
+{
+ my $i_line = shift;
+
+ # Strip all the spaces from the line.
+ $i_line =~ s/\s+//g;
+
+ # Each line is plain text where each byte is separated by spaces.
+ # To determine how many bytes are on the line, divide by characters per byte
+ use constant CHARS_PER_BYTE => 2;
+ my $dataLength = length($i_line) / CHARS_PER_BYTE;
+
+ return $dataLength;
+}
+
+__END__
+
+=head1 NAME
+
+buildBpmFlashImage.pl
+
+=head1 SYNOPSIS
+
+buildBpmFlashImage.pl [..]
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help>
+
+Prints a brief help message and exits.
+
+=item B<--man>
+
+Prints the manual page and exits.
+
+=item B<--output-dir>
+
+Path to directory to emit the output files to.
+
+=item B<--image>
+
+File containing a BPM flash update script. More than one --image
+argument can be provided. If no images are supplied, the script will do
+nothing.
+
+=back
+
+=head1 DESCRIPTION
+
+B<buildBpmFlashImage.pl> will process a set of one or more BPM flash update
+scripts in .txt format by transforming the lines of text into blocks of binary
+data of the form BLOCK_SIZE, ADDRESS_OFFSET, PAYLOAD. The final binary output by
+this script will have the first 2 bytes be the version info (first byte Major,
+second Minor), then followed by two bytes that give the number of blocks in the
+file, and the remainder of the file will be blocks organized in the following
+way:
+
+BLOCK_SIZE is the number of bytes following the BLOCK_SIZE byte.
+ADDRESS_OFFSET is the offset the PAYLOAD data originally came from within the .txt file.
+PAYLOAD is the data, along with the ADDRESS_OFFSET, that will be used to construct the payloads to send to the BPM to perform the update.
+
+=cut
diff --git a/src/build/buildpnor/buildpnor.pl b/src/build/buildpnor/buildpnor.pl
index 227e8fe0f..eb76f868f 100755
--- a/src/build/buildpnor/buildpnor.pl
+++ b/src/build/buildpnor/buildpnor.pl
@@ -6,7 +6,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2018
+# Contributors Listed Below - COPYRIGHT 2012,2019
# [+] International Business Machines Corp.
#
#
@@ -56,6 +56,7 @@ my %SideOptions = (
B => "B",
sideless => "sideless",
);
+my $editedLayoutLocation = "";
if ($#ARGV < 0) {
usage();
@@ -95,6 +96,10 @@ for (my $i=0; $i < $#ARGV + 1; $i++)
elsif($ARGV[$i] =~ /--test/) {
$testRun = 1;
}
+ elsif($ARGV[$i] =~ /--editedLayoutLocation/) {
+ $editedLayoutLocation = $ARGV[++$i];
+ trace(2, "Location where the edited layout file will be placed: $editedLayoutLocation");
+ }
else {
traceErr("Unrecognized Input: $ARGV[$i]");
exit 1;
@@ -112,7 +117,8 @@ if (-e $pnorBinName)
}
#Load PNOR Layout XML file
-loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun);
+loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun,
+ $editedLayoutLocation);
#Verify all the section files exist
verifyFilesExist(\%pnorLayout, \%binFiles);
@@ -621,6 +627,7 @@ print <<"ENDUSAGE";
--fpartCmd invoke string for executing the fpart tool
--fcpCmd invoke string for executing the fcp tool
--test Output test-only sections.
+ --editedLayoutLocation <directory> Location to place edited layout file
Current Limitations:
--TOC Records must be 4 or 8 bytes in length
diff --git a/src/build/buildpnor/defaultPnorLayout.xml b/src/build/buildpnor/defaultPnorLayout.xml
index bb59a60fa..6e7c88e3d 100644
--- a/src/build/buildpnor/defaultPnorLayout.xml
+++ b/src/build/buildpnor/defaultPnorLayout.xml
@@ -89,7 +89,6 @@ Layout Description
<section>
<description>Guard Data (20K)</description>
<eyeCatch>GUARD</eyeCatch>
- <physicalOffset>0x2C000</physicalOffset>
<physicalRegionSize>0x5000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -98,7 +97,7 @@ Layout Description
<description>DIMM JEDEC (288K)</description>
<eyeCatch>DJVPD</eyeCatch>
<!--NOTE: MUST update standalone.simics if offset changes -->
- <physicalOffset>0x31000</physicalOffset>
+ <physicalOffset>0x31000</physicalOffset>
<physicalRegionSize>0x48000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -124,7 +123,6 @@ Layout Description
<section>
<description>Hostboot Base (1MB)</description>
<eyeCatch>HBB</eyeCatch>
- <physicalOffset>0x151000</physicalOffset>
<physicalRegionSize>0x100000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -133,7 +131,6 @@ Layout Description
<section>
<description>Hostboot Data (2MB)</description>
<eyeCatch>HBD</eyeCatch>
- <physicalOffset>0x251000</physicalOffset>
<physicalRegionSize>0x200000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -142,7 +139,6 @@ Layout Description
<section>
<description>Hostboot Extended image (14.22MB w/o ECC)</description>
<eyeCatch>HBI</eyeCatch>
- <physicalOffset>0x451000</physicalOffset>
<physicalRegionSize>0x1000000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -151,7 +147,6 @@ Layout Description
<section>
<description>SBE-IPL (Staging Area) (752K)</description>
<eyeCatch>SBE</eyeCatch>
- <physicalOffset>0x1451000</physicalOffset>
<physicalRegionSize>0xBC000</physicalRegionSize>
<sha512perEC/>
<sha512Version/>
@@ -161,7 +156,6 @@ Layout Description
<section>
<description>HCODE Ref Image (1.125MB)</description>
<eyeCatch>HCODE</eyeCatch>
- <physicalOffset>0x150D000</physicalOffset>
<physicalRegionSize>0x120000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -170,17 +164,15 @@ Layout Description
<section>
<description>Hostboot Runtime Services for Sapphire (7.0MB)</description>
<eyeCatch>HBRT</eyeCatch>
- <physicalOffset>0x162D000</physicalOffset>
<physicalRegionSize>0x700000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
</section>
<section>
- <description>Payload (19.875MB)</description>
+ <description>Payload (6MB)</description>
<eyeCatch>PAYLOAD</eyeCatch>
- <physicalOffset>0x1D2D000</physicalOffset>
- <physicalRegionSize>0x13E0000</physicalRegionSize>
+ <physicalRegionSize>0x0600000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
@@ -188,7 +180,6 @@ Layout Description
<section>
<description>Special PNOR Test Space (36K)</description>
<eyeCatch>TEST</eyeCatch>
- <physicalOffset>0x310D000</physicalOffset>
<physicalRegionSize>0x9000</physicalRegionSize>
<testonly/>
<side>sideless</side>
@@ -199,7 +190,6 @@ Layout Description
from skipping header. Signing is forced in build pnor phase -->
<description>Special PNOR Test Space with Header (36K)</description>
<eyeCatch>TESTRO</eyeCatch>
- <physicalOffset>0x3116000</physicalOffset>
<physicalRegionSize>0x9000</physicalRegionSize>
<side>sideless</side>
<testonly/>
@@ -210,7 +200,6 @@ Layout Description
<section>
<description>Hostboot Bootloader (28K)</description>
<eyeCatch>HBBL</eyeCatch>
- <physicalOffset>0x311F000</physicalOffset>
<!-- Physical Size includes Header rounded to ECC valid size -->
<!-- Max size of actual HBBL content is 20K and 22.5K with ECC -->
<physicalRegionSize>0x7000</physicalRegionSize>
@@ -219,17 +208,8 @@ Layout Description
<ecc/>
</section>
<section>
- <description>Global Data (36K)</description>
- <eyeCatch>GLOBAL</eyeCatch>
- <physicalOffset>0x3126000</physicalOffset>
- <physicalRegionSize>0x9000</physicalRegionSize>
- <side>sideless</side>
- <ecc/>
- </section>
- <section>
<description>Ref Image Ring Overrides (20K)</description>
<eyeCatch>RINGOVD</eyeCatch>
- <physicalOffset>0x312F000</physicalOffset>
<physicalRegionSize>0x5000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -237,7 +217,6 @@ Layout Description
<section>
<description>SecureBoot Key Transition Partition (16K)</description>
<eyeCatch>SBKT</eyeCatch>
- <physicalOffset>0x3134000</physicalOffset>
<physicalRegionSize>0x4000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -245,7 +224,6 @@ Layout Description
<section>
<description>OCC Lid (1.125M)</description>
<eyeCatch>OCC</eyeCatch>
- <physicalOffset>0x3138000</physicalOffset>
<physicalRegionSize>0x120000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -256,7 +234,6 @@ Layout Description
<!-- We need 266KB per module sort, going to support
40 tables by default, plus ECC -->
<eyeCatch>WOFDATA</eyeCatch>
- <physicalOffset>0x3258000</physicalOffset>
<!-- TODO RTC: 208004
Reduced by MB total to allow HBI + tests to
fit in PNOR, need to increase back 1 MB once HBI size
@@ -269,7 +246,6 @@ Layout Description
<section>
<description>FIRDATA (12K)</description>
<eyeCatch>FIRDATA</eyeCatch>
- <physicalOffset>0x3E58000</physicalOffset>
<physicalRegionSize>0x3000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -277,7 +253,6 @@ Layout Description
<section>
<description>Memory Data (128K)</description>
<eyeCatch>MEMD</eyeCatch>
- <physicalOffset>0x3E5B000</physicalOffset>
<physicalRegionSize>0x20000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -286,7 +261,6 @@ Layout Description
<section>
<description>Secureboot Test Load (12K)</description>
<eyeCatch>TESTLOAD</eyeCatch>
- <physicalOffset>0x3E7B000</physicalOffset>
<physicalRegionSize>0x3000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -295,7 +269,6 @@ Layout Description
<section>
<description>Centaur Hw Ref Image (12K)</description>
<eyeCatch>CENHWIMG</eyeCatch>
- <physicalOffset>0x3E7E000</physicalOffset>
<physicalRegionSize>0x3000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -304,7 +277,6 @@ Layout Description
<section>
<description>Secure Boot (144K)</description>
<eyeCatch>SECBOOT</eyeCatch>
- <physicalOffset>0x3E81000</physicalOffset>
<physicalRegionSize>0x24000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -313,7 +285,6 @@ Layout Description
<section>
<description>Open CAPI Memory Buffer (OCMB) Firmware (300K)</description>
<eyeCatch>OCMBFW</eyeCatch>
- <physicalOffset>0x3EA5000</physicalOffset>
<physicalRegionSize>0x4B000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -323,7 +294,6 @@ Layout Description
<section>
<description>HDAT Data (16K)</description>
<eyeCatch>HDAT</eyeCatch>
- <physicalOffset>0x3EF0000</physicalOffset>
<physicalRegionSize>0x4000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
diff --git a/src/build/buildpnor/genPnorImages.pl b/src/build/buildpnor/genPnorImages.pl
index 4782b7e8f..cc3b4f5e9 100755
--- a/src/build/buildpnor/genPnorImages.pl
+++ b/src/build/buildpnor/genPnorImages.pl
@@ -61,6 +61,11 @@ my $programName = File::Basename::basename $0;
my @systemBinFiles = ();
my %pnorLayout = ();
my %PhysicalOffsets = ();
+my %partitionUtilHash;
+
+# percentage utilization threshold, if crossed display warning message
+# that partition is almost full
+use constant CRITICAL_THRESHOLD => 85.00;
# Truncate SHA to n bytes
use constant SHA_TRUNCATE_SIZE => 32;
@@ -74,6 +79,7 @@ use constant VFS_MODULE_TABLE_MAX_SIZE => VFS_EXTENDED_MODULE_MAX
# Flag parameter string passed into signing tools
# Note spaces before/after are critical.
use constant OP_SIGNING_FLAG => " --flags ";
+use constant SW_FLAG_HAS_A_HPT => 0x80000000;
# Security bits HW flag strings
use constant OP_BUILD_FLAG => 0x80000000;
use constant FIPS_BUILD_FLAG => 0x40000000;
@@ -120,6 +126,7 @@ my $sign_mode = $DEVELOPMENT;
my $hwKeyHashFile = "";
my $hb_standalone="";
my $buildType="";
+my $editedLayoutLocation="";
# @TODO RTC 170650: Set default to 0 after all environments provide external
# control over this policy, plus remove '!' from 'lab-security-override'
@@ -142,6 +149,7 @@ GetOptions("binDir:s" => \$bin_dir,
"lab-security-override!" => \$labSecurityOverride,
"emit-eccless" => \$emitEccless,
"build-type:s" => \$buildType,
+ "editedLayoutLocation:s" => \$editedLayoutLocation,
"help" => \$help);
if ($help)
@@ -385,7 +393,8 @@ if ($build_all && $secureboot)
}
#Load PNOR Layout XML file
-loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun);
+loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun,
+ $editedLayoutLocation);
# Generate final images for each system's bin files.
foreach my $binFilesCSV (@systemBinFiles)
@@ -408,6 +417,17 @@ foreach my $binFilesCSV (@systemBinFiles)
manipulateImages(\%pnorLayout, \%binFiles, $system_target);
}
+# display percentage utilization data for each eyecatch
+foreach my $key (keys %partitionUtilHash) {
+
+ print "$key is $partitionUtilHash{$key}{pctUtilized} utilized ($partitionUtilHash{$key}{freeBytes} of $partitionUtilHash{$key}{physicalRegionSize} bytes free)\n";
+
+ # if percentage is greater than critical threshold, surface warning
+ if ($partitionUtilHash{$key}{pctUtilized} > CRITICAL_THRESHOLD) {
+ print "Warning: Percent utilization for $key shows that partition is almost full.\n";
+ }
+}
+
################################################################################
# Subroutines
################################################################################
@@ -451,6 +471,7 @@ sub partitionDepSort
################################################################################
# manipulateImages - Perform any ECC/padding/sha/signing manipulations
################################################################################
+
sub manipulateImages
{
my ($i_pnorLayoutRef, $i_binFilesRef, $system_target) = @_;
@@ -464,7 +485,10 @@ sub manipulateImages
# Partitions that have a hash page table at the beginning of the section
# for secureboot purposes.
- my %hashPageTablePartitions = (HBI => 1);
+ # TODO: add back SBE and HCODE as per story 209485
+ my %hashPageTablePartitions = (HBI => 1,
+ WOFDATA => 1,
+ MEMD => 1);
if($ENV{'RM_HASH_PAGE_TABLE'})
{
undef %hashPageTablePartitions;
@@ -483,7 +507,16 @@ sub manipulateImages
instructionStartStackPointer => 0);
my $layoutKey = findLayoutKeyByEyeCatch($key, \%$i_pnorLayoutRef);
+
+ # Skip if binary file isn't included in the PNOR layout file
+ if ($layoutKey eq -1)
+ {
+ print "Warning: skipping $key since it is NOT in the PNOR layout file\n";
+ next;
+ }
+
my $eyeCatch = $sectionHash{$layoutKey}{eyeCatch};
+ my $physicalRegionSize = $sectionHash{$layoutKey}{physicalRegionSize};
my %tempImages = (
HDR_PHASE => "$bin_dir/$parallelPrefix.$eyeCatch.temp.hdr.bin",
TEMP_SHA_IMG => "$bin_dir/$parallelPrefix.$eyeCatch.temp.sha.bin",
@@ -506,24 +539,23 @@ sub manipulateImages
# Sections that have secureboot support. Secureboot still must be
# enabled for secureboot actions on these partitions to occur.
my $isNormalSecure = ($eyeCatch eq "HBBL");
- $isNormalSecure ||= ($eyeCatch eq "SBE");
- $isNormalSecure ||= ($eyeCatch eq "MEMD");
$isNormalSecure ||= ($eyeCatch eq "HBRT");
$isNormalSecure ||= ($eyeCatch eq "PAYLOAD");
$isNormalSecure ||= ($eyeCatch eq "OCC");
- $isNormalSecure ||= ($eyeCatch eq "CAPP");
$isNormalSecure ||= ($eyeCatch eq "BOOTKERNEL");
- $isNormalSecure ||= ($eyeCatch eq "HCODE");
- $isNormalSecure ||= ($eyeCatch eq "CENHWIMG");
- $isNormalSecure ||= ($eyeCatch eq "WOFDATA");
$isNormalSecure ||= ($eyeCatch eq "IMA_CATALOG");
$isNormalSecure ||= ($eyeCatch eq "TESTRO");
$isNormalSecure ||= ($eyeCatch eq "TESTLOAD");
$isNormalSecure ||= ($eyeCatch eq "VERSION");
+ $isNormalSecure ||= ($eyeCatch eq "CENHWIMG");
+ $isNormalSecure ||= ($eyeCatch eq "SBE");
+ $isNormalSecure ||= ($eyeCatch eq "HCODE");
my $isSpecialSecure = ($eyeCatch eq "HBB");
$isSpecialSecure ||= ($eyeCatch eq "HBD");
$isSpecialSecure ||= ($eyeCatch eq "HBI");
+ $isSpecialSecure ||= ($eyeCatch eq "WOFDATA");
+ $isSpecialSecure ||= ($eyeCatch eq "MEMD");
# Used to indicate security is supported in firmware
my $secureSupported = $isNormalSecure || $isSpecialSecure;
@@ -662,6 +694,9 @@ sub manipulateImages
else
{
run_command("cp $tempImages{hashPageTable} $tempImages{PAYLOAD_TEXT}");
+ # Hash table generated so need to set sw-flags
+ my $hex_sw_flag = sprintf("0x%08X", SW_FLAG_HAS_A_HPT);
+ $CUR_OPEN_SIGN_REQUEST .= " --sw-flags $hex_sw_flag ";
}
run_command("$CUR_OPEN_SIGN_REQUEST "
@@ -734,6 +769,22 @@ sub manipulateImages
setCallerHwHdrFields(\%callerHwHdrFields, $tempImages{HDR_PHASE});
+
+ # store binary file size + header size in hash
+
+ # If section will passed through ecc, include this in size calculation
+ if( ($sectionHash{$layoutKey}{ecc} eq "yes") )
+ {
+ $partitionUtilHash{$eyeCatch}{logicalFileSize} = $callerHwHdrFields{totalContainerSize} * (9/8);
+ }
+ else
+ {
+ $partitionUtilHash{$eyeCatch}{logicalFileSize} = $callerHwHdrFields{totalContainerSize};
+ }
+ $partitionUtilHash{$eyeCatch}{pctUtilized} = sprintf("%.2f", $partitionUtilHash{$eyeCatch}{logicalFileSize} / $physicalRegionSize * 100);
+ $partitionUtilHash{$eyeCatch}{freeBytes} = $physicalRegionSize - $partitionUtilHash{$eyeCatch}{logicalFileSize};
+ $partitionUtilHash{$eyeCatch}{physicalRegionSize} = $physicalRegionSize;
+
# Padding Phase
if ($eyeCatch eq "HBI" && $testRun)
{
@@ -1258,6 +1309,7 @@ print <<"ENDUSAGE";
switch (separated with a space and not
including the single quotes). OpenPower is
the default.
+ --editedLayoutLocation <directory> Location to place edited layout file
Current Limitations:
- Issues with dependency on ENGD build for certain files such as SBE. This is why [--build-all | --install-all ] are used.
diff --git a/src/build/buildpnor/memd_creation.pl b/src/build/buildpnor/memd_creation.pl
index c4f551b03..b33981ad6 100755
--- a/src/build/buildpnor/memd_creation.pl
+++ b/src/build/buildpnor/memd_creation.pl
@@ -66,7 +66,7 @@ pod2usage(-verbose => 2) if $man;
if($memd_dir)
{
print "Reading files from $memd_dir\n";
- @memd_files = glob($memd_dir . '/*');
+ @memd_files = glob($memd_dir . '/*vpd');
}
elsif(@memd_files)
{
diff --git a/src/build/buildpnor/pkgOcmbFw.pl b/src/build/buildpnor/pkgOcmbFw.pl
index eb5d8f953..b7fdb90cf 100755
--- a/src/build/buildpnor/pkgOcmbFw.pl
+++ b/src/build/buildpnor/pkgOcmbFw.pl
@@ -89,6 +89,13 @@
#
###############################################################################
+# ******************WARNING**********************
+#
+# THIS FILE MUST BE KEPT IN SYNC WITH
+# src/include/usr/expupd/ocmbFwImage_const.H
+#
+# ******************WARNING**********************
+
use strict;
use File::Basename;
use Digest::SHA qw(sha512);
diff --git a/src/build/buildpnor/pnorLayoutAxone.xml b/src/build/buildpnor/pnorLayoutAxone.xml
index 150bab112..274439a39 100644
--- a/src/build/buildpnor/pnorLayoutAxone.xml
+++ b/src/build/buildpnor/pnorLayoutAxone.xml
@@ -86,26 +86,31 @@ Layout Description
<ecc/>
</section>
<section>
+ <!-- NOTE must be before images that are likely to change like HBI,
+ also mustupdate standalone.simics if EECACHE offset changes-->
+ <description>Eeprom Cache(512K)</description>
+ <eyeCatch>EECACHE</eyeCatch>
+ <physicalOffset>0x2C000</physicalOffset>
+ <physicalRegionSize>0x80000</physicalRegionSize>
+ <side>sideless</side>
+ <ecc/>
+ </section>
+ <section>
<description>Guard Data (20K)</description>
<eyeCatch>GUARD</eyeCatch>
- <physicalOffset>0x2C000</physicalOffset>
<physicalRegionSize>0x5000</physicalRegionSize>
<side>sideless</side>
<ecc/>
</section>
<section>
- <description>Module VPD (576K)</description>
- <eyeCatch>MVPD</eyeCatch>
- <!--NOTE: MUST update standalone.simics if offset changes -->
- <physicalOffset>0x31000</physicalOffset>
- <physicalRegionSize>0x90000</physicalRegionSize>
+ <description>Attributes</description>
+ <eyeCatch>ATTR_TMP</eyeCatch>
+ <physicalRegionSize>0x4000</physicalRegionSize>
<side>sideless</side>
- <ecc/>
</section>
<section>
<description>Hostboot Base (1MB)</description>
<eyeCatch>HBB</eyeCatch>
- <physicalOffset>0xC1000</physicalOffset>
<physicalRegionSize>0x100000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -114,17 +119,15 @@ Layout Description
<section>
<description>Hostboot Data (2MB)</description>
<eyeCatch>HBD</eyeCatch>
- <physicalOffset>0x1C1000</physicalOffset>
<physicalRegionSize>0x200000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
</section>
<section>
- <description>Hostboot Extended image (14.22MB w/o ECC)</description>
+ <description>Hostboot Extended image (17.77MB w/o ECC)</description>
<eyeCatch>HBI</eyeCatch>
- <physicalOffset>0x3C1000</physicalOffset>
- <physicalRegionSize>0x1000000</physicalRegionSize>
+ <physicalRegionSize>0x1400000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
@@ -132,7 +135,6 @@ Layout Description
<section>
<description>SBE-IPL (Staging Area) (752K)</description>
<eyeCatch>SBE</eyeCatch>
- <physicalOffset>0x13C1000</physicalOffset>
<physicalRegionSize>0xBC000</physicalRegionSize>
<sha512perEC/>
<sha512Version/>
@@ -142,26 +144,23 @@ Layout Description
<section>
<description>HCODE Ref Image (1.125MB)</description>
<eyeCatch>HCODE</eyeCatch>
- <physicalOffset>0x147D000</physicalOffset>
<physicalRegionSize>0x120000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
</section>
<section>
- <description>Hostboot Runtime Services for Sapphire (7.0MB)</description>
+ <description>Hostboot Runtime Services for Sapphire (8.0MB)</description>
<eyeCatch>HBRT</eyeCatch>
- <physicalOffset>0x159D000</physicalOffset>
- <physicalRegionSize>0x700000</physicalRegionSize>
+ <physicalRegionSize>0x800000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
</section>
<section>
- <description>Payload (19.875MB)</description>
+ <description>Payload (16KB)</description>
<eyeCatch>PAYLOAD</eyeCatch>
- <physicalOffset>0x1C9D000</physicalOffset>
- <physicalRegionSize>0x13E0000</physicalRegionSize>
+ <physicalRegionSize>0x4000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
@@ -169,7 +168,6 @@ Layout Description
<section>
<description>Special PNOR Test Space (36K)</description>
<eyeCatch>TEST</eyeCatch>
- <physicalOffset>0x307D000</physicalOffset>
<physicalRegionSize>0x9000</physicalRegionSize>
<testonly/>
<side>sideless</side>
@@ -180,7 +178,6 @@ Layout Description
from skipping header. Signing is forced in build pnor phase -->
<description>Special PNOR Test Space with Header (36K)</description>
<eyeCatch>TESTRO</eyeCatch>
- <physicalOffset>0x3086000</physicalOffset>
<physicalRegionSize>0x9000</physicalRegionSize>
<side>sideless</side>
<testonly/>
@@ -191,7 +188,6 @@ Layout Description
<section>
<description>Hostboot Bootloader (28K)</description>
<eyeCatch>HBBL</eyeCatch>
- <physicalOffset>0x308F000</physicalOffset>
<!-- Physical Size includes Header rounded to ECC valid size -->
<!-- Max size of actual HBBL content is 20K and 22.5K with ECC -->
<physicalRegionSize>0x7000</physicalRegionSize>
@@ -200,17 +196,8 @@ Layout Description
<ecc/>
</section>
<section>
- <description>Global Data (36K)</description>
- <eyeCatch>GLOBAL</eyeCatch>
- <physicalOffset>0x3096000</physicalOffset>
- <physicalRegionSize>0x9000</physicalRegionSize>
- <side>sideless</side>
- <ecc/>
- </section>
- <section>
<description>Ref Image Ring Overrides (20K)</description>
<eyeCatch>RINGOVD</eyeCatch>
- <physicalOffset>0x309F000</physicalOffset>
<physicalRegionSize>0x5000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -218,7 +205,6 @@ Layout Description
<section>
<description>SecureBoot Key Transition Partition (16K)</description>
<eyeCatch>SBKT</eyeCatch>
- <physicalOffset>0x30A4000</physicalOffset>
<physicalRegionSize>0x4000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -226,18 +212,16 @@ Layout Description
<section>
<description>OCC Lid (1.125M)</description>
<eyeCatch>OCC</eyeCatch>
- <physicalOffset>0x30A8000</physicalOffset>
<physicalRegionSize>0x120000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
</section>
<section>
- <description>VFRT data for WOF (12MB)</description>
+ <description>VFRT data for WOF (6MB)</description>
<!-- We need 266KB per module sort, going to support
40 tables by default, plus ECC -->
<eyeCatch>WOFDATA</eyeCatch>
- <physicalOffset>0x31C8000</physicalOffset>
<physicalRegionSize>0x600000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -246,52 +230,30 @@ Layout Description
<section>
<description>FIRDATA (12K)</description>
<eyeCatch>FIRDATA</eyeCatch>
- <physicalOffset>0x37C8000</physicalOffset>
<physicalRegionSize>0x3000</physicalRegionSize>
<side>sideless</side>
<ecc/>
</section>
<section>
- <description>Memory Data (128K)</description>
- <eyeCatch>MEMD</eyeCatch>
- <physicalOffset>0x37CB000</physicalOffset>
- <physicalRegionSize>0x20000</physicalRegionSize>
- <side>sideless</side>
- <sha512Version/>
- <ecc/>
- </section>
- <section>
<description>Secureboot Test Load (12K)</description>
<eyeCatch>TESTLOAD</eyeCatch>
- <physicalOffset>0x37EB000</physicalOffset>
<physicalRegionSize>0x3000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
<ecc/>
</section>
<section>
- <description>Centaur Hw Ref Image (12K)</description>
- <eyeCatch>CENHWIMG</eyeCatch>
- <physicalOffset>0x37EE000</physicalOffset>
- <physicalRegionSize>0x3000</physicalRegionSize>
- <sha512Version/>
- <side>sideless</side>
- <ecc/>
- </section>
- <section>
<description>Secure Boot (144K)</description>
<eyeCatch>SECBOOT</eyeCatch>
- <physicalOffset>0x37F1000</physicalOffset>
<physicalRegionSize>0x24000</physicalRegionSize>
<side>sideless</side>
<ecc/>
<preserved/>
</section>
<section>
- <description>Open CAPI Memory Buffer (OCMB) Firmware (300K)</description>
+ <description>Open CAPI Memory Buffer (OCMB) Firmware (1164K)</description>
<eyeCatch>OCMBFW</eyeCatch>
- <physicalOffset>0x3815000</physicalOffset>
- <physicalRegionSize>0x4B000</physicalRegionSize>
+ <physicalRegionSize>0x123000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
<readOnly/>
@@ -300,18 +262,9 @@ Layout Description
<section>
<description>HDAT Data (16K)</description>
<eyeCatch>HDAT</eyeCatch>
- <physicalOffset>0x3860000</physicalOffset>
<physicalRegionSize>0x4000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
<ecc/>
</section>
- <section>
- <description>Eeprom Cache(512K)</description>
- <eyeCatch>EECACHE</eyeCatch>
- <physicalOffset>0x3864000</physicalOffset>
- <physicalRegionSize>0x80000</physicalRegionSize>
- <side>sideless</side>
- <ecc/>
- </section>
</pnor>
diff --git a/src/build/buildpnor/pnorLayoutFSP.xml b/src/build/buildpnor/pnorLayoutFSP.xml
index a842001c3..9569e479f 100644
--- a/src/build/buildpnor/pnorLayoutFSP.xml
+++ b/src/build/buildpnor/pnorLayoutFSP.xml
@@ -168,10 +168,10 @@ Layout Description - Used when building an FSP driver
<ecc/>
</section>
<section>
- <description>Hostboot Runtime Services for Sapphire (6MB)</description>
+ <description>Hostboot Runtime Services for Sapphire (8MB)</description>
<eyeCatch>HBRT</eyeCatch>
<physicalOffset>0x162D000</physicalOffset>
- <physicalRegionSize>0x600000</physicalRegionSize>
+ <physicalRegionSize>0x800000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
<ecc/>
@@ -179,7 +179,7 @@ Layout Description - Used when building an FSP driver
<section>
<description>Hostboot Bootloader (28K)</description>
<eyeCatch>HBBL</eyeCatch>
- <physicalOffset>0x1C2D000</physicalOffset>
+ <physicalOffset>0x1E2D000</physicalOffset>
<!-- Physical Size includes Header rounded to ECC valid size -->
<!-- Max size of actual HBBL content is 20K and 22.5K with ECC -->
<physicalRegionSize>0x7000</physicalRegionSize>
@@ -188,17 +188,9 @@ Layout Description - Used when building an FSP driver
<ecc/>
</section>
<section>
- <description>Global Data (36K)</description>
- <eyeCatch>GLOBAL</eyeCatch>
- <physicalOffset>0x1C34000</physicalOffset>
- <physicalRegionSize>0x9000</physicalRegionSize>
- <side>sideless</side>
- <ecc/>
- </section>
- <section>
<description>Ref Image Ring Overrides (20K)</description>
<eyeCatch>RINGOVD</eyeCatch>
- <physicalOffset>0x1C3D000</physicalOffset>
+ <physicalOffset>0x1E34000</physicalOffset>
<physicalRegionSize>0x5000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -206,7 +198,7 @@ Layout Description - Used when building an FSP driver
<section>
<description>SecureBoot Key Transition Partition (16K)</description>
<eyeCatch>SBKT</eyeCatch>
- <physicalOffset>0x1C42000</physicalOffset>
+ <physicalOffset>0x1E39000</physicalOffset>
<physicalRegionSize>0x4000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -215,7 +207,7 @@ Layout Description - Used when building an FSP driver
<section>
<description>OCC Lid (1.125M)</description>
<eyeCatch>OCC</eyeCatch>
- <physicalOffset>0x1C46000</physicalOffset>
+ <physicalOffset>0x1E3D000</physicalOffset>
<physicalRegionSize>0x120000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -226,7 +218,7 @@ Layout Description - Used when building an FSP driver
<!-- We need 266KB per module sort, going to support
40 tables by default, plus ECC -->
<eyeCatch>WOFDATA</eyeCatch>
- <physicalOffset>0x1D66000</physicalOffset>
+ <physicalOffset>0x1F5D000</physicalOffset>
<physicalRegionSize>0xC00000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -235,7 +227,7 @@ Layout Description - Used when building an FSP driver
<section>
<description>Memory Data (128K)</description>
<eyeCatch>MEMD</eyeCatch>
- <physicalOffset>0x2966000</physicalOffset>
+ <physicalOffset>0x2B5D000</physicalOffset>
<physicalRegionSize>0x20000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
@@ -244,7 +236,7 @@ Layout Description - Used when building an FSP driver
<section>
<description>Centaur Hw Ref Image (12K)</description>
<eyeCatch>CENHWIMG</eyeCatch>
- <physicalOffset>0x2986000</physicalOffset>
+ <physicalOffset>0x2B7D000</physicalOffset>
<physicalRegionSize>0x3000</physicalRegionSize>
<sha512Version/>
<side>sideless</side>
@@ -253,7 +245,7 @@ Layout Description - Used when building an FSP driver
<section>
<description>Secure Boot (144K)</description>
<eyeCatch>SECBOOT</eyeCatch>
- <physicalOffset>0x2989000</physicalOffset>
+ <physicalOffset>0x2B80000</physicalOffset>
<physicalRegionSize>0x24000</physicalRegionSize>
<side>sideless</side>
<ecc/>
@@ -262,7 +254,7 @@ Layout Description - Used when building an FSP driver
<section>
<description>Open CAPI Memory Buffer (OCMB) Firmware (300K)</description>
<eyeCatch>OCMBFW</eyeCatch>
- <physicalOffset>0x29AD000</physicalOffset>
+ <physicalOffset>0x2BA4000</physicalOffset>
<physicalRegionSize>0x4B000</physicalRegionSize>
<side>sideless</side>
<sha512Version/>
diff --git a/src/build/citest/autocitest b/src/build/citest/autocitest
index 0cb8d078f..3e29c414f 100755
--- a/src/build/citest/autocitest
+++ b/src/build/citest/autocitest
@@ -154,8 +154,11 @@ waitkb
timestamp=`date +'%H:%M:%S'`
echo "$timestamp Starting autosample test..."
-# see simics license usage
-tail -n 500 /afs/rch/usr4/dlarson/public/stats/lic_usage.txt | grep hindsight
+# see simics license usage.
+hindsight_license=$(echo "hindsight_usage-"`date +%Y`-`date +%B`".log")
+# show last 4 hours. Gives alittle insight to license usage trends.
+#This log file is added to every twenty minutes. There are spaces between each line. 4x2x3=24 lines
+tail -n 24 /gsa/ausgsa/projects/s/simics_test/license_logs/$hindsight_license
# Run set up in current shell
echo "run autosimsetup.."
@@ -333,10 +336,11 @@ while [ $(($modsstarted)) -lt 1 -o $(($modsstarted)) -ne $(($modscompleted)) ];
sleep 20
((loopcount++)) # increment loopcount
echo "loopcount = $loopcount"
-
+ date +'%H:%M:%S'
echo "modscompleted log command"
- echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)\" 1> $SBXHOME/modscompleted.log 2> /dev/null"
- autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)" 1> $SBXHOME/modscompleted.log 2> /dev/null
+ echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)\" 1> $SBXHOME/modscompleted.log 2> /dev/null"
+ autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)" 1> $SBXHOME/modscompleted.log 2> /dev/null
+ date +'%H:%M:%S'
echo
echo "modscompleted command"
@@ -344,9 +348,11 @@ while [ $(($modsstarted)) -lt 1 -o $(($modsstarted)) -ne $(($modscompleted)) ];
modscompleted=`cat $SBXHOME/modscompleted.log | awk '/0x/ {print strtonum($1)}'`
echo
+ date +'%H:%M:%S'
echo "modsstarted log command"
- echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)\" 1> $SBXHOME/modsstarted.log 2> /dev/null"
- autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)" 1> $SBXHOME/modsstarted.log 2> /dev/null
+ echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)\" 1> $SBXHOME/modsstarted.log 2> /dev/null"
+ autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)" 1> $SBXHOME/modsstarted.log 2> /dev/null
+ date +'%H:%M:%S'
echo
echo "modsstarted command"
@@ -356,18 +362,35 @@ while [ $(($modsstarted)) -lt 1 -o $(($modsstarted)) -ne $(($modscompleted)) ];
echo "ModulesStarted:ModulesCompleted => $modsstarted:$modscompleted"
- # @TODO RTC:149210 temporary fix for autosim hangs on real code errors. For some reason
- # when we hit an actual bug and simics halts, the autosim commands hang
- # causing this loop to take >8 hours.
- if [ -z $modsstarted ] && [ -z $modscompleted ]; then
- echo "ERROR: autosim hanging on real code errors, temporarily catching early"
- echo "See archived hbTracMerg for more info"
- exit 1
+ # For code coverage, sometimes simics takes a while to respond as it dumps data.
+ # Allow it to continue if this condition is seen.
+ if [[ -z "${HOSTBOOT_PROFILE}" ]]; then
+ # @TODO RTC:149210 temporary fix for autosim hangs on real code errors. For some reason
+ # when we hit an actual bug and simics halts, the autosim commands hang
+ # causing this loop to take >8 hours.
+ if [ -z $modsstarted ] && [ -z $modscompleted ]; then
+ echo "ERROR: autosim hanging on real code errors, temporarily catching early"
+ echo "See archived hbTracMerg for more info"
+ exit 1
+ fi
+ fi
+
+ if [[ -z "${HOSTBOOT_PROFILE}" ]]; then
+ if [[ "$CHIP" == "AXONE" ]]; then
+ # 75 minutes for axone
+ loop_timeout=225
+ else
+ # 50 minutes by default
+ loop_timeout=150
+ fi
+ else
+ # Increase timeout to 166 minutes for code coverage
+ loop_timeout=500
fi
- if [ "$loopcount" -ge 150 ]; then
+ if [ "$loopcount" -ge "$loop_timeout" ]; then
timestamp=`date +'%H:%M:%S'`
- echo "$timestamp ERROR: timed out after 50 minutes waiting for until test completion"
+ echo "$timestamp ERROR: timed out waiting for until test completion"
autosim $NOWIN --simcmd "hb-Ps with-backtrace"
timeout=$(($modsstarted - $modscompleted))
break
@@ -467,6 +490,15 @@ if [ $? -ne 0 ] ; then
echo "ERROR: Unable to run $?"
fi
+if [[ ! -z "${HOSTBOOT_PROFILE}" ]]; then
+ # After simics test are complete, dump data.
+ echo "====> hb-Gcov..."
+ autosim $NOWIN --simcmd "hb-Gcov" --timeout 300
+ if [ $? -ne 0 ] ; then
+ echo "ERROR: Unable to run $?"
+ fi
+fi
+
########################################################
## done. Stop the simulation
########################################################
diff --git a/src/build/citest/build-script b/src/build/citest/build-script
index 7510d76c9..7198ed5b2 100755
--- a/src/build/citest/build-script
+++ b/src/build/citest/build-script
@@ -24,10 +24,62 @@
#
# IBM_PROLOG_END_TAG
+usage="
+$(basename "$0") [-h|--help] [--skipCxxTests] [--skipCopyrightCheck]
+
+Description:
+ The original use of this script was for the Hostboot standalone CI job,
+ so by default it will run a copyright check, then compile hostboot and
+ populate an ODE sandbox and run the CXX test suite in standalone simics.
+
+ Flags have been added to skip the copyright checks and the cxx tests
+ for cases where we only want to get a populated sandbox.
+
+Expectations:
+ This script is expected to be ran from the top level of the
+ hostboot directory. (ie src/build/citest/build-script <params>). It will
+ look at env variables PROJECT_ROOT, WORKSPACE, SANDBOXNAME, SANDBOXROOT,
+ CHIP, PNOR, CONFIG_FILE, and HOSTBOOT_PROFILE.
+
+Optional Flags:
+ -h|--help shows this help text
+ --skipCxxTests skips the execution of the cxx test suite
+ --skipCopyrightCheck skips the execution of the copyright check
+"
+
if [ -z $PROJECT_ROOT ]; then
source "$WORKSPACE/env.bash"
fi
+while [[ $# -gt 0 ]]
+do
+key="$1"
+
+case $key in
+ --skipCopyrightCheck)
+ SKIP_CR_CHECK=1
+ shift # past argument
+ ;;
+ --skipCxxTests)
+ SKIP_CXX_TESTS=1
+ shift # past argument
+ ;;
+ -h|--help)
+ echo "$usage"
+ exit 0
+ ;;
+ *)
+ echo "
+!!! Invalid argument \"$1\" passed into ${0} !!!!"
+ echo "$usage"
+ exit 22
+ ;;
+esac
+done
+
+echo "SKIP_CR_CHECK = ${SKIP_CR_CHECK}"
+echo "SKIP_CXX_TESTS = ${SKIP_CXX_TESTS}"
+
source "$PROJECT_ROOT/src/build/citest/setup-env"
echo "#--------------------------------"
echo "SANDBOXROOT=$SANDBOXROOT"
@@ -41,32 +93,49 @@ echo "#--------------------------------"
# Force simics into Secure Mode
export SECURITY_HW_POLICY="1"
-# Check copyright.
-check-copyright > copyright.log 2>&1
-if [ $? -eq 0 ]; then
- echo "----Copyright check succeeded."
- cat copyright.log
-else
- echo "----Copyright check failed."
- cat copyright.log
- exit -1
+if [ -z "$SKIP_CR_CHECK" ]; then
+ # Check copyright.
+ check-copyright > copyright.log 2>&1
+ if [ $? -eq 0 ]; then
+ echo "----Copyright check succeeded."
+ cat copyright.log
+ else
+ echo "----Copyright check failed."
+ cat copyright.log
+ exit -1
+ fi
fi
-
# Create simics sandbox.
create-sandbox > create-sandbox.log 2>&1 &
CREATESANDBOX_PID=$!
-my_date=$(date)
-# Build Hostboot.
+# normal build is empty quotes
+build_opt=""
+# code coverage
+if [[ ! -z "${HOSTBOOT_PROFILE}" ]]; then
+ build_opt="gcov"
+# static analysis
+elif [[ ! -z "${HOSTBOOT_CPPCHECK}" ]]; then
+ build_opt="cppcheck"
+ COMPILE_ONLY=1
+fi
+# Build Hostboot
+start_time=$(date)
echo "#--------------------------------"
-printf "\n\n$(date): STARTED running \"make -j32\"\n\n"
+printf "\n\n$(date): STARTED running \"make -j32 $build_opt\"\n\n"
echo "#--------------------------------"
-make -j32 || exit -1
+make -j32 $build_opt || exit -1
+make_rc=$?
echo "#--------------------------------"
-printf "\n\nrc=$?: $(date): FINISHED running (\"make -j32\" was started at $my_date)\n\n"
+printf "\n\nrc=$make_rc: $(date): FINISHED running (\"make -j32 $build_opt\" was started at $start_time)\n\n"
echo "#--------------------------------"
+if [[ ! -z "${COMPILE_ONLY}" ]]; then
+ echo "Compile only"
+ exit $make_rc
+fi
+
# Check sandbox create completion.
wait $CREATESANDBOX_PID
if [ $? -eq 0 ]; then
@@ -79,48 +148,62 @@ else
fi
# Add Hostboot files to simics sandbox.
-my_date=$(date)
+start_time=$(date)
echo "#--------------------------------"
-printf "\n\n$(date): STARTED running populate-sandbox....\n\n"
+printf "\n\n$start_time: STARTED running populate-sandbox....\n\n"
echo "#--------------------------------"
populate-sandbox || exit -1
echo "#--------------------------------"
-printf "\n\nrc=$?: $(date): FINISHED running (\"populate-sandbox\" was started at $my_date)\n\n"
+printf "\n\nrc=$?: $(date): FINISHED running (\"populate-sandbox\" was started at $start_time)\n\n"
echo "#--------------------------------"
-if [ "$CHIP" == "FSPBUILD" ];
-then
- # Start errl parser building.
- my_date=$(date)
- printf "\n\n$(date): STARTED running \"build-errl-parsers\"\n\n"
- build-errl-parsers > errl-parsers.log 2>&1 &
- ERRLPARSERS_PID=$!
-
- # Check errl parser completion.
- wait $ERRLPARSERS_PID
- if [ $? -ne 0 ]; then
- echo "----Error parsers failed."
- cat errl-parsers.log
- exit -1
- else
- printf "\n\n$(date): FINISHED running (\"build-errl-parsers\" was started at $my_date)\n\n"
- fi
-
-
-else
- printf "2) CHIP=$CHIP"
- echo "CHIP3=$CHIP"
-
-
- # Start CxxTest Simics execution.
- my_date=$(date)
- echo "#--------------------------------"
- printf "\n\n$(date): STARTED running cxxtest-start.sh....\n\n"
- echo "#--------------------------------"
- cxxtest-start.sh || exit -1
- echo "#--------------------------------"
- printf "\n\nrc=$?: $(date): FINISHED running (\"cxxtest-start.sh\" was started at $my_date)\n\n"
- echo "#--------------------------------"
+if [ -z "$SKIP_CXX_TESTS" ]; then
+
+ if [ "$CHIP" == "FSPBUILD" ]; then
+ # Start errl parser building.
+ start_time=$(date)
+ printf "\n\n$start_time: STARTED running \"build-errl-parsers\"\n\n"
+ build-errl-parsers > errl-parsers.log 2>&1 &
+ ERRLPARSERS_PID=$!
+
+ # Check errl parser completion.
+ wait $ERRLPARSERS_PID
+ if [ $? -ne 0 ]; then
+ echo "----Error parsers failed."
+ cat errl-parsers.log
+ exit -1
+ else
+ printf "\n\n$(date): FINISHED running (\"build-errl-parsers\" was started at $start_time)\n\n"
+ fi
+
+
+ else
+ printf "2) CHIP=$CHIP"
+ echo "CHIP3=$CHIP"
+
+ # Start CxxTest Simics execution.
+ start_time=$(date)
+ echo "#--------------------------------"
+ printf "\n\n$start_time: STARTED running cxxtest-start.sh....\n\n"
+ echo "#--------------------------------"
+ cxxtest-start.sh || exit -1
+ echo "#--------------------------------"
+ printf "\n\nrc=$?: $(date): FINISHED running (\"cxxtest-start.sh\" was started at $start_time)\n\n"
+ echo "#--------------------------------"
+
+ fi
fi
+if [[ ! -z "${HOSTBOOT_PROFILE}" ]]; then
+ # Generate the code coverage report. Located obj/gcov_report
+ # Jenkins will artifact and can display html report
+ start_time=$(date)
+ echo "#--------------------------------"
+ printf "\n\n$start_time: STARTED running \"make lcov\"\n\n"
+ echo "#--------------------------------"
+ make lcov || exit -1
+ echo "#--------------------------------"
+ printf "\n\nrc=$?: $(date): FINISHED running (\"make lcov\" was started at $start_time)\n\n"
+ echo "#--------------------------------"
+fi
diff --git a/src/build/citest/create-sandbox b/src/build/citest/create-sandbox
index 0018e4422..b07158f02 100755
--- a/src/build/citest/create-sandbox
+++ b/src/build/citest/create-sandbox
@@ -78,11 +78,15 @@ if [ "$MACHINE" != "NIMBUS" ] && [ "$MACHINE" != "CUMULUS" ] && \
[ "$MACHINE" != "CUMULUS_CDIMM" ] && [ "$MACHINE" != "FSPBUILD" ];
then
SIMICS_LEVEL=`cat ${PROJECT_ROOT}/src/build/citest/etc/simbuild`
+ EECACHE_PREBUILT=`cat ${PROJECT_ROOT}/src/build/citest/etc/eecache_prebuilt`
echo "mkdir -p ${SANDBOXBASE}/simics"
execute_in_sandbox "mkdir -p ${SANDBOXBASE}/simics" "ppc"
echo "tar ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/"
execute_in_sandbox "tar -xf ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/" "ppc"
+ echo "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh"
execute_in_sandbox "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh" "ppc"
+ echo "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc"
+ execute_in_sandbox "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc" "ppc"
else
execute_in_sandbox "start_simics -no_start -machine $MACHINE -batch_mode" \
"ppc" || exit -1
diff --git a/src/build/citest/cxxtest-start.sh b/src/build/citest/cxxtest-start.sh
index dcb25c201..b34c744d8 100755
--- a/src/build/citest/cxxtest-start.sh
+++ b/src/build/citest/cxxtest-start.sh
@@ -38,7 +38,7 @@ if [ "$MACHINE" != "NIMBUS" ] && [ "$MACHINE" != "CUMULUS" ] && \
[ "$MACHINE" != "CUMULUS_CDIMM" ] && [ "$MACHINE" != "FSPBUILD" ];
then
export PATH=$PATH:$SANDBOXBASE/simics/
- export START_SIMICS_CMD="runsim -m $MACHINE hb_script_to_run=$SANDBOXBASE/obj/ppc/simu/scripts/hbfw/startup.simics pnor_img=$SANDBOXBASE/obj/ppc/hbfw/img/axone.pnor sbe_seeprom_img=$SANDBOXBASE/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=1 vpd_proc=vpd/images/99a8c3fe4e5c74798f5bd4212f3d9a2a"
+ export START_SIMICS_CMD="runsim -m $MACHINE hb_script_to_run=$SANDBOXBASE/obj/ppc/simu/scripts/hbfw/startup.simics pnor_img=$SANDBOXBASE/obj/ppc/hbfw/img/axone.pnor sbe_seeprom_img=$SANDBOXBASE/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=2 enable_lpc_console=TRUE"
fi
# Front end to autocitest - script to execute unit tests under simics.
diff --git a/src/build/citest/etc/bbuild b/src/build/citest/etc/bbuild
index 873e0f4bd..a6ac16e07 100644
--- a/src/build/citest/etc/bbuild
+++ b/src/build/citest/etc/bbuild
@@ -1 +1 @@
-/esw/fips930/Builds/b0121a_1904.930
+/esw/fips940/Builds/b0516a_1921.940
diff --git a/src/build/citest/etc/cppcheck b/src/build/citest/etc/cppcheck
new file mode 100644
index 000000000..f92ac3604
--- /dev/null
+++ b/src/build/citest/etc/cppcheck
@@ -0,0 +1,27 @@
+#!/bin/bash
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/citest/etc/cppcheck $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2019
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+export CPPCHECK_COMMIT="4939e0c3086151033bd491bb2df72f7728a4c037"
diff --git a/src/build/citest/etc/eecache_prebuilt b/src/build/citest/etc/eecache_prebuilt
new file mode 100644
index 000000000..e7ff59666
--- /dev/null
+++ b/src/build/citest/etc/eecache_prebuilt
@@ -0,0 +1 @@
+/gsa/ausgsa/projects/h/hostboot/eecache_prebuilt/10_02_19_eecache_prebuilt.bin.ecc
diff --git a/src/build/citest/etc/simbuild b/src/build/citest/etc/simbuild
index 31d4a6f2e..ba464d4c5 100644
--- a/src/build/citest/etc/simbuild
+++ b/src/build/citest/etc/simbuild
@@ -1 +1 @@
-/gsa/ausgsa/projects/h/hostboot/simbuild/04_08_19_973eb4_simics.tar.gz
+/gsa/ausgsa/projects/h/hostboot/simbuild/axone/2019-11-11_f0c353_simics.tar.gz
diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup
index d904f6c3b..26cc2bd03 100755
--- a/src/build/citest/etc/workarounds.postsimsetup
+++ b/src/build/citest/etc/workarounds.postsimsetup
@@ -6,7 +6,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2019
+# Contributors Listed Below - COPYRIGHT 2011,2020
# [+] International Business Machines Corp.
#
#
@@ -39,5 +39,8 @@ mkdir -p $sb/simu/configs/
grep -v PROC_EC $BACKING_BUILD/src/simu/configs/P9_NIMBUS.config > $sb/simu/configs/P9_NIMBUS.config
echo "SETENV PROC_EC 22" >> $sb/simu/configs/P9_NIMBUS.config
+# TODO RTC:215621
+# remove when simics gets dimmspd.dat updated
+mkdir -p $sb/../simics/import/vpd/
+cp /gsa/ausgsa/projects/h/hostboot/.binary_cache/data/f6f5b778c406883e1b392b311350a1e83583e15a $sb/../simics/import/vpd/dimmspd.dat
-##########################################################################
diff --git a/src/build/citest/setup-env b/src/build/citest/setup-env
index 21133ef67..e82032d8a 100755
--- a/src/build/citest/setup-env
+++ b/src/build/citest/setup-env
@@ -26,6 +26,7 @@
export CITESTPATH=${PROJECT_ROOT}/src/build/citest
export PATH=${CITESTPATH}:${PATH}
+export CXXPATH=/opt/rh/devtoolset-3/root/usr/bin
# Determine backing build.
export BACKING_BUILD=`cat ${CITESTPATH}/etc/bbuild`
diff --git a/src/build/configs/simics_axone.config b/src/build/configs/simics_axone.config
index 3d044edcc..c3f33e583 100644
--- a/src/build/configs/simics_axone.config
+++ b/src/build/configs/simics_axone.config
@@ -1,35 +1,27 @@
-# Force DJVPD read/write to use EEPROM layer instead of VPD cache
-set DJVPD_READ_FROM_HW
-set DJVPD_WRITE_TO_HW
-unset DJVPD_READ_FROM_PNOR
-unset DJVPD_WRITE_TO_PNOR
-
-# Force MEMVPD read/write to PNOR ( No actual hardware )
-set MEMVPD_READ_FROM_PNOR
-set MEMVPD_WRITE_TO_PNOR
-unset MEMVPD_READ_FROM_HW
-unset MEMVPD_WRITE_TO_HW
-
-# Force MVPD read/write to use EEPROM layer instead of VPD cache
-# (not working because shoddy MVPD currently)
-#set MVPD_READ_FROM_HW
-#set MVPD_WRITE_TO_HW
-set MVPD_READ_FROM_PNOR
-set MVPD_WRITE_TO_PNOR
+# Have Planar VPD
+set HAVE_PVPD
+
+# Don't have any memory buffer VPD
+unset HAVE_MBVPD
#set to run cxx testcases during boot
unset EARLY_TESTCASES
-#skip enabling checkstop analysis until OCC is ready in simics
-unset IPLTIME_CHECKSTOP_ANALYSIS
+#Enable checkstop analysis for IPL failures
+set IPLTIME_CHECKSTOP_ANALYSIS
#enable EEPROM caching
set SUPPORT_EEPROM_CACHING
-#Try to keep a list of things this does
-# - skipping setting voltages in istep 8.12, nothing on other side of AVSbus
-# in simics currently.
+# Allows us to put in workarounds specifically for Axone bringup
set AXONE_BRING_UP
# Set this to pull in Axone on code (such as P9A/EXP MSS code)
-set AXONE \ No newline at end of file
+set AXONE
+
+# Enable Console
+set CONSOLE
+set CONSOLE_OUTPUT_ERRORDISPLAY
+
+# OMIs were introduced in Axone and will be in P10 also
+set SUPPORT_OMI
diff --git a/src/build/debug/Hostboot/BlTrace.pm b/src/build/debug/Hostboot/BlTrace.pm
index 5fd8baf18..9d9dc9988 100644
--- a/src/build/debug/Hostboot/BlTrace.pm
+++ b/src/build/debug/Hostboot/BlTrace.pm
@@ -83,6 +83,7 @@ my %traceText = (
"FA" => "PNOR Access getHBBSection findTOC no HBB section",
"FB" => "main verifyBaseImage failed",
"FC" => "main verifyBaseImage secure rom invalid",
+ "FD" => "PNOR Access findTOC handleMMIO LPC ERR returned",
);
sub formatTrace
diff --git a/src/build/debug/Hostboot/Dump.pm b/src/build/debug/Hostboot/Dump.pm
index 705638aa2..90b445df9 100755
--- a/src/build/debug/Hostboot/Dump.pm
+++ b/src/build/debug/Hostboot/Dump.pm
@@ -6,7 +6,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2018
+# Contributors Listed Below - COPYRIGHT 2012,2019
# [+] International Business Machines Corp.
#
#
@@ -106,6 +106,13 @@ sub main
$debug = 1;
}
+ # Parse 'quiet' option.
+ my $quiet = 0;
+ if (defined $args->{"quiet"})
+ {
+ $quiet = 1;
+ }
+
# Check for a different output directory
my $outdir = "./";
if (defined $args->{"outdir"})
@@ -128,7 +135,7 @@ sub main
open( OUTFH, ">$hbDumpFile" ) or die "can't open $hbDumpFile: $!\n";
binmode(OUTFH);
- ::userDisplay "Using HRMOR=". ::getHRMOR() . "\n";
+ ::userDisplay "Using HRMOR=". sprintf("0x%X",::getHRMOR()) . "\n";
# Read memory regions and output to file.
foreach my $state (@{$memory_states{int $memstate}})
@@ -152,7 +159,7 @@ sub main
$curlength = $length_remaining;
}
- ::userDisplay (sprintf "...%x@%x\n", $curlength, $curstart);
+ ::userDisplay (sprintf "...%x@%x\n", $curlength, $curstart) if !$quiet;
my $data = ::readData($curstart, $curlength);
seek OUTFH, $curstart, SEEK_SET;
@@ -187,6 +194,7 @@ sub helpInfo
options => {
"outdir=<path>" => ["Output directory for dump file"],
"debug" => ["More debug output."],
+ "quiet" => ["Less output."],
},
);
}
diff --git a/src/build/debug/Hostboot/Gcov.pm b/src/build/debug/Hostboot/Gcov.pm
index 84df2f9f9..48e71d66b 100755
--- a/src/build/debug/Hostboot/Gcov.pm
+++ b/src/build/debug/Hostboot/Gcov.pm
@@ -1,4 +1,3 @@
-#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
@@ -6,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2015
+# Contributors Listed Below - COPYRIGHT 2012,2019
# [+] International Business Machines Corp.
#
#
@@ -23,15 +22,18 @@
# permissions and limitations under the License.
#
# IBM_PROLOG_END_TAG
+#!/usr/bin/perl
use strict;
+use warnings;
use File::Path;
use File::Basename;
+use IO::Handle;
package Hostboot::Gcov;
use Hostboot::_DebugFrameworkVMM qw(NotFound NotPresent getPhysicalAddr);
use Exporter;
-our @EXPORT_OK = ('main');
+our @EXPORT_OK = ('init', 'main', 'parseGcovInfo');
# NOTE:
#
@@ -50,26 +52,37 @@ our @EXPORT_OK = ('main');
use constant GCOV_EXTENDED_IMAGE_ADDRESS => (1024 * 1024 * 1024);
use constant GCOV_INFO_HEAD_SYMBOLNAME => "_gcov_info_head";
+use constant GCOV_INFO_MAGIC_SYMBOLNAME => "_gcov_info_magic";
+use constant GCOV_MAGIC_IDENTIFIER => 0xbeefb055;
-use constant GCOV_INFO_VERSION_OFFSET => 0;
-use constant GCOV_INFO_NEXT_OFFSET => GCOV_INFO_VERSION_OFFSET + 8;
-use constant GCOV_INFO_TIMESTAMP_OFFSET => GCOV_INFO_NEXT_OFFSET + 8;
-use constant GCOV_INFO_FILENAME_OFFSET => GCOV_INFO_TIMESTAMP_OFFSET + 8;
-use constant GCOV_INFO_NFUNCTIONS_OFFSET => GCOV_INFO_FILENAME_OFFSET + 8;
-use constant GCOV_INFO_FUNCTIONS_OFFSET => GCOV_INFO_NFUNCTIONS_OFFSET + 8;
-use constant GCOV_INFO_CTRMASK_OFFSET => GCOV_INFO_FUNCTIONS_OFFSET + 8;
-use constant GCOV_INFO_COUNTS_OFFSET => GCOV_INFO_CTRMASK_OFFSET + 8;
-
-use constant GCOV_FNINFO_IDENT_OFFSET => 0;
-use constant GCOV_FNINFO_CHECKSUM_OFFSET => GCOV_FNINFO_IDENT_OFFSET + 4;
-use constant GCOV_FNINFO_NCTRS_OFFSET => GCOV_FNINFO_CHECKSUM_OFFSET + 4;
+use constant GCOV_COUNTERS_492 => 9;
+use constant SIZEOF_PTR => 8;
+use constant SIZEOF_UINT64 => 8;
-use constant GCOV_CTRINFO_COUNT_OFFSET => 0;
-use constant GCOV_CTRINFO_VALUEPTR_OFFSET => GCOV_CTRINFO_COUNT_OFFSET + 8;
-
-use constant GCOV_GCDA_MAGIC_VALUE => 0x67636461;
use constant GCOV_FUNCTION_TAG => 0x01000000;
use constant GCOV_COUNTERS_TAG => 0x01a10000;
+use constant GCOV_PROGRAM_SUMMARY_TAG => 0xa3000000;
+
+use constant GCOV_GCDA_MAGIC_VALUE => 0x67636461;
+
+# See gcov.h for the structs (gcov_info, gcov_fn_info) from which
+# these offsets derive
+
+use constant GCOV_INFO_VERSION_OFFSET_492 => 0;
+use constant GCOV_INFO_NEXT_OFFSET_492 => 8;
+use constant GCOV_INFO_TIMESTAMP_OFFSET_492 => 16;
+use constant GCOV_INFO_FILENAME_OFFSET_492 => 24;
+use constant GCOV_INFO_MERGE_OFFSET_492 => 32;
+use constant GCOV_INFO_N_FUNCTIONS_OFFSET_492 => 32 + (9 * 8);
+use constant GCOV_INFO_FUNCTIONS_OFFSET_492 => GCOV_INFO_N_FUNCTIONS_OFFSET_492 + 8;
+
+use constant GCOV_FN_INFO_IDENT_OFFSET_492 => 8;
+use constant GCOV_FN_INFO_LINENO_CHECKSUM_OFFSET_492 => 12;
+use constant GCOV_FN_INFO_CFG_CHECKSUM_OFFSET_492 => 16;
+use constant GCOV_FN_INFO_CTR_INFO_OFFSET_492 => 24;
+
+use constant GCOV_CTR_INFO_NUM_OFFSET_492 => 0;
+use constant GCOV_CTR_INFO_VALUES_OFFSET_492 => 8;
# In memory format:
# GCC creates a 'gcov_info' structure for each .o file. The info
@@ -134,20 +147,43 @@ use constant GCOV_COUNTERS_TAG => 0x01a10000;
# uint64_ts, containing instrumented counts, for the preceeding function.
# Global of where we want the output to go.
-our $output_dir;
our $debug_mode;
+our $hbicore_extended_bin_file;
+our $hbicore_extended_bin_file_size;
BEGIN
{
$debug_mode = 0;
- $output_dir = "";
}
-return 1;
+
+sub init
+{
+ # TODO: We need to figure out how to handle reading data from
+ # HBB/HBRT for when those are instrumented. One hurdle is being
+ # able to determine from an address what module it belongs to,
+ # because HBB/HBI/HBRT are not necessarily laid out in memory as
+ # they are in PNOR or anywhere else.
+
+ my $hbicore_extended_bin_fname = "$ENV{SANDBOXROOT}/$ENV{SANDBOXNAME}/src/hbfw/img/hostboot_extended.bin";
+
+ userDebug("Opening " . $hbicore_extended_bin_fname . " for HBI\n");
+
+ unless (open($hbicore_extended_bin_file, "< $hbicore_extended_bin_fname")) {
+ ::userDisplay "Failed to open $hbicore_extended_bin_fname, exiting\n";
+ return 0;
+ }
+
+ binmode($hbicore_extended_bin_file);
+
+ $hbicore_extended_bin_file_size = -s $hbicore_extended_bin_fname;
+
+ return 1;
+}
sub main
{
- # Pick a new output directory based on the time.
- $output_dir = sprintf "gcov.output.%d/", time;
- File::Path::mkpath($output_dir);
+ if (!init()) {
+ return;
+ }
# Find all the hostboot modules.
my @modules = getModules();
@@ -160,7 +196,10 @@ sub main
my $pwd = `pwd`;
chomp $pwd;
- ::userDisplay "GCOV output written to: $pwd/$output_dir\n";
+
+ close $hbicore_extended_bin_file or die;
+
+ ::userDisplay("GCOV info extraction complete.\n");
}
sub parseModuleGcov
@@ -168,8 +207,23 @@ sub parseModuleGcov
my $module = shift;
::userDisplay "Extracting GCOV info for ".$module."\n";
+ # Search for magic symbol.
+ my ($gcov_magic, $unused) =
+ ::findSymbolAddress($module.GCOV_INFO_MAGIC_SYMBOLNAME);
+
+ if (!defined($gcov_magic))
+ {
+ $gcov_magic = 0;
+ }
+
+ if ($gcov_magic == 0 || read32($gcov_magic, 1) != GCOV_MAGIC_IDENTIFIER)
+ {
+ ::userDisplay "\tgcov_magic at address " . (sprintf "0x%x", $gcov_magic) . " is incorrect. Skipped.\n";
+ return;
+ }
+
# Search for gcov_info chain symbol.
- my ($gcov_info, $unused) =
+ my ($gcov_info, $unused2) =
::findSymbolAddress($module.GCOV_INFO_HEAD_SYMBOLNAME);
userDebug("\tFound info at 0x" . (sprintf "%x", $gcov_info) . "\n");
@@ -181,7 +235,7 @@ sub parseModuleGcov
if (($gcov_info eq NotFound) || ($gcov_info eq NotPresent))
{
- ::userDisplay "\tModule data is not present.\n";
+ ::userDisplay "\tModule data is not present, module might have been unloaded, skipping.\n";
return;
}
}
@@ -189,7 +243,7 @@ sub parseModuleGcov
# Check that we found the gcov_info chain.
if ($gcov_info == 0)
{
- ::userDisplay "\tUnable to find gcov_info chain. Skipped.\n";
+ ::userDisplay "\tUnable to find gcov_info chain, module might hvae been unloaded. Skipping.\n";
return;
}
@@ -202,39 +256,44 @@ sub parseGcovInfo
my $info_ptr = shift;
return if (0 eq $info_ptr);
- my $filename = readStr(read64($info_ptr + GCOV_INFO_FILENAME_OFFSET));
- userDebug("\tFile = ".$filename."\n");
+ userDebug("\tReading filename pointer from offset " . (sprintf "0x%x", ($info_ptr + GCOV_INFO_FILENAME_OFFSET_492)) . "\n");
- my $version = read32($info_ptr + GCOV_INFO_VERSION_OFFSET);
- my $stamp = read32($info_ptr + GCOV_INFO_TIMESTAMP_OFFSET);
+ my $filename_addr = read64($info_ptr + GCOV_INFO_FILENAME_OFFSET_492);
- my $func_count = read32($info_ptr + GCOV_INFO_NFUNCTIONS_OFFSET);
- userDebug("\tFunction Count = ".$func_count."\n");
+ userDebug("\tReading filename from offset " . (sprintf "0x%x", $filename_addr) . "\n");
- my $funcs = read64($info_ptr + GCOV_INFO_FUNCTIONS_OFFSET);
- userDebug("\tFunc Address = ".(sprintf "%x", $funcs)."\n");
+ my $filename = readStr($filename_addr);
- my $ctrmask = read32($info_ptr + GCOV_INFO_CTRMASK_OFFSET);
- if ($ctrmask % 2) # Check that COUNTER_ARCS is turned on.
- {
- # COUNTER_ARCS is on. Create file, find arc-values array,
- # parse functions.
+ if ($filename) {
+ ::userDisplay("\tFile = ".$filename."\n");
- my $fd = createGcovFile($filename, $version, $stamp);
+ my $version = read32($info_ptr + GCOV_INFO_VERSION_OFFSET_492);
+ my $stamp = read32($info_ptr + GCOV_INFO_TIMESTAMP_OFFSET_492);
- my $arcs_ptr = read64($info_ptr + GCOV_INFO_COUNTS_OFFSET +
- GCOV_CTRINFO_VALUEPTR_OFFSET);
- parseGcovFuncs($fd, $funcs, $func_count, $ctrmask, $arcs_ptr);
+ my $func_count = read32($info_ptr + GCOV_INFO_N_FUNCTIONS_OFFSET_492);
+ userDebug("\tFunction Count = ".$func_count."\n");
- close $fd;
- }
- else
- {
- userDebug("COUNTER_ARCS is missing!\n");
+ my $funcs = read64($info_ptr + GCOV_INFO_FUNCTIONS_OFFSET_492, 1);
+
+ if ($funcs ne NotFound && $funcs ne NotPresent) {
+ userDebug("\tFunc Address = ".(sprintf "0x%x", $funcs)."\n");
+
+ if ($version ne NotFound && $stamp ne NotFound && $func_count ne NotFound) {
+ my $fd = createGcovFile($filename, $version, $stamp);
+
+ parseGcovFuncs($fd, $funcs, $func_count);
+
+ close $fd or die $!;
+ }
+ } else {
+ userDebug("\tFunc Address is NULL, skipping\n");
+ }
+ } else {
+ userDebug("\tCannot read filename, skipping\n");
}
# Look for next .o in gcov_info chain, parse.
- my $next = read64($info_ptr + GCOV_INFO_NEXT_OFFSET);
+ my $next = read64($info_ptr + GCOV_INFO_NEXT_OFFSET_492);
parseGcovInfo($next);
}
@@ -243,62 +302,95 @@ sub parseGcovFuncs
my $fd = shift;
my $func_ptr = shift;
my $func_count = shift;
- my $mask = shift;
- my $val_ptr = shift;
- my $fn_offset = 0;
+ my $GCOV_COUNTERS_SUMMABLE_492 = 1;
- # Need to calculate the number of counters based on the bits on in
- # the 'mask'. This is used to determine the size of the function
- # descriptor object.
- my $counters = 0;
- {
- my $_mask = $mask;
+ print $fd pack('l', GCOV_PROGRAM_SUMMARY_TAG); # data.program.header.tag
- while (0 != $_mask)
- {
- $counters++;
- $_mask = ($_mask >> 1);
- }
- }
+ # for each GCOV_COUNTERS_SUMMABLE we have ten int32 (num, runs, and bitvector{8})
+ # plus three int64 (sum, max, sum_max) i.e. 10 + 3*2
+ # data.unit.header.length is the number of int32's we have following.
+ print $fd pack('l', 1 + $GCOV_COUNTERS_SUMMABLE_492 * (10 + 3 * 2)); # data.unit.header.length;
- userDebug("\tCounters = ".$counters."\n");
+ print $fd pack('l', 0); # data.summary:object.checksum (must be 0 according to docs)
- # Round up the counter count to the nearest two for alignment of the
- # function descriptor object.
- if ($counters % 2)
- {
- $counters++;
- }
- my $func_size = GCOV_FNINFO_CHECKSUM_OFFSET + 4 * $counters;
+ for (my $i = 0; $i < $GCOV_COUNTERS_SUMMABLE_492; $i++) {
+ print $fd pack('l', 0); # data.summary:object.count-summary.num
+ print $fd pack('l', 0); # data.summary:object.count-summary.runs
+ print $fd pack('l', 0); # data.summary:object.count-summary.sum@lo
+ print $fd pack('l', 0); # data.summary:object.count-summary.sum@hi
+ print $fd pack('l', 0); # data.summary:object.count-summary.max@lo
+ print $fd pack('l', 0); # data.summary:object.count-summary.max@hi
+ print $fd pack('l', 0); # data.summary:object.count-summary.sum_max@lo
+ print $fd pack('l', 0); # data.summary:object.count-summary.sum_max@hi
- userDebug("\tFunction size = ".$func_size."\n");
+ print $fd pack('l8', (0) x 8); # data.summary:object.count-summary.histogram.bitvector{8}
+ }
# Iterate through the functions and parse.
for(my $function = 0; $function < $func_count; $function++)
{
- my $func_off = ($func_ptr + $func_size * $function);
- my $ident = read32($func_off + GCOV_FNINFO_IDENT_OFFSET);
- my $chksum = read32($func_off + GCOV_FNINFO_CHECKSUM_OFFSET);
+ userDebug("\tFunction $function of $func_count\n");
+
+ my $fn_info_ptr = read64($func_ptr + SIZEOF_PTR*$function, 1);
+
+ if (($fn_info_ptr eq NotFound) || ($fn_info_ptr eq NotPresent))
+ {
+ userDebug("\tCannot read function info pointer, skipping\n");
+ next;
+ }
+
+ userDebug("\tfn_info_ptr = " . (sprintf "%x", $fn_info_ptr) . "\n");
+
+ my $ident = read32($fn_info_ptr + GCOV_FN_INFO_IDENT_OFFSET_492, 1);
+ my $lineno_chksum = read32($fn_info_ptr + GCOV_FN_INFO_LINENO_CHECKSUM_OFFSET_492, 1);
+ my $cfg_chksum = read32($fn_info_ptr + GCOV_FN_INFO_CFG_CHECKSUM_OFFSET_492, 1);
+ my $ctr_info_ptr = $fn_info_ptr + GCOV_FN_INFO_CTR_INFO_OFFSET_492;
+
+ if ($ident eq NotFound
+ || $lineno_chksum eq NotFound
+ || $cfg_chksum eq NotFound)
+ {
+ userDebug("Skipping because fn_info structure members are not readable\n");
+ next;
+ }
+
+ my $num_ctrs = read32($ctr_info_ptr + GCOV_CTR_INFO_NUM_OFFSET_492, 1);
+ my $ctrs_ptr = read64($ctr_info_ptr + GCOV_CTR_INFO_VALUES_OFFSET_492, 1);
+
+ if ($ctrs_ptr eq NotFound || $num_ctrs eq NotFound)
+ {
+ userDebug("Skipping because counters length isn't mapped\n");
+ next;
+ }
- userDebug("Ident = ".(sprintf "%x", $ident)."\n");
- userDebug("Chksum = ".(sprintf "%x", $chksum)."\n");
+ my $counters = readData($ctrs_ptr, SIZEOF_UINT64 * $num_ctrs);
+
+ userDebug("Ident = ".(sprintf "0x%x", $ident)."\n");
+ userDebug("lineno Chksum = ".(sprintf "0x%x", $lineno_chksum)."\n");
+ userDebug("cfg Chksum = ".(sprintf "0x%x", $cfg_chksum)."\n");
+ userDebug("Num counters = ".(sprintf "%d", $num_ctrs)."\n");
+ userDebug("ctrs_ptr = ".(sprintf "0x%x", $ctrs_ptr)."\n");
+
+ if (($counters eq NotFound) || ($counters eq NotPresent))
+ {
+ userDebug("Skipping because counter data not resident in memory\n");
+ next;
+ }
print $fd pack('l', GCOV_FUNCTION_TAG); # Write function tag.
- print $fd pack('l', 2); # Write size = 2.
+ print $fd pack('l', 3); # Write size = 3.
print $fd pack('l', $ident); # Write ident.
- print $fd pack('l', $chksum); # Write checksum.
-
- my $nctr_val = read32($func_off + GCOV_FNINFO_NCTRS_OFFSET);
- userDebug("N-Counters = ".$nctr_val."\n");
+ print $fd pack('l', $lineno_chksum); # Write checksum.
+ print $fd pack('l', $cfg_chksum); # Write checksum.
print $fd pack('l', GCOV_COUNTERS_TAG); # Write counter tag.
- print $fd pack('l', $nctr_val * 2); # Write counter length.
+ print $fd pack('l', $num_ctrs * 2); # Write counter length.
# Read each counter value, output.
# Read as one big block for performance reasons.
- my $counters = readData($val_ptr + 8*($fn_offset), 8 * $nctr_val);
- for(my $v_idx = 0; $v_idx < $nctr_val; $v_idx++)
+
+ for(my $v_idx = 0; $v_idx < $num_ctrs; $v_idx++)
{
my $val = substr $counters, 0, 8;
$counters = substr $counters, 8;
@@ -306,15 +398,34 @@ sub parseGcovFuncs
$val = unpack("Q", $val);
userDebug("\tValue[$v_idx] = ".$val."\n");
+ my $preex_read_low = read($fd, my $low_word, 4);
+ my $preex_read_high = read($fd, my $high_word, 4);
+
+ if (!defined($preex_read_low) or !(defined($preex_read_high))) {
+ die;
+ }
+ my $preex_read = $preex_read_low + $preex_read_high;
+
+ if ($preex_read == 8)
+ {
+ my $preex_val = (unpack("l", $high_word) << 32) | unpack("l", $low_word);
+
+ $val += $preex_val;
+ }
+
+ if ($preex_read > 0)
+ {
+ seek $fd, -$preex_read, 1;
+ }
+ else
+ {
+ seek $fd, 0, 2;
+ }
+
print $fd pack('l', $val & 0xFFFFFFFF); # Write lower word.
print $fd pack('l', $val >> 32) ; # Write upper word.
}
-
- # We used up a number of counters, so move the offset forward for
- # the next function.
- $fn_offset += $nctr_val;
}
-
}
# The *.gcda filename found in the gcov_info struct is an absolute path to
@@ -330,16 +441,25 @@ sub createGcovFile
my $version = shift;
my $stamp = shift;
- # Change *./../obj/ into obj/, prepend output_dir.
- $name =~ s/.*\/obj\//obj\//;
- $name = $output_dir.$name;
-
- # Make sure everything after 'obj/' exists (create subdirs).
- my $dir = File::Basename::dirname($name);
- File::Path::mkpath($dir);
+ # if the file exists then we update it, if not we create it
+ my $GCOVFILE;
+ if (-e $name)
+ {
+ if (!open($GCOVFILE, "+<$name"))
+ {
+ ::userDisplay("Failed to open $name for reading/writing gcov information\n");
+ die;
+ }
+ }
+ else
+ {
+ if (!open($GCOVFILE, "+>$name"))
+ {
+ ::userDisplay("Failed to open $name for writing gcov information\n");
+ die;
+ }
+ }
- # Create file.
- open(my $GCOVFILE, "> $name");
binmode($GCOVFILE);
# Write out header.
@@ -377,6 +497,22 @@ sub isVirtualAddress
return ($addr >= GCOV_EXTENDED_IMAGE_ADDRESS);
}
+sub readExtImage
+{
+ my $addr = shift;
+ my $amount = shift;
+
+ if ($addr + $amount >= $hbicore_extended_bin_file_size) {
+ return NotFound;
+ }
+
+ seek $hbicore_extended_bin_file, $addr, 0;
+
+ read $hbicore_extended_bin_file, my ($contents), $amount;
+
+ return $contents;
+}
+
# Utility to read a block of data from eithr memory or using the extended
# image file as a fallback if not present in memory.
use constant PAGESIZE => 4096;
@@ -401,8 +537,13 @@ sub readData
my $paddr = getPhysicalAddr($addr);
if ((NotFound eq $paddr) || (NotPresent eq $paddr))
{
- $paddr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS;
- $result = $result.::readExtImage($paddr, $amount);
+ my $tmpdata = readExtImage($addr - GCOV_EXTENDED_IMAGE_ADDRESS, $amount);
+
+ if ($tmpdata eq NotFound) {
+ return NotFound;
+ }
+
+ $result = $result . $tmpdata;
}
else
{
@@ -423,14 +564,27 @@ sub readData
sub read64
{
my $addr = shift;
+ my $fallback = shift;
+
my $old_addr = $addr;
if (isVirtualAddress($addr))
{
$addr = getPhysicalAddr($addr);
if ((NotFound eq $addr) || (NotPresent eq $addr))
{
+ userDebug((sprintf "0x%x", $old_addr). " not translatable 2\n");
+
+ if (!$fallback) {
+ return NotFound;
+ }
+
$addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS;
- my $result = ::readExtImage($addr, 8);
+ my $result = readExtImage($addr, 8);
+
+ if ($result eq NotFound) {
+ return NotFound;
+ }
+
if (::littleendian()) { $result = reverse($result); }
return unpack("Q", $result);
}
@@ -444,14 +598,25 @@ sub read64
sub read32
{
my $addr = shift;
+ my $fallback = shift;
+
my $old_addr = $addr;
if (isVirtualAddress($addr))
{
$addr = getPhysicalAddr($addr);
if ((NotFound eq $addr) || (NotPresent eq $addr))
{
+ userDebug((sprintf "0x%x", $old_addr). "not translatable 3\n");
+
+ if (!$fallback) {
+ return NotFound;
+ }
+
$addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS;
- my $result = ::readExtImage($addr, 4);
+ my $result = readExtImage($addr, 4);
+ if ($result eq NotFound) {
+ return NotFound;
+ }
if (::littleendian()) { $result = reverse($result); }
return unpack("L", $result);
}
@@ -471,8 +636,10 @@ sub read8
$addr = getPhysicalAddr($addr);
if ((NotFound eq $addr) || (NotPresent eq $addr))
{
+ userDebug((sprintf "0x%x", $addr). "not translatable 4\n");
+
$addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS;
- my $result = ::readExtImage($addr, 1);
+ my $result = readExtImage($addr, 1);
return unpack("C", $result);
}
}
@@ -486,31 +653,82 @@ sub readStr
{
my $addr = shift;
my $old_addr = $addr;
+
if (isVirtualAddress($addr))
{
- $addr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS;
+ userDebug("it is a virtual address, addr is " . (sprintf "%x", $addr) . "\n");
+ my $phys_addr = getPhysicalAddr($addr);
- # Virtual address, so need to read 1 byte at a time from the file.
- my $string = "";
- my $byte = 0;
-
- do
+ if ((NotFound eq $phys_addr) || (NotPresent eq $phys_addr))
{
- $byte = ::readExtImage($addr,1);
- $addr = $addr + 1;
+ userDebug("Translation not found, reading from pnor\n");
+ # Virtual address, so need to read 1 byte at a time from the file.
+ my $string = "";
+ my $byte = 0;
- if (unpack("C",$byte) eq 0)
+ do
{
- return $string;
- }
+ $byte = readExtImage($addr - GCOV_EXTENDED_IMAGE_ADDRESS, 1);
- $string = $string.$byte;
+ if ($byte eq NotFound)
+ {
+ return "";
+ }
- } while (1)
+ $addr = $addr + 1;
+
+ if (unpack("C",$byte) eq 0)
+ {
+ return $string;
+ }
+
+ $string = $string.$byte;
+ } while (1);
+ }
+ else
+ {
+ my $string = "";
+ my $byte = 0;
+
+ do
+ {
+ if (($addr & 0xfff) == 0)
+ {
+ # we have to recalculate the physical address
+ # whenever we cross a page boundary
+ $phys_addr = getPhysicalAddr($addr);
+
+ if ((NotFound eq $phys_addr) || (NotPresent eq $phys_addr))
+ {
+ userDebug((sprintf "0x%x", $addr). "not translatable 10\n");
+ return "";
+ }
+ }
+
+ $byte = read8($phys_addr);
+
+ if ($byte eq NotFound)
+ {
+ userDebug("Cannot read byte from physical address\n");
+ return "";
+ }
+
+ $addr += 1;
+ $phys_addr += 1;
+
+ if ($byte != 0)
+ {
+ $string = $string . pack("C", $byte);
+ }
+ } while ($byte != 0);
+
+ return $string;
+ }
}
else
{
- ::readStr($addr);
+ userDebug("it is NOT a virtual address\n");
+ return ::readStr($addr);
}
}
@@ -531,3 +749,5 @@ sub helpInfo
intro => [ "Extracts the GCOV information."],
);
}
+
+1; # Last expression in a perl module must be truthy.
diff --git a/src/build/debug/Hostboot/GcovModuleUnload.pm b/src/build/debug/Hostboot/GcovModuleUnload.pm
new file mode 100644
index 000000000..1a411cc3c
--- /dev/null
+++ b/src/build/debug/Hostboot/GcovModuleUnload.pm
@@ -0,0 +1,69 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/debug/Hostboot/GcovModuleUnload.pm $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2019
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+#!/usr/bin/perl
+use strict;
+use File::Path;
+use File::Basename;
+
+package Hostboot::GcovModuleUnload;
+use Hostboot::Gcov qw(parseGcovInfo init);
+
+use Exporter;
+our @EXPORT_OK = ('main', 'parseGcovInfo');
+
+sub main
+{
+ my ($packName, $args) = @_;
+
+ my $gcov_info_address = $args->{"address"};
+
+ ::userDisplay("Dumping gcov module info from " . (sprintf "0x%x", $gcov_info_address) . "\n");
+
+ if ($gcov_info_address <= 0) {
+ ::userDisplay("Can't dump from NULL\n");
+ return -1;
+ }
+
+ if (!Hostboot::Gcov::init()) {
+ return -2;
+ }
+
+ Hostboot::Gcov::parseGcovInfo($gcov_info_address);
+
+ ::userDisplay("Done.\n");
+
+ return 0;
+}
+
+# Debug tool help info.
+sub helpInfo
+{
+ my %info = (
+ name => "GcovModuleUnload",
+ intro => [ "Extracts the GCOV information from modules as they are being unloaded."],
+ );
+}
+
+1; # Last expression in a perl module must be truthy.
diff --git a/src/build/debug/Hostboot/PrintVMM.pm b/src/build/debug/Hostboot/PrintVMM.pm
index 476262d93..57a57a9e2 100644
--- a/src/build/debug/Hostboot/PrintVMM.pm
+++ b/src/build/debug/Hostboot/PrintVMM.pm
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2018
+# Contributors Listed Below - COPYRIGHT 2012,2020
# [+] International Business Machines Corp.
#
#
@@ -73,7 +73,7 @@ sub main
my @segment_manager_addr = ::findPointer("SGMNTMGR",
"Singleton<SegmentManager>::instance()::instance");
- if (not defined @segment_manager_addr)
+ if (not @segment_manager_addr)
{
::userDisplay " VirtualToPhy: Cannot find Device Segment symbol.\n"; die;
}
diff --git a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
index 128df4ec7..ca323bd32 100755
--- a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
+++ b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
@@ -6,7 +6,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2018
+# Contributors Listed Below - COPYRIGHT 2012,2020
# [+] International Business Machines Corp.
#
#
@@ -404,7 +404,7 @@ sub getPhysicalAddr
"Singleton<SegmentManager>::instance()::instance");
- if (not defined @segment_manager_addr)
+ if (not @segment_manager_addr)
{
::userDisplay " VirtualToPhy: Cannot find SegmentManager symbol.\n";
return NotFound;
diff --git a/src/build/debug/eSEL.pl b/src/build/debug/eSEL.pl
index ddce72f50..ed9ef2335 100755
--- a/src/build/debug/eSEL.pl
+++ b/src/build/debug/eSEL.pl
@@ -6,7 +6,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2017,2018
+# Contributors Listed Below - COPYRIGHT 2017,2019
# [+] International Business Machines Corp.
#
#
@@ -588,6 +588,11 @@ sub DecodeObmcEselData
$timestamp_found = 1;
last;
}
+ elsif($next_line =~ /timestamp/)
+ {
+ $timestamp_found = 2;
+ last;
+ }
elsif($next_line =~ /ESEL/ or
$next_line =~ /20 00 04/) # found the next ESEL
{
@@ -601,16 +606,35 @@ sub DecodeObmcEselData
if($timestamp_found)
{
- # strip the "Timestamp", commas, spaces, and the newline
- $next_line =~ s/"Timestamp"://g;
- $next_line =~ s/,//g;
- $next_line =~ s/ //g;
- chomp $next_line;
-
- # convert to date/time (we are given the timestamp in ms, so divide
- # by 1000 to get s).
- $timestamp =
+ if($timestamp_found == 1)
+ {
+ # strip the "Timestamp", commas, spaces, and the newline
+ $next_line =~ s/"Timestamp"://g;
+ $next_line =~ s/,//g;
+ $next_line =~ s/ //g;
+ chomp $next_line;
+
+ # convert to date/time (we are given the timestamp in ms, so divide
+ # by 1000 to get s).
+ $timestamp =
strftime("%m/%d/%Y %H:%M:%S", localtime($next_line/1000));
+ }
+ elsif($timestamp_found == 2)
+ {
+ # Field format :: "timestamp": "2019-10-31 10:20:50"
+ $next_line =~ s/"timestamp"://g;
+ $next_line =~ s/"//g; #drop the quotes
+ my @tmp1 = split( " ", $next_line ); #break the date and time apart
+ my @df = split( /-/, $tmp1[0] ); #break up the date fields
+ # Convert to :: 11/05/2019 12:25:41
+ $timestamp = "$df[1]/$df[2]/$df[0] $tmp1[1]";
+ ($debug) && print "timestamp> $timestamp \n";
+ }
+ else
+ {
+ die "Bad timestamp\n";
+ }
+
($debug) && print "Timestamp for ESEL #$esel_record_count:$next_line\n";
($debug) && print "Decoded timestamp for ESEL #$esel_record_count:$timestamp\n";
diff --git a/src/build/debug/ffdcExpander b/src/build/debug/ffdcExpander
new file mode 100755
index 000000000..95f7c970f
--- /dev/null
+++ b/src/build/debug/ffdcExpander
@@ -0,0 +1,727 @@
+#!/bin/sh
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/debug/ffdcExpander $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2013,2020
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+
+###############################################################################
+# @file ffdcExpander
+# This shell script takes a SYSDUMP file and extracts various debug elements.
+# The caller has the option to post artifacts to a defect.
+#
+# The starting point for this script is at the end of the file.
+###############################################################################
+
+###############################################################################
+# Some helpful constants
+###############################################################################
+FFDC_GUNZIP_TOOL="/bin/gunzip"
+FFDC_DUMP_PARSER="/esw/bin/dumpparser"
+
+
+###############################################################################
+# Some global variables
+###############################################################################
+FFDC_3RD_PARTY_SCRIPT_DIR="/gsa/ausgsa/projects/h/hostboot/optools/" # Location of files updatecq.pl, cqcmd.pl and Slurp.pm
+FFDC_SCRIPT_NAME=$(basename "${0}") # Cache the name of this script
+FFDC_SCRIPT_DIR=$(dirname "${0}") # Location of this script and supporting scripts
+FFDC_SCRIPT_DIR="${FFDC_SCRIPT_DIR}/"
+FFDC_SYSDUMP_FILE_GZ="" # format SYSDUMP.13020B8.20000001.20190725181300.gz
+FFDC_SYSDUMP_FILE="" # format SYSDUMP.13020B8.20000001.20190725181300
+FFDC_HB_DUMP_FILE=""; # format hb.dump.SYSDUMP.13020B8.20000001.20190725181300
+FFDC_FSP_DRIVER_DIR="" # format '/esw/fips922/Builds/b0724a_1931.922'
+FFDC_FSP_DRIVER="" # format 'fips922', 'fips950' , etc
+FFDC_FSP_BUILD_TAG="" # format b0724a_1931.922
+FFDC_DEFECT_NUM="" # format 'SW123456', 'sw123456', 'Sw123456' or 'sW123456'
+FFDC_DEFECT_NUM_CHARS="8" # The number of characters expected in defect including 'SW'
+FFDC_CWD="`pwd -P`/" # The current working directory
+FFDC_DEST_DIR="${FFDC_CWD}" # The destination directory of artifacts, default to CWD
+FFDC_CQ_USER="" # The CQ user ID
+FFDC_CQ_PASS="" # The CQ password
+FFDC_RETURN_VALUE="0" # The return value. Default to success '0'
+FFDC_TIME_STAMP="" # A time stamp is generated to make the files unique
+
+###############################################################################
+# Print the usage line
+#
+# @return 0 if successful, not 0 if a failure occurred
+###############################################################################
+function _ffdcUsage_()
+{
+ echo ""
+ echo " Usage: ${FFDC_SCRIPT_NAME} -g <FFDC_SYSDUMP_FILE.gz> | -s <FFDC_SYSDUMP_FILE> |"
+ echo " -h <HB_FFDC_SYSDUMP_FILE> -b <FSP_BUILD_TAG>"
+ echo " [ OPTIONS ]"
+ echo ""
+ echo " OPTIONS: [ -d <DEST_DIR> ] [ -a <DEFECT_NUM> ] [ -t ]"
+ echo " -t attach a time stamp to the artifacts"
+ echo ""
+ echo " Examples: ${FFDC_SCRIPT_NAME} -g SYSDUMP.13020B8.20000001.20190725181300.raw67117184.gz"
+ echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184"
+ echo " ${FFDC_SCRIPT_NAME} -h hb.dump.SYSDUMP.13020B8.20000001.20190725181300 -b b0724a_1931.922"
+ echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184 -a SW123456 -t"
+ echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184 -d dir"
+ echo ""
+ return 0; # Return success
+}
+
+###############################################################################
+# @brief Get the caller's options and validate them
+#
+# @param [in] $* - All of the caller's inputs after name of script
+#
+# @return 0 if successful, not 0 if a failure occurred
+###############################################################################
+function _getUserInputOptionsAndValidate_()
+{
+ # Default caller options
+ CALLER_SYSDUMP_FILE_GZ=""
+ CALLER_SYSDUMP_FILE=""
+ CALLER_HB_DUMP_FILE=""
+ CALLER_FSP_BUILD_TAG=""
+ CALLER_DEST_DIR=""
+ CALLER_REQUESTS_TIME_STAMP=""
+
+ # Get caller's options
+ FFDC_RETURN_VALUE="22" # Default to 'Invalid argument'
+ MANDATORY_OPTION_CHOSEN="0"
+ echo ""
+ while getopts ts:g:h:b:d:a: option
+ do
+ if [ -n "${option}" ]; then
+ FFDC_RETURN_VALUE="0"; # Found an argument
+ fi
+ case "${option}"
+ in
+ t) CALLER_REQUESTS_TIME_STAMP=1;;
+ s) CALLER_SYSDUMP_FILE=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";;
+ g) CALLER_SYSDUMP_FILE_GZ=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";;
+ h) CALLER_HB_DUMP_FILE=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";;
+ b) CALLER_FSP_BUILD_TAG=${OPTARG};;
+ d) CALLER_DEST_DIR=${OPTARG};;
+ a) CALLER_DEFECT_NUM=${OPTARG};;
+ \?) FFDC_RETURN_VALUE=22;;
+ :) FFDC_RETURN_VALUE=22;;
+ esac
+ done
+
+ # If call to getopts not successful, then propagate error back
+ if [ "$FFDC_RETURN_VALUE" != "0" ]; then
+ _ffdcUsage_
+ return $FFDC_RETURN_VALUE;
+ fi
+
+ # Check for a valid option chosen
+ if [ "$MANDATORY_OPTION_CHOSEN" == "0" ]; then
+ _ffdcUsage_
+ return $FFDC_RETURN_VALUE;
+ fi
+
+ # Check for nonsensical options
+ if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then
+ echo " ERROR: Incompatible options: options -g and -s can't be used together";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi
+
+ if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ] && [ -n "${CALLER_HB_DUMP_FILE}" ]; then
+ echo " ERROR: Incompatible options: options -g and -h can't be used together";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi
+
+ if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then
+ echo " ERROR: Incompatible options: options -g and -b can't be used together";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi
+
+ if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then
+ echo " ERROR: Incompatible options: options -s and -b can't be used together";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi
+
+ if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_HB_DUMP_FILE}" ]; then
+ echo " ERROR: Incompatible options: options -s and -h can't be used together";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi
+
+ # Verify that if caller is passing in a HB dump file, they must supply the build tag
+ if [ -n "${CALLER_HB_DUMP_FILE}" ] && [ -z "${CALLER_FSP_BUILD_TAG}" ]; then
+ echo " ERROR: Must supply a -b option with the -h option";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi
+
+ if [ -z "${CALLER_HB_DUMP_FILE}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then
+ echo " ERROR: Must supply a -h option with the -b option";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi
+
+ # If caller requests a time stamp, option -t, then oblige
+ if [ "$CALLER_REQUESTS_TIME_STAMP" == "1" ]; then
+ FFDC_TIME_STAMP=$(date +%s)
+ FFDC_TIME_STAMP="_${FFDC_TIME_STAMP}"
+ fi
+
+ # If caller supplied a gzippped SYSDUMP file, option -g, then confirm it exists
+ if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then
+ if [ ! -e "${CALLER_SYSDUMP_FILE_GZ}" ]; then
+ echo " gzipped SYSDUMP file (${CALLER_SYSDUMP_FILE_GZ}) not found";
+ return 22; # return 'Invalid argument'
+ fi
+
+ # Check if file given is a gzipped file, verify that it ends in .gz
+ if [[ "${CALLER_SYSDUMP_FILE_GZ}" != *\.gz ]]; then
+ echo " ";
+ echo " WARNING: It appears that file (${CALLER_SYSDUMP_FILE_GZ}) is not a gzipped file"
+ while true; do
+ echo ""
+ read -p " Do you wish to continue with file [Y/N] ? " yn
+ case $yn in
+ [Yy] ) break;;
+ [Nn] ) echo " ÂŻ\_(?)_/ÂŻ exiting ..."; echo ""; return 22;; # return 'Invalid argument'
+ * ) echo " Please answer [Y]es or [N]o.";;
+ esac
+ done
+ fi
+
+ # Save caller's gzippped SYSDUMP file, option -g
+ FFDC_SYSDUMP_FILE_GZ="$CALLER_SYSDUMP_FILE_GZ"
+
+ ## Add an absolute path to the gzipped file, if not already an absolute path
+ # Check the first character to see if starting with absolute path
+ FIRST_CHAR="${FFDC_SYSDUMP_FILE_GZ:0:1}"
+ # If first char not a '/' then append an absolute path
+ if [ "${FIRST_CHAR}" != "/" ]; then
+ FFDC_SYSDUMP_FILE_GZ="${FFDC_CWD}${FFDC_SYSDUMP_FILE_GZ}"
+ fi
+ fi # end if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then
+
+
+ # If caller supplied a SYSDUMP file, option -f, then confirm it exists
+ if [ -n "${CALLER_SYSDUMP_FILE}" ]; then
+ if [ ! -e "${CALLER_SYSDUMP_FILE}" ]; then
+ echo " SYSDUMP file (${CALLER_SYSDUMP_FILE}) not found";
+ return 22; # return 'Invalid argument'
+ fi
+
+ # Save caller's SYSDUMP file, option -f
+ FFDC_SYSDUMP_FILE="${CALLER_SYSDUMP_FILE}"
+
+ ## Add an absolute path to the gzipped file, if not already an absolute path
+ # Check the first character to see if starting with absolute path
+ FIRST_CHAR="${FFDC_SYSDUMP_FILE:0:1}"
+ # If first char not a '/' then append an absolute path
+ if [ "${FIRST_CHAR}" != "/" ]; then
+ FFDC_SYSDUMP_FILE="${FFDC_CWD}${FFDC_SYSDUMP_FILE}"
+ fi
+ fi # end if [ -n "${CALLER_SYSDUMP_FILE}" ]; then
+
+
+ # If caller supplied a HB dump file, option -h, then confirm it exists
+ if [ -n "${CALLER_HB_DUMP_FILE}" ]; then
+ if [ ! -e "${CALLER_HB_DUMP_FILE}" ]; then
+ echo " HB dump file (${CALLER_HB_DUMP_FILE}) not found";
+ return 22; # return 'Invalid argument'
+ fi
+
+ # Save caller's HB dump file, option -h
+ FFDC_HB_DUMP_FILE="${CALLER_HB_DUMP_FILE}"
+
+ ## Add an absolute path to the HB dump file, if not already an absolute path
+ # Check the first character to see if starting with absolute path
+ FIRST_CHAR="${FFDC_HB_DUMP_FILE:0:1}"
+ # If first char not a '/' then append an absolute path
+ if [ "${FIRST_CHAR}" != "/" ]; then
+ FFDC_HB_DUMP_FILE="${FFDC_CWD}${FFDC_HB_DUMP_FILE}"
+ fi
+ fi # end if [ -n "${CALLER_HB_DUMP_FILE}" ]; then
+
+
+ # If caller supplied an FSP build tag, option -b, then validate it
+ if [ -n "${CALLER_FSP_BUILD_TAG}" ]; then
+ # Extrapolate the FSP Build Release from the FSP build tag
+ if [[ "${CALLER_FSP_BUILD_TAG}" = *"."* ]]; then
+ FIPS_VERS=$(echo ${CALLER_FSP_BUILD_TAG} | \cut -d"." -f 2)
+ if [ -n "${FIPS_VERS}" ]; then
+ FFDC_FSP_DRIVER="fips${FIPS_VERS}"
+ else
+ echo " ";
+ echo " Build tag (${CALLER_FSP_BUILD_TAG}) appears to be in wrong format";
+ echo " Cannot extrapolate the FIPS version from build tag";
+ return 22; # return 'Invalid argument'
+ fi
+ else
+ echo " ";
+ echo " Build tag (${CALLER_FSP_BUILD_TAG}) appears to be in wrong format";
+ echo " Cannot extrapolate the FIPS version from build tag";
+ _ffdcUsage_
+ return 22; # return 'Invalid argument'
+ fi # end if [[ "${CALLER_FSP_BUILD_TAG}" = *"."* ]]; then
+
+ # Save the caller's FSP build tag
+ FFDC_FSP_BUILD_TAG="${CALLER_FSP_BUILD_TAG}"
+
+ # Save the caller's FSP build tag with the directory to it
+ FFDC_FSP_DRIVER_DIR="/esw/${FFDC_FSP_DRIVER}/Builds/${CALLER_FSP_BUILD_TAG}"
+ fi # end if [ -n "${CALLER_FSP_BUILD_TAG}" ]; then
+
+ # If caller supplied a defect, option -a, just confirm it is in the correct
+ # nomenclature and format
+ if [ -n "${CALLER_DEFECT_NUM}" ]; then
+
+ FFDC_DEFECT_NUM=$(echo ${CALLER_DEFECT_NUM^^})
+ if [[ $FFDC_DEFECT_NUM != SW* ]]; then
+ echo " ERROR: software defect must be preceded with 'SW'";
+ echo " ";
+ return 22; # return 'Invalid argument'
+ fi
+
+ NUM_CHARS=${#FFDC_DEFECT_NUM}
+ if [[ "${NUM_CHARS}" -ne "${FFDC_DEFECT_NUM_CHARS}" ]]; then
+ echo " ERROR: software defect must have a total of ${FFDC_DEFECT_NUM_CHARS} characters, including 'SW'";
+ echo " ";
+ return 22; # return 'Invalid argument'
+ fi
+
+ INTEGER_PART=$(echo ${CALLER_DEFECT_NUM} | sed "s/^SW//g")
+ REG_EXP='^[0-9]+$'
+ if ! [[ $INTEGER_PART =~ $REG_EXP ]]; then
+ echo " ERROR: the characters (${INTEGER_PART}) that follow 'SW' must be an integer";
+ echo " ";
+ return 22; # return 'Invalid argument'
+ fi
+
+ # Prompt username and password for CQ
+ _queryUserPassword_;
+ FFDC_RETURN_VALUE=$?
+ if [ "${FFDC_RETURN_VALUE}" != "0" ]; then
+ echo ""
+ return ${FFDC_RETURN_VALUE}; # Return failure
+ fi
+ fi # end # If caller supplied a defect, option -a, ...
+
+
+ # If caller supplied a destination directory, option -d, then confirm it
+ # exists and determine if it is a relative path or absolute path
+ if [ -n "${CALLER_DEST_DIR}" ]; then
+ if [ ! -e "${CALLER_DEST_DIR}" ]; then
+ echo " Destination directory (${CALLER_DEST_DIR}) not found";
+ while true; do
+ echo ""
+ read -p " Do you wish to ceate it [Y/N] ? " yn
+ case $yn in
+ [Yy] ) break;;
+ [Nn] ) echo " ÂŻ\_(?)_/ÂŻ exiting ..."; echo ""; return 22;; # return 'Invalid argument'
+ * ) echo " Please answer [Y]es or [N]o.";;
+ esac
+ done
+
+ mkdir -p ${CALLER_DEST_DIR}
+ FFDC_RETURN_VALUE=$?
+ if [ "$FFDC_RETURN_VALUE" != "0" ]; then
+ echo ""
+ return $FFDC_RETURN_VALUE; # Propagate failure
+ fi
+ echo " Destination directory (${CALLER_DEST_DIR}) created";
+ echo ""
+ fi
+
+ # Save caller's destination directory option
+ FFDC_DEST_DIR="$CALLER_DEST_DIR"
+ NUM_CHARS=$((${#FFDC_DEST_DIR}-1))
+ LAST_CHAR="${FFDC_DEST_DIR:$NUM_CHARS:1}"
+ # If last char not a '/' then append a '/'
+ if [ "${LAST_CHAR}" != "/" ]; then
+ FFDC_DEST_DIR="${FFDC_DEST_DIR}/"
+ fi
+
+ ## Add an absolute path to the destination directory, if it is not
+ ## already an absolute path.
+ # Inspect the first character to determine path is absolute or not
+ FIRST_CHAR="${FFDC_DEST_DIR:0:1}"
+ # If first char not a '/' then append an absolute path
+ if [ "${FIRST_CHAR}" != "/" ]; then
+ FFDC_DEST_DIR="${FFDC_CWD}${FFDC_DEST_DIR}"
+ fi
+ fi # end if [ -n "${CALLER_DEST_DIR}" ]; then
+
+ return 0; # Return success
+}
+
+###############################################################################
+# @brief Query caller for user name and password
+###############################################################################
+function _queryUserPassword_()
+{
+ if [ -n "${FFDC_DEFECT_NUM}" ]; then
+ read -p 'CQ Username: ' FFDC_CQ_USER
+ read -sp 'CQ Password: ' FFDC_CQ_PASS
+ fi
+
+ return 0;
+}
+
+###############################################################################
+# @brief Unzip the system dump file
+#
+# Example: unzip SYSDUMP.13020B8.20000001.20190725181300.raw67117184.gz =>
+# SYSDUMP.13020B8.20000001.20190725181300.raw67117184
+#
+# @return 0 if successful, not 0 if a failure occurred
+###############################################################################
+function _unzipSysDumpFile_()
+{
+ # Verify that we can get to the dumpparser script
+ if [[ ! -e "${FFDC_GUNZIP_TOOL}" ]]; then
+ echo ""
+ echo " ERROR: Could not find gunzip tool ${FFDC_GUNZIP_TOOL}"
+ echo ""
+ return 2; # Return 'No such file or directory'
+ fi
+
+ ## Extrapolate the SYSDUMP file from the gzipped file
+ # Remove any directories and only get the file name
+ FFDC_SYSDUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE_GZ} | awk -F / '{ print $NF }')
+ # Remove the '.gz' from the gzipped file
+ FFDC_SYSDUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE} | sed "s/\.gz$//")
+ # Prepend the caller's directory
+ FFDC_SYSDUMP_FILE="${FFDC_DEST_DIR}${FFDC_SYSDUMP_FILE}"
+
+ # Check if the SYSDUMP file already exists, if so, ask caller if they wish
+ # to overwrite it
+ if [[ -e "${FFDC_SYSDUMP_FILE}" ]]; then
+ echo ""
+ echo " SYSDUMP file (${FFDC_SYSDUMP_FILE}) already exists ..."
+ while true; do
+ echo ""
+ read -p " Do you wish to override the file and continue [Y/N] ? " yn
+ case $yn in
+ [Yy] ) break;;
+ [Nn] ) echo " Skipping call to ${FFDC_GUNZIP_TOOL} ..."; echo ""; return 0;;
+ * ) echo " Please answer [Y]es or [N]o.";;
+ esac
+ done
+ fi
+
+ # Unzip the gzipped SYSDUMP file
+ echo ""
+ echo " ${FFDC_GUNZIP_TOOL} -c ${FFDC_SYSDUMP_FILE_GZ} > ${FFDC_SYSDUMP_FILE}"
+ `${FFDC_GUNZIP_TOOL} -c ${FFDC_SYSDUMP_FILE_GZ} > ${FFDC_SYSDUMP_FILE}`
+ FFDC_RETURN_VALUE=$?
+ if [ "${FFDC_RETURN_VALUE}" != "0" ]; then
+ echo ""
+ return ${FFDC_RETURN_VALUE}; # Return failure
+ fi
+
+ return 0; # Return success
+}
+
+
+###############################################################################
+# @brief Extract the HB system dump file from the SYSDUMP file
+#
+# Example: /esw/bin/dumpparser -extMem SYSDUMP.13020B8.20000001.20190725181300.raw67117184 =>
+# hb.dump.SYSDUMP.13020B8.20000001.20190725181300
+#
+# @return 0 if successful, not 0 if a failure occurred
+###############################################################################
+function _extractHbSysDumpFile_()
+{
+ # Verify that we can get to the dump parser script
+ if [[ ! -e "${FFDC_DUMP_PARSER}" ]]; then
+ echo ""
+ echo " ERROR: Could not find parser ${FFDC_DUMP_PARSER}"
+ echo ""
+ return 2; # Return 'No such file or directory'
+ fi
+
+ ## Extrapolate the HB dump file name from the SYSDUMP file
+ # Remove any directories and only get the file name
+ FFDC_HB_DUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE} | awk -F / '{ print $NF }')
+ # Remove the .gz from the SYSDUMP, if it exists
+ FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/\.gz$//")
+ # Remove the postpended '.rawxxx' from the SYSDUMP file, if it exists
+ FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/\.raw.*$//")
+ # Prepend 'hb.dump.' to file
+ FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/^/hb.dump./")
+ # Prepend the caller's directory
+ FFDC_HB_DUMP_FILE="${FFDC_DEST_DIR}${FFDC_HB_DUMP_FILE}"
+
+ # Extract the the FSP build info from the SYSDUMP file
+ FSP_BUILD_INFO=$(${FFDC_DUMP_PARSER} -a ${FFDC_SYSDUMP_FILE} | grep "Driver is" | awk '{ print $4 }')
+
+ # Extract the the FSP driver info from the FSP build info
+ FFDC_FSP_DRIVER=$(echo ${FSP_BUILD_INFO} | awk -F / '{ print $1 }')
+
+ # Extract the FSP build tag info from the FSP build info
+ FFDC_FSP_BUILD_TAG=$(echo ${FSP_BUILD_INFO} | awk -F / '{ print $2 }')
+
+ # Create a path to FSP build driver info
+ FFDC_FSP_DRIVER_DIR="/esw/${FFDC_FSP_DRIVER}/Builds/${FFDC_FSP_BUILD_TAG}"
+
+ # Check if the HB dump file already exists, if so, ask caller if they wish
+ # to overwrite it
+ if [[ -e "${FFDC_HB_DUMP_FILE}" ]]; then
+ echo ""
+ echo " HB system dump file (${FFDC_HB_DUMP_FILE}) already exists ..."
+ while true; do
+ echo ""
+ read -p " Do you wish to override the file and continue [Y/N] ? " yn
+ case $yn in
+ [Yy] ) break;;
+ [Nn] ) echo " Skipping call to ${FFDC_DUMP_PARSER} ..."; return 0;;
+ * ) echo " Please answer [Y]es or [N]o.";;
+ esac
+ done
+ fi
+
+ # Change directory to user supplied directory
+ \cd -P ${FFDC_DEST_DIR} ;
+
+ # Parse out the HB dump file using the dump parser
+ echo ""
+ echo " ${FFDC_DUMP_PARSER} -extMem ${FFDC_SYSDUMP_FILE}"
+ ${FFDC_DUMP_PARSER} -extMem ${FFDC_SYSDUMP_FILE}
+
+ FFDC_RETURN_VALUE=$?
+ if [ "${FFDC_RETURN_VALUE}" != "0" ]; then
+ # Return back to current working directory
+ \cd -P ${FFDC_CWD}
+ echo ""
+ return ${FFDC_RETURN_VALUE}; # Return failure
+ fi
+
+ echo " Created file ${FFDC_HB_DUMP_FILE}"
+
+ # Return back to current working directory
+ \cd -P ${FFDC_CWD}
+
+ return 0; # Return success
+}
+
+
+###############################################################################
+# @brief Set the path to the fsp-trace tool
+#
+# @return 0
+###############################################################################
+function _setFSPTracePath_()
+{
+ FFDC_FSP_PATH="/esw/$FFDC_FSP_DRIVER/Builds/built/images/nfs/x86.nfp/bin/"
+ echo ""
+ echo " Using fsp-trace tool: ${FFDC_FSP_PATH}fsp-trace"
+ PATH=${FFDC_FSP_PATH}:$PATH
+
+ # Verify that we can get to the dump parser script
+ if [[ ! -e "${FFDC_FSP_PATH}fsp-trace" ]]; then
+ echo ""
+ echo " ERROR: Could not find fsp trace ${FFDC_DUMP_PARSER}"
+ echo ""
+ return 2; # Return 'No such file or directory'
+ fi
+
+ echo "PATH=${FFDC_FSP_PATH}:\$PATH" >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+
+ return 0; # Return success
+}
+
+###############################################################################
+# @brief Extract various HB dump info
+#
+# @param [in] $1 The HB tools directory
+# @param [in] $2 Path to the hb-dump-debug tools directory
+###############################################################################
+function _getInfoFromHBDump_()
+{
+ echo ""
+ echo " Extracting the Trace information from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=Trace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=Trace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the Printk information from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=Printk --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=Printk --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the Errl information (Component/PLID list) from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=Errl --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=Errl --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the Errl information (Detailed listing of all Error Logs) from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=Errl --tool-options='display=all' --file=${FFDC_HB_DUMP_FILE} >> ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=Errl --tool-options='display=all' --file=${FFDC_HB_DUMP_FILE} >> ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the Ps information from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the Ps information from HB dump with backtrace ..."
+ echo " running: $1 --img-path=$2/ --tool=Ps --tool-options="with-backtrace" --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=Ps --tool-options="with-backtrace" --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the MemStats information from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=MemStats --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the PageMgr information from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=PageMgr --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=PageMgr --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP}
+
+ echo ""
+ echo " Extracting the BlTrace information from HB dump ..."
+ echo " running: $1 --img-path=$2/ --tool=BlTrace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ $1 --img-path=$2/ --tool=BlTrace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP}
+}
+
+###############################################################################
+# @brief Extract various HB dump info and post to defect, if caller wishes to
+###############################################################################
+function _getInfoFromHBDumpAndPost_()
+{
+ _setFSPTracePath_
+ FFDC_RETURN_VALUE=$?
+ # If call to _setFSPTracePath_ not successful, then propagate error back
+ if [ "$FFDC_RETURN_VALUE" != "0" ]; then
+ return $FFDC_RETURN_VALUE;
+ fi
+
+ HB_TOOLS_DIR=$FFDC_FSP_DRIVER_DIR/obj/x86.nfp/hbfw/simics
+ HB_DUMP_DEBUG=$HB_TOOLS_DIR/hb-dump-debug
+ _getInfoFromHBDump_ $HB_DUMP_DEBUG $HB_TOOLS_DIR
+
+ # If supplied a defect number, then post a comment to the defect and add
+ # the generated dump files as attachments
+ if [ -n "${FFDC_DEFECT_NUM}" ]; then
+ PATH=${FFDC_3RD_PARTY_SCRIPT_DIR}:$PATH
+ CQFILE=${FFDC_3RD_PARTY_SCRIPT_DIR}updatecq.pl
+
+ echo ""
+ echo -e "\n Adding attachment TRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS -s "Hostboot dump files stored at $FFDC_DEST_DIR"
+
+ echo -e "\n Adding attachment PRINTK${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS
+
+ echo -e "\n Adding attachment ERRL${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS
+
+ echo -e "\n Adding attachment PS${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS
+
+ echo -e "\n Adding attachment PS_BACKTRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS
+
+ echo -e "\n Adding attachment MEMSTATS${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS
+
+ echo -e "\n Adding attachment PAGEMGR${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS
+
+ echo -e "\n Adding attachment BLTRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..."
+ perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS
+ fi
+}
+
+
+###############################################################################
+# @brief The main. The real starting place of this script
+#
+# @return 0 if successful, not 0 if a failure occurred
+###############################################################################
+function ffdcExpanderMain()
+{
+ # Get user input options and validate
+ _getUserInputOptionsAndValidate_ $*
+ FFDC_RETURN_VALUE=$?
+ # If call to _getUserInputOptionsAndValidate_ not successful, then propagate error back
+ if [ "$FFDC_RETURN_VALUE" != "0" ]; then
+ return $FFDC_RETURN_VALUE;
+ fi
+
+
+ # If caller supplied a gzipped file then unzip it
+ if [ -n "${FFDC_SYSDUMP_FILE_GZ}" ]; then
+ _unzipSysDumpFile_
+ FFDC_RETURN_VALUE=$?
+ fi
+ # If call to _unzipSysDumpFile_ not successful, then propagate error back
+ if [ "$FFDC_RETURN_VALUE" != "0" ]; then
+ return $FFDC_RETURN_VALUE;
+ fi
+
+
+ # If caller supplied a SYSDUMP file then extract HB dump file
+ if [ -n "${FFDC_SYSDUMP_FILE}" ]; then
+ _extractHbSysDumpFile_ ${FFDC_SYSDUMP_FILE}
+ FFDC_RETURN_VALUE=$?
+ fi
+ # If call to _extractHbSysDumpFile_ not successful, then propagate error back
+ if [ "$FFDC_RETURN_VALUE" != "0" ]; then
+ return $FFDC_RETURN_VALUE;
+ fi
+
+
+ # If caller supplied a HB dump file and a FSP build tag, then retrieve HB info
+ if [ -n "${FFDC_HB_DUMP_FILE}" ] && [ -n "${FFDC_FSP_DRIVER_DIR}" ]; then
+ # Save the FSP build tag as a file for the caller's benefit
+ touch ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ # Add some info data to the file
+ echo ${FFDC_FSP_BUILD_TAG} > ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ echo ${FFDC_FSP_DRIVER} >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+ echo ${FFDC_FSP_DRIVER_DIR} >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG}
+
+ _getInfoFromHBDumpAndPost_ ${FFDC_HB_DUMP_FILE} ${FFDC_FSP_DRIVER_DIR};
+ FFDC_RETURN_VALUE=$?
+ fi
+ # If call to _getInfoFromHBDumpAndPost_ not successful, then propagate error back
+ if [ "$FFDC_RETURN_VALUE" != "0" ]; then
+ return $FFDC_RETURN_VALUE;
+ fi
+
+ echo ""
+ return 0;
+}
+
+
+###############################################################################
+# @brief Call the main starting function, ffdcExpanderMain, the beginning point
+# of this script
+#
+# @return 0 if successful, not 0 if a failure occurred
+###############################################################################
+
+ffdcExpanderMain $*
+exit $?;
+
diff --git a/src/build/debug/simics-debug-framework.py b/src/build/debug/simics-debug-framework.py
index 3176f8cba..fd90806bb 100644
--- a/src/build/debug/simics-debug-framework.py
+++ b/src/build/debug/simics-debug-framework.py
@@ -516,7 +516,7 @@ def magic_instruction_callback(user_arg, cpu, arg):
# Stop the simulation, much like a hard-coded breakpoint
SIM_break_simulation( "Simulation stopped. (hap 7007)" )
- if arg == 7008:
+ if arg == 7008: # MAGIC_RANDOM
cpu.r3 = random.randint(1, 0xffffffffffffffffL)
if arg == 7009: # MAGIC_MEMORYLEAK_FUNCTION
@@ -525,6 +525,10 @@ def magic_instruction_callback(user_arg, cpu, arg):
if arg == 7011: #MAGIC_SIMICS_CHECK
cpu.r3 = 1
print "TimeManager::cv_isSimicsRunning = true"
+ # Clear the dump flag in case it was still set from a previous boot
+ # (this call happens only 1 time and it is very early in the boot)
+ if( os.environ.has_key('HB_DUMP_COMPLETE') ):
+ del os.environ['HB_DUMP_COMPLETE']
if arg == 7012: # MAGIC_LOAD_PAYLOAD
#For P9 the Payload load is much faster due to PNOR
@@ -537,6 +541,17 @@ def magic_instruction_callback(user_arg, cpu, arg):
#SIM_run_alone( run_command, cmd )
print "MAGIC_LOAD_PAYLOAD not implemented\n";
+ if arg == 7014: # MAGIC_HB_DUMP
+ # Collect a hostboot dump
+ # (no args)
+
+ # Make sure we only do 1 dump even though every thread will TI
+ if( not os.environ.has_key('HB_DUMP_COMPLETE') ):
+ print "Generating Hostboot Dump for TI"
+ os.environ['HB_DUMP_COMPLETE']="1"
+ cmd1 = "hb-Dump quiet"
+ SIM_run_alone(run_command, cmd1 )
+
if arg == 7018: # MAGIC_BREAK_ON_ERROR
# Stop the simulation if an env var is set
if( os.environ.has_key('HB_BREAK_ON_ERROR') ):
@@ -573,6 +588,7 @@ def magic_instruction_callback(user_arg, cpu, arg):
percent_s = "%s"
dateCommand = "shell \" date +'%s > TRACE REGS: %d %d' \""%(percent_s,first_num,second_num)
SIM_run_alone(run_command, dateCommand )
+
if arg == 7022: # MAGIC_SET_LOG_LEVEL
if( not os.environ.has_key('ENABLE_HB_SIMICS_LOGS') ):
#print("Skipping Hostboot Simics Logging because ENABLE_HB_SIMICS_LOGS is not set")
@@ -745,7 +761,9 @@ def magic_instruction_callback(user_arg, cpu, arg):
#file = open("hb_trace_debug.dat", "a")
#file.write("%s\n" % (saveCommand))
#file.close()
-
+ if arg == 7056: # MAGIC_GCOV_DUMP_NOW
+ print('Gcov dumping chain from 0x%x' % (cpu.r3,))
+ SIM_run_alone(run_command, 'hb-GcovModuleUnload "address=%d"' % (cpu.r3,))
# Continuous trace: Clear these files.
rc = os.system( "rm -f hbTracMERG" )
@@ -769,4 +787,3 @@ SIM_hap_add_callback_range( "Core_Magic_Instruction", magic_instruction_callback
# Run the registration automatically whenever this script is loaded.
register_hb_debug_framework_tools()
-
diff --git a/src/build/linker/genlist.C b/src/build/linker/genlist.C
index 053f7aaa2..d89fbfaa6 100644
--- a/src/build/linker/genlist.C
+++ b/src/build/linker/genlist.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -95,6 +95,19 @@ string g_imageName;
* call binutils tools. */
char* g_crossPrefix = NULL;
+ /** Whether we should use cached objdump files (true) or redump the
+ ELF objects (false). */
+bool use_cached_objdump = false;
+
+ /** Print status messages */
+bool verbose = false;
+
+#define VFPRINTF(...) \
+ do { \
+ if (verbose) \
+ fprintf(__VA_ARGS__); \
+ } while (0)
+
int main(int argc, char** argv)
{
// Only parameter allowed is the name of the base image.
@@ -103,6 +116,16 @@ int main(int argc, char** argv)
print_usage();
}
+ verbose = getenv("BUILD_VERBOSE") != NULL;
+
+ use_cached_objdump = getenv("BUILD_FAST") != NULL;
+
+ if (use_cached_objdump) {
+ VFPRINTF(stderr, "Using cached OBJDUMP output\n");
+ } else {
+ VFPRINTF(stderr, "Using fresh OBJDUMP output\n");
+ }
+
// Get base image name from parameters.
g_imageName = argv[1];
add_image_subdir(g_imageName);
@@ -310,18 +333,42 @@ void* read_module_content(void* input)
// Assumes they are in the same subdirectory.
string module_path = g_imageName.substr(0, g_imageName.rfind('/') + 1) +
module;
+ const string objdump_path =
+ g_imageName.substr(0, g_imageName.rfind('/') + 1) + "/objdump/" + module;
+
+ FILE* pipe = NULL;
- // Create the 'objdump' command for finding all the symbols and start as
- // a sub-process.
- // -d - Disassemble sections containing code.
- // -C - Intersparse C code.
- // -S - Demangle symbol names.
- // -j .text, .data, .rodata - Only dump those 3 sections.
- string command = string(g_crossPrefix) +
- string("objdump -dCS -j .text -j .data -j .rodata ") +
- module_path;
- FILE* pipe = popen(command.c_str(), "r");
- if (NULL == pipe) return NULL;
+ VFPRINTF(stderr, "GENLIST: Processing %s\n", module_path.c_str());
+
+ if (use_cached_objdump) {
+ string bzcat_command = "bzcat " + objdump_path + ".objdump";
+ pipe = popen(bzcat_command.c_str(), "r");
+
+ if (NULL == pipe) {
+ VFPRINTF(stderr, "GENLIST: Failed to run %s, falling back to live dump\n",
+ bzcat_command.c_str());
+ }
+ }
+
+ if (pipe == NULL) {
+ // Create the 'objdump' command for finding all the symbols and start as
+ // a sub-process.
+ // -d - Disassemble sections containing code.
+ // -C - Intersparse C code.
+ // -S - Demangle symbol names.
+ // -j .text, .data, .rodata - Only dump those 3 sections.
+ string objdump_command = string(g_crossPrefix) +
+ string("objdump -dCS -j .text -j .data -j .rodata ") +
+ module_path;
+
+ pipe = popen(objdump_command.c_str(), "r");
+
+ if (NULL == pipe) {
+ fprintf(stderr, "GENLIST: Failed to open pipe for objdump: %s\n",
+ objdump_command.c_str());
+ return NULL;
+ }
+ }
// Start result string and add module start header.
string result;
diff --git a/src/build/linker/linker.C b/src/build/linker/linker.C
index a9a9d0f5e..6a8854d83 100644
--- a/src/build/linker/linker.C
+++ b/src/build/linker/linker.C
@@ -112,6 +112,8 @@ struct Section
size_t size;
bfd_byte* data;
+
+ Section() : name(""), vma_offset(0), size(0), data(NULL) {}
};
/**
@@ -123,6 +125,7 @@ struct Object
string name; //!< full path name of file
bfd* image; //!< bfd image of object
Section text; //!< text section of binary
+ Section sfpr; //!< sfpr section of binary
Section rodata; //!< rodata section of binary
Section data; //!< data section of binary
map<string, Symbol> symbols; //!< symbol map
@@ -203,7 +206,7 @@ struct Object
/**
* CTOR default
*/
- Object() : image(NULL), text(), rodata(), data(), offset(0),
+ Object() : image(NULL), text(), rodata(), data(), sfpr(), offset(0),
base_addr(0), iv_output(NULL), tls_module(-1) {}
@@ -213,7 +216,7 @@ struct Object
* @param[in] i_out : output FILE handle
*/
Object(unsigned long i_baseAddr, FILE* i_out)
- : image(NULL), text(), rodata(), data(), offset(0),
+ : image(NULL), text(), rodata(), data(), sfpr(), offset(0),
base_addr(i_baseAddr), iv_output(i_out), tls_module(-1) {}
};
@@ -439,6 +442,8 @@ int main(int argc, char** argv)
// A contained member value might be something like
// _ZZ3fooE3bar.
string sym_name = string((i->c_str())+1);
+ const char* gcovstr = "__gcov";
+ size_t gcovstrlen = strlen(gcovstr);
cout << "Checking weak symbol: " << *i << endl;
@@ -451,6 +456,12 @@ int main(int argc, char** argv)
== j->find("traceData_codeInfo"))
&& (*i != *j))
{
+ if (strncmp((*j).c_str(),
+ gcovstr,
+ gcovstrlen)==0)
+ {
+ continue;
+ }
cout << "\tDuplicate member found: " << *j << endl;
throw std::runtime_error(
string("Duplicate weak symbol with contained "
@@ -586,6 +597,11 @@ bool Object::read_object(const char* i_file)
{
s = &this->text;
}
+ else if (string(".sfpr") ==
+ bfd_get_section_name(image, image_section))
+ {
+ s = &this->sfpr;
+ }
else if (string(".rodata") ==
bfd_get_section_name(image, image_section))
{
@@ -640,6 +656,16 @@ bool Object::write_object()
cout << strerror(error) << endl;
}
+ // Output sfpr section.
+ fseek(iv_output, offset + sfpr.vma_offset, SEEK_SET);
+ if ((0 != sfpr.size) &&
+ (sfpr.size != fwrite(sfpr.data, 1, sfpr.size, iv_output)))
+ {
+ int error = errno;
+ cout << "Error writing to output for sfpr." << endl;
+ cout << strerror(error) << endl;
+ }
+
// Output RODATA section.
fseek(iv_output, offset + rodata.vma_offset, SEEK_SET);
if ((0 != rodata.size) &&
diff --git a/src/build/mkrules/cc.rules.mk b/src/build/mkrules/cc.rules.mk
index c89995f82..409166e29 100644
--- a/src/build/mkrules/cc.rules.mk
+++ b/src/build/mkrules/cc.rules.mk
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2013,2017
+# Contributors Listed Below - COPYRIGHT 2013,2019
# [+] International Business Machines Corp.
#
#
@@ -31,22 +31,71 @@ $(OBJDIR)/%.list : $(OBJDIR)/%.o
$(C2) " OBJDUMP $(notdir $<)"
$(C1)$(OBJDUMP) -rdlCS $< > $@
+# SOURCE_FILE and INCLUDE_DIRS are variables that are either absolute
+# paths to the .C file being compiled and the include directories if
+# we're building with gcov, or else they are relative paths
+# otherwise. The key thing to remember is that they are lazily
+# expanded, so they're relevant to whatever rule they're used in. We
+# don't want to always have absolute paths because of build
+# performance and because it causes the build output with
+# BUILD_VERBOSE to be larger and less readable.
+ifdef HOSTBOOT_PROFILE
+SOURCE_FILE=$(shell readlink -f $<)
+INCLUDE_DIRS=$(shell $(ROOTPATH)/src/build/tools/cflags.sh $(INCFLAGS))
+else
+SOURCE_FILE=$<
+INCLUDE_DIRS=$(INCFLAGS)
+endif
+
+# TODO RTC 215692
+# The following script is used to run the cppcheck tool when enabled. If one
+# cppcheck error is found, the make process will stop here, the error will be
+# printed out to the terminal and stored in a file .`basename $<`.cppcheck in
+# the directory where the original file is located
+ifdef DOCPPCHECK
+ CXX_PRINT=$(C2) " CPPCHECK $(notdir $<)"
+ # NoteL Error code 127 means that the command timed-out. We do not fail
+ # for timeouts
+ CXX_CPPCHECK_COMMAND=$(C1) set -o pipefail && cd `dirname $<` && timeout 2m $(CXX_CHECK) `basename $<` 2>&1 | tee .`basename $<`.cppcheck; exit_code=$$? ; \
+ if [ "$$exit_code" -ne 1 ]; then \
+ rm -f .`basename $<`.cppcheck; \
+ if [ "$$exit_code" -eq 127 ]; then \
+ exit_code=0; \
+ fi; \
+ fi; exit "$$exit_code"
+ C_CPPCHECK_COMMAND=$(C1) set -o pipefail && cd `dirname $<` && timeout 2m $(C_CHECK) `basename $<` 2>&1 | tee .`basename $<`.cppcheck; exit_code=$$? ; \
+ if [ "$$exit_code" -ne 1 ]; then \
+ rm -f .`basename $<`.cppcheck; \
+ if [ "$$exit_code" -eq 127 ]; then \
+ exit_code=0; \
+ fi; \
+ fi; exit "$$exit_code"
+else
+ CXX_PRINT=
+ CXX_CPPCHECK_COMMAND=
+ C_CPPCHECK_COMMAND=
+endif
+
$(OBJDIR)/%.o : %.C
@mkdir -p $(OBJDIR)
$(C2) " CXX $(notdir $<)"
- $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $< \
- -o $@.trace $(INCFLAGS) -iquote .
+ $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $(SOURCE_FILE) \
+ -o $@.trace $(INCLUDE_DIRS) -iquote .
$(C1)$(TRACE_HASHER) $@ $(TRACE_FLAGS)
@rm $@.trace
+ $(CXX_PRINT)
+ $(CXX_CPPCHECK_COMMAND)
# Compiling *.cc files
$(OBJDIR)/%.o : %.cc
@mkdir -p $(OBJDIR)
$(C2) " CXX $(notdir $<)"
- $(C1)$(CXX) -c $(CXXFLAGS) $< -o $@.trace $(INCFLAGS) -iquote .
+ $(C1)$(CXX) -c $(CXXFLAGS) $(SOURCE_FILE) -o $@.trace \
+ $(INCLUDE_DIRS) -iquote .
$(C1)$(TRACE_HASHER) $@ $(TRACE_FLAGS)
@rm $@.trace
-
+ $(CXX_PRINT)
+ $(CXX_CPPCHECK_COMMAND)
$(OBJDIR)/%.o : %.c
@mkdir -p $(OBJDIR)
@@ -54,12 +103,16 @@ $(OBJDIR)/%.o : %.c
# CC_OVERRIDE is set in the makefile of the component
ifndef CC_OVERRIDE
$(C2) " CC $(notdir $<)"
- $(C1)$(CC) -c $(call FLAGS_FILTER, $(CFLAGS), $<) $< \
- -o $@.trace $(INCFLAGS) -iquote .
+ $(C1)$(CC) -c $(call FLAGS_FILTER, $(CFLAGS), $<) $(SOURCE_FILE) \
+ -o $@.trace $(INCLUDE_DIRS) -iquote .
+ $(CXX_PRINT)
+ $(C_CPPCHECK_COMMAND)
else
$(C2) " CXX $(notdir $<)"
- $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $< \
- -o $@.trace $(INCFLAGS) -iquote .
+ $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $(SOURCE_FILE) \
+ -o $@.trace $(INCLUDE_DIRS) -iquote .
+ $(CXX_PRINT)
+ $(CXX_CPPCHECK_COMMAND)
endif
$(C1)$(TRACE_HASHER) $@ $(TRACE_FLAGS)
@rm $@.trace
diff --git a/src/build/mkrules/cflags.env.mk b/src/build/mkrules/cflags.env.mk
index 04ff6fedd..cb25561f8 100644
--- a/src/build/mkrules/cflags.env.mk
+++ b/src/build/mkrules/cflags.env.mk
@@ -28,7 +28,7 @@
# Description:
# Configuration of the compiler, linker, etc. flags.
-OPT_LEVEL ?= -O3
+OPT_LEVEL ?= -Os
ifdef MODULE
COMMONFLAGS += -fPIC -Bsymbolic -Bsymbolic-functions
@@ -38,6 +38,8 @@ CFLAGS += -DNO_INITIALIZER_LIST
CFLAGS += -D__FAPI
endif
+# Force all files to pull in the CONFIG_ variables
+CFLAGS += -include config.h
COMMONFLAGS += $(OPT_LEVEL) -nostdlib
CFLAGS += $(COMMONFLAGS) -mcpu=power7 -nostdinc -g -mno-vsx -mno-altivec\
diff --git a/src/build/mkrules/dist.targets.mk b/src/build/mkrules/dist.targets.mk
index 0d592b838..c925f25b5 100755
--- a/src/build/mkrules/dist.targets.mk
+++ b/src/build/mkrules/dist.targets.mk
@@ -304,6 +304,9 @@ fsp.tar_CONTENTS = \
src/build/buildpnor/genfakeheader.pl \
src/build/buildpnor/genPnorImages.pl \
src/build/buildpnor/buildUcdFlashImages.pl \
+ src/build/buildpnor/buildBpmFlashImages.pl \
+ src/build/buildpnor/bpm-utils/insertBpmFwCrc.py \
+ src/build/buildpnor/bpm-utils/imageCrc.c \
src/build/buildpnor/PnorUtils.pm \
src/build/buildpnor/imprintHwKeyHash \
src/build/buildpnor/pkgOcmbFw.pl \
@@ -357,7 +360,8 @@ fsp.tar_CONTENTS = \
src/include/usr/hwas/common/hwasCallout.H:hwas/ \
src/include/usr/devicefw/driverif.H:devicefw/ \
src/include/usr/devicefw/userif.H:devicefw/ \
- obj/genfiles/plugins/errludattribute.H:plugins/ \
+ obj/genfiles/plugins/errludattributeP_gen.H:plugins/ \
+ src/usr/errl/plugins/errludattributeP.H:plugins/ \
obj/genfiles/plugins/errludtarget.H:plugins/ \
$(addsuffix :plugins/,\
$(call ROOTPATH_WILDCARD,obj/genfiles/plugins/hbfwSrcParse*.C)) \
diff --git a/src/build/mkrules/gcov.env.mk b/src/build/mkrules/gcov.env.mk
index 8ddcd3ef6..edce52a24 100644
--- a/src/build/mkrules/gcov.env.mk
+++ b/src/build/mkrules/gcov.env.mk
@@ -5,7 +5,9 @@
#
# OpenPOWER HostBoot Project
#
-# COPYRIGHT International Business Machines Corp. 2013,2014
+# Contributors Listed Below - COPYRIGHT 2013,2019
+# [+] International Business Machines Corp.
+#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -26,21 +28,44 @@
# Configuration of the GCOV settings.
GCOVDIR = $(ROOTPATH)/obj/gcov
+vpath %.C $(ROOTPATH)/src/sys/prof
ifdef MODULE
-GCOVNAME = $(MODULE).lcov
+
+# Don't profile HBRT modules to keep size down
+ifdef HOSTBOOT_RUNTIME
+HOSTBOOT_PROFILE=
+endif
+
+## We don't want certain modules to be profiled (HBB, HBRT).
+
+# This is replacing spaces with colons so that we can get an exact
+# match on the module name in the list of unprofilable modules with
+# findstring, which otherwise would find matches on "partial"
+# substrings (i.e. we don't want to deprofile module ABC just because
+# module ABCD is blacklisted, so we create a blacklist of modules
+# separated by colons and search for :ABC:).
+null :=
+MODULE_PROFILE_BLACKLIST:=:$(subst ${null} ${null},:,$(BASE_MODULES_GCOV_BLACKLIST) $(RUNTIME_MODULES_GCOV_BLACKLIST)):
+
+ifneq (,$(findstring :$(MODULE):,$(MODULE_PROFILE_BLACKLIST)))
+HOSTBOOT_PROFILE=
+endif
+
+GCOVNAME := $(MODULE).lcov
+
ifndef TESTS
ifdef HOSTBOOT_PROFILE
-vpath %.C $(ROOTPATH)/src/sys/prof
OBJS := gcov.o $(OBJS)
endif
endif
else
-GCOVNAME = $(notdir $(shell pwd)).lcov
+GCOVNAME := $(notdir $(shell pwd)).lcov
endif
-## Disable coverage on test cases, any directory that sets
-## HOSTBOOT_PROFILE_NO_INSTRUMENT or any file that has 'gcov' in the name.
+## Disable coverage on test cases or any directory that sets
+## HOSTBOOT_PROFILE_NO_INSTRUMENT
+
ifndef TESTS
ifdef HOSTBOOT_PROFILE
ifndef HOSTBOOT_PROFILE_NO_INSTRUMENT
@@ -59,5 +84,16 @@ endif
## Reduce the optimization level when profiling is enabled to ensure the
## base image fits in 512k still.
ifdef HOSTBOOT_PROFILE
-OPT_LEVEL = -Os
+# We're not doing this right now because it causes linker errors in
+# various parts of hostboot with or without gcov (i.e. functions that
+# the code relies on being inlined are not; some const statics that
+# aren't defined in a compilation unit have linker references, etc.)
+# and it also causes the image to be generated incorrectly (symbol
+# names are wrong, calls to functions named things like __savegpr_rXX
+# are emitted but the functions themselves aren't and so you end up
+# jumping into an area of zeroes, ...). We should come back to this
+# later and fix, we might be able to profile more of hostboot with the
+# space savings that -Os could give.
+
+#OPT_LEVEL = -Os
endif
diff --git a/src/build/mkrules/hbfw/img/makefile b/src/build/mkrules/hbfw/img/makefile
index 269a52ce5..114cb6384 100755
--- a/src/build/mkrules/hbfw/img/makefile
+++ b/src/build/mkrules/hbfw/img/makefile
@@ -65,6 +65,7 @@ SBEI_OBJPATH = ${HBFW_OBJPATH:S/hbfw\/img/sbei\/sbfw\/img/g}
ENGD_WOFPATH = ${HBFW_OBJPATH:S/hbfw\/img/engd\/wofdata/g}
ENGD_MEMDPATH = ${HBFW_OBJPATH:S/hbfw\/img/engd\/memd/g}
HBFW_SIMPATH = ${HBFW_OBJPATH:S/img/simics/g}
+EDITED_LAYOUT_PATH = ${DUMMY:!pwd!}
#################################################
# Copy Hostboot binary images to obj dir to be grabbed
# during build flash pass and consumption by HWSV.
@@ -113,7 +114,6 @@ TESTRO_FINAL_IMG = TESTRO.bin
TESTLOAD_FINAL_IMG = TESTLOAD.bin
HBEL_FINAL_IMG = HBEL.bin
GUARD_FINAL_IMG = GUARD.bin
-GLOBAL_FINAL_IMG = GLOBAL.bin
DJVPD_FINAL_IMG = DJVPD.bin
MVPD_FINAL_IMG = MVPD.bin
CVPD_FINAL_IMG = CVPD.bin
@@ -126,7 +126,7 @@ EECACHE_FINAL_IMG = EECACHE.bin
OCMBFW_FINAL_IMG = OCMBFW.bin
FINAL_OUTPUT_IMAGES = ${HBBL_FINAL_IMG} ${HBB_FINAL_IMG} ${HBI_FINAL_IMG} \
${HBRT_FINAL_IMG} ${TEST_FINAL_IMG} ${TESTRO_FINAL_IMG} \
- ${HBEL_FINAL_IMG} ${GUARD_FINAL_IMG} ${GLOBAL_FINAL_IMG} \
+ ${HBEL_FINAL_IMG} ${GUARD_FINAL_IMG} \
${DJVPD_FINAL_IMG} ${MVPD_FINAL_IMG} ${CVPD_FINAL_IMG} \
${PAYLOAD_FINAL_IMG} ${RINGOVD_FINAL_IMG} ${SBKT_FINAL_IMG} \
${FIRDATA_FINAL_IMG} ${MEMD_FINAL_IMG} ${EECACHE_FINAL_IMG} \
@@ -214,26 +214,28 @@ BUILD_TYPE_PARAMS = --build-type fspbuild
.endif
# Decide which images to use for each PNOR layout
-GEN_COMMON_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},HBEL=EMPTY,GUARD=EMPTY,GLOBAL=EMPTY,MVPD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY
+GEN_COMMON_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},HBEL=EMPTY,GUARD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY
GEN_STANDALONE_BIN_FILES = ${GEN_COMMON_BIN_FILES},TEST=EMPTY,TESTRO=EMPTY,TESTLOAD=EMPTY,PAYLOAD=EMPTY,FIRDATA=EMPTY
.if (${FAKEPNOR} == "")
# Parameters passed into GEN_PNOR_IMAGE_SCRIPT.
.if (${PNOR_LAYOUT_SELECTED} == "STANDALONE")
- GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY
+ GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY,MVPD=EMPTY
.elif(${PNOR_LAYOUT_SELECTED} == "AXONE")
- GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},EECACHE=EMPTY,MEMD=${${ZZ_MEMD_IMG}:P},OCMBFW=${${OCMBFW_IMG}:P}
+ GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},EECACHE=EMPTY,OCMBFW=${${OCMBFW_IMG}:P}
.else
- GEN_DEFAULT_BIN_FILES = ${GEN_COMMON_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY
+ GEN_DEFAULT_BIN_FILES = ${GEN_COMMON_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY,MVPD=EMPTY
.endif
DEFAULT_PARAMS = --build-all --emit-eccless ${TARGET_TEST:b--test} ${HB_STANDALONE:b--hb-standalone} \
${CONFIG_SECUREBOOT:b--secureboot} --systemBinFiles ${GEN_DEFAULT_BIN_FILES} \
--pnorLayout ${PNOR_LAYOUT} ${KEY_TRANSITION_PARAMS} ${CORRUPT_PARAMS} \
- --hwKeyHashFile ${IMPRINT_HW_KEY_HASH}
+ --hwKeyHashFile ${IMPRINT_HW_KEY_HASH} \
+ --editedLayoutLocation ${EDITED_LAYOUT_PATH}
.else
PNOR_LAYOUT = ${pnorLayoutFake.xml:P}
# Parameters passed into GEN_PNOR_IMAGE_SCRIPT.
GEN_DEFAULT_BIN_FILES = HBI=${HBI_IMG},HBEL=EMPTY,MVPD=${${VPO_FAKE_MVPD}:P},DJVPD=${${VPO_FAKE_DJVPD}:P},FIRDATA=EMPTY,MEMD=EMPTY
- DEFAULT_PARAMS = --systemBinFiles ${GEN_DEFAULT_BIN_FILES} --pnorLayout ${PNOR_LAYOUT}
+ DEFAULT_PARAMS = --systemBinFiles ${GEN_DEFAULT_BIN_FILES} --pnorLayout ${PNOR_LAYOUT} \
+ --editedLayoutLocation ${EDITED_LAYOUT_PATH}
.endif
# rule to update hostboot image tags for custom CFM image, only enabled
@@ -375,7 +377,6 @@ AXONE_HCODE_IMG = ${ENGD_SRCPATH:Fp9a.hw_ref_image.bin}
CUMULUS_CENHWIMG_IMG = ${ENGD_SRCPATH:Fcen.hw_ref_image.bin}
NIMBUS_CENHWIMG_IMG = cen.hw_ref_image.bin.fake
-AXONE_CENHWIMG_IMG = cen.hw_ref_image.bin.fake
NIMBUS_OCC_IMG = ${bb}/images/ppc/lab/fs/p9le/rootfs/opt/extucode/81e00430.lid
CUMULUS_OCC_IMG = ${bb}/images/ppc/lab/fs/p9le/rootfs/opt/extucode/81e00430.lid
AXONE_OCC_IMG = ${bb}/images/ppc/lab/fs/p9le/rootfs/opt/extucode/81e00430.lid
@@ -389,6 +390,8 @@ ZEPPELIN_MEMD_IMG = ${ENGD_MEMDPATH:Fzeppelin_memd_output.dat}
FLEETWOOD_MEMD_IMG = ${ENGD_MEMDPATH:Ffleetwood_memd_output.dat}
ZZ_HBD_IMG = ${HBFW_TARGPATH:FZZ_hb_targeting.bin}
ZZ2U_HBD_IMG = ${HBFW_TARGPATH:FZZ-2U_hb_targeting.bin}
+ZZGEN4_HBD_IMG = ${HBFW_TARGPATH:FZZ-GEN4_hb_targeting.bin}
+ZZ2UGEN4_HBD_IMG = ${HBFW_TARGPATH:FZZ-2U-GEN4_hb_targeting.bin}
ZEPPELIN_HBD_IMG = ${HBFW_TARGPATH:FZEPPELIN_hb_targeting.bin}
# Create list of images for each node (in node order)
# genPnorImages will handle multiple HBD=binfile pairs
@@ -409,7 +412,6 @@ CUMULUS_HCODE_FINAL_IMG = CUMULUS.HCODE.bin
AXONE_HCODE_FINAL_IMG = AXONE.HCODE.bin
CUMULUS_CENHWIMG_FINAL_IMG = CUMULUS.CENHWIMG.bin
NIMBUS_CENHWIMG_FINAL_IMG = NIMBUS.CENHWIMG.bin
-AXONE_CENHWIMG_FINAL_IMG = AXONE.CENHWIMG.bin
NIMBUS_SBE_FINAL_IMG = NIMBUS.SBE.bin
CUMULUS_SBE_FINAL_IMG = CUMULUS.SBE.bin
AXONE_SBE_FINAL_IMG = AXONE.SBE.bin
@@ -428,7 +430,8 @@ ZZ_HBD_FINAL_IMG = ZZ.HBD.bin
ZEPPELIN_HBD_FINAL_IMG = ZEPPELIN.HBD.bin
FLEETWOOD_HBD_FINAL_IMGS = FLEETWOOD.HBD_NODE_0.bin,FLEETWOOD.HBD_NODE_1.bin,FLEETWOOD.HBD_NODE_2.bin,FLEETWOOD.HBD_NODE_3.bin,FLEETWOOD_MST.HBD_NODE_0.bin,FLEETWOOD_2N.HBD_NODE_0.bin,FLEETWOOD_2N.HBD_NODE_1.bin,FLEETWOOD_2N.HBD_NODE_2.bin,FLEETWOOD_2N.HBD_NODE_3.bin
ZZ2U_HBD_FINAL_IMG = ZZ-2U.HBD.bin
-
+ZZGEN4_HBD_FINAL_IMG = ZZ-GEN4.HBD.bin
+ZZ2UGEN4_HBD_FINAL_IMG = ZZ-2U-GEN4.HBD.bin
# Decide which PNOR to build
@@ -438,18 +441,20 @@ ZZ2U_HBD_FINAL_IMG = ZZ-2U.HBD.bin
GEN_NIMBUS_BIN_FILES = NIMBUS:SBE=${${NIMBUS_SBE_IMG}:P},HCODE=${${NIMBUS_HCODE_IMG}:P},OCC=${${NIMBUS_OCC_IMG}:P},HBD=${${NIMBUS_HBD_IMG}:P},CENHWIMG=${NIMBUS_CENHWIMG_IMG}
GEN_CUMULUS_BIN_FILES = CUMULUS:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P}
GEN_CUMULUS_CDIMM_BIN_FILES = CUMULUS_CDIMM:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_CDIMM_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P}
- GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P},CENHWIMG=${AXONE_CENHWIMG_IMG}
+ GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P}
.else
GEN_NIMBUS_BIN_FILES = NIMBUS:SBE=${${NIMBUS_SBE_IMG}:P},HCODE=${${NIMBUS_HCODE_IMG}:P},OCC=${${NIMBUS_OCC_IMG}:P},HBD=${${NIMBUS_HBD_IMG}:P},CENHWIMG=${NIMBUS_CENHWIMG_IMG}
GEN_CUMULUS_BIN_FILES = CUMULUS:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P}
GEN_CUMULUS_CDIMM_BIN_FILES = CUMULUS_CDIMM:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_CDIMM_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P}
- GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P},CENHWIMG=${AXONE_CENHWIMG_IMG}
+ GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P}
.endif
GEN_ZZ_BIN_FILES = ZZ:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZ_HBD_IMG}:P}
GEN_ZEPPELIN_BIN_FILES = ZEPPELIN:WOFDATA=${${ZEPPELIN_WOFDATA_IMG}:P},MEMD=${${ZEPPELIN_MEMD_IMG}:P},HBD=${${ZEPPELIN_HBD_IMG}:P}
GEN_FLEETWOOD_BIN_FILES = FLEETWOOD:WOFDATA=${${FLEETWOOD_WOFDATA_IMG}:P},MEMD=${${FLEETWOOD_MEMD_IMG}:P},${FLEETWOOD_HBD_IMGS}
GEN_ZZ2U_BIN_FILES = ZZ-2U:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZ2U_HBD_IMG}:P}
+ GEN_ZZGEN4_BIN_FILES = ZZ-GEN4:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZGEN4_HBD_IMG}:P}
+ GEN_ZZ2UGEN4_BIN_FILES = ZZ-2U-GEN4:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZ2UGEN4_HBD_IMG}:P}
SYSTEM_SPECIFIC_PARAMS = --install-all --emit-eccless ${TARGET_TEST:b--test} ${CONFIG_SECUREBOOT:b--secureboot} \
--pnorLayout ${PNOR_LAYOUT} ${CORRUPT_PARAMS} ${HB_STANDALONE:b--hb-standalone} \
@@ -461,18 +466,22 @@ ZZ2U_HBD_FINAL_IMG = ZZ-2U.HBD.bin
--systemBinFiles ${GEN_ZEPPELIN_BIN_FILES} \
--systemBinFiles ${GEN_FLEETWOOD_BIN_FILES} \
--systemBinFiles ${GEN_ZZ2U_BIN_FILES} \
- --hwKeyHashFile ${IMPRINT_HW_KEY_HASH}
+ --systemBinFiles ${GEN_ZZGEN4_BIN_FILES} \
+ --systemBinFiles ${GEN_ZZ2UGEN4_BIN_FILES} \
+ --hwKeyHashFile ${IMPRINT_HW_KEY_HASH} \
+ --editedLayoutLocation ${EDITED_LAYOUT_PATH}
.else
# Parameters passed into GEN_PNOR_IMAGE_SCRIPT.
GEN_NIMBUS_BIN_FILES = NIMBUS:HCODE=${${NIMBUS_HCODE_IMG}:P},HBD=${${NIMBUS_VPO_HBD_IMG}:P},CENHWIMG=EMPTY
GEN_CUMULUS_BIN_FILES = CUMULUS:HCODE=${${CUMULUS_HCODE_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P}
GEN_CUMULUS_CDIMM_BIN_FILES = CUMULUS:HCODE=${${CUMULUS_HCODE_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P}
- GEN_AXONE_BIN_FILES = AXONE:HCODE=${${AXONE_HCODE_IMG}:P},HBD=${${AXONE_VPO_HBD_IMG}:P},CENHWIMG=EMPTY
+ GEN_AXONE_BIN_FILES = AXONE:HCODE=${${AXONE_HCODE_IMG}:P},HBD=${${AXONE_VPO_HBD_IMG}:P}
SYSTEM_SPECIFIC_PARAMS = --pnorLayout ${PNOR_LAYOUT} \
--systemBinFiles ${GEN_NIMBUS_BIN_FILES} \
--systemBinFiles ${GEN_CUMULUS_BIN_FILES} \
--systemBinFiles ${GEN_AXONE_BIN_FILES} \
- --systemBinFiles ${GEN_CUMULUS_CDIMM_BIN_FILES}
+ --systemBinFiles ${GEN_CUMULUS_CDIMM_BIN_FILES} \
+ --editedLayoutLocation ${EDITED_LAYOUT_PATH}
.endif
gen_system_specific_images_bypass_cache : dump-secureboot-config
@@ -493,14 +502,14 @@ gen_system_specific_images: build_sbe_partitions .PMAKE
.if (${PNOR_LAYOUT_SELECTED} == "FSP")
- HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG}
+ HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG}
.else
- HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},TEST=${TEST_FINAL_IMG},TESTRO=${TESTRO_FINAL_IMG},TESTLOAD=${TESTLOAD_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},PAYLOAD=${PAYLOAD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG}
+ HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},TEST=${TEST_FINAL_IMG},TESTRO=${TESTRO_FINAL_IMG},TESTLOAD=${TESTLOAD_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},PAYLOAD=${PAYLOAD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG}
.endif
-NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG},MEMD=${ZZ_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG}
-CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${ZEPPELIN_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG}
-CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG}
-AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},SBE=${AXONE_SBE_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG},OCC=${AXONE_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${AXONE_CENHWIMG_FINAL_IMG},EECACHE=${EECACHE_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG},MEMD=${MEMD_FINAL_IMG},OCMBFW=${OCMBFW_FINAL_IMG}
+NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG},MEMD=${ZZ_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG}
+CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${ZEPPELIN_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG}
+CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG}
+AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},SBE=${AXONE_SBE_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG},OCC=${AXONE_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},EECACHE=${EECACHE_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG},OCMBFW=${OCMBFW_FINAL_IMG}
.if (${PNOR_LAYOUT_SELECTED} == "AXONE")
@@ -525,7 +534,7 @@ PNOR_IMG_INFO = \
NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG}
CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG}
CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG}
- AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG},CENHWIMG=${AXONE_CENHWIMG_FINAL_IMG}
+ AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG}
PNOR_IMG_INFO = \
${FAKEPNOR}:${PNOR_LAYOUT}:${NIMBUS_SECT}:${CUMULUS_SECT}:${CUMULUS_CDIMM_SECT},${HOSTBOOT_DEFAULT_SECTIONS},${AXONE_SECT} \
${FIPS_PNOR_INFO}
@@ -562,7 +571,8 @@ ${IMAGE_TARGET}: ${IMAGE_LAYOUT} ${IMAGE_BINS} ${PNOR_BUILD_SCRIPT}
${FAKEPNOR} == ${IMAGE_TARGET})
${PNOR_BUILD_SCRIPT} --pnorOutBin ${IMAGE_TARGET} \
${TARGET_TEST:b--test} --pnorLayout ${IMAGE_LAYOUT} \
- ${IMAGE_BIN_OPTION} --fpartCmd "fpart" --fcpCmd "fcp"
+ ${IMAGE_BIN_OPTION} --fpartCmd "fpart" --fcpCmd "fcp" \
+ --editedLayoutLocation ${EDITED_LAYOUT_PATH}
.endif
.endif
diff --git a/src/build/mkrules/images.rules.mk b/src/build/mkrules/images.rules.mk
index 2a611b030..c6b863d89 100644
--- a/src/build/mkrules/images.rules.mk
+++ b/src/build/mkrules/images.rules.mk
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2013,2017
+# Contributors Listed Below - COPYRIGHT 2013,2019
# [+] International Business Machines Corp.
#
#
@@ -27,14 +27,49 @@
# Description:
# Rules for linking the Hostboot binary images using the custom linker.
+# Folder to store *.objdump files in
+OBJDUMP_FOLDER := $(IMGDIR)/objdump
+
+# Clean up after ourselves
+clean: clean-objdump
+
+.PHONY: clean-objdump
+clean-objdump:
+ $(C2) " MAKE objdump CLEAN"
+ $(C1)rm -rf $(OBJDUMP_FOLDER)
+
ifdef IMGS
_IMGS = $(addprefix $(IMGDIR)/, $(IMGS))
IMAGES += $(addsuffix .bin, $(_IMGS)) $(addsuffix .elf, $(_IMGS))
+ifdef BUILD_FAST
+OBJDUMP_MODULES := $(sort $(foreach img, $(IMGS), $($(img)_MODULES) $($(img)_EXTENDED_MODULES)))
+
+OBJDUMP_BIN_TARGETS := $(addsuffix .elf.objdump, $(IMGS))
+OBJDUMP_LIB_TARGETS := $(addsuffix .so.objdump, $(OBJDUMP_MODULES))
+
+OBJDUMP_TARGETS := $(addprefix $(OBJDUMP_FOLDER)/lib, $(OBJDUMP_LIB_TARGETS))
+OBJDUMP_TARGETS += $(addprefix $(OBJDUMP_FOLDER)/, $(OBJDUMP_BIN_TARGETS))
+
+# Tell make not to delete our objdumps
+.SECONDARY: $(OBJDUMP_TARGETS)
+endif
+
IMAGE_PASS_POST += $(addsuffix .list.bz2, $(_IMGS)) $(addsuffix .syms, $(_IMGS))
CLEAN_TARGETS += $(addsuffix .list.bz2, $(_IMGS)) $(addsuffix .syms, $(_IMGS))
CLEAN_TARGETS += $(addsuffix .lnkout.bz2, $(addprefix $(IMGDIR)/., $(IMGS)))
+$(OBJDUMP_FOLDER):
+ mkdir -p $@
+
+$(OBJDUMP_FOLDER)/%.so.objdump: $(IMGDIR)/%.so $(OBJDUMP_FOLDER)
+ $(C2) " OBJDUMP $(notdir $*)"
+ $(C1)$(OBJDUMP) -dCS -j .text -j .data -j .rodata $< | bzip2 >$@
+
+$(OBJDUMP_FOLDER)/%.elf.objdump: $(IMGDIR)/%.elf $(OBJDUMP_FOLDER)
+ $(C2) " OBJDUMP $(notdir $*)"
+ $(C1)$(OBJDUMP) -dCS -j .text -j .data -j .rodata $< | bzip2 >$@
+
define ELF_template
$$(IMGDIR)/$(1).elf: $$(addprefix $$(OBJDIR)/, $$($(1)_OBJECTS)) \
$$(ROOTPATH)/src/$$($(1)_LDFILE)
@@ -63,7 +98,7 @@ $(IMGDIR)/%.bin: $(IMGDIR)/%.elf \
| bzip2 -zc > $(IMGDIR)/.$*.lnkout.bz2'
$(C1)$(ROOTPATH)/src/build/tools/addimgid $@ $<
-$(IMGDIR)/%.list.bz2 $(IMGDIR)/%.syms: $(IMGDIR)/%.bin
+$(IMGDIR)/%.list.bz2 $(IMGDIR)/%.syms: $(IMGDIR)/%.bin $(OBJDUMP_TARGETS)
$(C2) " GENLIST $(notdir $*)"
$(C1)(cd $(ROOTPATH)&& \
src/build/linker/gensyms $*.bin \
diff --git a/src/build/simics/standalone.simics b/src/build/simics/standalone.simics
index 39a382303..c785dfc44 100755
--- a/src/build/simics/standalone.simics
+++ b/src/build/simics/standalone.simics
@@ -9,10 +9,17 @@ if not defined hb_skip_vpd_preload {$hb_skip_vpd_preload = 0}
if ($hb_mode == 0) { # Axone and beyond
- # this number is no longer provided we have to look it up
- $num_dimms = (dec (list-length((get-master-procs)[0].get-dimms)))
+ # There is no VPD cache on Axone
+ $hb_skip_vpd_preload = 1;
}
+# Load up the pnor parsing function
+try {
+ add-directory $hb_pnor_dir
+ run-python-file (lookup-file simpnor.py)
+ echo "Loaded simpnor.py"
+} except { "No simpnor.py found, using hardcoding PNOR offsets." }
+
# Preload VPD in PNOR unless told not to
if ($hb_skip_vpd_preload == 0) {
@@ -24,8 +31,7 @@ if ($hb_skip_vpd_preload == 0) {
$procChipType=(get-object-list p9_proc)[0]->chip_type
python "os.environ['HB_PROC_CHIP_TYPE'] = \""+$procChipType+"\""
} else {
- $procChipType=($hb_masterproc)->chip_type
- python "os.environ['HB_PROC_CHIP_TYPE'] = \""+$procChipType+"\""
+ python "os.environ['HB_PROC_CHIP_TYPE'] = \""+$proc_chip_type+"\""
}
@@ -54,6 +60,36 @@ if ($hb_skip_vpd_preload == 0) {
} except { echo "ERROR: Failed to preload VPD into PNOR." }
}
+if ($hb_mode == 0) {
+ $eccPreload = (lookup-file "%simics%/eecache_prebuilt.bin.ecc")
+ # NOTE must change offset if PNOR layout changes EECACHE offsets
+ echo " - Loading prebuilt EECACHE "+$eccPreload+" at 0x2C000 in PNOR"
+ ($hb_pnor).load-file $eccPreload 0x2C000
+}
+
+# Look for attribute overrides to load
+try {
+ $attr_tmp = (lookup-file "ATTR_TMP")
+ try {
+ @simenv.attr_tmp_addr = hb_get_pnor_offset("ATTR_TMP")
+ } except {
+ $attr_tmp_addr = 0x000B2000
+ }
+ echo " - Loading ATTR_TMP "+$attr_tmp+" at "+$attr_tmp_addr+" in PNOR"
+ ($hb_pnor).load-file $attr_tmp $attr_tmp_addr
+} except { echo "No attribute overrides found." }
+
+# Look for a guard file to load
+try {
+ $guard = (lookup-file "GUARD")
+ try {
+ @simenv.guard_addr = hb_get_pnor_offset("GUARD")
+ } except {
+ $guard_addr = 0x000AC000
+ }
+ echo " - Loading GUARD "+$guard+" at "+$guard_addr+" in PNOR"
+ ($hb_pnor).load-file $guard $guard_addr
+} except { echo "No gard records found." }
# Turn on all processor cec-chips
if ($hb_mode == 1) {
@@ -108,3 +144,51 @@ if ($hb_mode == 1) {
($hb_masterproc_cecchip).invoke parallel_store FSIMBOX 0x01 "80000000" 32
($hb_masterproc_cecchip).invoke parallel_store FSIMBOX 0x08 "00080000" 32
}
+
+###############################
+#Initialize Explorer Registers
+###############################
+if ($hb_mode == 0) { #Only do this on Axone and later models that have Explorer chip
+
+ # IDEC register consumed by Hostboot
+ # UCHIP(0x2134)=0x110600D2
+ # TODO RTC: 215621 Remove workarounds after simics gets updated
+ set-class-attr ocmb mscc_regs_xcbi_chip_info 0x110600D2
+
+ # Loop over all explorer chips
+ foreach $obj in (get-object-list ocmb -all){
+
+ # RAM1 image ID consumed by Hostboot
+ # UCHIP(0x2200)=0x00000000
+ $obj->mscc_regs_xcbi_ram1[0] = 0x00000000
+
+ # RAM1 hash value registers consumed by Hostboot
+ # This matches the hash of zero-filled 4k file.
+ $obj->mscc_regs_xcbi_ram1[1] = 0x2D23913D
+ $obj->mscc_regs_xcbi_ram1[2] = 0x3759EF01
+ $obj->mscc_regs_xcbi_ram1[3] = 0x704A86B4
+ $obj->mscc_regs_xcbi_ram1[4] = 0xBEE3AC8A
+ $obj->mscc_regs_xcbi_ram1[5] = 0x29002313
+ $obj->mscc_regs_xcbi_ram1[6] = 0xECC98A74
+ $obj->mscc_regs_xcbi_ram1[7] = 0x24425A78
+ $obj->mscc_regs_xcbi_ram1[8] = 0x170F2195
+ $obj->mscc_regs_xcbi_ram1[9] = 0x77822FD7
+ $obj->mscc_regs_xcbi_ram1[10] = 0x7E4AE963
+ $obj->mscc_regs_xcbi_ram1[11] = 0x13547696
+ $obj->mscc_regs_xcbi_ram1[12] = 0xAD7D5949
+ $obj->mscc_regs_xcbi_ram1[13] = 0xB58E12D5
+ $obj->mscc_regs_xcbi_ram1[14] = 0x063EF2EE
+ $obj->mscc_regs_xcbi_ram1[15] = 0x063B5957
+ $obj->mscc_regs_xcbi_ram1[16] = 0x40A3A12D
+
+ # Allow for testing MMIO HW failures
+ # Forces write access to TRACE_TRDATA_CONFIG_0 to fail
+ # in src/usr/mmio/test/mmiotest.H
+ # NOTE: address is left shifted 3 and has MMIO
+ # offset (0x100000000) added.
+ $obj->mmio_regs_mmioerr = 0x0000000140082018
+
+ }
+}
+
+
diff --git a/src/build/simics/startup.simics b/src/build/simics/startup.simics
index a6534be01..440e9562b 100755
--- a/src/build/simics/startup.simics
+++ b/src/build/simics/startup.simics
@@ -48,7 +48,8 @@ if ($hb_mode == 1) {
}
}else{
- $hb_machine = "AXONE"
+ # simics now provides us the chip type (starting w/ p9a )
+ $hb_machine = $proc_chip_type
}
python "os.environ['HB_MACHINE'] = \""+$hb_machine+"\""
@@ -98,9 +99,9 @@ if ($hb_mode == 1) {
($cc).seeprom3.seeprom3_image.set 0x3FED9 0x5A5A5A5A 8 -l
}
} else {
- foreach $cc in (get-object-list proc_hb_standalone) {
- ($cc).seeprom1_image.set 0x3FED9 0x5A5A5A5A 8 -l
- ($cc).seeprom3_image.set 0x3FED9 0x5A5A5A5A 8 -l
+ foreach $proc in (get-all-procs) {
+ ($proc.get-seeprom 1).set 0x3FED9 0x5A5A5A5A 8 -l
+ ($proc.get-seeprom 3).set 0x3FED9 0x5A5A5A5A 8 -l
}
}
@@ -112,6 +113,7 @@ try {
run-python-file (lookup-file hbfw/hb-simdebug.py)
} except { echo "ERROR: Failed to load Hostboot debug tools (hb-simdebug.py)" }
+
# Determine security state
$hw_security=(shell "echo $SECURITY_HW_POLICY")
if($hw_security == "") {
@@ -133,13 +135,27 @@ if($hw_security == "1") {
$jumperApplied=FALSE
}
-# Load jumper state to each processor
-foreach $procX in (get-object-list p9_proc) {
-
+if ($hb_machine == "p9a") {
# Set logical jumper state in SIMICS based on HW policy
# "TRUE"=jumper applied(security disabled, default)
# "FALSE"=jumper removed(security enabled)
- (($procX)->secure_jumper=$jumperApplied)
+
+ # Load jumper state to the master processor
+ $hb_masterproc.set-secure-jumper value = $jumperApplied
+
+ # Load jumper state to all slave processors
+ foreach $procS in ($hb_masterproc.get-slave-procs) {
+ $procS.set-secure-jumper value = $jumperApplied
+ }
+} else {
+ # Load jumper state to each processor
+ foreach $procX in (get-object-list p9_proc) {
+
+ # Set logical jumper state in SIMICS based on HW policy
+ # "TRUE"=jumper applied(security disabled, default)
+ # "FALSE"=jumper removed(security enabled)
+ (($procX)->secure_jumper=$jumperApplied)
+ }
}
if ($hb_mode == 0) {
diff --git a/src/build/tools/addCopyright b/src/build/tools/addCopyright
index 81e871010..1a172a49b 100755
--- a/src/build/tools/addCopyright
+++ b/src/build/tools/addCopyright
@@ -96,6 +96,9 @@ use constant LICENSE_PROLOG => "LICENSE_PROLOG";
# When adding a new company add constant here and to %fileContributorsCompany
use constant IBM => 'International Business Machines Corp.';
use constant GOOGLE => 'Google Inc.';
+use constant INSPUR => 'Inspur Power Systems Corp.';
+use constant SUPERMICRO => 'Super Micro Computer, Inc.';
+use constant YADRO => 'YADRO';
# Create mapping for git contrubitors to companies
my %fileContributorsCompany = (
@@ -103,6 +106,9 @@ my %fileContributorsCompany = (
"ozlabs.org" => IBM,
"google.com" => GOOGLE,
"Google Shared Technology" => GOOGLE,
+ "inspur.com" => INSPUR,
+ "supermicro.com" => SUPERMICRO,
+ "yadro.com" => YADRO,
);
#------------------------------------------------------------------------------
diff --git a/src/build/tools/build-cppcheck b/src/build/tools/build-cppcheck
new file mode 100755
index 000000000..8e19ed429
--- /dev/null
+++ b/src/build/tools/build-cppcheck
@@ -0,0 +1,95 @@
+#!/bin/bash -e
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/tools/build-cppcheck $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2019
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+source $PROJECT_ROOT/src/build/citest/etc/cppcheck
+
+update_toolconfig(){
+ echo "commit: $CPPCHECK_COMMIT"
+ echo "gcc version: $(gcc -dumpversion)"
+ echo "S: $(uname -o)"
+ echo "arch: $(uname -m)"
+ echo "$(lsb_release -i)"
+ echo "$(lsb_release -r)"
+}
+
+if [ -n "${OPENPOWER_BUILD}" ]; then
+ exit
+fi
+
+cd $PROJECT_ROOT/src/build/tools
+
+if [[ ! -d "cpptools" ]]; then
+ mkdir cpptools
+fi
+
+cd cpptools
+if [[ ! -d "cppcheck" ]]; then
+ # cppcheck folder does not exist, clone repo for the first time
+ git clone git@github.com:danmar/cppcheck.git
+ cd cppcheck
+ git reset --hard $CPPCHECK_COMMIT #update to cppcheck commit
+ update_toolconfig >.cpp_toollevel
+ SHOULDMAKE=1
+else
+ cd cppcheck
+ if ! cmp -s .cpp_toollevel <(update_toolconfig) ; then
+ # cppcheck repo is not at the
+ # level set in $PROJECT_ROOT/src/build/citest/etc/cppcheck
+ if ! git fetch origin; then
+ cd $PROJECT_ROOT/src/build/tools/cpptools
+ rm -rf cppcheck
+ git clone git@github.com:danmar/cppcheck.git
+ cd cppcheck
+ fi
+ git reset --hard $CPPCHECK_COMMIT
+ update_toolconfig >.cpp_toollevel
+
+ SHOULDMAKE=1
+ fi
+ if [[ ! -f "cppcheck" ]]; then
+ SHOULDMAKE=1
+ fi
+fi
+
+if [ "${SHOULDMAKE}" ]; then
+
+ # Check if CXX is set, if it is not then try to find it with CXXPATH
+ # if CXXPATH does not exist, default to host's g++
+ if [ -z "$CXX" ]; then
+ if [ -z "${CXXPATH}" ]; then
+ export CXX=g++
+ else
+ export CXX=${CXXPATH}/g++
+ fi
+ fi
+
+ make
+
+fi
+
+cd $PROJECT_ROOT
+
+
diff --git a/src/build/tools/cflags.sh b/src/build/tools/cflags.sh
new file mode 100755
index 000000000..0ca39f374
--- /dev/null
+++ b/src/build/tools/cflags.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/tools/cflags.sh $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2019
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# The purpose of this script is to convert a series of GCC compiler
+# flags into an equivalent series of flags, but which use absolute
+# paths for include directories (i.e. the "-I" flag) instead of
+# relative paths. We have to do this when GCOV is in use, because it
+# stupidly puts data files in one path but stores paths inside the
+# data files that are relative to some other path. When GCOV then
+# tries to read the source files via these relative paths, it can't
+# find the files. We correct this by converting all paths to source
+# and header files to absolute paths.
+
+if [ ! "$HOSTBOOT_PROFILE" ] ; then
+ echo "$@"
+ exit
+fi
+
+make_path_abs () {
+ local ABSPATH
+ ABSPATH=$(readlink -f "$1")
+
+ if [ $? -ne 0 ] ; then
+ ABSPATH="$1"
+ fi
+
+ echo -n "$ABSPATH"
+}
+
+while [ "$#" -gt 0 ] ; do
+ FLAG="$1"
+
+ if [ "$FLAG" = "-I" ] ; then
+ shift
+ echo -n "-I $(make_path_abs "$1") "
+ elif [ "${FLAG:0:2}" = "-I" ] ; then
+ echo -n "-I $(make_path_abs "${FLAG:2}") "
+ else
+ echo -n "$FLAG "
+ fi
+
+ shift
+done
+
+echo
diff --git a/src/build/tools/eecache_editor.pl b/src/build/tools/eecache_editor.pl
new file mode 100755
index 000000000..262f56376
--- /dev/null
+++ b/src/build/tools/eecache_editor.pl
@@ -0,0 +1,802 @@
+#!/usr/local/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/tools/eecache_editor.pl $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2019
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+use strict;
+use Getopt::Long;
+use File::Copy;
+
+
+binmode STDOUT, ':bytes';
+
+my $pnorBinaryPath = "";
+my $eecacheBinaryPath = "";
+my $newImagePath = "";
+my $outFilePath = "./eecache_editor_output.dat";
+my $masterHuid = 0;
+my $port = 0;
+my $engine = 0;
+my $devAddr = 0;
+my $muxHuid = 0;
+my $muxSelect = 0xFF;
+my $eepromSize = 0;
+my $usage = 0;
+my $uniqueId = "";
+my $verbose = 0;
+my $onlyValid = 0;
+my $clearEepromData = 0;
+my $overwrite = 0;
+my $summary = 0;
+my $devOffset = 0xFFFF; # initialized to invalid offset
+
+# Goals of this tool:
+#
+# ** Handle both entire PNOR image as well as single EECACHE section as input **
+#
+# 1) Given masterHuid, port, engine, devAddr, muxSelect lookup cached EEPROM value and replace
+# it with a given binary file. (File size must be <= allocated space)
+#
+# 2) Given a binary pnor/eecache. Print summary of cached eeproms
+#
+# 3) Zero out a given cached eeprom
+#
+# 4) Extract the contents for a given masterHuid, port, engine, devAddr, muxSelect
+
+use constant VERSION_1_TOC_ENTRY_SIZE_BYTES => 17;
+use constant VERSION_1_TOC_ENTRY_SIZE_BITS => (VERSION_1_TOC_ENTRY_SIZE_BYTES * 8) ;
+use constant VERSION_1_NUM_ENTRIES => 50;
+use constant VERSION_1_TOC_SIZE => (VERSION_1_TOC_ENTRY_SIZE_BYTES * VERSION_1_NUM_ENTRIES) + 5;
+
+use constant VERSION_2_TOC_ENTRY_SIZE_BYTES => 18;
+use constant VERSION_2_TOC_ENTRY_SIZE_BITS => (VERSION_2_TOC_ENTRY_SIZE_BYTES * 8) ;
+use constant VERSION_2_NUM_ENTRIES => 50;
+use constant VERSION_2_TOC_SIZE => (VERSION_2_TOC_ENTRY_SIZE_BYTES * VERSION_2_NUM_ENTRIES) + 5;
+
+use constant VERSION_LATEST => 2;
+
+use constant EEPROM_ACCESS_I2C => 1;
+use constant EEPROM_ACCESS_SPI => 2;
+
+
+
+my $eecacheVersion = VERSION_LATEST;
+
+GetOptions("pnor:s" => \$pnorBinaryPath,
+ "eecache:s" => \$eecacheBinaryPath,
+ "newImage:s" => \$newImagePath,
+ "newFile:s" => \$newImagePath,
+ "out:s" => \$outFilePath,
+ "of:s" => \$outFilePath,
+ "masterHuid:o" => \$masterHuid,
+ "port:o" => \$port,
+ "engine:o" => \$engine,
+ "devAddr:o" => \$devAddr,
+ "muxSelect:o" => \$muxSelect,
+ "eepromSize:o" => \$eepromSize,
+ "uniqueId:s" => \$uniqueId,
+ "devOffset:o" => \$devOffset,
+ "version:o" => \$eecacheVersion,
+ "onlyValid" => \$onlyValid,
+ "overwrite" => \$overwrite,
+ "clear" => \$clearEepromData,
+ "verbose" => \$verbose,
+ "usage" => \$usage,
+ "help" => \$usage,
+ "h" => \$usage);
+
+sub print_help()
+{
+ print "--------- EECACHE Editor Tool V 2.0 ---------\n";
+ print "\n";
+ print "Mandatory:\n\n";
+
+ print " --eecache Path to ECC-less eeprom cache section of PNOR (IE : EECACHE.bin )\n\n";
+
+ print "Optional:\n\n";
+
+ print " --clear If a matching eeprom is found, clear out its contents\n";
+ print " --devAddr Device address of desired EEPROM\n";
+ print " --devOffset Offset (KB) of where record begins in eeprom for SPI access\n";
+ print " --engine Engine of I2C/SPI Master desired EEPROM exists on\n";
+ print " --masterHuid HUID of the I2C/SPI Master Target\n";
+ print " --muxSelect Mux Select (if needed) defaults to 0xFF \n";
+ print " --onlyValid If printing summary, only print valid eeprom caches\n";
+ print " --out Full path to desired out file, if not provided defaults to ./eecache_editor_output.dat\n";
+ print " --port Port of I2C Master desired EEPROM exists on\n";
+ print " --uniqueId Combination of unique I2C Slave information, alternative to passing\n";
+ print " information in 1 thing at a time\n";
+ print " --version Version of eecache (default to latest if this isn't provided)\n";
+ print " --verbose Print extra information \n";
+ print " --help Print this information \n";
+ print "\n ";
+ print "Examples: \n\n";
+ print " # prints out info about all eeproms in EECACHE.bin\n";
+ print " eecache_editor.pl --eecache EECACHE.bin\n";
+ print "\n";
+ print " # (I2C) lookup eeprom matching input params and write contents of that EEPROM's cached data to outfile \n";
+ print " eecache_editor.pl --eecache EECACHE.bin --version 1 --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000\n";
+ print "\n";
+ print " # (I2C) lookup eeprom matching input params and clear the contents ( manipulate input binary )\n";
+ print " eecache_editor.pl --eecache EECACHE.bin --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000 --clear\n";
+ print "\n";
+ print " # (I2C) lookup eeprom matching input params and write new image's contents to offset in EECACHE where matching eeprom data exists ( manipulate input binary )\n";
+ print " eecache_editor.pl --eecache EECACHE.bin --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000 --newImage newSPD.dat\n";
+ print "\n";
+ print " # (SPI) lookup eeprom matching input params and write contents of that EEPROM's cached data to outfile \n";
+ print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000\n";
+ print "\n";
+ print " # (SPI) lookup eeprom matching input params and clear the contents ( manipulate input binary )\n";
+ print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000 --clear\n";
+ print "\n";
+ print " # (SPI) lookup eeprom matching input params and write new image's contents to offset in EECACHE where matching eeprom data exists ( manipulate input binary )\n";
+ print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000 --newImage newSPD.dat\n";
+ print "---------------------------------------------\n";
+}
+
+if( $usage )
+{
+ print_help();
+ exit 0;
+}
+
+if( ($pnorBinaryPath eq "") &&
+ ($eecacheBinaryPath eq ""))
+{
+ # Print error saying we need one of these filled in
+ print "ERROR Neither PNOR binary nor EECACHE section binary passed in. Cannot continue.\n\n";
+ print_help();
+ exit 0;
+}
+
+# if PNOR is not empty, ignore eecacheBinary , we will
+# output a full updated pnor since we were provided a pnor.
+# but if no pnor is provided , we will just return and EECACHE sections
+my $inputIsEntirePnor = 0;
+if( $pnorBinaryPath ne "")
+{
+ $inputIsEntirePnor = 1;
+}
+
+if($newImagePath ne "")
+{
+ $overwrite = 1;
+}
+
+if ($eecacheVersion > VERSION_LATEST)
+{
+ print "ERROR: --version $eecacheVersion is greater than max ".VERSION_LATEST."\n\n";
+ print_help();
+ exit 0;
+}
+
+if ($uniqueId eq "")
+{
+ if ($eecacheVersion == VERSION_LATEST)
+ {
+ # devOffset is specific to SPI access so check to see if it is valid
+ if ($devOffset != 0xFFFF)
+ {
+ $uniqueId = sprintf ("%.02X", EEPROM_ACCESS_SPI);
+ $uniqueId .= sprintf ("%.08X", $masterHuid);
+ $uniqueId .= sprintf ("%.02X", $engine);
+ $uniqueId .= sprintf ("%.04X", $devOffset);
+ $uniqueId .= "00"; # blank byte
+ }
+ else
+ {
+ $uniqueId = sprintf ("%.02X", EEPROM_ACCESS_I2C);
+ $uniqueId .= sprintf ("%.08X", $masterHuid);
+ $uniqueId .= sprintf ("%.02X", $port);
+ $uniqueId .= sprintf ("%.02X", $engine);
+ $uniqueId .= sprintf ("%.02X", $devAddr);
+ $uniqueId .= sprintf ("%.02X", $muxSelect);
+ }
+ }
+ elsif ($eecacheVersion == 1)
+ {
+ $uniqueId .= sprintf ("%.08X", $masterHuid);
+ $uniqueId .= sprintf ("%.02X", $port);
+ $uniqueId .= sprintf ("%.02X", $engine);
+ $uniqueId .= sprintf ("%.02X", $devAddr);
+ $uniqueId .= sprintf ("%.02X", $muxSelect);
+ }
+}
+
+my $displayOnly = 0;
+
+unless (isUniqueIdValid($uniqueId))
+{
+ if( $clearEepromData )
+ {
+ print_help();
+ print "\n ERROR: Detecting that user is trying to --clear data without providing what info on what eeprom to clear. Exiting. \n\n";
+ exit 0;
+ }
+ $displayOnly = 1;
+ $verbose = 1;
+}
+else
+{
+ print "\nUnique ID we are looking up: 0x$uniqueId \n\n" ;
+}
+
+# setup input and output files
+my $input_fh;
+my $output_fh;
+
+my $new_fh;
+
+if($inputIsEntirePnor)
+{
+ open $input_fh, '<', $pnorBinaryPath or die "failed to open $pnorBinaryPath: $!\n";
+ if($overwrite)
+ {
+ open $output_fh, '>', $pnorBinaryPath or die "failed to open $pnorBinaryPath: $!\n";
+ }
+ else
+ {
+ open $output_fh, '>', $outFilePath or die "failed to open $outFilePath: $!\n";
+ }
+}
+else
+{
+ open $input_fh, '+<:raw', $eecacheBinaryPath or die "failed to open $eecacheBinaryPath: $!\n";
+ if($overwrite)
+ {
+ $output_fh = $input_fh;
+ }
+ else
+ {
+ open $output_fh, '+>:raw', $outFilePath or die "failed to open $outFilePath: $!\n";
+ copy($eecacheBinaryPath, $outFilePath) ;
+ }
+}
+
+if($newImagePath ne "")
+{
+ open $new_fh, '<', $newImagePath or die "failed to open $newImagePath: $!\n";
+}
+
+
+
+# at this point we should know what we are trying to accomplish :
+#
+# IF ($displayOnly != 0) THEN we will only print a summary
+#
+# ELSE IF ($newImagePath != "") THEN we will write new contents if matching section found
+#
+# ELSE IF ($clear != 0) THEN clear the contents if matching section found
+#
+# ELSE if matching section found, then write contents to outfile
+
+
+
+# TODO handle entire PNOR
+if($inputIsEntirePnor)
+{
+ #find EECACHE offset , seek to there
+}
+else
+{
+ # Parse the larger binary blob to get just the Table of Contents
+ my $eecacheTOC = readEecacheToc($input_fh);
+
+ # The hashRef you key back has members: offset and size
+ # This represents offset and size of eeprom data in given
+ # binary.
+ my $hashRef = parseEecacheToc($eecacheTOC, $uniqueId);
+
+ # if we are doing displayOnly then we are done, we can skip the following logic
+ if(!$displayOnly)
+ {
+ # If the offset is 0, then no match was found
+ if($hashRef->{'entry_offset'} != 0)
+ {
+ if($newImagePath ne "") # if a new image is available try to load it in
+ {
+ my $new_file_size = -s $newImagePath ;
+ my $new_file_data;
+ read($new_fh, $new_file_data, $new_file_size );
+
+ # Verify the new image is the correct size
+ if( $new_file_size != $hashRef->{'entry_size'})
+ {
+ print "ERROR incorrect size, EECACHE is reporting size to be".$hashRef->{'entry_size'}."bytes but file proved is only".$new_file_size." bytes\n";
+ exit 0;
+ }
+
+ # seek to the offset inside EEACHE where this eeprom's cache lives
+ # and write the new file contents
+ seek($output_fh, $hashRef->{'entry_offset'} , 0);
+ print $output_fh $new_file_data;
+ }
+ elsif($clearEepromData) # if we are told to clear the data do that
+ {
+ print "Attempting Clearing starting at $hashRef->{'entry_offset'} $hashRef->{'header_offset'}!!!!!!!!\n";
+ my $byteOfOnes = pack("H2", "FF") ;
+ my $byteOfZeroes = pack("H2", "00") ;
+ seek($output_fh, $hashRef->{'entry_offset'} , 0);
+ for(my $i = 0; $i < $hashRef->{'entry_size'}; $i++)
+ {
+ print $output_fh $byteOfOnes;
+ }
+
+ # seek($output_fh, $hashRef->{'header_offset'} + 16, 0);
+ # print $output_fh $byteOfZeroes;
+ }
+ else
+ {
+ seek($input_fh, $hashRef->{'entry_offset'} , 0);
+ my $cur_pos = tell $input_fh;
+ print "reading $hashRef->{'entry_size'} from $cur_pos\n ";
+ my $cachedData;
+ read($input_fh, $cachedData, $hashRef->{'entry_size'});
+ print $output_fh $cachedData;
+ }
+ }
+ }
+}
+
+close $input_fh;
+close $output_fh;
+
+# End of Main
+exit 0;
+
+
+# Start Subroutines
+
+sub readEecacheToc {
+ my $eecache_fh = shift;
+
+ my $start_location = tell $eecache_fh;
+
+ my $eecache_toc_version = 0;
+
+ read($eecache_fh, $eecache_toc_version, 1) == 1 or die "failed to read single byte from eecache file handle";
+ $eecache_toc_version = unpack 'C', $eecache_toc_version;
+
+ my $eecache_toc;
+
+ if( $eecache_toc_version == 1 )
+ {
+ seek($eecache_fh, $start_location, 0);
+ read($eecache_fh, $eecache_toc, VERSION_1_TOC_SIZE) or die "failed to read ".VERSION_1_TOC_SIZE." bytes from eecache file handle"; ;
+ }
+ elsif ( $eecache_toc_version == 2)
+ {
+ seek($eecache_fh, $start_location, 0);
+ read($eecache_fh, $eecache_toc, VERSION_2_TOC_SIZE) or die "failed to read ".VERSION_2_TOC_SIZE." bytes from eecache file handle"; ;
+ }
+ else
+ {
+ die "Failed to find valid TOC, version found = $eecache_toc_version. Latest version this tool supports is ".VERSION_LATEST;
+ }
+
+ return $eecache_toc;
+}
+
+# Brief : Takes in binary blob representing EECACHE table of contents, as well as
+# a uniqueID to match against, returns hash that contains size and offset of
+# cached eeprom data inside EEACHE section
+#
+# If verbose is set,
+
+sub parseEecacheToc {
+ my $eecacheTOC = shift;
+ my $idToMatch = shift;
+
+ # figure out what version of EECACHE header exists
+ my $headerVersion = 0;
+ my $tocEntrySizeBytes = 0;
+ my $tocEntries = 0;
+
+ my ($version) = unpack('H2', "$eecacheTOC");
+ if ($version == 0x01)
+ {
+ $headerVersion = 1;
+ $tocEntrySizeBytes = VERSION_1_TOC_ENTRY_SIZE_BYTES;
+ $tocEntries = VERSION_1_NUM_ENTRIES;
+ }
+ elsif ($version == 0x02)
+ {
+ $headerVersion = 2;
+ $tocEntrySizeBytes = VERSION_2_TOC_ENTRY_SIZE_BYTES;
+ $tocEntries = VERSION_2_NUM_ENTRIES;
+ }
+ else
+ {
+ die "Unsupported PNOR EECACHE level $version";
+ }
+
+ # verify uniqueId was built against same version as PNOR's EECACHE
+ if (isUniqueIdValid($uniqueId))
+ {
+ unless (($headerVersion == $eecacheVersion))
+ {
+ die "PNOR EECACHE version $headerVersion is not same as expected EECACHE version $eecacheVersion!" .
+ "Maybe changed expected with --version option";
+ }
+ }
+
+ # header entries start after on 6th byte
+ my $headerEntryOffset = 5;
+
+ # this will end up being the return value
+ my %entryInfo;
+ $entryInfo{entry_offset} = 0;
+ $entryInfo{entry_size} = 0;
+ $entryInfo{header_offset} = 0;
+
+ my $totalEntryCount = 0;
+ my $validEntryCount = 0;
+
+ my $matchSummaryString = "";
+
+ # Some common variables between header versions
+ my $internal_offset = 0xFFFF;
+ my $cached_copy_valid = 0;
+ my $cached_copy_size = 0;
+ my $entry_size = 0;
+ my $entry_offset = 0;
+ my $bitFieldByte = 0; # last byte of header
+ my $entryUniqueID = "FFFFFFFFFFFFFFFF";
+
+ use Class::Struct;
+
+ struct I2C_Entry_t => {
+ i2c_master_huid => '$',
+ port => '$',
+ engine => '$',
+ devAddr => '$',
+ mux_select => '$',
+ };
+
+ struct SPI_Entry_t => {
+ spi_master_huid => '$',
+ engine => '$',
+ offset_KB => '$',
+ };
+
+ for(my $i = 0; $i < $tocEntries; $i++)
+ {
+ my $eepromAccess = EEPROM_ACCESS_I2C;
+ my $master_eeprom = 0xFF; # default to invalid master eeprom
+
+ my $entry = substr $eecacheTOC, $headerEntryOffset, $tocEntrySizeBytes;
+
+ # update offset right away so we dont forget
+ $headerEntryOffset += $tocEntrySizeBytes;
+ my $entry_data;
+
+ if ($headerVersion == 1)
+ {
+ ###### VERSION 1 ########
+ # struct completeRecord
+ # {
+ # uint32_t i2c_master_huid; // HUID of i2c Master
+ # uint8_t port; // I2C Port
+ # uint8_t engine; // I2C Engine
+ # uint8_t devAddr; // I2C Device Address
+ # uint8_t mux_select; // Some I2C devices are behind a mux, this says
+ # // what setting on the mux is required
+ # uint32_t cache_copy_size; // Size of data saved in cache (in KB)
+ # uint32_t internal_offset; // offset from start of EECACHE section where cached
+ # // data exists
+ # uint8_t cached_copy_valid : 1, // This bit is set when we think the contents of the
+ # // cache is valid.
+ # unused : 7;
+ #
+ # } PACKED completeRecord;
+ #
+ # struct uniqueRecord
+ # {
+ # uint8_t uniqueID [NUM_BYTE_UNIQUE_ID];
+ # uint8_t metaData [sizeof(completeRecord) - NUM_BYTE_UNIQUE_ID];
+ # } PACKED uniqueRecord;
+
+ # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above)
+ my @entryFields = unpack('H8 H2 H2 H2 H2 H8 H8 H2', "$entry");
+
+ $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]@entryFields[4]";
+ $eepromAccess = EEPROM_ACCESS_I2C;
+ $entry_data = I2C_Entry_t->new();
+ $entry_data->i2c_master_huid( @entryFields[0] );
+ $entry_data->port ( @entryFields[1] );
+ $entry_data->engine ( @entryFields[2] );
+ $entry_data->devAddr ( @entryFields[3] );
+ $entry_data->mux_select ( @entryFields[4] );
+ $bitFieldByte = @entryFields[7];
+ $cached_copy_valid = (hex( "0x".@entryFields[7]) & 0x80) >> 7;
+
+
+ # if the entry ID is FFFFFFFFFFFFFFFF this indicates
+ # that the entry is not filled out
+ if($entryUniqueID == "FFFFFFFFFFFFFFFF")
+ {
+ next;
+ }
+ $cached_copy_size = @entryFields[5];
+ $internal_offset = @entryFields[6];
+ }
+ elsif ($headerVersion == 2)
+ {
+ ###### VERSION 2 ########
+ # struct completeRecord
+ # {
+ # EepromAccessMethodType accessType; // how to access record
+ # union eepromAccess_t
+ # {
+ # struct i2cAccess_t
+ # {
+ # uint32_t i2c_master_huid; // HUID of i2c Master
+ # uint8_t port; // I2C Port
+ # uint8_t engine; // I2C Engine
+ # uint8_t devAddr; // I2C Device Address
+ # uint8_t mux_select; // Some I2C devices are behind a mux, this says
+ # // what setting on the mux is required
+ # } PACKED i2cAccess;
+ # struct spiAccess_t
+ # {
+ # uint32_t spi_master_huid; // HUID of SPI master
+ # uint8_t engine; // engine specific to eeprom
+ # uint16_t offset_KB; // offset in KB of where record begins in eeprom
+ # } PACKED spiAccess;
+ # } PACKED eepromAccess;
+ # uint32_t cache_copy_size; // Size of data saved in cache (in KB)
+ # uint32_t internal_offset; // offset from start of EECACHE section where cached
+ # // data exists
+ # uint8_t cached_copy_valid : 1, // This bit is set when we think the contents of the
+ # // cache is valid.
+ # master_eeprom : 1, // This bit marks this record as the master one (i.e. look at this one for change)
+ # unused : 6;
+ #
+ # } PACKED completeRecord;
+ #
+ # struct uniqueRecord
+ # {
+ # uint8_t uniqueID [NUM_BYTE_UNIQUE_ID];
+ # uint8_t metaData [sizeof(completeRecord) - NUM_BYTE_UNIQUE_ID];
+ # } PACKED uniqueRecord;
+
+ ($eepromAccess) = unpack('H2', "$entry");
+ if ($eepromAccess == EEPROM_ACCESS_I2C)
+ {
+ # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above)
+ my @entryFields = unpack('H2 H8 H2 H2 H2 H2 H8 H8 H2', "$entry");
+
+ $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]@entryFields[4]@entryFields[5]";
+
+ $entry_data = I2C_Entry_t->new();
+ $entry_data->i2c_master_huid( @entryFields[1] );
+ $entry_data->port( @entryFields[2] );
+ $entry_data->engine( @entryFields[3] );
+ $entry_data->devAddr( @entryFields[4] );
+ $entry_data->mux_select( @entryFields[5] );
+
+ $cached_copy_size = @entryFields[6];
+ $internal_offset = @entryFields[7];
+
+ $bitFieldByte = @entryFields[8];
+ $cached_copy_valid = (hex("0x".@entryFields[8]) & 0x80) >> 7;
+ $master_eeprom = (hex("0x".@entryFields[8]) & 0x40) >> 6;
+ }
+ elsif ($eepromAccess == EEPROM_ACCESS_SPI)
+ {
+ # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above)
+ my @entryFields = unpack('H2 H8 H2 H4 H2 H8 H8 H2', "$entry");
+
+ $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]00";
+
+ $entry_data = SPI_Entry_t->new();
+ $entry_data->spi_master_huid( @entryFields[1] );
+ $entry_data->engine( @entryFields[2] );
+ $entry_data->offset_KB( @entryFields[3] );
+
+ # @entryField[4] is just filler
+
+ $cached_copy_size = @entryFields[5];
+ $internal_offset = @entryFields[6];
+
+ $bitFieldByte = @entryFields[7];
+ $cached_copy_valid = (hex("0x".@entryFields[7]) & 0x80) >> 7;
+ $master_eeprom = (hex("0x".@entryFields[7]) & 0x40) >> 6;
+ }
+ else
+ {
+ # entry is not filled out if eepromAccess is not I2C or SPI
+ next;
+ }
+ }
+
+ $totalEntryCount++;
+
+ if(uc $entryUniqueID eq uc $idToMatch)
+ {
+ $entryInfo{entry_offset} = $internal_offset;
+ $entryInfo{entry_size} = $cached_copy_size * 1024; # KB to Bytes
+ $entryInfo{header_offset} = $headerEntryOffset - $tocEntrySizeBytes;
+
+ $matchSummaryString = "ENTRY FOUND ...\n";
+ if ($eepromAccess == EEPROM_ACCESS_I2C)
+ {
+ if ($headerVersion >= 2)
+ {
+ $matchSummaryString .=
+ "accessType = 0x".$eepromAccess." I2C ACCESS\n";
+ }
+ $matchSummaryString .=
+ "Master I2C Huid = 0x". $entry_data->i2c_master_huid ."\n".
+ "Port = 0x". $entry_data->port ."\n".
+ "Engine = 0x". $entry_data->engine ."\n".
+ "Device Address = 0x". $entry_data->devAddr ."\n".
+ "Mux Select = 0x". $entry_data->mux_select ."\n".
+ "Size of Cached Copy (KB) = 0x$cached_copy_size\n".
+ "Offset within EECACHE = 0x$internal_offset\n".
+ "Cached copy valid ? = 0x$cached_copy_valid (1st bit of 0x$bitFieldByte)\n";
+ }
+ else # EEPROM_ACCESS_SPI
+ {
+ if ($headerVersion >= 2)
+ {
+ $matchSummaryString .=
+ "accessType = 0x".$eepromAccess." SPI ACCESS\n";
+ }
+ $matchSummaryString .=
+ "Master SPI Huid = 0x". $entry_data->spi_master_huid ."\n".
+ "Engine = 0x". $entry_data->engine ."\n".
+ "Offset in EEPROM = 0x". $entry_data->offset_KB ."\n".
+ "Size of Cached Copy (KB) = 0x$cached_copy_size\n".
+ "Offset within EECACHE = 0x$internal_offset\n".
+ "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n";
+ }
+ if ($master_eeprom != 0xFF)
+ {
+ $matchSummaryString .=
+ "EEPROM master ? = $master_eeprom (2nd bit of 0x$bitFieldByte)\n";
+ }
+ $matchSummaryString .=
+ "unique ID = 0x$entryUniqueID \n\n";
+
+ if(!$verbose)
+ {
+ last;
+ }
+ }
+
+ if( !$cached_copy_valid )
+ {
+ # skip if this entry is not valid and told to just
+ # print valid only entries
+ if($onlyValid)
+ {
+ next;
+ }
+ }
+ else
+ {
+ $validEntryCount++;
+ }
+
+ my $entryString = "";
+ if ($eepromAccess == EEPROM_ACCESS_I2C)
+ {
+ if ($headerVersion >= 2)
+ {
+ $entryString .=
+ "accessType = 0x".$eepromAccess." I2C ACCESS\n";
+ }
+ $entryString .=
+ "Master I2C Huid = 0x". $entry_data->i2c_master_huid ."\n".
+ "Port = 0x". $entry_data->port ."\n".
+ "Engine = 0x". $entry_data->engine ."\n".
+ "Device Address = 0x". $entry_data->devAddr ."\n".
+ "Mux Select = 0x". $entry_data->mux_select ."\n".
+ "Size of Cached Copy (KB) = 0x$cached_copy_size\n".
+ "Offset within EECACHE = 0x$internal_offset\n".
+ "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n";
+ }
+ else
+ {
+ if ($headerVersion >= 2)
+ {
+ $entryString .=
+ "accessType = 0x".$eepromAccess." SPI ACCESS\n";
+ }
+ $entryString .=
+ "Master SPI Huid = 0x". $entry_data->spi_master_huid ."\n".
+ "Engine = 0x". $entry_data->engine ."\n".
+ "Offset in EEPROM = 0x". $entry_data->offset_KB ."\n".
+ "Size of Cached Copy (KB) = 0x$cached_copy_size\n".
+ "Offset within EECACHE = 0x$internal_offset\n".
+ "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n";
+ }
+
+ if ($master_eeprom != 0xFF)
+ {
+ $entryString .=
+ "EEPROM master ? = $master_eeprom (2nd bit of 0x$bitFieldByte)\n";
+ }
+ $entryString .=
+ "unique ID = 0x$entryUniqueID \n\n";
+
+ printVerbose($entryString);
+ }
+
+ printVerbose(
+ "Summary :\n".
+ " Total Entry Count : $totalEntryCount \n".
+ " Valid Entry Count : $validEntryCount \n".
+ " Max Possible Entries : $tocEntries\n\n");
+
+ if($matchSummaryString ne "")
+ {
+ print $matchSummaryString;
+ }
+ else
+ {
+ # Skip failure message if not looking for a unique id match
+ if (isUniqueIdValid($uniqueId))
+ {
+ print "No Match Found! \n\n";
+ }
+ }
+
+ return \%entryInfo;
+}
+
+
+sub findEepromRecordOffset {
+
+
+
+}
+
+sub printVerbose {
+
+ my $string = shift;
+
+ if($verbose)
+ {
+ print $string;
+ }
+}
+
+sub isUniqueIdValid
+{
+ my ($uniqueId) = @_;
+
+ if( (($eecacheVersion == 1) && ($uniqueId == "00000000000000FF")) ||
+ (($eecacheVersion == 2) && ($uniqueId == "0100000000000000FF")) ||
+ (($eecacheVersion == 2) && ($uniqueId == "020000000000000000")) )
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
diff --git a/src/build/tools/hb b/src/build/tools/hb
index 9576adb0f..9e7e38a48 100755
--- a/src/build/tools/hb
+++ b/src/build/tools/hb
@@ -39,6 +39,7 @@ execute_in_sandbox()
echo $1 > ${SANDBOXBASE}/src/sandbox_execute_cmd
chmod 700 ${SANDBOXBASE}/src/sandbox_execute_cmd
+ echo "Sandbox :: $1"
${WORKON_CMD} -c ./sandbox_execute_cmd
@@ -356,14 +357,16 @@ hb_simsetup()
DRIVER=`cat ${PROJECT_ROOT}/src/build/citest/etc/bbuild`
SIMICS_LEVEL=`cat ${PROJECT_ROOT}/src/build/citest/etc/simbuild`
+ EECACHE_PREBUILT=`cat ${PROJECT_ROOT}/src/build/citest/etc/eecache_prebuilt`
needs_machine_variable
if [ "${MACHINE}" == "AXONE" ]; then
- echo "mkdir -p ${SANDBOXBASE}/simics"
execute_in_sandbox "mkdir -p ${SANDBOXBASE}/simics" "ppc"
- echo "tar ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/"
execute_in_sandbox "tar -xf ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/" "ppc"
+ echo "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh"
execute_in_sandbox "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh" "ppc"
+ echo "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc"
+ execute_in_sandbox "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc" "ppc"
else
execute_in_sandbox "start_simics -no_start -machine ${MACHINE}" "ppc"
fi
@@ -424,8 +427,19 @@ hb_startsimics()
#export MYDIR=$bb/obj/ppc/hbfw/simics/startup.simics
#then /runsim -m axone -o hb_script_to_run=$MYDIR
export MY_DIR="${SANDBOXBASE}/obj/ppc/simu/scripts/hbfw"
- echo "cd ${SANDBOXBASE}/simics/ && ./runsim -m ${MACHINE} hb_script_to_run=${MY_DIR}/startup.simics pnor_img=${MY_DIR}/../../../hbfw/img/axone.pnor sbe_seeprom_img=${SANDBOXBASE}/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=1 vpd_proc=vpd/images/99a8c3fe4e5c74798f5bd4212f3d9a2a"
- execute_in_sandbox "cd ${SANDBOXBASE}/simics/ && ./runsim -m ${MACHINE} hb_script_to_run=${MY_DIR}/startup.simics pnor_img=${MY_DIR}/../../../hbfw/img/axone.pnor sbe_seeprom_img=${SANDBOXBASE}/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=1 vpd_proc=vpd/images/99a8c3fe4e5c74798f5bd4212f3d9a2a" "ppc"
+ # If '-nre' was passed in as a flag, then do not vexec
+ # also, if $POOL is defined, this indicates are already in
+ # a vexec shell so do not vexec
+ if [ "$*" = "-nre" ] || [ ! -z ${POOL} ]; then
+ VEXEC_STR=" vexec"
+ else
+ VEXEC_STR=""
+ fi
+ export RUNSIMCMD="cd ${SANDBOXBASE}/simics/ &&${VEXEC_STR} ./runsim -m ${MACHINE} hb_script_to_run=${MY_DIR}/startup.simics pnor_img=${MY_DIR}/../../../hbfw/img/axone.pnor sbe_seeprom_img=${SANDBOXBASE}/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=2 enable_lpc_console=TRUE hb_pnor_dir=${MY_DIR}/../../../hbfw/img/"
+ echo "**********"
+ echo $RUNSIMCMD
+ echo "**********"
+ execute_in_sandbox "${RUNSIMCMD} ${SIMICSOPTIONS}" "ppc"
else
execute_in_sandbox \
"start_simics -machine ${MACHINE} ${SIMICSOPTIONS} $*" "ppc"
diff --git a/src/build/tools/listdeps.pl b/src/build/tools/listdeps.pl
index 9bad71ef9..2eaf7a6ad 100755
--- a/src/build/tools/listdeps.pl
+++ b/src/build/tools/listdeps.pl
@@ -229,6 +229,7 @@ my $resident_modules = {
"libexpaccess.so" => '1',
"libnvdimm.so" => '1',
"libmmio.so" => '1',
+ "libsmf.so" => '1',
};
# A list of the dependent libraries in each istep.
diff --git a/src/build/tools/pre-commit b/src/build/tools/pre-commit
index 3dc621bb3..ccf02b80a 100755
--- a/src/build/tools/pre-commit
+++ b/src/build/tools/pre-commit
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
@@ -6,7 +6,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2017
+# Contributors Listed Below - COPYRIGHT 2011,2019
# [+] International Business Machines Corp.
#
#
@@ -35,3 +35,48 @@ else
echo "For more info run './hb --help'"
exit -1
fi
+
+# Run cppcheck if variable is set, if not exit here
+if [[ $DOCPPCHECK -ne 1 ]]; then
+ exit 0
+fi
+
+echo "Running CPPCHECK"
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+ against=HEAD
+else
+ # This is the hash of the default empty tree in Git.
+ # If for some reason HEAD is not set, then diff'ing against this is like
+ # diff'ing against the very first commit.
+ against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+${TOOLSDIR}/build-cppcheck
+CPPCHECKTOOL=${TOOLSDIR}/cpptools/cppcheck/cppcheck
+CPPCHECKFLAGS="--inline-suppr --error-exitcode=1"
+CPPCHECK=" ${CPPCHECKTOOL} ${CPPCHECKFLAGS}"
+
+for file in $(git diff-index --cached $against | \
+ grep -E '[MA].*\.(C|c|cpp|cc|cxx)$' | cut -f 2)
+do
+
+ dir="$(dirname $file)"
+ filename="$(basename $file)"
+
+ # TODO RTC 215692
+ # The following command checks for cppcheck errors. All cppcheck errors are
+ # printed to the terminal and stored to a file .${filename}.cppcheck.
+ set -o pipefail && cd ${dir} && timeout 2m ${CPPCHECK} $filename 2>&1 | tee .${filename}.cppcheck; exit_code=$?; \
+ if [ "$exit_code" -ne 1 ]; then \
+ # If exit code does not equal 1 (which is the error code when a cppcheck
+ # error is found) delete the created .cppcheck file.
+ # Note that time-out fails with error code 127.
+ rm -f .${filename}.cppcheck; \
+ fi
+ cd $PROJECT_ROOT
+
+done
+
+exit 0
OpenPOWER on IntegriCloud