Socionext GoPro GP1 Imaging Processor Research, SC2000a, M10v
Posted by Mark Kirschenbaum on
In my attempt to resurrect a bricked GoPro Camera, I've studied the bootup and update sequence of the Socionext GP1. This processor is a SC2000a with possibly some changes by GoPro. Socionext's internal name is M10v Milbeaut DSC Processor.
Cores
- Cortex M0 Supervisor running at 100Mhz
- Quad ARM Cortex-A7 Running at 600Mhz
- LPDDR Package on Package 1GB HERO6 or 2GB for HERO[7,8,MAX,9]
- RTOS running on three cores, Linux on one. AMP mode
Architecture of Cortex-A7
I've dumped the CPUIDs of the Cortex-A7 core to know what features are installed. GP1 Linux Loader / RTOS patch used to get this information.
Architecture= 9, read 0x410fc075The DAP Info can be seen at GP1 DAP Info.
midr = 0x410fc075
mpidr32 = 0x80000f00
DBGDIDR = 0x3515f005
3 Watch points, 5 Breakpoint Registers
Debug architecture 0x5 The processor implements ARMv7.1 Debug architecture.
The GoPro HERO6 Physical Page table or TTB.
GP1 Cortex-M0
The GP1 has a supervisor core that is tasked with thermal protection, calendar, internal PMIC, and initial bootup sequencing. It has access to most of the peripherals and is the first processor to bootup.
Not only does the supervisor code run on this Cortex-M0 processor, but also the bootrom, and the SD loader.
The base address is 0x3FFE0000 with a 0x400 vector offset for the SD loader and 0x300 for the supervisor code.
Debug Port
The GoPro HERO[6,7] has the following debug port pinout. Here is a GP1 OpenOCD(updated) config file for using Joe Fitz's Tigard adapter.
Unfortunately, the CM0 core does not have a coresight debugger. I was able to infer code execution via the stack and data on the shared memory location [0x31000000].
GoPro HERO6 & 7 Debug Connector Pinout (Hypoxic 10/5/2022) | ||||
Pin
|
Function | Function | Pin | |
PWR1 | GND | GND | PWR1 | |
1 | To QCA - TX? | 1v8 ref | 20 | |
2 |
to unpopulated Likely JTAG xrst |
Micronesia TX | 19 | |
3 | JTAG trst | Micronesia RX | 18 | |
4 | JTAG tms | To GP1 (boot, CM0 tx?) | 17 | |
5 | JTAG tdi | Linux RX | 16 | |
6 | JTAG tdo | Linux TX | 15 | |
7 | JTAG Tclk | RTOS RX | 14 | |
8 | GND | RTOS TX | 13 | |
9 | Micronesia Reset | Micronesia SWCLK | 12 | |
10 | PMIC Reset | Micronesia SWDIO | 11 | |
PWR2 | GND | GND | PWR2 |
External Security Processor "Micronesia"
Micronesia was the name given to the security enclave for the GoPro Fusion. They probably named it something different for the HERO[6-9] but that's what I continue to call this external supervisor. This is the device that ensures authentic batteries are connected and the PMIC is good before releasing the GP1 reset. This micro also ensures the connected USB-C accessories are authentic and works with the type-C PD controller.
On the GoPro HERO[8,MAX,9] it acts like the RTC and helps with the scheduled captures. It is a Microchip (Atmel) ATSAML22G18A-UUT WLSCP-49.
Micronesia does not ensure USB-C devices are authentic until the GP1 M0 signifies the GP1 is ready.
Here is my previous research of GoPro's Security Enclave & Breaking 128bit AES encrypted updates.
eMMC 8GB
I ended up wiring up the GoPro HERO6 eMMC to an SDCard adapter. Unfortunately there are no external resistors to tap into to do this in circuit.
The Samsung KLM8G1GEME-B041 (8GCE4R) eMMC has four physical partitions. Only the Boot0 and User partitions are being used by the GoPro. This document helped with the pinout.
Samsung's eMMC LayoutBoot 0 (4 KB) | Boot 1 (4 KB) |
RPMB (4KB) | |
User (~8GB) |
Boot 0 Region
This partition contains the bootup parameters and the CM0 supervisor code.
The boot block region 0 within the eMMC is comparable to the RS_MILBCM0-ES3.bin - found within Ricoh's Stubby codebase. This code runs in the GP1's Cortex-M0 coprocessor. GoPro's versions is slightly different than in the Ricoh's Stubby code base. It is sector00 of the GoPro DATA.bin update.
This code is located at 0x800 within the eMMC. However from 0 to 0x800 is the binary equivalents of "boot.par" & "sdram.par" The bootrom loads these up to know how to boot the device, early configure the sdram controller, and when it exists, configure the NAND interface. However, since the GoPro uses eMMC, it does not contain NAND parameters.
Boot 1 & RPMB Regions
Neither regions are used. The RPMB is a secure counter to prevent replay attacks.
User Region
The User partition contains all the remaining code and settings. It is broken down into four sections the Calibration data, Code space, FAT16 file system, and finally WARP hibernation data.
Calibration Space
The first partition is the calibration space. Below is an example of the calibration space for the GoPro HERO6. Each section has the <u32 CRC of data[0:len]><u32 len used><u32 revision> at the end of the memory space
DIRECTORY size_bytes=1024 version=0x20171190 num_entries=8 crc32=0x7d5e6701
0 : id=7 off=0x00000400 siz=0x00000400 sha=285b537 flg=0x00000001 GPDEBUG
1 : id=6 off=0x00000800 siz=0x00001000 sha=91f9c23 flg=0x00000001 NVDATA
2 : id=8 off=0x00001800 siz=0x00004000 sha=d3373ae flg=0x00000001 COMM
3 : id=1 off=0x00005800 siz=0x00000200 sha=91f9c23 flg=0x00000001 GYRO
4 : id=9 off=0x00005a00 siz=0x00002000 sha=91f9c23 flg=0x00000001 AUDIO
5 : id=2 off=0x00007a00 siz=0x00020000 sha=91f9c23 flg=0x00000001 VIGNETTE
6 : id=4 off=0x00027a00 siz=0x00000200 sha=91f9c23 flg=0x00000001 WB
7 : id=3 off=0x00027c00 siz=0x00200000 sha=91f9c23 flg=0x00000001 BPC
User Space
The GoPro update comes as a DATA.bin file. The various partitions have a volume id and type. Type determines whether the data gets loaded into the boot region (3) or flash (4).
Below the partition table for the GoPro HERO6 after an update. Notice the active partition indicator. This will toggle as the camera updates. I'm not sure what the option field is used for on the rootfs partition, but it is needed.
The GoPro HERO9 Black, HERO8 Black and HERO7 Black have the same partition table. The other GP1 based cameras have different tables, GoPro HERO6 & GoPro HERO8 MAX.
file_size 1d2000000 Partition Sector Sec Len Phy Addr Virt. Addr Data Len Option (Sectors) (Bytes) [00] 0x00000600 0x00020000 0 0x00000000 0x00000000 0x00000000 0x0 Active 0x00000000 0x00000000 0x00000000 0x0 [01] 0x00020600 0x00000800 0 0x00000000 0x00000000 0x00000000 0x0 Active 0x00000000 0x00000000 0x00000000 0x0 [02] 0x00020E00 0x00000400 1 0x45500000 0x45500000 0x0000df20 0x0 0x45500000 0x45500000 0x0000df20 0x0 Active [03] 0x00021200 0x00001000 0 0x00000000 0x00000000 0x00000000 0x0 Active 0x00000000 0x00000000 0x00000000 0x0 [04] 0x00022200 0x00100000 1 0xa0000000 0xa0000000 0x0344c980 0x0 0xa0000000 0xa0000000 0x0344c980 0x0 Active [05] 0x00122200 0x00010000 0 0x00000000 0x00000000 0x00000000 0x0 Active 0x00000000 0x00000000 0x00000000 0x0 [06] 0x00132200 0x00020000 0 0x00000000 0x00000000 0x00000000 0x0 Active 0x00000000 0x00000000 0x00000000 0x0 [07] 0x00152200 0x00010000 1 0x41000000 0x41000000 0x0039ec00 0x0 0x41000000 0x41000000 0x0039ec00 0x0 Active [08] 0x00162200 0x00080000 1 0x43000000 0x00000000 0x0647f000 0x1 0x43000000 0x00000000 0x0647f000 0x1 Active [09] 0x001E2200 0x00080000 1 0x00000000 0x00000000 0x00080400 0x0 0x00000000 0x00000000 0x00080400 0x0 Active [10] 0x00262200 0x00004000 0 0xa8bb4000 0x00000000 0x00000000 0x0 Active 0x00000000 0x00000000 0x00000000 0x0 [11] 0x00266200 0x00000400 1 0xa8400000 0x00000000 0x00000000 0x0 0xa8400000 0x00000000 0x00020000 0x0 Active [12] 0x00266600 0x00000400 1 0xa8400000 0x00000000 0x00000000 0x0 0xa8400000 0x00000000 0x00020000 0x0 Active [13] 0x00266A00 0x0000a000 1 0xa8420000 0x00000000 0x00000000 0x0 0xa8420000 0x00000000 0x00500000 0x0 Active [14] 0x00270A00 0x0000a000 1 0xa8420000 0x00000000 0x00000000 0x0 0xa8420000 0x00000000 0x00500000 0x0 Active [15] 0x0027AA00 0x00005800 0 0xaa412200 0x00000000 0x00000000 0x0 Active 0x00000000 0x00000000 0x00000000 0x0 found 15 partitions
Code to extract the DATA.bin is located in our Github Repository.
Partition | load address | Use |
0 | CM0 | Monitor code |
1 | runtime | Calibration (entry 0 in partition table) |
2 | 0x45500000 | Bootstrap |
4 | 0xA0000000 |
RTOS |
7 | 0x41000000 |
Stubby (linux bootloader) |
8 | 0x43000000 |
Linux rootfs |
9 |
W5HD - Warp Hibernation? |
|
10 | 0xa8bb4000 |
User Preferences [0x000000] |
11 | 0xa8400000 | Hibernation |
12 | 0xa8400000 | Unknown data, assuming dsp |
13 | 0xa8420000 | Unknown data-similar, assuming dsp |
14 | 0xa8420000 | empty |
15 | 0xaa412200 | ceva_flcor_main |
MBR/ Fat File System
For persistent Linux and RTOS data, there are several mapped drives that house this continuously overwritten data. Located at the end of the above code space I could not locate an explicit a pointer to this region but it maybe hardcoded or calculated at the end of the above code space. This is beneficial as a reburn should not touch these locations.
Partition table located at 0x0027AA00 + 0x00b00000 = 0x50040000
- num = 4
- partition 0 type=4, LBA=0x280300, size=0x100000 [0x50060000]
- partition 1 type=4, LBA=0x380300, size=0x100000 [0x70060000]
- partition 2 type=4, LBA=0x480300, size=0x200000 [0x90060000]
- partition 3 type=4, LBA=0x680300, size=0x200000 [0xD0060000]
- partition 4 type=0, LBA=0x0, size=0x0
- partition 5 type=0, LBA=0x0, size=0x0
- partition 6 type=0, LBA=0x0, size=0x0
- partition 7 type=0, LBA=0x0, size=0x0
Partitions physical address (Drive letters/ mount points TBD)
RTOS: J, K, L
Linux: fuse_a, fuse_b
Warp Hibernation
Not going to explore this at this time.
Boot Process
The purpose of this research is to fix bricked cameras and to eventually load our own firmware on the GP1. Before we can safely create our own, we must understand their specialized method of updating and booting up the device.
Hardwiring to the UART(s)
Normal initial power up (Coldboot)
- BootROM at 0x0, reads the eMMC and loads up boot.par, sdram.par binary blobs from boot0 into the M0.
- Using those parameters, the bootrom loads up the Cortex M0 CM0 supervisor code from eMMC bootblock 0 and vectors to this code at 0x3FFE0300.
- The CM0 supervisor initializes the LPDDR and loads up the partitions into SDRAM using the partition table at eMMC user block [0..n].
- The CM0 writes the reset branch code at 0x0100_0000 and the address of the bootstrap code 0x0100_0020
- It then releases the cortex-a7 reset. All four cores starts running the bootstrap code.
- Core 3 (zero based) sets up the shared memory, GPV, GPIO, clocks, interrupts, etc.
- It then releases the other cores by setting a trampoline addresses and flags.
- The three cores (0,1,2) run the RTOS and core 3 for the Linux subsystem. T-Kernel takes care of scheduling for the RTOS.
- If a button is pressed during a window the camera will remain booted up.
- Otherwise camera goes into hibernation. The clocks are shutdown but ram stays refreshed. ASV gets lowered in newer cameras.
- The GoPro will now warm boot on button press.
Button press before 8 hour timeout, card install, etc
- Warm boot occurs and LPDDR does not need to be restored.
- Linux does quick boot
- RTOS does complete boot.
After 8 hours
- Full shutdown occurs
Factory Update
Socionext Stubby Code Base
We gathered most of this information from inspecting the Stubby GPL2 open source tar located on GoPro's website and newer version on Ricoh. The Ricoh version has an ES3 variant which is for the SC2000.
SD.DAT - Branches to stubby
If loaded on the card, SD.DAT will be ran by the CM0. It’s purpose is to load and program a special DATA.bin. By holding the record button, with no battery, and adding USB power, the GP1 will run SD.DAT.
This code then checks for the following files:
(Note: must have DOS LR & CF's!!!!)
File | Description | Required |
SD.DAT | Initializes SDRAM and loads an image from an "SD" card | X |
BOOT.PAR | Informs sd.dat which gpio to use for status, whether to load the code, program into NAND or program into eMMC. It also contains the vector address and size for the supervisor code as well as timeout parameters. | X |
SDRAM.PAR | LPPDR configuration file | X |
DATA.BIN | The formatted data file to load and then vector. It contains a header, M0 supervisor code, then the stubby/DTB/linux code. | X |
NAND.PAR | NAND configuration file | |
PARDATA .PAR | Partition data. Defines the partition parameters and options. This is needed! | X |
DEVICE .PAR | Device parameters for M8M | |
SECURE .PAR | A signature that is not used on the GP1 |
If put boot.par, sdram.par, data.bin with SD.DAT it loads your code. There is no method for SD.DAT to do a RAM boot as far as I can tell. Therefore you will need a properly formed pardata.par to properly repair the eMMC.
The SD.DAT code runs on the CM0 and starts at 0xFFE00400. It self modifies a vector table tables at 0x31000000. If the top, front, led never lights, you know this code is getting launched. The LED signifies an error if it is properly configured in boot.par for the camera.
The peripheral addresses are not the same as on the Cortex-A7, so it made inspecting the code difficult. However, the addresses are offset by 0x3000_0000. My rough GP1 / SC2000 Memory Map Listing.
SD.DAT to resurrect bricked cameras
Parameter files were extracted from eMMC for the GoPro HERO6. I will need some time to make files for the HERO[7-9]. The GoPro HERO[10,11] will require a new SD.DAT that runs on aarch64 (ARM64). That will be my next project.
<Each camera is different! So files are not provided to save you from yourself.>
With no battery, put the contents on the root, hold the top record button, add USB power. After red LED, put in fully charged battery, and eject and then reinstall card. Press mode button and allow it to update.
Calibration (Important)
Calibration data is not touched if partition table is correct for the camera. If it is wrong you can destroy your calibration data which is really, really bad. If I were to make a tool commercially, I would backup this data before attempting a resurrection.
Do not use the wrong pardata!!!!!
Burrner Code (m8m-nand-SD.bin)
m8m-nand-SD.bin Appears to burn the DATA.bin file into NAND. As the GoPro has eMMC, this does not seem to work or is not configured correctly.
It gets loaded at 0x40000000 so the SDRAM needs to be running.
BootROM / USB repairs
I've finally extracted and inspected the bootrom and it appears to have USB descriptors. Therefore, I'll have to mess around with various USB-C pins to see if I can't force the GP1 into a USB update mode.
Conclusion
This is a work in progress. Perhaps someone has some suggestions/comments. Feel free to reach me here or on Twitter @GetHypoxic.
LEGAL: This product and/or service is not affiliated with, endorsed by, or in any way associated with GoPro Inc. or its products and services. GoPro, HERO, and their respective logos are trademarks or registered trademarks of GoPro, Inc. HEROBUS and BACPAC are trademarks of GoPro Inc.