Compare commits

...

21 Commits

Author SHA1 Message Date
NIIBE Yutaka
b619db59d2 version 1.0.3 2013-03-14 14:46:53 +09:00
NIIBE Yutaka
8870d58b69 stabilize stlinkv2.py 2013-03-14 14:02:23 +09:00
NIIBE Yutaka
4abcddef93 fix for newer GNU Toolchain 2013-03-14 13:24:35 +09:00
NIIBE Yutaka
ca46cc465c more 2013-03-12 14:49:52 +09:00
NIIBE Yutaka
3cf5ed482f more 2013-03-12 14:24:47 +09:00
NIIBE Yutaka
87d95d0864 more change for stlinkv2.py 2013-03-12 14:10:50 +09:00
NIIBE Yutaka
428adc7ac6 add changelog 2013-03-12 11:43:44 +09:00
NIIBE Yutaka
cc185eabb5 Improve initialization 2013-03-12 11:42:07 +09:00
NIIBE Yutaka
80e3cda267 change main.c for relocatable reGNUal 2013-03-09 10:18:24 +09:00
NIIBE Yutaka
ee867794e7 update regnual 2013-03-09 10:17:16 +09:00
NIIBE Yutaka
a4f7386b8a relocatable reGNUal 2013-03-09 10:16:51 +09:00
NIIBE Yutaka
7d4d6cff5e fix usb. 2013-03-07 13:07:31 +09:00
NIIBE Yutaka
b09460f0ae follow change of USB stack 2013-03-07 09:42:49 +09:00
NIIBE Yutaka
4298809ffb USB stack implementation improvement 2013-03-07 09:37:49 +09:00
NIIBE Yutaka
b297cf22b6 add changelog entry for the bug fix of usb-icc 2013-02-27 20:23:01 +09:00
NIIBE Yutaka
f84f52156c bug fix 2013-02-27 20:20:59 +09:00
NIIBE Yutaka
1564a4fbe6 Fix configure typo, type punning pointers 2013-02-25 15:46:02 +09:00
NIIBE Yutaka
16610ca5c7 Merge branch 'STABLE-BRANCH-1-0' of www.gniibe.org:git/gnuk into STABLE-BRANCH-1-0 2013-02-22 21:34:16 +09:00
NIIBE Yutaka
352f81a61f Add Quan to THANKS 2013-02-22 21:32:58 +09:00
NIIBE Yutaka
7c82839fba apply GPG_DO_DISCRETIONARY from master 2013-02-22 21:29:27 +09:00
NIIBE Yutaka
10c685be16 add Paul to THANKS (should be done at the beginning) 2013-02-20 16:56:10 +09:00
19 changed files with 459 additions and 242 deletions

124
ChangeLog
View File

@@ -1,3 +1,127 @@
2013-03-14 Niibe Yutaka <gniibe@fsij.org>
* Version 1.0.3.
* src/usb_desc.c (gnukStringSerial): Updated.
* tool/stlinkv2.py (stlinkv2.start): Call write_debug_reg to run
the core again.
2013-03-13 Niibe Yutaka <gniibe@fsij.org>
* ChibiOS_2.0.8/os/ports/GCC/ARMCMx/cmsis/core_cm3.c (__STREXB)
(__STREXH, __STREXW): Specify R2 to avoid %0 and %2 will be same
register. This is for newer GNU binutils (>= 2.22).
2013-03-12 Niibe Yutaka <gniibe@fsij.org>
* tool/stlinkv2.py (stlinkv2.exit_from_debug_swd)
(stlinkv2.exit_from_debug_swim): New.
(stlinkv2.start): Call exit_from_debug_swd or
exit_from_debug_swim.
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.
* regnual/regnual.ld (MEMORY): 0x1400 was the value of Gnuk 1.0.1.
Keep this value.
(.text): Include .text.entry next to the .vectors.
(.got): New.
* regnual/sys.c (entry): Now, it's at .text.entry section.
Do relocations.
Don't use absolute values which causes relocations, but
access at GOT.
* regnual/Makefile (CFLAGS): Add -fpie.
2013-03-07 Niibe Yutaka <gniibe@fsij.org>
* src/usb_stm32f103.c (handle_setup0): Fix selecting handler.
Follow the USB stack change.
* regnual/regnual.c (usb_cb_device_reset): Rename from
regnual_device_reset.
(mem): Change type to uint32_t.
(mem_info): Removed.
(fetch): Avoid pointer punning.
(usb_cb_ctrl_write_finish): Rename from regnual_ctrl_write_finish.
(usb_cb_setup): Rename from regnual_setup.
(usb_cb_get_descriptor): Rename from regnual_get_descriptor.
(usb_cb_handle_event): Rename regnual_usb_event.
(usb_cb_interface): Rename regnual_interface.
(Device_Method): Remove.
(usb_cb_get_descriptor): Not use struct Descriptor.
2013-03-06 Niibe Yutaka <gniibe@fsij.org>
USB stack implementation improvement.
* src/usb_lld.c (Device_Method, method_p): Remove.
(usb_interrupt_handler): Call usb_cb_device_reset.
(std_get_descriptor): Call usb_cb_get_descriptor.
(std_set_configuration): Call usb_cb_handle_event.
(std_get_status, std_get_interface, std_set_interface): Call
usb_cb_interface.
(handle_setup0): Call usb_cb_setup.
(handle_in0): Call usb_cb_handle_event and
usb_cb_ctrl_write_finish.
(request_handler): Remove.
(handle_setup0): Call std_* directly, not indirectly by
request_handler.
(ep_intr_handler_IN, ep_intr_handler_OUT): Remove.
(usb_handle_transfer): Call EP*_Callback directly, not indirectly
by ep_intr_handler_IN, ep_intr_handler_OUT.
* src/usb_lld.h (struct usb_device_method, Device_Method): Remove.
(usb_cb_device_reset, usb_cb_ctrl_write_finish)
(usb_cb_setup, usb_cb_get_descriptor, usb_cb_handle_event)
(usb_cb_interface): Define callbacks.
(usb_initial_feature): New.
(struct Descriptor): Move to ...
* src/usb_desc.c: ... here.
(usb_initial_feature): New.
(usb_cb_get_descriptor): Rename from gnuk_get_descriptor and move
from usb_ctrl.c.
* src/usb_ctrl.c (usb_cb_device_reset): Rename from
gnuk_device_reset.
(usb_cb_setup): Rename from gnuk_setup.
(usb_cb_ctrl_write_finish): Rename from gnuk_ctrl_write_finish.
(usb_cb_event): Rename from gnuk_usb_event.
(usb_cb_interface): Rename from gnuk_interface.
(Device_Method): Remove.
* src/main.c (main): Use usb_initial_feature.
2013-02-27 Niibe Yutaka <gniibe@fsij.org>
* src/usb-icc.c (set_sw1sw2): Arguments are C and CHUNK_LEN.
Fix reporting remaining bytes.
(icc_send_data_block_gr): Follow the arguments change of
set_sw1sw2.
2013-02-25 Niibe Yutaka <gniibe@fsij.org>
* src/configure: Correct typo in help text.
* src/gnuk.h (struct key_data_internal): Use uint32_t.
* src/openpgp-do.c (do_openpgpcard_aid): Fix calculation of VID.
(compute_key_data_checksum): Don't use type-punning pointer.
(gpg_do_write_prvkey): Use coercing to char *.
2013-02-22 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (GPG_DO_DISCRETIONARY, cmp_discretionary): New.
(cmp_app_data): Change to factor out GPG_DO_DISCRETIONARY.
(gpg_do_table): Add GPG_DO_DISCRETIONARY.
2013-02-15 Niibe Yutaka <gniibe@fsij.org>
* Version 1.0.2.

View File

@@ -731,7 +731,7 @@ uint32_t __LDREXW(uint32_t *addr)
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
@@ -748,7 +748,7 @@ uint32_t __STREXB(uint8_t value, uint8_t *addr)
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
@@ -765,7 +765,7 @@ uint32_t __STREXH(uint16_t value, uint16_t *addr)
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);

22
NEWS
View File

@@ -1,5 +1,23 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.0.3
Released 2013-03-14, by NIIBE Yutaka
** Relocatable reGNUal
The upgrade helper, reGNUal, is now relocatable (other than the first
vector table). It runs well when loaded at different address. This
makes the upgrade procedure more stable.
** Compilation by newer GNU Toolchain
Now, Gnuk can be compiled with newer GNU Toolchain, specifically GCC
4.7.x and GNU Binutils 2.22. Old versions of Gnuk had problem for
ChibiOS_2.0.8/os/ports/GCC/ARMCMx/cmsis/core_cm3.c, which was fixed.
** Data object 0x0073
Data object 0x0073 is now available.
* Major changes in Gnuk 1.0.2
Released 2013-02-15, by NIIBE Yutaka
@@ -36,6 +54,10 @@ Now, VERIFY command accepts empty data and returns remaining trial
counts, or 0x9000 (OK) when it's already authenticated. This is
useful for application to synchronize card's authentication status.
** Extended Capabilities
Since Gnuk supports GET CHALLENGE command, the flag for GET CHALLENGE
in extended capabilities are now on.
* Major changes in Gnuk 1.0.1

23
README
View File

@@ -1,7 +1,7 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.0.2
2013-02-15
Version 1.0.3
2013-03-14
Niibe Yutaka
Free Software Initiative of Japan
@@ -108,14 +108,19 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
"GPG Password Agent" and "SSH Key Agent".
Qc: Do you know a good SWD debugger to connect FST-01 or something?
Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
writer program.
Ac: ST-Link/V2 is cheap one and works, although it's not very good
(for example, we have not yet been able to use OpenOCD to write
option bytes of STM32F103). We have a tool/stlinkv2.py as a flash
ROM writer program. Note that some "Discovery Kit" from ST has
the feature of ST-Link/V2, but it is not as stable as the real
one.
Release notes
=============
This is a second minor release in version 1.0 series of Gnuk.
This is a third minor release in version 1.0 series of Gnuk.
While it is daily use for a year and a half, some newly introduced
features (including key generation and firmware upgrade) should be
@@ -174,7 +179,7 @@ disable read from flash. For real use, please consider killing DfuSe
and enabling read protection using JTAG debugger.
I think that it could run on Olimex STM32-P103, or other boards with
STM32F103. Besides, we are porting it to STM32 Primer 2.
STM32F103. Besides, we did an experiment with STM32 Primer 2.
For PIN-pad support, I connect a consumer IR receive module to STBee
Mini and STM8S Discovery Kit, and use controller for TV. PIN
@@ -338,8 +343,7 @@ Recently, there is "gcc-arm-embedded" project. See:
https://launchpad.net/gcc-arm-embedded/
It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd
need "-O3 -Os" instead of "-O2" and it will be slightly better.
It is based on GCC 4.6 or 4.7.
Change directory to `src':
@@ -657,7 +661,8 @@ linux/Documentation/usb/usbmon.txt
Firmware update
===============
See doc/note/firmware-update.
See doc/note/firmware-update. Note that this is an experimental
feature.
Git Repositories

4
THANKS
View File

@@ -1,3 +1,5 @@
-*- coding: utf-8 -*-
We would like to express our gratitudes to Werner Koch for GnuPG, and
Giovanni Di Sirio for ChibiOS/RT.
@@ -14,5 +16,7 @@ Ludovic Rousseau ludovic.rousseau@free.fr
Luis Felipe R. Murillo luisfelipe@ucla.edu
MATSUU Takuto matsuu@gentoo.org
NAGAMI Takeshi nagami-takeshi@aist.go.jp
Nguyễn Hồng Quân quannguyen@mbm.vn
Paul Bakker polarssl_maintainer@polarssl.org
Shane Coughlan scoughlan@openinventionnetwork.com
Werner Koch wk@gnupg.org

View File

@@ -22,6 +22,7 @@ MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
DEFS = -DFREE_STANDING
CFLAGS = -O2 -g
CFLAGS += -Wa,-alms=$(notdir $(<:.c=.lst)) -fpie
CFLAGS += $(CWARN) -I . -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS)
LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT)

View File

@@ -1,7 +1,7 @@
/*
* regnual.c -- Firmware installation for STM32F103 Flash ROM
*
* Copyright (C) 2012 Free Software Initiative of Japan
* Copyright (C) 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.
@@ -99,33 +99,15 @@ static const uint8_t regnual_string_serial[] = {
'0', 0, '.', 0, '0', 0,
};
const struct Descriptor device_desc = {
regnual_device_desc,
sizeof (regnual_device_desc)
};
const struct Descriptor config_desc = {
regnual_config_desc,
sizeof (regnual_config_desc)
};
const struct Descriptor string_descs[] = {
{regnual_string_lang_id, sizeof (regnual_string_lang_id)},
{gnukStringVendor, sizeof (gnukStringVendor)},
{gnukStringProduct, sizeof (gnukStringProduct)},
{regnual_string_serial, sizeof (regnual_string_serial)},
};
#define NUM_STRING_DESC (sizeof (string_descs)/sizeof (struct Descriptor))
static void
regnual_device_reset (void)
void
usb_cb_device_reset (void)
{
/* Set DEVICE as not configured */
usb_lld_set_configuration (0);
/* Current Feature initialization */
usb_lld_set_feature (config_desc.Descriptor[7]);
usb_lld_set_feature (regnual_config_desc[7]);
usb_lld_reset ();
@@ -141,11 +123,9 @@ regnual_device_reset (void)
#define USB_REGNUAL_PROTECT 4
#define USB_REGNUAL_FINISH 5
static uint8_t mem[256];
static uint32_t mem[256/4];
static uint32_t result;
static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, };
static uint32_t rbit (uint32_t v)
{
@@ -159,7 +139,7 @@ static uint32_t fetch (int i)
{
uint32_t v;
v = *(uint32_t *)(&mem[i*4]);
v = mem[i];
return rbit (v);
}
@@ -186,9 +166,8 @@ static uint32_t calc_crc32 (void)
}
static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index,
uint16_t len)
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -200,7 +179,7 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
{
uint32_t dst_addr = (0x08000000 + value * 0x100);
result = flash_write (dst_addr, mem, 256);
result = flash_write (dst_addr, (const uint8_t *)mem, 256);
}
else if (req_no == USB_REGNUAL_PROTECT && len == 0
&& value == 0 && index == 0)
@@ -211,8 +190,8 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
}
}
static int
regnual_setup (uint8_t req, uint8_t req_no,
int
usb_cb_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -223,6 +202,10 @@ regnual_setup (uint8_t req, uint8_t req_no,
{
if (req_no == USB_REGNUAL_MEMINFO)
{
static const uint8_t *mem_info[2];
mem_info[0] = &_flash_start;
mem_info[1] = &_flash_end;
usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
return USB_SUCCESS;
}
@@ -240,7 +223,8 @@ regnual_setup (uint8_t req, uint8_t req_no,
return USB_UNSUPPORT;
if (index + len < 256)
memset (mem + index + len, 0xff, 256 - (index + len));
memset ((uint8_t *)mem + index + len, 0xff,
256 - (index + len));
usb_lld_set_data_to_recv (mem + index, len);
return USB_SUCCESS;
@@ -264,38 +248,55 @@ regnual_setup (uint8_t req, uint8_t req_no,
return USB_UNSUPPORT;
}
static int
regnual_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
int
usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
{
(void)index;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (device_desc.Descriptor,
device_desc.Descriptor_Size);
usb_lld_set_data_to_send (regnual_device_desc,
sizeof (regnual_device_desc));
return USB_SUCCESS;
}
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (config_desc.Descriptor,
config_desc.Descriptor_Size);
usb_lld_set_data_to_send (regnual_config_desc,
sizeof (regnual_config_desc));
return USB_SUCCESS;
}
else if (desc_type == STRING_DESCRIPTOR)
{
uint8_t desc_index = value & 0xff;
const uint8_t *str;
int size;
if (desc_index < NUM_STRING_DESC)
switch (desc_index)
{
usb_lld_set_data_to_send (string_descs[desc_index].Descriptor,
string_descs[desc_index].Descriptor_Size);
return USB_SUCCESS;
case 0:
str = regnual_string_lang_id;
size = sizeof (regnual_string_lang_id);
case 1:
str = gnukStringVendor;
size = sizeof (gnukStringVendor);
case 2:
str = gnukStringProduct;
size = sizeof (gnukStringProduct);
case 3:
str = regnual_string_serial;
size = sizeof (regnual_string_serial);
break;
default:
return USB_UNSUPPORT;
}
usb_lld_set_data_to_send (str, size);
return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
static int regnual_usb_event (uint8_t event_type, uint16_t value)
int usb_cb_handle_event (uint8_t event_type, uint16_t value)
{
(void)value;
@@ -311,20 +312,12 @@ static int regnual_usb_event (uint8_t event_type, uint16_t value)
return USB_UNSUPPORT;
}
static int regnual_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
{
(void)cmd; (void)interface; (void)alt;
return USB_UNSUPPORT;
}
const struct usb_device_method Device_Method = {
regnual_device_reset,
regnual_ctrl_write_finish,
regnual_setup,
regnual_get_descriptor,
regnual_usb_event,
regnual_interface,
};
static void wait (int count)
{

View File

@@ -39,6 +39,7 @@ SECTIONS
{
_text = .;
KEEP(*(.vectors))
*(.text.entry)
*(.text)
*(.text.*)
*(.rodata)
@@ -48,6 +49,12 @@ SECTIONS
*(.gcc*)
} > ram1
.got :
{
*(.got)
*(.got.*)
} > ram1
.ctors :
{
PROVIDE(_ctors_start_ = .);

View File

@@ -9,17 +9,41 @@ static void none (void)
{
}
/* Note: it is not reset */
static __attribute__ ((naked))
/*
* Note: the address of this routine 'entry' will be in the vectors as
* RESET, but this will be called from application. It's not RESET
* state, then.
*/
static __attribute__ ((naked,section(".text.entry")))
void entry (void)
{
asm volatile ("ldr r0, =__ram_end__\n\t"
"ldr r1, =__main_stack_size__\n\t"
asm volatile ("mov r0, pc\n\t"
"bic r0, r0, #255\n\t" /* R0 := vector_table address */
"mov r1, #0x90\n" /* R1 := numbers of entries * 4 */
"0:\n\t"
"ldr r2, [r0, r1]\n\t"
"add r2, r2, #-0x20000000\n\t"
"sub r2, r2, #0x1400\n\t"
"add r2, r2, r0\n\t" /* Relocate: -0x20001400 + R0 */
"str r2, [r0, r1]\n\t"
"subs r1, r1, #4\n\t"
"bne 0b\n\t"
/* Relocation done. We don't care the first entry. */
"ldr r3, .L00\n"
".LPIC00:\n\t"
"add r3, pc\n\t" /* R3 := @_GLOBAL_OFFSET_TABLE_ */
"ldr r4, .L00+4\n\t"
"ldr r0, [r3, r4]\n\t"
"ldr r4, .L00+8\n\t"
"ldr r1, [r3, r4]\n\t"
"sub r0, r0, r1\n\t"
"mov sp, r0\n\t"
/* Clear BSS. */
"mov r0, #0\n\t"
"ldr r1, =_bss_start\n\t"
"ldr r2, =_bss_end\n"
"ldr r4, .L00+12\n\t"
"ldr r1, [r3, r4]\n\t"
"ldr r4, .L00+16\n\t"
"ldr r2, [r3, r4]\n"
"0:\n\t"
"str r0, [r1], #4\n\t"
"cmp r2, r1\n\t"
@@ -30,6 +54,12 @@ void entry (void)
"bl main\n"
"1:\n\t"
"b 1b\n"
".L00:\n\t"
".word _GLOBAL_OFFSET_TABLE_-(.LPIC00+4)\n\t"
".word __ram_end__(GOT)\n\t"
".word __main_stack_size__(GOT)\n\t"
".word _bss_start(GOT)\n\t"
".word _bss_end(GOT)"
: /* no output */ : /* no input */ : "memory");
}

2
src/configure vendored
View File

@@ -84,7 +84,7 @@ Configuration:
-h, --help display this help and exit [no]
--vidpid=VID:PID specify vendor/product ID [<NONE>]
--target=TARGET specify target [OLIMEX_STM32_H103]
supported targes are:
supported targets are:
OLIMEX_STM32_H103
STM32_PRIMER2
CQ_STARM

View File

@@ -171,8 +171,8 @@ struct key_data {
};
struct key_data_internal {
uint8_t data[KEY_CONTENT_LEN]; /* p and q */
uint8_t checksum[DATA_ENCRYPTION_KEY_SIZE];
uint32_t data[KEY_CONTENT_LEN/4]; /* p and q */
uint32_t checksum[DATA_ENCRYPTION_KEY_SIZE/4];
};
struct prvkey_data {

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;
@@ -338,7 +356,7 @@ main (int argc, char *argv[])
flash_unlock ();
device_initialize_once ();
usb_lld_init (Config_Descriptor.Descriptor[7]);
usb_lld_init (usb_initial_feature);
random_init ();
while (1)
@@ -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 */

View File

@@ -241,7 +241,7 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
#define GPG_DO_LOGIN_DATA 0x005e
#define GPG_DO_CH_DATA 0x0065
#define GPG_DO_APP_DATA 0x006e
/* XXX: 0x0073 ??? */
#define GPG_DO_DISCRETIONARY 0x0073
#define GPG_DO_SS_TEMP 0x007a
#define GPG_DO_DS_COUNT 0x0093
#define GPG_DO_EXTCAP 0x00c0
@@ -447,7 +447,7 @@ const uint8_t openpgpcard_aid[] = {
static int
do_openpgpcard_aid (uint16_t tag, int with_tag)
{
uint16_t vid = *((const volatile uint16_t *)&openpgpcard_aid[8]);
uint16_t vid = (openpgpcard_aid[8] << 8) | openpgpcard_aid[9];
if (with_tag)
{
@@ -664,7 +664,7 @@ compute_key_data_checksum (struct key_data_internal *kdi, int check_or_calc)
uint32_t d[4] = { 0, 0, 0, 0 };
for (i = 0; i < KEY_CONTENT_LEN / sizeof (uint32_t); i++)
d[i&3] ^= *(uint32_t *)(&kdi->data[i*4]);
d[i&3] ^= kdi->data[i];
if (check_or_calc == 0) /* store */
{
@@ -790,7 +790,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
encrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal));
r = flash_key_write (key_addr, kdi.data, modulus);
r = flash_key_write (key_addr, (const uint8_t *)kdi.data, modulus);
if (modulus_allocated_here)
modulus_free (modulus);
@@ -989,10 +989,14 @@ static const uint16_t cmp_ch_data[] = {
};
static const uint16_t cmp_app_data[] = {
10,
3,
GPG_DO_AID,
GPG_DO_HIST_BYTES,
/* XXX Discretionary data objects 0x0073 ??? */
GPG_DO_DISCRETIONARY,
};
static const uint16_t cmp_discretionary[] = {
8,
GPG_DO_EXTCAP,
GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT,
GPG_DO_PW_STATUS,
@@ -1038,6 +1042,7 @@ gpg_do_table[] = {
/* Compound data: Read access only */
{ GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data },
{ GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data },
{ GPG_DO_DISCRETIONARY, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_discretionary },
{ GPG_DO_SS_TEMP, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ss_temp },
/* Simple data: write access only */
{ GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,

View File

@@ -321,10 +321,8 @@ static void no_buf (struct ep_in *epi, size_t len)
epi->buf_len = 0;
}
static void set_sw1sw2 (struct ep_in *epi)
static void set_sw1sw2 (struct ccid *c, size_t chunk_len)
{
struct ccid *c = (struct ccid *)epi->priv;
if (c->a->expected_res_size >= c->len)
{
c->sw1sw2[0] = 0x90;
@@ -333,10 +331,10 @@ static void set_sw1sw2 (struct ep_in *epi)
else
{
c->sw1sw2[0] = 0x61;
if (c->len >= 256)
if (c->len - chunk_len >= 256)
c->sw1sw2[1] = 0;
else
c->sw1sw2[1] = (uint8_t)c->len;
c->sw1sw2[1] = (uint8_t)(c->len - chunk_len);
}
}
@@ -968,7 +966,7 @@ icc_send_data_block_gr (struct ccid *c, size_t chunk_len)
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE);
set_sw1sw2 (c->epi);
set_sw1sw2 (c, chunk_len);
if (chunk_len <= USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE)
{

View File

@@ -1,7 +1,7 @@
/*
* usb_ctrl.c - USB control pipe device specific code for 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.
@@ -147,8 +147,8 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
#endif
}
static void
gnuk_device_reset (void)
void
usb_cb_device_reset (void)
{
int i;
@@ -156,7 +156,7 @@ gnuk_device_reset (void)
usb_lld_set_configuration (0);
/* Current Feature initialization */
usb_lld_set_feature (Config_Descriptor.Descriptor[7]);
usb_lld_set_feature (usb_initial_feature);
usb_lld_reset ();
@@ -214,8 +214,8 @@ static int download_check_crc32 (const uint32_t *end_p)
return USB_UNSUPPORT;
}
static int
gnuk_setup (uint8_t req, uint8_t req_no,
int
usb_cb_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -310,9 +310,8 @@ gnuk_setup (uint8_t req, uint8_t req_no,
return USB_UNSUPPORT;
}
static void gnuk_ctrl_write_finish (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index,
uint16_t len)
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -329,38 +328,7 @@ static void gnuk_ctrl_write_finish (uint8_t req, uint8_t req_no,
}
static int
gnuk_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
{
(void)index;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (Device_Descriptor.Descriptor,
Device_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (Config_Descriptor.Descriptor,
Config_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == STRING_DESCRIPTOR)
{
uint8_t desc_index = value & 0xff;
if (desc_index < NUM_STRING_DESC)
{
usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor,
String_Descriptors[desc_index].Descriptor_Size);
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}
static int gnuk_usb_event (uint8_t event_type, uint16_t value)
int usb_cb_handle_event (uint8_t event_type, uint16_t value)
{
int i;
uint8_t current_conf;
@@ -401,7 +369,7 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value)
return USB_UNSUPPORT;
}
static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
{
static uint8_t zero = 0;
@@ -429,18 +397,6 @@ static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
}
}
/*
* Interface to USB core
*/
const struct usb_device_method Device_Method = {
gnuk_device_reset,
gnuk_ctrl_write_finish,
gnuk_setup,
gnuk_get_descriptor,
gnuk_usb_event,
gnuk_interface,
};
CH_IRQ_HANDLER (Vector90)
{

View File

@@ -9,6 +9,13 @@
#include "usb_conf.h"
#include "usb-cdc.h"
struct Descriptor
{
const uint8_t *Descriptor;
uint16_t Descriptor_Size;
};
#define USB_ICC_INTERFACE_CLASS 0x0B
#define USB_ICC_INTERFACE_SUBCLASS 0x00
#define USB_ICC_INTERFACE_BULK_PROTOCOL 0x00
@@ -53,6 +60,15 @@ static const uint8_t gnukDeviceDescriptor[] = {
#define NUM_INTERFACES (ICC_NUM_INTERFACES+VCOM_NUM_INTERFACES+MSC_NUM_INTERFACES)
#if defined(USB_SELF_POWERED)
#define USB_INITIAL_FEATURE 0xC0 /* bmAttributes: self powered */
#else
#define USB_INITIAL_FEATURE 0x80 /* bmAttributes: bus powered */
#endif
const uint8_t usb_initial_feature = USB_INITIAL_FEATURE;
/* Configuation Descriptor */
static const uint8_t gnukConfigDescriptor[] = {
9, /* bLength: Configuation Descriptor size */
@@ -61,11 +77,7 @@ static const uint8_t gnukConfigDescriptor[] = {
NUM_INTERFACES, /* bNumInterfaces: */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
#if defined(USB_SELF_POWERED)
0xC0, /* bmAttributes: self powered */
#else
0x80, /* bmAttributes: bus powered */
#endif
USB_INITIAL_FEATURE, /* bmAttributes*/
50, /* MaxPower 100 mA */
/* Interface Descriptor */
@@ -260,25 +272,25 @@ static const uint8_t gnukStringLangID[] = {
const uint8_t gnukStringSerial[] = {
19*2+2, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
/* FSIJ-1.0.1- */
/* FSIJ-1.0.3- */
'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0,
'1', 0, '.', 0, '0', 0, '.', 0, '2', 0, /* Version number of Gnuk */
'1', 0, '.', 0, '0', 0, '.', 0, '3', 0, /* Version number of Gnuk */
'-', 0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
const struct Descriptor Device_Descriptor = {
static const struct Descriptor Device_Descriptor = {
gnukDeviceDescriptor,
sizeof (gnukDeviceDescriptor)
};
const struct Descriptor Config_Descriptor = {
static const struct Descriptor Config_Descriptor = {
gnukConfigDescriptor,
sizeof (gnukConfigDescriptor)
};
const struct Descriptor String_Descriptors[NUM_STRING_DESC] = {
static const struct Descriptor String_Descriptors[NUM_STRING_DESC] = {
{gnukStringLangID, sizeof (gnukStringLangID)},
{gnukStringVendor, sizeof (gnukStringVendor)},
{gnukStringProduct, sizeof (gnukStringProduct)},
@@ -287,3 +299,34 @@ const struct Descriptor String_Descriptors[NUM_STRING_DESC] = {
{gnuk_config_options, sizeof (gnuk_config_options)},
{sys_version, sizeof (sys_version)},
};
int
usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
{
(void)index;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (Device_Descriptor.Descriptor,
Device_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (Config_Descriptor.Descriptor,
Config_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == STRING_DESCRIPTOR)
{
uint8_t desc_index = value & 0xff;
if (desc_index < NUM_STRING_DESC)
{
usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor,
String_Descriptors[desc_index].Descriptor_Size);
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}

View File

@@ -74,12 +74,10 @@ struct DEVICE_INFO
static struct CONTROL_INFO control_info;
static struct DEVICE_INFO device_info;
static struct DATA_INFO data_info;
extern const struct usb_device_method Device_Method;
static struct CONTROL_INFO *const ctrl_p = &control_info;
static struct DEVICE_INFO *const dev_p = &device_info;
static struct DATA_INFO *const data_p = &data_info;
static const struct usb_device_method *const method_p = &Device_Method;
#define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */
#define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */
@@ -399,7 +397,7 @@ usb_interrupt_handler (void)
if (istr_value & ISTR_RESET)
{
st103_set_istr (CLR_RESET);
method_p->reset ();
usb_cb_device_reset ();
}
if (istr_value & ISTR_DOVR)
@@ -529,7 +527,7 @@ static int std_get_status (uint8_t req,
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
r = (*method_p->interface) (USB_QUERY_INTERFACE, index, 0);
r = usb_cb_interface (USB_QUERY_INTERFACE, index, 0);
if (r != USB_SUCCESS)
return USB_UNSUPPORT;
@@ -700,7 +698,7 @@ static int std_get_descriptor (uint8_t req, uint16_t value,
(void)length;
if (rcp == DEVICE_RECIPIENT)
return (*method_p->get_descriptor) ((value >> 8), index, value);
return usb_cb_get_descriptor ((value >> 8), index, value);
return USB_UNSUPPORT;
}
@@ -736,7 +734,7 @@ static int std_set_configuration (uint8_t req, uint16_t value,
{
int r;
r = (*method_p->event) (USB_EVENT_CONFIG, value);
r = usb_cb_handle_event (USB_EVENT_CONFIG, value);
if (r == USB_SUCCESS)
return USB_SUCCESS;
}
@@ -760,7 +758,7 @@ static int std_get_interface (uint8_t req, uint16_t value,
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
return (*method_p->interface) (USB_GET_INTERFACE, index, 0);
return usb_cb_interface (USB_GET_INTERFACE, index, 0);
}
return USB_UNSUPPORT;
@@ -784,7 +782,7 @@ static int std_set_interface (uint8_t req, uint16_t value,
if (dev_p->current_configuration != 0)
return USB_UNSUPPORT;
r = (*method_p->interface) (USB_SET_INTERFACE, index, value);
r = usb_cb_interface (USB_SET_INTERFACE, index, value);
if (r == USB_SUCCESS)
return USB_SUCCESS;
}
@@ -792,21 +790,6 @@ static int std_set_interface (uint8_t req, uint16_t value,
return USB_UNSUPPORT;
}
static const HANDLER std_request_handler[TOTAL_REQUEST] = {
std_get_status,
std_clear_feature,
std_none,
std_set_feature,
std_none,
std_set_address,
std_get_descriptor,
std_none, /* set_descriptor is not supported */
std_get_configuration,
std_set_configuration,
std_get_interface,
std_set_interface,
std_none, /* sync_frame is not supported (for now) */
};
static void handle_setup0 (void)
{
@@ -836,13 +819,26 @@ static void handle_setup0 (void)
{
if (req < TOTAL_REQUEST)
{
handler = std_request_handler[req];
switch (req)
{
case 0: handler = std_get_status; break;
case 1: handler = std_clear_feature; break;
case 3: handler = std_set_feature; break;
case 5: handler = std_set_address; break;
case 6: handler = std_get_descriptor; break;
case 8: handler = std_get_configuration; break;
case 9: handler = std_set_configuration; break;
case 10: handler = std_get_interface; break;
case 11: handler = std_set_interface; break;
default: handler = std_none; break;
}
r = (*handler) (ctrl_p->bmRequestType,
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
}
}
else
r = (*method_p->setup) (ctrl_p->bmRequestType, req,
r = usb_cb_setup (ctrl_p->bmRequestType, req,
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
if (r != USB_SUCCESS)
@@ -890,10 +886,10 @@ static void handle_in0 (void)
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
{
st103_set_daddr (ctrl_p->wValue);
(*method_p->event) (USB_EVENT_ADDRESS, ctrl_p->wValue);
usb_cb_handle_event (USB_EVENT_ADDRESS, ctrl_p->wValue);
}
else
(*method_p->ctrl_write_finish) (ctrl_p->bmRequestType,
usb_cb_ctrl_write_finish (ctrl_p->bmRequestType,
ctrl_p->bRequest, ctrl_p->wValue,
ctrl_p->wIndex, ctrl_p->wLength);
@@ -938,26 +934,6 @@ void WEAK EP5_OUT_Callback (void);
void WEAK EP6_OUT_Callback (void);
void WEAK EP7_OUT_Callback (void);
void (*const ep_intr_handler_IN[7]) (void) = {
EP1_IN_Callback,
EP2_IN_Callback,
EP3_IN_Callback,
EP4_IN_Callback,
EP5_IN_Callback,
EP6_IN_Callback,
EP7_IN_Callback,
};
void (*const ep_intr_handler_OUT[7]) (void) = {
EP1_OUT_Callback,
EP2_OUT_Callback,
EP3_OUT_Callback,
EP4_OUT_Callback,
EP5_OUT_Callback,
EP6_OUT_Callback,
EP7_OUT_Callback,
};
static void
usb_handle_transfer (void)
{
@@ -1008,13 +984,31 @@ usb_handle_transfer (void)
if ((ep_value & EP_CTR_RX) != 0)
{
st103_ep_clear_ctr_rx (ep_index);
(*ep_intr_handler_OUT[ep_index-1]) ();
switch ((ep_index - 1))
{
case 0: EP1_OUT_Callback (); break;
case 1: EP2_OUT_Callback (); break;
case 2: EP3_OUT_Callback (); break;
case 3: EP4_OUT_Callback (); break;
case 4: EP5_OUT_Callback (); break;
case 5: EP6_OUT_Callback (); break;
case 6: EP7_OUT_Callback (); break;
}
}
if ((ep_value & EP_CTR_TX) != 0)
{
st103_ep_clear_ctr_tx (ep_index);
(*ep_intr_handler_IN[ep_index-1]) ();
switch ((ep_index - 1))
{
case 0: EP1_IN_Callback (); break;
case 1: EP2_IN_Callback (); break;
case 2: EP3_IN_Callback (); break;
case 3: EP4_IN_Callback (); break;
case 4: EP5_IN_Callback (); break;
case 5: EP6_IN_Callback (); break;
case 6: EP7_IN_Callback (); break;
}
}
}
}

View File

@@ -49,29 +49,20 @@ enum DESCRIPTOR_TYPE
#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0)
#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0)
struct Descriptor
{
const uint8_t *Descriptor;
uint16_t Descriptor_Size;
};
enum
{
USB_UNSUPPORT = 0,
USB_SUCCESS = 1,
};
struct usb_device_method
{
void (*reset) (void);
void (*ctrl_write_finish) (uint8_t req, uint8_t req_no,
void usb_cb_device_reset (void);
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len);
int (*setup) (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len);
int (*get_descriptor) (uint8_t desc_type, uint16_t index, uint16_t value);
int (*event) (uint8_t event_type, uint16_t value);
int (*interface) (uint8_t cmd, uint16_t interface, uint16_t value);
};
int usb_cb_setup (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len);
int usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value);
int usb_cb_handle_event (uint8_t event_type, uint16_t value);
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t value);
enum {
USB_EVENT_ADDRESS,
@@ -87,14 +78,6 @@ enum {
USB_QUERY_INTERFACE,
};
extern void USB_Cable_Config (int NewState);
extern const struct usb_device_method Device_Method;
extern const struct Descriptor Device_Descriptor;
extern const struct Descriptor Config_Descriptor;
extern const struct Descriptor String_Descriptors[];
enum DEVICE_STATE
{
UNCONNECTED,
@@ -106,6 +89,7 @@ enum DEVICE_STATE
};
extern uint32_t bDeviceState;
extern const uint8_t usb_initial_feature;
#define STM32_USB_IRQ_PRIORITY 11

View File

@@ -3,7 +3,7 @@
"""
stlinkv2.py - a tool to control ST-Link/V2
Copyright (C) 2012 Free Software Initiative of Japan
Copyright (C) 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.
@@ -165,12 +165,20 @@ class stlinkv2(object):
v = self.execute_get("\xf5\x00", 2)
return (v[1] * 256 + v[0])
def exit_from_debug_swd(self):
self.execute_put("\xf2\x21\x00")
time.sleep(1)
def exit_from_dfu(self):
self.__devhandle.bulkWrite(self.__bulkout, "\xf3\x07", self.__timeout)
self.execute_put("\xf3\x07\x00")
time.sleep(1)
def exit_from_debug_swim(self):
self.execute_put("\xf4\x01\x00")
time.sleep(1)
def enter_swd(self):
self.__devhandle.bulkWrite(self.__bulkout, "\xf2\x20\xa3", self.__timeout)
self.execute_put("\xf2\x20\xa3")
time.sleep(1)
def get_status(self):
@@ -208,6 +216,9 @@ class stlinkv2(object):
def write_reg(self, regno, value):
return self.execute_get("\xf2\x06" + pack('<BI', regno, value), 2)
def write_debug_reg(self, addr, value):
return self.execute_get("\xf2\x35" + pack('<II', addr, value), 2)
def run(self):
v = self.execute_get("\xf2\x09\x00", 2)
return (v[1] << 8) + v[0]
@@ -216,6 +227,11 @@ class stlinkv2(object):
v = self.execute_get("\xf2\x22\x00", 4)
return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24)
def version(self):
v = self.execute_get("\xf1", 6)
val = (v[0] << 8) + v[1]
return ((val >> 12) & 0x0f, (val >> 6) & 0x3f, val & 0x3f)
# For FST-01-00 and FST-01: LED on, USB connect
def setup_gpio(self):
apb2enr = self.read_memory_u32(0x40021018)
@@ -444,13 +460,23 @@ class stlinkv2(object):
def start(self):
mode = self.stl_mode()
if mode == 2:
return
elif mode != 1:
self.exit_from_debug_swd()
elif mode == 5:
self.exit_from_debug_swim()
elif mode != 1 and mode != 4:
self.exit_from_dfu()
mode = self.stl_mode()
print "Change ST-Link/V2 mode to: %04x" % mode
new_mode = self.stl_mode()
print "Change ST-Link/V2 mode %04x -> %04x" % (mode, new_mode)
self.enter_swd()
s = self.get_status()
if s != 0x0080:
print "Status is %04x" % s
self.run()
s = self.get_status()
if s != 0x0080:
# DCB_DHCSR DBGKEY
self.write_debug_reg(0xE000EDF0, 0xA05F0000)
s = self.get_status()
if s != 0x0080:
raise ValueError("Status of core is not running.", s)
mode = self.stl_mode()
@@ -511,6 +537,7 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
if not stl:
raise ValueError("No ST-Link/V2 device found.", None)
print "ST-Link/V2 version info: %d %d %d" % stl.version()
stl.start()
core_id = stl.core_id()
chip_id = stl.read_memory_u32(0xE0042000)
@@ -533,6 +560,11 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
stl.enter_debug()
status = stl.get_status()
if status != 0x0081:
print "Core does not halt, try API V2 halt."
# DCB_DHCSR DBGKEY|C_HALT|C_DEBUGEN
stl.write_debug_reg(0xE000EDF0, 0xA05F0003)
status = stl.get_status()
if status != 0x0081:
raise ValueError("Status of core is not halt.", status)