option to disable solo bootloader
This commit is contained in:
parent
b9ebde22e5
commit
beedc24839
@ -24,6 +24,7 @@ typedef enum
|
|||||||
BootVersion = 0x44,
|
BootVersion = 0x44,
|
||||||
BootReboot = 0x45,
|
BootReboot = 0x45,
|
||||||
BootBootloader = 0x46,
|
BootBootloader = 0x46,
|
||||||
|
BootDisable = 0x47,
|
||||||
} BootOperation;
|
} BootOperation;
|
||||||
|
|
||||||
|
|
||||||
@ -46,12 +47,30 @@ static void erase_application()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LAST_ADDR (APPLICATION_END_ADDR-2048 + 8)
|
||||||
|
#define LAST_PAGE (APPLICATION_END_PAGE-1)
|
||||||
|
static void disable_bootloader()
|
||||||
|
{
|
||||||
|
uint8_t page[PAGE_SIZE];
|
||||||
|
memmove(page, (uint8_t*)LAST_ADDR, PAGE_SIZE);
|
||||||
|
memset(page+PAGE_SIZE -4, 0, 4);
|
||||||
|
flash_erase_page(LAST_PAGE);
|
||||||
|
flash_write(LAST_ADDR, page, PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
static void authorize_application()
|
static void authorize_application()
|
||||||
{
|
{
|
||||||
uint32_t zero = 0;
|
// uint32_t zero = 0;
|
||||||
uint32_t * ptr;
|
// uint32_t * ptr;
|
||||||
ptr = (uint32_t *)AUTH_WORD_ADDR;
|
// ptr = (uint32_t *)AUTH_WORD_ADDR;
|
||||||
flash_write((uint32_t)ptr, (uint8_t *)&zero, 4);
|
// flash_write((uint32_t)ptr, (uint8_t *)&zero, 4);
|
||||||
|
uint8_t page[PAGE_SIZE];
|
||||||
|
if (is_authorized_to_boot())
|
||||||
|
return;
|
||||||
|
memmove(page, (uint8_t*)LAST_ADDR, PAGE_SIZE);
|
||||||
|
memset(page+PAGE_SIZE -8, 0, 4);
|
||||||
|
flash_erase_page(LAST_PAGE);
|
||||||
|
flash_write(LAST_ADDR, page, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_authorized_to_boot()
|
int is_authorized_to_boot()
|
||||||
@ -60,6 +79,12 @@ int is_authorized_to_boot()
|
|||||||
return *auth == 0;
|
return *auth == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_bootloader_disabled()
|
||||||
|
{
|
||||||
|
uint32_t * auth = (uint32_t *)(AUTH_WORD_ADDR+4);
|
||||||
|
return *auth == 0;
|
||||||
|
}
|
||||||
|
|
||||||
int bootloader_bridge(int klen, uint8_t * keyh)
|
int bootloader_bridge(int klen, uint8_t * keyh)
|
||||||
{
|
{
|
||||||
static int has_erased = 0;
|
static int has_erased = 0;
|
||||||
@ -150,7 +175,22 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
|||||||
break;
|
break;
|
||||||
case BootReboot:
|
case BootReboot:
|
||||||
printf1(TAG_BOOT, "BootReboot.\r\n");
|
printf1(TAG_BOOT, "BootReboot.\r\n");
|
||||||
device_reboot();
|
REBOOT_FLAG = 1;
|
||||||
|
break;
|
||||||
|
case BootDisable:
|
||||||
|
printf1(TAG_BOOT, "BootDisable %08lx.\r\n", *(uint32_t *)(AUTH_WORD_ADDR+4));
|
||||||
|
if (req->payload[0] == 0xcd && req->payload[1] == 0xde
|
||||||
|
&& req->payload[2] == 0xba && req->payload[3] == 0xaa)
|
||||||
|
{
|
||||||
|
disable_bootloader();
|
||||||
|
version = 0;
|
||||||
|
u2f_response_writeback(&version,1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
version = CTAP2_ERR_OPERATION_DENIED;
|
||||||
|
u2f_response_writeback(&version,1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef SOLO_HACKER
|
#ifdef SOLO_HACKER
|
||||||
case BootBootloader:
|
case BootBootloader:
|
||||||
|
@ -95,22 +95,26 @@ int main(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef SOLO_HACKER
|
#ifdef SOLO_HACKER
|
||||||
|
if (!is_bootloader_disabled())
|
||||||
|
{
|
||||||
stboot_time = millis();
|
stboot_time = millis();
|
||||||
if ( RCC->CSR & (1<<29) )// check if there was independent watchdog reset
|
if ( RCC->CSR & (1<<29) )// check if there was independent watchdog reset
|
||||||
{
|
{
|
||||||
RCC->CSR |= (1<<23); // clear reset flags
|
RCC->CSR |= (1<<23); // clear reset flags
|
||||||
goto start_bootloader;
|
goto start_bootloader;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (boot && is_authorized_to_boot())
|
if (is_authorized_to_boot() && (boot || is_bootloader_disabled()))
|
||||||
{
|
{
|
||||||
BOOT_boot();
|
BOOT_boot();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf1(TAG_RED,"Not authorized to boot\r\n");
|
printf1(TAG_RED,"Not authorized to boot (%08x == %08lx)\r\n", AUTH_WORD_ADDR, *(uint32_t*)AUTH_WORD_ADDR);
|
||||||
}
|
}
|
||||||
start_bootloader:
|
start_bootloader:
|
||||||
|
|
||||||
@ -156,7 +160,7 @@ int main(int argc, char * argv[])
|
|||||||
{
|
{
|
||||||
stboot_time = millis();
|
stboot_time = millis();
|
||||||
}
|
}
|
||||||
if ((millis() - stboot_time) > 2000)
|
if ((millis() - stboot_time) > 5000)
|
||||||
{
|
{
|
||||||
boot_st_bootloader();
|
boot_st_bootloader();
|
||||||
}
|
}
|
||||||
|
@ -25,4 +25,9 @@ first[AUTH_WORD_ADDR+1] = 0
|
|||||||
first[AUTH_WORD_ADDR+2] = 0
|
first[AUTH_WORD_ADDR+2] = 0
|
||||||
first[AUTH_WORD_ADDR+3] = 0
|
first[AUTH_WORD_ADDR+3] = 0
|
||||||
|
|
||||||
|
first[AUTH_WORD_ADDR+4] = 0xff
|
||||||
|
first[AUTH_WORD_ADDR+5] = 0xff
|
||||||
|
first[AUTH_WORD_ADDR+6] = 0xff
|
||||||
|
first[AUTH_WORD_ADDR+7] = 0xff
|
||||||
|
|
||||||
first.tofile(sys.argv[len(sys.argv)-1], format='hex')
|
first.tofile(sys.argv[len(sys.argv)-1], format='hex')
|
||||||
|
@ -170,7 +170,7 @@ void heartbeat()
|
|||||||
{
|
{
|
||||||
state = !state;
|
state = !state;
|
||||||
}
|
}
|
||||||
if (but) led_rgb((val*b));
|
if (but) led_rgb(((val * r)<<8) | ((val*b) << 16) | (val*g));
|
||||||
else
|
else
|
||||||
led_rgb(((val * g)<<8) | ((val*r) << 16) | (val*b));
|
led_rgb(((val * g)<<8) | ((val*r) << 16) | (val*b));
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,13 @@ static void flash_unlock()
|
|||||||
// Locks flash and turns off DFU
|
// Locks flash and turns off DFU
|
||||||
void flash_option_bytes_init(int boot_from_dfu)
|
void flash_option_bytes_init(int boot_from_dfu)
|
||||||
{
|
{
|
||||||
#if DEBUG_LEVEL
|
#ifndef FLASH_ROP
|
||||||
|
#define FLASH_ROP 0
|
||||||
|
#endif
|
||||||
|
#if FLASH_ROP == 0
|
||||||
uint32_t val = 0xfffff8aa;
|
uint32_t val = 0xfffff8aa;
|
||||||
|
#elif FLASH_ROP == 2
|
||||||
|
uint32_t val = 0xfffff8cc;
|
||||||
#else
|
#else
|
||||||
uint32_t val = 0xfffff8b9;
|
uint32_t val = 0xfffff8b9;
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,7 @@ class SoloBootloader:
|
|||||||
version = 0x44
|
version = 0x44
|
||||||
reboot = 0x45
|
reboot = 0x45
|
||||||
st_dfu = 0x46
|
st_dfu = 0x46
|
||||||
|
disable = 0x47
|
||||||
|
|
||||||
HIDCommandBoot = 0x50
|
HIDCommandBoot = 0x50
|
||||||
HIDCommandEnterBoot = 0x51
|
HIDCommandEnterBoot = 0x51
|
||||||
@ -136,21 +137,24 @@ class Programmer():
|
|||||||
self.send_data_hid(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11')
|
self.send_data_hid(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11')
|
||||||
self.send_data_hid(SoloBootloader.HIDCommandEnterBoot, '')
|
self.send_data_hid(SoloBootloader.HIDCommandEnterBoot, '')
|
||||||
|
|
||||||
|
def is_solo_bootloader(self,):
|
||||||
|
try:
|
||||||
|
p.version()
|
||||||
|
return True
|
||||||
|
except CtapError as e:
|
||||||
|
if e.code == CtapError.ERR.INVALID_COMMAND:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise (e)
|
||||||
|
return False
|
||||||
|
|
||||||
def enter_st_dfu(self,):
|
def enter_st_dfu(self,):
|
||||||
"""
|
"""
|
||||||
If solo is configured as solo hacker or something similar,
|
If solo is configured as solo hacker or something similar,
|
||||||
this command will tell the token to boot directly to the st DFU
|
this command will tell the token to boot directly to the st DFU
|
||||||
so it can be reprogrammed. Warning, you could brick your device.
|
so it can be reprogrammed. Warning, you could brick your device.
|
||||||
"""
|
"""
|
||||||
soloboot = False
|
soloboot = self.is_solo_bootloader()
|
||||||
try:
|
|
||||||
p.version()
|
|
||||||
soloboot = True
|
|
||||||
except CtapError as e:
|
|
||||||
if e.code == CtapError.ERR.INVALID_COMMAND:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
raise (e)
|
|
||||||
|
|
||||||
if soloboot or self.exchange == self.exchange_u2f:
|
if soloboot or self.exchange == self.exchange_u2f:
|
||||||
req = Programmer.format_request(SoloBootloader.st_dfu)
|
req = Programmer.format_request(SoloBootloader.st_dfu)
|
||||||
@ -158,6 +162,21 @@ class Programmer():
|
|||||||
else:
|
else:
|
||||||
self.send_only_hid(SoloBootloader.HIDCommandEnterSTBoot, '')
|
self.send_only_hid(SoloBootloader.HIDCommandEnterSTBoot, '')
|
||||||
|
|
||||||
|
def disable_solo_bootloader(self,):
|
||||||
|
"""
|
||||||
|
Disables the Solo bootloader. Only do this if you want to void the possibility
|
||||||
|
of any updates.
|
||||||
|
If you've started from a solo hacker, make you you've programmed a final/production build!
|
||||||
|
"""
|
||||||
|
ret = self.exchange(SoloBootloader.disable, 0, b'\xcd\xde\xba\xaa') # magic number
|
||||||
|
if ret[0] != CtapError.ERR.SUCCESS:
|
||||||
|
print('Failed to disable bootloader')
|
||||||
|
return False
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.exchange(SoloBootloader.reboot)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def program_file(self,name):
|
def program_file(self,name):
|
||||||
|
|
||||||
if name.lower().endswith('.json'):
|
if name.lower().endswith('.json'):
|
||||||
@ -246,6 +265,7 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument("--reboot", action="store_true", help = 'Tell bootloader to reboot.')
|
parser.add_argument("--reboot", action="store_true", help = 'Tell bootloader to reboot.')
|
||||||
parser.add_argument("--enter-bootloader", action="store_true", help = 'Don\'t write anything, try to enter bootloader. Typically only supported by Solo Hacker builds.')
|
parser.add_argument("--enter-bootloader", action="store_true", help = 'Don\'t write anything, try to enter bootloader. Typically only supported by Solo Hacker builds.')
|
||||||
parser.add_argument("--st-dfu", action="store_true", help = 'Don\'t write anything, try to enter ST DFU. Warning, you could brick your Solo if you overwrite everything. You should reprogram the option bytes just to be safe (boot to Solo bootloader first, then run this command).')
|
parser.add_argument("--st-dfu", action="store_true", help = 'Don\'t write anything, try to enter ST DFU. Warning, you could brick your Solo if you overwrite everything. You should reprogram the option bytes just to be safe (boot to Solo bootloader first, then run this command).')
|
||||||
|
parser.add_argument("--disable", action="store_true", help = 'Disable the Solo bootloader. Cannot be undone. No future updates can be applied.')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
print()
|
print()
|
||||||
|
|
||||||
@ -271,6 +291,10 @@ if __name__ == '__main__':
|
|||||||
p.enter_st_dfu()
|
p.enter_st_dfu()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
if args.disable:
|
||||||
|
p.disable_solo_bootloader()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print('version is ', p.version())
|
print('version is ', p.version())
|
||||||
except CtapError as e:
|
except CtapError as e:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user