⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkimage.pl

📁 采用ST20 CPU的机顶盒的烧写程序
💻 PL
📖 第 1 页 / 共 5 页
字号:
#
# 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 + -