Merge pull request #1190 from stefanrueger/bootloader-hash

Provide bootloader-hash tool
This commit is contained in:
Stefan Rueger 2022-11-25 17:40:36 +00:00 committed by GitHub
commit 10ca3661bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 124 additions and 3 deletions

View File

@ -1142,9 +1142,6 @@ static void guessblstart(const PROGRAMMER *pgm, const AVRPART *p) {
{ 2048, 0, 0x12ab8da0, 0xca46a3ca }, // ATmegaBOOT_168_diecimila.hex { 2048, 0, 0x12ab8da0, 0xca46a3ca }, // ATmegaBOOT_168_diecimila.hex
{ 2048, 0, 0x3242ddd3, 0xf3e94dba }, // ATmegaBOOT_168_ng.hex { 2048, 0, 0x3242ddd3, 0xf3e94dba }, // ATmegaBOOT_168_ng.hex
{ 2048, 0, 0x2eed30b3, 0x47d14ffa }, // ATmegaBOOT_168_pro_8MHz.hex { 2048, 0, 0x2eed30b3, 0x47d14ffa }, // ATmegaBOOT_168_pro_8MHz.hex
{ 4096, 0, 0xc52edd05, 0xa3371f94 }, // Caterina-LilyPadUSB.hex
{ 4096, 0, 0x663b8f7e, 0x7efdda2b }, // Caterina-Robot-Control.hex
{ 4096, 0, 0x3c6387e7, 0x7e96eea2 }, // Caterina-Robot-Motor.hex
{ 2048, 0, 0x1cef0d75, 0x6cfbac49 }, // LilyPadBOOT_168.hex { 2048, 0, 0x1cef0d75, 0x6cfbac49 }, // LilyPadBOOT_168.hex
{ 1024, 1, 0x6ca0f37b, 0x31bae545 }, // bigboot_328.hex { 1024, 1, 0x6ca0f37b, 0x31bae545 }, // bigboot_328.hex
{ 512, 0, 0x035cbc07, 0x24ba435e }, // optiboot_atmega168.hex { 512, 0, 0x035cbc07, 0x24ba435e }, // optiboot_atmega168.hex
@ -1159,6 +1156,7 @@ static void guessblstart(const PROGRAMMER *pgm, const AVRPART *p) {
{ 256, 0, 0xaa62bafc, 0xaa62bafc }, // picobootArduino8v3rc1.hex { 256, 0, 0xaa62bafc, 0xaa62bafc }, // picobootArduino8v3rc1.hex
{ 256, 0, 0x56263965, 0x56263965 }, // picobootSTK500-168p.hex { 256, 0, 0x56263965, 0x56263965 }, // picobootSTK500-168p.hex
{ 512, 0, 0x3242ddd3, 0x5ba5f5f6 }, // picobootSTK500-328p.hex { 512, 0, 0x3242ddd3, 0x5ba5f5f6 }, // picobootSTK500-328p.hex
{ 3072, 0, 0x3242ddd3, 0xd3347c5d }, // optiboot_lgt8f328p.hex
}; };
uint8_t buf[4096], b128[128]; uint8_t buf[4096], b128[128];

123
tools/bootloader-hash Executable file
View File

@ -0,0 +1,123 @@
#!/bin/bash
# published under GNU General Public License, version 3 (GPL-3.0)
# author Stefan Rueger, 2022
#
# Recursivly find in the current directory intel .hex files, which are
# presumed to be bootloaders; create their hash table entry for urclock.c
#
# Background. This bash script computes the hash-sum of stk500v1 bootloaders
# to ease the guesswork of AVRDUDE's -c urclock programmer. Urclock is
# compatible with -c arduino, but needs to know the size of the bootloader to
# protect it *externally* from being overwritten. In contrast to urboot,
# optiboot et al binaries do not advertise their size and properties. Hence,
# urclock.c maintains a table with hash-sums of popular bootloaders that are
# out there in the wild, so the user doesn't have to know, let alone specify,
# the size of the bootloader on their devices. This utility computes the
# table entry from a .hex files in the directory.
#
# Example:
# $ git clone git@github.com:MCUdude/optiboot_flash.git
# $ ./bootloader-hash
progname=$(basename $0)
hash srec_cat 2>/dev/null || { echo $progname: package srecord is needed, try apt install srecord; exit; }
hash cc 2>/dev/null || { echo $progname: need a C compiler; exit; }
tmp=$(mktemp "$progname.XXXXXX")
trap "rm -f $tmp $tmp.[ch]" EXIT
cat >$tmp.c <<END
// published under GNU General Public License, version 3 (GPL-3.0)
// meta-autor Stefan Rueger, 2022
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "$tmp.h"
// https://en.wikipedia.org/wiki/Jenkins_hash_function
uint32_t jenkins_hash(const uint8_t* key, size_t length) {
size_t i = 0;
uint32_t hash = 0;
while (i != length) {
hash += key[i++];
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
int main(int argc, char **argv) {
unsigned char reverse[4096];
if(argc != 2 || !argv[1])
exit(1);
int len, addr, end, flashsize, bi, ri;
char *base = strrchr(argv[1], '/');
base = base? base+1: argv[1];
memset(reverse, 0, sizeof reverse);
flashsize = bootloader_finish;
while(flashsize & (flashsize-1))
flashsize++;
int N = sizeof bootloader_length_of_sections/sizeof*bootloader_length_of_sections;
ri = 0; // buffer index
bi = sizeof bootloader-1; // index in bootloader[] array, top to bottom
end = flashsize;
for(int i=N-1; i >= 0; i--) {
len = bootloader_length_of_sections[i];
addr = bootloader_address[i];
if(addr == 0)
break;
if(addr + len > end) {
printf("inconsistent %d + %d > %d\n", addr, len, end);
exit(1);
}
int nff = end-addr-len;
if(ri+nff <= (int) sizeof reverse)
memset(reverse+ri, 0xff, nff);
else {
printf("buffer too small %d + %d > %d\n", ri, nff, (int) sizeof reverse);
exit(1);
}
ri += nff;
for(int n=len; n; n--) {
if(ri >= (int) sizeof reverse)
goto done;
reverse[ri] = bootloader[bi];
ri++;
bi--;
}
end = addr;
}
done:
;
printf(" { %4d, %d, 0x%08x, 0x%08x }, // %s\n", ri,
strstr(base, "bigboot") || strstr(base, "BIGBOOT"),
jenkins_hash(reverse, 256), jenkins_hash(reverse, ri), base);
}
END
for hn in $(find . -iname \*.hex -type f); do
srec_cat "$hn" -intel -o "$tmp.h" -c-array bootloader -c_compressed -line_length 96
cc $tmp.c -o $tmp
./$tmp $hn
done