mirror of
https://github.com/gnuton/asuswrt-merlin.ng.git
synced 2025-05-19 07:51:46 +02:00
115 lines
2.7 KiB
Perl
Executable file
115 lines
2.7 KiB
Perl
Executable file
#!/usr/bin/env perl
|
|
|
|
#
|
|
# mkhashes -- assemble a block of hashes
|
|
#
|
|
# Usage example....
|
|
# hostTools/imagetools/mkhashes --out="hashes.bin" --item rootfs=targets/963158GW/squashfs.img targets/963158GW/bootfs/
|
|
#
|
|
# mkhashes [options] PATHS ...
|
|
# --out output filename (defaults to hashes.bin)
|
|
# --item name=path Add a file to the list of files to be hashed, but use "name" as its designation instead
|
|
# of the basename
|
|
# PATHS.... A list of paths that should have every regular file within them included
|
|
#
|
|
#
|
|
|
|
use strict;
|
|
use warnings;
|
|
use bytes;
|
|
use Getopt::Long;
|
|
use File::Find;
|
|
use File::stat;
|
|
use File::Temp qw[ tempfile ];
|
|
use File::Basename;
|
|
use Data::Dumper;
|
|
|
|
# constants match cfe/cfe/board/bcm63xx_rom/include/bcm63xx_boot.h
|
|
use constant {
|
|
FLAG_BOOTLOADER => 1,
|
|
FLAG_COMPRESSED => 2,
|
|
FLAG_ENCRYPTED => 4
|
|
};
|
|
|
|
my $end = '<';
|
|
my $output = "hashes.bin";
|
|
my @items;
|
|
my @hashes;
|
|
my %extra;
|
|
my @exclude;
|
|
my %flags;
|
|
my $current = '';
|
|
|
|
GetOptions(
|
|
"output=s", \$output,
|
|
"item=s", \%extra,
|
|
"exclude=s", \@exclude,
|
|
"file=s", \$current,
|
|
"bootloader", sub { $flags{$current} |= FLAG_BOOTLOADER },
|
|
"compressed", sub { $flags{$current} |= FLAG_COMPRESSED },
|
|
"encrypted", sub { $flags{$current} |= FLAG_ENCRYPTED },
|
|
) or die("bad option");
|
|
|
|
|
|
if (@ARGV) {
|
|
|
|
# generate list of paths
|
|
find(
|
|
sub {
|
|
if ( -f $_ ) {
|
|
foreach my $exclusion (@exclude) {
|
|
return if ( $File::Find::name =~ /$exclusion/ );
|
|
}
|
|
push @items, { path => $File::Find::name };
|
|
}
|
|
},
|
|
@ARGV
|
|
);
|
|
}
|
|
|
|
foreach ( keys %extra ) {
|
|
push @items, { path => $extra{$_}, tag => $_ };
|
|
|
|
}
|
|
|
|
open( FO, ">", $output );
|
|
|
|
foreach my $item (@items) {
|
|
my $file = $item->{path};
|
|
my $st = stat($file);
|
|
my $sha;
|
|
$sha = `sha256sum $file`;
|
|
$sha =~ s/^([0-9a-fA-F]+)\s.*$/$1/;
|
|
my $shabin = join( '', map { pack( 'C', hex($_) ) } ( $sha =~ /(..)/g ) );
|
|
my $fname = $item->{tag} || basename($file);
|
|
push @hashes, { name => $fname, len => $st->size, hash => $shabin };
|
|
}
|
|
|
|
# TLV
|
|
# Type: U32
|
|
# Length : U32
|
|
# Value
|
|
#
|
|
# If type is NAME_FILELEN_SHA 0x00000001
|
|
# After the lenth field
|
|
# Flags: U32
|
|
# Name: ASCIIZ
|
|
# Filelen: U32
|
|
# SHA256: 32 bytes
|
|
|
|
foreach (@hashes) {
|
|
my $flags = $flags{$_->{name}} || 0;
|
|
my $rec = pack( "(LZ*LA*)$end", $flags, $_->{name}, $_->{len}, $_->{hash} );
|
|
print FO pack( "(LL)$end", 0x00000001, 8 + length($rec) );
|
|
print FO $rec;
|
|
print $_->{name}
|
|
. " has flags "
|
|
. $flags
|
|
. " has size "
|
|
. $_->{len}
|
|
. " length "
|
|
. length( $_->{hash} ) . "\n";
|
|
}
|
|
print FO pack( "(LL)$end", 0x00000000, 0 );
|
|
close(FO);
|
|
|