change main.c for relocatable reGNUal

This commit is contained in:
NIIBE Yutaka
2013-03-09 10:04:36 +09:00
parent ee867794e7
commit 80e3cda267
2 changed files with 27 additions and 3 deletions

View File

@@ -1,3 +1,8 @@
2013-03-09 Niibe Yutaka <gniibe@fsij.org>
* src/main.c (calculate_regnual_entry_address): New.
(main): Use calculate_regnual_entry_address for entry point.
2013-03-08 Niibe Yutaka <gniibe@fsij.org>
Relocatable reGNUal.

View File

@@ -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 <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -319,6 +319,23 @@ led_blink (int spec)
chEvtSignal (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.
@@ -330,6 +347,7 @@ int
main (int argc, char *argv[])
{
unsigned int count = 0;
uint32_t entry;
(void)argc;
(void)argv;
@@ -429,6 +447,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)
@@ -447,12 +466,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 */