119 lines
6.5 KiB
C
119 lines
6.5 KiB
C
#define _CRT_SECURE_NO_WARNINGS
|
|
#include "../ports/tms320f28335/f28335_boot_store.h"
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
static unsigned char eeprom[0x40000],backup[0x40000];
|
|
static long budget=-1;
|
|
static int read_fail;
|
|
static unsigned written_words;
|
|
static bool read_mem(void *u,uint32_t addr,pcan_boot_byte_t *p,unsigned int n)
|
|
{ unsigned i; (void)u; assert(addr+n<=sizeof(eeprom)); if(read_fail) return false;
|
|
for(i=0;i<n;++i) p[i]=eeprom[addr+i]; return true; }
|
|
static bool write_mem(void *u,uint32_t addr,const pcan_boot_byte_t *p,unsigned int n)
|
|
{ unsigned i; (void)u; assert(addr+n<=0x3FE00);
|
|
for(i=0;i<n;++i) { if(budget==0) return false; if(budget>0) --budget; eeprom[addr+i]=(unsigned char)p[i]; }
|
|
return true; }
|
|
static f28335_boot_io_t io={read_mem,write_mem,0};
|
|
static pcan_boot_byte_t image[40];
|
|
static pcan_boot_manifest_t manifest;
|
|
static void make_image(void)
|
|
{
|
|
memset(image,0,sizeof(image)); image[0]=0xAA; image[1]=8;
|
|
image[20]=0; image[21]=0x80; /* entry=8000, high-word first */
|
|
image[22]=5; image[26]=0; image[27]=0x80;
|
|
image[28]=0x34; image[29]=0x12;
|
|
memset(&manifest,0,sizeof(manifest)); manifest.product_type=0x2833;
|
|
manifest.hardware_revision_min=manifest.hardware_revision_max=1;
|
|
manifest.image_size=40; manifest.image_crc32=f28335_boot_crc(0,image,40);
|
|
manifest.firmware_version=0x01010002;
|
|
}
|
|
static void image_to(f28335_boot_store_t *s,unsigned slot)
|
|
{ unsigned i; assert(f28335_boot_prepare(s,slot));
|
|
for(i=0;i<40;i+=8) assert(f28335_boot_write(s,slot,i,image+i,8)); }
|
|
static bool ram(void *u,uint32_t address,uint16_t word)
|
|
{ (void)u; assert(address==0x8000+written_words); if(!written_words) assert(word==0x1234);
|
|
++written_words; return true; }
|
|
static void reopen(f28335_boot_store_t *s) { assert(f28335_boot_open(s,&io)); }
|
|
int main(int argc,char **argv)
|
|
{
|
|
f28335_boot_store_t s; unsigned slot; uint32_t entry; long cut;
|
|
memset(eeprom,0xA5,sizeof(eeprom)); make_image(); reopen(&s);
|
|
assert(s.active==255 && !s.valid); assert(f28335_boot_select(&s,&slot) && slot==255);
|
|
image_to(&s,0); assert(f28335_boot_verify(&s,0,&manifest,&entry) && entry==0x8000);
|
|
assert(f28335_boot_commit(&s,0,&manifest));
|
|
assert(!f28335_boot_confirm(&s,0)); /* Cannot confirm an image not yet started. */
|
|
reopen(&s); assert(f28335_boot_select(&s,&slot) && slot==0 && s.attempted);
|
|
assert(f28335_boot_load(&s,slot,ram,0,&entry) && written_words==5);
|
|
assert(!f28335_boot_confirm(&s,1)); assert(f28335_boot_confirm(&s,0));
|
|
assert(f28335_boot_confirm(&s,0)); /* idempotent */
|
|
assert(!f28335_boot_prepare(&s,0));
|
|
assert(!f28335_boot_write(&s,0,0,image,8));
|
|
assert(!f28335_boot_write(&s,1,F28335_AB_SLOT_BYTES,image,8));
|
|
image_to(&s,1); memcpy(backup,eeprom,sizeof(eeprom));
|
|
/* Every torn write position in journal publication keeps confirmed A. */
|
|
for(cut=0;cut<=68;++cut) {
|
|
memcpy(eeprom,backup,sizeof(eeprom)); reopen(&s); budget=cut;
|
|
(void)f28335_boot_commit(&s,1,&manifest); budget=-1; reopen(&s);
|
|
assert(s.active==0); assert(f28335_boot_verify(&s,0,&s.image[0],0));
|
|
assert(s.pending==255 || s.pending==1);
|
|
}
|
|
memcpy(eeprom,backup,sizeof(eeprom)); reopen(&s); assert(f28335_boot_commit(&s,1,&manifest));
|
|
memcpy(backup,eeprom,sizeof(eeprom));
|
|
/* Torn trial bookkeeping must never select an unrecorded trial. */
|
|
for(cut=0;cut<=68;++cut) {
|
|
memcpy(eeprom,backup,sizeof(eeprom)); reopen(&s); budget=cut;
|
|
if(f28335_boot_select(&s,&slot)) { assert(slot==1); assert(s.attempted); }
|
|
budget=-1; reopen(&s); assert(s.active==0);
|
|
}
|
|
memcpy(eeprom,backup,sizeof(eeprom)); reopen(&s);
|
|
assert(f28335_boot_select(&s,&slot) && slot==1);
|
|
reopen(&s); assert(f28335_boot_select(&s,&slot) && slot==0 && s.pending==255);
|
|
image_to(&s,1); assert(f28335_boot_commit(&s,1,&manifest));
|
|
assert(f28335_boot_select(&s,&slot) && slot==1);
|
|
memcpy(backup,eeprom,sizeof(eeprom));
|
|
for(cut=0;cut<=68;++cut) {
|
|
memcpy(eeprom,backup,sizeof(eeprom)); reopen(&s); budget=cut;
|
|
(void)f28335_boot_confirm(&s,1); budget=-1; reopen(&s);
|
|
assert(s.active==0 || s.active==1);
|
|
assert(f28335_boot_select(&s,&slot) && (slot==0 || slot==1));
|
|
}
|
|
memcpy(eeprom,backup,sizeof(eeprom)); reopen(&s); assert(f28335_boot_confirm(&s,1));
|
|
/* CRC correct but malicious SCI8 destination and entry are rejected. */
|
|
image_to(&s,0); image[26]=0; image[27]=0xE0;
|
|
manifest.image_crc32=f28335_boot_crc(0,image,40);
|
|
image_to(&s,0); assert(!f28335_boot_verify(&s,0,&manifest,0));
|
|
image[27]=0x80; image[21]=0x90; manifest.image_crc32=f28335_boot_crc(0,image,40);
|
|
image_to(&s,0); assert(!f28335_boot_verify(&s,0,&manifest,0));
|
|
make_image(); image[22]=1; image[30]=1; image[35]=0x80;
|
|
manifest.image_crc32=f28335_boot_crc(0,image,40);
|
|
image_to(&s,0); assert(!f28335_boot_verify(&s,0,&manifest,0)); /* overlapping sections */
|
|
make_image(); image_to(&s,0); manifest.image_size=38;
|
|
manifest.image_crc32=f28335_boot_crc(0,image,38);
|
|
assert(!f28335_boot_verify(&s,0,&manifest,0)); /* missing terminator */
|
|
make_image(); image[22]=4; manifest.image_crc32=f28335_boot_crc(0,image,40);
|
|
image_to(&s,0); assert(!f28335_boot_verify(&s,0,&manifest,0)); /* trailing octets */
|
|
make_image(); image_to(&s,0); eeprom[F28335_AB_SLOT_A+29]^=1;
|
|
assert(!f28335_boot_verify(&s,0,&manifest,0));
|
|
/* Failed EEPROM reads fail closed, including subsequent writes. */
|
|
read_fail=1; assert(!f28335_boot_open(&s,&io));
|
|
assert(!f28335_boot_prepare(&s,0)); assert(!f28335_boot_write(&s,0,0,image,8)); read_fail=0;
|
|
for(entry=0x3FE00;entry<0x40000;++entry) assert(eeprom[entry]==0xA5);
|
|
if(argc>1) {
|
|
FILE *file=fopen(argv[1],"rb"); uint32_t offset,crc=0;
|
|
pcan_boot_byte_t bytes[32]; unsigned n;
|
|
assert(file); make_image();
|
|
manifest.image_size=(uint32_t)fread(eeprom+F28335_AB_SLOT_A,1,F28335_AB_SLOT_BYTES,file);
|
|
assert(!ferror(file) && fgetc(file)==EOF); fclose(file); reopen(&s);
|
|
for(offset=0;offset<manifest.image_size;offset+=n) {
|
|
n=manifest.image_size-offset<32?(unsigned)(manifest.image_size-offset):32;
|
|
assert(read_mem(0,F28335_AB_SLOT_A+offset,bytes,n)); crc=f28335_boot_crc(crc,bytes,n);
|
|
}
|
|
manifest.image_crc32=crc;
|
|
assert(f28335_boot_verify(&s,0,&manifest,&entry));
|
|
puts("Production SCI8 binary: CRC, destinations and entry accepted");
|
|
}
|
|
puts("F28335 A/B: journal power cuts, trial, rollback, confirm, bounds, SCI8: OK");
|
|
return 0;
|
|
}
|