Group: Hardware/Computers/e-readers/Kobo/Aura H2O Edition 2
(→Exporting the internal eMMC) |
m (GNUtoo moved page Group:Hardware/research/e-readers/Kobo/Aura H2O Edition 2 to Group:Hardware/Computers/e-readers/Kobo/Aura H2O Edition 2: it's a computer type) |
||
(255 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
+ | == Warnings == | ||
+ | This page describe research done on the Kobo Aura H2O Edition 2 e-reader. | ||
+ | |||
+ | The instructions given here are meant for research purpose: they are intended to find out if the kobo Aura H2O Edition 2 can meet the Respect Your Freedom certification with an amount of work that is not too big. | ||
+ | |||
+ | This doesn't mean that merely following the instruction will automatically make the source code respect the Free software distributions guidelines or that the device would automatically respect the Respect Your Freedom certification. | ||
+ | |||
+ | So for instance the instructions that explain how to make the display work with free software are only meant to validate that part, and didn't necessarily remove unrelated nonfree software. | ||
+ | |||
+ | == Reviewed devices == | ||
+ | * So far only devices using the arch/arm/boot/dts/imx6sll-e60qm2.dts devicetree were reviewed. | ||
+ | |||
+ | == Issues found so far == | ||
+ | * The WiFi firmware is under the GPLv2 but lacks source code. It needs to be reverse engineered. Hopefully it is small and the CPU ISA is known. | ||
+ | |||
+ | == Priority investigations == | ||
+ | === TODO === | ||
+ | Urgent: | ||
+ | * e-paper display: validate its usability better if possible | ||
+ | * verify if nothing was missed | ||
+ | |||
+ | Extra verifications: | ||
+ | * u-boot source code: Read it to see if it loads any firmware | ||
+ | * Linux source code: Look at the dts and drivers again to spot if something was missed | ||
+ | * Hardware: describe the hardware better and look again if there is anything dodgy (unlikely to be missed with the software review though) | ||
+ | * check what driver/cards the free wifi firmwares work on | ||
+ | * Document the waveform data format | ||
+ | |||
+ | Later: | ||
+ | * Document how to do bootloader development (device recovery, usb boot, etc) | ||
+ | |||
+ | === waveform === | ||
+ | Findings: | ||
+ | * The waveform partition contains: | ||
+ | * a mxcfb_waveform_data_file struct header | ||
+ | * zero padding at the end | ||
+ | |||
+ | That header also contains some RAW data which seem to only contain waveform data: | ||
+ | * That data was analyzed with inkwave as shown below | ||
+ | * A quick look in mxc_epdc_v2_fb.c tend to indicate that there is only data in this waveform partition. | ||
+ | |||
+ | $ git clone https://github.com/fread-ink/inkwave | ||
+ | $ cd inkwave && make | ||
+ | $ ./inkwave -f wrf ../ntx-partitions-parser/partitions/waveform.img | ||
+ | |||
+ | File size: 10485760 bytes | ||
+ | |||
+ | Header info: | ||
+ | Serial number: 6786 | ||
+ | Run type: 0x11 | Unknown | ||
+ | Manufacturer code: 0xba | Unknown | ||
+ | Frontplane Laminate (FPL) platform: 0x0 | 2.0 | ||
+ | Frontplane Laminate (FPL) lot: 208 | ||
+ | Frontplane Laminate (FPL) size: 0x0 | Unknown | ||
+ | Frontplane Laminate (FPL) rate: 0x85 | 85Hz | ||
+ | Waveform version: 32 | ||
+ | Waveform sub-version: 33 | ||
+ | Waveform type: 0x51 | Unknown | ||
+ | Waveform tuning bias: Unknown | ||
+ | Waveform revision: 0 | ||
+ | Adhesive run number: 25 | ||
+ | Mode version: Unknown | ||
+ | Number of modes in this waveform: 8 | ||
+ | Number of temperature ranges in this waveform: 14 | ||
+ | 4 or 5-bits per pixel: 5 | ||
+ | |||
+ | Modes: Unknown (no mode version specified) | ||
+ | |||
+ | === ntxfw and hwcfg === | ||
+ | |||
+ | Findings: | ||
+ | * hwcfg only contains hardware configuration data and a lot of zero padding | ||
+ | * ntxfw contains backlight tables, and some unknown extra data that is not described in structs and doesn't seem to be used. Backlight still work with the unknown data removed. | ||
+ | |||
+ | Tools: | ||
+ | * [https://framagit.org/imx-e-readers/ntx-partitions-parser ntx-partitions-parser] | ||
+ | |||
+ | Boot flow: | ||
+ | * u-boot loads that partition in memory and tells the kernel about it through kernel command line argument like ntxfw_p=<address> and ntxfw_sz=<size> in board/freescale/common/ntx_comm.c | ||
+ | * The kernel picks that up in arch/arm/mach-imx/common.c | ||
+ | |||
+ | ntxcfg test: | ||
+ | $ cp ntxfw.img ntxfw_cleaned.img | ||
+ | $ dd if=/dev/zero of=ntxfw_cleaned.img seek=1427 bs=1 count=129133 conv=notrunc # zero out all the data outside of struct | ||
+ | $ echo -n '<--NTXFW}' | dd of=ntxfw_cleaned.img bs=1 seek=9464 count=9 conv=notrunc # Add the footer signature just in case | ||
+ | Result: | ||
+ | $ hexdump -C ntxfw_cleaned.img | sed 's#^# #' | ||
+ | 00000000 7b 4e 54 58 46 57 2d 2d 3e 00 45 36 30 51 4d 32 |{NTXFW-->.E60QM2| | ||
+ | 00000010 00 5b 25 64 5d 3d 25 64 0a 00 00 00 00 03 00 00 |.[%d]=%d........| | ||
+ | 00000020 00 25 73 20 67 6f 74 20 25 64 00 00 00 00 02 00 |.%s got %d......| | ||
+ | 00000030 00 00 00 00 ff fc 5c c5 5c c5 cf ff 78 56 34 12 |......\.\...xV4.| | ||
+ | 00000040 06 00 00 00 10 00 00 00 45 36 30 51 4d 32 5f 64 |........E60QM2_d| | ||
+ | 00000050 75 61 6c 66 6c 5f 68 64 72 5f 31 36 31 31 31 36 |ualfl_hdr_161116| | ||
+ | 00000060 00 00 00 00 00 00 00 00 00 00 00 00 0b 00 00 00 |................| | ||
+ | 00000070 0a 05 00 00 00 00 00 00 00 00 00 00 ff fc 5c c5 |..............\.| | ||
+ | 00000080 5c c5 cf ff 78 56 34 12 07 00 00 00 44 24 00 00 |\...xV4.....D$..| | ||
+ | 00000090 45 36 30 51 4d 32 5f 64 75 61 6c 66 6c 5f 74 61 |E60QM2_dualfl_ta| | ||
+ | 000000a0 62 5f 31 36 31 31 31 36 00 00 00 00 00 00 00 00 |b_161116........| | ||
+ | 000000b0 00 00 00 00 54 30 00 00 00 00 00 00 00 00 00 00 |....T0..........| | ||
+ | 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | 000000d0 00 00 00 00 00 00 00 00 36 47 54 5b 62 6a 71 78 |........6GT[bjqx| | ||
+ | 000000e0 7d 83 87 8b 8e 90 93 95 97 99 9b 9d 9f a2 a4 a7 |}...............| | ||
+ | 000000f0 a9 ab b0 b2 b4 b5 b6 b8 ba bb bd bf c0 c1 c2 c3 |................| | ||
+ | 00000100 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 |................| | ||
+ | 00000110 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 |................| | ||
+ | 00000120 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 |................| | ||
+ | 00000130 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 00 00 00 |................| | ||
+ | 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | * | ||
+ | 00000260 00 00 00 00 00 00 00 00 02 05 00 00 e7 05 00 00 |................| | ||
+ | 00000270 b6 06 00 00 59 07 00 00 fb 07 00 00 18 09 00 00 |....Y...........| | ||
+ | 00000280 5d 0a 00 00 ce 0b 00 00 f3 0c 00 00 90 0e 00 00 |]...............| | ||
+ | 00000290 ea 0f 00 00 62 11 00 00 8e 12 00 00 82 13 00 00 |....b...........| | ||
+ | 000002a0 d2 14 00 00 b9 15 00 00 b7 16 00 00 f3 17 00 00 |................| | ||
+ | 000002b0 57 1a 00 00 57 1a 00 00 79 1b 00 00 9f 1d 00 00 |W...W...y.......| | ||
+ | 000002c0 33 1f 00 00 85 21 00 00 71 23 00 00 2e 25 00 00 |3....!..q#...%..| | ||
+ | 000002d0 06 2c 00 00 e0 2e 00 00 7a 30 00 00 1e 32 00 00 |.,......z0...2..| | ||
+ | 000002e0 68 33 00 00 ac 35 00 00 36 38 00 00 b2 39 00 00 |h3...5..68...9..| | ||
+ | 000002f0 c2 3d 00 00 b0 40 00 00 18 42 00 00 3a 43 00 00 |.=...@...B..:C..| | ||
+ | 00000300 14 46 00 00 86 47 00 00 e4 48 00 00 d2 4b 00 00 |.F...G...H...K..| | ||
+ | 00000310 3a 4d 00 00 ec 4f 00 00 86 51 00 00 4c 54 00 00 |:M...O...Q..LT..| | ||
+ | 00000320 96 55 00 00 ac 58 00 00 2c 5b 00 00 da 5c 00 00 |.U...X..,[...\..| | ||
+ | 00000330 86 60 00 00 74 63 00 00 f4 65 00 00 e2 68 00 00 |.`..tc...e...h..| | ||
+ | 00000340 a8 6b 00 00 aa 6e 00 00 48 71 00 00 2c 74 00 00 |.k...n..Hq..,t..| | ||
+ | 00000350 10 77 00 00 7a 7b 00 00 04 7e 00 00 1e 82 00 00 |.w..z{...~......| | ||
+ | 00000360 ee 84 00 00 f4 88 00 00 c4 8b 00 00 a6 90 00 00 |................| | ||
+ | 00000370 8e 94 00 00 8a 98 00 00 9a 9c 00 00 82 a0 00 00 |................| | ||
+ | 00000380 56 a4 00 00 34 a8 00 00 30 ac 00 00 58 b1 00 00 |V...4...0...X...| | ||
+ | 00000390 2c b5 00 00 90 ba 00 00 a4 bf 00 00 dc c3 00 00 |,...............| | ||
+ | 000003a0 08 ca 00 00 52 d0 00 00 4a d8 00 00 62 de 00 00 |....R...J...b...| | ||
+ | 000003b0 a2 e4 00 00 1c ed 00 00 16 f3 00 00 82 fa 00 00 |................| | ||
+ | 000003c0 02 02 01 00 8c 09 01 00 b8 0f 01 00 94 1a 01 00 |................| | ||
+ | 000003d0 ec 21 01 00 5c 2a 01 00 44 33 01 00 4c 3a 01 00 |.!..\*..D3..L:..| | ||
+ | 000003e0 12 47 01 00 9c 53 01 00 fa 5e 01 00 10 6c 01 00 |.G...S...^...l..| | ||
+ | 000003f0 f4 78 01 00 d8 85 01 00 00 00 00 00 00 00 00 00 |.x..............| | ||
+ | 00000400 54 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |T1..............| | ||
+ | 00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | 00000420 00 00 00 00 2a 43 4e 58 5f 67 6e 76 7a 7f 84 88 |....*CNX_gnvz...| | ||
+ | 00000430 8a 8d 8f 92 94 96 98 9a 9c 9e a1 a3 a5 a8 ab ae |................| | ||
+ | 00000440 b0 b1 b2 b4 b6 b7 b9 bb bc bd be bf c0 c1 c2 c3 |................| | ||
+ | 00000450 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 |................| | ||
+ | 00000460 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 |................| | ||
+ | 00000470 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 |................| | ||
+ | 00000480 f4 f5 f6 f7 f8 f9 fa fb 00 00 00 00 00 00 00 00 |................| | ||
+ | 00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | * | ||
+ | 000004e0 00 00 00 00 00 00 00 00 00 00 00 00 05 01 01 02 |................| | ||
+ | 000004f0 06 12 1b 10 2b 2e 2d 30 43 3f 42 44 45 45 47 4a |....+.-0C?BDEEGJ| | ||
+ | 00000500 4c 56 4e 5b 5d 55 76 63 67 65 6a 69 64 6a 6b 73 |LVN[]Uvcgejidjks| | ||
+ | 00000510 72 6a 69 72 71 73 76 76 7d 76 7c 75 7a 7d 7c 7a |rjirqsvv}v|uz}|z| | ||
+ | 00000520 75 7b 78 77 7c 78 79 76 7f 80 85 80 86 80 86 86 |u{xw|xyv........| | ||
+ | 00000530 89 88 89 8a 8a 89 8e 8f 93 94 93 93 94 9a 9a 9a |................| | ||
+ | 00000540 9b 9c 9d 9d a0 a0 a2 a1 a2 a3 a3 a6 a6 a8 a8 aa |................| | ||
+ | 00000550 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | * | ||
+ | 000024f0 00 00 00 00 00 00 00 00 3c 2d 2d 4e 54 58 46 57 |........<--NTXFW| | ||
+ | 00002500 7d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |}...............| | ||
+ | 00002510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | * | ||
+ | 0001fe00 | ||
+ | |||
+ | == Firmwares == | ||
+ | === WiFi firmware === | ||
+ | The WiFi driver rely on binary firmwares for the WiFi part. | ||
+ | |||
+ | The firmwares are provided as binary (in arrays format) in the hal/phydm/rtl8188f/halhwimg8188f_fw.c source code file, however this file is provided under the GPLv2. So it may be possible to convert the firmware binary in source code. | ||
+ | |||
+ | TODO: | ||
+ | * Add in this wiki the findings documented in the [https://libreplanet.org/w/images/b/b5/Mp8188-disasm.tar.xz reverse engineering work Willem on this firmware]. | ||
+ | * Investigate if the WiFi chip also has other functions (Bluetooth, FM Radio, etc) | ||
+ | * Investigate if the firmware source code can easily be reconstructed | ||
+ | * Investigate if the chip can work without the firmware | ||
+ | |||
+ | ==== WiFi firmware informations found inside the driver ==== | ||
+ | * The firmware binary is really uploaded to the device chip, see | ||
+ | hal/phydm/phydm_hwconfig.c:2730: READ_FIRMWARE_MP(8188F, _FW_NIC); | ||
+ | hal/phydm/phydm_hwconfig.c:2764: READ_FIRMWARE_MP(8188F,_FW_NIC); | ||
+ | |||
+ | ==== How to extract the firmware ==== | ||
+ | There are generic tools to create a binary out of hex arrays, but it took me less time to write a specific program than to find such tool. I vaguely remember that one of theses tools was mentioned on a blog post on the sigrok blog, it was about something like reconstructing an I2S stream with 'unix way' tools. | ||
+ | |||
+ | [[/firmware_extraction_utility|firmware_extraction_utility.c]] | ||
+ | |||
+ | usage: | ||
+ | $ gcc firmware_extraction_utility.c | ||
+ | $ ./a.out > 8188F_FW_NIC.bin | ||
+ | |||
+ | The first 0x20 bytes are a header: | ||
+ | $ hexdump -C 8188F_FW_NIC.bin | ||
+ | 00000000 f1 88 10 00 01 00 0e 00 03 25 14 55 62 52 02 00 |.........%.UbR..| | ||
+ | 00000010 af 2f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |./..............| | ||
+ | |||
+ | And the rest is code: | ||
+ | 00000020 02 86 a9 02 c7 d7 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | 00000030 00 00 00 02 c0 2d 00 00 00 00 00 00 00 00 00 00 |.....-..........| | ||
+ | 00000040 00 00 00 02 c8 29 00 00 00 00 00 00 00 00 00 00 |.....)..........| | ||
+ | 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | 00000060 00 00 00 02 c7 d8 00 00 00 00 00 02 c2 f0 00 00 |................| | ||
+ | 00000070 00 00 00 02 c8 28 00 00 00 00 00 00 00 00 00 00 |.....(..........| | ||
+ | 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
+ | * | ||
+ | 000000a0 02 87 b7 02 88 d5 02 80 86 02 80 89 02 a5 11 02 |................| | ||
+ | [...] | ||
+ | |||
+ | The code can be extracted like that: | ||
+ | $ dd if=8188F_FW_NIC.bin of=code.bin skip=32 bs=1 | ||
+ | |||
+ | It can then be analyzed with radare2 this way: | ||
+ | $ r2 -a 8051 -m 0x8000 ./code.bin # r2 comes from radare2, which is an interactive disassembler. | ||
+ | Then we can start using radare2: | ||
+ | $ r2 -a 8051 -m 0x8000 ./code.bin | ||
+ | WARNING: using oba to load the syminfo from different mapaddress. | ||
+ | TODO: Must use the API instead of running commands to speedup loading times. | ||
+ | -- You haxor! Me jane? | ||
+ | [0x00008000]> aaaa -AA | ||
+ | [x] Analyze all flags starting with sym. and entry0 (aa) | ||
+ | [x] Analyze function calls (aac) | ||
+ | [x] find and analyze function preludes (aap) | ||
+ | [x] Analyze len bytes of instructions for references (aar) | ||
+ | [x] Check for objc references | ||
+ | [x] Check for vtables | ||
+ | [x] Finding xrefs in noncode section with anal.in=io.maps | ||
+ | [x] Analyze value pointers (aav) | ||
+ | [x] Value from 0x00008000 to 0x0000d262 (aav) | ||
+ | [x] 0x00008000-0x0000d262 in 0x8000-0xd262 (aav) | ||
+ | [Warning: No SN reg alias for current architecture. | ||
+ | [x] Emulate code to find computed references (aae) | ||
+ | [x] Type matching analysis for all functions (aaft) | ||
+ | [x] Use -AA or aaaa to perform additional experimental analysis. | ||
+ | [x] Enable constraint types analysis for variables | ||
+ | [0x00008000]> pd | ||
+ | / (fcn) fcn.00008000 181 | ||
+ | | fcn.00008000 (); | ||
+ | | ; CODE XREF from skip (+0x128) | ||
+ | | ,=< 0x00008000 0286a9 ljmp 0x86a9 | ||
+ | ,==< 0x00008003 02c7d7 ljmp 0xc7d7 | ||
+ | || 0x00008006 00 nop | ||
+ | || 0x00008007 00 nop | ||
+ | || 0x00008008 00 nop | ||
+ | || 0x00008009 00 nop | ||
+ | || 0x0000800a 00 nop | ||
+ | || 0x0000800b 00 nop | ||
+ | || 0x0000800c 00 nop | ||
+ | || 0x0000800d 00 nop | ||
+ | || 0x0000800e 00 nop | ||
+ | || 0x0000800f 00 nop | ||
+ | || 0x00008010 00 nop | ||
+ | || 0x00008011 00 nop | ||
+ | || 0x00008012 00 nop | ||
+ | ,===< 0x00008013 02c02d ljmp 0xc02d | ||
+ | ||| 0x00008016 00 nop | ||
+ | ||| 0x00008017 00 nop | ||
+ | ||| 0x00008018 00 nop | ||
+ | ||| 0x00008019 00 nop | ||
+ | ||| 0x0000801a 00 nop | ||
+ | ||| 0x0000801b 00 nop | ||
+ | ||| 0x0000801c 00 nop | ||
+ | ||| 0x0000801d 00 nop | ||
+ | ||| 0x0000801e 00 nop | ||
+ | ||| 0x0000801f 00 nop | ||
+ | ||| 0x00008020 00 nop | ||
+ | ||| 0x00008021 00 nop | ||
+ | ||| 0x00008022 00 nop | ||
+ | ,====< 0x00008023 02c829 ljmp 0xc829 | ||
+ | |||| 0x00008026 00 nop | ||
+ | |||| ; CODE XREF from skip (+0x1db) | ||
+ | |||| 0x00008027 00 nop | ||
+ | |||| 0x00008028 00 nop | ||
+ | |||| 0x00008029 00 nop | ||
+ | |||| 0x0000802a 00 nop | ||
+ | |||| 0x0000802b 00 nop | ||
+ | |||| 0x0000802c 00 nop | ||
+ | |||| 0x0000802d 00 nop | ||
+ | |||| 0x0000802e 00 nop | ||
+ | |||| 0x0000802f 00 nop | ||
+ | |||| 0x00008030 00 nop | ||
+ | |||| ; CODE XREF from skip (+0x1dd) | ||
+ | |||| 0x00008031 00 nop | ||
+ | |||| 0x00008032 00 nop | ||
+ | |||| 0x00008033 00 nop | ||
+ | |||| 0x00008034 00 nop | ||
+ | |||| 0x00008035 00 nop | ||
+ | |||| 0x00008036 00 nop | ||
+ | |||| 0x00008037 00 nop | ||
+ | |||| 0x00008038 00 nop | ||
+ | |||| 0x00008039 00 nop | ||
+ | |||| 0x0000803a 00 nop | ||
+ | |||| 0x0000803b 00 nop | ||
+ | |||| 0x0000803c 00 nop | ||
+ | |||| 0x0000803d 00 nop | ||
+ | |||| 0x0000803e 00 nop | ||
+ | |||| 0x0000803f 00 nop | ||
+ | |||| 0x00008040 00 nop | ||
+ | |||| 0x00008041 00 nop | ||
+ | |||| 0x00008042 00 nop | ||
+ | ,=====< 0x00008043 02c7d8 ljmp 0xc7d8 | ||
+ | ||||| 0x00008046 00 nop | ||
+ | ||||| 0x00008047 00 nop | ||
+ | ||||| 0x00008048 00 nop | ||
+ | ||||| 0x00008049 00 nop | ||
+ | [0x00008000]> | ||
+ | |||
+ | * You can then jump to functions with s <address> | ||
+ | * You can continue listing code with s<address><enter> <enter> | ||
+ | |||
+ | ==== Information on the WiFi firmware ==== | ||
+ | ===== WiFi Firmware ISA ===== | ||
+ | * The firmware uses the 8051 instruction | ||
+ | * The entry point and load address is at 0x8000 | ||
+ | |||
+ | ===== Reverse engineering ===== | ||
+ | * The driver has many comments about the firmware and processor that runs the firmware. That can help a lot. | ||
+ | * At the time of writing, [https://github.com/avast-tl/retdec/blob/master/README.md Retdec README] doesn't support the 8051 architecture yet: | ||
+ | Supported architectures (32b only): Intel x86, ARM, MIPS, PIC32, and PowerPC. | ||
+ | * Radare2 seem to work on the firmware and has some good auto-analyze functions | ||
+ | * The firmware is small: | ||
+ | $ du -hs 8188F_FW_NIC.bin | ||
+ | 24K 8188F_FW_NIC.bin | ||
+ | |||
+ | ===== firmware format ===== | ||
+ | * it probably has a header and some calibration data at the begining | ||
+ | => check the struct format | ||
+ | |||
+ | === Touchscreen === | ||
+ | ==== cyttsp5 ==== | ||
+ | This should work without having to load any firmware. | ||
+ | |||
+ | Details: | ||
+ | * This driver can use the cyttsp5_fw.bin firmware | ||
+ | ** The firmware seem optional at least in certain cases | ||
+ | ** A firmware file cannot be found on the filesystem | ||
+ | ** The support for loading the firmware is builtin the module but that could be because the vendor code has some issue without that code (like won't compile or similar) | ||
+ | ** The touchscreen works in Parabola (with ntxfw partition blanked): tested with evtest /dev/input/event1 | ||
+ | |||
== External interfaces == | == External interfaces == | ||
=== USB === | === USB === | ||
Line 6: | Line 340: | ||
=== Power button === | === Power button === | ||
+ | Some more research is needed to understand how exactly is connected the power button: | ||
+ | * It probably has to be connected to the PMIC to power up the device | ||
+ | * It's also connected to an I.MX GPIO, and it's possible to get the button value through that GPIO as well, under certain conditions. | ||
+ | |||
=== Touchscreen === | === Touchscreen === | ||
== Internal interfaces == | == Internal interfaces == | ||
=== Serial/UART === | === Serial/UART === | ||
+ | As it can be seen on one of the [https://archive.org/details/kobo_aura_H2O_edition_2_pcb_01.jpeg PCB pictures], near the battery, there is some holes with some markings: V, TX, RX, and a ground sign. It seems that more recent manufacturing batch lacks such markings. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | | V | ||
+ | | | ||
+ | * At 3.3v when the device is powered on | ||
+ | * At 0v when the device is off | ||
+ | * You should not connect the serial port adapter to it | ||
+ | |- | ||
+ | | TX | ||
+ | | | ||
+ | * Serial port TX | ||
+ | * Connect to the RX of your USB<->Serial port adapter | ||
+ | |- | ||
+ | | RX | ||
+ | | | ||
+ | * Serial port RX | ||
+ | * Connect to the TX of your USB<->Serial port adapter | ||
+ | |- | ||
+ | | GND | ||
+ | | Ground | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | The holes pitch are 2.54mm (0.1 inch), so it's compatible with most common [https://en.wikipedia.org/wiki/Pin_header pin-headers] found in electronic shops like [https://en.wikipedia.org/wiki/File:6_Pin_Header.jpg this one]. | ||
+ | The best is to use headers that are bent, this way: | ||
+ | * You could even be able to put back the cover if the pin headers height is small enough | ||
+ | * You can still easily use the e-book reader with the screen towards you while still having the serial port adapter plugged in. | ||
+ | |||
+ | Soldering on theses holes is tricky as there is some transparent plastic coating on all the PCB, including the internal connectors and the components. Under that there is the classic PCB coating (which is green here). | ||
+ | |||
+ | So I used some "grain 400" sand paper to remove the plastic and green coating on the serial port pin holes. | ||
+ | |||
+ | If you're not careful enough this will also expose the ground plane, making it harder to solder without any shorts. | ||
+ | |||
+ | For the ground connector, if you remove too much coating, it will make soldering harder as the big ground plane will dissipate your soldering iron heat, preventing you from melting the tin. | ||
+ | |||
+ | Also beware that the '3v3' pin is shorted to GND when the device is off (and is at 3.3V when the device is on). So even if it seems shorted to GND, it might not be. | ||
+ | |||
+ | You also need to choose how to solder the header: | ||
+ | * If the header pin goes on the battery side, then there won't be any risk of shorting the pins and if you manage to find a header that is the right size, it will stay better in place as the cable you will plug in can be exactly the size of the hole between the header and the battery. However you won't be able to close the cover anymore. | ||
+ | * If the header pin goes on the opposite side of the battery, then you will be able to close the cover, but you will need to make sure that the header, the cable (and possibly the serial adapter stay in a position where they cannot cause short circuit by having their metallic part touch some of the conductive part on the e-reader [https://en.wikipedia.org/wiki/Printed_circuit_board PCB]. | ||
+ | |||
+ | I used the following equipment to do it: | ||
+ | * Lead free solder | ||
+ | * TS100 Soldering iron with the free software firmware at 450 Degrees | ||
+ | * A tip that is chisel-like but only one one side | ||
+ | * Tivoly "Métal Peint", grain 240 "sand paper" | ||
+ | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 42: | Line 430: | ||
This effectively prevent the device from going into suspend. | This effectively prevent the device from going into suspend. | ||
+ | |||
+ | === main storage === | ||
+ | |||
+ | ==== Partitions ==== | ||
+ | With fdisk or by looking in /proc/partition we can see 3 partitions: | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! partition | ||
+ | ! size | ||
+ | ! function | ||
+ | ! source | ||
+ | |- | ||
+ | | mmcblk0p1 | ||
+ | | 256M | ||
+ | | rootfs | ||
+ | | cat /proc/cmdline: root=/dev/mmcblk0p1 | ||
+ | |- | ||
+ | | mmcblk0p2 | ||
+ | | 256M | ||
+ | | Backup rootfs ? | ||
+ | | after mounting it, there are some similar files. Strangely there are no kernel modules in this one. | ||
+ | |- | ||
+ | | mmcblk0p3 | ||
+ | | 6.8G | ||
+ | | user data | ||
+ | | mount: /dev/mmcblk0p3 on /mnt/onboard type vfat | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | However if we look at update scripts or fastboot we have more partitions: | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! name | ||
+ | ! start | ||
+ | ! size (from fastboot) | ||
+ | ! function | ||
+ | ! source | ||
+ | |- | ||
+ | | mbr | ||
+ | | 0 | ||
+ | | 1 | ||
+ | | [https://en.wikipedia.org/wiki/Master_boot_record The MBR] | ||
+ | | | ||
+ | * The partition is called mbr and it's at the beginning. | ||
+ | |- | ||
+ | | sn | ||
+ | | 1 | ||
+ | | 1 | ||
+ | | The device serial number | ||
+ | | | ||
+ | * The partition content viewed with hexdump | ||
+ | |- | ||
+ | | bootloader | ||
+ | | 2 | ||
+ | | 1022 | ||
+ | | The bootloader (u-boot code) | ||
+ | | | ||
+ | * The name of the partition | ||
+ | * bootloader partitions are typically at the beginning | ||
+ | |- | ||
+ | | hwcfg | ||
+ | | 1024 | ||
+ | | 2 | ||
+ | | | ||
+ | * Hardware configuration data | ||
+ | * zero padding at the end | ||
+ | | rowspan="2" | | ||
+ | * Kernel source code | ||
+ | * I've also written a tool to analyze it to make sure that everything is understood | ||
+ | |- | ||
+ | | ntxfw | ||
+ | | 1030 | ||
+ | | 255 | ||
+ | | | ||
+ | * Backlight configuration tables | ||
+ | * Unknown data (which is probably unused) that can be removed | ||
+ | * zero padding at the end | ||
+ | |- | ||
+ | | waveform | ||
+ | | 14336 | ||
+ | | 20480 | ||
+ | | The waveform for the e-ink display | ||
+ | | | ||
+ | * The name of the partition | ||
+ | * Some e-paper displays needs some 'waveform' data to work | ||
+ | * Contains some huge patterns of zero ones two that are contiguous | ||
+ | |- | ||
+ | | logo | ||
+ | | 34816 | ||
+ | | 4096 | ||
+ | | empty | ||
+ | | | ||
+ | * partition content viewed with hexdump | ||
+ | |- | ||
+ | | bootenv | ||
+ | | 1536 | ||
+ | | 510 | ||
+ | | Probably u-boot environment | ||
+ | | | ||
+ | * The name of the partition | ||
+ | * The fact that u-boot typically stores its environment in a separate partition | ||
+ | * The partition content contains the boot environment strings | ||
+ | |- | ||
+ | | kernel | ||
+ | | 2048 | ||
+ | | 12284 | ||
+ | | The linux kernel in zImage format | ||
+ | | | ||
+ | * The partition content | ||
+ | |- | ||
+ | | dtb | ||
+ | | 1286 | ||
+ | | 250 | ||
+ | | The [https://en.wikipedia.org/wiki/Device_tree device tree] binary | ||
+ | | | ||
+ | * The partition content | ||
+ | |- | ||
+ | | rootfs | ||
+ | | 49152 | ||
+ | | 524289 | ||
+ | | The two rootfs concatenated | ||
+ | | | ||
+ | * The name of the partition | ||
+ | * The location and size of the partition | ||
+ | * The fact that it's recognized as ext4 | ||
+ | |- | ||
+ | | vfat | ||
+ | | 1097730 | ||
+ | | 14139389 | ||
+ | | | ||
+ | * Probably user data | ||
+ | * this partition is vfat and can be mounted | ||
+ | * this partition is made available if you choose to use your computer to setup the device | ||
+ | | | ||
+ | * The partition name and content | ||
+ | * The usage of the e-book reader | ||
+ | |- | ||
+ | | recoveryfs | ||
+ | | 573441 | ||
+ | | 524289 | ||
+ | | | ||
+ | * A recovery partition? | ||
+ | | | ||
+ | * The name of the partition | ||
+ | * Contains a Linux kernel and initramfs | ||
+ | |} | ||
+ | |||
+ | More detail on ntxfw partition dumped from a device compatible with the imx6sll-e60qm2.dts devicetree: | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! partition name | ||
+ | |- | ||
+ | | NTX_FW_TYPE_LM3630_DUALFL_HDR | ||
+ | |- | ||
+ | | NTX_FW_TYPE_LM3630_DUALFL_PERCENTTAB | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | ==== Exporting the internal eMMC as a block device ==== | ||
+ | After getting a shell in u-boot we can look at the list of eMMC/SD cards: | ||
+ | eBR-1A # mmc list | ||
+ | FSL_SDHC: 0 (eMMC) | ||
+ | FSL_SDHC: 1 | ||
+ | |||
+ | The second mmc listed above doesn't seem to exist: | ||
+ | eBR-1A # mmc dev 1 | ||
+ | Card did not respond to voltage select! | ||
+ | This is probably because the u-boot code is based on the code for a Freescale developement/evaluation board and since device manufacturers need to ship products fast they probably didn't bother removing the code for that non-existing hardware. | ||
+ | |||
+ | There is a command called 'ums' in u-boot that can export the e-MMC card through USB and make it appear as a mass storage device (like an USB key or an USB hard disk) to the computer it's connected to. | ||
+ | |||
+ | To use it you need to first connect an usb cable between your computer and the e-book reader and then type 'ums 0 mmc 0' in u-boot like that: | ||
+ | eBR-1A # ums 0 mmc 0 | ||
+ | UMS: LUN 0, dev 0, hwpart 0, sector 0xe90000 | ||
+ | |||
+ | You can then see it on your laptop: | ||
+ | $ lsblk | ||
+ | [...] | ||
+ | sdb 8:16 1 7.3G 0 disk | ||
+ | ├─sdb1 8:17 1 256M 0 part | ||
+ | ├─sdb2 8:18 1 256M 0 part | ||
+ | └─sdb3 8:19 1 6.8G 0 part | ||
+ | |||
+ | You can then use GNU ddrescue to backup the eMMC device: | ||
+ | ddrescue /dev/sdb kobo_emmc.img | ||
+ | |||
+ | ==== Extracting the hidden partitions ==== | ||
+ | Since the fastboot provides us the offset and that dd default is to operate on 512b at a time we can simply run the following commands: | ||
+ | dd if=kobo_emmc.img of=mbr.img count=1 | ||
+ | dd if=kobo_emmc.img of=sn.img skip=1 count=1 | ||
+ | dd if=kobo_emmc.img of=bootloader.img skip=2 count=1022 | ||
+ | dd if=kobo_emmc.img of=hwcfg.img skip=1024 count=2 | ||
+ | dd if=kobo_emmc.img of=ntxfw.img skip=1030 count=255 | ||
+ | dd if=kobo_emmc.img of=waveform.img skip=14336 count=20480 | ||
+ | dd if=kobo_emmc.img of=logo.img skip=34816 count=4096 | ||
+ | dd if=kobo_emmc.img of=bootenv.img skip=1536 count=510 | ||
+ | dd if=kobo_emmc.img of=kernel.img skip=2048 count=12284 | ||
+ | dd if=kobo_emmc.img of=dtb.img skip=1286 count=250 | ||
+ | dd if=kobo_emmc.img of=rootfs.img skip=49152 count=524289 | ||
+ | dd if=kobo_emmc.img of=vfat.img skip=1097730 count=14139389 | ||
+ | dd if=kobo_emmc.img of=recoveryfs.img skip=573441 count=524289 | ||
+ | |||
+ | ==== Fastboot ==== | ||
+ | There is a fastboot command in u-boot. If you want to enable it from the u-boot shell you can do it like that: | ||
+ | # fastboot 0 | ||
+ | ptn 0 name='mbr' start=0 len=1 | ||
+ | ptn 1 name='sn' start=1 len=1 | ||
+ | ptn 2 name='bootloader' start=2 len=1022 | ||
+ | ptn 3 name='hwcfg' start=1024 len=2 | ||
+ | ptn 4 name='ntxfw' start=1030 len=255 | ||
+ | ptn 5 name='waveform' start=14336 len=20480 | ||
+ | ptn 6 name='logo' start=34816 len=4096 | ||
+ | ptn 7 name='bootenv' start=1536 len=510 | ||
+ | ptn 8 name='kernel' start=2048 len=12284 | ||
+ | ptn 9 name='dtb' start=1286 len=250 | ||
+ | ptn 10 name='rootfs' start=49152 len=524289 | ||
+ | ptn 11 name='vfat' start=1097730 len=14139389 | ||
+ | ptn 12 name='recoveryfs' start=573441 len=524289 | ||
+ | |||
+ | Here we have access to a lot more partition than with the block device export over USB. | ||
+ | |||
+ | ==== fastboot lsusb ==== | ||
+ | Here's how it looks like on lsusb | ||
+ | $ lsusb | ||
+ | Bus 001 Device 008: ID 18d1:0d02 Google Inc. Celkon A88 | ||
+ | |||
+ | ==== Triggering fastboot without access to the serial port ==== | ||
+ | First run the fastboot command you want to run. You need to do that first because with this method, fastboot will be available for a very short ammount of time (about 5 seconds). | ||
+ | |||
+ | For instance if you want to boot an image named 'boot.img' you can run the follwing command: | ||
+ | $ fastboot boot ./boot.img | ||
+ | |||
+ | First make sure that the device is powered off. With the stock OS, it will either display 'Powered off' in the language it's configured in, or an image on how to plug the device if it never has been powered on. | ||
+ | |||
+ | Once the device is off press the power button. The device will then lit the top-right blue light. At this point press the power button again, and the device will go in fastboot mode for a very short amount of time (about 5 seconds). | ||
== PCB == | == PCB == | ||
Line 60: | Line 684: | ||
|- | |- | ||
| 512M [https://en.wikipedia.org/wiki/Random-access_memory RAM] | | 512M [https://en.wikipedia.org/wiki/Random-access_memory RAM] | ||
− | | | + | | On the PCB top, near the I.MX |
| 168-Ball PoP-FBGA | | 168-Ball PoP-FBGA | ||
| | | | ||
Line 71: | Line 695: | ||
|- | |- | ||
| ? | | ? | ||
− | | | + | | On the PCB top, near the I.MX |
| ? | | ? | ||
| | | | ||
Line 81: | Line 705: | ||
| | | | ||
|- | |- | ||
− | | [https://en.wikipedia.org/wiki/System_on_a_chip System on a chip] | + | | [https://en.wikipedia.org/wiki/System_on_a_chip System on a chip] (IMX6SLL CEC) |
− | | | + | | On the PCB top |
| ? (BGA) | | ? (BGA) | ||
| | | | ||
− | MCIMX6V7DVN10AB | + | [https://www.nxp.com/part/MCIMX6V7DVN10AB MCIMX6V7DVN10AB] |
XAA 1739 | XAA 1739 | ||
TAIW HMAAXK | TAIW HMAAXK | ||
| Lots of drivers | | Lots of drivers | ||
− | | | + | | [https://www.nxp.com/docs/en/reference-manual/IMX6SLLRM.pdf Reference Manual] |
|- | |- | ||
| WiFi chip (and potentially other features) | | WiFi chip (and potentially other features) | ||
− | | | + | | On the PCB top, near the I.MX |
| ? | | ? | ||
| | | | ||
Line 99: | Line 723: | ||
H857492 | H857492 | ||
GH438 | GH438 | ||
− | | | + | | The 8188f chip in the RTL8189FS out of tree driver |
| | | | ||
|- | |- | ||
− | | | + | | Main PMIC (powers down the device) |
− | | | + | | On the PCB top, near the power button |
− | | | + | | BGA (CSP0608-80 Package) |
| | | | ||
− | RICOH | + | [https://www.e-devices.ricoh.co.jp/en/products/product_pmic/multiple-pmu/rc5t619/ RICOH RC5T619] |
1137 | 1137 | ||
− | |||
| | | | ||
+ | | | ||
+ | * [https://www.e-devices.ricoh.co.jp/en/products/product_pmic/multiple-pmu/rc5t619/rc5t619.pdf datasheet] | ||
|- | |- | ||
| [https://en.wikipedia.org/wiki/Power_management_integrated_circuit Power management integrated circuit] (and potentially other features) | | [https://en.wikipedia.org/wiki/Power_management_integrated_circuit Power management integrated circuit] (and potentially other features) | ||
Line 149: | Line 774: | ||
* https://archive.org/details/kobo_aura_H2O_edition_2_pcb_09.jpeg | * https://archive.org/details/kobo_aura_H2O_edition_2_pcb_09.jpeg | ||
* https://archive.org/details/kobo_aura_H2O_edition_2_pcb_10.jpeg | * https://archive.org/details/kobo_aura_H2O_edition_2_pcb_10.jpeg | ||
+ | |||
+ | === Booting configuration === | ||
+ | Findings: | ||
+ | * The device doesn't have restricted boot enabled/configured. | ||
+ | * How to recover the device was not found yet. | ||
+ | * Building and reflashing a bootloader works. | ||
+ | |||
+ | ===== Restricted boot details ===== | ||
+ | The device tested doesn't have restricted boot configured/enabled: | ||
+ | * According to the [https://www.nxp.com/docs/en/application-note/AN4581.pdf Secure Boot on ... i.MX 6 ... application note] , the SRK (Super Root Key) is "An RSA key pair which forms the start of the boot-time authentication chain. [...]" | ||
+ | * According to the SOC reference manuals, in the "OCOTP memory map", the SRK fuses settings are available in the OTP Bank3 (words 0 to 7 both included) | ||
+ | * The SRK fuses registers were dumped and were blank: | ||
+ | eBR-1A # fuse sense 3 0 8 | ||
+ | Sensing bank 3: | ||
+ | |||
+ | Word 0x00000000: 00000000 00000000 00000000 00000000 | ||
+ | Word 0x00000004: 00000000 00000000 00000000 00000000 | ||
+ | |||
+ | ===== Boot order and recovery details ===== | ||
+ | Findings: | ||
+ | * The device is set to the "Internal Boot" BOOT_MODE | ||
+ | * The fuses are then configured to make the device boot on MMC/eMMC | ||
+ | * The boot settings can be overriden by GPIOs (BT_FUSE_SEL=0) | ||
+ | |||
+ | ===== BOOT_MODE details ===== | ||
+ | In the chapter 8.2.1 Boot mode pin settings of the SOC reference manual we have: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! BOOT_MODE[1:0] | ||
+ | ! Boot Type | ||
+ | |- | ||
+ | | 00 | ||
+ | | Boot From Fuses | ||
+ | |- | ||
+ | | 01 | ||
+ | | Serial Downloader | ||
+ | |- | ||
+ | | 10 | ||
+ | | Internal Boot | ||
+ | |- | ||
+ | | 11 | ||
+ | | Reserved | ||
+ | |} | ||
+ | |||
+ | We are in the "Internal Boot" case here: | ||
+ | |||
+ | # devmem2 0x20D801C w # 0x76fb5000 is SRC_SMBR2 | ||
+ | /dev/mem opened. | ||
+ | Memory mapped at address 0x76fb5000. | ||
+ | Value at address 0x20D801C (0x76fb501c): 0x2000001 | ||
+ | Which results in: | ||
+ | SRC_SMBR2[25] = BOOT_MODE1 = 1 | ||
+ | SRC_SMBR2[24] = BOOT_MODE0 = 0 | ||
+ | |||
+ | ===== BT_FUSE_SEL details ===== | ||
+ | |||
+ | In the "8.2.5 Internal Boot mode (BOOT_MODE[1:0] = 0b10)" chapter we have: "If BT_FUSE_SEL = 0, the specific boot configuration parameters may be set using the GPIO pins rather than eFUSEs." | ||
+ | |||
+ | And in "SRC_SBMR2 field descriptions" in "Chapter 41 System Reset Controller (SRC)" we have: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Field | ||
+ | | Description | ||
+ | |- | ||
+ | |4 | ||
+ | BT_FUSE_SEL | ||
+ | | BT_FUSE_SEL (connected to gpio bt_fuse_sel) shows the state of the BT_FUSE_SEL fuse. See | ||
+ | Fusemap for additional information on this fuse. | ||
+ | |} | ||
+ | |||
+ | And Looking to it on the device | ||
+ | # devmem2 0x20D801C w # 0x76fb5000 is SRC_SMBR2 | ||
+ | /dev/mem opened. | ||
+ | Memory mapped at address 0x76fb5000. | ||
+ | Value at address 0x20D801C (0x76fb501c): 0x2000001 | ||
+ | results in: | ||
+ | SRC_SMBR2[4] = BT_FUSE_SEL = 0 | ||
+ | |||
+ | ===== MMC/EMMC boot details ===== | ||
+ | |||
+ | Since we're in "Internal Boot", according to the "5.1 Boot Fusemap" chapter, the following table applies: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Boot Device | ||
+ | ! BOOT_CFG1[6] | ||
+ | ! BOOT_CFG1[5] | ||
+ | ! BOOT_CFG1[4] | ||
+ | |- | ||
+ | | Serial ROM | ||
+ | | 0 | ||
+ | | 1 | ||
+ | | 1 | ||
+ | |- | ||
+ | | SD/eSD | ||
+ | | 1 | ||
+ | | 0 | ||
+ | | X | ||
+ | |- | ||
+ | | MMC/eMMC | ||
+ | | 1 | ||
+ | | 1 | ||
+ | | X | ||
+ | |} | ||
+ | |||
+ | If we look at the device settings: | ||
+ | [root@parabola ~]# devmem2 0x20D8004 w | ||
+ | /dev/mem opened. | ||
+ | Memory mapped at address 0x76fca000. | ||
+ | Value at address 0x20D8004 (0x76fca004): 0x4064 | ||
+ | we have: | ||
+ | BOOT_CFG1[6] = 1 | ||
+ | BOOT_CFG1[5] = 1 | ||
+ | BOOT_CFG1[4] = 0 | ||
+ | which results in the MMC/eMMC being selected. | ||
+ | |||
+ | ===== GPIO override details ===== | ||
+ | In "Table 8-3. GPIO override contact assignments" in "Chapter 8 System Boot" we have: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Package pin | ||
+ | ! eFuse | ||
+ | |- | ||
+ | | LCD_DAT12 | ||
+ | | BOOT_CFG2[4] | ||
+ | |- | ||
+ | | LCD_DAT13 | ||
+ | | BOOT_CFG2[5] | ||
+ | |- | ||
+ | | LCD_DAT14 | ||
+ | | BOOT_CFG2[6] | ||
+ | |} | ||
+ | |||
+ | Theses seem unused: | ||
+ | imx6sll-e60qm2.dts: | ||
+ | [...] | ||
+ | pinctrl_lcdif_dat: lcdifdatgrp { | ||
+ | fsl,pins = < | ||
+ | [...] | ||
+ | MX6SLL_PAD_LCD_DATA12__LCD_DATA12 0x79 | ||
+ | MX6SLL_PAD_LCD_DATA13__LCD_DATA13 0x79 | ||
+ | MX6SLL_PAD_LCD_DATA14__LCD_DATA14 0x79 | ||
+ | [...] | ||
+ | >; | ||
+ | }; | ||
+ | [...] | ||
+ | &lcdif { | ||
+ | pinctrl-names = "default"; | ||
+ | pinctrl-0 = <&pinctrl_lcdif_dat | ||
+ | &pinctrl_lcdif_ctrl>; | ||
+ | display = <&display>; | ||
+ | status = "disabled"; | ||
+ | [...] | ||
+ | }; | ||
+ | [...] | ||
+ | |||
+ | ==== stock u-boot image details ==== | ||
+ | With tools/dumpimage from u-boot master: | ||
+ | $ tools/dumpimage -l ../ntx-partitions-parser/partitions/bootloader.img | ||
+ | Image Type: Freescale IMX Boot Image | ||
+ | Image Ver: 2 (i.MX53/6/7 compatible) | ||
+ | Mode: DCD | ||
+ | Data Size: 401408 Bytes = 392.00 KiB = 0.38 MiB | ||
+ | Load Address: 877ff420 | ||
+ | Entry Point: 87800000 | ||
+ | |||
+ | ==== Building u-boot ==== | ||
+ | The following compiler version was used (it comes from Parabola): | ||
+ | $ pacman -Q -o arm-none-eabi-gcc | ||
+ | /usr/bin/arm-none-eabi-gcc is owned by arm-none-eabi-gcc 8.2.0-1 | ||
+ | |||
+ | Building: | ||
+ | export ARCH=arm | ||
+ | export CROSS_COMPILE=arm-none-eabi- | ||
+ | make mx6sll_e70q02_defconfig | ||
+ | make -j4 | ||
+ | |||
+ | Flashing: | ||
+ | fastboot flash bootloader u-boot.imx | ||
+ | |||
+ | Booting prompt: | ||
+ | eBR-1A # reset | ||
+ | resetting ... | ||
+ | |||
+ | |||
+ | U-Boot 2016.03-21136-g06b320c20e-dirty (Feb 21 2019 - 16:16:09 +0100) | ||
+ | |||
+ | CPU: Freescale i.MX6SLL rev1.1 996 MHz (running at 792 MHz) | ||
+ | CPU: Commercial temperature grade (0C to 95C) at 44C | ||
+ | Reset cause: WDOG | ||
+ | Board: MX6SLL LPDDR2 NTX | ||
+ | I2C: ready | ||
+ | DRAM: 512 MiB | ||
+ | __get_sd_number(),cfg23=0,cfg24=0 | ||
+ | MMC: board_mmc_init() : isd=0 | ||
+ | board_mmc_init() : wifi=2 | ||
+ | FSL_SDHC: 0, FSL_SDHC: 1 | ||
+ | In: serial | ||
+ | Out: serial | ||
+ | Err: serial | ||
+ | ntx_hw_early_init() 0 | ||
+ | ram p=80000000,size=536870912 | ||
+ | switch to partitions #0, OK | ||
+ | mmc0(part 0) is current device | ||
+ | mmc read 0x9ffffe00 0x3ff 0x1 | ||
+ | |||
+ | MMC read: dev # 0, block # 1023, count 1 ... 1 blocks read: OK | ||
+ | mmc read 0x9ffffe00 0x400 0x1 | ||
+ | |||
+ | MMC read: dev # 0, block # 1024, count 1 ... 1 blocks read: OK | ||
+ | ntx_hw_late_init() | ||
+ | mmc read 0x9ffffc00 0x1 0x1 | ||
+ | |||
+ | MMC read: dev # 0, block # 1, count 1 ... 1 blocks read: OK | ||
+ | NTXSN not avalible ! | ||
+ | ntx_gpio_get_value(402) : error parameter ! null ptr ! | ||
+ | ntx_config_fastboot_layout():10 binaries partition added | ||
+ | ntx_config_fastboot_layout():3 mbr partition added | ||
+ | check_and_clean: reg 0, flag_set 0 | ||
+ | Fastboot: Normal | ||
+ | Net: CPU Net Initialization Failed | ||
+ | No ethernet found. | ||
+ | Hit any key to stop autoboot: 0 | ||
+ | switch to partitions #0, OK | ||
+ | mmc0(part 0) is current device | ||
+ | mmc read 0x80800000 0x7ff 0x1 | ||
+ | |||
+ | MMC read: dev # 0, block # 2047, count 1 ... 1 blocks read: OK | ||
+ | kernel size = 5364784@80800000 | ||
+ | mmc read 0x80800000 0x800 0x28f5 | ||
+ | |||
+ | MMC read: dev # 0, block # 2048, count 10485 ... 10485 blocks read: OK | ||
+ | Booting from mmc ... | ||
+ | mmc read 0x83000000 0x505 0x1 | ||
+ | |||
+ | MMC read: dev # 0, block # 1285, count 1 ... 1 blocks read: OK | ||
+ | dtb size = 34761@83000000 | ||
+ | mmc read 0x83000000 0x506 0x49 | ||
+ | |||
+ | MMC read: dev # 0, block # 1286, count 73 ... 73 blocks read: OK | ||
+ | |||
+ | hwcfgp=9ffffe00,pcb=60,customer=9 | ||
+ | |||
+ | ntx_gpio_get_value(402) : error parameter ! null ptr ! | ||
+ | ESDin=0,UPGKey=-1,PWRKey=0,USBin=0x1,BootESD=0,MenuKey=0 | ||
+ | mmc read 0x9ffffc00 0x37ff 0x1 | ||
+ | |||
+ | MMC read: dev # 0, block # 14335, count 1 ... 1 blocks read: OK | ||
+ | mmc read 0x9fdc8a00 0x3800 0x11ba | ||
+ | |||
+ | MMC read: dev # 0, block # 14336, count 4538 ... 4538 blocks read: OK | ||
+ | mmc read 0x9fdc8800 0x405 0x1 | ||
+ | |||
+ | MMC read: dev # 0, block # 1029, count 1 ... 1 blocks read: OK | ||
+ | [WARNING] Binaries load sequence should Lo->Hi ! | ||
+ | mmc read 0x9fda8a00 0x406 0x100 | ||
+ | |||
+ | MMC read: dev # 0, block # 1030, count 256 ... 256 blocks read: OK | ||
+ | Kernel RAM visiable size=509M->509M | ||
+ | hwcfg rootfstype : 2 | ||
+ | hwcfg partition type : 2 | ||
+ | Kernel image @ 0x80800000 [ 0x000000 - 0x51dc30 ] | ||
+ | ## Flattened Device Tree blob at 83000000 | ||
+ | Booting using the fdt blob at 0x83000000 | ||
+ | Using Device Tree in place at 83000000, end 8300b7c8 | ||
+ | |||
+ | Starting kernel ... | ||
+ | |||
+ | === Devices described in code but not present on the PCB? === | ||
+ | ==== [https://framagit.org/imx-e-readers/linux/raw/kobo-aura-h2o-edition2/linux-4.1.15-fsl-base/arch/arm/boot/dts/imx6sll-e60qm2.dts imx6sll-e60qm2.dts] ==== | ||
+ | * No HALL sensor? | ||
+ | * No mmc LEDS? | ||
+ | * No mmc/SD on mmc1 | ||
+ | |||
+ | == Hardware versions and revisions == | ||
+ | The hardware reviewed here had imx6sll-e60qm2.dts, but similarly looking dts are in the vendor Linux source code. | ||
+ | |||
+ | Some hardware components with critical impact on freedom are not described in the devicetree such as: | ||
+ | * The WiFi chip: however no other WiFi drivers are in the kernel configuration and the WiFi driver is an external driver with source code. | ||
+ | |||
+ | Because of that we cannot know in advance if the variants are also good for freedom, without looking at them physically or inferring it from other sources such as the kernel configuration. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! dts | ||
+ | ! Differences with imx6sll-e60qm2.dts | ||
+ | ! Comments | ||
+ | |- | ||
+ | | | ||
+ | * imx6sll-e60k02.dts | ||
+ | | | ||
+ | Small differences: | ||
+ | * it uses imx6sll-ntx.dtsi instead of imx6sll-ntx_emmc.dtsi which only difference is to invert the order of the usdhc busses | ||
+ | * there are some pinmux and GPIO configuration differences | ||
+ | * there seem to be some differences with the eMMC (maybe it's connected on another usdhc bus) | ||
+ | * other very small differences | ||
+ | | | ||
+ | |- | ||
+ | | | ||
+ | * imx6sll-e60ql2.dts | ||
+ | | | ||
+ | Big differences: | ||
+ | * It uses an elan touchscreen (compatible = "elan,elan-touch";) and the driver is built in the kernel we have. The driver used doesn't seem to be able to load a firmware. However it can get the touchscreen builtin firmware version. | ||
+ | * It contains a different power management chip (compatible = "fiti,fp9928";) for the display ("EPDC PMIC I2C address"). | ||
+ | Small differences: | ||
+ | * it uses imx6sll-ntx.dtsi instead of imx6sll-ntx_emmc.dtsi which only difference is to invert the order of the usdhc busses | ||
+ | * there are some pinmux and GPIO configuration differences | ||
+ | * there seem to be some differences with the eMMC (maybe it's connected on another usdhc bus) | ||
+ | * other very small differences | ||
+ | | TODO: Look in u-boot if there is a driver for the EPDC PMIC. | ||
+ | |- | ||
+ | | | ||
+ | * imx6sll-e60qp2.dts | ||
+ | | | ||
+ | Small differences: | ||
+ | * there are some pinmux and GPIO configuration differences | ||
+ | * there seem to be some differences with the eMMC (maybe it's connected on another usdhc bus) | ||
+ | * other very small differences | ||
+ | Big differences: | ||
+ | * It uses another touchscreen (compatible = "neonode,zforce-ir-touch";) and the driver is built in the kernel we have. The driver used doesn't seem to be able to load a firmware. However it can get the touchscreen builtin firmware version. | ||
+ | | | ||
+ | |- | ||
+ | | | ||
+ | * imx6sll-e70q02.dts | ||
+ | | | ||
+ | Big differences: | ||
+ | * It uses a different procimity sensor (compatible = "si,si114x-als";). The driver doesn't load any firmware. | ||
+ | * It uses an elan touchscreen (compatible = "elan,elan-touch";) and the driver is built in the kernel we have. The driver used doesn't seem to be able to load a firmware. However it can get the touchscreen builtin firmware version. | ||
+ | Small differences: | ||
+ | * there are some pinmux and GPIO configuration differences | ||
+ | * there seem to be some differences with the eMMC (maybe it's connected on another usdhc bus) | ||
+ | * other very small differences | ||
+ | | | ||
+ | |- | ||
+ | | | ||
+ | * imx6sll-t05r02.dts | ||
+ | | | ||
+ | |||
+ | |||
+ | Big differences: | ||
+ | * It has an accelerator (compatible = "si,si114x-als";). The driver used doesn't seem to be able to load a firmware. | ||
+ | * It uses an elan touchscreen (compatible = "elan,elan-touch";) and the driver is built in the kernel we have. The driver used doesn't seem to be able to load a firmware. However it can get the touchscreen builtin firmware version. | ||
+ | Small differences: | ||
+ | * there are some pinmux and GPIO configuration differences | ||
+ | * there seem to be some differences with the eMMC (maybe it's connected on another usdhc bus) | ||
+ | * other very small differences | ||
+ | | | ||
+ | |- | ||
+ | | | ||
+ | * imx6sll-evk-btwifi.dts | ||
+ | * imx6sll-evk.dts | ||
+ | * imx6sll-evk-reva.dts | ||
+ | | | ||
+ | | Probably NXP evaluation boards. Not work investigating here. | ||
+ | |- | ||
+ | | | ||
+ | * imx6sll-lpddr2-arm2.dts | ||
+ | * imx6sll-lpddr2-ntx.dts | ||
+ | * imx6sll-lpddr3-arm2-csi.dts | ||
+ | * imx6sll-lpddr3-arm2.dts | ||
+ | * imx6sll-lpddr3-arm2-ecspi.dts | ||
+ | * imx6sll-lpddr3-arm2-spdif.dts | ||
+ | | | ||
+ | | Probably evaluation boards related dts. Not work investigating here. | ||
+ | |- | ||
+ | |} | ||
== Software == | == Software == | ||
Line 199: | Line 1,189: | ||
eBR-1A # | eBR-1A # | ||
− | ==== | + | ==== u-boot environment ==== |
− | + | Here's the u-boot environment: | |
− | eBR-1A # mmc | + | eBR-1A # printenv |
− | + | baudrate=115200 | |
− | + | bootcmd=mmc dev ${mmcdev};if run loadimage; then run mmcboot; fi; | |
+ | bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr}; | ||
+ | bootdelay=1 | ||
+ | bootscript=echo Running bootscript from mmc ...; source | ||
+ | console=ttymxc0 | ||
+ | epdc_waveform=epdc_splash.bin | ||
+ | fastboot_dev=mmc0 | ||
+ | fdt_addr=0x83000000 | ||
+ | fdt_file=undefined | ||
+ | fdt_high=0xffffffff | ||
+ | image=zImage | ||
+ | initrd_addr=0x83800000 | ||
+ | initrd_high=0xffffffff | ||
+ | ip_dyn=yes | ||
+ | loadaddr=0x80800000 | ||
+ | loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script}; | ||
+ | loadfdt=load_ntxdtb | ||
+ | loadimage=load_ntxkernel | ||
+ | mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" | ||
+ | mmcargs=setenv bootargs console=${console},${baudrate} rootwait rw no_console_suspend | ||
+ | mmcautodetect=no | ||
+ | mmcboot=echo Booting from mmc ...; run mmcargs; if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; | ||
+ | mmcdev=0 | ||
+ | mmcpart=1 | ||
+ | script=boot.scr | ||
+ | stderr=serial | ||
+ | stdin=serial | ||
+ | stdout=serial | ||
+ | |||
+ | Environment size: 1203/8188 bytes | ||
+ | |||
+ | ==== u-boot booting process ==== | ||
+ | Here the u-boot boot process in uncomon and relies on custom commands like load_ntxkernel to load and execute the Linux kernel and associated data like the dtb: | ||
+ | bootcmd=mmc dev ${mmcdev};if run loadimage; then run mmcboot; fi; | ||
+ | loadimage=load_ntxkernel | ||
+ | ==== Adding extra kernel commandline arguments ==== | ||
+ | You can do that in u-boot by overriding mmcargs | ||
+ | setenv mmcargs setenv bootargs <your extra arguments> console=\${console},\${baudrate} rootwait rw no_console_suspend | ||
+ | |||
+ | === Stock OS analysis === | ||
+ | * The default OS forces the user to register or use some network services like Kobo, google, facebook, etc, however we can get a shell through the serial port. | ||
− | + | ==== Source code ==== | |
− | + | * Some [https://github.com/kobolabs/Kobo-Reader/blob/master/hw/imx6sll-aurah2o2-aura/kernel.tar.bz2?raw=true Heavily modified Linux 4.1.15 source code] is provided by Kobo for this device. It is most probably based on an unknown branch in Freescale's fork of Linux for I.MX system on a chip. | |
− | + | * The [https://github.com/kobolabs/Kobo-Reader/blob/master/hw/imx6sll-aurah2o2-aura/wifi.tgz?raw=true WiFi driver source code] is also provided by Kobo for this device. | |
− | + | * Some less interesting userspace source code is probably also provided at the same location. | |
− | + | ==== Linux 4.1.15 sources ==== | |
+ | New sources for Linux seem to have been pushed the 30 April: | ||
+ | * They don't contain all the build scripts that the 3.0.35 did | ||
+ | * They use the devicetre | ||
+ | * They were compiled with gcc 5.3.0 | ||
+ | * Parabola's community/arm-none-eabi-gcc isn't able to compile it, however pcr/crosstool-ng can be installed and used to create an arm baremetal 5.4.0 gcc which is able to compile it. | ||
− | To | + | ===== How to build ===== |
− | + | ====== Getting the kernel configuration and device tree source file name ====== | |
− | + | To build it for the device we need: | |
+ | * A configuration file, hopefully in my case it can be exrtacted from the device by running the following on the device: | ||
+ | # zcat /proc/config.gz | ||
+ | * To identify which device tree source file was used if we want to avoid reusing the one that is in the eMMC | ||
− | + | We can start by looking the machine name: | |
− | + | # grep . /sys/firmware/devicetree/base/* | |
[...] | [...] | ||
− | + | /sys/firmware/devicetree/base/compatible:fsl,imx6sll-lpddr3-arm2 | |
− | + | /sys/firmware/devicetree/base/compatible:fsl,imx6sll | |
− | + | /sys/firmware/devicetree/base/model:Freescale i.MX6SLL NTX Board | |
− | |||
− | + | And grepping in the source to see the matching files: | |
− | + | $ grep "Freescale i.MX6SLL NTX Board" -r arch/arm/boot/dts/* | |
− | + | arch/arm/boot/dts/imx6sll-e60k02.dts: model = "Freescale i.MX6SLL NTX Board"; | |
− | + | arch/arm/boot/dts/imx6sll-e60ql2.dts: model = "Freescale i.MX6SLL NTX Board"; | |
− | + | arch/arm/boot/dts/imx6sll-e60qm2.dts: model = "Freescale i.MX6SLL NTX Board"; | |
− | + | arch/arm/boot/dts/imx6sll-e60qp2.dts: model = "Freescale i.MX6SLL NTX Board"; | |
− | + | arch/arm/boot/dts/imx6sll-e70q02.dts: model = "Freescale i.MX6SLL NTX Board"; | |
− | + | arch/arm/boot/dts/imx6sll-lpddr2-ntx.dts: model = "Freescale i.MX6SLL NTX Board"; | |
− | + | arch/arm/boot/dts/imx6sll-t05r02.dts: model = "Freescale i.MX6SLL NTX Board"; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Then on my board I've the 'cyttsp5' touchscreen controller: | |
− | * | + | # cd /sys/bus/i2c/devices |
+ | # grep . 0-*/name 1-*/name 2-*/name | ||
+ | 0-0036/name:lm3630a_bl | ||
+ | 1-0024/name:cyttsp5_i2c_adapter | ||
+ | 1-0068/name:tps6518x | ||
+ | 2-0032/name:ricoh619 | ||
− | + | Now only two files are remainign: | |
− | * | + | $ grep "cyttsp5_i2c_adapter" $(grep "Freescale i.MX6SLL NTX Board" -r arch/arm/boot/dts/* | sed 's#:.*##') |
− | + | arch/arm/boot/dts/imx6sll-e60k02.dts: compatible = "cy,cyttsp5_i2c_adapter"; | |
+ | arch/arm/boot/dts/imx6sll-e60k02.dts: cy,adapter_id = "cyttsp5_i2c_adapter"; | ||
+ | arch/arm/boot/dts/imx6sll-e60qm2.dts: compatible = "cy,cyttsp5_i2c_adapter"; | ||
+ | arch/arm/boot/dts/imx6sll-e60qm2.dts: cy,adapter_id = "cyttsp5_i2c_adapter"; | ||
− | + | It is possible to visualize the difference between both files in a very convenient way like this: | |
− | + | $ meld arch/arm/boot/dts/imx6sll-e60k02.dts arch/arm/boot/dts/imx6sll-e60qm2.dts | |
− | + | It shows quite some difference in the way the system on a chip pins are configured. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | For instance for arch/arm/boot/dts/imx6sll-e60qm2.dts we have: | |
+ | pinctrl_elan_ts_gpio_sleep: elan_ts_gpio_grp_sleep { | ||
+ | fsl,pins = < | ||
+ | MX6SLL_PAD_SD1_DATA3__GPIO5_IO06 0x10059 /* TP_INT */ | ||
+ | MX6SLL_PAD_SD1_DATA2__GPIO5_IO13 0x10059 /* TP_RST */ | ||
+ | >; | ||
+ | }; | ||
− | + | and for arch/arm/boot/dts/imx6sll-e60k02.dts we have: | |
+ | pinctrl_elan_ts_gpio: elan_ts_gpio_grp { | ||
+ | fsl,pins = < | ||
+ | MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x17059 /* TP_INT */ | ||
+ | MX6SLL_PAD_GPIO4_IO18__GPIO4_IO18 0x10059 /* TP_RST */ | ||
+ | MX6SLL_PAD_GPIO4_IO17__GPIO4_IO17 0x10059 /* TP_SWDIO */ | ||
+ | >; | ||
+ | }; | ||
− | + | Fortunately the Linux kernel exports that information at runtime, and we can access it like that: | |
− | + | # mount -t debugfs none /sys/kernel/debug/ | |
− | + | # cd /sys/kernel/debug/pinctrl | |
− | |||
− | |||
− | + | After grepping we can see the following line in pinctrl-handles: | |
+ | type: MUX_GROUP controller 20e0000.iomuxc group: elan_ts_gpio_grp (34) function: imx6sll-lpddr3-arm2 | ||
+ | type: CONFIGS_PIN controller 20e0000.iomuxc pin MX6SLL_PAD_GPIO4_IO24 (147) 00017059 | ||
+ | type: CONFIGS_PIN controller 20e0000.iomuxc pin MX6SLL_PAD_GPIO4_IO18 (146) 00010059 | ||
+ | type: CONFIGS_PIN controller 20e0000.iomuxc pin MX6SLL_PAD_GPIO4_IO17 (149) 00010059 | ||
− | + | Note that to open pinctrl-handles with a text editor on the device you need to copy it somewhere first, like in /tmp/ | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | In my case the device tree file that works for my hardware is the arch/arm/boot/dts/imx6sll-e60qm2.dts | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | ==== | + | ==== kernel logs ==== |
* [[Group:Hardware/Freest/e-readers/Aura_H2O_Edition_2/boot_log_Bienvenue_sur_Kobo_!|First Boot]] | * [[Group:Hardware/Freest/e-readers/Aura_H2O_Edition_2/boot_log_Bienvenue_sur_Kobo_!|First Boot]] | ||
+ | * [[Group:Hardware/Freest/e-readers/Aura_H2O_Edition_2/boot_dmesg_01|dmesg after boot]] | ||
+ | * [[Group:Hardware/Freest/e-readers/Aura_H2O_Edition_2/boot_wifi_cleaned_01|dmesg after wifi modules loading]] | ||
+ | |||
+ | ==== runtime informations ==== | ||
+ | Here's the kernel version of the device I got: | ||
+ | # uname -r | ||
+ | 4.1.15-00104-gcd6a6a6 | ||
+ | |||
+ | The boot kernel parameters are available in /proc/cmdline: | ||
+ | console=ttymxc0,115200 rootwait rw no_console_suspend hwcfg_p=0x9ffffe00 hwcfg_sz=110 waveform_p=0x9fdc8a00 waveform_sz=2323160 ntxfw_p=0x9fdc6400 ntxfw_sz=9474 mem=509M boot_port=0 rootfstype=ext4 root=/dev/mmcblk0p1 quiet | ||
+ | |||
+ | * The kernel configuration is available at /proc/config.gz | ||
+ | * The device uses a devicertee that is passed by the bootloader: | ||
+ | # grep . /sys/firmware/devicetree/base/* | ||
+ | [...] | ||
+ | /sys/firmware/devicetree/base/compatible:fsl,imx6sll-lpddr3-arm2 | ||
+ | /sys/firmware/devicetree/base/compatible:fsl,imx6sll | ||
+ | /sys/firmware/devicetree/base/model:Freescale i.MX6SLL NTX Board | ||
− | ==== main | + | === Running Parabola === |
− | + | ||
+ | The rootfs partitions are too small to install Parabola (They are 256M each), thankfully we have a big partition (6.8G) that is formatted as FAT. But we cannot easily use this as the bootloader boot command uses "root=/dev/mmcblk0p1" and we don't want to require users to use the serial console as it would require soldering. | ||
+ | |||
+ | A way to deal with that would be to set the fat partition as mmcblk0p1. This is possible since we can force the device to go in fastboot mode and overwrite the MBR that way. | ||
+ | |||
+ | ==== Changing partition order ==== | ||
+ | |||
+ | First dump the MBR in mbr1.img as described in this page. | ||
+ | |||
+ | Then change the partitions orders. | ||
+ | |||
+ | sfdisk -d mbr.img > mbr.txt | ||
+ | The following will be in mbr.txt: | ||
+ | mbr1.img1 : start= 49152, size= 524289, type=83 | ||
+ | mbr1.img2 : start= 573441, size= 524289, type=83 | ||
+ | mbr1.img3 : start= 1097730, size= 14139389, type=b | ||
+ | You can change it to: | ||
+ | mbr.img2 : start= 49152, size= 524289, type=83 | ||
+ | mbr.img3 : start= 573441, size= 524289, type=83 | ||
+ | mbr.img1 : start= 1097730, size= 14139389, type=b | ||
+ | |||
+ | Then we recreate a new mbr: | ||
+ | qemu-img create -f raw tmp.img 8G | ||
+ | sfdisk -f tmp.img < mbr.txt | ||
+ | dd if=tmp.img of=mbr2.img count=1 | ||
+ | rm tmp.img | ||
+ | |||
+ | We can then flash that: | ||
+ | fastboot flash mbr mbr2.img | ||
+ | |||
+ | TODO: | ||
+ | * Find if it's still possible to trigger the mount of the partition from the stock OS (which doesn't require a serial port) | ||
+ | |||
+ | ==== Serial console with OpenRC ==== | ||
+ | Then you can install OpenRC as systemd won't work with the default kernel unless you recompile it (systemd requires cgroups) | ||
+ | |||
+ | To get a serial console follow this guide https://wiki.gentoo.org/wiki/OpenRC#openrc-init | ||
+ | and also add ttymxc0 to /etc/securetty | ||
+ | |||
+ | You also need to create a file at /etc/conf.d/agetty.ttymxc0 with this content: | ||
+ | # make agetty quiet | ||
+ | #quiet="yes" | ||
+ | |||
+ | # Set the baud rate of the terminal line | ||
+ | baud="115200" | ||
+ | |||
+ | # set the terminal type | ||
+ | term_type="linux" | ||
+ | |||
+ | # extra options to pass to agetty for this port | ||
+ | agetty_options="" | ||
+ | else the console will use 38400 bauds while it is at 115200 during the boot. | ||
+ | |||
+ | ==== Stock kernel and modules modules ==== | ||
+ | To use the stock kernel and modules seamlessly do: | ||
+ | mkdir -p /lib/modules/4.1.15-00104-gcd6a6a6/kernel/drivers/ | ||
+ | If the stock rootfs is mounted on /mnt you can just copy them that way: | ||
+ | cp -r /mnt/drivers/mx6sll-ntx/usb/ /lib/modules/4.1.15-00104-gcd6a6a6/kernel/drivers/ | ||
+ | cp -r /mnt/drivers/mx6sll-ntx/wifi/ /lib/modules/4.1.15-00104-gcd6a6a6/kernel/drivers/ | ||
+ | touch /lib/modules/4.1.15-00104-gcd6a6a6/modules.order | ||
+ | touch /lib/modules/4.1.15-00104-gcd6a6a6/modules.builtin | ||
+ | depmod -a | ||
+ | Then you can use them as usual, for instance to get usbnet you could do: | ||
+ | modprobe g_ether | ||
+ | |||
+ | |||
+ | |||
+ | === Making the display work === | ||
+ | |||
+ | TODO: | ||
+ | * The display was only validated with 1fps with Xorg and xfce4. | ||
+ | * We need to check if the [https://linux-libre.fsfla.org/pub/linux-libre/releases/4.1.15-gnu/ linux-libre patch] applies to this vendor kernel | ||
+ | |||
+ | To enable the display: | ||
+ | * Build [https://framagit.org/imx-e-readers/linux/commits/kobo-aura-h2o-edition2/linux-4.1.15-fsl-base the patched vendor kernel] that has CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE=y enabled and the dependency on nonfree display binaries removed. | ||
+ | * Once the device booted under Parabola, run the following program: | ||
+ | |||
+ | /* | ||
+ | * Copyright (C) 2019 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | ||
+ | * | ||
+ | * This program is free software: you can redistribute it and/or modify | ||
+ | * it under the terms of the GNU General Public License as published by | ||
+ | * the Free Software Foundation, either version 3 of the License, or | ||
+ | * (at your option) any later version. | ||
+ | * | ||
+ | * This program is distributed in the hope that it will be useful, | ||
+ | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
+ | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
+ | * GNU General Public License for more details. | ||
+ | * | ||
+ | * You should have received a copy of the GNU General Public License | ||
+ | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
+ | */ | ||
+ | |||
+ | #include <errno.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <stdio.h> | ||
+ | #include <string.h> | ||
+ | #include <stropts.h> | ||
+ | #include <stdint.h> | ||
+ | #include <asm/ioctls.h> | ||
+ | |||
+ | #define AUTO_UPDATE_MODE_AUTOMATIC_MODE 1 | ||
+ | #define MXCFB_SET_AUTO_UPDATE_MODE _IOW('F', 0x2D, uint32_t) | ||
+ | |||
+ | static int set_auto_update(int fd) | ||
+ | { | ||
+ | int ret; | ||
+ | int mode = AUTO_UPDATE_MODE_AUTOMATIC_MODE; | ||
+ | |||
+ | ret = ioctl(fd, MXCFB_SET_AUTO_UPDATE_MODE, &mode); | ||
+ | if (ret < 0) { | ||
+ | int err = errno; | ||
+ | printf("ioctl error: %s\n", strerror(err)); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int fd = open("/dev/fb0", 0); | ||
+ | if (fd < 0) { | ||
+ | int err = errno; | ||
+ | printf("open error: %s\n", strerror(err)); | ||
+ | } | ||
+ | set_auto_update(fd); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | * Run Xorg -retro or startxfce4 as root | ||
+ | * Touch the screen, the cursor will move (not at the location of the touch though) | ||
+ | |||
+ | By default the display orientation is in landscape mode. | ||
+ | |||
+ | === Making the touchscreen work === | ||
+ | The input orientation can be adjusted to match the display landscape mode with: | ||
+ | xinput set-prop "cyttsp5_mt" "Coordinate Transformation Matrix" -1 0 1 0 -1 1 0 0 1 | ||
+ | |||
+ | See the following links for more information on how to compute the coordinate transformation matrix: | ||
+ | * https://unix.stackexchange.com/questions/138168/matrix-structure-for-screen-rotation | ||
+ | * https://en.wikipedia.org/wiki/File:2D_affine_transformation_matrix.svg | ||
+ | * https://en.wikipedia.org/wiki/Matrix_multiplication | ||
+ | |||
+ | To come up with that number I computed a translation to the origin multiplicated by a half-circle rotation which was transleted again to 1/2 width, 1/2 height coordinates. | ||
+ | |||
+ | That didn't work however replacing the width and height by 1 in the final matrix worked (and gave the command above). I probably did a sign error somewhere in the calculation. | ||
+ | |||
+ | === Linux upstream TODO === | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Driver or chip | ||
+ | ! Devicetree | ||
+ | ! Driver or comments | ||
+ | |- | ||
+ | | Base hardware | ||
+ | | Sent upstream: | ||
+ | * [https://www.spinics.net/lists/devicetree/msg308583.html ARM: dts: imx6sll: Add the Kobo Aura H2O Edition 2]: Awaiting review at the time of writing | ||
+ | * [https://www.spinics.net/lists/devicetree/msg308584.html dt-bindings: arm: fsl: Add the Kobo Aura H2O Edition 2]: [https://www.spinics.net/lists/devicetree/msg308716.html Acked by a maintainer] | ||
+ | | TODO: | ||
+ | * <s>Validate the basic PMIC support (power off, reboot, regulators)</s> DONE | ||
+ | * <s>Send the DTS upstream</s> DONE | ||
+ | |- | ||
+ | | GPIO button | ||
+ | | | ||
+ | | Understand how it's connected and how it interferes with the PMIC, and why it works in u-boot | ||
+ | |- | ||
+ | | cyttsp5 touchscreen+button+proximity driver | ||
+ | | | ||
+ | | | ||
+ | * Find the exact chip used | ||
+ | * Look if it's supported by drivers/input/touchscreen/cyttsp* | ||
+ | |- | ||
+ | | Ricoh RC5T619: Driver present for: | ||
+ | * regulators | ||
+ | * watchdog timer | ||
+ | * RTC (since 5.7-rc1 | ||
+ | * ADC (since 5.7-rc1, can also read battery voltage) | ||
+ | | | ||
+ | | Missing: | ||
+ | * Battery charger / (gauge?) | ||
+ | * power button | ||
+ | * GPIOs | ||
+ | |- | ||
+ | | TPS 6518? | ||
+ | | | ||
+ | | It might be possible to integrate it in similar already existing drivers or make one line in: | ||
+ | * drivers/mfd/tps* | ||
+ | |- | ||
+ | | TI lm3630 backlight driver | ||
+ | | | ||
+ | | | ||
+ | |- | ||
+ | | NXP/Freescale epdc (e-paper display controller) | ||
+ | | TODO | ||
+ | | TODO | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | == Enabling people to easily install and backup a rootfs == | ||
+ | |||
+ | Without serial we only have access to fastboot which only support booting an image, flashing an image or rebooting the device<ref>From the vendor u-boot in drivers/fastboot/fastboot.c we have: "fastboot main process, only support 'download', 'flash' 'reboot' command now"</ref>. | ||
+ | |||
+ | So with that we need to find a way to backup and/or install a distribution on the device that people can easily use. | ||
+ | |||
+ | We have several approaches for that: | ||
+ | * Modify the u-boot environment from adb. This is the most simple way but it's dangerous. | ||
+ | * Create a rootfs that has to fit in RAM, so it needs to be less than 512M | ||
+ | |||
+ | === Distributions === | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
− | | | + | ! Distribution |
− | | | + | ! Type |
− | | | + | ! Size |
− | | | + | ! Verdict |
− | |- | + | |- |
− | | | + | | Parabola arm with openssh, ddrescue, vim |
− | | | + | | initramfs |
− | | | + | | 899M |
− | | | + | | Cannot fit into the RAM even as an XZ compressed initramfs as the kernel would have to decompress it anyway. |
+ | |- | ||
+ | | Parabola arm with openssh, ddrescue, vim | ||
+ | | squashfs with -comp xz | ||
+ | | 408M | ||
+ | | May fit, needs testing | ||
+ | |- | ||
+ | | Parabola arm with openssh, ddrescue, vim | ||
+ | | squashfs with -comp lzo | ||
+ | | 465M | ||
+ | | May fit, needs testing | ||
+ | |- | ||
+ | | Parabola arm with openssh, ddrescue, vim | ||
+ | | xz compressed intramfs and Linux with CONFIG_ZSWAP (LZO compression) | ||
+ | | | ||
+ | | May work, need testing | ||
+ | |- | ||
+ | | LibreCMC | ||
+ | | Allwinner A1x/A20/A3x | ||
+ | | | ||
+ | | | ||
|- | |- | ||
− | | | + | | LibreCMC |
− | | | + | | Allwinner A1x/A20/A3x |
− | | | + | | |
− | | | + | | Needs an external kernel |
|- | |- | ||
− | | | + | | LibreCMC |
− | | | + | | QEMU ARM Virtual Machine |
− | | | + | | |
− | | | + | | |
+ | * Needs an external kernel | ||
+ | * Easier to test in a vm | ||
|- | |- | ||
|} | |} | ||
− | === | + | === References === |
− | + | ||
− | + | <references/> | |
== Manufacturer informations == | == Manufacturer informations == | ||
* [https://kbdownload1-a.akamaihd.net/magento/userguides/downloads/KoboAuraH2O-ed2/KoboAuraH2O-Edition2-userguide_EN.pdf Device manual] | * [https://kbdownload1-a.akamaihd.net/magento/userguides/downloads/KoboAuraH2O-ed2/KoboAuraH2O-Edition2-userguide_EN.pdf Device manual] | ||
+ | |||
+ | == Other informations == | ||
+ | * See [[Group:Hardware/Freest/e-readers#e-reader_specific_projects_and_distributions]] for pointers to other projects, distributions, and software made for such e-readers | ||
+ | * https://framagit.org/imx-e-readers/ some of the source code used in this analysis | ||
+ | * Other people are working on I.MX Kobo too: https://www.spinics.net/lists/devicetree/msg311574.html |
Latest revision as of 16:59, 14 March 2023
Contents
- 1 Warnings
- 2 Reviewed devices
- 3 Issues found so far
- 4 Priority investigations
- 5 Firmwares
- 6 External interfaces
- 7 Internal interfaces
- 8 PCB
- 9 Hardware versions and revisions
- 10 Software
- 11 Enabling people to easily install and backup a rootfs
- 12 Manufacturer informations
- 13 Other informations
Warnings
This page describe research done on the Kobo Aura H2O Edition 2 e-reader.
The instructions given here are meant for research purpose: they are intended to find out if the kobo Aura H2O Edition 2 can meet the Respect Your Freedom certification with an amount of work that is not too big.
This doesn't mean that merely following the instruction will automatically make the source code respect the Free software distributions guidelines or that the device would automatically respect the Respect Your Freedom certification.
So for instance the instructions that explain how to make the display work with free software are only meant to validate that part, and didn't necessarily remove unrelated nonfree software.
Reviewed devices
- So far only devices using the arch/arm/boot/dts/imx6sll-e60qm2.dts devicetree were reviewed.
Issues found so far
- The WiFi firmware is under the GPLv2 but lacks source code. It needs to be reverse engineered. Hopefully it is small and the CPU ISA is known.
Priority investigations
TODO
Urgent:
- e-paper display: validate its usability better if possible
- verify if nothing was missed
Extra verifications:
- u-boot source code: Read it to see if it loads any firmware
- Linux source code: Look at the dts and drivers again to spot if something was missed
- Hardware: describe the hardware better and look again if there is anything dodgy (unlikely to be missed with the software review though)
- check what driver/cards the free wifi firmwares work on
- Document the waveform data format
Later:
- Document how to do bootloader development (device recovery, usb boot, etc)
waveform
Findings:
- The waveform partition contains:
- a mxcfb_waveform_data_file struct header
- zero padding at the end
That header also contains some RAW data which seem to only contain waveform data:
- That data was analyzed with inkwave as shown below
- A quick look in mxc_epdc_v2_fb.c tend to indicate that there is only data in this waveform partition.
$ git clone https://github.com/fread-ink/inkwave $ cd inkwave && make $ ./inkwave -f wrf ../ntx-partitions-parser/partitions/waveform.img File size: 10485760 bytes Header info: Serial number: 6786 Run type: 0x11 | Unknown Manufacturer code: 0xba | Unknown Frontplane Laminate (FPL) platform: 0x0 | 2.0 Frontplane Laminate (FPL) lot: 208 Frontplane Laminate (FPL) size: 0x0 | Unknown Frontplane Laminate (FPL) rate: 0x85 | 85Hz Waveform version: 32 Waveform sub-version: 33 Waveform type: 0x51 | Unknown Waveform tuning bias: Unknown Waveform revision: 0 Adhesive run number: 25 Mode version: Unknown Number of modes in this waveform: 8 Number of temperature ranges in this waveform: 14 4 or 5-bits per pixel: 5 Modes: Unknown (no mode version specified)
ntxfw and hwcfg
Findings:
- hwcfg only contains hardware configuration data and a lot of zero padding
- ntxfw contains backlight tables, and some unknown extra data that is not described in structs and doesn't seem to be used. Backlight still work with the unknown data removed.
Tools:
Boot flow:
- u-boot loads that partition in memory and tells the kernel about it through kernel command line argument like ntxfw_p=<address> and ntxfw_sz=<size> in board/freescale/common/ntx_comm.c
- The kernel picks that up in arch/arm/mach-imx/common.c
ntxcfg test:
$ cp ntxfw.img ntxfw_cleaned.img $ dd if=/dev/zero of=ntxfw_cleaned.img seek=1427 bs=1 count=129133 conv=notrunc # zero out all the data outside of struct $ echo -n '<--NTXFW}' | dd of=ntxfw_cleaned.img bs=1 seek=9464 count=9 conv=notrunc # Add the footer signature just in case
Result: $ hexdump -C ntxfw_cleaned.img | sed 's#^# #'
00000000 7b 4e 54 58 46 57 2d 2d 3e 00 45 36 30 51 4d 32 |{NTXFW-->.E60QM2| 00000010 00 5b 25 64 5d 3d 25 64 0a 00 00 00 00 03 00 00 |.[%d]=%d........| 00000020 00 25 73 20 67 6f 74 20 25 64 00 00 00 00 02 00 |.%s got %d......| 00000030 00 00 00 00 ff fc 5c c5 5c c5 cf ff 78 56 34 12 |......\.\...xV4.| 00000040 06 00 00 00 10 00 00 00 45 36 30 51 4d 32 5f 64 |........E60QM2_d| 00000050 75 61 6c 66 6c 5f 68 64 72 5f 31 36 31 31 31 36 |ualfl_hdr_161116| 00000060 00 00 00 00 00 00 00 00 00 00 00 00 0b 00 00 00 |................| 00000070 0a 05 00 00 00 00 00 00 00 00 00 00 ff fc 5c c5 |..............\.| 00000080 5c c5 cf ff 78 56 34 12 07 00 00 00 44 24 00 00 |\...xV4.....D$..| 00000090 45 36 30 51 4d 32 5f 64 75 61 6c 66 6c 5f 74 61 |E60QM2_dualfl_ta| 000000a0 62 5f 31 36 31 31 31 36 00 00 00 00 00 00 00 00 |b_161116........| 000000b0 00 00 00 00 54 30 00 00 00 00 00 00 00 00 00 00 |....T0..........| 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000d0 00 00 00 00 00 00 00 00 36 47 54 5b 62 6a 71 78 |........6GT[bjqx| 000000e0 7d 83 87 8b 8e 90 93 95 97 99 9b 9d 9f a2 a4 a7 |}...............| 000000f0 a9 ab b0 b2 b4 b5 b6 b8 ba bb bd bf c0 c1 c2 c3 |................| 00000100 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 |................| 00000110 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 |................| 00000120 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 |................| 00000130 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 00 00 00 |................| 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000260 00 00 00 00 00 00 00 00 02 05 00 00 e7 05 00 00 |................| 00000270 b6 06 00 00 59 07 00 00 fb 07 00 00 18 09 00 00 |....Y...........| 00000280 5d 0a 00 00 ce 0b 00 00 f3 0c 00 00 90 0e 00 00 |]...............| 00000290 ea 0f 00 00 62 11 00 00 8e 12 00 00 82 13 00 00 |....b...........| 000002a0 d2 14 00 00 b9 15 00 00 b7 16 00 00 f3 17 00 00 |................| 000002b0 57 1a 00 00 57 1a 00 00 79 1b 00 00 9f 1d 00 00 |W...W...y.......| 000002c0 33 1f 00 00 85 21 00 00 71 23 00 00 2e 25 00 00 |3....!..q#...%..| 000002d0 06 2c 00 00 e0 2e 00 00 7a 30 00 00 1e 32 00 00 |.,......z0...2..| 000002e0 68 33 00 00 ac 35 00 00 36 38 00 00 b2 39 00 00 |h3...5..68...9..| 000002f0 c2 3d 00 00 b0 40 00 00 18 42 00 00 3a 43 00 00 |.=...@...B..:C..| 00000300 14 46 00 00 86 47 00 00 e4 48 00 00 d2 4b 00 00 |.F...G...H...K..| 00000310 3a 4d 00 00 ec 4f 00 00 86 51 00 00 4c 54 00 00 |:M...O...Q..LT..| 00000320 96 55 00 00 ac 58 00 00 2c 5b 00 00 da 5c 00 00 |.U...X..,[...\..| 00000330 86 60 00 00 74 63 00 00 f4 65 00 00 e2 68 00 00 |.`..tc...e...h..| 00000340 a8 6b 00 00 aa 6e 00 00 48 71 00 00 2c 74 00 00 |.k...n..Hq..,t..| 00000350 10 77 00 00 7a 7b 00 00 04 7e 00 00 1e 82 00 00 |.w..z{...~......| 00000360 ee 84 00 00 f4 88 00 00 c4 8b 00 00 a6 90 00 00 |................| 00000370 8e 94 00 00 8a 98 00 00 9a 9c 00 00 82 a0 00 00 |................| 00000380 56 a4 00 00 34 a8 00 00 30 ac 00 00 58 b1 00 00 |V...4...0...X...| 00000390 2c b5 00 00 90 ba 00 00 a4 bf 00 00 dc c3 00 00 |,...............| 000003a0 08 ca 00 00 52 d0 00 00 4a d8 00 00 62 de 00 00 |....R...J...b...| 000003b0 a2 e4 00 00 1c ed 00 00 16 f3 00 00 82 fa 00 00 |................| 000003c0 02 02 01 00 8c 09 01 00 b8 0f 01 00 94 1a 01 00 |................| 000003d0 ec 21 01 00 5c 2a 01 00 44 33 01 00 4c 3a 01 00 |.!..\*..D3..L:..| 000003e0 12 47 01 00 9c 53 01 00 fa 5e 01 00 10 6c 01 00 |.G...S...^...l..| 000003f0 f4 78 01 00 d8 85 01 00 00 00 00 00 00 00 00 00 |.x..............| 00000400 54 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |T1..............| 00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000420 00 00 00 00 2a 43 4e 58 5f 67 6e 76 7a 7f 84 88 |....*CNX_gnvz...| 00000430 8a 8d 8f 92 94 96 98 9a 9c 9e a1 a3 a5 a8 ab ae |................| 00000440 b0 b1 b2 b4 b6 b7 b9 bb bc bd be bf c0 c1 c2 c3 |................| 00000450 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 |................| 00000460 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 |................| 00000470 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 |................| 00000480 f4 f5 f6 f7 f8 f9 fa fb 00 00 00 00 00 00 00 00 |................| 00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000004e0 00 00 00 00 00 00 00 00 00 00 00 00 05 01 01 02 |................| 000004f0 06 12 1b 10 2b 2e 2d 30 43 3f 42 44 45 45 47 4a |....+.-0C?BDEEGJ| 00000500 4c 56 4e 5b 5d 55 76 63 67 65 6a 69 64 6a 6b 73 |LVN[]Uvcgejidjks| 00000510 72 6a 69 72 71 73 76 76 7d 76 7c 75 7a 7d 7c 7a |rjirqsvv}v|uz}|z| 00000520 75 7b 78 77 7c 78 79 76 7f 80 85 80 86 80 86 86 |u{xw|xyv........| 00000530 89 88 89 8a 8a 89 8e 8f 93 94 93 93 94 9a 9a 9a |................| 00000540 9b 9c 9d 9d a0 a0 a2 a1 a2 a3 a3 a6 a6 a8 a8 aa |................| 00000550 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000024f0 00 00 00 00 00 00 00 00 3c 2d 2d 4e 54 58 46 57 |........<--NTXFW| 00002500 7d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |}...............| 00002510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 0001fe00
Firmwares
WiFi firmware
The WiFi driver rely on binary firmwares for the WiFi part.
The firmwares are provided as binary (in arrays format) in the hal/phydm/rtl8188f/halhwimg8188f_fw.c source code file, however this file is provided under the GPLv2. So it may be possible to convert the firmware binary in source code.
TODO:
- Add in this wiki the findings documented in the reverse engineering work Willem on this firmware.
- Investigate if the WiFi chip also has other functions (Bluetooth, FM Radio, etc)
- Investigate if the firmware source code can easily be reconstructed
- Investigate if the chip can work without the firmware
WiFi firmware informations found inside the driver
- The firmware binary is really uploaded to the device chip, see
hal/phydm/phydm_hwconfig.c:2730: READ_FIRMWARE_MP(8188F, _FW_NIC); hal/phydm/phydm_hwconfig.c:2764: READ_FIRMWARE_MP(8188F,_FW_NIC);
How to extract the firmware
There are generic tools to create a binary out of hex arrays, but it took me less time to write a specific program than to find such tool. I vaguely remember that one of theses tools was mentioned on a blog post on the sigrok blog, it was about something like reconstructing an I2S stream with 'unix way' tools.
usage:
$ gcc firmware_extraction_utility.c $ ./a.out > 8188F_FW_NIC.bin
The first 0x20 bytes are a header:
$ hexdump -C 8188F_FW_NIC.bin 00000000 f1 88 10 00 01 00 0e 00 03 25 14 55 62 52 02 00 |.........%.UbR..| 00000010 af 2f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |./..............|
And the rest is code:
00000020 02 86 a9 02 c7 d7 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 02 c0 2d 00 00 00 00 00 00 00 00 00 00 |.....-..........| 00000040 00 00 00 02 c8 29 00 00 00 00 00 00 00 00 00 00 |.....)..........| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000060 00 00 00 02 c7 d8 00 00 00 00 00 02 c2 f0 00 00 |................| 00000070 00 00 00 02 c8 28 00 00 00 00 00 00 00 00 00 00 |.....(..........| 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000000a0 02 87 b7 02 88 d5 02 80 86 02 80 89 02 a5 11 02 |................| [...]
The code can be extracted like that:
$ dd if=8188F_FW_NIC.bin of=code.bin skip=32 bs=1
It can then be analyzed with radare2 this way:
$ r2 -a 8051 -m 0x8000 ./code.bin # r2 comes from radare2, which is an interactive disassembler.
Then we can start using radare2:
$ r2 -a 8051 -m 0x8000 ./code.bin WARNING: using oba to load the syminfo from different mapaddress. TODO: Must use the API instead of running commands to speedup loading times. -- You haxor! Me jane? [0x00008000]> aaaa -AA [x] Analyze all flags starting with sym. and entry0 (aa) [x] Analyze function calls (aac) [x] find and analyze function preludes (aap) [x] Analyze len bytes of instructions for references (aar) [x] Check for objc references [x] Check for vtables [x] Finding xrefs in noncode section with anal.in=io.maps [x] Analyze value pointers (aav) [x] Value from 0x00008000 to 0x0000d262 (aav) [x] 0x00008000-0x0000d262 in 0x8000-0xd262 (aav) [Warning: No SN reg alias for current architecture. [x] Emulate code to find computed references (aae) [x] Type matching analysis for all functions (aaft) [x] Use -AA or aaaa to perform additional experimental analysis. [x] Enable constraint types analysis for variables [0x00008000]> pd / (fcn) fcn.00008000 181 | fcn.00008000 (); | ; CODE XREF from skip (+0x128) | ,=< 0x00008000 0286a9 ljmp 0x86a9 ,==< 0x00008003 02c7d7 ljmp 0xc7d7 || 0x00008006 00 nop || 0x00008007 00 nop || 0x00008008 00 nop || 0x00008009 00 nop || 0x0000800a 00 nop || 0x0000800b 00 nop || 0x0000800c 00 nop || 0x0000800d 00 nop || 0x0000800e 00 nop || 0x0000800f 00 nop || 0x00008010 00 nop || 0x00008011 00 nop || 0x00008012 00 nop ,===< 0x00008013 02c02d ljmp 0xc02d ||| 0x00008016 00 nop ||| 0x00008017 00 nop ||| 0x00008018 00 nop ||| 0x00008019 00 nop ||| 0x0000801a 00 nop ||| 0x0000801b 00 nop ||| 0x0000801c 00 nop ||| 0x0000801d 00 nop ||| 0x0000801e 00 nop ||| 0x0000801f 00 nop ||| 0x00008020 00 nop ||| 0x00008021 00 nop ||| 0x00008022 00 nop ,====< 0x00008023 02c829 ljmp 0xc829 |||| 0x00008026 00 nop |||| ; CODE XREF from skip (+0x1db) |||| 0x00008027 00 nop |||| 0x00008028 00 nop |||| 0x00008029 00 nop |||| 0x0000802a 00 nop |||| 0x0000802b 00 nop |||| 0x0000802c 00 nop |||| 0x0000802d 00 nop |||| 0x0000802e 00 nop |||| 0x0000802f 00 nop |||| 0x00008030 00 nop |||| ; CODE XREF from skip (+0x1dd) |||| 0x00008031 00 nop |||| 0x00008032 00 nop |||| 0x00008033 00 nop |||| 0x00008034 00 nop |||| 0x00008035 00 nop |||| 0x00008036 00 nop |||| 0x00008037 00 nop |||| 0x00008038 00 nop |||| 0x00008039 00 nop |||| 0x0000803a 00 nop |||| 0x0000803b 00 nop |||| 0x0000803c 00 nop |||| 0x0000803d 00 nop |||| 0x0000803e 00 nop |||| 0x0000803f 00 nop |||| 0x00008040 00 nop |||| 0x00008041 00 nop |||| 0x00008042 00 nop ,=====< 0x00008043 02c7d8 ljmp 0xc7d8 ||||| 0x00008046 00 nop ||||| 0x00008047 00 nop ||||| 0x00008048 00 nop ||||| 0x00008049 00 nop [0x00008000]>
- You can then jump to functions with s <address>
- You can continue listing code with s<address><enter> <enter>
Information on the WiFi firmware
WiFi Firmware ISA
- The firmware uses the 8051 instruction
- The entry point and load address is at 0x8000
Reverse engineering
- The driver has many comments about the firmware and processor that runs the firmware. That can help a lot.
- At the time of writing, Retdec README doesn't support the 8051 architecture yet:
Supported architectures (32b only): Intel x86, ARM, MIPS, PIC32, and PowerPC.
- Radare2 seem to work on the firmware and has some good auto-analyze functions
- The firmware is small:
$ du -hs 8188F_FW_NIC.bin 24K 8188F_FW_NIC.bin
firmware format
- it probably has a header and some calibration data at the begining
=> check the struct format
Touchscreen
cyttsp5
This should work without having to load any firmware.
Details:
- This driver can use the cyttsp5_fw.bin firmware
- The firmware seem optional at least in certain cases
- A firmware file cannot be found on the filesystem
- The support for loading the firmware is builtin the module but that could be because the vendor code has some issue without that code (like won't compile or similar)
- The touchscreen works in Parabola (with ntxfw partition blanked): tested with evtest /dev/input/event1
External interfaces
USB
Several interfaces are exposed through USB:
- It's possible to make the device switch to fastboot during boot
- If the device is not registered, you can switch to mass-storage by selecting "no wifi" during the device boot.
Power button
Some more research is needed to understand how exactly is connected the power button:
- It probably has to be connected to the PMIC to power up the device
- It's also connected to an I.MX GPIO, and it's possible to get the button value through that GPIO as well, under certain conditions.
Touchscreen
Internal interfaces
Serial/UART
As it can be seen on one of the PCB pictures, near the battery, there is some holes with some markings: V, TX, RX, and a ground sign. It seems that more recent manufacturing batch lacks such markings.
V |
|
TX |
|
RX |
|
GND | Ground |
The holes pitch are 2.54mm (0.1 inch), so it's compatible with most common pin-headers found in electronic shops like this one. The best is to use headers that are bent, this way:
- You could even be able to put back the cover if the pin headers height is small enough
- You can still easily use the e-book reader with the screen towards you while still having the serial port adapter plugged in.
Soldering on theses holes is tricky as there is some transparent plastic coating on all the PCB, including the internal connectors and the components. Under that there is the classic PCB coating (which is green here).
So I used some "grain 400" sand paper to remove the plastic and green coating on the serial port pin holes.
If you're not careful enough this will also expose the ground plane, making it harder to solder without any shorts.
For the ground connector, if you remove too much coating, it will make soldering harder as the big ground plane will dissipate your soldering iron heat, preventing you from melting the tin.
Also beware that the '3v3' pin is shorted to GND when the device is off (and is at 3.3V when the device is on). So even if it seems shorted to GND, it might not be.
You also need to choose how to solder the header:
- If the header pin goes on the battery side, then there won't be any risk of shorting the pins and if you manage to find a header that is the right size, it will stay better in place as the cable you will plug in can be exactly the size of the hole between the header and the battery. However you won't be able to close the cover anymore.
- If the header pin goes on the opposite side of the battery, then you will be able to close the cover, but you will need to make sure that the header, the cable (and possibly the serial adapter stay in a position where they cannot cause short circuit by having their metallic part touch some of the conductive part on the e-reader PCB.
I used the following equipment to do it:
- Lead free solder
- TS100 Soldering iron with the free software firmware at 450 Degrees
- A tip that is chisel-like but only one one side
- Tivoly "Métal Peint", grain 240 "sand paper"
Voltage | 3.3v |
Baudrate | 115200 |
Settings | 8N1 (the default almost everywhere) |
To get a shell you can login through the serial port with the user 'root':
(none) login: root [root@(none) ~]#
However once logged the console will probably freeze at some point. This is because the device has aggressive power management which makes the device goes into suspend.
To wake up the device, touching the screen is enough, however touching the screen all the time is not very convenient for development.
It seems to be an userspace application that makes the device goes into suspend. So we will overwrite /sys/power/state with a file that does nothing. We have ram filesystem mounted in /tmp, so we will use that to be saver (as it will not make permanent modifications):
[root@(none) ~]# mount [...] none on /tmp type tmpfs (rw,relatime,size=16384k) [...]
We can overwrite /sys/power/state like that:
[root@(none) ~]# touch /tmp/state [root@(none) ~]# mount -o bind /tmp/state /sys/power/state
This effectively prevent the device from going into suspend.
main storage
Partitions
With fdisk or by looking in /proc/partition we can see 3 partitions:
partition | size | function | source |
---|---|---|---|
mmcblk0p1 | 256M | rootfs | cat /proc/cmdline: root=/dev/mmcblk0p1 |
mmcblk0p2 | 256M | Backup rootfs ? | after mounting it, there are some similar files. Strangely there are no kernel modules in this one. |
mmcblk0p3 | 6.8G | user data | mount: /dev/mmcblk0p3 on /mnt/onboard type vfat |
However if we look at update scripts or fastboot we have more partitions:
name | start | size (from fastboot) | function | source |
---|---|---|---|---|
mbr | 0 | 1 | The MBR |
|
sn | 1 | 1 | The device serial number |
|
bootloader | 2 | 1022 | The bootloader (u-boot code) |
|
hwcfg | 1024 | 2 |
|
|
ntxfw | 1030 | 255 |
|
|
waveform | 14336 | 20480 | The waveform for the e-ink display |
|
logo | 34816 | 4096 | empty |
|
bootenv | 1536 | 510 | Probably u-boot environment |
|
kernel | 2048 | 12284 | The linux kernel in zImage format |
|
dtb | 1286 | 250 | The device tree binary |
|
rootfs | 49152 | 524289 | The two rootfs concatenated |
|
vfat | 1097730 | 14139389 |
|
|
recoveryfs | 573441 | 524289 |
|
|
More detail on ntxfw partition dumped from a device compatible with the imx6sll-e60qm2.dts devicetree:
partition name |
---|
NTX_FW_TYPE_LM3630_DUALFL_HDR |
NTX_FW_TYPE_LM3630_DUALFL_PERCENTTAB |
Exporting the internal eMMC as a block device
After getting a shell in u-boot we can look at the list of eMMC/SD cards:
eBR-1A # mmc list FSL_SDHC: 0 (eMMC) FSL_SDHC: 1
The second mmc listed above doesn't seem to exist:
eBR-1A # mmc dev 1 Card did not respond to voltage select!
This is probably because the u-boot code is based on the code for a Freescale developement/evaluation board and since device manufacturers need to ship products fast they probably didn't bother removing the code for that non-existing hardware.
There is a command called 'ums' in u-boot that can export the e-MMC card through USB and make it appear as a mass storage device (like an USB key or an USB hard disk) to the computer it's connected to.
To use it you need to first connect an usb cable between your computer and the e-book reader and then type 'ums 0 mmc 0' in u-boot like that:
eBR-1A # ums 0 mmc 0 UMS: LUN 0, dev 0, hwpart 0, sector 0xe90000
You can then see it on your laptop:
$ lsblk [...] sdb 8:16 1 7.3G 0 disk ├─sdb1 8:17 1 256M 0 part ├─sdb2 8:18 1 256M 0 part └─sdb3 8:19 1 6.8G 0 part
You can then use GNU ddrescue to backup the eMMC device:
ddrescue /dev/sdb kobo_emmc.img
Extracting the hidden partitions
Since the fastboot provides us the offset and that dd default is to operate on 512b at a time we can simply run the following commands:
dd if=kobo_emmc.img of=mbr.img count=1 dd if=kobo_emmc.img of=sn.img skip=1 count=1 dd if=kobo_emmc.img of=bootloader.img skip=2 count=1022 dd if=kobo_emmc.img of=hwcfg.img skip=1024 count=2 dd if=kobo_emmc.img of=ntxfw.img skip=1030 count=255 dd if=kobo_emmc.img of=waveform.img skip=14336 count=20480 dd if=kobo_emmc.img of=logo.img skip=34816 count=4096 dd if=kobo_emmc.img of=bootenv.img skip=1536 count=510 dd if=kobo_emmc.img of=kernel.img skip=2048 count=12284 dd if=kobo_emmc.img of=dtb.img skip=1286 count=250 dd if=kobo_emmc.img of=rootfs.img skip=49152 count=524289 dd if=kobo_emmc.img of=vfat.img skip=1097730 count=14139389 dd if=kobo_emmc.img of=recoveryfs.img skip=573441 count=524289
Fastboot
There is a fastboot command in u-boot. If you want to enable it from the u-boot shell you can do it like that:
# fastboot 0 ptn 0 name='mbr' start=0 len=1 ptn 1 name='sn' start=1 len=1 ptn 2 name='bootloader' start=2 len=1022 ptn 3 name='hwcfg' start=1024 len=2 ptn 4 name='ntxfw' start=1030 len=255 ptn 5 name='waveform' start=14336 len=20480 ptn 6 name='logo' start=34816 len=4096 ptn 7 name='bootenv' start=1536 len=510 ptn 8 name='kernel' start=2048 len=12284 ptn 9 name='dtb' start=1286 len=250 ptn 10 name='rootfs' start=49152 len=524289 ptn 11 name='vfat' start=1097730 len=14139389 ptn 12 name='recoveryfs' start=573441 len=524289
Here we have access to a lot more partition than with the block device export over USB.
fastboot lsusb
Here's how it looks like on lsusb
$ lsusb Bus 001 Device 008: ID 18d1:0d02 Google Inc. Celkon A88
Triggering fastboot without access to the serial port
First run the fastboot command you want to run. You need to do that first because with this method, fastboot will be available for a very short ammount of time (about 5 seconds).
For instance if you want to boot an image named 'boot.img' you can run the follwing command:
$ fastboot boot ./boot.img
First make sure that the device is powered off. With the stock OS, it will either display 'Powered off' in the language it's configured in, or an image on how to plug the device if it never has been powered on.
Once the device is off press the power button. The device will then lit the top-right blue light. At this point press the power button again, and the device will go in fastboot mode for a very short amount of time (about 5 seconds).
PCB
Here are the chips on the top of the PCB. Caevats:
- you need a big screen to view properly the markings as it will line-break with smaller screens
- The markings might contain errors as they are tiny and some letter/number could be mixed up
- I didn't disassemble it enough to see the bottom because the connectors seemed really fragile (they even had glue inside them) so if I do, I fear that I won't be able to put everything back in place. There might be some more chips on the bottom.
Usage | Location | Package | Markings | Driver(s) | Documentation |
---|---|---|---|---|---|
512M RAM | On the PCB top, near the I.MX | 168-Ball PoP-FBGA |
NANYA 1718 NT6TL 128M 32BQ-G0 7201166 AEP 3TW |
? | |
? | On the PCB top, near the I.MX | ? |
SEC 737 BO41 KLM8616EME H56P4788D |
? | |
System on a chip (IMX6SLL CEC) | On the PCB top | ? (BGA) |
MCIMX6V7DVN10AB XAA 1739 TAIW HMAAXK |
Lots of drivers | Reference Manual |
WiFi chip (and potentially other features) | On the PCB top, near the I.MX | ? |
REALTEK 8189PTY H857492 GH438 |
The 8188f chip in the RTL8189FS out of tree driver | |
Main PMIC (powers down the device) | On the PCB top, near the power button | BGA (CSP0608-80 Package) |
RICOH RC5T619 1137 |
||
Power management integrated circuit (and potentially other features) | ? |
TPS 65185 T1 7AI CS6S G4 |
? | ||
On the display flex cable | ? |
TT21000 -48L0I 1725 B03 PRD627959 PHI □ C 041 |
? |
Pictures
Some pictures of the top PCB taken with a camera:
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_01.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_02.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_03.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_04.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_05.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_06.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_07.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_08.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_09.jpeg
- https://archive.org/details/kobo_aura_H2O_edition_2_pcb_10.jpeg
Booting configuration
Findings:
- The device doesn't have restricted boot enabled/configured.
- How to recover the device was not found yet.
- Building and reflashing a bootloader works.
Restricted boot details
The device tested doesn't have restricted boot configured/enabled:
- According to the Secure Boot on ... i.MX 6 ... application note , the SRK (Super Root Key) is "An RSA key pair which forms the start of the boot-time authentication chain. [...]"
- According to the SOC reference manuals, in the "OCOTP memory map", the SRK fuses settings are available in the OTP Bank3 (words 0 to 7 both included)
- The SRK fuses registers were dumped and were blank:
eBR-1A # fuse sense 3 0 8 Sensing bank 3: Word 0x00000000: 00000000 00000000 00000000 00000000 Word 0x00000004: 00000000 00000000 00000000 00000000
Boot order and recovery details
Findings:
- The device is set to the "Internal Boot" BOOT_MODE
- The fuses are then configured to make the device boot on MMC/eMMC
- The boot settings can be overriden by GPIOs (BT_FUSE_SEL=0)
BOOT_MODE details
In the chapter 8.2.1 Boot mode pin settings of the SOC reference manual we have:
BOOT_MODE[1:0] | Boot Type |
---|---|
00 | Boot From Fuses |
01 | Serial Downloader |
10 | Internal Boot |
11 | Reserved |
We are in the "Internal Boot" case here:
# devmem2 0x20D801C w # 0x76fb5000 is SRC_SMBR2 /dev/mem opened. Memory mapped at address 0x76fb5000. Value at address 0x20D801C (0x76fb501c): 0x2000001
Which results in:
SRC_SMBR2[25] = BOOT_MODE1 = 1 SRC_SMBR2[24] = BOOT_MODE0 = 0
BT_FUSE_SEL details
In the "8.2.5 Internal Boot mode (BOOT_MODE[1:0] = 0b10)" chapter we have: "If BT_FUSE_SEL = 0, the specific boot configuration parameters may be set using the GPIO pins rather than eFUSEs."
And in "SRC_SBMR2 field descriptions" in "Chapter 41 System Reset Controller (SRC)" we have:
Field | Description |
---|---|
4
BT_FUSE_SEL |
BT_FUSE_SEL (connected to gpio bt_fuse_sel) shows the state of the BT_FUSE_SEL fuse. See
Fusemap for additional information on this fuse. |
And Looking to it on the device
# devmem2 0x20D801C w # 0x76fb5000 is SRC_SMBR2 /dev/mem opened. Memory mapped at address 0x76fb5000. Value at address 0x20D801C (0x76fb501c): 0x2000001
results in:
SRC_SMBR2[4] = BT_FUSE_SEL = 0
MMC/EMMC boot details
Since we're in "Internal Boot", according to the "5.1 Boot Fusemap" chapter, the following table applies:
Boot Device | BOOT_CFG1[6] | BOOT_CFG1[5] | BOOT_CFG1[4] |
---|---|---|---|
Serial ROM | 0 | 1 | 1 |
SD/eSD | 1 | 0 | X |
MMC/eMMC | 1 | 1 | X |
If we look at the device settings:
[root@parabola ~]# devmem2 0x20D8004 w /dev/mem opened. Memory mapped at address 0x76fca000. Value at address 0x20D8004 (0x76fca004): 0x4064
we have:
BOOT_CFG1[6] = 1 BOOT_CFG1[5] = 1 BOOT_CFG1[4] = 0
which results in the MMC/eMMC being selected.
GPIO override details
In "Table 8-3. GPIO override contact assignments" in "Chapter 8 System Boot" we have:
Package pin | eFuse |
---|---|
LCD_DAT12 | BOOT_CFG2[4] |
LCD_DAT13 | BOOT_CFG2[5] |
LCD_DAT14 | BOOT_CFG2[6] |
Theses seem unused:
imx6sll-e60qm2.dts: [...] pinctrl_lcdif_dat: lcdifdatgrp { fsl,pins = < [...] MX6SLL_PAD_LCD_DATA12__LCD_DATA12 0x79 MX6SLL_PAD_LCD_DATA13__LCD_DATA13 0x79 MX6SLL_PAD_LCD_DATA14__LCD_DATA14 0x79 [...] >; }; [...] &lcdif { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lcdif_dat &pinctrl_lcdif_ctrl>; display = <&display>; status = "disabled"; [...] }; [...]
stock u-boot image details
With tools/dumpimage from u-boot master:
$ tools/dumpimage -l ../ntx-partitions-parser/partitions/bootloader.img Image Type: Freescale IMX Boot Image Image Ver: 2 (i.MX53/6/7 compatible) Mode: DCD Data Size: 401408 Bytes = 392.00 KiB = 0.38 MiB Load Address: 877ff420 Entry Point: 87800000
Building u-boot
The following compiler version was used (it comes from Parabola):
$ pacman -Q -o arm-none-eabi-gcc /usr/bin/arm-none-eabi-gcc is owned by arm-none-eabi-gcc 8.2.0-1
Building:
export ARCH=arm export CROSS_COMPILE=arm-none-eabi- make mx6sll_e70q02_defconfig make -j4
Flashing:
fastboot flash bootloader u-boot.imx
Booting prompt:
eBR-1A # reset resetting ... U-Boot 2016.03-21136-g06b320c20e-dirty (Feb 21 2019 - 16:16:09 +0100) CPU: Freescale i.MX6SLL rev1.1 996 MHz (running at 792 MHz) CPU: Commercial temperature grade (0C to 95C) at 44C Reset cause: WDOG Board: MX6SLL LPDDR2 NTX I2C: ready DRAM: 512 MiB __get_sd_number(),cfg23=0,cfg24=0 MMC: board_mmc_init() : isd=0 board_mmc_init() : wifi=2 FSL_SDHC: 0, FSL_SDHC: 1 In: serial Out: serial Err: serial ntx_hw_early_init() 0 ram p=80000000,size=536870912 switch to partitions #0, OK mmc0(part 0) is current device mmc read 0x9ffffe00 0x3ff 0x1 MMC read: dev # 0, block # 1023, count 1 ... 1 blocks read: OK mmc read 0x9ffffe00 0x400 0x1 MMC read: dev # 0, block # 1024, count 1 ... 1 blocks read: OK ntx_hw_late_init() mmc read 0x9ffffc00 0x1 0x1 MMC read: dev # 0, block # 1, count 1 ... 1 blocks read: OK NTXSN not avalible ! ntx_gpio_get_value(402) : error parameter ! null ptr ! ntx_config_fastboot_layout():10 binaries partition added ntx_config_fastboot_layout():3 mbr partition added check_and_clean: reg 0, flag_set 0 Fastboot: Normal Net: CPU Net Initialization Failed No ethernet found. Hit any key to stop autoboot: 0 switch to partitions #0, OK mmc0(part 0) is current device mmc read 0x80800000 0x7ff 0x1 MMC read: dev # 0, block # 2047, count 1 ... 1 blocks read: OK kernel size = 5364784@80800000 mmc read 0x80800000 0x800 0x28f5 MMC read: dev # 0, block # 2048, count 10485 ... 10485 blocks read: OK Booting from mmc ... mmc read 0x83000000 0x505 0x1 MMC read: dev # 0, block # 1285, count 1 ... 1 blocks read: OK dtb size = 34761@83000000 mmc read 0x83000000 0x506 0x49 MMC read: dev # 0, block # 1286, count 73 ... 73 blocks read: OK hwcfgp=9ffffe00,pcb=60,customer=9 ntx_gpio_get_value(402) : error parameter ! null ptr ! ESDin=0,UPGKey=-1,PWRKey=0,USBin=0x1,BootESD=0,MenuKey=0 mmc read 0x9ffffc00 0x37ff 0x1 MMC read: dev # 0, block # 14335, count 1 ... 1 blocks read: OK mmc read 0x9fdc8a00 0x3800 0x11ba MMC read: dev # 0, block # 14336, count 4538 ... 4538 blocks read: OK mmc read 0x9fdc8800 0x405 0x1 MMC read: dev # 0, block # 1029, count 1 ... 1 blocks read: OK [WARNING] Binaries load sequence should Lo->Hi ! mmc read 0x9fda8a00 0x406 0x100 MMC read: dev # 0, block # 1030, count 256 ... 256 blocks read: OK Kernel RAM visiable size=509M->509M hwcfg rootfstype : 2 hwcfg partition type : 2 Kernel image @ 0x80800000 [ 0x000000 - 0x51dc30 ] ## Flattened Device Tree blob at 83000000 Booting using the fdt blob at 0x83000000 Using Device Tree in place at 83000000, end 8300b7c8 Starting kernel ...
Devices described in code but not present on the PCB?
imx6sll-e60qm2.dts
- No HALL sensor?
- No mmc LEDS?
- No mmc/SD on mmc1
Hardware versions and revisions
The hardware reviewed here had imx6sll-e60qm2.dts, but similarly looking dts are in the vendor Linux source code.
Some hardware components with critical impact on freedom are not described in the devicetree such as:
- The WiFi chip: however no other WiFi drivers are in the kernel configuration and the WiFi driver is an external driver with source code.
Because of that we cannot know in advance if the variants are also good for freedom, without looking at them physically or inferring it from other sources such as the kernel configuration.
dts | Differences with imx6sll-e60qm2.dts | Comments |
---|---|---|
|
Small differences:
|
|
|
Big differences:
Small differences:
|
TODO: Look in u-boot if there is a driver for the EPDC PMIC. |
|
Small differences:
Big differences:
|
|
|
Big differences:
Small differences:
|
|
|
Small differences:
|
|
|
Probably NXP evaluation boards. Not work investigating here. | |
|
Probably evaluation boards related dts. Not work investigating here. |
Software
Kobo u-boot version
U-boot is a free software bootloader. The source code is provided by kobo.
It is based on one of the branches/commits of the freescale fork of u-boot for their I.MX System on a chip.
u-boot serial console
To get a shell in u-boot you will need to setup a serial cable, and press a key in the serial console during boot:
U-Boot 2016.03-00031-gcd5f70c (Aug 31 2017 - 13:17:25 +0800) CPU: Freescale i.MX6SLL rev1.1 996 MHz (running at 792 MHz) CPU: Commercial temperature grade (0C to 95C) at 43C Reset cause: WDOG Board: MX6SLL LPDDR2 NTX I2C: ready DRAM: 512 MiB __get_sd_number(),cfg23=0,cfg24=0 MMC: board_mmc_init() : isd=0 board_mmc_init() : wifi=2 FSL_SDHC: 0, FSL_SDHC: 1 In: serial Out: serial Err: serial ntx_hw_early_init() 0 ram p=80000000,size=536870912 switch to partitions #0, OK mmc0(part 0) is current device mmc read 0x9ffffe00 0x3ff 0x1 MMC read: dev # 0, block # 1023, count 1 ... 1 blocks read: OK mmc read 0x9ffffe00 0x400 0x1 MMC read: dev # 0, block # 1024, count 1 ... 1 blocks read: OK ntx_hw_late_init() mmc read 0x9ffffc00 0x1 0x1 MMC read: dev # 0, block # 1, count 1 ... 1 blocks read: OK NTXSN not avalible ! ntx_gpio_get_value(402) : error parameter ! null ptr ! ntx_config_fastboot_layout():10 binaries partition added ntx_config_fastboot_layout():3 mbr partition added check_and_clean: reg 0, flag_set 0 Fastboot: Normal Net: CPU Net Initialization Failed No ethernet found. Hit any key to stop autoboot: 0 eBR-1A #
u-boot environment
Here's the u-boot environment:
eBR-1A # printenv baudrate=115200 bootcmd=mmc dev ${mmcdev};if run loadimage; then run mmcboot; fi; bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr}; bootdelay=1 bootscript=echo Running bootscript from mmc ...; source console=ttymxc0 epdc_waveform=epdc_splash.bin fastboot_dev=mmc0 fdt_addr=0x83000000 fdt_file=undefined fdt_high=0xffffffff image=zImage initrd_addr=0x83800000 initrd_high=0xffffffff ip_dyn=yes loadaddr=0x80800000 loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script}; loadfdt=load_ntxdtb loadimage=load_ntxkernel mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" mmcargs=setenv bootargs console=${console},${baudrate} rootwait rw no_console_suspend mmcautodetect=no mmcboot=echo Booting from mmc ...; run mmcargs; if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; mmcdev=0 mmcpart=1 script=boot.scr stderr=serial stdin=serial stdout=serial Environment size: 1203/8188 bytes
u-boot booting process
Here the u-boot boot process in uncomon and relies on custom commands like load_ntxkernel to load and execute the Linux kernel and associated data like the dtb:
bootcmd=mmc dev ${mmcdev};if run loadimage; then run mmcboot; fi; loadimage=load_ntxkernel
Adding extra kernel commandline arguments
You can do that in u-boot by overriding mmcargs
setenv mmcargs setenv bootargs <your extra arguments> console=\${console},\${baudrate} rootwait rw no_console_suspend
Stock OS analysis
- The default OS forces the user to register or use some network services like Kobo, google, facebook, etc, however we can get a shell through the serial port.
Source code
- Some Heavily modified Linux 4.1.15 source code is provided by Kobo for this device. It is most probably based on an unknown branch in Freescale's fork of Linux for I.MX system on a chip.
- The WiFi driver source code is also provided by Kobo for this device.
- Some less interesting userspace source code is probably also provided at the same location.
Linux 4.1.15 sources
New sources for Linux seem to have been pushed the 30 April:
- They don't contain all the build scripts that the 3.0.35 did
- They use the devicetre
- They were compiled with gcc 5.3.0
- Parabola's community/arm-none-eabi-gcc isn't able to compile it, however pcr/crosstool-ng can be installed and used to create an arm baremetal 5.4.0 gcc which is able to compile it.
How to build
Getting the kernel configuration and device tree source file name
To build it for the device we need:
- A configuration file, hopefully in my case it can be exrtacted from the device by running the following on the device:
# zcat /proc/config.gz
- To identify which device tree source file was used if we want to avoid reusing the one that is in the eMMC
We can start by looking the machine name:
# grep . /sys/firmware/devicetree/base/* [...] /sys/firmware/devicetree/base/compatible:fsl,imx6sll-lpddr3-arm2 /sys/firmware/devicetree/base/compatible:fsl,imx6sll /sys/firmware/devicetree/base/model:Freescale i.MX6SLL NTX Board
And grepping in the source to see the matching files:
$ grep "Freescale i.MX6SLL NTX Board" -r arch/arm/boot/dts/* arch/arm/boot/dts/imx6sll-e60k02.dts: model = "Freescale i.MX6SLL NTX Board"; arch/arm/boot/dts/imx6sll-e60ql2.dts: model = "Freescale i.MX6SLL NTX Board"; arch/arm/boot/dts/imx6sll-e60qm2.dts: model = "Freescale i.MX6SLL NTX Board"; arch/arm/boot/dts/imx6sll-e60qp2.dts: model = "Freescale i.MX6SLL NTX Board"; arch/arm/boot/dts/imx6sll-e70q02.dts: model = "Freescale i.MX6SLL NTX Board"; arch/arm/boot/dts/imx6sll-lpddr2-ntx.dts: model = "Freescale i.MX6SLL NTX Board"; arch/arm/boot/dts/imx6sll-t05r02.dts: model = "Freescale i.MX6SLL NTX Board";
Then on my board I've the 'cyttsp5' touchscreen controller:
# cd /sys/bus/i2c/devices # grep . 0-*/name 1-*/name 2-*/name 0-0036/name:lm3630a_bl 1-0024/name:cyttsp5_i2c_adapter 1-0068/name:tps6518x 2-0032/name:ricoh619
Now only two files are remainign:
$ grep "cyttsp5_i2c_adapter" $(grep "Freescale i.MX6SLL NTX Board" -r arch/arm/boot/dts/* | sed 's#:.*##') arch/arm/boot/dts/imx6sll-e60k02.dts: compatible = "cy,cyttsp5_i2c_adapter"; arch/arm/boot/dts/imx6sll-e60k02.dts: cy,adapter_id = "cyttsp5_i2c_adapter"; arch/arm/boot/dts/imx6sll-e60qm2.dts: compatible = "cy,cyttsp5_i2c_adapter"; arch/arm/boot/dts/imx6sll-e60qm2.dts: cy,adapter_id = "cyttsp5_i2c_adapter";
It is possible to visualize the difference between both files in a very convenient way like this:
$ meld arch/arm/boot/dts/imx6sll-e60k02.dts arch/arm/boot/dts/imx6sll-e60qm2.dts
It shows quite some difference in the way the system on a chip pins are configured.
For instance for arch/arm/boot/dts/imx6sll-e60qm2.dts we have:
pinctrl_elan_ts_gpio_sleep: elan_ts_gpio_grp_sleep { fsl,pins = < MX6SLL_PAD_SD1_DATA3__GPIO5_IO06 0x10059 /* TP_INT */ MX6SLL_PAD_SD1_DATA2__GPIO5_IO13 0x10059 /* TP_RST */ >; };
and for arch/arm/boot/dts/imx6sll-e60k02.dts we have:
pinctrl_elan_ts_gpio: elan_ts_gpio_grp { fsl,pins = < MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x17059 /* TP_INT */ MX6SLL_PAD_GPIO4_IO18__GPIO4_IO18 0x10059 /* TP_RST */ MX6SLL_PAD_GPIO4_IO17__GPIO4_IO17 0x10059 /* TP_SWDIO */ >; };
Fortunately the Linux kernel exports that information at runtime, and we can access it like that:
# mount -t debugfs none /sys/kernel/debug/ # cd /sys/kernel/debug/pinctrl
After grepping we can see the following line in pinctrl-handles:
type: MUX_GROUP controller 20e0000.iomuxc group: elan_ts_gpio_grp (34) function: imx6sll-lpddr3-arm2 type: CONFIGS_PIN controller 20e0000.iomuxc pin MX6SLL_PAD_GPIO4_IO24 (147) 00017059 type: CONFIGS_PIN controller 20e0000.iomuxc pin MX6SLL_PAD_GPIO4_IO18 (146) 00010059 type: CONFIGS_PIN controller 20e0000.iomuxc pin MX6SLL_PAD_GPIO4_IO17 (149) 00010059
Note that to open pinctrl-handles with a text editor on the device you need to copy it somewhere first, like in /tmp/
In my case the device tree file that works for my hardware is the arch/arm/boot/dts/imx6sll-e60qm2.dts
kernel logs
runtime informations
Here's the kernel version of the device I got:
# uname -r 4.1.15-00104-gcd6a6a6
The boot kernel parameters are available in /proc/cmdline:
console=ttymxc0,115200 rootwait rw no_console_suspend hwcfg_p=0x9ffffe00 hwcfg_sz=110 waveform_p=0x9fdc8a00 waveform_sz=2323160 ntxfw_p=0x9fdc6400 ntxfw_sz=9474 mem=509M boot_port=0 rootfstype=ext4 root=/dev/mmcblk0p1 quiet
- The kernel configuration is available at /proc/config.gz
- The device uses a devicertee that is passed by the bootloader:
# grep . /sys/firmware/devicetree/base/* [...] /sys/firmware/devicetree/base/compatible:fsl,imx6sll-lpddr3-arm2 /sys/firmware/devicetree/base/compatible:fsl,imx6sll /sys/firmware/devicetree/base/model:Freescale i.MX6SLL NTX Board
Running Parabola
The rootfs partitions are too small to install Parabola (They are 256M each), thankfully we have a big partition (6.8G) that is formatted as FAT. But we cannot easily use this as the bootloader boot command uses "root=/dev/mmcblk0p1" and we don't want to require users to use the serial console as it would require soldering.
A way to deal with that would be to set the fat partition as mmcblk0p1. This is possible since we can force the device to go in fastboot mode and overwrite the MBR that way.
Changing partition order
First dump the MBR in mbr1.img as described in this page.
Then change the partitions orders.
sfdisk -d mbr.img > mbr.txt
The following will be in mbr.txt:
mbr1.img1 : start= 49152, size= 524289, type=83 mbr1.img2 : start= 573441, size= 524289, type=83 mbr1.img3 : start= 1097730, size= 14139389, type=b
You can change it to:
mbr.img2 : start= 49152, size= 524289, type=83 mbr.img3 : start= 573441, size= 524289, type=83 mbr.img1 : start= 1097730, size= 14139389, type=b
Then we recreate a new mbr:
qemu-img create -f raw tmp.img 8G sfdisk -f tmp.img < mbr.txt dd if=tmp.img of=mbr2.img count=1 rm tmp.img
We can then flash that:
fastboot flash mbr mbr2.img
TODO:
- Find if it's still possible to trigger the mount of the partition from the stock OS (which doesn't require a serial port)
Serial console with OpenRC
Then you can install OpenRC as systemd won't work with the default kernel unless you recompile it (systemd requires cgroups)
To get a serial console follow this guide https://wiki.gentoo.org/wiki/OpenRC#openrc-init and also add ttymxc0 to /etc/securetty
You also need to create a file at /etc/conf.d/agetty.ttymxc0 with this content:
# make agetty quiet #quiet="yes" # Set the baud rate of the terminal line baud="115200" # set the terminal type term_type="linux" # extra options to pass to agetty for this port agetty_options=""
else the console will use 38400 bauds while it is at 115200 during the boot.
Stock kernel and modules modules
To use the stock kernel and modules seamlessly do:
mkdir -p /lib/modules/4.1.15-00104-gcd6a6a6/kernel/drivers/
If the stock rootfs is mounted on /mnt you can just copy them that way:
cp -r /mnt/drivers/mx6sll-ntx/usb/ /lib/modules/4.1.15-00104-gcd6a6a6/kernel/drivers/ cp -r /mnt/drivers/mx6sll-ntx/wifi/ /lib/modules/4.1.15-00104-gcd6a6a6/kernel/drivers/ touch /lib/modules/4.1.15-00104-gcd6a6a6/modules.order touch /lib/modules/4.1.15-00104-gcd6a6a6/modules.builtin depmod -a
Then you can use them as usual, for instance to get usbnet you could do:
modprobe g_ether
Making the display work
TODO:
- The display was only validated with 1fps with Xorg and xfce4.
- We need to check if the linux-libre patch applies to this vendor kernel
To enable the display:
- Build the patched vendor kernel that has CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE=y enabled and the dependency on nonfree display binaries removed.
- Once the device booted under Parabola, run the following program:
/* * Copyright (C) 2019 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stropts.h> #include <stdint.h> #include <asm/ioctls.h> #define AUTO_UPDATE_MODE_AUTOMATIC_MODE 1 #define MXCFB_SET_AUTO_UPDATE_MODE _IOW('F', 0x2D, uint32_t) static int set_auto_update(int fd) { int ret; int mode = AUTO_UPDATE_MODE_AUTOMATIC_MODE; ret = ioctl(fd, MXCFB_SET_AUTO_UPDATE_MODE, &mode); if (ret < 0) { int err = errno; printf("ioctl error: %s\n", strerror(err)); } } int main() { int fd = open("/dev/fb0", 0); if (fd < 0) { int err = errno; printf("open error: %s\n", strerror(err)); } set_auto_update(fd); return 0; }
- Run Xorg -retro or startxfce4 as root
- Touch the screen, the cursor will move (not at the location of the touch though)
By default the display orientation is in landscape mode.
Making the touchscreen work
The input orientation can be adjusted to match the display landscape mode with:
xinput set-prop "cyttsp5_mt" "Coordinate Transformation Matrix" -1 0 1 0 -1 1 0 0 1
See the following links for more information on how to compute the coordinate transformation matrix:
- https://unix.stackexchange.com/questions/138168/matrix-structure-for-screen-rotation
- https://en.wikipedia.org/wiki/File:2D_affine_transformation_matrix.svg
- https://en.wikipedia.org/wiki/Matrix_multiplication
To come up with that number I computed a translation to the origin multiplicated by a half-circle rotation which was transleted again to 1/2 width, 1/2 height coordinates.
That didn't work however replacing the width and height by 1 in the final matrix worked (and gave the command above). I probably did a sign error somewhere in the calculation.
Linux upstream TODO
Driver or chip | Devicetree | Driver or comments |
---|---|---|
Base hardware | Sent upstream:
|
TODO:
|
GPIO button | Understand how it's connected and how it interferes with the PMIC, and why it works in u-boot | |
cyttsp5 touchscreen+button+proximity driver |
|
|
Ricoh RC5T619: Driver present for:
|
Missing:
|
|
TPS 6518? | It might be possible to integrate it in similar already existing drivers or make one line in:
|
|
TI lm3630 backlight driver | ||
NXP/Freescale epdc (e-paper display controller) | TODO | TODO |
Enabling people to easily install and backup a rootfs
Without serial we only have access to fastboot which only support booting an image, flashing an image or rebooting the device[1].
So with that we need to find a way to backup and/or install a distribution on the device that people can easily use.
We have several approaches for that:
- Modify the u-boot environment from adb. This is the most simple way but it's dangerous.
- Create a rootfs that has to fit in RAM, so it needs to be less than 512M
Distributions
Distribution | Type | Size | Verdict |
---|---|---|---|
Parabola arm with openssh, ddrescue, vim | initramfs | 899M | Cannot fit into the RAM even as an XZ compressed initramfs as the kernel would have to decompress it anyway. |
Parabola arm with openssh, ddrescue, vim | squashfs with -comp xz | 408M | May fit, needs testing |
Parabola arm with openssh, ddrescue, vim | squashfs with -comp lzo | 465M | May fit, needs testing |
Parabola arm with openssh, ddrescue, vim | xz compressed intramfs and Linux with CONFIG_ZSWAP (LZO compression) | May work, need testing | |
LibreCMC | Allwinner A1x/A20/A3x | ||
LibreCMC | Allwinner A1x/A20/A3x | Needs an external kernel | |
LibreCMC | QEMU ARM Virtual Machine |
|
References
- ↑ From the vendor u-boot in drivers/fastboot/fastboot.c we have: "fastboot main process, only support 'download', 'flash' 'reboot' command now"
Manufacturer informations
Other informations
- See Group:Hardware/Freest/e-readers#e-reader_specific_projects_and_distributions for pointers to other projects, distributions, and software made for such e-readers
- https://framagit.org/imx-e-readers/ some of the source code used in this analysis
- Other people are working on I.MX Kobo too: https://www.spinics.net/lists/devicetree/msg311574.html