Browse Source

update: encode version in the firmware files; better .rpf generation

Encode the flash target (MAX80v?) in the firmware files to avoid
flashing the wrong image on the wrong platform.

Be trickier in how to figure out the .rpf file length -- basically:
create a compressed .rbf and then use it to take the same number of
bytes from the .rpd file. There doesn't seem to be a better way to do it.
H. Peter Anvin 3 years ago
parent
commit
84afb464e6

+ 11 - 6
fpga/Makefile

@@ -146,18 +146,23 @@ $(outdir)/%.rbf: $(outdir)/%.sof
 # but is rather large if not compressed. Adjust bit ordering to match
 # SPI...
 $(outdir)/%.rpd: $(outdir)/%.pof
-	$(QCPF) -o rpd_little_endian=off -o bitstream_compression=on -c $< $@
+	$(QCPF) -c -o bitstream_compression=on -o rpd_little_endian=off $< $@
 
-# RPD file for the FPGA only
-$(outdir)/%.rpf: $(outdir)/%.rpd $(outdir)/%.rbf
-	dd if=$< of=$@ bs=$$(wc -c < $(@:.rpf=.rbf)) count=1
+# RPD file for the FPGA only. The necessary length can be gotten from
+# generating a compressed .rbf, but that file is not valid for flashing
+# even if bit-reversed due to header(?) differences.
+$(outdir)/%.z.rbf: $(outdir)/%.sof
+	$(QCPF) -c -o bitstream_compression=on $< $@
+
+$(outdir)/%.rpf: $(outdir)/%.rpd $(outdir)/%.z.rbf 
+	dd if=$< of=$@ bs=$$(wc -c < $(@:.rpf=.z.rbf)) count=1
 
 $(outdir)/%.gz: $(outdir)/%
 	$(GZIP) -9 < $< > $@
 
 $(outdir)/%.fw: $(outdir)/%.rpf.gz ../rv32/dram.bin.gz ../tools/wrapflash.pl
-	$(PERL) ../tools/wrapflash.pl $@ $< 0 ../rv32/dram.bin.gz 0x100000
-
+	$(PERL) ../tools/wrapflash.pl 'MAX80$*' $@ \
+		$< 0 ../rv32/dram.bin.gz 0x100000
 
 $(outdir)/%.update.svf: ./scripts/flashsvf.pl \
 	$(outdir)/jtagupd/%.svf $(outdir)/%.map.rpt $(outdir)/%.fw

+ 2 - 2
fpga/max80.qpf

@@ -19,12 +19,12 @@
 #
 # Quartus Prime
 # Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
-# Date created = 04:03:01  February 18, 2022
+# Date created = 13:05:48  February 18, 2022
 #
 # -------------------------------------------------------------------------- #
 
 QUARTUS_VERSION = "21.1"
-DATE = "04:03:01  February 18, 2022"
+DATE = "13:05:48  February 18, 2022"
 
 # Revisions
 

BIN
fpga/output/jtagupd/v1.rbf.gz


BIN
fpga/output/jtagupd/v1.sof


BIN
fpga/output/jtagupd/v1.svf.gz


BIN
fpga/output/jtagupd/v2.rbf.gz


BIN
fpga/output/jtagupd/v2.sof


BIN
fpga/output/jtagupd/v2.svf.gz


BIN
fpga/output/v1.fw


BIN
fpga/output/v1.jic


BIN
fpga/output/v1.rbf.gz


BIN
fpga/output/v1.rpd.gz


BIN
fpga/output/v1.sof


BIN
fpga/output/v1.svf.gz


BIN
fpga/output/v1.update.svf.gz


BIN
fpga/output/v1.update.xsvf.gz


BIN
fpga/output/v1.xsvf.gz


BIN
fpga/output/v2.fw


BIN
fpga/output/v2.jic


BIN
fpga/output/v2.rbf.gz


BIN
fpga/output/v2.rpd.gz


BIN
fpga/output/v2.sof


BIN
fpga/output/v2.svf.gz


BIN
fpga/output/v2.update.svf.gz


BIN
fpga/output/v2.update.xsvf.gz


BIN
fpga/output/v2.xsvf.gz


+ 5 - 6
rv32/romcopy.c

@@ -295,7 +295,8 @@ static const struct spiflash_param max80_spiflash_param = {
 static struct spiflash max80_flash = {
     .ops    = &max80_spiflash_ops,
     .cookie = NULL,
-    .param  = &max80_spiflash_param
+    .param  = &max80_spiflash_param,
+    .target = "MAX80v?"
 };
 
 /*
@@ -316,17 +317,15 @@ void rom_flash_from_memory(void *buf, size_t buflen)
 	return;
     }
 
-    memset(romid, 0, sizeof romid);
-    spiflash_read_id(&max80_flash, romid);
-    con_printf("update: ROM serial number %08x-%08x\n", romid[0], romid[1]);
+    max80_flash.target[6] = SYS_BOARDFPGA + '0';
 
     if (spiflash_flash_files(&max80_flash, buf, buflen)) {
 	con_puts("update: flash update data invalid\n");
 	return;
     }
 
-    con_puts("update: Flash complete, restarting in 5 s...\n");
-    udelay(5000000);
+    con_puts("update: flash complete, restarting in 500 ms...\n");
+    udelay(500000);
 
     reset(SYS_RESET_RECONFIG);
 }

+ 7 - 0
rv32/spiflash.c

@@ -182,6 +182,13 @@ static int spiflash_data_init(spz_stream *spz)
 	goto err;
     }
 
+    if (memcmp(spz->header->target, spz->flash->target, 8)) {
+	MSG("expected firmware for \"%.8s\", but this image is for \"%.8s\"\n",
+	    spz->flash->target, spz->header->target);
+	spz->err = Z_DATA_ERROR;
+	goto err;
+    }
+
     rlen -= sizeof *spz->header;
     spz->zs.next_in += sizeof *spz->header;
 

+ 2 - 1
rv32/spiflash.h

@@ -73,7 +73,7 @@ struct spiflash_header {
     uint32_t dlen;		/* Uncompressed data length */
     uint32_t crc32;		/* CRC32 of (raw) data block */
     uint32_t address;		/* Target address in flash (block aligned) */
-    uint32_t resv[2];		/* Set to zero for now */
+    char target[8];		/* Flash target */
     uint32_t header_crc32;	/* CRC32 of above fields */
 };
 
@@ -264,6 +264,7 @@ struct spiflash {
     const struct spiflash_ops *ops;
     void *cookie;		/* Pointer passed to spiflash_ops functions */
     const struct spiflash_param *param;
+    char target[8];		/* What are we programming for? */
 };
 
 /*

+ 8 - 7
tools/wrapflash.pl

@@ -17,19 +17,20 @@ sub filelen($) {
 
     return $s[7];
 }
-sub makeheader($$$$) {
-    my($zlen,$dlen,$dcrc,$address) = @_;
+sub makeheader($$$$$) {
+    my($target,$zlen,$dlen,$dcrc,$address) = @_;
 
-    my $hdr = pack("V*", $SPIFLASH_MAGIC, $zlen, $dlen, $dcrc, $address,
-		   0, 0);
+    my $hdr = pack("V*", $SPIFLASH_MAGIC, $zlen, $dlen, $dcrc, $address);
+    $hdr .= substr($target.("\0" x 8), 0, 8);
     $hdr .= pack("V", Digest::CRC::crc32($hdr));
     return $hdr;
 }
 
+my $target  = shift @ARGV;
 my $outfile = shift @ARGV;
 
 if (!defined($outfile)) {
-    die "Usage: $0 outfile [infile addr]...\n";
+    die "Usage: $0 target_name outfile [infile addr]...\n";
 }
 
 open(my $out, '>', $outfile)
@@ -60,7 +61,7 @@ while (1) {
 	$dlen = unpack("V", substr($data, -4));
     }
     my $dcrc = Digest::CRC::crc32($data);
-    print $out makeheader($zlen, $dlen, $dcrc, $inaddr);
+    print $out makeheader($target, $zlen, $dlen, $dcrc, $inaddr);
     print $out $data;
     if ($zlen & 3) {
 	# pad to dword boundary
@@ -74,5 +75,5 @@ if (defined($err)) {
     die "$0: $err\n";
 }
 
-print $out makeheader(0, 0, Digest::CRC::crc32(''), 0);
+print $out makeheader($target, 0, 0, Digest::CRC::crc32(''), 0);
 close($out);