diff --git a/Makefile.common b/Makefile.common index d6a695f..7fc3949 100644 --- a/Makefile.common +++ b/Makefile.common @@ -28,13 +28,13 @@ build/main.o: build/section_data_patch.bin build/section_isr.bin --change-section-address .vectors=0xffe0 \ --set-start 0x8000 build/section_data_patch.bin $@ -build/enter_bsl.o: shellcode/enter_bsl.c +build/fn_hooks.o: shellcode/fn_hooks.c @echo "Compiling shellcode..." $(QUIET)msp430-gcc -Os -mmcu=msp430f5510 -c $< -o $@ # The main.o is an relocatable elf which we convert to an actual elf # for IDA to like it. Also link in our own objects -build/main.elf: build/main.o build/enter_bsl.o +build/main.elf: build/main.o build/fn_hooks.o @echo "Create main.elf..." $(QUIET)msp430-gcc -O0 -mmcu=msp430f5510 \ -Wl,--section-start=.text=0x8000 \ diff --git a/patch.py b/patch.py index eb5b121..8438599 100644 --- a/patch.py +++ b/patch.py @@ -98,15 +98,17 @@ def original_fw_valid(path): m.update(orig.read()) return m.hexdigest() == orig_fw_md5 -def write_jump_to_bsl(): - '''Make fn + F1 + F4 jump to BSL (firmware update mode)''' - # Replace mov instruction with a call to our own code for checking - # which F keys are currently pressed. If fn + F1 + F4 is pressed - # jump to 0x1000 (BSL entry addr). +def write_handle_fn_key_handler_hooks(): + '''Add C hooks for doing stuff when fn + key(s) is pressed''' - # bytecode for asm 'call 0xa780; nop' + # bytecode for asm 'calla 0xa780; nop' (on_fn_key_down) dest.seek(0x83a) - dest.write('b01280a70343'.decode('hex')) + dest.write('b01380a70343'.decode('hex')) + + # calla #0xa8f0 (on_fn_key_up, INCREDIHACK: offest depends on size + # of on_fn_key_down since this is linked after) + dest.seek(0xa98) + dest.write('b01302a8'.decode('hex')) if __name__ == '__main__': # Remap caps to ctrl @@ -141,4 +143,4 @@ if __name__ == '__main__': for text in usb_hid_strings: write_usb_string(dest, text) - write_jump_to_bsl() + write_handle_fn_key_handler_hooks() diff --git a/shellcode/enter_bsl.c b/shellcode/enter_bsl.c deleted file mode 100644 index 0290627..0000000 --- a/shellcode/enter_bsl.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include - -// Declare pointers to variables we access in Novatouch fw -unsigned char* const repeat_flags = (unsigned char*)0x2404; -unsigned char* const repeat_rate = (unsigned char*)0x252f; -unsigned char* const num_for_7x_c1 = (unsigned char*)0x2530; - -void check_bsl_enter() { - // We just replaced this copy to get here, perform it here instead - // (although it seems to be redundant because it is never actually - // read) - *num_for_7x_c1 = *repeat_rate; - - // Enter BSL if fn + f1 + f4 is pressed - if ((*repeat_flags & 0x9) == 0x09) { - __dint(); - // Maybe need to slow down clock to 8 MHz also, not sure what - // is configured by Novatouch fw - USBKEYPID = 0x9628; - USBCNF &= ~PUR_EN; - USBPWRCTL &= ~VBOFFIE; - USBKEYPID = 0x9600; - ((void (*)())0x1000)(); - } -} diff --git a/shellcode/fn_hooks.c b/shellcode/fn_hooks.c new file mode 100644 index 0000000..6d1343f --- /dev/null +++ b/shellcode/fn_hooks.c @@ -0,0 +1,90 @@ +#include + +// Declare pointers to variables we access in Novatouch fw +unsigned char* const repeat_flags = (unsigned char*)0x2404; +unsigned char* const repeat_rate = (unsigned char*)0x252f; +unsigned char* const num_for_7x_c1 = (unsigned char*)0x2530; +unsigned char* const current_keycode = (unsigned char*)0x2400; + +// Defines for internal scancodes (corresponding to scancode_table_1). Find out +// missing ones by using table at bottom of README.org. +#define KEY_H 0x24 +#define KEY_J 0x25 +#define KEY_K 0x26 +#define KEY_L 0x27 +#define KEY_UP 0x53 +#define KEY_DOWN 0x54 +#define KEY_LEFT 0x4f +#define KEY_RIGHT 0x59 + +// Seems like original FW is compiled with IAR compiler and has different +// calling convention than mspgcc. Use macro to call functions and get correct +// parameter passing. +#define QUEUE_KEY(code) asm("mov.b %0, r12\n" \ + "calla #0x91a2" : : "i"(code)) + +#define UNQUEUE_KEY(code) asm("mov.b %0, r12\n" \ + "calla #0x9086" : : "i"(code)) + +// To be called when key is pressed and fn is also pressed +void on_fn_key_down() { + // We just replaced this copy to get here, perform it here instead + // (although it seems to be redundant because it is never actually + // read) + *num_for_7x_c1 = *repeat_rate; + + // Enter BSL if fn + f1 + f4 is pressed + if ((*repeat_flags & 0x9) == 0x09) { + __dint(); + // Maybe need to slow down clock to 8 MHz also, not sure what + // is configured by Novatouch fw + USBKEYPID = 0x9628; + USBCNF &= ~PUR_EN; + USBPWRCTL &= ~VBOFFIE; + USBKEYPID = 0x9600; + ((void (*)())0x1000)(); + } + + // Extra bindings for fn + key + switch (*current_keycode) { + case KEY_H: + QUEUE_KEY(KEY_LEFT); + break; + case KEY_J: + QUEUE_KEY(KEY_DOWN); + break; + case KEY_K: + QUEUE_KEY(KEY_UP); + break; + case KEY_L: + QUEUE_KEY(KEY_RIGHT); + break; + } +} + +// To be called when key is released and fn is also down +void on_fn_key_up() { + + // Extra bindings for fn + key + switch (*current_keycode) { + case KEY_H: + UNQUEUE_KEY(KEY_LEFT); + break; + case KEY_J: + UNQUEUE_KEY(KEY_DOWN); + break; + case KEY_K: + UNQUEUE_KEY(KEY_UP); + break; + case KEY_L: + UNQUEUE_KEY(KEY_RIGHT); + break; + default: + // Moar ugly hacks! To hook this function we replaced the + // original call to unqueue key, setup original argument and + // do the call. + asm("mov.b &0x2400, r12\n" + "calla #0x9086"); + break; + } +}