#define _CRT_SECURE_NO_WARNINGS #include "../ports/tms320f28335/f28335_boot_store.h" #include #include #include 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;i0) --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