📄 mkimage.pl
字号:
#
# Routine to create a data image file
#
sub createDataImage()
{
open(HANDLE, ">$options{o}") or die("unable to open '$options{o}' ($!), stopped");
binmode(HANDLE);
#
# Figure out params
#
my $start;
my $fileName;
my $placement = $PLACEMENT_TYPE_INPLACE | $SECTION_TYPE_SKIP;
if (($start, $fileName) = $options{b} =~ m/^(0x[[:xdigit:]]+),(.+)$/)
{
$start = hex($start);
}
elsif (($start, $fileName) = $options{b} =~ m/^([[:digit:]]+),(.+)$/)
{
}
elsif (($fileName, $start) = $options{b} =~ m/^([^@]+)@(0x[[:xdigit:]]+)$/)
{
$start = hex($start);
}
elsif (($fileName, $start) = $options{b} =~ m/^([^@]+)@([[:digit:]]+)$/)
{
}
else
{
($fileName) = $options{b} =~ m/^(.+)$/;
$placement = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_SKIP;
$start = 0;
}
unless (exists($options{d}))
{
my @time = localtime();
$options{d} = "data from $fileName (" .
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]) .
")";
}
#
# Get length of bin file
#
open(BINFILE, "<$fileName") or die("unable to open '$fileName' ($!), stopped");
binmode(BINFILE);
my $length = sysseek(BINFILE, 0, 2) or die("unable to seek in '$fileName' ($!), stopped");
sysseek(BINFILE, 0, 0) or die("unable to seek in '$fileName' ($!), stopped");
#
# The header...
#
my $fileHeader = pack('VZ32VVVV',
$IMAGE_FILE_MAGIC_NUM,
$options{d},
$IMAGE_TYPE_DATA,
0x00000000,
0x00000000,
1);
syswrite(HANDLE, $fileHeader, length($fileHeader)) or die("unable to write to '$options{o}' ($!), stopped");
my $section = pack('VVVV',
$placement,
$start,
$start,
$length);
syswrite(HANDLE, $section, length($section)) or die("unable to write to '$options{o}' ($!), stopped");
my $buffer;
sysread(BINFILE, $buffer, $length) or die("unable to read from '$fileName' ($!), stopped");
syswrite(HANDLE, $buffer, length($buffer)) or die("unable to write to '$options{o}' ($!), stopped");
close(BINFILE);
close(HANDLE);
if ($verboseOutput)
{
printf("\nGenerated $options{o} containing 1 blanks section @ 0x%08x, length 0x%08x\n", $start, $length);
}
}
#
# Routine to create a SigDMA data image file
#
sub createSigDMAImage()
{
# Figure out fields needed for image file header
# We will have 3 sections per SigDMA - 1 for info, one for data and one for
# the signature. Anything using SigDMAs will be expected to know the ordering
# of these sections.
my $numSections = 3 * scalar(@sigDMAFiles);
# Generate description based on filenames if none provided via -d option
unless (exists($options{d}))
{
$options{d} = "";
my $separator = "";
for my $sigDMAArrayRef (@sigDMAFiles)
{
my $sigDMAInfoFile;
my @sigDMAArgArray = @$sigDMAArrayRef;
if (scalar(@sigDMAArgArray) > 1)
{
$sigDMAInfoFile = $sigDMAArgArray[1];
}
else
{
$sigDMAInfoFile = $sigDMAArgArray[0];
}
$options{d} .= "$separator$sigDMAInfoFile";
$separator = ", ";
}
}
open(HANDLE, ">$options{o}") or die("unable to open '$options{o}' ($!), stopped");
binmode(HANDLE);
# Write image file header...
my $fileHeader = pack('VZ32VVVV',
$IMAGE_FILE_MAGIC_NUM,
$options{d},
$IMAGE_TYPE_CC_SIGDMA,
0x00000000,
0x00000000,
$numSections);
syswrite(HANDLE, $fileHeader, length($fileHeader)) or die("unable to write to '$options{o}' ($!), stopped");
# Now deal with the sections...
# Note: The section destination is always the uncompressed length for SigDMA
# images.
# Record the file location of the start of the section headers, and ensure
# that the last byte existing in the file is at the end of the region that
# will contain these headers.
my $startSectionHeaders = sysseek(HANDLE, 0, 1);
sysseek(HANDLE, $startSectionHeaders + ($numSections * 16) - 1, 0);
syswrite(HANDLE, "0", 1);
for (my $count = 0; $count < scalar(@sigDMAFiles); $count++)
{
my $ref = $sigDMAFiles[$count];
my @sigDMAArgArray = @$ref;
my ($srcAddr, $srcLen, $dstAddr, $dstLen, $sigAddr, $enAddr, $enData,
$dmaVCCAddr, $dmaVCCValue, $dmaSTCAddr, $dmaSTCValue, $data);
my ($sigDMAInfoFile,$tmpBinFile);
# Depending on whether we have 1 or 2 entries in @sigDMAArgArray we select the
# type of file we are processing:
# 1 - this is a SigDMA conf file with the SigDMA info followed by a list of
# words (the SigDMA data)
# 2 - this is a binary input file, text SigDMA info file as 2nd entry
if (scalar(@sigDMAArgArray) > 1)
{
my $sigDMAFile = $sigDMAArgArray[0];
# Binary input file, with text SigDMA info file
$sigDMAInfoFile = $sigDMAArgArray[1];
# Read the SigDMA info file
($srcAddr, $dstAddr, $sigAddr, $enAddr, $enData, $null, $dmaVCCAddr,
$dmaVCCValue, $dmaSTCAddr, $dmaSTCValue) =
readSigDMAInfoFile($sigDMAInfoFile, 0);
# Read the binary
open(IN_FILE, $sigDMAFile) || die("failed to open binary SigDMA file $sigDMAFile ($!), stopped");
binmode(IN_FILE);
$dstLen = (stat($sigDMAFile))[7];
sysread(IN_FILE, $data, $dstLen);
close(IN_FILE);
# Prepare to modify binary in temporary file
$tmpBinFile = createtmpname();
copy($sigDMAFile, $tmpBinFile); # Don't modify original file
}
else
{
# Text SigDMA input file only (data expected in file)
# Can mostly be common with above....
$sigDMAInfoFile = $sigDMAArgArray[0];
# Read the SigDMA info file
($srcAddr, $dstAddr, $sigAddr, $enAddr, $enData, $data, $dmaVCCAddr,
$dmaVCCValue, $dmaSTCAddr, $dmaSTCValue) =
readSigDMAInfoFile($sigDMAInfoFile, 1);
$dstLen = length($data);
# Put the data from the info file into a temporary binary file
my $sigDMAFile = createtmpname();
open(OUT_FILE, ">$sigDMAFile") || die("failed to open temporary file $sigDMAFile ($!), stopped");
binmode(OUT_FILE);
syswrite(OUT_FILE, $data);
close(OUT_FILE);
# We modify $tmpBinFile, but $sigDMAFile is a temporary, so we just use that
$tmpBinFile = $sigDMAFile;
}
print("SigDMA input length is $dstLen bytes\n") if ($verboseOutput);
# We now know the destination length - pad by the correct amount to get the
# source length (add 5 words and round up to next multiple of 64)
my $paddingBytes = 0;
$srcLen = $dstLen + 20;
if ($srcLen % 64)
{
# Add 64 and then mask off any excess bits to make it a multiple of 64
$srcLen += 64;
$srcLen &= 0xFFFFFFC0;
$paddingBytes = $srcLen - $dstLen - 20;
printf("%d bytes padding added before SigDMA config words\n", $paddingBytes) if ($verboseOutput);
}
$data .= pack("C", 0) x $paddingBytes if ($paddingBytes);
# $data now has everything needed for the 1st of the 2 data sections
# Write out the SigDMA info section
my $infoSection = pack('VVVVVVV', $srcAddr, $srcLen/4, $dstAddr, $dstLen/4,
$sigAddr, $enAddr, $enData);
my $sectionHeader = pack('VVVV', $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_SKIP,
0, length($infoSection), length($infoSection));
# Section header in section headers location
sysseek(HANDLE, $startSectionHeaders + ($count * 3 * 16), 0);
syswrite(HANDLE, $sectionHeader, length($sectionHeader)) or die("unable to write to '$options{o}' ($!), stopped");
# Info section at end of file
sysseek(HANDLE, 0, 2);
syswrite(HANDLE, $infoSection, length($infoSection)) or die("unable to write to '$options{o}' ($!), stopped");
# Write out the SigDMA data section
my $dataSectionType;
if ($options{p} eq "deflate")
{
warn("Warning: Ignoring source address from $sigDMAInfoFile as data is to " .
"be deflated.\n") if ($srcAddr);
$srcAddr = 0;
$dataSectionType = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_DEFLATED;
}
else
{
$dataSectionType = $SECTION_TYPE_SKIP;
if ($srcAddr)
{
$dataSectionType |= $PLACEMENT_TYPE_INPLACE;
}
else
{
$dataSectionType |= $PLACEMENT_TYPE_ANYWHERE;
}
}
my $uncompressedLen = length($data);
if ($options{p} eq "deflate")
{
# Init compressor
my $stream = deflateInit(-Level => Z_BEST_COMPRESSION()) or die("unable to create deflation stream, stopped");
my $compressed;
my $status;
# Compress it
($data, $status) = $stream->deflate($data);
$status == Z_OK() or die("deflation failed, stopped");
($compressed, $status) = $stream->flush() ;
$status == Z_OK() or die("deflation flush failed, stopped");
$data .= $compressed;
}
$sectionHeader = pack('VVVV', $dataSectionType, $srcAddr, $uncompressedLen,
length($data));
# Section header in section headers location
sysseek(HANDLE, $startSectionHeaders + ((1 + (3 * $count)) * 16), 0);
syswrite(HANDLE, $sectionHeader, length($sectionHeader)) or die("unable to write to '$options{o}' ($!), stopped");
# SigDMA data section at end of file
sysseek(HANDLE, 0, 2);
syswrite(HANDLE, $data, length($data)) or die("unable to write to '$options{o}' ($!), stopped");
# Clear data so the perl interpreter can reduce memory usage if it wants...
$data = "";
# Get the signature of the binary - we need to append any padding, and the 5
# extra words which are signed with the SigDMA data
my $tmpSigFile = createtmpname();
open(OUT_FILE, ">>$tmpBinFile") || die("failed to open temporary file $tmpBinFile for appending ($!), stopped");
binmode(OUT_FILE);
sysseek(OUT_FILE, 0 , 2); # Seek to end of file
# Write any padding words needed
if ($paddingBytes)
{
# We 0 padded our data, so do the same when signing
syswrite(OUT_FILE, pack("V", 0) x ($paddingBytes / 4));
}
# Write 5 SigDMA info words
syswrite(OUT_FILE, pack("VVVVV", $srcLen/4, $dstAddr, $dstLen/4, $enAddr, $enData));
close(OUT_FILE);
runSigningTool($options{k}, $tmpBinFile, $tmpSigFile, $dmaVCCAddr,
$dmaVCCValue, $dmaSTCAddr, $dmaSTCValue);
# Read the signature file
my $signature = readBinFileToStr($tmpSigFile);
my $sigLen = length($signature);
if ($lenDigitalSignature != $sigLen)
{
die("expected $lenDigitalSignature byte signature, but saw a $sigLen byte signature, stopped");
}
# $signature now contains the signature required to go into the 2nd of the
# 2 data sections => Write out the SigDMA signature data section.
my $signatureSectionType;
if ($ALLOW_SIGNATURE_DEFLATION && $options{p} eq "deflate")
{
warn("Warning: Ignoring signature address from $sigDMAInfoFile as " .
"signature is to be deflated.\n") if ($sigAddr);
$sigAddr = 0;
$signatureSectionType = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_DEFLATED;
}
else
{
$signatureSectionType = $SECTION_TYPE_SKIP;
if ($sigAddr)
{
$signatureSectionType |= $PLACEMENT_TYPE_INPLACE;
}
else
{
$signatureSectionType |= $PLACEMENT_TYPE_ANYWHERE;
}
}
if ($ALLOW_SIGNATURE_DEFLATION && $options{p} eq "deflate")
{
# Init compressor
my $stream = deflateInit(-Level => Z_BEST_COMPRESSION()) or die("unable to create deflation stream, stopped");
my $compressed;
my $status;
# Compress it
($signature, $status) = $stream->deflate($signature);
$status == Z_OK() or die("deflation failed, stopped");
($compressed, $status) = $stream->flush() ;
$status == Z_OK() or die("deflation flush failed, stopped");
$signature .= $compressed;
}
$sectionHeader = pack('VVVV', $signatureSectionType, $sigAddr, $sigLen,
length($signature));
# Section header in section headers location
sysseek(HANDLE, $startSectionHeaders + ((2 + (3 * $count)) * 16), 0);
syswrite(HANDLE, $sectionHeader, length($sectionHeader)) or die("unable to write to '$options{o}' ($!), stopped");
# SigDMA signature section at end of file
sysseek(HANDLE, 0, 2);
syswrite(HANDLE, $signature, $sigLen) or die("unable to write to '$options{o}' ($!), stopped");
# All done for this SigDMA...
if ($verboseOutput)
{
print("SigDMA from $sigDMAInfoFile:\n Source address: ");
if ($srcAddr)
{
printf("0x%08x\n", $srcAddr);
}
else
{
print("should be set when put into final ROM image form\n");
}
printf(" Source length: 0x%08x words\n Destination address: 0x%08x\n Destination
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -