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

📄 mkbinrom.pl

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

  # Extract a default section type if specified
  if ($filename =~ /\%(inplace|pic|deflate|copy)/)
  {
    $defSecType = $1;
  }
  elsif ($filename =~ /[^\%]+\%([^\:\@]+)/)
  {
    usage("unrecognised default section type '$1' in '$filename'\n");
  }

  if ($elfType eq "reloc" && $defSecType ne "copy" && $defSecType ne "deflate")
  {
    die("section type for relocatable library $elfFilename must be \"copy\" or \"deflate\", stopped");
  }

  # Start creating our command line
  my @time = localtime();
  # Our description is the image type, cpu num and date and time
  my $desc = "$cpu: $elfType (" .
             sprintf("%02d/%02d/%02d, %02d:%02d", $time[3], $time[4] + 1, 
                     (($time[5] > 100) ? ($time[5] - (int($time[5]/100)*100)): $time[5]),
                     $time[2], $time[1]) . ")";
  my $cmdLine = $^X . " -w $PATH_TO_THIS_SCRIPT/mkimage.pl $elfArg $elfFilename " .
                "-o $baseName.img -p $defSecType -d \"$desc\"";
  if ($signingKeyFile ne "" && ($elfType eq "app" || $elfType eq "reloc"))
  {
    $cmdLine .= " -k $signingKeyFile";

    # Also add the inflash option if the app is inplace (assume inplace means
    # this is going in FLASH).
    if ($elfType eq "app" && $defSecType eq "inplace")
    {
      $cmdLine .= " -inflash";
    }
  }
  $cmdLine .= " -c $cpu" if ($cpu != 0);
  $cmdLine .= " -V$verboseOutput" if ($verboseOutput);
  $cmdLine .= " -t $chipType" if ($chipType ne "");
  if (($elfType eq "app" || $elfType eq "reloc") &&
      defined($stcValue) && $stcValue != 0)
  {
    warn("Warning: STC will be same for boot sector and signature of " .
         "$elfFilename.  Use mkimage.pl directly to specify different values.\n");
    $cmdLine .= " -stc $stcAddr $stcValue" if (defined($stcValue));
  }
  if (($elfType eq "app" || $elfType eq "reloc") &&
      defined($vccValue) && $vccValue != 0)
  {
    warn("Warning: VCC will be same for boot sector and signature of " .
         "$elfFilename.  Use mkimage.pl directly to specify different values.\n");
    $cmdLine .= " -vcc $vccAddr $vccValue" if (defined($vccValue));
  }

  print("Running command: $cmdLine\n") if ($verboseOutput > 1);
  my $err = system($cmdLine);

  if ($err)
  {
    warn("Warning: Failed to convert $elfFilename to an image file - continuing " .
         "as if it were one already.\n");
  }
  else
  {
    print("Successfully converted ELF file $elfFilename to image file $baseName.img\n") if ($verboseOutput);
    $filename = "$baseName.img";
  }
  return $filename;
}

#
# Sub to calculate the CRC for a series of bytes in FLASH - given an offset and
# an end offset.
# This is a perl version of the flashCalcCRC function from flashutil.c in the
# rombootram example.
#
sub calcCRC($$)
{
  my $startOffset = shift(@_);
  my $endOffset = shift(@_);
  my $size = $endOffset - $startOffset;
  my $crc = 0xFFFFFFFF;

  printf("CRC from 0x%08x to 0x%08x is ", $startOffset, $endOffset) if ($verboseOutput);

  my $binary = getFlashFileBinary($startOffset, $endOffset);
  
  for (my $offset = 0; $size > 0; $size -= 4, $offset += 4)
  {
    # Get a word
    my $val = unpack("V", substr($binary, $offset, 4));
    printf("Val at 0x%08x is 0x%08x\n", $startOffset + $offset, $val) if ($verboseOutput > 2);
    my $prev = $crc;

    my $this;
    for (my $count = 0; $count < 32; $count++)
    {
      $this = (($prev << 1) + (($val & 0x80000000) ? 1 : 0)) ^ (($prev & 0x80000000) ? $CRC_POLY : 0);
      $val <<= 1;
      $prev = $this;
    }
    $crc = $this;
  }

  $crc = $crc ^ 0xFFFFFFFF;

  # On awkward perl builds we make sure $crc is 32-bit before we print it
  $crc &= 0xFFFFFFFF;

  printf("0x%08x\n", $crc) if ($verboseOutput);

  return $crc;
}

#
# Ensure there is exactly one bootable slot per CPU
#
sub setBootSlots($)
{
  my $appsRef = shift(@_);
  my @apps = @$appsRef;
  print("Checking boot slots:\n") if ($verboseOutput);
  foreach my $cpu (@cpusWithApps)
  {
    my $hasBootImage = 0;
    # Check for boot slots for this CPU
    # In the @slots array, it is indexed by slot number, CPU numbers are stored
    # in the array entries
    # In @bootSlots we simply have a list of slot numbers which are bootable
    for (my $slot = 0; $slot < scalar(@slots); $slot++)
    {
      if (defined($slots[$slot]) && $slots[$slot] == $cpu)
      {
        # This slot is for this cpu - is it bootable?
        if (scalar(grep($_ == $slot, @bootSlots)) != 0)
        {
          if ($hasBootImage)
          {
            warn("Warning: Detected multiple boot slots for cpu $cpu.\n");
          }
          elsif ($cpu == 0)
          {
            $masterCPUBootSlot = $slot;
          }
          print("  Slot $slot is bootable for CPU $cpu\n") if ($verboseOutput);
          $hasBootImage = 1;
        }
      }
    }
    if (!$hasBootImage)
    {
      # No boot image found - select one - the first app for this CPU
      foreach my $appRef (@apps)
      {
        my @app = @$appRef;
        if (($app[2] & $CPU_NUMBER_MASK) == $cpu && !($app[2] & $IMAGE_TYPE_MASK))
        {
          # Set it's slot as the boot slot for this cpu
          push(@bootSlots, $app[0]);
          print("  Implicitly setting slot $app[0] bootable for CPU $cpu\n") if ($verboseOutput);
          $masterCPUBootSlot = $app[0] if ($cpu == 0);
          last;
        }
      }
    }
  }
  unless (defined($masterCPUBootSlot))
  {
    # No master CPU boot slot - if signing we need this to determine which
    # application should have it's region(s) registered with the Cryptocore.
    # As we have none, select the first boot image in @bootSlots
    if ($cryptocoreSigning)
    {
      if (scalar(@bootSlots))
      {
        $masterCPUBootSlot = $bootSlots[0];
        warn("Warning: No master CPU application detected.  Assuming bootable " .
             "application in slot $masterCPUBootSlot is the application which " .
             "will be copied to RAM and should be registered with the Cryptocore.\n");
      }
    }
  }
  print("\n") if ($verboseOutput);
}

#
# Sub to amalgamate a used range into @usedRanges
#
sub useRange($$)
{
  my $offset1 = shift(@_);
  my $offset2 = shift(@_);
  die("attempting to use reverse range in FLASH, stopped") if ($offset2 < $offset1);
  my $done = 0;
  for (my $count = 0; $count < @usedRanges; $count++)
  {
    if (overlaps($usedRanges[$count][0], $usedRanges[$count][1], $offset1, $offset2) ||
        ($offset2 + 1 == $usedRanges[$count][0] || $usedRanges[$count][1] + 1 == $offset1))
    {
      # We have overlapping or neighbouring ranges - merge them
      if ($offset1 < $usedRanges[$count][0])
      {
        $usedRanges[$count][0] = $offset1;
      }
      if ($offset2 > $usedRanges[$count][1])
      {
        $usedRanges[$count][1] = $offset2;
      }
      $done = 1;
      last;
    }
    elsif ($offset1 < $usedRanges[$count][0])
    {
      # We've found the location this range should be in the ordered list
      splice(@usedRanges, $count, 0, [$offset1, $offset2]);
      $done = 1;
      last;
    }
  }
  
  if (!$done)
  {
    # We need to append the range to the ordered list
    push(@usedRanges, [$offset1, $offset2]);
  }
}

#
# Sub to find a large enough gap in FLASH to house the size given (1st
# arg) with a base offset with the given alignment (2nd arg).
# The 3rd arg is non-zero if the space required is for executable code that will
# be run at the address this returns.  This is not important unless we are
# Cryptocore signing, in which case we must ensure the space we return does not
# overlap the Cryptocore boot sector gap.
# An optional starting offset can be given (if lower than
# $FLASH_PROTECTED_SECTIONS_OFFSET it will be ignored).
# Returns offset in flash with enough space.
#
sub findSpaceInROMFor($$$;$)
{
  my $size = shift(@_);
  my $alignment = shift(@_);
  my $executable = shift(@_);
  my $startOffset = undef;
  if (scalar(@_))
  {
    $startOffset = shift(@_);
  }
  # We start searching from the lowest address we can put sections at...
  my $offset = $FLASH_PROTECTED_SECTIONS_OFFSET;
  # Unless a start offset was given and it's higher, in which case we start from
  # there
  $offset = $startOffset if (defined($startOffset) && $startOffset > $offset);
  my $foundSpace = 0;

  my $misAlign = $offset % $alignment;
  if ($misAlign)
  {
    $offset += $alignment - $misAlign;
  }

  # Cycle through used ranges looking for a gap big enough.  If there isn't one
  # we have to go after the end of the currently used ranges
  my $count = 1;
  for (; $count < @usedRanges; $count++)
  {
    my $lastEnd = $usedRanges[$count - 1][1];
    my $thisStart = $usedRanges[$count][0];
    next if ($offset > $thisStart);
    # Check space available
    if ($offset < $lastEnd)
    {
      $offset = $lastEnd;
      $misAlign = $offset % $alignment;
      if ($misAlign)
      {
        $offset += $alignment - $misAlign;
      }
    }
    next if ($thisStart - $offset < $size);
    if ($cryptocoreSigning && $executable &&
        overlaps($offset, $offset + $size, $BOOT_GAP_LO, $BOOT_GAP_HI))
    {
      # Cryptocore signing is on and this space overlaps the boot sector gap,
      # which is usually fine, except this space will have code run at the
      # address we return ($executable is set)
      $offset = $BOOT_GAP_HI;
      $misAlign = $offset % $alignment;
      if ($misAlign)
      {
        $offset += $alignment - $misAlign;
      }
      redo;
    }
    $foundSpace = 1;
    last;
  }
  
  if (!$foundSpace)
  {
    # Return offset after last recorded range or the startOffset we were given
    # if that was higher
    if ($offset < $usedRanges[$count - 1][1])
    {
      $offset = $usedRanges[$count - 1][1];
      $misAlign = $offset % $alignment;
      if ($misAlign)
      {
        $offset += $alignment - $misAlign;
      }
    }
    if ($cryptocoreSigning && $executable &&
        overlaps($offset, $offset + $size, $BOOT_GAP_LO, $BOOT_GAP_HI))
    {
      # Cryptocore signing is on and this space overlaps the boot sector gap,
      # which is usually fine, except this space will have code run at the
      # address we return ($executable is set)
      $offset = $BOOT_GAP_HI;
      my $misAlign = $offset % $alignment;
      if ($misAlign)
      {
        $offset += $alignment - $misAlign;
      }
    }
  }
  
  return $offset;
}

#
# Given an offset from $FLASH_START and a list of bytes, puts the bytes in
# the FLASH file.
# 1st argument is a description of what we're adding.
# Overlapping existing data causes a fatal error.
#
sub addBytesToFlashFile($$$)
{
  my $desc = shift(@_);
  my $offset = shift(@_);
  my $byteArrayRef = shift(@_);
  my $endOffset = $offset + @$byteArrayRef;
  # We first check to see if we overlap any used ranges.  If not we call
  # replaceInFlashFile 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);
    }
  }
  replaceBytesInFlashFile($desc, $offset, $byteArrayRef, "Added");
}

#
# Given an offset from $FLASH_START and a list of bytes, puts the bytes in
# the FLASH file.
# 1st argument is a description of what we're adding.
# Overlapping existing data causes a fatal error.
#
sub addBinaryToFlashFile($$$)
{
  my $desc = shift(@_);
  my $offset = shift(@_);
  my $binaryRef = shift(@_);

⌨️ 快捷键说明

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