📄 mkimage.pl
字号:
#
# Special consideration for ST200 images.
#
# * Look for the .boot section - this code must be put uncompressed
# somewhere in FLASH, and it is the app's entry point.
#
if (($architecture eq $CPU_ARCH_LX) && ($name eq ".boot"))
{
$type = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_LX_BOOT;
}
}
else
{
# Never deflate .post_(text|rodata)_reserve sections
if (exists($options{p}) && ($options{p} eq "deflate") && ($name !~ /^\.post_(text|rodata)_reserve$/))
{
$type = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_DEFLATED;
}
else
{
$type = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_COPY;
}
}
#
# Filter section against any specified with the '-j' option
#
if (elfSectionAllowed($name))
{
push @sections, { name => $name,
src => $srcAddr,
dst => $dstAddr,
size => $size,
type => $type };
}
}
}
}
close(HANDLE);
#
# At this stage the @sections array contains all the sections
# we need to consider. We now scan it to coalesce sections which
# are adjacent and of the same type.
#
# Special ST200 processing - we keep an eye open for the .boot section.
# This contains PIC boot code which sets up the stack, and intrinsicly
# knows the _real_ entry point of the code. If we spot a .boot section,
# we place it above the last real section in RAM, and set the entrypoint
# to be the address of _boot_rom_start_address, rather than the ELF published
# entrypoint.
#
# We never coalesce sections with names of the form .post_(text|rodata)_reserve
# which are correctly sized to be a Cryptocore reserve section as these need
# to be distinct, uncompressed sections which data could be inserted in by
# another script.
#
# Also keep an eye open for any .got sections - we need to highlight these
# so that the flasher tool can fix them up once in flash (or mkbinrom.pl in
# a binary ROM image).
#
my $lastSection = undef;
my $newSection = { name => "", src => 0, dst => 0, size => 0, type => 0};
#
# Put a dummy section on the end to ensure last coalesced bit is emitted
#
push @sections, { name => "_DUMMY_",
src => 0,
dst => 0,
size => 0,
type => 0 };
foreach my $section (@sections)
{
if (defined($lastSection))
{
# Coalesce if up to 128 bytes apart (and meet other requirements).
if (($section->{name} ne "_DUMMY_") &&
($lastSection->{type} == $section->{type}) &&
($section->{src} > $lastSection->{src}) &&
(($section->{src} - ($lastSection->{src} + $lastSection->{size})) <= 128) &&
($section->{name} !~ /^\.post_(text|rodata)_reserve$/ ||
($section->{size} != $RESERVE_1024_BIT_KEY && $section->{size} != $RESERVE_2048_BIT_KEY)) &&
($lastSection->{name} !~ /^\.post_(text|rodata)_reserve$/ ||
($lastSection->{size} != $RESERVE_1024_BIT_KEY && $lastSection->{size} != $RESERVE_2048_BIT_KEY)))
{
$newSection->{name} .= " $section->{name}";
$newSection->{size} = ($section->{src}-$newSection->{src})+$section->{size};
}
else
{
push @coalescedSections, $newSection;
$newSection = {%{$section}};
}
}
else
{
$newSection = {%{$section}};
#
# If this is an ST200 image, and this is the .boot section, then
# adjust its address to be above the highest loaded address
#
if (($architecture eq $CPU_ARCH_LX) && ($section->{name} eq ".boot"))
{
$newSection->{src} = $bootAddr;
$newSection->{dst} = $bootAddr;
}
if (($architecture eq $CPU_ARCH_LX) && ($section->{name} eq ".text"))
{
# If using a useful linker script, the .boot section will have been
# placed at the very start of the text section
$startAddress = $newSection->{dst};
}
}
$lastSection = $section;
}
#
# If this is a pic ST200 image use the advertised entry point. Otherwise
# the entrypoint is determined at flash time by calling the .boot section.
#
if ($architecture eq $CPU_ARCH_LX)
{
if ($defaultType == ($PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_SKIP))
{
my $hdrCmd = getObjdump() . " -f $elfName";
open(HANDLE, $hdrCmd."|") or die("unable to open pipe ($!), stopped");
while (<HANDLE>)
{
if (/^start address (\S+)\r?$/)
{
$startAddress = hex ($1);
last;
}
}
close(HANDLE);
}
else
{
$startAddress = 0 if (!defined($startAddress));
}
}
return @coalescedSections;
}
#
# Routine to decompose an ELF file into an image file
#
# This supports ST40 and ST200 ELF images, as well as
# execute from ROM (inplace & PIC) and execute from RAM.
#
# Take two parameters - the name of the ELF file, and the
# default placement type.
#
sub processElfFile($$)
{
my $elfFile = shift;
my $defaultType = $defaultSectionTypes{(shift)};
my $loadAddress = undef;
my $stackAddress = undef;
my $gotSection = undef;
my $tmpFile = createtmpname();
my $tmpSignFile = createtmpname();
my $tmpSigFile = createtmpname();
my @sections;
#
# Read in the section list
#
@sections = getElfSections($elfFile, $defaultType);
#
# ST40 images have to have the symbol __SH_DEBUGGER_CONNECTED zeroed out
# also scan for the stack address while we're at it
#
my $zeroedAddress;
my $zeroedSize;
my $symCmd = getObjdump() . " -t $elfFile";
open(HANDLE, $symCmd."|") or die("unable to open pipe ($!), stopped");
while (<HANDLE>)
{
if (/^(\S+) +[gw] +.*\.data\t(\S+) __SH_DEBUGGER_CONNECTED\r?$/)
{
$zeroedAddress = hex($1);
$zeroedSize = hex($2);
}
elsif (/^(\S+).* _stack\r?$/)
{
$stackAddress = hex($1);
}
}
close(HANDLE);
unless (defined($stackAddress))
{
if ($architecture eq $CPU_ARCH_SH4)
{
warn("Warning: Could not find stack address from the ELF image.\n");
}
$stackAddress = 0;
}
#
# Extract the start address (entry point) for the image
# if its not already known (we'll have figured out ST200 entry
# point by here).
#
unless (defined($startAddress))
{
my $hdrCmd = getObjdump() . " -f $elfFile";
open(HANDLE, $hdrCmd."|") or die("unable to open pipe ($!), stopped");
while (<HANDLE>)
{
if (/^start address (\S+)\r?$/)
{
$startAddress = hex($1);
}
}
close(HANDLE);
unless (defined($startAddress))
{
warn("Warning: Could not find entry point from the ELF image.\n");
$startAddress = 0;
}
}
unless (exists($options{d}))
{
my @time = localtime();
$options{d} = "ELF from $elfFile (" .
sprintf("%02d/%02d/%02d, %02d:%02d", $time[3], $time[4],
(($time[5] > 100) ? ($time[5] - (int($time[5]/100)*100)): $time[5]),
$time[2], $time[1]) .
")";
}
#
# Finally we can generate the image file
#
open(HANDLE, ">$options{o}") or die("unable to open '$options{o}' ($!), stopped");
binmode(HANDLE);
my $numSections = $#sections + 1;
if (defined($zeroedAddress))
{
$numSections++;
}
#
# Emit the file header
#
my $fileHeader = pack('VZ32VVVV',
$IMAGE_FILE_MAGIC_NUM,
$options{d},
$options{c} | $architecture,
$stackAddress,
$startAddress,
$numSections);
syswrite(HANDLE, $fileHeader, length($fileHeader)) or die("unable to write to '$options{o}' ($!), stopped");
#
# Emit the sections
#
foreach my $section (@sections)
{
my $rawSection = pack('VVVV',
$section->{type},
$section->{src},
$section->{dst},
$section->{size});
syswrite(HANDLE, $rawSection, length($rawSection)) or die("unable to write to '$options{o}' ($!), stopped");
}
#
# Emit the zero section if there is one
#
if (defined($zeroedAddress))
{
my $rawSection = pack('VVVV',
$PLACEMENT_TYPE_NONE | $SECTION_TYPE_ZERO,
$zeroedAddress,
$zeroedAddress,
$zeroedSize);
syswrite(HANDLE, $rawSection, length($rawSection)) or die("unable to write to '$options{o}' ($!), stopped");
}
#
# Now generate the sections and append them to the end of the file
#
my $section_index = 0;
foreach my $section (@sections)
{
my $names;
# Copy this section into $tmpFile
copySectionsToFile($section->{name}, $elfFile, $tmpFile);
if ($section->{type} == $SECTION_TYPE_DEFLATED)
{
#
# Init compressor
#
my $stream = deflateInit(-Level => Z_BEST_COMPRESSION()) or die("unable to create deflation stream, stopped");
my ($output, $status);
my $buffer;
#
# Read in uncompressed data to memory
#
open(IN_HANDLE, $tmpFile) or die("unable to open '$tmpFile' (!$), stopped");
binmode(IN_HANDLE);
my $uncomp_length = (stat($tmpFile))[7];
sysread(IN_HANDLE, $buffer, $uncomp_length) or die("unable to read from '$tmpFile' ($!), stopped");
close(IN_HANDLE);
#
# Compress it, and write it out
#
($output, $status) = $stream->deflate($buffer) ;
$status == Z_OK() or die("deflation failed, stopped");
my $length = length($output);
syswrite(HANDLE, $output, $length) or die("unable to write to '$options{o}' ($!), stopped");
($output, $status) = $stream->flush() ;
$status == Z_OK() or die("deflation flush failed, stopped");
$length += length($output);
syswrite(HANDLE, $output, length($output)) or die("unable to write to '$options{o}' ($!), stopped");
#
# Update the length recorded in the section header with compressed length
#
sysseek(HANDLE, 64 + ($section_index * 16), 0) or die("unable to seek in '$options{o}' ($!), stopped");
my $new_length = pack('V', $length);
syswrite(HANDLE, $new_length, length($new_length)) or die("unable to write to '$options{o}' ($!), stopped");
sysseek(HANDLE, 0, 2) or die("unable to seek in '$options{o}' ($!), stopped");
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -