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

📄 mkimage.pl

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

          #
          # Special consideration for ST200 images.
          #
          # * Look for the .boot section - this code must be put uncompressed
          #   somewhere in FLASH, and it is the app's entry point.
          #
          if (($architecture eq $CPU_ARCH_LX) && ($name eq ".boot"))
          {
            $type = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_LX_BOOT;
          }
        }
        else
        {
          # Never deflate .post_(text|rodata)_reserve sections
          if (exists($options{p}) && ($options{p} eq "deflate") && ($name !~ /^\.post_(text|rodata)_reserve$/))
          {
            $type = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_DEFLATED;
          }
          else
          {
            $type = $PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_COPY;
          }
        }

        #
        # Filter section against any specified with the '-j' option
        #
        if (elfSectionAllowed($name))
        {
          push @sections, { name => $name,
                            src  => $srcAddr,
                            dst  => $dstAddr,
                            size => $size,
                            type => $type };
        }
      }
    }
  }
  close(HANDLE);

  #
  # At this stage the @sections array contains all the sections
  # we need to consider. We now scan it to coalesce sections which
  # are adjacent and of the same type.
  #
  # Special ST200 processing - we keep an eye open for the .boot section.
  # This contains PIC boot code which sets up the stack, and intrinsicly
  # knows the _real_ entry point of the code. If we spot a .boot section,
  # we place it above the last real section in RAM, and set the entrypoint
  # to be the address of _boot_rom_start_address, rather than the ELF published
  # entrypoint.
  #
  # We never coalesce sections with names of the form .post_(text|rodata)_reserve
  # which are correctly sized to be a Cryptocore reserve section as these need
  # to be distinct, uncompressed sections which data could be inserted in by
  # another script.
  #
  # Also keep an eye open for any .got sections - we need to highlight these
  # so that the flasher tool can fix them up once in flash (or mkbinrom.pl in
  # a binary ROM image).
  #
  my $lastSection = undef;
  my $newSection  = { name => "", src  => 0, dst  => 0, size => 0, type => 0};

  #
  # Put a dummy section on the end to ensure last coalesced bit is emitted
  #
  push @sections, { name => "_DUMMY_",
                    src  => 0,
                    dst  => 0,
                    size => 0,
                    type => 0 };

  foreach my $section (@sections)
  {
    if (defined($lastSection))
    {
      # Coalesce if up to 128 bytes apart (and meet other requirements).
      if (($section->{name} ne "_DUMMY_") &&
          ($lastSection->{type} == $section->{type}) &&
          ($section->{src} > $lastSection->{src}) &&
          (($section->{src} - ($lastSection->{src} + $lastSection->{size})) <= 128) &&
          ($section->{name} !~ /^\.post_(text|rodata)_reserve$/ ||
            ($section->{size} != $RESERVE_1024_BIT_KEY && $section->{size} != $RESERVE_2048_BIT_KEY)) &&
          ($lastSection->{name} !~ /^\.post_(text|rodata)_reserve$/ ||
            ($lastSection->{size} != $RESERVE_1024_BIT_KEY && $lastSection->{size} != $RESERVE_2048_BIT_KEY)))
      {
        $newSection->{name} .= " $section->{name}";
        $newSection->{size}  = ($section->{src}-$newSection->{src})+$section->{size};
      }
      else
      {
        push @coalescedSections, $newSection;
        $newSection = {%{$section}};
      }
    }
    else
    {
      $newSection = {%{$section}};

      #
      # If this is an ST200 image, and this is the .boot section, then
      # adjust its address to be above the highest loaded address
      #
      if (($architecture eq $CPU_ARCH_LX) && ($section->{name} eq ".boot"))
      {
        $newSection->{src} = $bootAddr;
        $newSection->{dst} = $bootAddr;
      }
      if (($architecture eq $CPU_ARCH_LX) && ($section->{name} eq ".text"))
      {
        # If using a useful linker script, the .boot section will have been
        # placed at the very start of the text section
        $startAddress = $newSection->{dst};
      }
    }
    $lastSection = $section;
  }

  #
  # If this is a pic ST200 image use the advertised entry point. Otherwise
  # the entrypoint is determined at flash time by calling the .boot section.
  #
  if ($architecture eq $CPU_ARCH_LX)
  {
    if ($defaultType == ($PLACEMENT_TYPE_ANYWHERE | $SECTION_TYPE_SKIP))
    {
      my $hdrCmd  = getObjdump() . " -f $elfName";

      open(HANDLE, $hdrCmd."|") or die("unable to open pipe ($!), stopped");
      while (<HANDLE>)
      {
        if (/^start address (\S+)\r?$/)
        {
          $startAddress = hex ($1);
          last;
        }
      }
      close(HANDLE);
    }
    else
    {
      $startAddress = 0 if (!defined($startAddress));
    }
  }

  return @coalescedSections;
}

#
# Routine to decompose an ELF file into an image file
#
# This supports ST40 and ST200 ELF images, as well as
# execute from ROM (inplace & PIC) and execute from RAM.
#
# Take two parameters - the name of the ELF file, and the
# default placement type.
#
sub processElfFile($$)
{
  my $elfFile      = shift;
  my $defaultType  = $defaultSectionTypes{(shift)};
  my $loadAddress  = undef;
  my $stackAddress = undef;
  my $gotSection   = undef;
  my $tmpFile      = createtmpname();
  my $tmpSignFile  = createtmpname();
  my $tmpSigFile   = createtmpname();
  my @sections;

  #
  # Read in the section list
  #
  @sections = getElfSections($elfFile, $defaultType);

  #
  # ST40 images have to have the symbol __SH_DEBUGGER_CONNECTED zeroed out
  # also scan for the stack address while we're at it
  #
  my $zeroedAddress;
  my $zeroedSize;

  my $symCmd  = getObjdump() . " -t $elfFile";

  open(HANDLE, $symCmd."|") or die("unable to open pipe ($!), stopped");
  while (<HANDLE>)
  {
    if (/^(\S+) +[gw] +.*\.data\t(\S+) __SH_DEBUGGER_CONNECTED\r?$/)
    {
      $zeroedAddress = hex($1);
      $zeroedSize    = hex($2);
    }
    elsif (/^(\S+).* _stack\r?$/)
    {
      $stackAddress = hex($1);
    }
  }
  close(HANDLE);

  unless (defined($stackAddress))
  {
    if ($architecture eq $CPU_ARCH_SH4)
    {
      warn("Warning: Could not find stack address from the ELF image.\n");
    }
    $stackAddress = 0;
  }

  #
  # Extract the start address (entry point) for the image
  # if its not already known (we'll have figured out ST200 entry
  # point by here).
  #
  unless (defined($startAddress))
  {
    my $hdrCmd = getObjdump() . " -f $elfFile";

    open(HANDLE, $hdrCmd."|") or die("unable to open pipe ($!), stopped");
    while (<HANDLE>)
    {
      if (/^start address (\S+)\r?$/)
      {
        $startAddress = hex($1);
      }
    }
    close(HANDLE);

    unless (defined($startAddress))
    {
      warn("Warning: Could not find entry point from the ELF image.\n");
      $startAddress = 0;
    }
  }

  unless (exists($options{d}))
  {
    my @time = localtime();
    $options{d} = "ELF from $elfFile (" . 
                  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]) .
                  ")";
  }

  #
  # Finally we can generate the image file
  #
  open(HANDLE, ">$options{o}") or die("unable to open '$options{o}' ($!), stopped");
  binmode(HANDLE);

  my $numSections = $#sections + 1;

  if (defined($zeroedAddress))
  {
    $numSections++;
  }

  #
  # Emit the file header
  #
  my $fileHeader = pack('VZ32VVVV',
                        $IMAGE_FILE_MAGIC_NUM,
                        $options{d},
                        $options{c} | $architecture,
                        $stackAddress,
                        $startAddress,
                        $numSections);

  syswrite(HANDLE, $fileHeader, length($fileHeader)) or die("unable to write to '$options{o}' ($!), stopped");

  #
  # Emit the sections
  #
  foreach my $section (@sections)
  {
    my $rawSection = pack('VVVV',
                          $section->{type},
                          $section->{src},
                          $section->{dst},
                          $section->{size});

    syswrite(HANDLE, $rawSection, length($rawSection)) or die("unable to write to '$options{o}' ($!), stopped");
  }

  #
  # Emit the zero section if there is one
  #
  if (defined($zeroedAddress))
  {
    my $rawSection = pack('VVVV',
                          $PLACEMENT_TYPE_NONE | $SECTION_TYPE_ZERO,
                          $zeroedAddress,
                          $zeroedAddress,
                          $zeroedSize);

    syswrite(HANDLE, $rawSection, length($rawSection)) or die("unable to write to '$options{o}' ($!), stopped");
  }

  #
  # Now generate the sections and append them to the end of the file
  #
  my $section_index = 0;

  foreach my $section (@sections)
  {
    my $names;

    # Copy this section into $tmpFile
    copySectionsToFile($section->{name}, $elfFile, $tmpFile);

    if ($section->{type} == $SECTION_TYPE_DEFLATED)
    {
      #
      # Init compressor
      #
      my $stream = deflateInit(-Level => Z_BEST_COMPRESSION()) or die("unable to create deflation stream, stopped");
      my ($output, $status);
      my $buffer;

      #
      # Read in uncompressed data to memory
      #
      open(IN_HANDLE, $tmpFile) or die("unable to open '$tmpFile' (!$), stopped");
      binmode(IN_HANDLE);

      my $uncomp_length = (stat($tmpFile))[7];

      sysread(IN_HANDLE, $buffer, $uncomp_length) or die("unable to read from '$tmpFile' ($!), stopped");

      close(IN_HANDLE);

      #
      # Compress it, and write it out
      #
      ($output, $status) = $stream->deflate($buffer) ;
      $status == Z_OK() or die("deflation failed, stopped");

      my $length = length($output);
      syswrite(HANDLE, $output, $length) or die("unable to write to '$options{o}' ($!), stopped");

      ($output, $status) = $stream->flush() ;
      $status == Z_OK() or die("deflation flush failed, stopped");
      $length += length($output);
      syswrite(HANDLE, $output, length($output)) or die("unable to write to '$options{o}' ($!), stopped");

      #
      # Update the length recorded in the section header with compressed length
      #
      sysseek(HANDLE, 64 + ($section_index * 16), 0) or die("unable to seek in '$options{o}' ($!), stopped");
      my $new_length = pack('V', $length);
      syswrite(HANDLE, $new_length, length($new_length)) or die("unable to write to '$options{o}' ($!), stopped");

      sysseek(HANDLE, 0, 2) or die("unable to seek in '$options{o}' ($!), stopped");
    }
    else
    {

⌨️ 快捷键说明

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