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

📄 mkcommon.pm

📁 采用ST20 CPU的机顶盒的烧写程序
💻 PM
📖 第 1 页 / 共 3 页
字号:

#
# Reads the header from an image file, does some checks and returns some info
#
sub readImgHeader($$)
{
  my $headerBuffer = shift(@_);
  my $filename = shift(@_);
  my ($magicNum, $desc, $cpuNum, $stackAddr, $entryAddr, $numSections, $secType, $srcAddr, $dstAddr, $secLen) = 
    unpack("VZ32V8", $headerBuffer);

  if ($magicNum != $IMAGE_FILE_MAGIC_NUM)
  {
    die("$filename does not appear to be a valid image file, stopped");
  }

  if ($verboseOutput)
  {
    my $tempString;
    my $isRelocLib = 0;
    print("\n$filename:\n");
    print("\tImage description: $desc\n");
    if (($cpuNum & $IMAGE_TYPE_MASK) == $IMAGE_TYPE_RELOC_LIB)
    {
      $tempString = "Relocatable library";
      $isRelocLib = 1;
    }
    elsif (($cpuNum & $IMAGE_TYPE_MASK) == $IMAGE_TYPE_DATA)
    {
      $tempString = "Data image";
    }
    elsif (($cpuNum & $IMAGE_TYPE_MASK) == $IMAGE_TYPE_CC_SIGDMA)
    {
      $tempString = "Cryptocore SigDMA image";
    }
    else
    {
      $tempString = "Standard image";
    }
    print("\tImage type: $tempString\n");
    
    my $arch = ($cpuNum & $CPU_ARCH_MASK);
    $tempString = "Unknown";
    $tempString = "ST40" if ($arch == $CPU_ARCH_SH4);
    $tempString = "ST200" if ($arch == $CPU_ARCH_LX);
    $tempString = "ST20" if ($arch == $CPU_ARCH_ST20);
    print("\tArchitecture: $tempString\n");
    print("\tFor CPU: " . ($cpuNum & $CPU_NUMBER_MASK) . "\n");
    printf("\tStack addr: 0x%08x, ", $stackAddr);
    if ($isRelocLib)
    {
      printf("Uncompressed size: 0x%08x\n", $entryAddr);
    }
    else
    {
      printf("Entry addr: 0x%08x\n", $entryAddr);
    }
    print("\tNumSections: $numSections\n");
    printf("\tSec type: 0x%08x, src addr: 0x%08x, dst addr: 0x%08x, sec len: $secLen\n\n",
           $secType, $srcAddr, $dstAddr);
  }

  if (($cpuNum & $CPU_NUMBER_MASK) >= $::FLASH_MAX_CPUS)
  {
    die("image in $filename is for CPU number " . 
        ($cpuNum & $CPU_NUMBER_MASK) . 
        " - must be in range 0 to " . ($::FLASH_MAX_CPUS - 1) . ", stopped");
  }

  return ($magicNum, $desc, $cpuNum, $stackAddr, $entryAddr, $numSections, 
          $secType, $srcAddr, $dstAddr, $secLen);
}

#
# Routine to copy a list of sections from an ELF file to a binary file
#
# Params: space separated list of names in a string, ELF file, output binary file
#
sub copySectionsToFile($$$)
{
  my $nameList = shift(@_);
  my $elfFile = shift(@_);
  my $outFile = shift(@_);

  # These lines should add -j before every section name (for passing to objcopy)
  ($nameList = $nameList) =~ s/ / -j /g;
  ($nameList = $nameList) =~ s/^/-j /g;

  # Suppress any (harmless) warnings when processing ST200 images with
  # objcopy by redirecting STDERR to a temporary file.
  my $errFile = createtmpname();
  my $dumpCmd = getObjcopy() . " -O binary -I elf32-little $nameList $elfFile $outFile 2>$errFile";
  # NOTE: when we output more than one section using objcopy in binary mode,
  # padding is inserted (0x00's)

  my $status = system($dumpCmd);
  die("unable to execute '$dumpCmd' ($status), stopped") unless ($status == 0);
}

#
# Sub to read an entire binary file into a string, which is returned
#
sub readBinFileToStr($)
{
  my $filename = shift(@_);
  my $str;
  open(IN_HANDLE, $filename) or die("unable to open '$filename' (!$), stopped");
  binmode(IN_HANDLE);
  my $fileLen = (stat($filename))[7];
  sysread(IN_HANDLE, $str, $fileLen) or die("unable to read from '$filename' ($!), stopped");
  close(IN_HANDLE);
  return $str;
}

#
# Sub to read a SigDMA info file, returning information retrieved in an array
#
sub readSigDMAInfoFile($$)
{
  my $sigDMAInfoFile = shift(@_);
  my $getDataToo = shift(@_);

  open(IN_FILE, "<$sigDMAInfoFile") || die("failed to open SigDMA info " .
                                           "file $sigDMAInfoFile ($!), stopped");
  my $srcAddr = 0;     # Default to being assigned by mkbinrom.pl
  my $dstAddr = undef;
  my $sigAddr = 0;     # Default to being assigned by mkbinrom.pl
  my $enAddr = undef;
  my $enData = undef;
  my $data = "";
  my $dmaVCCAddr = undef;
  my $dmaVCCValue = undef;
  my $dmaSTCAddr = undef;
  my $dmaSTCValue = undef;
  my $line;
  my $readingData = 0;
  while ($line = <IN_FILE>)
  {
    next if ($line =~ /^\s*#/);  # Comment line
    next if ($line =~ /^\s*$/); # Blank line
    if ($readingData)
    {
      # Remove any comment from $line
      if ($line =~ /^([^#]+)#/)
      {
        $line = $1;
      }
      # Split line on whitespace and append each word to our binary string, $data
      my @words = split(/\s+/, $line);
      foreach my $word (@words)
      {
        if ($word =~ /($HEX_NUM_REGEXP)/)
        {
          $data .= pack("V", hex($1));
        }
        else
        {
          # If it's whitespace, ignore silently...
          if ($word !~ /^\s*$/)
          {
            warn("Warning: Ignoring invalid input in data section of $sigDMAInfoFile - \"$word\"\n");
          }
        }
      }
    }
    else
    {
      # We're looking for info lines...or the "[data]" marker
      if ($line =~ /^\s*(source|src)_addr(ess)?\s+($HEX_NUM_REGEXP)/)
      {
        $srcAddr = hex($3);
        if ($srcAddr % 32)
        {
          my $oldSrcAddr = $srcAddr;
          $srcAddr &= 0xFFFFFFE0;
          my $errStr = sprintf("Warning: SigDMA source address of 0x%08x is not 32 byte aligned - using 0x%08x\n", $oldSrcAddr, $srcAddr);
          warn($errStr);
        }
      }
      elsif ($line =~ /^\s*dest(ination)?_addr(ess)?\s+($HEX_NUM_REGEXP)/)
      {
        $dstAddr = hex($3);
        if ($dstAddr % 4)
        {
          die("SigDMA destination address of 0x%08x is not 4 byte aligned, stopped");
        }
      }
      elsif ($line =~ /^\s*sig(nature)?_addr(ess)?\s+($HEX_NUM_REGEXP)/)
      {
        $sigAddr = hex($3);
        if ($sigAddr % 32)
        {
          my $errStr = sprintf("Warning: SigDMA signature address of 0x%08x is not 32 byte aligned - ", $sigAddr);
          warn($errStr);
          $sigAddr &= 0xFFFFFFE0;
          printf("using 0x%08x\n", $sigAddr);
        }
      }
      elsif ($line =~ /^\s*en(able)?_addr(ess)?\s+($HEX_NUM_REGEXP)/)
      {
        $enAddr = hex($3);
        if ($enAddr % 4)
        {
          die("SigDMA enable address of 0x%08x is not 4 byte aligned, stopped");
        }
      }
      elsif ($line =~ /^\s*en(able)?_data\s+($HEX_NUM_REGEXP|[0-9]+)/)
      {
        $enData = hex($2);
      }
      elsif ($line =~ /^\s*vcc_addr(ess)?\s+($HEX_NUM_REGEXP|[0-9]+)/)
      {
        $dmaVCCAddr = hex($2);
      }
      elsif ($line =~ /^\s*vcc_val(ue)?\s+($HEX_NUM_REGEXP|[0-9]+)/)
      {
        $dmaVCCValue = hex($2);
      }
      elsif ($line =~ /^\s*stc_addr(ess)?\s+($HEX_NUM_REGEXP|[0-9]+)/)
      {
        $dmaSTCAddr = hex($2);
      }
      elsif ($line =~ /^\s*stc_val(ue)?\s+($HEX_NUM_REGEXP|[0-9]+)/)
      {
        $dmaSTCValue = hex($2);
      }
      elsif ($line =~ /^\s*\[data\]/)
      {
        last if (!$getDataToo);
        $readingData = 1;
      }
    }
  }
  close(IN_FILE);
  
  # Check all values needed have been filled
  die("destination_address not seen in SigDMA info file $sigDMAInfoFile, stopped") if (!defined($dstAddr));
  die("enable_address not seen in SigDMA info file $sigDMAInfoFile, stopped") if (!defined($enAddr));
  die("enable_data not seen in SigDMA info file $sigDMAInfoFile, stopped") if (!defined($enData));
  if ($getDataToo && length($data) == 0)
  {
    die("supposed to retrieve data from $sigDMAInfoFile, but none found, stopped");
  }
  # All done
  return ($srcAddr, $dstAddr, $sigAddr, $enAddr, $enData, $data, $dmaVCCAddr,
          $dmaVCCValue, $dmaSTCAddr, $dmaSTCValue);
}

#
# Sub to check a section is a reserve section (.post_(text|rodata)_reserve and
# return the offset of the config table entry.  -1 is returned if
# this is not a reserve section.  A reference to section info is passed in,
# which takes the form [secType, srcAddr, destAddr, size, data].  The second
# argument is non-zero if the caller wishes to check for the presence of the
# 0xDEADADDA value in the next block config table entry address.
#
sub getCTEoffset($$)
{
  my $sec = shift(@_);
  my $checkDeadAdda = shift(@_);
  if ($sec->{len} == $RESERVE_1024_BIT_KEY || $sec->{len} == $RESERVE_2048_BIT_KEY)
  {
    my $lenDigitalSignature = 128;
    if ($sec->{len} == $RESERVE_2048_BIT_KEY)
    {
      $lenDigitalSignature += 128;
    }
    # We don't have section names in .img files, so we can only use the
    # size, type and content of sections to identify them as reserve
    # sections
    if (($sec->{type} & $defaultSectionTypes{"copy"}) == $defaultSectionTypes{"copy"} ||
        ($sec->{type} & $defaultSectionTypes{"inplace"}) == $defaultSectionTypes{"inplace"})
    {
      # The 0xDEADADDA word should be in the location we expect to put the
      # next_block_cfg_add field (only check if told to)

      # In order to help us out, mkimage.pl puts the size of the section this is a
      # reserve section for, in the first word of this section's data.
      my $signedBlockLen = unpack("V", $sec->{data});
      if ($signedBlockLen < 4)
      {
        # Signed section should be at least 4 bytes long (without padding to the
        # correct size).
        return -1;
      }

      # $padSize is the amount of padding to the place the signature will go
      my $padSize = 16; # We always have at least 16 bytes padding to ensure
                        # code cannot be in the last 16 bytes of the signed
                        # region
      my $misSize = ($signedBlockLen + $padSize) % 64;
      if ($misSize)
      {
        $padSize += 64 - $misSize;
      }

      my $cteOffset = $padSize + $lenDigitalSignature;
      if ($checkDeadAdda)
      {
        my $checkStr = substr($sec->{data}, $cteOffset + 16, 4);
        if ($checkStr ne pack("V", 0xDEADADDA))
        {
          # The magic number 0xDEADADDA was not in the right place - return -1
          return -1;
        }
      }
      return $cteOffset;
    }
  }
  # Not a reserve section - return -1.
  return -1;
}

#
# Write a given array of byte values to the given filename as binary (filename
# is 1st arg and should include the mode - append or write as > or >>).
# Undefined values in the array will be padded with 0xFF.
#
sub writeByteArray($$)
{
  my $filename = shift(@_);
  my $byteArrayRef = shift(@_);
  open(OUT_FILE, "$filename") || die("could not open $filename for writing, stopped");
  binmode(OUT_FILE);
  my $noUndefListRef = noUndef(0, $byteArrayRef, 0xFF);
  syswrite(OUT_FILE, pack("C*", @$noUndefListRef), scalar(@$byteArrayRef));
  close(OUT_FILE);
  print("Written " . scalar(@$byteArrayRef) . " bytes to $filename\n") if ($verboseOutput);
}

#
# Sub which returns 0 if the 2 ranges specified overlap each other.
# Args: start range 1 (inclusive)
#       end range 1 (exclusive)
#       start range 2 (inclusive)
#       end range 2 (exclusive)
sub overlaps($$$$)
{
  my $s1 = shift(@_);
  my $e1 = shift(@_);
  my $s2 = shift(@_);
  my $e2 = shift(@_);
  
  # Zero length?
  if ($s1 == $e1 || $s2 == $e2)
  {
    return 0;
  }
  
  if ($s1 > $s2)
  {
    if ($s1 < $e2)
    {
      return 1;
    }
  }
  else
  {
    if ($s2 < $e1)
    {
      return 1;
    }
  }
  return 0;
}

return 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -