summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xsrc/build/buildpnor/buildpnor.pl590
-rw-r--r--src/build/buildpnor/defaultPnorLayout.xml91
-rwxr-xr-xsrc/build/mkrules/hbfw/img/makefile4
-rw-r--r--src/include/usr/hwas/hwasPlatDeconfigGard.H19
-rw-r--r--src/include/usr/pnor/pnor_reasoncodes.H2
-rw-r--r--src/include/usr/pnor/pnorif.H39
-rw-r--r--src/usr/hwas/hwasPlatDeconfigGard.C89
-rw-r--r--src/usr/pnor/HBconfig5
-rw-r--r--src/usr/pnor/common/ffs_hb.H7
-rw-r--r--src/usr/pnor/makefile1
-rw-r--r--src/usr/pnor/pnor_common.C182
-rw-r--r--src/usr/pnor/pnor_common.H19
-rw-r--r--src/usr/pnor/pnorrp.C152
-rw-r--r--src/usr/pnor/pnorrp.H26
-rw-r--r--src/usr/pnor/pnorsbe.C87
-rw-r--r--src/usr/pnor/pnorvalid.C5
-rw-r--r--src/usr/pnor/runtime/rt_pnor.C11
-rw-r--r--src/usr/pnor/runtime/rt_pnor.H2
-rw-r--r--src/usr/pnor/test/pnorrptest.H104
-rw-r--r--src/usr/sbe/sbe_update.C95
-rw-r--r--src/usr/sbe/sbe_update.H38
-rw-r--r--src/usr/sbe/test/sbeupdatetest.H24
22 files changed, 1057 insertions, 535 deletions
diff --git a/src/build/buildpnor/buildpnor.pl b/src/build/buildpnor/buildpnor.pl
index 51b6922c7..f6df6c810 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,2014
+# Contributors Listed Below - COPYRIGHT 2012,2015
# [+] International Business Machines Corp.
#
#
@@ -62,16 +62,20 @@ my $g_trace = 1;
my $programName = File::Basename::basename $0;
my %pnorLayout;
my %binFiles;
-
-
my $pnorLayoutFile;
my $pnorBinName = "";
my $tocVersion = 0x1;
my $g_TOCEyeCatch = "part";
my $emitTestSections = 0;
-my $g_ffsCmd = "";
my $g_fpartCmd = "";
my $g_fcpCmd = "";
+my %sidelessSecFilled = ();
+
+my %SideOptions = (
+ A => "A",
+ B => "B",
+ sideless => "sideless",
+ );
if ($#ARGV < 0) {
usage();
@@ -102,9 +106,6 @@ for (my $i=0; $i < $#ARGV + 1; $i++)
my $argVal = $ARGV[++$i];
saveInputFile("--binFile", $argName, $argVal, \%binFiles);
}
- elsif($ARGV[$i] =~ /--ffsCmd/) {
- $g_ffsCmd = $ARGV[++$i];
- }
elsif($ARGV[$i] =~ /--fpartCmd/) {
$g_fpartCmd = $ARGV[++$i];
}
@@ -121,12 +122,14 @@ for (my $i=0; $i < $#ARGV + 1; $i++)
}
}
-#Extract ffs version number from help text.
-#Use to trigger using proper input parms..
-#my $ffsParms = 0;
-#my $ffsVersion = `$g_ffsCmd 2>&1 | grep "Partition Tool" `;
-#$ffsVersion =~ s/.*(v[0-9\.]*).*/\1/;
-#$ffsVersion = $1;
+############################## Begin Actions ##################################
+
+#Delete File (pnorBinName) if exists to prevent errors when making layout
+#changes
+if (-e $pnorBinName)
+{
+ unlink $pnorBinName or warn "Could not unlink $pnorBinName: $!";
+}
#Load PNOR Layout XML file
my $rc = loadPnorLayout($pnorLayoutFile, \%pnorLayout);
@@ -136,9 +139,6 @@ if($rc != 0)
exit 1;
}
-#trace(1, Dumper(%pnorLayout->{1576960}));
-#trace(1, Dumper(%binFiles));
-
#Verify all the section files exist
my $rc = verifyFilesExist(\%pnorLayout, \%binFiles);
if($rc != 0)
@@ -161,42 +161,48 @@ if($rc != 0)
trace(0, "Error detected from call to checkSpaceConstraints(). Exiting");
exit 1;
}
-
-#create the PNOR image
-#two copies of TOC created at different offsets
-my $sideAOffset = $pnorLayout{metadata}{sideAOffset};
-my $sideBOffset = $pnorLayout{metadata}{sideBOffset};
-
-$rc = createPnorImg($tocVersion, $pnorBinName, \%pnorLayout, $sideAOffset, 'A');
-if($rc != 0)
+trace(1, "Done checkSpaceConstraints");
+
+# @TODO RTC: 120062 - Determine which side is Golden, possibly handle a new
+# xml tag
+# Create all Partition Tables at each TOC offset
+# Each side has 2 TOC's created at different offsets for backup purposes.
+# Loop all side sections
+foreach my $sideId ( keys %{$pnorLayout{metadata}{sides}} )
{
- trace(0, "Error detected from createPnorImg() sideAOffset. Exiting");
- exit 1;
-}
+ # Loop all tocs (primary and backup)
+ foreach my $toc ( keys %{$pnorLayout{metadata}{sides}{$sideId}{toc}})
+ {
+ my $tocOffset = $pnorLayout{metadata}{sides}{$sideId}{toc}{$toc};
-$rc = createPnorImg($tocVersion, $pnorBinName, \%pnorLayout, $sideBOffset, 'B');
-if($rc != 0)
-{
- trace(0, "Error detected from createPnorImg() sideBOffset. Exiting");
- exit 1;
+ $rc = createPnorPartition($tocVersion, $pnorBinName, \%pnorLayout,
+ $sideId, $tocOffset);
+ if($rc != 0)
+ {
+ trace(0, "Error detected from createPnorPartition() $tocOffset Exiting");
+ exit 1;
+ }
+ }
}
-$rc = fillPnorImage($pnorBinName, \%pnorLayout, \%binFiles, $sideAOffset, 'A');
-if($rc != 0)
+# Fill all sides
+foreach my $sideId ( keys %{$pnorLayout{metadata}{sides}} )
{
- trace(0, "Error detected from call to fillPnorImage() sideAOffset. Exiting");
- exit 1;
-}
+ my $tocOffset = $pnorLayout{metadata}{sides}{$sideId}{toc}{primary};
-$rc = fillPnorImage($pnorBinName, \%pnorLayout, \%binFiles, $sideBOffset, 'B');
-if($rc != 0)
-{
- trace(0, "Error detected from call to fillPnorImage() sideBOffset. Exiting");
- exit 1;
+ $rc = fillPnorImage($pnorBinName, \%pnorLayout, \%binFiles, $sideId,
+ $tocOffset);
+ if($rc != 0)
+ {
+ trace(0, "Error detected from call to fillPnorImage() sideATocOffset. Exiting");
+ exit 1;
+ }
}
exit 0;
+######################### Begin Utility Subroutines ###########################
+
################################################################################
# loadPnorLayout
################################################################################
@@ -215,33 +221,52 @@ sub loadPnorLayout
my $xs = new XML::Simple(keyattr=>[], forcearray => 1);
my $xml = $xs->XMLin($i_pnorFile);
- #trace(1, "pnorLayoutXML \n ".Dumper($xml));
-
#Save the meatadata - imageSize, blockSize, etc.
+ # @TODO RTC:120062 enhance metadata section, fix metadataE1 to match xml
+ # and change TOC names accordingly
foreach my $metadataEl (@{$xml->{metadata}})
{
+ # Get meta data
my $imageSize = $metadataEl->{imageSize}[0];
my $blockSize = $metadataEl->{blockSize}[0];
- my $sideAOffset = $metadataEl->{sideAOffset}[0];
- my $sideBOffset = $metadataEl->{sideBOffset}[0];
-
- trace(3, "$this_func: metadata: imageSize = $imageSize, blockSize=$blockSize, sideAOffset=$sideAOffset, sideBOffset=$sideBOffset");
-
$imageSize = getNumber($imageSize);
$blockSize = getNumber($blockSize);
- $sideAOffset = getNumber($sideAOffset);
- $sideBOffset = getNumber($sideBOffset);
-
$$i_pnorLayoutRef{metadata}{imageSize} = $imageSize;
$$i_pnorLayoutRef{metadata}{blockSize} = $blockSize;
- $$i_pnorLayoutRef{metadata}{sideAOffset} = $sideAOffset;
- $$i_pnorLayoutRef{metadata}{sideBOffset} = $sideBOffset;
+
+ # Get Side A
+ my $sideATocOffset = $metadataEl->{sideATocOffset}[0];
+ my $sideATocBackupOffset = $metadataEl->{sideATocBackupOffset}[0];
+ $sideATocOffset = getNumber($sideATocOffset);
+ $sideATocBackupOffset = getNumber($sideATocBackupOffset);
+ # @TODO RTC: 120062 change pnorLayoutRef hash to match new xml
+ $$i_pnorLayoutRef{metadata}{sides}{$SideOptions{A}}{toc}{primary} = $sideATocOffset;
+ $$i_pnorLayoutRef{metadata}{sides}{$SideOptions{A}}{toc}{backup} = $sideATocBackupOffset;
+
+ # Get side B info (if it exists)
+ if (exists $metadataEl->{sideBTocOffset}[0])
+ {
+ trace(1, "Adding Side B information ....");
+ my $sideBTocOffset = $metadataEl->{sideBTocOffset}[0];
+ my $sideBTocBackupOffset = $metadataEl->{sideBTocBackupOffset}[0];
+ $sideBTocOffset = getNumber($sideBTocOffset);
+ $sideBTocBackupOffset = getNumber($sideBTocBackupOffset);
+ # @TODO RTC: 120062 change pnorLayoutRef hash to match new xml
+ $$i_pnorLayoutRef{metadata}{sides}{$SideOptions{B}}{toc}{primary} = $sideBTocOffset;
+ $$i_pnorLayoutRef{metadata}{sides}{$SideOptions{B}}{toc}{backup} = $sideBTocBackupOffset;
+
+ trace(3, "$this_func: metadata: imageSize = $imageSize, blockSize=$blockSize, sideATocOffset=$sideATocOffset, sideATocBackupOffset=$sideATocBackupOffset, sideBTocOffset=$sideBTocOffset, sideBTocBackupOffset=$sideBTocBackupOffset");
+ }
+ else
+ {
+ trace(3, "$this_func: metadata: imageSize = $imageSize, blockSize=$blockSize, sideATocOffset=$sideATocOffset, sideATocBackupOffset=$sideATocBackupOffset");
+ }
+
}
#Iterate over the <section> elements.
foreach my $sectionEl (@{$xml->{section}})
{
- #trace(1, "current Element: \n ".Dumper($sectionEl));
my $description = $sectionEl->{description}[0];
my $eyeCatch = $sectionEl->{eyeCatch}[0];
my $physicalOffset = $sectionEl->{physicalOffset}[0];
@@ -251,7 +276,9 @@ sub loadPnorLayout
my $ecc = (exists $sectionEl->{ecc} ? "yes" : "no");
my $sha512Version = (exists $sectionEl->{sha512Version} ? "yes" : "no");
my $sha512perEC = (exists $sectionEl->{sha512perEC} ? "yes" : "no");
-
+ my $sideless = (exists $sectionEl->{sideless} ? "yes" : "no");
+ my $preserved = (exists $sectionEl->{preserved} ? "yes" : "no");
+ my $readOnly = (exists $sectionEl->{readOnly} ? "yes" : "no");
if (($emitTestSections == 0) && ($sectionEl->{testonly}[0] eq "yes"))
{
next;
@@ -262,8 +289,6 @@ sub loadPnorLayout
$physicalOffset = getNumber($physicalOffset);
$physicalRegionSize = getNumber($physicalRegionSize);
- # trace(4, "$this_func: physicalOffset=$physicalOffset, physicalRegionSize=$physicalRegionSize");
-
$$i_pnorLayoutRef{sections}{$physicalOffset}{description} = $description;
$$i_pnorLayoutRef{sections}{$physicalOffset}{eyeCatch} = $eyeCatch;
$$i_pnorLayoutRef{sections}{$physicalOffset}{physicalOffset} = $physicalOffset;
@@ -272,6 +297,9 @@ sub loadPnorLayout
$$i_pnorLayoutRef{sections}{$physicalOffset}{ecc} = $ecc;
$$i_pnorLayoutRef{sections}{$physicalOffset}{sha512Version} = $sha512Version;
$$i_pnorLayoutRef{sections}{$physicalOffset}{sha512perEC} = $sha512perEC;
+ $$i_pnorLayoutRef{sections}{$physicalOffset}{sideless} = $sideless;
+ $$i_pnorLayoutRef{sections}{$physicalOffset}{preserved} = $preserved;
+ $$i_pnorLayoutRef{sections}{$physicalOffset}{readOnly} = $readOnly;
}
@@ -279,23 +307,16 @@ sub loadPnorLayout
}
################################################################################
-# createPnorImg - Create PNOR image and partitions based on input data.
+# createPnorImg - Create PNOR image based on input data.
################################################################################
sub createPnorImg
{
- my ($i_tocVersion, $i_pnorBinName, $i_pnorLayoutRef, $offset, $side) = @_;
+ my ($i_tocVersion, $i_pnorBinName, $i_pnorLayoutRef, $i_offset) = @_;
my $this_func = (caller(0))[3];
my $rc = 0;
- my $key;
- my $other_side = 'B';
trace(4, "$this_func: >>Enter");
- trace(1, "createPnorImg:: $offset");
-
- if($side eq 'B')
- {
- $other_side = 'A';
- }
+ trace(1, "createPnorImg:: $i_offset");
#get Block size
my $blockSize = $$i_pnorLayoutRef{metadata}{blockSize};
@@ -303,154 +324,212 @@ sub createPnorImg
#Get size of image in blocks
my $imageSize = $$i_pnorLayoutRef{metadata}{imageSize};
my $blockCount = $imageSize/$blockSize;
- if ($blockCount != int($blockCount))
+ do{
+ if ($blockCount != int($blockCount))
+ {
+ trace(0, "$this_func: Image size ($imageSize) is not an even multiple of erase blocks ($blockSize). This is not supported. Aborting!");
+ $rc = 1;
+ last;
+ }
+
+ #f{fs,part} --create tuleta.pnor --partition-offset 0 --size 8MiB --block 4KiB --force
+ trace(2, "$g_fpartCmd --target $i_pnorBinName --partition-offset $i_offset --create --size $imageSize --block $blockSize --force");
+ $rc = `$g_fpartCmd --target $i_pnorBinName --partition-offset $i_offset --create --size $imageSize --block $blockSize --force`;
+ if($rc)
+ {
+ trace(0, "$this_func: Call to creating image failed. rc=$rc. Aborting!");
+ last;
+ }
+ }while(0);
+
+ return $rc;
+}
+
+################################################################################
+# addUserData - Add partition user data.
+################################################################################
+sub addUserData
+{
+ my $i_pnorBinName = shift;
+ my $i_offset = shift;
+ my $i_key = shift;
+ my %i_sectionHash = @_;
+
+ my $this_func = (caller(0))[3];
+ my $rc = 0;
+ trace(4, "$this_func: >>Enter");
+
+ my $eyeCatch = $i_sectionHash{$i_key}{eyeCatch};
+
+ # User data Flags based on FFS entry user data (ffs_hb_user_t)
+ my $chip = 0;
+ my $compressType = 0;
+ my $dataInteg = 0;
+ my $verCheck = 0;
+ my $miscFlags = 0;
+
+ # DataInteg flag
+ if( ($i_sectionHash{$i_key}{ecc} eq "yes") )
{
- trace(0, "$this_func: Image size ($imageSize) is not an even multiple of erase blocks ($blockSize). This is not supported. Aborting!");
- $rc = 1;
- return $rc;
+ $dataInteg = 0x8000;
}
- #f{fs,part} --create tuleta.pnor --partition-offset 0 --size 8MiB --block 4KiB --force
- if ($g_ffsCmd eq "") {
- my $Out = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --create --size $imageSize --block $blockSize --force`;
- } else {
- my $Out = `$g_ffsCmd --target $i_pnorBinName --partition-offset $offset --create --size $imageSize --block $blockSize --force`;
+ # VerCheck Flag
+ if( ($i_sectionHash{$i_key}{sha512Version} eq "yes") )
+ {
+ $verCheck = 0x80;
}
- $rc = $?;
- if($rc)
+ elsif( ($i_sectionHash{$i_key}{sha512perEC} eq "yes") )
{
- trace(0, "$this_func: Call to creating image failed. rc=$rc. Aborting!");
- return $rc;
+ $verCheck = 0x40;
}
- #key into hash data is the physical offset of section. Need to sort the keys
- #so we put things in the correct order in toc.
- #Generally speaking, this loop is populating the FFS Header with records based on the
- #section data specified in the XML + actual sizes of the input binary files.
- my %sectionHash = %{$$i_pnorLayoutRef{sections}};
-
- for $key ( sort {$a<=> $b} keys %sectionHash)
+ # Misc Flags
+ if( ($i_sectionHash{$i_key}{preserved} eq "yes") )
+ {
+ $miscFlags |= 0x80;
+ }
+ if( ($i_sectionHash{$i_key}{readOnly} eq "yes") )
{
- my $eyeCatch = "UNDEF";
- my $physicalOffset = 0xFFFFFFFF;
- my $physicalRegionSize = 0xFFFFFFFF;
+ $miscFlags |= 0x40;
+ }
- # eyecatcher
- my $eyeCatch = $sectionHash{$key}{eyeCatch};
- my $myside = $sectionHash{$key}{side};
- #don't try to add the TOC, but need to update all other paritions
- #Add if side matches (or not set) -- so if it isn't equal to other side
- if(( $eyeCatch ne $g_TOCEyeCatch ) && ( $myside ne $other_side ))
- {
+ #First User Data Word
+ #[1:chip][1:compressType][2:dataInteg]
+ my $userflags0 = ($chip << 24)
+ | ($compressType << 16)
+ | $dataInteg;
- # base/physical offset
- my $physicalOffset = $sectionHash{$key}{physicalOffset};
- #make sure offset is on a block boundary
- my $val = $physicalOffset/$blockSize;
- if ($val != int($val))
- {
- trace(0, "$this_func: Partition offset ($val) is does not fall on an erase block ($blockSize) boundary. This is not supported. Aborting!");
- $rc = -1;
- last;
- }
+ #Second User Data Word
+ #[1:sha512Version/sha512perEC][1:miscFlags]
+ my $userflags1 = ($verCheck << 24)
+ | ($miscFlags << 16);
- #physical size
- my $physicalRegionSize = $sectionHash{$key}{physicalRegionSize};
- $val = $physicalRegionSize/$blockSize;
- if($val != int($val))
- {
- trace(0, "$this_func: Partition size ($val) is not an even multiple of erase blocks ($blockSize). This is not supported. Aborting!");
- exit 1;
- }
+ do{
+ trace(2, "$g_fpartCmd --target $i_pnorBinName --partition-offset $i_offset --user 0 --name $eyeCatch --value userflags0=$userflags0");
+ $rc = `$g_fpartCmd --target $i_pnorBinName --partition-offset $i_offset --user 0 --name $eyeCatch --value $userflags0`;
+ if($rc)
+ {
+ trace(0, "$this_func: Call to add userdata to $eyeCatch failed. rc=$rc. Aborting!");
+ last;
+ }
+ trace(2, "$g_fpartCmd --target $i_pnorBinName --partition-offset $i_offset --user 1 --name $eyeCatch --value userflags1=$userflags1");
+ $rc = `$g_fpartCmd --target $i_pnorBinName --partition-offset $i_offset --user 1 --name $eyeCatch --value $userflags1`;
+ if($rc)
+ {
+ trace(0, "$this_func: Call to add userdata to $eyeCatch failed. rc=$rc. Aborting!");
+ last;
+ }
+ }while(0);
- #Add Partition
- #f{fs,part} --add --target tuleta.pnor --partition-offset 0 --offset 0x1000 --size 0x280000 --name HBI --flags 0x0
- if ($g_ffsCmd eq "") {
- trace(1, "$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --add --offset $physicalOffset --size $physicalRegionSize --name $eyeCatch --flags 0x0");
- my $Out = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --add --offset $physicalOffset --size $physicalRegionSize --name $eyeCatch --flags 0x0`;
- } else {
- my $Out = `$g_ffsCmd --target $i_pnorBinName --partition-offset $offset --add --offset $physicalOffset --size $physicalRegionSize --name $eyeCatch --flags 0x0`;
- }
- $rc = $?;
- if($rc)
- {
- trace(0, "$this_func: Call to add partition $eyeCatch failed. rc=$rc. Aborting!");
- last;
- }
+ return $rc;
+}
- # User data Flags
- my $chip = 0;
- my $compress = 0;
- my $ecc = 0;
- my $version = 0;
+################################################################################
+# createPnorPartition - Create PNOR partitions based on input data.
+################################################################################
+sub createPnorPartition
+{
+ my ($i_tocVersion, $i_pnorBinName, $i_pnorLayoutRef, $side, $offset) = @_;
+ my $this_func = (caller(0))[3];
+ my $rc = 0;
+ my $key;
+ my $other_side = getOtherSide($side);
- if( ($sectionHash{$key}{ecc} eq "yes") )
- {
- $ecc = 0x8000;
- }
- if( ($sectionHash{$key}{sha512Version} eq "yes") )
- {
- $version = 0x80;
- }
- elsif( ($sectionHash{$key}{sha512perEC} eq "yes") )
- {
- $version = 0x40;
- }
+ trace(4, "$this_func: >>Enter");
- #First User Data Word
- #[1:chip][1:compression][2:ecc]
- my $userflags0 = ($chip << 24)
- | ($compress << 16)
- | $ecc;
-
- #Second User Data Word
- #[1:sha512Version/sha512perEC]
- my $userflags1 = ($version << 24);
-
- trace(1,"userflags0 = $userflags0");
- trace(1,"userflags1 = $userflags1");
- if ($g_ffsCmd eq "") {
- trace(1, "$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --user 0 --name $eyeCatch --value $userflags0");
- my $Out = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --user 0 --name $eyeCatch --value $userflags0`;
- trace(1, "$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --user 1 --name $eyeCatch --value $userflags1");
- my $Out = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --user 1 --name $eyeCatch --value $userflags1`;
- }
- $rc = $?;
- if($rc)
- {
- trace(0, "$this_func: Call to add userdata to $eyeCatch failed. rc=$rc. Aborting!");
- last;
- }
+ trace(1, "createPnorPartition:: $offset");
- #Trunc Partition
- #f{fs,part} --target tuleta.pnor --partition-offset 0 --name HBI --trunc
- if ($g_ffsCmd eq "") {
- my $Out = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --trunc --name $eyeCatch`;
- } else {
- my $Out = `$g_ffsCmd --target $i_pnorBinName --partition-offset $offset --trunc --name $eyeCatch`;
- }
- $rc = $?;
- if($rc)
- {
- trace(0, "$this_func: Call to trunc partition $eyeCatch failed. rc=$rc. Aborting!");
- last;
- }
+ do{
+ # Create pnor image at partition offset
+ $rc = createPnorImg($i_tocVersion, $i_pnorBinName, $i_pnorLayoutRef,
+ $offset);
+ if($rc)
+ {
+ last;
}
- #Disable usewords for now. Will get re-enabled and fixed up as
- #we add support for underlying functions
+ #get Block size
+ my $blockSize = $$i_pnorLayoutRef{metadata}{blockSize};
-# my $Out = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset
-# --user 0 --name $eyeCatch --value $actualRegionSize`;
-# $rc = $?;
-# if($rc)
-# {
-# trace(0, "$this_func: Call to fpart setting user 0 for partition $eyeCatch failed. rc=$rc. Aborting!");
-# last;
-# }
+ # key into hash data is the physical offset of section. Need to sort the
+ # keys so we put things in the correct order in toc. Generally speaking,
+ # this loop is populating the FFS Header with records based on the section
+ # data specified in the XML + actual sizes of the input binary files.
+ my %sectionHash = %{$$i_pnorLayoutRef{sections}};
- }
+ for $key ( sort {$a<=> $b} keys %sectionHash)
+ {
+ my $eyeCatch = "UNDEF";
+ my $physicalOffset = 0xFFFFFFFF;
+ my $physicalRegionSize = 0xFFFFFFFF;
+
+ # eyecatcher
+ my $eyeCatch = $sectionHash{$key}{eyeCatch};
+
+ my $sideInfo = getSideInfo($key, %sectionHash);
+
+ #don't try to add the TOC, but need to update all other paritions
+ #Add if side matches (or not set) -- so if it isn't equal to other side
+ #Also add if sideless
+ if( ($eyeCatch ne $g_TOCEyeCatch ) &&
+ ($sideInfo ne $other_side ))
+ {
+ # base/physical offset
+ my $physicalOffset = $sectionHash{$key}{physicalOffset};
+ #make sure offset is on a block boundary
+ my $val = $physicalOffset/$blockSize;
+ if ($val != int($val))
+ {
+ trace(0, "$this_func: Partition offset ($val) does not fall on an erase block ($blockSize) boundary. This is not supported. Aborting!");
+ $rc = -1;
+ last;
+ }
+
+ #physical size
+ my $physicalRegionSize = $sectionHash{$key}{physicalRegionSize};
+ $val = $physicalRegionSize/$blockSize;
+ if($val != int($val))
+ {
+ trace(0, "$this_func: Partition size ($val) is not an even multiple of erase blocks ($blockSize). This is not supported. Aborting!");
+ exit 1;
+ }
+
+ #Add Partition
+ #f{fs,part} --add --target tuleta.pnor --partition-offset 0 --offset 0x1000 --size 0x280000 --name HBI --flags 0x0
+ trace(2, "$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --add --offset $physicalOffset --size $physicalRegionSize --name $eyeCatch --flags 0x0");
+ $rc = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --add --offset $physicalOffset --size $physicalRegionSize --name $eyeCatch --flags 0x0`;
+ if($rc)
+ {
+ trace(0, "$this_func: Call to add partition $eyeCatch failed. rc=$rc. Aborting!");
+ last;
+ }
+
+ # Add User Partition data
+ $rc = addUserData($i_pnorBinName, $offset, $key, %sectionHash);
+ if($rc)
+ {
+ trace(0, "$this_func: Call to add user data to partition $eyeCatch failed. rc=$rc. Aborting!");
+ last;
+ }
+
+ #Trunc Partition
+ #f{fs,part} --target tuleta.pnor --partition-offset 0 --name HBI --trunc
+ $rc = `$g_fpartCmd --target $i_pnorBinName --partition-offset $offset --trunc --name $eyeCatch`;
+ if($rc)
+ {
+ trace(0, "$this_func: Call to trunc partition $eyeCatch failed. rc=$rc. Aborting!");
+ last;
+ }
+ }
+ }
+ # Added in case more functionality added before while ends
+ if ($rc)
+ {
+ last;
+ }
+ }while(0);
return $rc;
}
@@ -570,21 +649,13 @@ sub checkSpaceConstraints
################################################################################
sub fillPnorImage
{
- my ($i_pnorBinName, $i_pnorLayoutRef, $i_binFiles, $offset, $side) = @_;
+ my ($i_pnorBinName, $i_pnorLayoutRef, $i_binFiles, $side, $offset) = @_;
my $this_func = (caller(0))[3];
my $rc = 0;
my $key;
- my $other_side = 'B';
-
-
- if($side eq 'B')
- {
- $other_side = 'A';
- }
-
+ my $other_side = getOtherSide($side);
trace(1, "fillPnorImage:: $offset");
-
#key is the physical offset into the file, however don't need to sort
#since FFS allows populating partitions in any order
my %sectionHash = %{$$i_pnorLayoutRef{sections}};
@@ -605,27 +676,26 @@ sub fillPnorImage
next;
}
- my $myside = $sectionHash{$key}{side};
+ my $sideInfo = getSideInfo($key, %sectionHash);
- #Add if side matches (or not set) -- so if it isn't equal to other side
- if( $myside ne $other_side )
+ # Add if side matches (or not set) -- so if it isn't equal to other side
+ # Only fill sideless sections once
+ if( ($sideInfo ne $other_side) &&
+ (!exists($sidelessSecFilled{$eyeCatch})))
{
- trace(5, "$this_func: populating section $myside:$eyeCatch, filename=$inputFile");
-
- #fcp --target tuleta.pnor --partition-offset 0 --name HBI --write hostboot_extended.bin
- if ($g_ffsCmd eq "") {
- my $Out = `$g_fcpCmd $inputFile $i_pnorBinName:$eyeCatch --offset $offset --write --buffer 0x40000000`;
- } else {
- my $Out = `$g_ffsCmd --target $i_pnorBinName --partition-offset $offset --name $eyeCatch --write $inputFile`;
+ if($sideInfo eq $SideOptions{sideless})
+ {
+ $sidelessSecFilled{$eyeCatch} = 1;
}
- $rc = $?;
+ trace(5, "$this_func: populating section $sideInfo:$eyeCatch, filename=$inputFile");
+ #fcp --target tuleta.pnor --partition-offset 0 --name HBI --write hostboot_extended.bin
+ $rc = `$g_fcpCmd $inputFile $i_pnorBinName:$eyeCatch --offset $offset --write --buffer 0x40000000`;
if($rc)
{
trace(0, "$this_func: Call to fcp adding data to partition $eyeCatch failed. rc=$rc. Aborting!");
last;
}
}
-
}
return $rc;
@@ -653,28 +723,6 @@ sub saveInputFile
}
#################################################
-# getFFSEntrySize: Returns number of bytes in an ffs_entry based on specified version
-#################################################
-sub getFFSEntrySize
-{
- my($i_tocVersion, $i_pnorLayoutRef) = @_;
- my $this_func = (caller(0))[3];
- my $ffsEntrySize = 0;
-
- if($i_tocVersion == 0x1)
- {
- #16 char name + 12 fixed words + 16 user data words
- $ffsEntrySize = 16+(12*4)+(16*4);
- }
- else
- {
- trace(0, "$this_func: Layout Version Unsupported! i_tocVersion=$i_tocVersion");
- exit 1;
- }
- return $ffsEntrySize;
-}
-
-#################################################
# Insert specifed number of pad bytes into file
#
#################################################
@@ -732,6 +780,70 @@ sub trace
}
}
+################################################################################
+# getSideInfo - return side info of certain sections and determine if value is
+# a supported value
+################################################################################
+sub getSideInfo
+{
+ my $i_key = shift;
+ my %i_sectionHash = @_;
+
+ my $side = "";
+ my $eyeCatch = $i_sectionHash{$i_key}{eyeCatch};
+
+
+ if($i_sectionHash{$i_key}{sideless} eq "yes")
+ {
+ return $SideOptions{sideless};
+ }
+ else
+ {
+ $side = $i_sectionHash{$i_key}{side};
+ }
+
+ # Error paths
+ if ($side eq "")
+ {
+ trace(0, "Error detected from call to getSideInfo() - $eyeCatch has no side info specified Exiting");
+ exit 1;
+ }
+ elsif (!exists($SideOptions{$side}))
+ {
+ trace(0, "Error detected from call to getSideInfo() - $eyeCatch has sideInfo = $side which is not supported Exiting");
+ exit 1;
+ }
+
+ return $side;
+}
+
+################################################################################
+# getOtherSide - return other side of the given side
+# does not default to main side in case more sides are added
+################################################################################
+sub getOtherSide
+{
+ my $i_side = shift;
+ my $other_side = "";
+
+ if($i_side eq $SideOptions{A})
+ {
+ $other_side = $SideOptions{B};
+ }
+ elsif($i_side eq $SideOptions{B})
+ {
+ $other_side = $SideOptions{A};
+ }
+
+ # Error paths
+ if ($other_side eq "")
+ {
+ trace(0, "Error detected from call to getOtherSide() - Could not get other side of side = $i_side Exiting");
+ exit 1;
+ }
+
+ return $other_side;
+}
################################################################################
diff --git a/src/build/buildpnor/defaultPnorLayout.xml b/src/build/buildpnor/defaultPnorLayout.xml
index e34f0feba..249bdb476 100644
--- a/src/build/buildpnor/defaultPnorLayout.xml
+++ b/src/build/buildpnor/defaultPnorLayout.xml
@@ -5,7 +5,9 @@
<!-- -->
<!-- OpenPOWER HostBoot Project -->
<!-- -->
-<!-- COPYRIGHT International Business Machines Corp. 2012,2014 -->
+<!-- Contributors Listed Below - COPYRIGHT 2012,2015 -->
+<!-- [+] International Business Machines Corp. -->
+<!-- -->
<!-- -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); -->
<!-- you may not use this file except in compliance with the License. -->
@@ -22,48 +24,50 @@
<!-- IBM_PROLOG_END_TAG -->
<!--
Layout Description
-<metadata> Element -> Contains high-level information about
- the PNOR layout.
- <imageSize> -> Size of PNOR image in bytes.
- <blockSize> -> size of erase blocks in bytes.
- <sideAOffset> -> Location of Side A Partition Table
- <sideBOffset> -> Location of Side B Partition Table
-<section> -> Contains information about a PNOR Partition
- <description> -> Text description of the partition.
- Does not have to be machine readable.
- <eyeCatch> -> Name of the Partition
- <physicalOffset> -> Offset of the Partition in PNOR
- in bytes.
- <physicalSize> -> Size of the Partition in bytes.
- <side> -> Side the partition should be associated with.
- This determines if the partition should be
- added to the partition table at <sideAOffset>
- or <sideBOffset>
- <testonly/> Indicates partition is used for internal
- testing only. Partition should be skipped
- in production environments.
- <ecc/> Indicates Partition should be ECC protected
- <sha512Version/> Indicates Partition uses SHA512 for
- version information.
- <sha512perEC/> Indicates SHA512 is used to indicate
- version for each EC-specific image
- within the Partition.
- <preserved/> Indicates Partition is preserved
- across code updates.
+<metadata> Element -> Contains high-level information about the PNOR layout.
+ <imageSize> -> Size of PNOR image in bytes.
+ <blockSize> -> size of erase blocks in bytes.
+ <sideATocOffset> -> Location of Side A Partition Table
+ <sideATocBackupOffset>-> Location of Side A Backup Partition Table
+ <sideBTocOffset> -> Location of Side B Partition Table
+ <sideBTocBackupOffset>-> Location of Side B Backup Partition Table
+</metadata>
+<section> Element -> Contains information about a PNOR Partition
+ <description> -> Text description of the partition.
+ Does not have to be machine readable.
+ <eyeCatch> -> Name of the Partition
+ <physicalOffset>-> Offset of the Partition in PNOR
+ in bytes.
+ <physicalSize> -> Size of the Partition in bytes.
+ <side> -> Side the Partition should be associated with. This
+ determines if the partition should be added to the
+ partition table at <sideATocOffset> or <sideBTocOffset>
+ <sideless/> -> Indicates partition will be in both TOCs but only one
+ copy of the partition should be created
+ <testonly/> -> Indicates partition is used for internal testing only.
+ Partition should be skipped in production environments.
+ <ecc/> -> Indicates Partition should be ECC protected
+ <sha512Version/>-> Indicates Partition uses SHA512 for version information.
+ <sha512perEC/> -> Indicates SHA512 is used to indicate version for each
+ EC-specific image within the Partition.
+ <preserved/> -> Indicates Partition is preserved across code updates.
+</section>
-->
<pnor>
<metadata>
<imageSize>0x4000000</imageSize>
<blockSize>0x1000</blockSize>
- <sideAOffset>0x0</sideAOffset>
- <sideBOffset>0x8000</sideBOffset>
+ <!-- @TODO RTC: 120062 - Enhance meta info -->
+ <sideATocOffset>0x0</sideATocOffset>
+ <sideATocBackupOffset>0x8000</sideATocBackupOffset>
</metadata>
<section>
<description>Hostboot Error Logs (144K)</description>
<eyeCatch>HBEL</eyeCatch>
<physicalOffset>0x10000</physicalOffset>
<physicalRegionSize>0x24000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -71,6 +75,7 @@ Layout Description
<eyeCatch>GUARD</eyeCatch>
<physicalOffset>0x58000</physicalOffset>
<physicalRegionSize>0x5000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -78,6 +83,7 @@ Layout Description
<eyeCatch>HBD</eyeCatch>
<physicalOffset>0x5D000</physicalOffset>
<physicalRegionSize>0x120000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -86,6 +92,7 @@ Layout Description
<!--NOTE: MUST update standalone.simics if offset changes -->
<physicalOffset>0x17D000</physicalOffset>
<physicalRegionSize>0x48000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -94,6 +101,7 @@ Layout Description
<!--NOTE: MUST update standalone.simics if offset changes -->
<physicalOffset>0x1C5000</physicalOffset>
<physicalRegionSize>0x90000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -102,6 +110,7 @@ Layout Description
<!--NOTE: MUST update standalone.simics if offset changes -->
<physicalOffset>0x255000</physicalOffset>
<physicalRegionSize>0x48000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -110,6 +119,7 @@ Layout Description
<physicalOffset>0x29D000</physicalOffset>
<physicalRegionSize>0x5A0000</physicalRegionSize>
<sha512Version/>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -118,6 +128,7 @@ Layout Description
<physicalOffset>0x83D000</physicalOffset>
<physicalRegionSize>0x90000</physicalRegionSize>
<sha512perEC/>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -126,6 +137,7 @@ Layout Description
<physicalOffset>0x8CD000</physicalOffset>
<physicalRegionSize>0x48000</physicalRegionSize>
<sha512perEC/>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -134,6 +146,7 @@ Layout Description
<physicalOffset>0x915000</physicalOffset>
<physicalRegionSize>0x120000</physicalRegionSize>
<sha512Version/>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -142,6 +155,7 @@ Layout Description
<physicalOffset>0xA35000</physicalOffset>
<physicalRegionSize>0x240000</physicalRegionSize>
<sha512Version/>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -149,6 +163,7 @@ Layout Description
<eyeCatch>PAYLOAD</eyeCatch>
<physicalOffset>0xC75000</physicalOffset>
<physicalRegionSize>0x1680000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -157,6 +172,18 @@ Layout Description
<physicalOffset>0x3590000</physicalOffset>
<physicalRegionSize>0x9000</physicalRegionSize>
<testonly/>
+ <sideless/>
+ <ecc/>
+ </section>
+ <section>
+ <description>Special PNOR Test Space (36K)</description>
+ <eyeCatch>TESTRO</eyeCatch>
+ <physicalOffset>0x3599000</physicalOffset>
+ <physicalRegionSize>0x9000</physicalRegionSize>
+ <testonly/>
+ <sideless/>
+ <preserved/>
+ <readOnly/>
<ecc/>
</section>
<section>
@@ -166,6 +193,7 @@ Layout Description
<physicalOffset>0x3F67000</physicalOffset>
<physicalRegionSize>0x90000</physicalRegionSize>
<sha512Version/>
+ <sideless/>
<ecc/>
</section>
<section>
@@ -173,6 +201,7 @@ Layout Description
<eyeCatch>GLOBAL</eyeCatch>
<physicalOffset>0x3FF7000</physicalOffset>
<physicalRegionSize>0x9000</physicalRegionSize>
+ <sideless/>
<ecc/>
</section>
</pnor>
diff --git a/src/build/mkrules/hbfw/img/makefile b/src/build/mkrules/hbfw/img/makefile
index c0b09007c..925061e63 100755
--- a/src/build/mkrules/hbfw/img/makefile
+++ b/src/build/mkrules/hbfw/img/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2014
+# Contributors Listed Below - COPYRIGHT 2012,2015
# [+] International Business Machines Corp.
#
#
@@ -226,7 +226,7 @@ PNOR_BUILD_SCRIPT = ${buildpnor.pl:P}
#so need to use tryinclude for now.
.tryinclude <${.PATH:Ffips_pnor.mk}>
-HOSTBOOT_DEFAULT_SECTIONS = HBB=${BASE_W_HEADER_ECC_IMAGE},HBI=${EXT_ECC_HEADER_IMAGE},HBRT=${HBRT_ECC_HEADER_IMAGE},TEST=${TESTDATA_ECC},HBEL=${HBEL_ECC_IMAGE},GUARD=${GUARD_ECC_IMAGE},GLOBAL=${GLOBAL_ECC_IMAGE},PAYLOAD=${PAYLOAD_ECC_IMAGE},CVPD=${CVPD_ECC_IMAGE},MVPD=${MVPD_ECC_IMAGE},DJVPD=${DJVPD_ECC_IMAGE}
+HOSTBOOT_DEFAULT_SECTIONS = HBB=${BASE_W_HEADER_ECC_IMAGE},HBI=${EXT_ECC_HEADER_IMAGE},HBRT=${HBRT_ECC_HEADER_IMAGE},TEST=${TESTDATA_ECC},TESTRO=${TESTDATA_ECC},HBEL=${HBEL_ECC_IMAGE},GUARD=${GUARD_ECC_IMAGE},GLOBAL=${GLOBAL_ECC_IMAGE},PAYLOAD=${PAYLOAD_ECC_IMAGE},CVPD=${CVPD_ECC_IMAGE},MVPD=${MVPD_ECC_IMAGE},DJVPD=${DJVPD_ECC_IMAGE}
HBFW_OBJPATH = ${.PATH:M*obj*}
diff --git a/src/include/usr/hwas/hwasPlatDeconfigGard.H b/src/include/usr/hwas/hwasPlatDeconfigGard.H
index 4b89353fd..c439a4215 100644
--- a/src/include/usr/hwas/hwasPlatDeconfigGard.H
+++ b/src/include/usr/hwas/hwasPlatDeconfigGard.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012,2014 */
+/* Contributors Listed Below - COPYRIGHT 2012,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -30,6 +32,8 @@
#ifndef HWASPLATDECONFIGGARD_H_
#define HWASPLATDECONFIGGARD_H_
+#include <pnor/pnorif.H>
+
/**
* @brief Adapt common singleton declaration to specific platform
*
@@ -64,6 +68,19 @@ struct HBDeconfigGard
void *iv_pGardRecords; // Pointer to the GARD Records in PNOR
};
+/**
+ * @brief Gets iv_gardSectionInfo and sets it if first time called.
+ * Sets o_sectionInfo based on iv_gardSectionInfo for the caller
+ *
+ * @param[out] Guard PNOR section info
+ *
+ * @return errlHndl_t Error log handle, depending on config options will
+ * ignore error because no Guard section exists in PNOR
+ * (e.g. CONFIG_GOLDEN_PNOR_SIDE_SUPPORT)
+ *
+ */
+errlHndl_t getGardSectionInfo(PNOR::SectionInfo_t& o_sectionInfo);
+
} // namespace HWAS
#endif // HWASPLATDECONFIGGARD_H_
diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H
index a9854a4bc..4857c1b2c 100644
--- a/src/include/usr/pnor/pnor_reasoncodes.H
+++ b/src/include/usr/pnor/pnor_reasoncodes.H
@@ -136,6 +136,8 @@ namespace PNOR
RC_PNOR_READ_NOT_SUPPORTED = PNOR_COMP_ID | 0x1F,
RC_PNOR_WRITE_NOT_SUPPORTED = PNOR_COMP_ID | 0x20,
RC_NON_ECC_PROTECTED_SECTION = PNOR_COMP_ID | 0x21,
+ RC_WRITABLE_PERM_FAIL = PNOR_COMP_ID | 0x22,
+ RC_WRITE_TRACKED_PERM_FAIL = PNOR_COMP_ID | 0x23,
};
enum UserDetailsTypes
diff --git a/src/include/usr/pnor/pnorif.H b/src/include/usr/pnor/pnorif.H
index a9856f814..26890771a 100644
--- a/src/include/usr/pnor/pnorif.H
+++ b/src/include/usr/pnor/pnorif.H
@@ -29,6 +29,7 @@
#include <stdint.h>
#include <builtins.h>
#include <errl/errlentry.H>
+#include <utility>
namespace PNOR
{
@@ -61,6 +62,7 @@ enum SectionId
ATTR_PERM, /**< Permanent Attribute Override */
CAPP, /**< CAPP lid */
TEST, /**< Scratch space for PNOR test cases */
+ TESTRO, /**< Scratch space for PNOR ReadOnly test cases */
NUM_SECTIONS, /**< Number of defined sections */
@@ -82,7 +84,8 @@ struct SectionInfo_t
uint64_t size; /**< Size of partition in bytes */
bool eccProtected; /**< Section is ECC protected */
bool sha512Version; /**< Version Checking */
- bool sha512perEC; /**< Version Checking perEC */
+ bool sha512perEC; /**< Version Checking perEC */
+ bool readOnly; /**< Section is read only */
};
/**
@@ -121,6 +124,7 @@ errlHndl_t fixECC (SectionId i_section);
* true = PNOR DD is using L3 Cache for fake PNOR
* false = PNOR DD not using L3 Cache for fake PNOR
*/
+ bool usingL3Cache();
/**
* @brief Clears the specified PNOR section with all FF's (w/ good ECC)
@@ -131,8 +135,6 @@ errlHndl_t fixECC (SectionId i_section);
*/
errlHndl_t clearSection(PNOR::SectionId i_section);
-bool usingL3Cache();
-
/**
* @brief Validate the Alternative Master Processor's LPC
* Connection to PNOR
@@ -141,6 +143,14 @@ bool usingL3Cache();
*/
errlHndl_t validateAltMaster( void );
+//@ TODO RTC: 120061 add golden info
+//@ TODO RTC: 109703 make golden changes for informing OPAL
+struct TocInfo_t
+{
+ std::pair<uint64_t, uint64_t> activeTocOffsets;
+ std::pair<uint64_t, uint64_t> altTocOffsets;
+};
+
/** @brief PNOR::TEST section offsets for test cases to prevent
* concurrency problems
*/
@@ -150,6 +160,29 @@ enum TestSectionOffset{
pnorTestSec_rt_readwrite_offset = 0x6000,
};
+////////////////////////////////////////////////////////////////////////////////
+// SBE functionality that lives in PNOR
+
+// Used to keep track of perm/temp, and cur/alt
+enum sbeSeepromSide_t
+{
+ SBE_SEEPROM0 = 0x00, // corresponds to EEPROM::SBE_PRIMARY
+ SBE_SEEPROM1 = 0x01, // corresponts to EEPROM::SBE_BACKUP
+ SBE_SEEPROM_INVALID = 0xFF,
+};
+
+/**
+ * @brief Determines which Seeprom was used to boot the SBE
+ *
+ * @param[in] i_target Target processor to customize
+ *
+ * @param[out] o_bootSide The Seeprom the SBE booted from
+ *
+ * @return errlHndl_t Error log handle on failure.
+ */
+errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target,
+ sbeSeepromSide_t& o_bootSide);
+
}
#endif
diff --git a/src/usr/hwas/hwasPlatDeconfigGard.C b/src/usr/hwas/hwasPlatDeconfigGard.C
index 912f7d410..2911cf3c1 100644
--- a/src/usr/hwas/hwasPlatDeconfigGard.C
+++ b/src/usr/hwas/hwasPlatDeconfigGard.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -52,6 +52,15 @@ using namespace HWAS::COMMON;
using namespace TARGETING;
const uint32_t EMPTY_GARD_RECORDID = 0xFFFFFFFF;
+/**
+ * @brief Guard PNOR section info, obtained once for efficiency
+ */
+static PNOR::SectionInfo_t g_GardSectionInfo;
+
+/**
+ * @brief Flag indicating if getGardSectionInfo() was called previously
+ */
+static bool getGardSectionInfoCalled;
void _flush(void *i_addr);
errlHndl_t _GardRecordIdSetup(void *&io_platDeconfigGard);
@@ -90,7 +99,7 @@ errlHndl_t DeconfigGard::platClearGardRecords(
HWAS_MUTEX_LOCK(iv_mutex);
l_pErr = _GardRecordIdSetup(iv_platDeconfigGard);
- if (!l_pErr)
+ if (!l_pErr && iv_platDeconfigGard)
{
uint32_t l_gardRecordsCleared = 0;
HBDeconfigGard *l_hbDeconfigGard =
@@ -127,10 +136,6 @@ errlHndl_t DeconfigGard::platClearGardRecords(
HWAS_INF("GARD Records Cleared: %d", l_gardRecordsCleared);
}
- else
- {
- HWAS_ERR("Error from _GardRecordIdSetup");
- }
HWAS_MUTEX_UNLOCK(iv_mutex);
#endif // CONFIG_NO_GARD_SUPPORT
@@ -153,7 +158,7 @@ errlHndl_t DeconfigGard::platGetGardRecords(
HWAS_MUTEX_LOCK(iv_mutex);
l_pErr = _GardRecordIdSetup(iv_platDeconfigGard);
- if (!l_pErr)
+ if (!l_pErr && iv_platDeconfigGard)
{
HBDeconfigGard *l_hbDeconfigGard =
(HBDeconfigGard *)iv_platDeconfigGard;
@@ -183,10 +188,6 @@ errlHndl_t DeconfigGard::platGetGardRecords(
}
} // for
}
- else
- {
- HWAS_ERR("Error from _GardRecordIdSetup");
- }
HWAS_MUTEX_UNLOCK(iv_mutex);
HWAS_INF("Get returning %d GARD Records", o_records.size());
@@ -269,9 +270,8 @@ errlHndl_t DeconfigGard::platCreateGardRecord(
}
l_pErr = _GardRecordIdSetup(iv_platDeconfigGard);
- if (l_pErr)
+ if (l_pErr && iv_platDeconfigGard)
{
- HWAS_ERR("Error from _GardRecordIdSetup");
break;
}
@@ -394,20 +394,27 @@ errlHndl_t _GardRecordIdSetup( void *&io_platDeconfigGard)
break;
}
- // allocate our memory and set things up
- io_platDeconfigGard = malloc(sizeof(HBDeconfigGard));
- HBDeconfigGard *l_hbDeconfigGard =
- (HBDeconfigGard *)io_platDeconfigGard;
-
- // get the PNOR address.
+ // Get the PNOR Guard information
PNOR::SectionInfo_t l_section;
- l_pErr = PNOR::getSectionInfo(PNOR::GUARD_DATA, l_section);
+ l_pErr = getGardSectionInfo(l_section);
if (l_pErr)
{
- HWAS_ERR("PNOR::getSectionInfo failed!!!");
+ HWAS_ERR("_GardRecordIdSetup: getGardSectionInfo failed!!!");
// no support for GARD in this configuration.
break;
}
+ // Check if guard section exists, as certain configs ignore the above
+ // error (e.g. golden side has no GARD section)
+ if (l_section.size == 0)
+ {
+ HWAS_ERR("_GardRecordIdSetup: No guard section skipping function");
+ break;
+ }
+
+ // allocate our memory and set things up
+ io_platDeconfigGard = malloc(sizeof(HBDeconfigGard));
+ HBDeconfigGard *l_hbDeconfigGard =
+ (HBDeconfigGard *)io_platDeconfigGard;
l_hbDeconfigGard->iv_pGardRecords =
reinterpret_cast<DeconfigGard::GardRecord *> (l_section.vaddr);
@@ -466,4 +473,44 @@ void _flush(void *i_addr)
}
}
+errlHndl_t getGardSectionInfo(PNOR::SectionInfo_t& o_sectionInfo)
+{
+ errlHndl_t l_errl = NULL;
+ do
+ {
+ // getSectionInfo has already been called for GUARD_DATA
+ if(getGardSectionInfoCalled)
+ {
+ o_sectionInfo = g_GardSectionInfo;
+ break;
+ }
+
+ // Get Guard Section Info and set gardSectionInfo
+ l_errl = PNOR::getSectionInfo(PNOR::GUARD_DATA, g_GardSectionInfo);
+ if (l_errl)
+ {
+ g_GardSectionInfo.size = 0;
+// @TODO RTC: 120061 - replace config flag with a pnor interface call to say if
+// there is a guard section on the current (active) side
+// of pnor
+#ifdef CONFIG_TWO_SIDE_SUPPORT
+ HWAS_INF("getGardSectionInfo: No guard section disabling guard support");
+ l_errl = NULL;
+#else
+ HWAS_ERR("getGardSectionInfo:getSectionInfo failed");
+#endif
+ }
+ else
+ {
+ HWAS_INF("getGardSectionInfo: Section %s found, size %d",
+ g_GardSectionInfo.name, g_GardSectionInfo.size);
+ }
+
+ o_sectionInfo = g_GardSectionInfo;
+ getGardSectionInfoCalled = true;
+ } while(0);
+
+ return l_errl;
+}
+
} // namespace HWAS
diff --git a/src/usr/pnor/HBconfig b/src/usr/pnor/HBconfig
index 298144c8a..21082f4ea 100644
--- a/src/usr/pnor/HBconfig
+++ b/src/usr/pnor/HBconfig
@@ -37,3 +37,8 @@ config PNOR_IS_32MB
default n
help
Size of the attached flash chip is 32MB, if not set then 64MB is default
+
+config TWO_SIDE_SUPPORT
+ default n
+ help
+ This is used to turn on/off two sided pnor support
diff --git a/src/usr/pnor/common/ffs_hb.H b/src/usr/pnor/common/ffs_hb.H
index b63802158..c96911b3f 100644
--- a/src/usr/pnor/common/ffs_hb.H
+++ b/src/usr/pnor/common/ffs_hb.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012,2014 */
+/* Contributors Listed Below - COPYRIGHT 2012,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -25,7 +27,7 @@
/*
* FSP Destination: src/hbfw/fsp/pnor/common/ffs_hb.H
- *
+ *
* NOTE: Do NOT modify this file in CMVC directly! It comes from the Hostboot
* repository and will be overwritten.
*/
@@ -63,6 +65,7 @@ enum
/* Miscellaneous Bits : 1 byte */
FFS_MISC_PRESERVED = 0x80, /**< Preserved across code updates */
+ FFS_MISC_READ_ONLY = 0x40, /**< Read only section */
FFS_MISC_UNUSED = 0x1F, /**< Unused MISC Flags */
};
diff --git a/src/usr/pnor/makefile b/src/usr/pnor/makefile
index 31087a4b2..2f0a4e19b 100644
--- a/src/usr/pnor/makefile
+++ b/src/usr/pnor/makefile
@@ -32,6 +32,7 @@ OBJS += pnor_common.o
OBJS += pnorvalid.o
OBJS += ecc.o
OBJS += sfcdd.o
+OBJS += pnorsbe.o
#SFC Implementations
OBJS += $(if $(CONFIG_SFC_IS_IBM_DPSS),sfc_ibm.o)
diff --git a/src/usr/pnor/pnor_common.C b/src/usr/pnor/pnor_common.C
index e8972e2c4..00931ec64 100644
--- a/src/usr/pnor/pnor_common.C
+++ b/src/usr/pnor/pnor_common.C
@@ -24,14 +24,15 @@
/* IBM_PROLOG_END_TAG */
#include "pnor_common.H"
-#include <pnor/pnorif.H>
#include <pnor/pnor_reasoncodes.H>
#include "ffs.h" //Common header file with BuildingBlock.
#include "common/ffs_hb.H" //Hostboot def of user data in ffs_entry struct
+#include <sys/mm.h>
#include <initservice/initserviceif.H>
#include <util/align.H>
+#include <errl/errlmanager.H>
// Trace definition
trace_desc_t* g_trac_pnor = NULL;
@@ -45,28 +46,29 @@ TRAC_INIT(&g_trac_pnor, PNOR_COMP_NAME, 4*KILOBYTE, TRACE::BUFFER_SLOW); //4K
* Eyecatcher strings for PNOR TOC entries
*/
const char* cv_EYECATCHER[] = {
- "part", /**< PNOR::TOC : Table of Contents */
- "HBI", /**< PNOR::HB_EXT_CODE : Hostboot Extended Image */
- "GLOBAL", /**< PNOR::GLOBAL_DATA : Global Data */
- "HBB", /**< PNOR::HB_BASE_CODE : Hostboot Base Image */
- "SBEC", /**< PNOR::CENTAUR_SBE : Centaur Self-Boot Engine image */
- "SBE", /**< PNOR::SBE_IPL : Self-Boot Enginer IPL image */
- "WINK", /**< PNOR::WINK : Sleep Winkle Reference image */
- "PAYLOAD", /**< PNOR::PAYLOAD : HAL/OPAL */
- "HBRT", /**< PNOR::HB_RUNTIME : Hostboot Runtime (for Sapphire) */
- "HBD", /**< PNOR::HB_DATA : Hostboot Data */
- "GUARD", /**< PNOR::GUARD_DATA : Hostboot Data */
- "HBEL", /**< PNOR::HB_ERRLOGS : Hostboot Error log Repository */
- "DJVPD", /**< PNOR::DIMM_JEDEC_VPD : Dimm JEDEC VPD */
- "MVPD", /**< PNOR::MODULE_VPD : Module VPD */
- "CVPD", /**< PNOR::CENTAUR_VPD : Centaur VPD */
- "NVRAM", /**< PNOR::NVRAM : OPAL Storage */
- "OCC", /**< PNOR::OCC : OCC LID */
- "FIRDATA", /**< PNOR::FIRDATA : FIRDATA */
+ "part", /**< PNOR::TOC : Table of Contents */
+ "HBI", /**< PNOR::HB_EXT_CODE : Hostboot Extended Image */
+ "GLOBAL", /**< PNOR::GLOBAL_DATA : Global Data */
+ "HBB", /**< PNOR::HB_BASE_CODE : Hostboot Base Image */
+ "SBEC", /**< PNOR::CENTAUR_SBE : Centaur Self-Boot Engine image */
+ "SBE", /**< PNOR::SBE_IPL : Self-Boot Enginer IPL image */
+ "WINK", /**< PNOR::WINK : Sleep Winkle Reference image */
+ "PAYLOAD", /**< PNOR::PAYLOAD : HAL/OPAL */
+ "HBRT", /**< PNOR::HB_RUNTIME : Hostboot Runtime (for Sapphire) */
+ "HBD", /**< PNOR::HB_DATA : Hostboot Data */
+ "GUARD", /**< PNOR::GUARD_DATA : Hostboot Data */
+ "HBEL", /**< PNOR::HB_ERRLOGS : Hostboot Error log Repository */
+ "DJVPD", /**< PNOR::DIMM_JEDEC_VPD : Dimm JEDEC VPD */
+ "MVPD", /**< PNOR::MODULE_VPD : Module VPD */
+ "CVPD", /**< PNOR::CENTAUR_VPD : Centaur VPD */
+ "NVRAM", /**< PNOR::NVRAM : OPAL Storage */
+ "OCC", /**< PNOR::OCC : OCC LID */
+ "FIRDATA", /**< PNOR::FIRDATA : FIRDATA */
"ATTR_TMP", /**< PNOR::ATTR_TMP : Temporary Attribute Overrides */
"ATTR_PERM", /**< PNOR::ATTR_PERM : Permanent Attribute Overrides */
- "CAPP", /**< PNOR::CAPP : CAPP LID */
- "TEST", /**< PNOR::TEST : Test space for PNOR*/
+ "CAPP", /**< PNOR::CAPP : CAPP LID */
+ "TEST", /**< PNOR::TEST : Test space for PNOR*/
+ "TESTRO", /**< PNOR::TESTRO : ReadOnly Test space for PNOR */
//Not currently used
// "XXX", /**< NUM_SECTIONS : Used as invalid entry */
};
@@ -89,7 +91,7 @@ uint32_t PNOR::pnor_ffs_checksum(void* data, size_t size)
}
errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
- uint32_t & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr)
+ TOCS & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr)
{
TRACUCOMP(g_trac_pnor,"PNOR::parseTOC>");
errlHndl_t l_errhdl = NULL;
@@ -97,9 +99,10 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
bool TOC_0_failed = false;
do{
- o_TOC_used = 0;
+ o_TOC_used = TOC_0;
- for (uint32_t cur_TOC = 0; cur_TOC < NUM_TOCS; ++cur_TOC)
+ for (TOCS cur_TOC = TOC_0; cur_TOC < NUM_TOCS;
+ cur_TOC = (TOCS)(cur_TOC+1))
{
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC verifying TOC: %d",cur_TOC);
uint64_t nextVAddr = i_baseVAddr;
@@ -134,10 +137,10 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
{
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC TOC 0 failed header checksum");
TOC_0_failed = true;
- o_TOC_used = 1;
+ o_TOC_used = TOC_1;
continue;
}
- else if (cur_TOC == 1 && TOC_0_failed)
+ else if (cur_TOC == TOC_1 && TOC_0_failed)
{
// Both TOC's failed
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC both TOCs are corrupted");
@@ -164,7 +167,7 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
}
// Only check header if on first TOC or the first TOC failed
- if (cur_TOC == 0 || TOC_0_failed)
+ if (cur_TOC == TOC_0 || TOC_0_failed)
{
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: FFS Block size=0x%.8X,"
" Partition Table Size = 0x%.8x, entry_count=%d",
@@ -270,15 +273,15 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
// in SP-less config
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC pnor_ffs_checksum"
" entry checksums do not match");
- if (cur_TOC == 0)
+ if (cur_TOC == TOC_0)
{
TRACFCOMP(g_trac_pnor,"PNOR::parseTOC TOC 0 entry"
" checksum failed");
TOC_0_failed = true;
- o_TOC_used = 1;
+ o_TOC_used = TOC_1;
break;
}
- else if (cur_TOC == 1 && TOC_0_failed)
+ else if (cur_TOC == TOC_1 && TOC_0_failed)
{
// Both TOC's failed
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC both TOC's are"
@@ -306,7 +309,7 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
}
// Only set data if on first TOC or the first TOC failed
- if (cur_TOC == 0 || TOC_0_failed)
+ if (cur_TOC == TOC_0 || TOC_0_failed)
{
//Figure out section enum
for(uint32_t eyeIndex=PNOR::TOC;eyeIndex<PNOR::NUM_SECTIONS;
@@ -393,25 +396,120 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
0, 0, true);
break;
}
+
+# ifndef __HOSTBOOT_RUNTIME
+ // Handle section permissions
+ if (o_TOC[secId].misc & FFS_MISC_READ_ONLY)
+ {
+ // Need to set permissions to allow writing to virtual
+ // addresses, but prevents the kernel from ejecting
+ // dirty pages (no WRITE_TRACKED).
+ int rc = mm_set_permission(
+ (void*)o_TOC[secId].virtAddr,
+ o_TOC[secId].size,
+ WRITABLE);
+ if (rc)
+ {
+ TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC: Failed to set block permissions to WRITABLE for section %s.",
+ cv_EYECATCHER[secId]);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_READTOC
+ * @reasoncode PNOR::RC_WRITABLE_PERM_FAIL
+ * @userdata1 PNOR section id
+ * @userdata2 PNOR section vaddr
+ * @devdesc Could not set permissions of the
+ * given PNOR section to WRITABLE
+ * @custdesc A problem occurred while reading PNOR partition table
+ */
+ l_errhdl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_READTOC,
+ PNOR::RC_WRITABLE_PERM_FAIL,
+ secId,
+ o_TOC[secId].virtAddr,
+ true /*Add HB SW Callout*/);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ }
+ }
+ else
+ {
+ // Need to set permissions to R/W
+ int rc = mm_set_permission(
+ (void*)o_TOC[secId].virtAddr,
+ o_TOC[secId].size,
+ WRITABLE | WRITE_TRACKED);
+ if (rc)
+ {
+ TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC: Failed to set block permissions to WRITABLE/WRITE_TRACKED for section %s.",
+ cv_EYECATCHER[secId]);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_READTOC
+ * @reasoncode PNOR::RC_WRITE_TRACKED_PERM_FAIL
+ * @userdata1 PNOR section id
+ * @userdata2 PNOR section vaddr
+ * @devdesc Could not set permissions of the
+ * given PNOR section to
+ * WRITABLE/WRITE_TRACKED
+ * @custdesc A problem occurred while reading
+ * PNOR partition table
+ */
+ l_errhdl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_READTOC,
+ PNOR::RC_WRITE_TRACKED_PERM_FAIL,
+ secId,
+ o_TOC[secId].virtAddr,
+ true /*Add HB SW Callout*/);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ }
+ }
+#endif
+ if( l_errhdl )
+ {
+ // If both toc0 and toc1 fail break and return the error
+ if ( (cur_TOC == TOC_1) && (TOC_0_failed) )
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC readFromDevice Failed on both TOCs");
+ break;
+ }
+
+ // Toc 1 has not been read yet or Toc 0 was read
+ // successfully
+ // Commit error and break to continue checking the next
+ // TOC
+ else
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC readFromDevice Failed on TOC %d, commit error",
+ cur_TOC);
+ errlCommit(l_errhdl,PNOR_COMP_ID);
+ l_errhdl = NULL;
+ break;
+ }
+ }
}
- }
+ } // For TOC Entries
if (l_errhdl)
{
- TRACFCOMP(g_trac_pnor, ERR_MRK"PNOR::parseTOC: error parsing");
break;
}
-
- for(PNOR::SectionId tmpId = PNOR::FIRST_SECTION;
- tmpId < PNOR::NUM_SECTIONS;
- tmpId = (PNOR::SectionId) (tmpId + 1) )
- {
- TRACFCOMP(g_trac_pnor, "%s: size=0x%.8X flash=0x%.8X "
- "virt=0x%.16X", cv_EYECATCHER[tmpId], o_TOC[tmpId].size,
- o_TOC[tmpId].flashAddr, o_TOC[tmpId].virtAddr );
- }
+ } // For TOC's
+ if (l_errhdl)
+ {
+ break;
}
} while(0);
+ for(PNOR::SectionId tmpId = PNOR::FIRST_SECTION;
+ tmpId < PNOR::NUM_SECTIONS;
+ tmpId = (PNOR::SectionId) (tmpId + 1) )
+ {
+ TRACFCOMP(g_trac_pnor, "%s: size=0x%.8X flash=0x%.8X "
+ "virt=0x%.16X", cv_EYECATCHER[tmpId], o_TOC[tmpId].size,
+ o_TOC[tmpId].flashAddr, o_TOC[tmpId].virtAddr );
+ }
+
TRACUCOMP(g_trac_pnor, "< PNOR::parseTOC" );
return l_errhdl;
}
diff --git a/src/usr/pnor/pnor_common.H b/src/usr/pnor/pnor_common.H
index 3944e27fa..5eb893412 100644
--- a/src/usr/pnor/pnor_common.H
+++ b/src/usr/pnor/pnor_common.H
@@ -41,11 +41,22 @@ namespace PNOR {
uint8_t misc; /**< Misc Flags */
} PACKED;
+ // Simple enum of TOC's per PNOR side
+ enum TOCS
+ {
+ TOC_0 = 0,
+ TOC_1 = 1,
+ NUM_TOCS,
+ };
+
enum
{
- NUM_TOCS = 2,
- TOC_0_OFFSET = 0,
- TOC_1_OFFSET = 0x8000,
+ // @TODO RTC: 120061 - Determine TOC locations
+ // TOC offsets based on pnor layout
+ SIDE_A_TOC_0_OFFSET = 0,
+ SIDE_A_TOC_1_OFFSET = 0x8000,
+ SIDE_B_TOC_0_OFFSET = 0x2000000,
+ SIDE_B_TOC_1_OFFSET = 0x2008000,
/** Real number of bytes required to read 1 logical page */
PAGESIZE_PLUS_ECC = ((PAGESIZE * 9)/8), // 8B data + 1B of ECC
@@ -79,7 +90,7 @@ namespace PNOR {
* @return Error
*/
errlHndl_t parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
- uint32_t & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr);
+ TOCS & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr);
}
#endif
diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C
index 299a063f4..aeaeb222a 100644
--- a/src/usr/pnor/pnorrp.C
+++ b/src/usr/pnor/pnorrp.C
@@ -44,6 +44,7 @@
#include <endian.h>
#include <util/align.H>
#include <config.h>
+#include "pnor_common.H"
extern trace_desc_t* g_trac_pnor;
@@ -192,7 +193,9 @@ void* wait_for_message( void* unused )
* @brief Constructor
*/
PnorRP::PnorRP()
-: iv_TOC_used(0)
+: iv_activeTocOffsets(SIDE_A_TOC_0_OFFSET,SIDE_A_TOC_1_OFFSET)
+,iv_altTocOffsets(SIDE_B_TOC_0_OFFSET,SIDE_B_TOC_1_OFFSET)
+,iv_TOC_used(TOC_0)
,iv_msgQ(NULL)
,iv_startupRC(0)
{
@@ -231,12 +234,28 @@ void PnorRP::initDaemon()
do
{
- // read the TOC in the PNOR to compute the sections
- l_errhdl = readTOC();
- if( l_errhdl )
+ // @TODO RTC: 120062 - Determine which side is Golden
+ // Default TOC offsets set to side A. If two side support is enabled,
+ // check which SEEPROM hostboot booted from
+#ifdef CONFIG_TWO_SIDE_SUPPORT
+ TARGETING::Target* pnor_target = TARGETING::
+ MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ // Get correct TOC
+ PNOR::sbeSeepromSide_t l_bootSide;
+ PNOR::getSbeBootSeeprom(pnor_target, l_bootSide);
+ if (l_bootSide == PNOR::SBE_SEEPROM1)
{
- break;
+ TRACFCOMP( g_trac_pnor, "PnorRP::initDaemon> Booting from Side B");
+ iv_activeTocOffsets.first = SIDE_B_TOC_0_OFFSET;
+ iv_activeTocOffsets.second = SIDE_B_TOC_1_OFFSET;
+ iv_altTocOffsets.first = SIDE_A_TOC_0_OFFSET;
+ iv_altTocOffsets.second = SIDE_A_TOC_0_OFFSET;
}
+ else
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRP::initDaemon> Booting from Side A");
+ }
+#endif
// create a message queue
iv_msgQ = msg_q_create();
@@ -253,7 +272,7 @@ void PnorRP::initDaemon()
* @userdata1 Requested Address
* @userdata2 rc from mm_alloc_block
* @devdesc PnorRP::initDaemon> Error from mm_alloc_block
- * @custdesc A problem occurred while accessing the boot flash.
+ * @custdesc A problem occurred while accessing the boot flash.
*/
l_errhdl = new ERRORLOG::ErrlEntry(
ERRORLOG::ERRL_SEV_UNRECOVERABLE,
@@ -270,9 +289,14 @@ void PnorRP::initDaemon()
INITSERVICE::registerBlock(reinterpret_cast<void*>(BASE_VADDR),
TOTAL_SIZE,PNOR_PRIORITY);
- // Need to set permissions to R/W
- rc = mm_set_permission((void*) BASE_VADDR,TOTAL_SIZE,
- WRITABLE | WRITE_TRACKED);
+ // Read the TOC in the PNOR to compute the sections and set their
+ // correct permissions
+ l_errhdl = readTOC();
+ if( l_errhdl )
+ {
+ TRACFCOMP(g_trac_pnor, ERR_MRK"PnorRP::initDaemon: Failed to readTOC");
+ break;
+ }
// start task to wait on the queue
task_create( wait_for_message, NULL );
@@ -319,7 +343,7 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section,
* @userdata1 Requested Section
* @userdata2 Startup RC
* @devdesc PnorRP::getSectionInfo> RP not properly initialized
- * @custdesc A problem occurred while accessing the boot flash.
+ * @custdesc A problem occurred while accessing the boot flash.
*/
l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_PNORRP_GETSECTIONINFO,
@@ -346,7 +370,7 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section,
* @userdata1 Requested Section
* @userdata2 TOC used
* @devdesc PnorRP::getSectionInfo> Invalid Address for read/write
- * @custdesc A problem occurred while accessing the boot flash.
+ * @custdesc A problem occurred while accessing the boot flash.
*/
l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_PNORRP_GETSECTIONINFO,
@@ -378,12 +402,13 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section,
!= 0) ? true : false;
o_info.sha512perEC = ((iv_TOC[id].version & FFS_VERS_SHA512_PER_EC)
!= 0) ? true : false;
+ o_info.readOnly = ((iv_TOC[id].misc & FFS_MISC_READ_ONLY)
+ != 0) ? true : false;
}
return l_errhdl;
}
-
/**
* @brief Read the TOC and store section information
*/
@@ -395,7 +420,7 @@ errlHndl_t PnorRP::readTOC()
uint8_t* toc1Buffer = new uint8_t[PAGESIZE];
uint64_t fatal_error = 0;
do {
- l_errhdl = readFromDevice( TOC_0_OFFSET, 0, false,
+ l_errhdl = readFromDevice( iv_activeTocOffsets.first, 0, false,
toc0Buffer, fatal_error );
if (l_errhdl)
{
@@ -403,7 +428,7 @@ errlHndl_t PnorRP::readTOC()
break;
}
- l_errhdl = readFromDevice( TOC_1_OFFSET, 0, false,
+ l_errhdl = readFromDevice( iv_activeTocOffsets.second, 0, false,
toc1Buffer, fatal_error );
if (l_errhdl)
{
@@ -412,7 +437,7 @@ errlHndl_t PnorRP::readTOC()
}
l_errhdl = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC,
- BASE_VADDR);
+ BASE_VADDR);
if (l_errhdl)
{
TRACFCOMP(g_trac_pnor, "readTOC: parseTOC failed");
@@ -737,59 +762,63 @@ errlHndl_t PnorRP::computeDeviceAddr( void* i_vaddr,
o_chip = 99;
uint64_t l_vaddr = (uint64_t)i_vaddr;
- // make sure this is one of our addresses
- if( !((l_vaddr >= BASE_VADDR)
- && (l_vaddr < LAST_VADDR)) )
+ do
{
- TRACFCOMP( g_trac_pnor, "PnorRP::computeDeviceAddr> Virtual Address outside known PNOR range : i_vaddr=%p", i_vaddr );
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE
- * @reasoncode PNOR::RC_INVALID_ADDRESS
- * @userdata1 Virtual Address
- * @userdata2 Base PNOR Address
- * @devdesc PnorRP::computeDeviceAddr> Virtual Address outside
- * known PNOR range
- * @custdesc A problem occurred while accessing the boot flash.
- */
- l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORRP_COMPUTEDEVICEADDR,
- PNOR::RC_INVALID_ADDRESS,
- l_vaddr,
- BASE_VADDR,
- true /*Add HB SW Callout*/);
- l_errhdl->collectTrace(PNOR_COMP_NAME);
- return l_errhdl;
- }
+ // make sure this is one of our addresses
+ if( !((l_vaddr >= BASE_VADDR)
+ && (l_vaddr < LAST_VADDR)) )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRP::computeDeviceAddr> Virtual Address outside known PNOR range : i_vaddr=%p", i_vaddr );
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE
+ * @reasoncode PNOR::RC_INVALID_ADDRESS
+ * @userdata1 Virtual Address
+ * @userdata2 Base PNOR Address
+ * @devdesc PnorRP::computeDeviceAddr> Virtual Address outside
+ * known PNOR range
+ * @custdesc A problem occurred while accessing the boot flash.
+ */
+ l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_COMPUTEDEVICEADDR,
+ PNOR::RC_INVALID_ADDRESS,
+ l_vaddr,
+ BASE_VADDR,
+ true /*Add HB SW Callout*/);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ break;
+ }
- // find the matching section
- PNOR::SectionId id = PNOR::INVALID_SECTION;
- l_errhdl = computeSection( l_vaddr, id );
- if( l_errhdl )
- {
- return l_errhdl;
- }
+ // find the matching section
+ PNOR::SectionId id = PNOR::INVALID_SECTION;
+ l_errhdl = computeSection( l_vaddr, id );
+ if( l_errhdl )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRP::computeDeviceAddr> Virtual address does not match any pnor sections : i_vaddr=%p", i_vaddr );
+ break;
+ }
- // pull out the information we need to return from our global copy
- o_chip = iv_TOC[id].chip;
- o_ecc = (bool)(iv_TOC[id].integrity & FFS_INTEG_ECC_PROTECT);
- o_offset = l_vaddr - iv_TOC[id].virtAddr; //offset into section
+ // pull out the information we need to return from our global copy
+ o_chip = iv_TOC[id].chip;
+ o_ecc = (bool)(iv_TOC[id].integrity & FFS_INTEG_ECC_PROTECT);
+ o_offset = l_vaddr - iv_TOC[id].virtAddr; //offset into section
- // for ECC we need to figure out where the ECC-enhanced offset is
- // before tacking on the offset to the section
- if( o_ecc )
- {
- o_offset = (o_offset * 9) / 8;
- }
- // add on the offset of the section itself
- o_offset += iv_TOC[id].flashAddr;
+ // for ECC we need to figure out where the ECC-enhanced offset is
+ // before tacking on the offset to the section
+ if( o_ecc )
+ {
+ o_offset = (o_offset * 9) / 8;
+ }
+ // add on the offset of the section itself
+ o_offset += iv_TOC[id].flashAddr;
+ } while(0);
TRACUCOMP( g_trac_pnor, "< PnorRP::computeDeviceAddr: i_vaddr=%X, o_offset=0x%X, o_chip=%d", l_vaddr, o_offset, o_chip );
return l_errhdl;
}
/**
- * @brief Static instance function for testcase only
+ * @brief Static instance function
*/
PnorRP& PnorRP::getInstance()
{
@@ -987,3 +1016,10 @@ errlHndl_t PnorRP::fixECC (PNOR::SectionId i_section)
TRACFCOMP(g_trac_pnor, EXIT_MRK"PnorRP::fixECC");
return l_err;
}
+
+uint64_t PnorRP::getTocOffset(TOCS i_toc) const
+{
+ // Can use a ternary operator because there are only 2 TOCs per side
+ return (i_toc == TOC_0) ? iv_activeTocOffsets.first :
+ iv_activeTocOffsets.second;
+}
diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H
index 3703afe8a..509cf1436 100644
--- a/src/usr/pnor/pnorrp.H
+++ b/src/usr/pnor/pnorrp.H
@@ -76,9 +76,18 @@ class PnorRP
*/
errlHndl_t fixECC(PNOR::SectionId i_section);
+ /**
+ * @brief Get TOC offset of specified TOC on active side
+ *
+ * @param[in] i_toc TOC offset desired on active side
+ *
+ * @return uint64_t TOC offset
+ */
+ uint64_t getTocOffset(PNOR::TOCS i_toc) const;
+
protected:
/**
- * @brief Constructor
+ * @brief Constructor, default TOC offsets to side A
*/
PnorRP();
@@ -89,16 +98,23 @@ class PnorRP
private:
+
+ // TOC 0 and 1 offsets of both PNOR sides. The active PNOR side determined
+ // by the Seeprom the SBE booted from
+ std::pair<uint64_t, uint64_t> iv_activeTocOffsets;
+ std::pair<uint64_t, uint64_t> iv_altTocOffsets;
+
enum
{
BASE_VADDR = VMM_VADDR_PNOR_RP, /**< 2GB = 0x80000000*/
TOTAL_SIZE = 64*MEGABYTE, /**< Allocate 64 MB (0x4000000)*/
LAST_VADDR = BASE_VADDR + TOTAL_SIZE, /**< End of our VA range */
};
+
/**
* Which TOC (0 or 1) is used after verifying both.
*/
- uint32_t iv_TOC_used;
+ PNOR::TOCS iv_TOC_used;
/**
* Flash statistics
@@ -138,7 +154,8 @@ class PnorRP
/**
* @brief Verify both TOC's and store section information from one of the
- * verified TOC's
+ * verified TOC's. Additionally set each section permissions
+ * (e.g. readOnly)
*
* @return Error from device
*/
@@ -224,7 +241,6 @@ class PnorRP
return false;
};
-
// allow local helper function to call private methods
friend void* wait_for_message( void* unused );
@@ -237,7 +253,7 @@ class PnorRP
friend errlHndl_t PNOR::validateAltMaster( void );
/**
- * @brief Static instance function for testcase only
+ * @brief Static instance function
*/
static PnorRP& getInstance();
};
diff --git a/src/usr/pnor/pnorsbe.C b/src/usr/pnor/pnorsbe.C
new file mode 100644
index 000000000..0b6117313
--- /dev/null
+++ b/src/usr/pnor/pnorsbe.C
@@ -0,0 +1,87 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnorsbe.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file pnorsbe.C
+ *
+ * @brief Implements PNOR::getSbeBootSeeprom(), which Determines which
+ * Seeprom was used to boot the SB
+ */
+
+#include <pnor/pnorif.H>
+#include <trace/interface.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <devicefw/userif.H>
+
+extern trace_desc_t* g_trac_pnor;
+
+namespace PNOR
+{
+
+//Used to read SBE Boot Side from processor
+const uint64_t SBE_VITAL_REG_0x0005001C = 0x005001C;
+const uint64_t SBE_BOOT_SELECT_MASK = 0x0080000000000000;
+
+errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target,
+ sbeSeepromSide_t& o_bootSide)
+{
+ TRACFCOMP( g_trac_pnor, ENTER_MRK"PNOR::getSbeBootSeeprom()" );
+
+ errlHndl_t err = NULL;
+ uint64_t scomData = 0x0;
+
+ o_bootSide = SBE_SEEPROM0;
+
+ do{
+
+ size_t op_size = sizeof(scomData);
+ err = deviceRead( i_target,
+ &scomData,
+ op_size,
+ DEVICE_SCOM_ADDRESS(SBE_VITAL_REG_0x0005001C) );
+ if( err )
+ {
+ TRACFCOMP( g_trac_pnor, ERR_MRK"PNOR::getSbeBootSeeprom() -Error "
+ "reading SBE VITAL REG (0x%.8X) from Target :"
+ "HUID=0x%.8X",
+ SBE_VITAL_REG_0x0005001C,
+ TARGETING::get_huid(i_target));
+ break;
+ }
+ if(scomData & SBE_BOOT_SELECT_MASK)
+ {
+ o_bootSide = SBE_SEEPROM1;
+ }
+
+ }while(0);
+
+ TRACFCOMP( g_trac_pnor,
+ EXIT_MRK"PNOR::getSbeBootSeeprom(): o_bootSide=0x%X (reg=0x%X)",
+ o_bootSide, scomData );
+
+ return err;
+}
+
+} // end namespace \ No newline at end of file
diff --git a/src/usr/pnor/pnorvalid.C b/src/usr/pnor/pnorvalid.C
index 1bc09a2fa..46204caac 100644
--- a/src/usr/pnor/pnorvalid.C
+++ b/src/usr/pnor/pnorvalid.C
@@ -102,7 +102,7 @@ errlHndl_t validateAltMaster( void )
// When reading PNOR TOC assume a single page and no ECC
uint8_t* tocBuffer = new uint8_t[PAGESIZE];
size_t read_size = PAGESIZE;
- const uint64_t toc0_offset = PNOR::TOC_0_OFFSET;
+ const uint64_t toc0_offset = PnorRP::getInstance().getTocOffset(TOC_0);
do{
@@ -176,8 +176,7 @@ errlHndl_t validateAltMaster( void )
pnordd = new PnorDD(procList[i]);
// Read Flash
- l_err = pnordd->readFlash(tocBuffer, read_size,
- PNOR::TOC_0_OFFSET);
+ l_err = pnordd->readFlash(tocBuffer, read_size, toc0_offset);
if ( l_err )
{
// Commit Error Log, but continue the test
diff --git a/src/usr/pnor/runtime/rt_pnor.C b/src/usr/pnor/runtime/rt_pnor.C
index c43160f44..c61aa1d2d 100644
--- a/src/usr/pnor/runtime/rt_pnor.C
+++ b/src/usr/pnor/runtime/rt_pnor.C
@@ -297,7 +297,7 @@ errlHndl_t RtPnor::flush( PNOR::SectionId i_section)
}
/*******Protected Methods**************/
RtPnor::RtPnor()
-:iv_TOC_used(0)
+:iv_TOC_used(PNOR::TOC_0)
{
errlHndl_t l_err = readTOC();
if (l_err)
@@ -588,7 +588,10 @@ errlHndl_t RtPnor::readTOC ()
break;
}
- l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::TOC_0_OFFSET,
+ // @TODO RTC:120733
+ // RT code needs a way to get the active side tocs vs just defaulting
+ // to SIDE_A
+ l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::SIDE_A_TOC_0_OFFSET,
PAGESIZE,false,toc0Buffer);
if (l_err)
{
@@ -596,7 +599,7 @@ errlHndl_t RtPnor::readTOC ()
" for TOC0");
break;
}
- l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::TOC_1_OFFSET,
+ l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::SIDE_A_TOC_1_OFFSET,
PAGESIZE, false,toc1Buffer);
if (l_err)
{
@@ -605,7 +608,7 @@ errlHndl_t RtPnor::readTOC ()
break;
}
- l_err = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC,0);
+ l_err = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC, 0);
if (l_err)
{
TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: parseTOC failed");
diff --git a/src/usr/pnor/runtime/rt_pnor.H b/src/usr/pnor/runtime/rt_pnor.H
index 43041fc3f..f3a03a5ec 100644
--- a/src/usr/pnor/runtime/rt_pnor.H
+++ b/src/usr/pnor/runtime/rt_pnor.H
@@ -81,7 +81,7 @@ class RtPnor
/**
* Which TOC (0 or 1) is used after verifying both.
*/
- uint32_t iv_TOC_used;
+ PNOR::TOCS iv_TOC_used;
/**
* Cached copy of section data
diff --git a/src/usr/pnor/test/pnorrptest.H b/src/usr/pnor/test/pnorrptest.H
index 04ca72916..427227bf7 100644
--- a/src/usr/pnor/test/pnorrptest.H
+++ b/src/usr/pnor/test/pnorrptest.H
@@ -517,22 +517,30 @@ class PnorRpTest : public CxxTest::TestSuite
uint8_t* corruptBuffer = new uint8_t[PAGESIZE];
// Corrupt both ffs header and first entry for each TOC
- for (uint32_t cur_TOC = 0; cur_TOC < PNOR::NUM_TOCS; ++cur_TOC)
+ for (PNOR::TOCS cur_TOC = PNOR::TOC_0; cur_TOC < PNOR::NUM_TOCS;
+ cur_TOC = (PNOR::TOCS)(cur_TOC+1))
{
- uint32_t TOC_used = cur_TOC;
+ PNOR::TOCS TOC_used = cur_TOC;
if (cur_TOC == 0)
{
- offset = PNOR::TOC_0_OFFSET;
+ offset = PnorRP::getInstance().getTocOffset(PNOR::TOC_0);
}
else
{
- offset = PNOR::TOC_1_OFFSET;
+ offset = PnorRP::getInstance().getTocOffset(PNOR::TOC_1);
}
// Read cur_TOC header data
- PnorRP::getInstance().readFromDevice( offset, 0, false, tocHeader,
- fatal_error );
+ PnorRP::getInstance().readFromDevice( offset, 0, false,
+ tocHeader, fatal_error );
+ if (fatal_error)
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_TOC> ERROR : Could not read TOC header data at offset 0x%X RC=%X",
+ offset, fatal_error);
+ TS_FAIL("PnorRpTest::test_TOC> ERROR : Could not read TOC header data at offset 0x%X RC=%X",
+ offset, fatal_error);
+ }
// Corrupt cur_TOC header data
memcpy(corruptBuffer, tocHeader, PAGESIZE);
@@ -559,6 +567,13 @@ class PnorRpTest : public CxxTest::TestSuite
PnorRP::getInstance().readFromDevice( offset + FFS_HDR_SIZE, 0,
false, tocEntry,
fatal_error );
+ if (fatal_error)
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_TOC> ERROR : Could not read first TOC entry data at offset 0x%X RC=%X",
+ offset, fatal_error);
+ TS_FAIL("PnorRpTest::test_TOC> ERROR : Could not read first TOC entry data at offset 0x%X RC=%X",
+ offset, fatal_error);
+ }
// Corrupt cur_TOC header data
memcpy(corruptBuffer, tocEntry, PAGESIZE);
@@ -591,6 +606,83 @@ class PnorRpTest : public CxxTest::TestSuite
TRACFCOMP(g_trac_pnor, "PnorRpTest::test_TOC End");
}
+ /**
+ * @brief PNOR RP test - ReadOnlyTag
+ * Tests if readOnly tag on a section is being processed correctly
+ *
+ */
+ void test_ReadOnlyTag(void)
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag Start" );
+ PNOR::SectionInfo_t l_info;
+ errlHndl_t l_errhdl = NULL;
+ uint64_t chip_select = 0xF;
+ bool needs_ecc = false;
+
+ l_errhdl = PNOR::getSectionInfo(PNOR::TESTRO, l_info);
+ if( l_errhdl )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> ERROR : getSectionInfo returned error for %d : RC=%X",
+ PNOR::TESTRO, l_errhdl->reasonCode());
+ ERRORLOG::errlCommit(l_errhdl, PNOR_COMP_ID);
+ TS_FAIL( "PnorRpTest::test_ReadOnlyTag> ERROR : could not read pnor section %d", PNOR::TESTRO);
+ }
+
+ // Write some data
+ const uint64_t l_writeData = 0x1122334455667788;
+ uint64_t* l_dataptr = reinterpret_cast<uint64_t*> (l_info.vaddr);
+ l_dataptr[0] = l_writeData;
+
+ // Flush the page to make sure it gets out to the device
+ // Due to ReadOnly permissions set on TESTRO should be a no-op
+ int rc = mm_remove_pages( RELEASE, l_dataptr, PAGESIZE );
+ if( rc )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> ERROR : error on RELEASE : rc=%X", rc );
+ TS_FAIL( "PnorRpTest::test_ReadOnlyTag> ERROR : error on RELEASE" );
+ }
+
+ // Get physical address of pnor section
+ uint64_t l_address = 0;
+ l_errhdl = PnorRP::getInstance().computeDeviceAddr((void*)l_info.vaddr,
+ l_address,
+ chip_select,
+ needs_ecc);
+ if(l_errhdl)
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> ERROR : computeDeviceAddr vaddr = 0x%X",l_info.vaddr);
+ errlCommit(l_errhdl,PNOR_COMP_ID);
+ TS_FAIL( "PnorRpTest::test_ReadOnlyTag> ERROR : computeDeviceAddr vaddr = 0x%X",l_info.vaddr);
+ }
+
+ // Read pnor section and check if write did not occur
+ uint64_t l_readData = 0;
+ size_t l_size = sizeof(uint64_t);
+ l_errhdl = deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &l_readData,
+ l_size,
+ DEVICE_PNOR_ADDRESS(0, l_address));
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> Read Data = 0x%X",l_readData);
+ if(l_errhdl)
+ {
+ TS_FAIL("PnorRpTest::test_ReadOnlyTag: deviceRead() failed! Error committed.");
+ ERRORLOG::errlCommit(l_errhdl, PNOR_COMP_ID);
+ }
+ if(l_readData == l_writeData)
+ {
+ TS_FAIL("PnorRpTest::test_ReadOnlyTag: Data was written to readOnly section = %s",
+ l_info.name);
+ }
+ if(l_size != sizeof(uint64_t))
+ {
+ TS_FAIL("PnorRpTest::test_ReadOnlyTag: deviceRead() Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d",
+ l_address, sizeof(uint64_t), l_size);
+ }
+
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag End");
+ }
+
+
//@todo - import config data from build and compare to section info
/**
diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C
index 9dd9e0a6f..698d41a8c 100644
--- a/src/usr/sbe/sbe_update.C
+++ b/src/usr/sbe/sbe_update.C
@@ -1214,49 +1214,6 @@ namespace SBE
}
/////////////////////////////////////////////////////////////////////
- errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target,
- sbeSeepromSide_t& o_bootSide)
- {
- TRACUCOMP( g_trac_sbe,
- ENTER_MRK"getSbeBootSeeprom()" );
-
- errlHndl_t err = NULL;
- uint64_t scomData = 0x0;
-
- o_bootSide = SBE_SEEPROM0;
-
- do{
-
- size_t op_size = sizeof(scomData);
- err = deviceRead( i_target,
- &scomData,
- op_size,
- DEVICE_SCOM_ADDRESS(SBE_VITAL_REG_0x0005001C) );
- if( err )
- {
- TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeBootSeeprom() -Error "
- "reading SBE VITAL REG (0x%.8X) from Target :"
- "HUID=0x%.8X",
- SBE_VITAL_REG_0x0005001C,
- TARGETING::get_huid(i_target));
- break;
- }
- if(scomData & SBE_BOOT_SELECT_MASK)
- {
- o_bootSide = SBE_SEEPROM1;
- }
-
- }while(0);
-
- TRACUCOMP( g_trac_sbe,
- EXIT_MRK"getSbeBootSeeprom(): o_bootSide=0x%X (reg=0x%X)",
- o_bootSide, scomData );
-
- return err;
- }
-
-
-/////////////////////////////////////////////////////////////////////
errlHndl_t getSbeInfoState(sbeTargetState_t& io_sbeState)
{
@@ -1351,11 +1308,11 @@ namespace SBE
if(SEEPROM_0_PERMANENT_VALUE ==
(io_sbeState.mvpdSbKeyword.flags & PERMANENT_FLAG_MASK))
{
- io_sbeState.permanent_seeprom_side = SBE_SEEPROM0;
+ io_sbeState.permanent_seeprom_side = PNOR::SBE_SEEPROM0;
}
else // Side 1 must be permanent
{
- io_sbeState.permanent_seeprom_side = SBE_SEEPROM1;
+ io_sbeState.permanent_seeprom_side = PNOR::SBE_SEEPROM1;
}
@@ -1404,21 +1361,21 @@ namespace SBE
/* Determine which SEEPROM System Booted On */
/***********************************************/
//Get Current (boot) Side
- sbeSeepromSide_t tmp_cur_side = SBE_SEEPROM_INVALID;
- err = getSbeBootSeeprom(io_sbeState.target, tmp_cur_side);
+ PNOR::sbeSeepromSide_t tmp_cur_side = PNOR::SBE_SEEPROM_INVALID;
+ err = PNOR::getSbeBootSeeprom(io_sbeState.target, tmp_cur_side);
if(err)
{
TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error returned from getSbeBootSeeprom()");
break;
}
io_sbeState.cur_seeprom_side = tmp_cur_side;
- if (io_sbeState.cur_seeprom_side == SBE_SEEPROM0)
+ if (io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0)
{
- io_sbeState.alt_seeprom_side = SBE_SEEPROM1;
+ io_sbeState.alt_seeprom_side = PNOR::SBE_SEEPROM1;
}
- else if ( io_sbeState.cur_seeprom_side == SBE_SEEPROM1)
+ else if ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM1)
{
- io_sbeState.alt_seeprom_side = SBE_SEEPROM0;
+ io_sbeState.alt_seeprom_side = PNOR::SBE_SEEPROM0;
}
else
{
@@ -2055,7 +2012,7 @@ namespace SBE
/* Determine what side to update */
/**************************************************************/
// Set cur and alt isDirty values
- if( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 )
+ if( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 )
{
current_side_isDirty = seeprom_0_isDirty;
alt_side_isDirty = seeprom_1_isDirty;
@@ -2222,14 +2179,14 @@ namespace SBE
io_sbeState.seeprom_side_to_update = EEPROM::SBE_PRIMARY;
// Update MVPD PERMANENT flag: make cur=perm
- ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ?
+ ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 0
io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK
: //set bit 0
io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK;
// Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT:
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ?
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 1
io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK
: //set bit 1
@@ -2295,18 +2252,18 @@ namespace SBE
// Set Update side to alt
io_sbeState.seeprom_side_to_update =
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 )
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 )
? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ;
// Update MVPD PERMANENT flag: make cur=perm
- ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ?
+ ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 0
io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK
: //set bit 0
io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK;
// Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT:
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ?
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 1
io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK
: //set bit 1
@@ -2341,13 +2298,13 @@ namespace SBE
// Set Update side to alt
io_sbeState.seeprom_side_to_update =
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 )
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 )
? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ;
// MVPD flag Update
// Update MVPD flag make cur=perm
- ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ?
+ ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 0
io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK
: // set bit 0
@@ -2401,11 +2358,11 @@ namespace SBE
// Set Update side to alt
io_sbeState.seeprom_side_to_update =
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 )
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 )
? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ;
// Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT:
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ?
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 1
io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK
: // set bit 1
@@ -2416,7 +2373,7 @@ namespace SBE
if ( g_istep_mode )
{
// Update MVPD PERMANENT flag: make alt=perm
- (io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ?
+ (io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 0
io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK
: //set bit 0
@@ -2498,11 +2455,11 @@ namespace SBE
// Set Update side to alt
io_sbeState.seeprom_side_to_update =
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 )
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 )
? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ;
// Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT:
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ?
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ?
// clear bit 1
io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK
: // set bit 1
@@ -2534,7 +2491,7 @@ namespace SBE
// Set Update side to alt
io_sbeState.seeprom_side_to_update =
- ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 )
+ ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 )
? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ;
TRACFCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
@@ -3244,12 +3201,12 @@ namespace SBE
// Compare against 'current' Master side in case there is
// an issue with the other side
- if (io_sbeStates_v[i].cur_seeprom_side == SBE_SEEPROM0)
+ if (io_sbeStates_v[i].cur_seeprom_side == PNOR::SBE_SEEPROM0)
{
ver_ptr =
&(io_sbeStates_v[i].seeprom_0_ver.image_version);
}
- else // SBE_SEEPROM1
+ else // PNOR::SBE_SEEPROM1
{
ver_ptr =
&(io_sbeStates_v[i].seeprom_1_ver.image_version);
@@ -3389,12 +3346,12 @@ namespace SBE
else
{
// Not Master, so get 'current' version
- if (io_sbeStates_v[i].cur_seeprom_side == SBE_SEEPROM0)
+ if (io_sbeStates_v[i].cur_seeprom_side == PNOR::SBE_SEEPROM0)
{
ver_ptr =
&(io_sbeStates_v[i].seeprom_0_ver.image_version);
}
- else // SBE_SEEPROM1
+ else // PNOR::SBE_SEEPROM1
{
ver_ptr =
&(io_sbeStates_v[i].seeprom_1_ver.image_version);
diff --git a/src/usr/sbe/sbe_update.H b/src/usr/sbe/sbe_update.H
index aa880b2d4..e49c58289 100644
--- a/src/usr/sbe/sbe_update.H
+++ b/src/usr/sbe/sbe_update.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -53,10 +55,6 @@ namespace SBE
const uint64_t SBE_IMAGE_SEEPROM_ADDRESS = 0x400; // 1KB
const uint64_t SBE_VERSION_SEEPROM_ADDRESS = 0x300; // 1KB - 256B
- //Used to read SBE Boot Side from processor
- const uint64_t SBE_VITAL_REG_0x0005001C = 0x005001C;
- const uint64_t SBE_BOOT_SELECT_MASK = 0x0080000000000000;
-
// PNOR SBE and SBEC Partition constants
const uint32_t MAX_SBE_ENTRIES = 9;
const uint32_t SBETOC_EYECATCH = 0x53424500; //'SBE\0'
@@ -106,14 +104,6 @@ namespace SBE
MVPDOP_WRITE, // Write version data to MVPD
};
- // Used to keep track of perm/temp, and cur/alt
- enum sbeSeepromSide_t
- {
- SBE_SEEPROM0 = 0x00, // corresponds to EEPROM::SBE_PRIMARY
- SBE_SEEPROM1 = 0x01, // corresponts to EEPROM::SBE_BACKUP
- SBE_SEEPROM_INVALID = 0xFF,
- };
-
// Actions can be combined
enum sbeUpdateActions_t
{
@@ -127,7 +117,6 @@ namespace SBE
UNSUPPORTED_SITUATION = 0x80000000,
};
-
/******************************************/
/* Structs */
/******************************************/
@@ -207,9 +196,9 @@ namespace SBE
bool seeprom_0_ver_ECC_fail;
bool seeprom_1_ver_ECC_fail;
- sbeSeepromSide_t cur_seeprom_side; // aka 'booted' side
- sbeSeepromSide_t alt_seeprom_side;
- sbeSeepromSide_t permanent_seeprom_side;
+ PNOR::sbeSeepromSide_t cur_seeprom_side; // aka 'booted' side
+ PNOR::sbeSeepromSide_t alt_seeprom_side;
+ PNOR::sbeSeepromSide_t permanent_seeprom_side;
// Customized Image Information for this Target
size_t customizedImage_size;
@@ -329,21 +318,6 @@ namespace SBE
void* io_imgPtr,
size_t& o_actImgSize);
-
- /**
- * @brief Determines which Seeprom was used to boot the SBE
- *
- * @param[in] i_target Target processor to customize
- *
- * @param[out] o_bootSide The Seeprom the SBE booted from
- *
- * @return errlHndl_t Error log handle on failure.
- */
-
- errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target,
- sbeSeepromSide_t& o_bootSide);
-
-
/**
* @brief Collects Version information from a specific SEEPROM
*
diff --git a/src/usr/sbe/test/sbeupdatetest.H b/src/usr/sbe/test/sbeupdatetest.H
index d2351418b..5e2570631 100644
--- a/src/usr/sbe/test/sbeupdatetest.H
+++ b/src/usr/sbe/test/sbeupdatetest.H
@@ -580,7 +580,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
{
// Inputs
uint8_t i_situation;
- sbeSeepromSide_t i_cur; // current_seeprom_side
+ PNOR::sbeSeepromSide_t i_cur; // current_seeprom_side
uint8_t i_flags; // mvpdSbKeyword.flags
// Expected Output
@@ -596,7 +596,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
// - update alt=1
// - make cur=perm
// - re-IPL
- { 0xE0, SBE_SEEPROM0, 0x80,
+ { 0xE0, PNOR::SBE_SEEPROM0, 0x80,
static_cast<sbeUpdateActions_t>
(DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE),
EEPROM::SBE_BACKUP, 0x40 },
@@ -606,7 +606,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
// - update alt=0
// - make cur=perm
// - re-IPL
- { 0xC0, SBE_SEEPROM1, 0x00,
+ { 0xC0, PNOR::SBE_SEEPROM1, 0x00,
static_cast<sbeUpdateActions_t>
(DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE),
EEPROM::SBE_PRIMARY, 0x80 },
@@ -616,7 +616,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
// - update alt=0
// - make cur=perm
// - Continue IPL
- { 0xA0, SBE_SEEPROM1, 0x00,
+ { 0xA0, PNOR::SBE_SEEPROM1, 0x00,
static_cast<sbeUpdateActions_t>
(DO_UPDATE|UPDATE_MVPD|UPDATE_SBE),
EEPROM::SBE_PRIMARY, 0x80 },
@@ -625,7 +625,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
// Arbitrarily set cur side to 1 (therefore perm set to 0)
// - No updates
// - Continue IPL
- { 0x80, SBE_SEEPROM1, 0x00,
+ { 0x80, PNOR::SBE_SEEPROM1, 0x00,
static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS),
EEPROM::LAST_CHIP_TYPE, 0x00 },
@@ -633,7 +633,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
// Arbitrarily set cur side to 0 (therefore perm set to 0)
// - update alt=1
// - re-IPL
- { 0x60, SBE_SEEPROM0, 0x00,
+ { 0x60, PNOR::SBE_SEEPROM0, 0x00,
static_cast<sbeUpdateActions_t>
(DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE),
EEPROM::SBE_BACKUP, 0x40 },
@@ -644,14 +644,14 @@ class SBEUpdateTest: public CxxTest::TestSuite
// Arbitrarily set cur side to 1 (therefore perm set to 1)
// - update alt=0
// - re-IPL
- { 0x40, SBE_SEEPROM1, 0x80,
+ { 0x40, PNOR::SBE_SEEPROM1, 0x80,
static_cast<sbeUpdateActions_t>
(DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE),
EEPROM::SBE_PRIMARY, 0x80 },
// Repeat previous case to make sure global variables are used
// correctly to save MBOX value
- { 0x40, SBE_SEEPROM1, 0x80,
+ { 0x40, PNOR::SBE_SEEPROM1, 0x80,
static_cast<sbeUpdateActions_t>
(DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE),
EEPROM::SBE_PRIMARY, 0x80 },
@@ -660,7 +660,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
// Arbitrarily set cur side to 0 (therefore perm set to 0)
// - update alt=1
// - Continue IPL
- { 0x20, SBE_SEEPROM0, 0x00,
+ { 0x20, PNOR::SBE_SEEPROM0, 0x00,
static_cast<sbeUpdateActions_t>(DO_UPDATE|UPDATE_SBE),
EEPROM::SBE_BACKUP, 0x00 },
@@ -670,7 +670,7 @@ class SBEUpdateTest: public CxxTest::TestSuite
// - Continue IPL
// NOTE: this will test that right-most-bit is ignored:
// so techincally case 0x01, which should be = case 0x00
- { 0x01, SBE_SEEPROM0, 0x00,
+ { 0x01, PNOR::SBE_SEEPROM0, 0x00,
static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS),
EEPROM::LAST_CHIP_TYPE, 0x00 },
#endif // SBE_UPDATE_SEQUENTIAL
@@ -708,8 +708,8 @@ class SBEUpdateTest: public CxxTest::TestSuite
sbeState.cur_seeprom_side = testData[i].i_cur;
sbeState.alt_seeprom_side =
- ( ( testData[i].i_cur == SBE_SEEPROM0 )
- ? SBE_SEEPROM1 : SBE_SEEPROM0 );
+ ( ( testData[i].i_cur == PNOR::SBE_SEEPROM0 )
+ ? PNOR::SBE_SEEPROM1 : PNOR::SBE_SEEPROM0 );
sbeState.mvpdSbKeyword.flags = testData[i].i_flags;
OpenPOWER on IntegriCloud