📄 mkbinrom.pl
字号:
# Extract a default section type if specified
if ($filename =~ /\%(inplace|pic|deflate|copy)/)
{
$defSecType = $1;
}
elsif ($filename =~ /[^\%]+\%([^\:\@]+)/)
{
usage("unrecognised default section type '$1' in '$filename'\n");
}
if ($elfType eq "reloc" && $defSecType ne "copy" && $defSecType ne "deflate")
{
die("section type for relocatable library $elfFilename must be \"copy\" or \"deflate\", stopped");
}
# Start creating our command line
my @time = localtime();
# Our description is the image type, cpu num and date and time
my $desc = "$cpu: $elfType (" .
sprintf("%02d/%02d/%02d, %02d:%02d", $time[3], $time[4] + 1,
(($time[5] > 100) ? ($time[5] - (int($time[5]/100)*100)): $time[5]),
$time[2], $time[1]) . ")";
my $cmdLine = $^X . " -w $PATH_TO_THIS_SCRIPT/mkimage.pl $elfArg $elfFilename " .
"-o $baseName.img -p $defSecType -d \"$desc\"";
if ($signingKeyFile ne "" && ($elfType eq "app" || $elfType eq "reloc"))
{
$cmdLine .= " -k $signingKeyFile";
# Also add the inflash option if the app is inplace (assume inplace means
# this is going in FLASH).
if ($elfType eq "app" && $defSecType eq "inplace")
{
$cmdLine .= " -inflash";
}
}
$cmdLine .= " -c $cpu" if ($cpu != 0);
$cmdLine .= " -V$verboseOutput" if ($verboseOutput);
$cmdLine .= " -t $chipType" if ($chipType ne "");
if (($elfType eq "app" || $elfType eq "reloc") &&
defined($stcValue) && $stcValue != 0)
{
warn("Warning: STC will be same for boot sector and signature of " .
"$elfFilename. Use mkimage.pl directly to specify different values.\n");
$cmdLine .= " -stc $stcAddr $stcValue" if (defined($stcValue));
}
if (($elfType eq "app" || $elfType eq "reloc") &&
defined($vccValue) && $vccValue != 0)
{
warn("Warning: VCC will be same for boot sector and signature of " .
"$elfFilename. Use mkimage.pl directly to specify different values.\n");
$cmdLine .= " -vcc $vccAddr $vccValue" if (defined($vccValue));
}
print("Running command: $cmdLine\n") if ($verboseOutput > 1);
my $err = system($cmdLine);
if ($err)
{
warn("Warning: Failed to convert $elfFilename to an image file - continuing " .
"as if it were one already.\n");
}
else
{
print("Successfully converted ELF file $elfFilename to image file $baseName.img\n") if ($verboseOutput);
$filename = "$baseName.img";
}
return $filename;
}
#
# Sub to calculate the CRC for a series of bytes in FLASH - given an offset and
# an end offset.
# This is a perl version of the flashCalcCRC function from flashutil.c in the
# rombootram example.
#
sub calcCRC($$)
{
my $startOffset = shift(@_);
my $endOffset = shift(@_);
my $size = $endOffset - $startOffset;
my $crc = 0xFFFFFFFF;
printf("CRC from 0x%08x to 0x%08x is ", $startOffset, $endOffset) if ($verboseOutput);
my $binary = getFlashFileBinary($startOffset, $endOffset);
for (my $offset = 0; $size > 0; $size -= 4, $offset += 4)
{
# Get a word
my $val = unpack("V", substr($binary, $offset, 4));
printf("Val at 0x%08x is 0x%08x\n", $startOffset + $offset, $val) if ($verboseOutput > 2);
my $prev = $crc;
my $this;
for (my $count = 0; $count < 32; $count++)
{
$this = (($prev << 1) + (($val & 0x80000000) ? 1 : 0)) ^ (($prev & 0x80000000) ? $CRC_POLY : 0);
$val <<= 1;
$prev = $this;
}
$crc = $this;
}
$crc = $crc ^ 0xFFFFFFFF;
# On awkward perl builds we make sure $crc is 32-bit before we print it
$crc &= 0xFFFFFFFF;
printf("0x%08x\n", $crc) if ($verboseOutput);
return $crc;
}
#
# Ensure there is exactly one bootable slot per CPU
#
sub setBootSlots($)
{
my $appsRef = shift(@_);
my @apps = @$appsRef;
print("Checking boot slots:\n") if ($verboseOutput);
foreach my $cpu (@cpusWithApps)
{
my $hasBootImage = 0;
# Check for boot slots for this CPU
# In the @slots array, it is indexed by slot number, CPU numbers are stored
# in the array entries
# In @bootSlots we simply have a list of slot numbers which are bootable
for (my $slot = 0; $slot < scalar(@slots); $slot++)
{
if (defined($slots[$slot]) && $slots[$slot] == $cpu)
{
# This slot is for this cpu - is it bootable?
if (scalar(grep($_ == $slot, @bootSlots)) != 0)
{
if ($hasBootImage)
{
warn("Warning: Detected multiple boot slots for cpu $cpu.\n");
}
elsif ($cpu == 0)
{
$masterCPUBootSlot = $slot;
}
print(" Slot $slot is bootable for CPU $cpu\n") if ($verboseOutput);
$hasBootImage = 1;
}
}
}
if (!$hasBootImage)
{
# No boot image found - select one - the first app for this CPU
foreach my $appRef (@apps)
{
my @app = @$appRef;
if (($app[2] & $CPU_NUMBER_MASK) == $cpu && !($app[2] & $IMAGE_TYPE_MASK))
{
# Set it's slot as the boot slot for this cpu
push(@bootSlots, $app[0]);
print(" Implicitly setting slot $app[0] bootable for CPU $cpu\n") if ($verboseOutput);
$masterCPUBootSlot = $app[0] if ($cpu == 0);
last;
}
}
}
}
unless (defined($masterCPUBootSlot))
{
# No master CPU boot slot - if signing we need this to determine which
# application should have it's region(s) registered with the Cryptocore.
# As we have none, select the first boot image in @bootSlots
if ($cryptocoreSigning)
{
if (scalar(@bootSlots))
{
$masterCPUBootSlot = $bootSlots[0];
warn("Warning: No master CPU application detected. Assuming bootable " .
"application in slot $masterCPUBootSlot is the application which " .
"will be copied to RAM and should be registered with the Cryptocore.\n");
}
}
}
print("\n") if ($verboseOutput);
}
#
# Sub to amalgamate a used range into @usedRanges
#
sub useRange($$)
{
my $offset1 = shift(@_);
my $offset2 = shift(@_);
die("attempting to use reverse range in FLASH, stopped") if ($offset2 < $offset1);
my $done = 0;
for (my $count = 0; $count < @usedRanges; $count++)
{
if (overlaps($usedRanges[$count][0], $usedRanges[$count][1], $offset1, $offset2) ||
($offset2 + 1 == $usedRanges[$count][0] || $usedRanges[$count][1] + 1 == $offset1))
{
# We have overlapping or neighbouring ranges - merge them
if ($offset1 < $usedRanges[$count][0])
{
$usedRanges[$count][0] = $offset1;
}
if ($offset2 > $usedRanges[$count][1])
{
$usedRanges[$count][1] = $offset2;
}
$done = 1;
last;
}
elsif ($offset1 < $usedRanges[$count][0])
{
# We've found the location this range should be in the ordered list
splice(@usedRanges, $count, 0, [$offset1, $offset2]);
$done = 1;
last;
}
}
if (!$done)
{
# We need to append the range to the ordered list
push(@usedRanges, [$offset1, $offset2]);
}
}
#
# Sub to find a large enough gap in FLASH to house the size given (1st
# arg) with a base offset with the given alignment (2nd arg).
# The 3rd arg is non-zero if the space required is for executable code that will
# be run at the address this returns. This is not important unless we are
# Cryptocore signing, in which case we must ensure the space we return does not
# overlap the Cryptocore boot sector gap.
# An optional starting offset can be given (if lower than
# $FLASH_PROTECTED_SECTIONS_OFFSET it will be ignored).
# Returns offset in flash with enough space.
#
sub findSpaceInROMFor($$$;$)
{
my $size = shift(@_);
my $alignment = shift(@_);
my $executable = shift(@_);
my $startOffset = undef;
if (scalar(@_))
{
$startOffset = shift(@_);
}
# We start searching from the lowest address we can put sections at...
my $offset = $FLASH_PROTECTED_SECTIONS_OFFSET;
# Unless a start offset was given and it's higher, in which case we start from
# there
$offset = $startOffset if (defined($startOffset) && $startOffset > $offset);
my $foundSpace = 0;
my $misAlign = $offset % $alignment;
if ($misAlign)
{
$offset += $alignment - $misAlign;
}
# Cycle through used ranges looking for a gap big enough. If there isn't one
# we have to go after the end of the currently used ranges
my $count = 1;
for (; $count < @usedRanges; $count++)
{
my $lastEnd = $usedRanges[$count - 1][1];
my $thisStart = $usedRanges[$count][0];
next if ($offset > $thisStart);
# Check space available
if ($offset < $lastEnd)
{
$offset = $lastEnd;
$misAlign = $offset % $alignment;
if ($misAlign)
{
$offset += $alignment - $misAlign;
}
}
next if ($thisStart - $offset < $size);
if ($cryptocoreSigning && $executable &&
overlaps($offset, $offset + $size, $BOOT_GAP_LO, $BOOT_GAP_HI))
{
# Cryptocore signing is on and this space overlaps the boot sector gap,
# which is usually fine, except this space will have code run at the
# address we return ($executable is set)
$offset = $BOOT_GAP_HI;
$misAlign = $offset % $alignment;
if ($misAlign)
{
$offset += $alignment - $misAlign;
}
redo;
}
$foundSpace = 1;
last;
}
if (!$foundSpace)
{
# Return offset after last recorded range or the startOffset we were given
# if that was higher
if ($offset < $usedRanges[$count - 1][1])
{
$offset = $usedRanges[$count - 1][1];
$misAlign = $offset % $alignment;
if ($misAlign)
{
$offset += $alignment - $misAlign;
}
}
if ($cryptocoreSigning && $executable &&
overlaps($offset, $offset + $size, $BOOT_GAP_LO, $BOOT_GAP_HI))
{
# Cryptocore signing is on and this space overlaps the boot sector gap,
# which is usually fine, except this space will have code run at the
# address we return ($executable is set)
$offset = $BOOT_GAP_HI;
my $misAlign = $offset % $alignment;
if ($misAlign)
{
$offset += $alignment - $misAlign;
}
}
}
return $offset;
}
#
# Given an offset from $FLASH_START and a list of bytes, puts the bytes in
# the FLASH file.
# 1st argument is a description of what we're adding.
# Overlapping existing data causes a fatal error.
#
sub addBytesToFlashFile($$$)
{
my $desc = shift(@_);
my $offset = shift(@_);
my $byteArrayRef = shift(@_);
my $endOffset = $offset + @$byteArrayRef;
# We first check to see if we overlap any used ranges. If not we call
# replaceInFlashFile to add the data
for (my $count = 0; $count < @usedRanges; $count++)
{
last if ($offset < $usedRanges[$count][0]);
if (overlaps($offset, $endOffset, $usedRanges[$count][0], $usedRanges[$count][1]))
{
my $errStr = sprintf("could not add $desc at 0x%08x to 0x%08x - overlaps existing data in range 0x%08x to 0x%08x, stopped",
$offset, $endOffset, $usedRanges[$count][0], $usedRanges[$count][1]);
die($errStr);
}
}
replaceBytesInFlashFile($desc, $offset, $byteArrayRef, "Added");
}
#
# Given an offset from $FLASH_START and a list of bytes, puts the bytes in
# the FLASH file.
# 1st argument is a description of what we're adding.
# Overlapping existing data causes a fatal error.
#
sub addBinaryToFlashFile($$$)
{
my $desc = shift(@_);
my $offset = shift(@_);
my $binaryRef = shift(@_);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -