summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJaymes Wilks <mjwilks@us.ibm.com>2017-06-29 16:26:06 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-07-19 14:18:31 -0400
commit80631edd1d39c7bc5d0081f8ce0b792903d1955d (patch)
tree012f705cd9f2a7898534d075acd9f39d8935dec3 /src
parent48a8ff9008c000ce8b50708448a74f259c01d9d6 (diff)
downloadtalos-hostboot-80631edd1d39c7bc5d0081f8ce0b792903d1955d.tar.gz
talos-hostboot-80631edd1d39c7bc5d0081f8ce0b792903d1955d.zip
Generate range check code for persistent read/write attributes
This change to xmltobh.pl adds support for a new range tag in attribute_types.xml and generates range checking code when the new range tag is present for an attribute. Change-Id: Ib602b80e18d717fccd9cb8512f004c73be891bda RTC:163084 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42625 Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com> Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/targeting/common/target.H19
-rw-r--r--src/include/usr/targeting/common/targreasoncodes.H2
-rw-r--r--src/usr/targeting/attrcheck_errl.C34
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types.xml4
-rwxr-xr-xsrc/usr/targeting/common/xmltohb/xmltohb.pl221
5 files changed, 273 insertions, 7 deletions
diff --git a/src/include/usr/targeting/common/target.H b/src/include/usr/targeting/common/target.H
index bbbfe089d..0681da27f 100644
--- a/src/include/usr/targeting/common/target.H
+++ b/src/include/usr/targeting/common/target.H
@@ -762,7 +762,7 @@ void setFrequencyAttributes(Target * i_sys,
* and halts the IPL.
*
* @param[in] i_pTarget The target associated with the attribute that failed
- * enum value checking.
+ * enum value checking. Cannot be nullptr.
* @param[in] i_attr The attribute id of the attribute that failed enum
* value checking.
* @param[in] i_invalidValue The invalid value that failed the enum check.
@@ -771,6 +771,23 @@ void handleEnumCheckFailure(const Target* i_pTarget,
const ATTRIBUTE_ID i_attr,
const uint64_t i_invalidValue);
+// Function to handle secureboot attribute range check failures
+/**
+ * @brief Creates an error log with target and attribute information
+ * and halts the IPL.
+ *
+ * @param[in] i_pTarget The target associated with the attribute that failed.
+ * Cannot be nullptr.
+ *
+ * @param[in] i_attr The attribute id of the attribute that failed
+ *
+ * @param[in] i_outOfRangeValue The value that was out of range
+ */
+void handleRangeCheckFailure(const Target* i_pTarget,
+ const ATTRIBUTE_ID i_attr,
+ const uint64_t i_outOfRangeValue);
+
+
// The following #include ensures that persistent read/write attributes are
// value-checked for validity upon calling getAttr. This is done via
// autogenerated template specializations for each attribute. External calls
diff --git a/src/include/usr/targeting/common/targreasoncodes.H b/src/include/usr/targeting/common/targreasoncodes.H
index 18d7c6726..92d9611c4 100644
--- a/src/include/usr/targeting/common/targreasoncodes.H
+++ b/src/include/usr/targeting/common/targreasoncodes.H
@@ -49,6 +49,7 @@ enum TargetingModuleId
TARG_CREATE_VMM_SECTIONS = 0x09,
TARG_APPLY_ATTR_OVER = 0x0A,
TARG_HANDLE_ENUM_CHECK_FAILURE = 0x0B,
+ TARG_HANDLE_RANGE_CHECK_FAILURE = 0x0C,
};
enum TargetingReasonCode
@@ -75,6 +76,7 @@ enum TargetingReasonCode
TARG_RC_APPLY_ATTR_OVER_NOT_ALLOWED = TARG_COMP_ID | 0x14,
TARG_RC_MM_BLOCK_UNMAP_FAIL = TARG_COMP_ID | 0x15,
TARG_RC_ATTRIBUTE_ENUM_CHECK_FAIL = TARG_COMP_ID | 0x16,
+ TARG_RC_ATTRIBUTE_RANGE_CHECK_FAIL = TARG_COMP_ID | 0x17,
};
}; // End TARGETING namespace
diff --git a/src/usr/targeting/attrcheck_errl.C b/src/usr/targeting/attrcheck_errl.C
index 31a716779..13dd949d0 100644
--- a/src/usr/targeting/attrcheck_errl.C
+++ b/src/usr/targeting/attrcheck_errl.C
@@ -87,6 +87,40 @@ void handleEnumCheckFailure(const Target* i_pTarget,
// is advisable in most cases, including this one.
SECUREBOOT::handleSecurebootFailure(err, true);
}
+
+void handleRangeCheckFailure(const Target* i_pTarget,
+ const ATTRIBUTE_ID i_attr,
+ const uint64_t i_outOfRangeValue)
+{
+ TRACFCOMP(g_trac_targeting,
+ "ATTRIBUTE_ID range check failed! Attribute ID = 0x%x "
+ "with out of range value 0x%llX", i_attr, i_outOfRangeValue);
+
+ /*@
+ * @errortype
+ * @moduleid TARGETING::TARG_HANDLE_RANGE_CHECK_FAILURE
+ * @reasoncode TARGETING::TARG_RC_ATTRIBUTE_RANGE_CHECK_FAIL
+ * @userdata1[00:31] Target's HUID
+ * @userdata1[32:64] Attribute ID
+ * @userdata2 Value that was out of range
+ * @devdesc Invalid range for attribute value.
+ * @custdesc Unexpected internal firmware error.
+ */
+ auto err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ TARGETING::TARG_HANDLE_RANGE_CHECK_FAILURE,
+ TARGETING::TARG_RC_ATTRIBUTE_RANGE_CHECK_FAIL,
+ TWO_UINT32_TO_UINT64(
+ get_huid(i_pTarget),
+ i_attr),
+ i_outOfRangeValue,
+ true);
+
+ // handle the secureboot failure in the normal secureboot way
+ // The 'true' below indicates that we want to wait for shutdown, which
+ // is advisable in most cases, including this one.
+ SECUREBOOT::handleSecurebootFailure(err, true);
+}
#endif
} // End namespace TARGETING
diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
index a13c50817..665bd72c1 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
@@ -2693,6 +2693,10 @@
<default>0</default>
</int32_t>
</simpleType>
+ <range>
+ <min>-100</min>
+ <max>0</max>
+ </range>
<persistency>non-volatile</persistency>
<readable/>
<writeable/>
diff --git a/src/usr/targeting/common/xmltohb/xmltohb.pl b/src/usr/targeting/common/xmltohb/xmltohb.pl
index 75b6183dc..90c4817e4 100755
--- a/src/usr/targeting/common/xmltohb/xmltohb.pl
+++ b/src/usr/targeting/common/xmltohb/xmltohb.pl
@@ -187,7 +187,7 @@ use Digest::MD5 qw(md5_hex);
# NOTE: the attribute list initially contains both real and virtual attributes
my $allAttributes = $xml->XMLin($cfgHbXmlFile,
forcearray => ['enumerationType','enumerator','attribute','hwpfToHbAttrMap',
- 'compileAttribute']);
+ 'compileAttribute','range']);
my $fapiAttributes = {};
if ($cfgFapiAttributesXmlFile ne "")
@@ -496,6 +496,19 @@ foreach my $attrs (@{$attributes->{attribute}})
{
print $rwAttrFile "$attrs->{id}\n";
push @rwPersistAttrs, $attrs;
+
+ # do a little bit of validation for the range tag
+ if (exists $attrs->{range})
+ {
+ if (!exists $attrs->{simpleType})
+ {
+ die "Attribute $attrs->{id} must be simpleType to use range tag.";
+ }
+ elsif (exists $attrs->{simpleType}->{enumeration})
+ {
+ die "Enumeration and range tags cannot coexist. See $attrs->{id}";
+ }
+ }
}
}
@@ -545,7 +558,6 @@ foreach my $attr (@rwPersistAttrs)
{
if (exists $attr->{simpleType} &&
exists $attr->{simpleType}->{enumeration})
-
{
my $typeId = $attr->{simpleType}->{enumeration}->{id};
if (!exists $attrEnumTypes{$typeId})
@@ -618,9 +630,7 @@ foreach my $attr (@rwPersistAttrs)
. "}\n\n";
}
}
-print $rwAttrHFile "#endif\n";
print $rwAttrCFile "#endif // !__HOSTBOOT_RUNTIME\n";
-close $rwAttrHFile;
print $rwAttrCFile <<VERBATIM;
@@ -646,6 +656,21 @@ foreach my $attr (@rwPersistAttrs)
VERBATIM
}
}
+# throw in any range checked attributes
+foreach my $attr (@rwPersistAttrs)
+{
+ if (exists $attr->{range})
+ {
+ print $rwAttrCFile <<VERBATIM;
+ case (ATTR_$attr->{id}):
+ return tryGetAttr<ATTR_$attr->{id}>(
+ * reinterpret_cast<
+ typename AttributeTraits<ATTR_$attr->{id}>::Type*
+ >(io_attrData)
+ );
+VERBATIM
+ }
+}
print $rwAttrCFile <<VERBATIM;
default:
return _tryGetAttrUnsafe(i_attr, i_size, io_attrData);
@@ -655,12 +680,103 @@ print $rwAttrCFile <<VERBATIM;
#endif
}
+#if !defined(__HOSTBOOT_RUNTIME) && defined(__HOSTBOOT_MODULE)
+VERBATIM
+foreach my $attr (@rwPersistAttrs)
+{
+ if (exists $attr->{range})
+ {
+ print $rwAttrHFile "template<>\n"
+ . "bool Target::tryGetAttr<ATTR_$attr->{id}>("
+ . "typename AttributeTraits<ATTR_$attr->{id}>::Type& o_attrValue)"
+ . " const;\n\n";
+ print $rwAttrCFile "template<>\n"
+ . "bool Target::tryGetAttr<ATTR_$attr->{id}>("
+ . "typename AttributeTraits<ATTR_$attr->{id}>::Type& o_attrValue)"
+ . " const\n"
+ . "{\n"
+ . " bool l_read = _tryGetAttrUnsafe(ATTR_$attr->{id},"
+ . "sizeof(o_attrValue),&o_attrValue);\n"
+ . " if (l_read)\n"
+ . " {\n";
+ my $valueString = "";
+ my $extraIndent = "";
+ # persence of simpleType tag confirmed previously
+ my $isArrayType = exists $attr->{simpleType}->{array};
+ if ($isArrayType)
+ {
+ my $arrayTag = "$attr->{simpleType}->{array}";
+ my $arraySize = getArrayTagTotalSize($arrayTag);
+ my $numDimensions = getArrayNumDimensions($arrayTag);
+ my $arrayPrefix = "";
+ $extraIndent = " ";
+ for (my $i=0; $i < $numDimensions - 1; $i++)
+ {
+ $arrayPrefix = "$arrayPrefix*";
+ }
+ print $rwAttrCFile ""
+ . " for(int i=0; i<$arraySize; i++)\n"
+ . " {\n";
+ $valueString = "(${arrayPrefix}o_attrValue)[i]";
+ }
+ else
+ {
+ $valueString = "o_attrValue";
+ }
+ if (exists $attr->{range})
+ {
+ my @ranges = validateRangeMinsAndMaxes($attr->{range}, $attr->{id});
+ print $rwAttrCFile "$extraIndent"
+ . " do {\n$extraIndent";
+ for my $range (@ranges)
+ {
+ if (exists $range->{min} || exists $range->{max})
+ {
+ print $rwAttrCFile " if (";
+ }
+ if (exists $range->{min})
+ {
+ print $rwAttrCFile "$valueString >= $range->{min}";
+ }
+ if (exists $range->{min} && exists $range->{max})
+ {
+ print $rwAttrCFile " && ";
+ }
+ if (exists $range->{max})
+ {
+ print $rwAttrCFile "$valueString <= $range->{max}";
+ }
+ if (exists $range->{min} || exists $range->{max})
+ {
+ print $rwAttrCFile ")\n$extraIndent"
+ . " {\n$extraIndent"
+ . " break;\n$extraIndent"
+ . " }\n";
+ }
+ }
+ print $rwAttrCFile "$extraIndent"
+ . " handleRangeCheckFailure(this,ATTR_$attr->{id},"
+ . "$valueString);\n$extraIndent"
+ . " } while(0);\n";
+ }
+ if ($isArrayType)
+ {
+ print $rwAttrCFile " }\n";
+ }
+ print $rwAttrCFile ""
+ . " }\n"
+ . " return l_read;\n"
+ . "}\n";
+ }
+}
+print $rwAttrCFile <<VERBATIM;
+#endif // !__HOSTBOOT_RUNTIME &&__HOSTBOOT_MODULE
} // namespace TARGETING
VERBATIM
-
+print $rwAttrHFile "#endif\n";
+close $rwAttrHFile;
close $rwAttrCFile;
-
}
# sub getArrayTagTotalSize
@@ -693,6 +809,98 @@ sub getArrayNumDimensions {
return $dims;
}
+# sub validateRangeMinsAndMaxes
+# Looks at the supplied range tag to determine if it was authored correctly.
+# @param[in] range - The range tag and all of its sub elements
+# @param[in] attr_id - The attribute id string used for better error messages.
+sub validateRangeMinsAndMaxes {
+ my ($range, $attr_id) = @_;
+
+ # first check: make sure there is only one unbounded max and only one
+ # unbounded min
+ my $unboundedMins = 0;
+ my $unboundedMaxes = 0;
+ foreach my $i (@{$range})
+ {
+ if (!exists $i->{min} && exists $i->{max})
+ {
+ $unboundedMaxes++;
+ }
+ if (!exists $i->{max} && exists $i->{min})
+ {
+ $unboundedMins++;
+ }
+ if (!exists $i->{max} && !exists $i->{min})
+ {
+ die "empty range tag!";
+ }
+ }
+ if ($unboundedMins > 1)
+ {
+ die "$attr_id has > 1 unbounded min in range tag: $unboundedMins";
+ }
+ if ($unboundedMaxes > 1)
+ {
+ die "$attr_id has > 1 unbounded max in range tag: $unboundedMaxes";
+ }
+
+ # sort by mins
+ # if an item has no min tag assume lowest number possible
+ # if an item has no max tag assume highest number possible
+ # this puts the unbounded max at beginning and unbounded min at the end
+ my @rangeArray = sort { (!exists $a->{min}? "-inf":
+ !exists $a->{max}? "inf": $a->{min} ) <=>
+ (!exists $b->{min}? "-inf":
+ !exists $b->{max}? "inf": $b->{min} )
+ } @$range;
+
+ my $i=0;
+ # if the first range is an unbounded max then it stands alone
+ my $prevMax = "-inf"; # default prevMax is negative infinity
+ if (!exists @rangeArray->[$i]->{min})
+ {
+ if (!exists @rangeArray->[$i]->{max})
+ {
+ die "$attr_id has range tag with no min or max!";
+ }
+ $prevMax = @rangeArray->[$i]->{max};
+ $i++;
+ }
+
+ # go through the list and check for undesired overlap of ranges
+ while (exists @rangeArray->[$i]->{min} && exists @rangeArray->[$i]->{max})
+ {
+ if (@rangeArray->[$i]->{max} < @rangeArray->[$i]->{min})
+ {
+ print Dumper(@rangeArray[$i]);
+ die "Min/max pair in <range> tag inverted!";
+ }
+ if ($prevMax > @rangeArray->[$i]->{min})
+ {
+ print "Previous max: $prevMax\n";
+ print Dumper(@rangeArray[$i]);
+ die "Range overlap! Previous <max> tag $prevMax "
+ . "exceeds <min> tag value! @rangeArray->[$i]->{min}";
+ }
+ $prevMax = @rangeArray->[$i]->{max};
+ $i++;
+ }
+
+ # check for stray min tag at the end
+ if (exists @rangeArray->[$i]->{min})
+ {
+ # make sure trailing min is greater than previous max
+ if ($prevMax > @rangeArray->[$i]->{min})
+ {
+ print "Previous max: $prevMax\n";
+ print Dumper(@rangeArray[$i]);
+ die "Range overlap! Previous <max> tag $prevMax "
+ . "exceeds <min> tag value! @rangeArray->[$i]->{min}";
+ }
+ }
+
+ return @rangeArray;
+}
sub VALIDATION_FUNCTIONS { }
@@ -768,6 +976,7 @@ sub validateAttributes {
$elements{"serverwizReadonly"} = { required => 0, isscalar => 0};
$elements{"serverwizShow"} = { required => 0, isscalar => 1};
$elements{"global"} = { required => 0, isscalar => 0};
+ $elements{"range"} = { required => 0, isscalar => 0};
foreach my $attribute (@{$attributes->{attribute}})
{
OpenPOWER on IntegriCloud