diff --git a/src/main.c b/src/main.c index f230544..79cd59a 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* * main.c - main routine of Gnuk * - * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -321,6 +321,23 @@ led_blink (int spec) chEvtSignalFlags (main_thread, spec); } +/* + * In Gnuk 1.0.[12], reGNUal was not relocatable. + * Now, it's relocatable, but we need to calculate its entry address + * based on it's pre-defined address. + */ +#define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400 +static uint32_t +calculate_regnual_entry_address (const uint8_t *addr) +{ + const uint8_t *p = addr + 4; + uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); + + v -= REGNUAL_START_ADDRESS_COMPATIBLE; + v += (uint32_t)addr; + return v; +} + /* * Entry point. @@ -332,6 +349,7 @@ int main (int argc, char *argv[]) { unsigned int count = 0; + uint32_t entry; (void)argc; (void)argv; @@ -438,6 +456,7 @@ main (int argc, char *argv[]) port_disable (); /* Set vector */ SCB->VTOR = (uint32_t)&_regnual_start; + entry = calculate_regnual_entry_address (&_regnual_start); #ifdef DFU_SUPPORT #define FLASH_SYS_START_ADDR 0x08000000 #define FLASH_SYS_END_ADDR (0x08000000+0x1000) @@ -456,12 +475,12 @@ main (int argc, char *argv[]) flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000); /* Leave Gnuk to exec reGNUal */ - (*func) (*((void (**)(void))(&_regnual_start+4))); + (*func) ((void (*)(void))entry); for (;;); } #else /* Leave Gnuk to exec reGNUal */ - flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4))); + flash_erase_all_and_exec ((void (*)(void))entry); #endif /* Never reached */