📄 mkbinrom.pl
字号:
: # Perl
eval 'exec perl -w -S $0 ${1+"$@"}'
if 0;
#
# mkbinrom.pl
#
# Copyright (c) STMicroelectronics 2004-2007. All rights reserved.
#
# A perl script to build a ROM image from provided .img/elf files.
#
# It will also not work for the STb5301, which has the same memory map as the
# STi5100, an ST20-C2 part (boots from the top of FLASH).
#
# Syntax and usage notes
# ======================
#
# perl -w mkbinrom.pl <options>
#
# Syntax can be seen by running the script with no options.
#
#
# Multiple bootstraps and vectors can be provided as long as they have been
# prepared for different CPU's (done at the mkimage.pl stage or with extra
# ELF file input options).
#
# We don't know the size of the FLASH for the chip, so we will put images in
# FLASH sequentially from the base of FLASH after the boot and image directory
# information, the boot sector gap and the variable part of the boot sector.
#
# NOTE: Assumption has been made that the fixed part of the boot sector will
# cover the entire prescribed FLASH layout ($FLASH_START to $FLASH_START +
# 0x4000 = 16KB). If this is not the case the layout below will need to be
# changed.
#
# The layout of the FLASH is as follows (as offsets from $FLASH_START):
#
# 0x00000000 - 0x0000003F Boot vector for CPU 0
# 0x00000040 - 0x0000007F Boot vector for CPU 1
# ...
# 0x000001C0 - 0x000001FF Boot vector for CPU 7
# 0x00000200 - 0x0000021F ASCIIZ description for bootvector 0
# 0x00000220 - 0x0000023F ASCIIZ description for bootvector 1
# ...
# 0x000002E0 - 0x000002FF ASCIIZ description for bootvector 7
# 0x00000300 - 0x0000043F Bootstrap descriptors for CPUs 0 - 7 (see below)
# 0x00000440 - 0x00000443 Pointer to image control directory (main app)
# 0x00000444 - 0x0000053B Image control strucutres for fail-safe app
# 0x0000053C - 0x0000053F CRC for 0x00000000-0x0000053B
# 0x00000540 - X Space required for bootstraps and fail-safe app sections
# X - Y Padding to end of highest used FLASH block (anything
# below Y is to be considered non-updatable). Note
# that if there is no fail-safe application there may
# be no padding.
# Y - Y + 0xFF Main image control directory
# Y + 0x100 - Y + 0x37FB Main image control structures
# Y + 0x37FC - Y + 0x3800 CRC for Y to Y + 0x37FB
#
# References to the BOOT_GAP, boot sector, config_table and signatures are for
# Cryptocore signing and will be unused when not Cryptocore signing.
#
# The format of a bootstrap descriptor is:
#
# 0x0000 - 0x0003 Entry point
# 0x0004 - 0x0007 Size of bootstrap
# 0x0008 - 0x0027 ASCIIZ description
#
# The image control directory consists of 64 pointers to image control
# structures. These are the image slot descriptions. Unused entries are NULL.
#
# The format of an image control structure is:
#
# 0x0000 - 0x001F ASCIIZ description
# 0x0020 - 0x0023 CPU number (0-7). Top bit set if boot image. Arch and image types also ORed in.
# 0x0024 - 0x0027 Stack address
# 0x0028 - 0x002B Entry point
# 0x002C - 0x002F Number of sections which follow
# 0x0030+N*0x10 - 0x0033+N*0x10 Type (copy, zeroed, etc)
# 0x0034+N*0x10 - 0x0037+N*0x10 source address in FLASH
# 0x0038+N*0x10 - 0x003B+N*0x10 destination address in RAM
# 0x003C+N*0x10 - 0x003F+N*0x10 length in bytes (of source)
#
require 5.006_001;
use strict;
use warnings;
use Config;
use Getopt::Std;
use File::Basename;
use File::Copy;
BEGIN
{
# Include subs used by mkimage.pl and mkbinrom.pl
my ($null, $PATH_TO_THIS_SCRIPT, $null2) = fileparse($0, "\\..*");
unshift(@INC, $PATH_TO_THIS_SCRIPT);
}
use mkcommon;
# The $useST40Addressing variable imported from mkcommon.pm should be set based
# on the architecture of the boot vector image put in for CPU 0 which would
# normally be the CPU to do the move from ROM to RAM (which is what we mean by
# master in this case).
# Extract script name and path to script for later use
our ($script_bname, $PATH_TO_THIS_SCRIPT, $script_ext) = fileparse($0, "\\..*");
our $THIS_SCRIPT = $script_bname . $script_ext;
#
# Global and file scope constants/variables
#
my $ELF_MAGIC_NUMBER = 0x7F454C46;
our $FLASH_MAX_CPUS = 8;
my $FLASH_DESC_LEN = 32;
my $FLASH_BOOT_VECTOR_SIZE = 64;
my $FLASH_IMAGE_DIRECTORY_SIZE = 64;
my $FLASH_START = 0x00000000; # -flashbase overrides
my $FLASH_BOOTVEC_DESC_OFF = 0x200;
my $FLASH_BOOTSTRAP_DESC_OFF = 0x300;
my $FLASH_MAIN_ICD_PTR_OFFSET = 0x440;
my $FLASH_MAIN_SECS_FROM_ICD = 0x3800; # Length from main image control directory to where we can put sections
my $FLASH_FAILSAFE_ICS_OFFSET = 0x444;
my $FLASH_PROTECTED_SECTIONS_OFFSET = 0x540;
my $MIN_SECTION_ALIGNMENT = 64; # Alignment for sections (can be overridden)
# Polynomial value used for CRCs
my $CRC_POLY = 0x04C14BD7;
# Cryptocore gap layout
my $BOOT_GAP_LO = undef;
my $BOOT_GAP_HI = undef;
# Cryptocore values
my $CRYPTOCORE_VERSION = 1.5; # 1.5 and 2.0 are supported
my $CTE_SIGNING_LEVEL = 4; # Signing levels for the config table entry
# fields: 1 - just signed block len
# 2 - block addr and len
# 3 - block len, sig addr & block num
# 4 - block addr & len, sig addr & block num
our $SIGGEN_TOOL = "siggen";
if ($^O =~ /win/i)
{
$SIGGEN_TOOL .= ".exe";
}
my $CHIP_INFO_FILE = $PATH_TO_THIS_SCRIPT . "chipinfo.ini";
my $MAX_SIGNED_BLOCK_LEN = 64*1024*1024/4; # In words
my $lenDigitalSignature = 128; # In bytes (will be doubled if using 2048 bit keys)
my $vccAddr = undef; # VCC address
my $vccValue = undef; # VCC value
my $stcAddr = undef; # STC address
my $stcValue = undef; # STC value
# End of boot sector from FLASH start
my $endOfBootSectorFromFS = 0;
# For cmdline args
my $outputROM = "";
my $signingKeyFile = "";
my $firmwareKeyFile = ""; # Cryptocore 2 only (signs the public modulus of the signing key)
my $chipType = "";
my $inputBinaryROMFile = ""; # For just signing the boot sector of a prepared ROM image
my $inputFromBinaryROM = 0;
my $flashBlockMapFile = undef;
# For flexible parts of flash layout
my $mainICDoffset = undef;
# Will build up a list of all reserve section info in ROM image in here
my @reserveSecs = ();
my $cryptocoreSigning = 0; # Are we Cryptocore signing?
my $masterCPUBootSlot; # Will be set to the number of the slot containing
# the boot image for the master CPU (CPU 0)
my @bootSlots = (); # List of bootable slots
my @slots = (); # Slot to CPU mapping array
my @cpusWithApps = (); # CPUs we have app images for
# Used to keep a list of the ranges that have been used in our representation
# of FLASH
my @usedRanges = ();
# Place to throw things away to
my $null;
#
# Sub to report correct usage
#
sub usage($)
{
print("\n$THIS_SCRIPT: ", shift(@_), "\n\n");
print("usage: perl $THIS_SCRIPT -o <output_rom_image>\n",
" -v <boot_vector_image/elf_file>[:cpu][%default_sec_type]\n",
" -s <bootstrap_image/elf_file>[:cpu][%default_sec_type]\n",
" -i <application_image/elf_file>[\@slot][:cpu][%default_sec_type]\n",
" -fs <application_image/elf_file>[%default_sec_type]\n",
" -a <alignment>\n",
" -b <slot>\n",
" -flashbase <flash_base_address>\n",
" -flashmap <flash_block_map_file>\n",
" -t <chip_type>\n",
" -V[n]\n",
" (the following are only useful on Cryptocore parts)\n",
" -d <binary_sigdma_file> <sigdma_info_file>\n",
" -d <sigdma_info_file>\n",
" -k <signing_key_file>\n",
" -f <firmware_key_file>\n",
" -setbssize <boot_sec_size>\n",
" -signbinary <input_binary_rom_image>\n",
" -sksig <signing_key_signature_file>\n",
" -stc <addr> <value>\n",
" -vcc <addr> <value>\n\n",
" where:\n",
" -o specifies an output ROM image file\n",
" -v specifies a boot vector image/ELF file. If ELF, is for cpu (default 0) \n",
" with sections of default_sec_type (default is pic, other option is inplace)\n",
" -s specifies a bootstrap image/ELF file. If ELF, is for cpu (default 0) \n",
" with sections of default_sec_type (default is pic, other option is inplace)\n",
" -i specifies an application image/ELF file (may be a relocatable library) and\n",
" optional slot number, cpu (default 0) and default_sec_type (default is copy,\n",
" other options are deflate, pic or inplace)\n",
" -fs specifies a fail-safe application image/ELF file and optional default_sec_type (default\n",
" is copy, other options are deflate or inplace). The fail-safe application\n",
" always runs after the bootstrap on the master CPU. It is supposed to do any\n",
" checks and actions needed (e.g. repair FLASH after update failure), then load\n",
" the boot application for the master CPU\n",
" -a specifies the minimum section alignment for sections placed by this\n",
" script (default 64)\n",
" -b specifies the slot number which contains the boot application\n",
" -flashbase overrides the default flash base address (0) for boards with\n",
" flash at a different address\n",
" -flashmap when a fail-safe application is provided along with a flash block map\n",
" file, $THIS_SCRIPT will separate fixed and updatable areas in FLASH into\n",
" separate FLASH blocks so the bottom blocks can be locked\n",
" -t specifies a chip type (used to switch to STi5528 layout, set minimum section\n",
" alignments for some chips, or for retrieving Cryptocore information)\n",
" -V[n] specifies verbose mode (verbosity level n)\n",
" (the following are only useful on Cryptocore parts)\n",
" -d specifies SigDMA file(s), which can be a SigDMA info file (containing\n",
" the SigDMA data and info), or a binary file for the data and a\n",
" SigDMA info file\n",
" Note: Multiple SigDMAs can be placed within one image to save space in\n",
" the image directory if mkimage.pl is used to prepare them\n",
" -k specifies a signing key file to sign with\n",
" -f specifies firmware key file to sign signing key with (Cryptocore 2)\n",
" -setbssize specifies the Cryptocore boot sector size to be used, overriding\n",
" calculated or existing values (in bytes)\n",
" -signbinary specifies an input binary ROM image to Cryptocore sign the boot sector of\n",
" (use -setbssize too if boot sector size field is not already in place)\n",
" -sksig specifies a file containing a pre-signed version of the signing key\n",
" signature so that a firmware key is not needed (Cryptocore 2)\n",
" -stc specifies a Sales Type Check address and value for the boot sector (Cryptocore 2)\n",
" -vcc specifies a Version Control Check address and value for the boot sector (Cryptocore 2)\n");
exit(1);
}
#
# Sub to convert an ELF file to an image file by calling mkimage.pl
# 1st arg is type of ELF file: "bootvec", "bootstrap" or "app"
# 2nd arg is a filename
# Returns filname as is on failure, or new filename on success
#
sub convertIfElf($$)
{
my $elfType = shift(@_);
my $filename = shift(@_);
my ($elfFilename, $baseName);
# Set defaults for the cpu and default section type
my $cpu = 0;
my $defSecType = ($elfType eq "app" ? "copy" : "pic");
my $elfArg = "-e";
# We'll need to extract the filename from $filename (it may have '@', ':', or
# '%' options following)
if ($filename =~ /^((?:[a-zA-Z]\:\\)?[^\@\:\%]+)/)
{
$elfFilename = $1;
($baseName, $null, $null) = fileparse($elfFilename, "\\..*");
unless(-f $elfFilename)
{
die("$elfFilename does not exist, stopped");
}
# Lets check it's an ELF file
# First check the magic number at the start of the file - only try readelf
# if this is okay (the magic number COULD be there by chance...)
open(IN_HANDLE, "<$elfFilename") || die("could not open $elfFilename for reading ($!), stopped");
binmode(IN_HANDLE);
my $binStr;
sysread(IN_HANDLE, $binStr, 4) || die("unable to read from '$elfFilename' ($!), stopped");
close(IN_HANDLE);
my $err = 1; # Start off assuming not an ELF file (0 later implies it is)
if (unpack("N", $binStr) == $ELF_MAGIC_NUMBER)
{
# Correct magic number - use readelf
my $cmd = getReadelf() . " -h $elfFilename";
print("Running command: $cmd\n") if ($verboseOutput > 1);
open(OLDERR, ">&STDERR");
close(STDERR);
# We need STDERR to exist and be redirected or it may get printed to the
# console anyway
my $tmpFile = createtmpname();
open(STDERR, ">$tmpFile");
if ($elfType eq "app")
{
# Check whether this is a standalone app, or a relocatable library by
# checking the Type line in the header (if it is DYN it is an RL)
my @output = `$cmd`;
unless (scalar(@output) > 0)
{
# We need to put stderr back before die can print a message
close(STDERR);
open(STDERR, ">&OLDERR");
close(OLDERR);
die("unable to run " . getReadelf() . ", stopped");
}
for my $line (@output)
{
if ($line =~ /\s*Type:\s+DYN\s+/)
{
$elfType = "reloc";
$elfArg = "-r";
$err = 0;
last;
}
elsif ($line =~ /\s*Type:\s+EXEC\s+/)
{
$err = 0;
}
}
}
else
{
open(OLDOUT, ">&STDOUT");
close(STDOUT);
$err = system($cmd);
open(STDOUT, ">&OLDOUT");
close(OLDOUT);
}
close(STDERR);
open(STDERR, ">&OLDERR");
close(OLDERR);
}
if ($err)
{
print("$elfFilename is not a 'DYN' or 'EXEC' ELF file - assuming it is an image\n") if ($verboseOutput);
return $filename;
}
else
{
print("$elfFilename is an '$elfType' ELF file - converting to an image...\n") if ($verboseOutput);
}
}
# Extract a cpu if specified
if ($filename =~ /^(?:[a-zA-Z]\:\\)?[^\:]+\:([0-9]+)/)
{
$cpu = $1;
}
elsif ($filename =~ /^(?:[a-zA-Z]\:\\)?[^\:]+\:([^\@\%]+)/)
{
usage("invalid CPU number '$1' in '$filename'\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -