============
ARM CPU Core
============

- Probably some type of ARM7
- Supports 32-bit ARM and 16-bit Thumb
- Might have a flash icache, not sure yet
- Not Thumb-2
- No cp15 (not sure how to control cache, get CPU ID)
- Not fast. About 2 MIPS running Thumb NOPs from DRAM.
- Has blx
- Has muls, mla, umull


Vector Table
------------

The area from 10000 - 102ff is set aside by the bootloader protocol for
interrupt vectors.

The hardware IVT is at address 0, covered by a 0x400 byte SRAM mapping by the
standard firmawre.

00: reset
04: ARM undefined instruction
08: ARM software interrupt         -- hangs (infinite loop)
0c: ARM prefetch abort exception   -- unused normally; we use this to implement %hook
10: ARM data abort exception       -- unused normally

18: hardware interrupt
     - SCSI / inter-processor comms

1c: FIQ hardware interrupt
     - Eject button?


Not sure if these are actually vectors or they just look similar:

40: Very complex (IPC?) message handler?
46: SCSI command handler?


Cryptography
------------

Annoyingly but not necessarily suprisingly, I'm hitting cryptography already
just in trying to understand the boot process. It's likely someone thought the
firmware should include a chain of trust for something related to video DRM or
possibly protecting intellectual property. It's annoying, and hopefully not
very thorough.

 - Uses 128-bit blocks. It's likely AES, but I don't really know yet

 - A block cipher core lives at [4063000]

 - There also appears to be transparent decryption for code memory. The
   bootloader includes one encrypted region at 000:fff, but the application
   firmware includes many more. Unused areas at the end of these blocks
   exhibit a characteristic repeating 16-byte pattern, which seems like the
   transparent cipher would be using ECB mode. Every individually encrypted
   code block seems to use a different key. The blocks in the main app are
   prefixed with a NOP sled and an MSR instruction which enables supervisor
   mode.

   This hardware probably has a poweron default to be active for memory
   at 000:fff, hence the encrypted IVT in the bootloader.


Hardware Memory Map
-------------------

* 00000000 - 001fffff      Flash (2MB)
  00000000 - 0000ffff      Write-protected bootloader flash (64kB)
  00010000 - 001e1fff      Loadable firmware image (1863 kB)
  001e2000 - 001fffff      Runtime storage and bootloader info (120 kB)

* 01c08000 - 02007fff      DRAM (4MB)
  01c08000 - 01ffffff      Shared DRAM
  02000000 - 02001fff      System DRAM (32 kB)

  04000000 - 043fffff      Memory mapped I/O


DRAM
----

I'm not yet sure where DRAM is usually mapped in the ARM address space. It's
usually accessed indirectly, via ref[20]. I've been referring to this space a
lot as '8051' address space because I saw the ARM copy the 8051 firmware image
there, but now that I've figured out how to dump it using undocumented SCSI
command 3C02, the whole DRAM area can be examined.

When dumping from the bootloader after cold boot, the characteristic noisy
checkerboard patterns of DRAM's wiring show up in the uninitialized areas.

       0 -      fff     [BOOT] uninitialized
                        [TS01] Array with 8-byte records
    1000 -     2fff     8051 program memory
    3000 -   1f7fff     [BOOT] uninitialized

  1f8000 -   3fffff     gobs of loosely structured data!
                          It could be more code data here, but my hunch is
                          that this is a ring buffer of command data
                          structures. Many of the repeating blocks look like
                          they could be arguments, and I feel like a
                          sufficiently awesome tool could convert this into a
                          log of recent transfers.

All signs point to the DRAM region being 4MB in size. This is the size of the
"cache memory" advertised for the device, and it looks like at 400000 and
after, the same 2MB of memory mirrors over and over.

Most of this memory seems to be dynamically allocated, so it often has useful
tidbits in it but the overall structure varies wildly from run to run.


Memory Mapped I/O
-----------------

This processor has a substantial zoo of memory mapped peripherals.
Very rough notes, may be wildly wrong.

4000000     Low level system control, interrupt enables

            4000000   uint32      Flags
                                     10    Global interrupt enable?

4001000     Reset control

4002000     GPIO, System Timer

            4002004   uint32      Flags    Read only
                                    800
                                     40
                                     10    Eject button, 1=open, 0=pressed
                                      8
                                      4    Tray sensor nearest to edge, 1=open 0=closed
                                             - Both tray sensors affect other registers,
                                               probably because they have hardware power supply
                                               interlocks to prevent the laser from firing when
                                               open. But only the outermost switch is directly
                                               readable via GPIO.
                                      2

                                  NOTE: This may not be generated directly by hardware, this
                                        may be the result of some other software or SoC process.
                                        When pressing the tray button, reg [4002084] changes
                                        80ms ahead of this one.

            4002028   uint32      Interrupt flags?
            400202c   uint32      Interrupt vector pointer?

            4002058   uint32      "App select", affects bootloader in many ways
                                  Fully read/write. May be intended for firmware use,
                                  perhaps this survives some forms of reset.

            4002064   uint32      Used by ISR 1c

            4002078   uint32      System tick counter, 512*1024 Hz

            4002084   uint32      Flags    Read only
                                      1
                                      2
                                      4
                                      8
                                    400    Also changing frequently
                                    800
                                   1000
                                 100000
                                2000000
                                8000000
                               10000000    Eject button
                               20000000    Tray sensor

                                  NOTE: Possibly a lower-level version of [4002004]

            4002088   uint32      flags    Outputs, a few bits not implemented
                                           wwww_00ww_wwww_wwww_wwww_wwww_wwww_0www
                                              0    3    0    3    0    3    0    3
                                                 LED

                                      1
                                      2    Solenoid

                                    100
                                    200    Solenoid

                                  10000
                                  20000

                                1000000    \  LED enable,   1=off, 0=on
                                2000000    /  LED control,  1=off, 0=on

            4002108   uint32              - Clear upper half (ldrh/str) to ack interrupt

            4002120

4003000
4004000
4004800

4010000     8051 Co-processor

            4010000   uint8       write FIFO
            4010008   uint32      Write-1-to-clear?
            4010009   uint8

4011000     Coprocessor and encryption memory mapping control
            Possibly inter-processor message notification

            4011000   uint32      Flags
                                     80    Set at the top of bootloader app_main

            4011008   uint32      Low 10 bits (count?) set to 1 in app_main

            401100c   uint32      Flags
                                      4    Set after polling [4011088]
                                      2    Set / op / clear in app_main

            4011010   uint8       Flags
                                      8    Wait for 0 (second)
                                      4    Wait for 1 (first)

            4011040   uint32      Flags
                                      1    Set while booting app firmware, in bootloader

            4011050   uint32      Flags
                                      1    Cleared after polling [4011088]

            - Transparent 128-bit code decryption, possibly AES-ECB mode

            4011064   uint32      Flags
                                      4    Transparent encryption enabled
            4011068   uint32      First address of transparent encryption region
            401106c   uint32      Last address in transparent encryption region

            - Status?

            4011088   uint32      Flags
                                      1    Poll for bit=1 after setting [4011000] |= 80

            - Movable memory regions

            This register runs the show:

            4011f04   uint32      Flags
                                    800    Set by boot0
                                    400    Enable flag
                                    200    Enable flag, set by boot0
                                    100    Enable flag, set by boot0

            Then we have these pairs of first-address / last-address registers.
            Just the ones that are definitely addresses:

                4011f08 / 4011f0c    First 4k of address space
                4011f10 / 4011f14    Function in app flash, cfbe4
                                     Also seen at 400000:400bff:400c00:400fff for mapped memcpys
                                     This seems to be an SRAM page used by the firmware to accelerate
                                     specific functions in flash by copying them to RAM.
                4011f20 / 4011f24    All of flash
                4011f50 / 4011f54    In the firmware startup code, 1ec00:1efff
                4011f58 / 4011f5c    Much later in flash, 169220:16961f
                4011f60 / 4011f64    Bootloader, 2800:2fff

            Mappings have a fixed source size, after which they repeat.
            Mappings work for any address below 800000 (First 8MB). So,
            these mappings it seems can't overwrite DRAM or MMIO space, but
            they can be in the address space accessible to DMA.

4020000
4020f00     Related to RAM region 2000000, set up during boot0

            4020f04   uint32      Flags
                                    800    Set by boot0

4030000     RAM region setup / DMA engine

            40300e8   uint32      Mapped pointer for SCSI device-to-host transfer
                                  (DMA source address)

            40300f4   uint32      =   1_ffff  during boot0 (SRAM size?)
            4030f04   uint32      =        2  during boot0, then =8802 at end of boot0
            4030f20   uint32      DRAM mapping begin
            4030f24   uint32      DRAM mapping end
            4030f40   uint32      = 200_0000  during boot0
            4030f44   uint32      = 200_19ff  during boot0

4031000     - Vector 1019c

            4031000   uint32      =4000_0800  during boot0
            4031004   uint32      =        8  during boot0

4031140
4031180
4032040
4033000     - Vector 1019c
4033100
4033200
4033300

4040040     Related to commands (SCSI?) received via vector 10046
4041000
4042000     - SCSI response pipe

            4040064   uint32      USB Interrupt Flags, write-to-clear
                                  checking for mask 0x3008

                                    1000    SETUP completed
                                    2000    IN completed

            4040078   uint32      USB event interrupt

                                    80000   OUT completed
                                       xx   endpoint?

            40400a5   uint8       Bits 1F cleared prior to PIO transfer
            40400a8   uint32      Byte FIFO register for PIO (non-DMA)
                                  Used by cmd03 Request Sense and some others.
            40400d4   uint32      Byte in bits 15:8, set prior to transfer. PIO: 0x01__

            4042154   uint32      Pre-initiation write
                                     DMA: size, after pointer written to [40300e8]
                                     PIO: Before other MMIO writes, &= 1

                                   This one seems more protocol-related than to control
                                   the DMA/PIO hardware. It's a weird address (a header in
                                   a buffer somewhere) and the ordering is strange. In PIO,
                                   this is written prior to all error handling.

4050000

4062000
4063000     Crypto coprocessor. Seems to have a few different modes it can operate in.
            128-bit block size, probably AES. Used by bootloader and app firmware for
            hashing.

            4063000   uint32      Flags
                                      1   Set before op (after 4063090:1)
            4063004   uint8       Flags
                                      2   Operation complete
            4063008   uint32      Flags
                                      4   Cleared before op
                                      2   Cleared before op

            4063010   uint128     Zero'ed before a hashing operation
                                  Conditionally zeroed by boot2
            4063020   uint128     Key loaded from 10ff0 by boot2
                                  Blocks loaded from regions we're checking.
                                  Simpler checker algo in cmd3B uses a key from 1ff000.

            4063038   uint32      Result (boot2 expected a1b9d358)
            406303c   uint32      Result (boot2 expected 13201959)

            4063084   uint32      Flags
                                      4   Set during boot2
            4063088   uint32      boot2 init: reg = 50 + (reg & ~70)
            4063090   uint32      Flags
                                      1   Set before op, after op

4070200
4070300
4070400
4070500

4081e00
4081f00
4082d00

40b0040

40d0200

4100000     Debug trace interface

            (Used by logging func f6024, verified non-essential to operation)

            4010000   uint8       FIFO, byte output
            4010008   uint32      Flags? (read before writing)
            4010009   uint8       Acknowledge? (read after writing)

4100701

41f0000     8051 XDATA memory interface

            This looks like it might be an in-package serial bus.

            The registers at 41f4_ follow a protocol where [41f5c0c] is used for
            flow control and [41f5c08] performs delayed reads. This is probably how
            they cross clock domains.

            41f4d50   uint8       Write to firmware memory
            41f4d51   uint8       Flags
                                      1   Force firmware address to 0 when asserted. Strobe high to reset address.
                                      2   Disable firmware autoincrement?
                                      4   0 during upload, 1 during normal operation (just before [41f4dcc]=0)

            41f4d52   uint8       Read from firmware memory

            41f4d91   uint8       Firmware boot status

            41f4dcc   uint8       Flags
                                      8   Processor held in reset? (Set during firmware install)

            Bus control for registers in 41f4_

            41f5c08   uint8       Read data
            41f5c0c   uint8       Flags
                                      8   Busy pre-result, wait for 0
                                      4   Busy pre-result, wait for 0
                                      1   Busy post-result, wait for 1

            41f5c44   uint8

4200000
4201000

4204000

4206000     Stepper motor controller

            This seems to be a fairly high-level hardware motor controller,
            probably with a way to set up acceleration rates and such. The
            following commands, with the right initialization, on each
            issuance will cause the pickup sled to move about a centimeter
            away from the spindle motor.

            Possibly an auto-reset on error? After leaving in 500mA state for
            some seconds, the same commands will not produce motor movement.
            These commands seem fairly high-level, like they're executing
            something that's been set up elsewhere.

                %wr 4206000 a10200
                %wr 4206010 c646

                %wr 4206000 910200    <- Current up to 500mA, motor moves all at once
                %wr 4206010 c600

                %wr 4206000 910200    <- Drops current from ~500mA to 270mA

            ----

            4206000   uint32      Flags + number in [23c, b60]

                                  800000
                                  400000
                                  200000
                                  100000
                                   10000

            4206004

            4206010   uint32      number in [0, ffff]
            4206014   uint32      number in [0, f500]
            4206018   uint32      number in [17, b16e]
            420601c   uint32      number in [0, 3d00]
            4206020   uint32      number in [0, 3000]
            4206024   uint32      number in [0, 7dbe]

            4206080
            4206084
            420608c

            420610c   uint32      508
            4206114
            4206204
            4206208

            4206280
            4206284

            42062a8
            42062ac

            4206300

            4206308
            420630c
            4206310
            4206314
            4206318

            420640c

420c000

