#!/usr/bin/perl

use strict;
use integer;
use Digest::CRC;

my $MAX_DATA_LEN = 16 << 20;
my $SPIFLASH_MAGIC = 0xe201e7eb;

sub getint($) {
    my($s) = @_;
    return ($s =~ /^0/) ? oct $s : $s+0;
}
sub filelen($) {
    my($f) = @_;
    my @s = stat($f);

    return $s[7];
}
sub makeheader($$$$) {
    my($zlen,$dlen,$dcrc,$address) = @_;

    my $hdr = pack("V*", $SPIFLASH_MAGIC, $zlen, $dlen, $dcrc, $address,
		   0, 0);
    $hdr .= pack("V", Digest::CRC::crc32($hdr));
    return $hdr;
}

my $outfile = shift @ARGV;

if (!defined($outfile)) {
    die "Usage: $0 outfile [infile addr]...\n";
}

open(my $out, '>', $outfile)
    or die "$0: $outfile: $!\n";
binmode($outfile);

my $err;
while (1) {
    my $infile = shift @ARGV;
    my $inaddr = getint(shift @ARGV);

    last if (!defined($infile));

    my $in;
    if (!open($in, '<', $infile)) {
	$err = "$infile: $!";
	last;
    }
    binmode($in);

    my $data;
    my $zlen = read($in, $data, $MAX_DATA_LEN);
    close($in);

    my $dlen = $zlen;
    if (substr($in, 0, 3) == "\37\213\10") {
	# gzip file
	$dlen = unpack("V", substr($data, -4));
    }
    my $dcrc = Digest::CRC::crc32($data);
    print $out makeheader($zlen, $dlen, $dcrc, $inaddr);
    print $out $data;
    if ($zlen & 3) {
	# pad to dword boundary
	print $out "\0" x ((4-$zlen) & 3);
    }
}

if (defined($err)) {
    close($out);
    unlink($outfile);
    die "$0: $err\n";
}

print $out makeheader(0, 0, Digest::CRC::crc32(''), 0);
close($out);
