Option to include sketch in flash?

If it's possible with AVR executable images, a digital signature would solve some of the problems. As an added bonus, if the developer keeps the signing key a secret, the provenance of an image can determined.

OK, took some time today, ran a few tests with essentially some variations on the following code.

volatile char UUID[]  = "<UUID=da51a9f0-9a49-11e0-aa80-0800200c9a66>";

char version[] = "UUID_TEST 0.04";

void setup()
{
  Serial.begin(115200);
  Serial.println(version);
  UUID[0] = UUID[0];
}

void loop(){}

Then I retrieved the whole 32K image with [dosbox windows 7]

cd C:\Program Files (x86)\arduino-0021\hardware\tools\avr\bin>
avrdude -C "C:\Program Files (x86)\arduino-0022\hardware\tools\avr\etc\avrdude.conf" -v -v -v -v -p atmega328p -c stk500 -U flash:r:"C:/arduino.bin":r -P\\.\COM5 -b57600

viewing the binary easily reveals the UUID. See picture attached.

Some notes:
The UUID array must be volatile and the assignment UUID[0] = UUID[0] are needed both otherwise the compiler optimizes it away.

size without UUID string: 1908 bytes
size with UUID string: 1960 bytes

so this proof of concept implementation took 52 bytes.

  • Remove the tag structure <UUID=...> (-7) => 45 bytes
  • Remove - signs in the UUID (-4) => 41 bytes
  • Make the UUID binary (-17) => 24 bytes.

proof is in the pudding test:

volatile uint8_t UUID[] = { 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 
                          0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65 };  // character e 16 times
                          
char version[] = "UUID_TEST 0.06";

void setup()
{
  Serial.begin(115200);
  Serial.println(version);
  UUID[0] = UUID[0];
}

void loop(){}

size without UUID uint8_t array : 1908 bytes
size with UUID uint8_t array: 1932 bytes
so UUID signature now takes 24 bytes.

OK tinkered enough :wink:
Rob

RAM is in short supply. You MUST figure out how to put the UUID in flash only (and not have it garbage collected.)

first try

#include <avr/pgmspace.h>

//volatile char UUID[]  = "<UUID=da51a9f0-9a49-11e0-aa80-0800200c9a66>";
volatile uint8_t UUID[] PROGMEM = 
            { 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 
              0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65 };
                          
char version[] = "UUID_TEST 0.08";

void setup()
{
  Serial.begin(115200);
  Serial.println(version);
  uint8_t x = UUID[0];
}

void loop(){}

code size: 1928 ; so 4 bytes less but ==> 16 in PROGMEM and 4 in RAM, data still need to be referenced from RAM

gotta think deeper ....:wink:

2.5 hours and many many webpages later, dived into assembly to find out how to declare an array in assembly in flash.

char version[] = "UUID_TEST 0.10";

void setup()
{
  asm volatile(
  ".cseg"   // use code segment
  "uuid:  .byte 101,102,101,102,101,102,101,102,101,102,101,102,101,102,101,102"
  );
  Serial.begin(115200);
  Serial.println(version);
}

void loop(){}

code size: 1924 ; so the 16 bytes of the UUID in flash; no reference needed

filling the "uuid array" can also be done in hex

"uuid: .byte 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65"

or a bit shorter

"uuid: .word 0x6565, 0x6565, 0x6565, 0x6565, 0x6565, 0x6565, 0x6565, 0x6565"

So in the end storing a signature in the flash part of the code is only a few lines.

Thanks westfw for pushing me to the limits, I learned a few bits...
Rob

I didn't mean to make you dig deeply into advanced magics (though perhaps it was a good thing!)
It's also possible to get the linker to treat any file as "binary" to be explicitly included (maybe) in a final .elf/.hex file.
It would look something like

avr-objcopy -v -I binary -O elf32-avr -B avr  mysketch.pde sourcecode.o

(objcopy is one of those utilities that is a lot more complex than you would think it would be. It handles OODLES of different formats!)