Skip to content

Commit

Permalink
Generate range check code for persistent read/write attributes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
popfuture authored and dcrowell77 committed Jul 19, 2017
1 parent 48a8ff9 commit 80631ed
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 7 deletions.
19 changes: 18 additions & 1 deletion src/include/usr/targeting/common/target.H
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/include/usr/targeting/common/targreasoncodes.H
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
34 changes: 34 additions & 0 deletions src/usr/targeting/attrcheck_errl.C
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions src/usr/targeting/common/xmltohb/attribute_types.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2693,6 +2693,10 @@
<default>0</default>
</int32_t>
</simpleType>
<range>
<min>-100</min>
<max>0</max>
</range>
<persistency>non-volatile</persistency>
<readable/>
<writeable/>
Expand Down
221 changes: 215 additions & 6 deletions src/usr/targeting/common/xmltohb/xmltohb.pl
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
# 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 "")
Expand Down Expand Up @@ -496,6 +496,19 @@ sub generateRWPersistValidations {
{
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}";
}
}
}
}

Expand Down Expand Up @@ -545,7 +558,6 @@ sub generateRWPersistValidations {
{
if (exists $attr->{simpleType} &&
exists $attr->{simpleType}->{enumeration})

{
my $typeId = $attr->{simpleType}->{enumeration}->{id};
if (!exists $attrEnumTypes{$typeId})
Expand Down Expand Up @@ -618,9 +630,7 @@ sub generateRWPersistValidations {
. "}\n\n";
}
}
print $rwAttrHFile "#endif\n";
print $rwAttrCFile "#endif // !__HOSTBOOT_RUNTIME\n";
close $rwAttrHFile;

print $rwAttrCFile <<VERBATIM;
Expand All @@ -646,6 +656,21 @@ sub generateRWPersistValidations {
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);
Expand All @@ -655,12 +680,103 @@ sub generateRWPersistValidations {
#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
Expand Down Expand Up @@ -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 { }

Expand Down Expand Up @@ -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}})
{
Expand Down

0 comments on commit 80631ed

Please sign in to comment.