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

📄 mkimage.pl

📁 采用ST20 CPU的机顶盒的烧写程序
💻 PL
📖 第 1 页 / 共 5 页
字号:
      my $doneSection = 0;
      # If this is a .post_(text|rodata)_reserve section, we can now insert the
      # signature and 4 of the 5 words of the config_table entry.  We only check
      # the name and size to match.
      if ($section->{name} =~ /^\.post_(text|rodata)_reserve$/)
      {
        if ($section->{size} == $RESERVE_1024_BIT_KEY ||
            $section->{size} == $RESERVE_2048_BIT_KEY)
        {
          unless (exists($options{k}))
          {
            warn("Warning: Detected Cryptocore sections, but no private key to " .
                 "sign with provided on command line (use -k option).\n");
          }
          else
          {
            my $signedBlockDst;
            # Dump the required sections to a file so we can hash them...any gaps
            # will be padded automatically
            if ($section->{name} =~ /text/)
            {
              # Dump the .text, .plt, .init and .fini sections into $tmpSignFile
              # This order is guaranteed when the Cryptocore enhanced linker
              # scripts are used with the ST40/200 toolsets
              copySectionsToFile(".text .plt .init .fini", $elfFile, $tmpSignFile);
  
              # Destination address recorded during getElfSections
              $signedBlockDst = $textSectionDst;
            }
            else
            {
              # Dump the .rodata and .rodata1 sections into $tmpSignFile
              copySectionsToFile(".rodata .rodata1", $elfFile, $tmpSignFile);
  
              # Destination address recorded during getElfSections
              $signedBlockDst = $rodataSectionDst;
            }
  
            # Get signed block size (without padding => == file size)
            my $signedBlockLen = (stat($tmpSignFile))[7];
  
            # The number of bytes needed for the number of config table entry
            # fields signed with a signed block must be reserved, is the minimum
            # amount of padding required for extra signed words just below a 64
            # byte boundary
            my $cteSignedSize = $CTE_SIGNING_LEVEL * 4;
  
            # $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;
            }
  
            # Just append the padding we will sign for now - also put a copy in $reserveSecData
            # which will be the data we write out for this reserve section
            open(OUT_HANDLE, "+<$tmpSignFile") or die("unable to open '$tmpSignFile' (!$), stopped");
            binmode(OUT_HANDLE);
            sysseek(OUT_HANDLE, 0, 2) or die("unable to seek in '$tmpSignFile' ($!), stopped");
  
            my $zeroString = pack("C", 0x0) x ($padSize - $cteSignedSize);
            if (length($zeroString))
            {
              syswrite(OUT_HANDLE, $zeroString, length($zeroString)) or die("unable to write to '$tmpSignFile' ($!), stopped");
            }
  
            # In order to pass information on to the mksignedrom.pl script, we put
            # the size of the linked section in the first word of the reserve section
            # that will be stored in the .img file.  This will enable the mksignedrom.pl
            # script to work out where the signature and config table entry will be.  It
            # will be zeroed out again by the mksignedrom.pl script when the ROM image
            # is created.
            $zeroString = pack("C", 0x0) x ($padSize - 4);
            my $reserveSectionData = pack("V", $signedBlockLen) . $zeroString;
  
            # We now create the 4 config_table fields we know (they come after
            # the signature in $reserveSectionData):
            #   block_add == $signedBlockDst  # must be the physical address (i.e. 29-bit)
            #   block_len == ($signedBlockLen + $padSize) / 4   # we divide by 4 as this should be in words
            #   sig_add   == (section->{dst} aligned up to 64 byte boundary...again the physical address)
            #   block_no  == specified on command line (or that number +1 if signing data)
            my $blockAddr = physMemAddr($signedBlockDst, $elfFile);
            my $blockLen = ($signedBlockLen + $padSize) / 4;
            my $sigAddr = physMemAddr($section->{dst} + $padSize, $elfFile);
            my $blockNum = $options{g};
  
            # Issue a warning if the signed block length exceeds
            # $MAX_SIGNED_BLOCK_LEN
            if ($blockLen > $MAX_SIGNED_BLOCK_LEN)
            {
              warn("Warning: signed block from $elfFile exceeds " .
                   $MAX_SIGNED_BLOCK_LEN . " words - this may " .
                   "exceed the maximum size allowed by the Cryptocore.\n");
              # Unfortunately we have no way to split signed blocks as yet.  If it
              # ever becomes an issue an update to this package will be required
              # which reserves enough room for multiple config table entries and
              # signatures in the .post_text_reserve section and has the ability
              # to put them in place...
            }
  
            if ($CRYPTOCORE_VERSION >= 2.0)
            {
              # OR in bits in the l.s. 4 bits for i-monitor port enables based on
              # the CPU number this image is for, or those specified by -ce
              # options if there were any
              if (scalar(@cc2CPUEnables))
              {
                for my $enable (@cc2CPUEnables)
                {
                  $blockAddr |= (1 << $enable);
                  print("Cryptocore CPU $enable enable set\n") if ($verboseOutput);
                }
              }
              else
              {
                $blockAddr |= (1 << $options{c});
                print("Cryptocore CPU $options{c} set for signed block\n") if ($verboseOutput);
              }
              # OR in the region_in_flash bit if the signed block is to be in flash
              # region_in_flash is bit 28
              if ((defined($regionsInFlash) && $regionsInFlash) ||
                  (!defined($regionsInFlash) && ($section->{type} & $PLACEMENT_TYPE_INPLACE) == $PLACEMENT_TYPE_INPLACE))
              {
                $blockLen  |= 0x10000000;
                print("Cryptocore 'inflash' bit set for signed block\n") if ($verboseOutput);
              }
            }
  
            my $cte = pack("VVVV", $blockAddr, $blockLen, $sigAddr, $blockNum);
  
            if ($CRYPTOCORE_VERSION >= 2.0)
            {
              # OR in bits in the l.s. 4 bits for i-monitor port enables based on
              # the CPU number this image is for, or those specified by -ce
              # options if there were any.
              # This is just for signing - a hack to ensure the i-monitor port
              # enables are always signed (i.e. won't be in the config table in
              # FLASH/RAM).
              if (scalar(@cc2CPUEnables))
              {
                for my $enable (@cc2CPUEnables)
                {
                  $blockLen |= (1 << $enable);
                }
              }
              else
              {
                $blockLen |= (1 << $options{c});
              }
            }
  
            if ($verboseOutput > 1)
            {
              printf("Signed block information:\n\tBlock physical address: 0x%08x\n" .
                     "\tBlock length in words: $blockLen\n\tSignature physical address: 0x%08x\n" .
                     "\tBlock number: $blockNum\n", $blockAddr, $sigAddr);
            }

            # Write the correct fields for our chosen signing level
            if ($CTE_SIGNING_LEVEL % 2 == 0) # 2 or 4
            {
              syswrite(OUT_HANDLE, pack("V", $blockAddr), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
            }
  
            # Always sign block len
            syswrite(OUT_HANDLE, pack("V", $blockLen), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
  
            if ($CTE_SIGNING_LEVEL >= 3) # 3 or 4
            {
              syswrite(OUT_HANDLE, pack("V", $sigAddr), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
              syswrite(OUT_HANDLE, pack("V", $blockNum), 4) or die("unable to write to '$tmpSignFile' ($!), stopped");
            }
            close(OUT_HANDLE);
  
            $options{g}++; # Increment for next signed block
  
            # Now we can now use siggen to SHA1 and encrypt $tmpSignFile
            # Note we use siggen in binary mode (smaller files than hex-like file mode => quicker)
            runSigningTool($options{k}, $tmpSignFile, $tmpSigFile, $vccAddr,
                           $vccValue, $stcAddr, $stcValue);
  
            # Read the signature file
            my $signature = "";
            open(IN_HANDLE, $tmpSigFile) or die("unable to open '$tmpSigFile' (!$), stopped");
            binmode(IN_HANDLE);
            my $sigFileLen = (stat($tmpSigFile))[7];
            sysread(IN_HANDLE, $signature, $sigFileLen) or die("unable to read from '$tmpSigFile' ($!), stopped");
            close(IN_HANDLE);
  
            if ($lenDigitalSignature != $sigFileLen)
            {
              die("expected $lenDigitalSignature byte signature, but saw a $sigFileLen byte signature, stopped");
            }
  
            # Write this section (we add 0xdeadadda as the next config table addr as a placeholder)
            $reserveSectionData .= $signature . $cte . pack("V", 0xdeadadda);
  
            # We need to pad $reserveSectionData up to the full size of this section too
            $padSize = $section->{size} - length($reserveSectionData);
            die("internal error: reserve section appeared to be too small (size = " .
                "$section->{size}, data len = " . length($reserveSectionData) .
                ", stopped") if ($padSize < 0);
            $reserveSectionData .= (pack("C", 0x00) x $padSize);
  
            # Write this reserve section to the output 'img' file
            syswrite(HANDLE, $reserveSectionData, length($reserveSectionData)) or die("unable to write to '$options{o}' ($!), stopped");
  
            # So we know not to copy the section to \*HANDLE as we would for
            # other uncompressed sections
            $doneSection = 1;
            $signedSomething = 1;
          }
        }
        elsif (defined($options{k}))
        {
          # We only warn if the size was greater than 4 as the ST200 Toolset has
          # an 'intelligent' linker which doesn't set the VMA and LMA addresses
          # of sections to the same value when you have padding sections like
          # our reserve sections.  As a result I had to put something in the
          # reserve sections - a byte will always be there even when we aren't
          # signing.
          if ($section->{size} > 4)
          {
            warn("Warning: Saw potential reserve section $section->{name}, but " .
                 "size was $section->{size} bytes, which is not a valid Cryptocore " .
                 "reserve section size - image may not be correctly signed.\n");
          }
        }
      }

      if (!$doneSection)
      {
        # Normal input copy - just check the expected size and actual size match
        if ($section->{size} != (stat($tmpFile))[7])
        {
          die("section '$section->{name}' was expected to be $section->{size} " .
              "bytes, but " . (stat($tmpFile))[7] . " bytes copied, stopped");
        }
        copy($tmpFile, \*HANDLE);
      }
    }

    $section_index++;
  }

  close(HANDLE);

  #
  # All done
  #
  if (exists($options{k}) && !$signedSomething)
  {
    warn("Warning: Private key for signing specified on command line, but no " .
         ".post_text_reserve/.post_rodata_reserve section of the correct size " .
         "was found (check the link command line used the correct Cryptocore " .
         "linker scripts and symbol definitions) - image not signed.\n");
  }
  
  if ($verboseOutput)
  {
    print "\nGenerated $options{o} from ",
           ($architecture eq $CPU_ARCH_SH4) ? "ST40" : "ST200",
           " ELF file $elfFile.\n";

    printf("  Total sections: 0x%08x\n", $numSections);
    printf("  Entry point   : 0x%08x\n", $startAddress);
    printf("  Stack address : 0x%08x\n", $stackAddress);
  }
}

#
# Sub which takes a relocatable ELF filename and a storage type of "copy" or
# "deflate" and creates the relevant image.
#
# RL images are converted to binary by objcopy and are either compressed, or
# put in place as-is.
#
sub processRelocElf($$)
{
  my $rlFile = shift;
  my $store = shift;
  my $tmpRLFile = createtmpname();

  if (exists($options{k}))
  {
    # A Cryptocore signing key has been provided - check the RL contains a
    # reserve section and warn if it doesn't.
    open(HANDLE, getObjdump() . " -h $rlFile |") || die("unable to open pipe ($!), stopped");
    my $sawReserve = 0;
    my $line;
    while ($line = <HANDLE>)
    {
      if ($line =~ /^\s*[0-9]+\s(\S+)\s+[0-9A-Fa-f]+/)
      {
        my $name = $1;
        if ($name =~ /^\.post_(text|rodata)_reserve$/)
        {
          $sawReserve = 1;
          last;
        }
      }
    }
    # Read the rest of the output to prevent SIGPIPE being sent to objdump
    while ($line = <HANDLE>)
    { }
    close(HANDLE);

    unless ($sawReserve)
    {
      warn("Warning: No .post_text_reserve or .post_rodata_reserve sections seen " .
           "in $rlFile - is not Cryptocore signed/signable.\n");
    }
    else
    {
      # Reserve section exists - check whether the ELF has already been signed
      # by signrl.pl, or whether it still needs signing.  We do this by dumping
      # the contents of the reserve sections and ensuring they are not all 0, or
      # our fill values for .post_<X>_reserve sections.
      # Automatic signing of RL libraries is only possible if the signing level
      # is 1 (otherwise extra options are required to signrl.pl, which only the
      # user can specify).
      my $needsSigning = 0;
      my $tmpResFile  = createtmpname();
      my $cmd = getObjcopy() . " -O binary -I elf32-little -j .post_text_reserve -j .post_rodata_reserve $rlFile $tmpResFile";
      # Suppress any (warnings when processing ELF files with the 'wrong'
      # binutils by temporarily silencing STDERR.
      open(OLDERR, ">&STDERR");
      close(STDERR);
      print("Running command: $cmd\n") if ($verboseOutput);
      my $err = system($cmd);
      open(STDERR, ">&OLDERR");
      close(OLDERR);
      die("error running " . getObjcopy() . " ($!), stopped") if ($err);
      if ((stat($tmpResFile))[7] == 0)
      {
        $needsSigning = 1;
      }
      else
      {
        my $str = readBinFileToStr($tmpResFile);
        my @list = unpack("V*", $str);
        # We search for words which are not either 0, or a fill value
        if (scalar(grep($_ != 0 && $_ != 0xdaadadda, @list)) == 0)
        {
          $needsSigning = 1;
        }
      }
      if ($needsSigning)
      {
        if ($CTE_SIGNING_LEVEL == 1)
        {
          # Call signrl.pl to sign the ELF file
          my $cmd = $^X . " -w $PATH_TO_THIS_SCRIPT/signrl.pl -e $rlFile " .
                    "-o signed_$rlFile -k $options{k} -t $options{t}";

⌨️ 快捷键说明

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