diff --git a/targets/stm32l442/Makefile b/targets/stm32l442/Makefile
index b038069..f65e709 100644
--- a/targets/stm32l442/Makefile
+++ b/targets/stm32l442/Makefile
@@ -12,17 +12,17 @@ all-locked:
$(MAKE) -f application.mk -j8 solo.hex EXTRA_DEFINES='-DFLASH_ROP=2'
debugboot-app:
- $(MAKE) -f application.mk -j8 solo.hex DEBUG=1 \
+ $(MAKE) -f application.mk -j8 solo.hex DEBUG=2 \
LDSCRIPT=linker/stm32l4xx_extra.ld EXTRA_DEFINES='-DAPPLICATION_START_PAGE=16 -DSOLO_HACKER'
debugboot-boot:
$(MAKE) -f bootloader.mk -j8 bootloader.hex DEBUG=1 \
LDSCRIPT=linker/bootloader_stm32l4xx_extra.ld EXTRA_DEFINES='-DAPPLICATION_START_PAGE=16 -DSOLO_HACKER'
-boot:
- $(MAKE) -f bootloader.mk -j8 bootloader.hex DEBUG=$(DEBUG)
+boot-sig-checking:
+ $(MAKE) -f bootloader.mk -j8 bootloader.hex
-boot-hacker:
+boot-no-sig:
$(MAKE) -f bootloader.mk -j8 bootloader.hex EXTRA_DEFINES='-DSOLO_HACKER'
clean:
diff --git a/targets/stm32l442/bootloader/main.c b/targets/stm32l442/bootloader/main.c
index 19e930c..afdc15f 100644
--- a/targets/stm32l442/bootloader/main.c
+++ b/targets/stm32l442/bootloader/main.c
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2018 SoloKeys, Inc.
- *
+ *
* This file is part of Solo.
- *
+ *
* Solo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* Solo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Solo. If not, see
- *
+ *
* This code is available under licenses for commercial use.
* Please contact SoloKeys for more information.
*/
@@ -114,10 +114,10 @@ int main(int argc, char * argv[])
}
else
{
+
printf1(TAG_RED,"Not authorized to boot (%08x == %08lx)\r\n", AUTH_WORD_ADDR, *(uint32_t*)AUTH_WORD_ADDR);
}
start_bootloader:
-
usbhid_init();
printf1(TAG_GEN,"init usb\n");
@@ -155,7 +155,7 @@ int main(int argc, char * argv[])
device_reboot();
}
#ifdef SOLO_HACKER
- // Boot ST bootloader if button is held for 2s
+ // Boot ST bootloader if button is held for 5s
if (!device_is_button_pressed())
{
stboot_time = millis();
diff --git a/targets/stm32l442/merge_hex.py b/targets/stm32l442/merge_hex.py
index 5e46e03..397a72b 100644
--- a/targets/stm32l442/merge_hex.py
+++ b/targets/stm32l442/merge_hex.py
@@ -1,21 +1,21 @@
#
# Copyright (C) 2018 SoloKeys, Inc.
-#
+#
# This file is part of Solo.
-#
+#
# Solo is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-#
+#
# Solo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Solo. If not, see
-#
+#
# This code is available under licenses for commercial use.
# Please contact SoloKeys for more information.
#
@@ -59,6 +59,14 @@ for i in range(2, len(args)-1):
print('merging %s with ' % (args[1]), args[i])
first.merge(IntelHex( args[i] ), overlap = 'replace')
+first [ flash_addr(APPLICATION_END_PAGE-1) ] = 0x41
+first [ flash_addr(APPLICATION_END_PAGE-1)+1 ] = 0x41
+
+first[AUTH_WORD_ADDR-4] = 0
+first[AUTH_WORD_ADDR-1] = 0
+first[AUTH_WORD_ADDR-2] = 0
+first[AUTH_WORD_ADDR-3] = 0
+
first[AUTH_WORD_ADDR] = 0
first[AUTH_WORD_ADDR+1] = 0
first[AUTH_WORD_ADDR+2] = 0
@@ -69,6 +77,7 @@ first[AUTH_WORD_ADDR+5] = 0xff
first[AUTH_WORD_ADDR+6] = 0xff
first[AUTH_WORD_ADDR+7] = 0xff
+
if secret_attestation_key is not None:
key = unhexlify(secret_attestation_key)
diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c
index 94d024c..7bc5f48 100644
--- a/targets/stm32l442/src/device.c
+++ b/targets/stm32l442/src/device.c
@@ -124,6 +124,22 @@ void usb_init(void);
void usbhid_init()
{
usb_init();
+
+#if DEBUG_LEVEL>1
+ wait_for_usb_tether();
+#endif
+
+}
+
+void wait_for_usb_tether()
+{
+ while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) )
+ ;
+ while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) )
+ ;
+ delay(10);
+ while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) )
+ ;
}
int usbhid_recv(uint8_t * msg)
diff --git a/targets/stm32l442/src/init.c b/targets/stm32l442/src/init.c
index 0004318..daa81d0 100644
--- a/targets/stm32l442/src/init.c
+++ b/targets/stm32l442/src/init.c
@@ -210,7 +210,6 @@ void usb_init()
USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC);
- // USBD_Composite_Set_Classes(&USBD_CDC, &USBD_CDC);
in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0;
out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0;
diff --git a/tools/solotool.py b/tools/solotool.py
index dbd5bc6..3a579eb 100644
--- a/tools/solotool.py
+++ b/tools/solotool.py
@@ -170,7 +170,10 @@ class SoloClient():
ret = data[0]
if ret != CtapError.ERR.SUCCESS:
- raise RuntimeError('Device returned non-success code %02x' % ret)
+ str = ''
+ if ret == CtapError.ERR.NOT_ALLOWED:
+ str = 'Out of bounds write'
+ raise RuntimeError('Device returned non-success code %02x: %s' % (ret,str))
return data[1:]
@@ -184,7 +187,10 @@ class SoloClient():
ret = res.signature[0]
if ret != CtapError.ERR.SUCCESS:
- raise RuntimeError('Device returned non-success code %02x' % ret)
+ str = ''
+ if ret == CtapError.ERR.NOT_ALLOWED:
+ str = 'Out of bounds write'
+ raise RuntimeError('Device returned non-success code %02x: %s' % (ret,str))
return res.signature[1:]
@@ -506,7 +512,7 @@ def attempt_to_find_device(p):
return found
def attempt_to_boot_bootloader(p):
- print('Bootloader not active. Attempting to boot into bootloader mode...')
+
try:
p.enter_solo_bootloader()
except OSError:
@@ -520,8 +526,8 @@ def attempt_to_boot_bootloader(p):
print('Solo rebooted. Reconnecting...')
time.sleep(.500)
if not attempt_to_find_device(p):
- print('Failed to reconnect!')
- sys.exit(1)
+ raise RuntimeError('Failed to reconnect!')
+
def solo_main():
parser = argparse.ArgumentParser()
@@ -636,10 +642,16 @@ def sign_main():
def use_dfu(args):
fw = args.__dict__['[firmware]']
- dfu = DFUDevice()
- try:
- dfu.find(ser = args.dfu_serial)
- except RuntimeError:
+
+ for i in range(0,8):
+ dfu = DFUDevice()
+ try:
+ dfu.find(ser = args.dfu_serial)
+ except RuntimeError:
+ time.sleep(0.25)
+ dfu = None
+
+ if dfu is None:
print('No STU DFU device found. ')
if args.dfu_serial:
print('Serial number used: ', args.dfu_serial)
@@ -652,7 +664,7 @@ def use_dfu(args):
chunk = 2048
seg = ih.segments()[0]
- size = sum([x[1] - x[0] for x in ih.segments()])
+ size = sum([max(x[1] - x[0],chunk) for x in ih.segments()])
total = 0
t1 = time.time()*1000
@@ -672,20 +684,27 @@ def use_dfu(args):
dfu.write_page(i,data)
total += chunk
progress = total/float(size)*100
+
sys.stdout.write('downloading %.2f%% %08x - %08x ... \r' % (progress,i,i+page))
# time.sleep(0.100)
# print('done')
# print(dfu.read_mem(i,16))
t2 = time.time()*1000
-
+ print()
print('time: %d ms' %(t2 - t1))
print('verifying...')
+ progress = 0
for start,end in ih.segments():
for i in range(start, end, chunk):
data1 = (dfu.read_mem(i,2048))
data2 = ih.tobinarray(start=i,size = chunk)
- assert(data1 == data2)
+ total += chunk
+ progress = total/float(size)*100
+ sys.stdout.write('reading %.2f%% %08x - %08x ... \r' % (progress,i,i+page))
+ if (end-start) == chunk:
+ assert(data1 == data2)
+ print()
print('firmware readback verified.')
if args.detach:
dfu.detach()
@@ -706,19 +725,31 @@ def programmer_main():
parser.add_argument("--disable", action="store_true", help = 'Disable the Solo bootloader. Cannot be undone. No future updates can be applied.')
parser.add_argument("--detach", action="store_true", help = 'Detach from ST DFU and boot from main flash. Must be in DFU mode.')
parser.add_argument("--dfu-serial", default='', help = 'Specify a serial number for a specific DFU device to connect to.')
+ parser.add_argument("--use-dfu", action="store_true", help = 'Boot to ST-DFU before continuing.')
args = parser.parse_args()
fw = args.__dict__['[firmware]']
p = SoloClient()
+
+
+
try:
p.find_device()
+ if args.use_dfu:
+ print('entering dfu..')
+ try:
+ attempt_to_boot_bootloader(p)
+ p.enter_st_dfu()
+ except RuntimeError:
+ # already in DFU mode?
+ pass
except RuntimeError:
+ print('No Solo device detected.')
if fw or args.detach:
use_dfu(args)
sys.exit(0)
else:
- print('No Solo device detected.')
sys.exit(1)
if args.detach:
@@ -732,6 +763,7 @@ def programmer_main():
p.set_reboot(False)
if args.enter_bootloader:
+ print('Attempting to boot into bootloader mode...')
attempt_to_boot_bootloader(p)
sys.exit(0)
@@ -758,10 +790,12 @@ def programmer_main():
p.version()
except CtapError as e:
if e.code == CtapError.ERR.INVALID_COMMAND:
+ print('Bootloader not active. Attempting to boot into bootloader mode...')
attempt_to_boot_bootloader(p)
else:
raise(e)
except ApduError:
+ print('Bootloader not active. Attempting to boot into bootloader mode...')
attempt_to_boot_bootloader(p)
if args.reset_only: