From 5c6d20890bdc952af0886595f1061699b342ec8d Mon Sep 17 00:00:00 2001 From: Bottersnike Date: Mon, 5 Aug 2024 01:00:54 +0100 Subject: [PATCH] DRM docs --- docs/DRM.md | 123 ++++++++++++++++++++++++++++++++++++++++++++ docs/Development.md | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 docs/DRM.md diff --git a/docs/DRM.md b/docs/DRM.md new file mode 100644 index 0000000..0a1cebe --- /dev/null +++ b/docs/DRM.md @@ -0,0 +1,123 @@ +# DRM +DJ DAO implemented two forms of DRM within the TASOLLER firmware. + +1. The bootloader on the Host and LED microcontrollers make slight alterations to the uploaded binary +2. The stock Host firmware reads 4 bytes of memory from the bootloader firmware to validate it + +## Host DRM +### Magic number +Flash address `100FF8` (`LDROM+FF8`) must contain the value `5555A320`. The stock bootloader contains the following code to write this magic value: + +```cpp +#define BOOTLOADER_MAGIC ((uint32_t)0x5555A320) +#define BOOTLOADER_MAGIC_ADDR ((uint32_t)0x100FF8) + +void main(void) { + SYS_UnlockReg(); + SYS_Init(); + + FMC_Open(); + g_apromSize = GetApromSize(); + GetDataFlashInfo(&g_dataFlashAddr, &g_dataFlashSize); + + uint32_t u32FMCCheck; + FMC_Write(BOOTLOADER_MAGIC_ADDR, BOOTLOADER_MAGIC); + FMC_Read(BOOTLOADER_MAGIC_ADDR, &u32FMCCheck); + if (u32FMCCheck != BOOTLOADER_MAGIC) { + FMC_Erase_User(BOOTLOADER_MAGIC_ADDR); + FMC_Write(BOOTLOADER_MAGIC_ADDR, BOOTLOADER_MAGIC); + } + + // ... +} +``` + +Stock APROM firmware then contains +```cpp +void SYS_Bootloader_Check(void) { + FMC_Open(); + while (FMC_Read(BOOTLOADER_MAGIC_ADDR) != BOOTLOADER_MAGIC) + ; + FMC_Close(); +} + +void main(void) { + SYS_UnlockReg(); + SYS_Init(); + SYS_Bootloader_Check(); + + // ... +} +``` + +In our custom APROM, defining `ENABLE_BOOTLOADER_CHECK` (`tasoller.h`) will perform this check. Our custom bootloader (not included in this repository) uses a custom scatter file to include this magic value, safely asserting that the code does not overflow into these bytes. + +### Firmware modification +The following bytes in the uploaded firmware are modified before writing them to flash: + +| Offset | XOR value | +| ------ | --------- | +| `C0` | `FF` | +| `C1` | `FF` | +| `C2` | `FF` | +| `CC` | `2F` | + +These values are specifically chosen as the end of the vector table. The code at this offset is part of ARMC5's initialisation code, with `__main` being the entrypoint jumped to after register initialisation. + +```asm +__main: +_main_stk: + LDR R0, =__initial_sp ; Offset C0~C1 + MOV SP, R0 ; Offset C2~C3 + +_main_scatterload + BL __scatterload_rt2 ; Offset C4~C7 + +__main_after_scatterload: +_main_clock: +_main_cpp_init: +_main_init: + LDR R0, =main ; Offset C8~C9 + BR R0 ; Offset CA~CB + + DCD main ; Offset CC~CF, auto-generated by =main +``` + +Note that our custom firmware is compiled using GCC rather than ARMC5. Our linkerscript is not configured to place any initialisation code after the vectors, and as such this protection mechanism would be likely to cause random crashes rather than a complete inability to execute the firmware. + +Rather than implement this as a post-processing step after compiling firmware, our linkerscript is configured to pad C0~CF with nulls. + +## LED DRM +### Magic number +Flash address `1011F8` (`LDROM+11F8`) must contain the value `5555AAAA`. The stock bootloader contains the following code to write this magic value: + +```cpp +#define BOOTLOADER_MAGIC ((uint32_t)0x5555AAAA) +#define BOOTLOADER_MAGIC_ADDR ((uint32_t)0x1011F8) + +void main(void) { + SYS_UnlockReg(); + SYS_Init(); + + FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk; + g_apromSize = GetApromSize(); + GetDataFlashInfo(&g_dataFlashAddr, &g_dataFlashSize); + + FMC_Write_User(BOOTLOADER_MAGIC_ADDR, BOOTLOADER_MAGIC) + + // ... +} +``` + +No corresponding check appears to be implemented in the LED APROM firmware, however. + +### Firmware modification +The following bytes in the uploaded firmware are modified before writing them to flash: + +| Offset | XOR value | +| ------ | --------- | +| `C0` | `FF` | +| `C1` | `FF` | +| `C2` | `FF` | + +The disassembly at these offsets is the same as with the host APROM. Likewise, we opt to bypass this protection by inserting null bytes. diff --git a/docs/Development.md b/docs/Development.md index 7d1c0f2..5a2aacf 100644 --- a/docs/Development.md +++ b/docs/Development.md @@ -74,6 +74,6 @@ xHSETT can be used to directly control the USB device, such as sending SUSPEND s ## Airs See https://www.shinkoh-elecs.jp/wp-content/uploads/2024/05/C_KB1281_1581_24A.pdf -The loop of wire between the two wings is for connecting emitter pin 3 to detector pin 1. +The loop of wire between the two towers is for connecting emitter pin 3 to detector pin 1. The right bottom is an emitter, and then it alternates up from there.