📄 mkimage.pl
字号:
my $doneSection = 0;
# If this is a .post_(text|rodata)_reserve section, we can now insert the
# signature and 4 of the 5 words of the config_table entry. We only check
# the name and size to match.
if ($section->{name} =~ /^\.post_(text|rodata)_reserve$/)
{
if ($section->{size} == $RESERVE_1024_BIT_KEY ||
$section->{size} == $RESERVE_2048_BIT_KEY)
{
unless (exists($options{k}))
{
warn("Warning: Detected Cryptocore sections, but no private key to " .
"sign with provided on command line (use -k option).\n");
}
else
{
my $signedBlockDst;
# Dump the required sections to a file so we can hash them...any gaps
# will be padded automatically
if ($section->{name} =~ /text/)
{
# Dump the .text, .plt, .init and .fini sections into $tmpSignFile
# This order is guaranteed when the Cryptocore enhanced linker
# scripts are used with the ST40/200 toolsets
copySectionsToFile(".text .plt .init .fini", $elfFile, $tmpSignFile);
# Destination address recorded during getElfSections
$signedBlockDst = $textSectionDst;
}
else
{
# Dump the .rodata and .rodata1 sections into $tmpSignFile
copySectionsToFile(".rodata .rodata1", $elfFile, $tmpSignFile);
# Destination address recorded during getElfSections
$signedBlockDst = $rodataSectionDst;
}
# Get signed block size (without padding => == file size)
my $signedBlockLen = (stat($tmpSignFile))[7];
# The number of bytes needed for the number of config table entry
# fields signed with a signed block must be reserved, is the minimum
# amount of padding required for extra signed words just below a 64
# byte boundary
my $cteSignedSize = $CTE_SIGNING_LEVEL * 4;
# $padSize is the amount of padding to the place the signature will go
my $padSize = 16; # We always have at least 16 bytes padding to ensure
# code cannot be in the last 16 bytes of the signed
# region
my $misSize = ($signedBlockLen + $padSize) % 64;
if ($misSize)
{
$padSize += 64 - $misSize;
}
# Just append the padding we will sign for now - also put a copy in $reserveSecData
# which will be the data we write out for this reserve section
open(OUT_HANDLE, "+<$tmpSignFile") or die("unable to open '$tmpSignFile' (!$), stopped");
binmode(OUT_HANDLE);
sysseek(OUT_HANDLE, 0, 2) or die("unable to seek in '$tmpSignFile' ($!), stopped");
my $zeroString = pack("C", 0x0) x ($padSize - $cteSignedSize);
if (length($zeroString))
{
syswrite(OUT_HANDLE, $zeroString, length($zeroString)) or die("unable to write to '$tmpSignFile' ($!), stopped");
}
# In order to pass information on to the mksignedrom.pl script, we put
# the size of the linked section in the first word of the reserve section
# that will be stored in the .img file. This will enable the mksignedrom.pl
# script to work out where the signature and config table entry will be. It
# will be zeroed out again by the mksignedrom.pl script when the ROM image
# is created.
$zeroString = pack("C", 0x0) x ($padSize - 4);
my $reserveSectionData = pack("V", $signedBlockLen) . $zeroString;
# We now create the 4 config_table fields we know (they come after
# the signature in $reserveSectionData):
# block_add == $signedBlockDst # must be the physical address (i.e. 29-bit)
# block_len == ($signedBlockLen + $padSize) / 4 # we divide by 4 as this should be in words
# sig_add == (section->{dst} aligned up to 64 byte boundary...again the physical address)
# block_no == specified on command line (or that number +1 if signing data)
my $blockAddr = physMemAddr($signedBlockDst, $elfFile);
my $blockLen = ($signedBlockLen + $padSize) / 4;
my $sigAddr = physMemAddr($section->{dst} + $padSize, $elfFile);
my $blockNum = $options{g};
# Issue a warning if the signed block length exceeds
# $MAX_SIGNED_BLOCK_LEN
if ($blockLen > $MAX_SIGNED_BLOCK_LEN)
{
warn("Warning: signed block from $elfFile exceeds " .
$MAX_SIGNED_BLOCK_LEN . " words - this may " .
"exceed the maximum size allowed by the Cryptocore.\n");
# Unfortunately we have no way to split signed blocks as yet. If it
# ever becomes an issue an update to this package will be required
# which reserves enough room for multiple config table entries and
# signatures in the .post_text_reserve section and has the ability
# to put them in place...
}
if ($CRYPTOCORE_VERSION >= 2.0)
{
# OR in bits in the l.s. 4 bits for i-monitor port enables based on
# the CPU number this image is for, or those specified by -ce
# options if there were any
if (scalar(@cc2CPUEnables))
{
for my $enable (@cc2CPUEnables)
{
$blockAddr |= (1 << $enable);
print("Cryptocore CPU $enable enable set\n") if ($verboseOutput);
}
}
else
{
$blockAddr |= (1 << $options{c});
print("Cryptocore CPU $options{c} set for signed block\n") if ($verboseOutput);
}
# OR in the region_in_flash bit if the signed block is to be in flash
# region_in_flash is bit 28
if ((defined($regionsInFlash) && $regionsInFlash) ||
(!defined($regionsInFlash) && ($section->{type} & $PLACEMENT_TYPE_INPLACE) == $PLACEMENT_TYPE_INPLACE))
{
$blockLen |= 0x10000000;
print("Cryptocore 'inflash' bit set for signed block\n") if ($verboseOutput);
}
}
my $cte = pack("VVVV", $blockAddr, $blockLen, $sigAddr, $blockNum);
if ($CRYPTOCORE_VERSION >= 2.0)
{
# OR in bits in the l.s. 4 bits for i-monitor port enables based on
# the CPU number this image is for, or those specified by -ce
# options if there were any.
# This is just for signing - a hack to ensure the i-monitor port
# enables are always signed (i.e. won't be in the config table in
# FLASH/RAM).
if (scalar(@cc2CPUEnables))
{
for my $enable (@cc2CPUEnables)
{
$blockLen |= (1 << $enable);
}
}
else
{
$blockLen |= (1 << $options{c});
}
}
if ($verboseOutput > 1)
{
printf("Signed block information:\n\tBlock physical address: 0x%08x\n" .
"\tBlock length in words: $blockLen\n\tSignature physical address: 0x%08x\n" .
"\tBlock number: $blockNum\n", $blockAddr, $sigAddr);
}
# Write the correct fields for our chosen signing level
if ($CTE_SIGNING_LEVEL % 2 == 0) # 2 or 4
{
syswrite(OUT_HANDLE, pack("V", $blockAddr), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
}
# Always sign block len
syswrite(OUT_HANDLE, pack("V", $blockLen), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
if ($CTE_SIGNING_LEVEL >= 3) # 3 or 4
{
syswrite(OUT_HANDLE, pack("V", $sigAddr), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
syswrite(OUT_HANDLE, pack("V", $blockNum), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
}
close(OUT_HANDLE);
$options{g}++; # Increment for next signed block
# Now we can now use siggen to SHA1 and encrypt $tmpSignFile
# Note we use siggen in binary mode (smaller files than hex-like file mode => quicker)
runSigningTool($options{k}, $tmpSignFile, $tmpSigFile, $vccAddr,
$vccValue, $stcAddr, $stcValue);
# Read the signature file
my $signature = "";
open(IN_HANDLE, $tmpSigFile) or die("unable to open '$tmpSigFile' (!$), stopped");
binmode(IN_HANDLE);
my $sigFileLen = (stat($tmpSigFile))[7];
sysread(IN_HANDLE, $signature, $sigFileLen) or die("unable to read from '$tmpSigFile' ($!), stopped");
close(IN_HANDLE);
if ($lenDigitalSignature != $sigFileLen)
{
die("expected $lenDigitalSignature byte signature, but saw a $sigFileLen byte signature, stopped");
}
# Write this section (we add 0xdeadadda as the next config table addr as a placeholder)
$reserveSectionData .= $signature . $cte . pack("V", 0xdeadadda);
# We need to pad $reserveSectionData up to the full size of this section too
$padSize = $section->{size} - length($reserveSectionData);
die("internal error: reserve section appeared to be too small (size = " .
"$section->{size}, data len = " . length($reserveSectionData) .
", stopped") if ($padSize < 0);
$reserveSectionData .= (pack("C", 0x00) x $padSize);
# Write this reserve section to the output 'img' file
syswrite(HANDLE, $reserveSectionData, length($reserveSectionData)) or die("unable to write to '$options{o}' ($!), stopped");
# So we know not to copy the section to \*HANDLE as we would for
# other uncompressed sections
$doneSection = 1;
$signedSomething = 1;
}
}
elsif (defined($options{k}))
{
# We only warn if the size was greater than 4 as the ST200 Toolset has
# an 'intelligent' linker which doesn't set the VMA and LMA addresses
# of sections to the same value when you have padding sections like
# our reserve sections. As a result I had to put something in the
# reserve sections - a byte will always be there even when we aren't
# signing.
if ($section->{size} > 4)
{
warn("Warning: Saw potential reserve section $section->{name}, but " .
"size was $section->{size} bytes, which is not a valid Cryptocore " .
"reserve section size - image may not be correctly signed.\n");
}
}
}
if (!$doneSection)
{
# Normal input copy - just check the expected size and actual size match
if ($section->{size} != (stat($tmpFile))[7])
{
die("section '$section->{name}' was expected to be $section->{size} " .
"bytes, but " . (stat($tmpFile))[7] . " bytes copied, stopped");
}
copy($tmpFile, \*HANDLE);
}
}
$section_index++;
}
close(HANDLE);
#
# All done
#
if (exists($options{k}) && !$signedSomething)
{
warn("Warning: Private key for signing specified on command line, but no " .
".post_text_reserve/.post_rodata_reserve section of the correct size " .
"was found (check the link command line used the correct Cryptocore " .
"linker scripts and symbol definitions) - image not signed.\n");
}
if ($verboseOutput)
{
print "\nGenerated $options{o} from ",
($architecture eq $CPU_ARCH_SH4) ? "ST40" : "ST200",
" ELF file $elfFile.\n";
printf(" Total sections: 0x%08x\n", $numSections);
printf(" Entry point : 0x%08x\n", $startAddress);
printf(" Stack address : 0x%08x\n", $stackAddress);
}
}
#
# Sub which takes a relocatable ELF filename and a storage type of "copy" or
# "deflate" and creates the relevant image.
#
# RL images are converted to binary by objcopy and are either compressed, or
# put in place as-is.
#
sub processRelocElf($$)
{
my $rlFile = shift;
my $store = shift;
my $tmpRLFile = createtmpname();
if (exists($options{k}))
{
# A Cryptocore signing key has been provided - check the RL contains a
# reserve section and warn if it doesn't.
open(HANDLE, getObjdump() . " -h $rlFile |") || die("unable to open pipe ($!), stopped");
my $sawReserve = 0;
my $line;
while ($line = <HANDLE>)
{
if ($line =~ /^\s*[0-9]+\s(\S+)\s+[0-9A-Fa-f]+/)
{
my $name = $1;
if ($name =~ /^\.post_(text|rodata)_reserve$/)
{
$sawReserve = 1;
last;
}
}
}
# Read the rest of the output to prevent SIGPIPE being sent to objdump
while ($line = <HANDLE>)
{ }
close(HANDLE);
unless ($sawReserve)
{
warn("Warning: No .post_text_reserve or .post_rodata_reserve sections seen " .
"in $rlFile - is not Cryptocore signed/signable.\n");
}
else
{
# Reserve section exists - check whether the ELF has already been signed
# by signrl.pl, or whether it still needs signing. We do this by dumping
# the contents of the reserve sections and ensuring they are not all 0, or
# our fill values for .post_<X>_reserve sections.
# Automatic signing of RL libraries is only possible if the signing level
# is 1 (otherwise extra options are required to signrl.pl, which only the
# user can specify).
my $needsSigning = 0;
my $tmpResFile = createtmpname();
my $cmd = getObjcopy() . " -O binary -I elf32-little -j .post_text_reserve -j .post_rodata_reserve $rlFile $tmpResFile";
# Suppress any (warnings when processing ELF files with the 'wrong'
# binutils by temporarily silencing STDERR.
open(OLDERR, ">&STDERR");
close(STDERR);
print("Running command: $cmd\n") if ($verboseOutput);
my $err = system($cmd);
open(STDERR, ">&OLDERR");
close(OLDERR);
die("error running " . getObjcopy() . " ($!), stopped") if ($err);
if ((stat($tmpResFile))[7] == 0)
{
$needsSigning = 1;
}
else
{
my $str = readBinFileToStr($tmpResFile);
my @list = unpack("V*", $str);
# We search for words which are not either 0, or a fill value
if (scalar(grep($_ != 0 && $_ != 0xdaadadda, @list)) == 0)
{
$needsSigning = 1;
}
}
if ($needsSigning)
{
if ($CTE_SIGNING_LEVEL == 1)
{
# Call signrl.pl to sign the ELF file
my $cmd = $^X . " -w $PATH_TO_THIS_SCRIPT/signrl.pl -e $rlFile " .
"-o signed_$rlFile -k $options{k} -t $options{t}";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -