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

📄 mkbinrom.pl

📁 采用ST20 CPU的机顶盒的烧写程序
💻 PL
📖 第 1 页 / 共 5 页
字号:
  my $endOffset = $offset + length($$binaryRef);
  # We first check to see if we overlap any used ranges.  If not we call
  # replaceBytesInFlashFile to add the data
  for (my $count = 0; $count < @usedRanges; $count++)
  {
    last if ($offset < $usedRanges[$count][0]);
    if (overlaps($offset, $endOffset, $usedRanges[$count][0], $usedRanges[$count][1]))
    {
      my $errStr = sprintf("could not add $desc at 0x%08x to 0x%08x - overlaps existing data in range 0x%08x to 0x%08x, stopped",
                           $offset, $endOffset, $usedRanges[$count][0], $usedRanges[$count][1]);
      die($errStr);
    }
  }
  replaceBinaryInFlashFile($desc, $offset, $binaryRef, "Added");
}

#
# Given an offset from $FLASH_START and a list of bytes, puts the bytes in the
# FLASH file.
# Args: description of what we're putting in place
#       offset
#       reference to list of bytes
#       optional override string for "Replaced" in the verbose output
#
sub replaceBytesInFlashFile($$$;$)
{
  my $desc = shift(@_);
  my $offset = shift(@_);
  my $byteArrayRef = shift(@_);
  my $action;
  if (@_)
  {
    $action = shift(@_);
  }
  else
  {
    $action = "Replaced";
  }
  
  replaceBinaryInFlashFile($desc, $offset, \pack("C*", @$byteArrayRef), $action);
}

#
# Given an offset from $FLASH_START and binary string, puts the binary in the
# FLASH file.
# Args: description of what we're putting in place
#       offset
#       binary string
#       optional override string for "Replaced" in the verbose output
#
sub replaceBinaryInFlashFile($$$;$)
{
  my $desc = shift(@_);
  my $offset = shift(@_);
  my $binaryRef = shift(@_);
  my $action;
  if (@_)
  {
    $action = shift(@_);
  }
  else
  {
    $action = "Replaced";
  }
  
  die("output binary file would exceed 512MB.  If this is not in error edit this script, stopped") if ($offset > 512 * 1024 * 1024);
  
  my $topByte = $offset + length($$binaryRef) - 1;
  
  my $eofOff = sysseek(FLASHFILE, 0, 2);
  if ($offset > $eofOff)
  {
    # Extending size of file - write 0xff's in the gap (default unprogrammed
    # value for bytes in FLASH)
    syswrite(FLASHFILE, pack("C", 0xff) x ($offset - $eofOff));
  }
  if (sysseek(FLASHFILE, $offset, 0) != $offset)
  {
    die("failed to seek to offset $offset in internal representation of FLASH, stopped");
  }
  syswrite(FLASHFILE, $$binaryRef);
  
  # Update @usedRanges if necessary
  useRange($offset, $topByte);

  printf("$action %d bytes in FLASH, range 0x%08x to 0x%08x ($desc)\n", 
         length($$binaryRef), $offset, $topByte) if ($verboseOutput);
  if ($verboseOutput > 2)
  {
    print("Bytes written:\n");
    my $count = 0;
    while ($count < length($$binaryRef))
    {
      print(join(" ", map(sprintf("%02x", $_), unpack("C32", substr($$binaryRef, $count)))) . "\n");
      $count += 32;
    }
  }
}

#
# Extend the size of the FlashFile to cover the given offset - do not call
# useRange as we don't actually want to prevent anything overwriting the new
# bytes which will initially be 0xFF.
#
sub extendFlashFileToOffset($)
{
  my $offset = shift(@_);

  my $eofOff = sysseek(FLASHFILE, 0, 2);
  if ($offset > $eofOff)
  {
    # Extending size of file - write 0xff's in the gap (default unprogramed
    # value for bytes in FLASH)
    syswrite(FLASHFILE, pack("C", 0xff) x ($offset - $eofOff));
  }
  printf("Extended FLASH to cover offset 0x%08x\n", $offset) if ($verboseOutput > 2);
}

#
# Sub to copy a chunk of the FLASH file to another binary file
#
sub copyFlashFile($$$)
{
  my $filename = shift(@_);
  my $offset = shift(@_);
  my $endOffset = shift(@_);
  my $size = $endOffset - $offset;
  my $written = 0;
  open(OUT_FILE, "$filename") || die("could not open $filename for writing, stopped");
  binmode(OUT_FILE);
  while ($offset < $endOffset)
  {
    my $chunkEnd = $offset + (512 * 1024); # Read in 512KB chunks
    if ($chunkEnd > $endOffset)
    {
      $chunkEnd = $endOffset;
    }
    my $binary = getFlashFileBinary($offset, $chunkEnd);
    $written += syswrite(OUT_FILE, $binary);
    $offset = $chunkEnd;
  }
  if ($written != $size)
  {
    die("failed to write " . $size . " bytes from FLASH representation to $filename, stopped");
  }
  close(OUT_FILE);
}

#
# Given 2 offsets from $FLASH_START, returns a reference to a byte array of the
# contents.
#
sub getFlashFileBytes($$)
{
  my $offset1 = shift(@_);
  my $offset2 = shift(@_);

  my $binary = getFlashFileBinary($offset1, $offset2);
  my $binaryLen = length($binary);
  my @byteArray = unpack("C$binaryLen", $binary);

  return \@byteArray;
}

#
# Given 2 offsets from $FLASH_START, returns a binary string of the contents.
# Will pad the string with 0xFF's if request is longer than what is known, and
# extend the size of the FlashFile to cover it.
#
sub getFlashFileBinary($$)
{
  my $offset1 = shift(@_);
  my $offset2 = shift(@_);
  
  die("reverse access of range in FLASH requested, stopped") if ($offset2 <= $offset1);
  
  my $len = $offset2 - $offset1;
  my $binary;
  if (sysseek(FLASHFILE, $offset1, 0) != $offset1)
  {
    die("failed to seek to offset $offset1 in internal representation of FLASH, stopped");
  }
  my $binaryLen = sysread(FLASHFILE, $binary, $len);
  
  if (!defined($binaryLen))
  {
    die("failed to read data from internal representation of FLASH ($!), stopped");
  }
  
  if ($binaryLen < $len)
  {
    $binary .= pack("C", 0xFF) x ($len - $binaryLen);
    extendFlashFileToOffset($offset2);
  }
  
  return $binary;
}

#
# Directly modify our representation of FLASH with relocations using 1st arg as
# offset, section info in 2nd arg, architecture in 3rd arg, and the symbols and
# relocations section numbers in @sectionInfo as the 4th and 5th args.
#
sub performRelocations($$$$$)
{
  my $ffOffset = shift(@_);
  my $sectionInfoRef = shift(@_);
  my @sectionInfo = @$sectionInfoRef;
  my $arch = shift(@_);
  my $symbolsSection = shift(@_);
  my $relocationsSection = shift(@_);

  print("Performing relocations...\n") if ($verboseOutput);

  if ($arch != $CPU_ARCH_LX && $arch != $CPU_ARCH_SH4)
  {
    die("architecture type $arch detected, but unsupported by relocation code, stopped");
  }

  my $relocData = $sectionInfo[$relocationsSection]{data};
  my $numRelocs = $sectionInfo[$relocationsSection]{len} / 12;
  my $symbolData = $sectionInfo[$symbolsSection]{data};
  my $numSyms = $sectionInfo[$symbolsSection]{len} / (12 + 1 + 1 + 2);

  for (my $count = 0; $count < $numRelocs; $count++)
  {
    my %curReloc;
    my $value;
    ($curReloc{offset}, $curReloc{info}, $curReloc{addend}) = 
      unpack("VVV", substr($relocData, $count * 12, 12));

    if (($curReloc{info} & 0xFF) == $R_LX_32 ||
        ($curReloc{info} & 0xFF) == $R_LX_JMP_SLOT ||
        ($curReloc{info} & 0xFF) == $R_SH_DIR32)
    {
      my $symbol = $curReloc{info} >> 8;
      if ($symbol >= $numSyms)
      {
        die("invalid relocation symbol reference ($symbol), stopped");
      }
      $value = $FLASH_START + $ffOffset +
               unpack("V", substr($sectionInfo[$symbolsSection]{data}, ($symbol * 16) + 4, 4));
    }
    elsif (($curReloc{info} & 0xFF) == $R_SH_RELATIVE ||
           ($curReloc{info} & 0xFF) == $R_LX_REL32)
    {
      $value = $FLASH_START + $ffOffset + $curReloc{addend};
    }
    else
    {
      die("unsupported relocation (type " . ($curReloc{info} & 0xFF) . "), stopped");
    }
    replaceBinaryInFlashFile("relocation", $ffOffset + $curReloc{offset}, \pack("V", $value));
  }
  print("Relocations complete.\n") if ($verboseOutput);
}

#
# Sub that processes a boot vector image file directly into our representation
# of FLASH.
#
sub processBootVector($)
{
  my $bootVecFile = shift(@_);

  # If it's an ELF file, convert it to an image file and change $bootVecFile accordingly
  $bootVecFile = convertIfElf("bootvec", $bootVecFile);

  # Strip any extra stuff from the filename in case conversion failed
  $bootVecFile =~ /^((?:[a-zA-Z]\:\\)?[^\@\:\%]+)/;
  $bootVecFile = $1;

  my $bootVecBuffer = "";
  open(IN_FILE, $bootVecFile) || die("failed to open boot vector file " .
                                     "$bootVecFile ($!), stopped");
  binmode(IN_FILE);

  # Read header information
  sysread(IN_FILE, $bootVecBuffer, $IMG_FILE_HEADER_LEN);
  my ($magicNum, $desc, $cpuNum, $stackAddr, $entryAddr, $numSections, $secType, $srcAddr, $dstAddr, $secLen) = 
    readImgHeader($bootVecBuffer, $bootVecFile);

  if ($numSections != 1)
  {
    die("boot vectors must have just 1 section, stopped");
  }

  my $realCpuNum = $cpuNum & $CPU_NUMBER_MASK;

  if ($realCpuNum == 0)
  {
    # This is the master CPU's boot vector.  The architecture of this file is
    # the architecture of the CPU which will copy from ROM to RAM - the master
    # CPU.
    $useST40Addressing = (($cpuNum & $CPU_ARCH_MASK) == $CPU_ARCH_SH4);
  }

  # Length of section must be less than or equal to $FLASH_BOOT_VECTOR_SIZE
  if ($secLen > $FLASH_BOOT_VECTOR_SIZE)
  {
    die("boot vector in $bootVecFile is too big - is $secLen bytes, but " .
        "must be less than $FLASH_BOOT_VECTOR_SIZE, stopped");
  }

  my $calcLoadAddr = ($realCpuNum * $FLASH_BOOT_VECTOR_SIZE) + $FLASH_START;
  if ($secType == $PLACEMENT_TYPE_INPLACE)
  {
    if ($calcLoadAddr != $srcAddr || $calcLoadAddr != $dstAddr)
    {
      die("boot vector in $bootVecFile has a run in-place section, but " .
          "it was expected to be at $calcLoadAddr, not $srcAddr, stopped");
    }
  }

  # Put the description in position
  $desc .= pack("C", 0) x (32 - length($desc)) if (length($desc) < 32);
  replaceBinaryInFlashFile("Boot vector description for CPU $realCpuNum",
                          ($FLASH_BOOTVEC_DESC_OFF + ($realCpuNum * 0x20)),
                          \$desc);

  # Put the code into our representation of FLASH
  my $code = "";
  sysread(IN_FILE, $code, $secLen);

  close(IN_FILE);
  $code .= pack("C*", 0) x (40 - length($code)) if (length($code) < 40);
  addBinaryToFlashFile("Boot vector for CPU $realCpuNum", ($realCpuNum * 0x40), 
                       \$code);
}

#
# Sub that processes a bootstrap image file into our representation of FLASH.
# Returns the top address used.
#
sub processBootstrap($)
{
  my $bootstrapFile = shift(@_);
  my $topAddr = 0;

  # If it's an ELF file, convert it to an image file and change $bootstrapFile 
  # accordingly
  $bootstrapFile = convertIfElf("bootstrap", $bootstrapFile);

  # Strip any extra stuff from the filename
  $bootstrapFile =~ /^((?:[a-zA-Z]\:\\)?[^\@\:\%]+)/;
  $bootstrapFile = $1;

  my $bootstrapBuffer = "";
  open(IN_FILE, $bootstrapFile) || die("failed to open bootstrap file $bootstrapFile ($!), stopped");
  binmode(IN_FILE);

  # Read header information
  sysread(IN_FILE, $bootstrapBuffer, $IMG_FILE_HEADER_LEN);
  my ($magicNum, $desc, $cpuNum, $stackAddr, $entryAddr, $numSections, $secType, $srcAddr, $dstAddr, $secLen) = 
    readImgHeader($bootstrapBuffer, $bootstrapFile);

  if ($numSections < 1)
  {
    die("bootstraps should contain 1 or more sections - usually a code " .
        "section and optional SYMBOLS and RELOCATIONS sections, stopped");
  }

  my $realCpuNum = ($cpuNum & $CPU_NUMBER_MASK);
  my $cpuArchType = ($cpuNum & $CPU_ARCH_MASK);

  # Check section type
  if (($secType & $SECTION_TYPE_MASK) != $SECTION_TYPE_SKIP)

⌨️ 快捷键说明

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