Мне всегда хотелось заполучить экран на электронных чернилах для своих будущих проектов. Я купил небольшой экранчик с платой расширения Raspberry Pi, однако потом понял, что можно просто воспользоваться старой «читалкой» Amazon Kindle.
Когда-то давно я уже экспериментировал с Kindle: портировал на него интерпретатор Infocom и приложение для чтения манги. Мне удалось заставить ПО Amazon загружать их как Kindlet и отображать их интегрированными в «читалку». Однако сейчас мне нужна была просто дешёвая и удобная платформа разработки под Linux с eink.
Дешёвый Kindle с Ebay (и причина его дешевизны)
Итак, я отправился на ebay! Нашёл там множество очень дешёвых лотов, помеченных как «Заблокирован Amazon». Я решил, что не стоит их брать, потому что, теоретически, они могут быть краденными. В конечном итоге я выбрал Kindle 4 без сенсорного экрана за 7 фунтов.
Спустя несколько дней он приехал. Тогда я и понял, почему он был таким дешёвым: на экране постоянно отображался некий демо-режим, из которого невозможно выйти:
Я загуглил, и хотя оказалось, что более новые версии Kindle можно было вывести из демо-режима, с этой версией ничего не сработало. Впрочем, это меня не волновало, мне всё равно не надо запускать на устройстве оригинальное ПО Kindle.
Итак, следующий шаг — получение доступа. Изучив форумы mobileread, я обнаружил отладочный последовательный порт: настало время вскрывать корпус!
Физический доступ получен!
Всё оказалось довольно непросто! По периметру есть множество защёлок, а сам корпус приклеен к аккумуляторному отсеку, поэтому потребовалось вмешательство большого ножа. От клея устройство я отчистил ацетоном.
- Красное: надоедливые защёлки
- Фиолетовое: очень надоедливый клей.
- Жёлтое: последовательный порт!
Как обычно и бывает в таких случаях, у последовательного порта нет разъёма, поэтому нужно припаять к плате крошечные контакты. Для подобной работы я люблю использовать провод для скрутки диаметром примерно 0,2 мм и жало для поверхностного монтажа:
Не хочу оставлять болтающиеся провода, но в то же время понимаю, что рано или поздно что-нибудь напутаю и мне понадобится доступ к консоли последовательного порта, поэтому придумал следующее решение:
Я приклеил суперклеем к печатной плате Kindle кусок макетной платы, а затем припаял с одного конца проводники от крошечных контактов на печатной плате. Потом я припаял с другого конца более крупный и удобный разъём Dupont, чтобы можно легко было подключаться к нему. Верхний кабель на плате Kindle — это 0v/GND, а остальные — это TX и RX (я забыл, какой из них где).
Последняя проблема: последовательный порт Kindle работает от 1,8 В, поэтому мне нужен адаптер последовательного порта с поддержкой такого напряжения:
Купленный мной адаптер поддерживает 5 В, 3,3 В, 2,5 В и 1,8 В — очень удобно!
Root-доступ получен!
Далее я подключил адаптер последовательного порта к ноутбуку, запустил ПО последовательного порта minicom и перезапустил Kindle. Затем, поменяв местами провода TX и RX (это всегда неизбежно), я увидел следующую информацию!
U-Boot 2009.08-lab126 (Aug 29 2012 - 12:55:24)
CPU: Freescale i.MX50 family 1.1V at 800 MHz
mx50 pll1: 800MHz
mx50 pll2: 400MHz
mx50 pll3: 216MHz
ipg clock : 50000000Hz
ipg per clock : 50000000Hz
uart clock : 24000000Hz
ahb clock : 100000000Hz
axi_a clock : 400000000Hz
axi_b clock : 200000000Hz
weim_clock : 100000000Hz
ddr clock : 800000000Hz
esdhc1 clock : 80000000Hz
esdhc2 clock : 80000000Hz
esdhc3 clock : 80000000Hz
esdhc4 clock : 80000000Hz
MMC: FSL_ESDHC: 0, FSL_ESDHC: 1
Board: Tequila
Boot Reason: [POR]
Boot Device: MMC
Board Id: 0031701123730Z56
S/N: B02317022392005M
Initing MDDR memory
ZQ calibration complete: 0x128=0xfffe0010 0x12C=0xffffffff
DRAM: 256 MB
Using default environment
In: serial
Out: logbuff
Err: logbuff
Quick Memory Test 0x70000000, 0x10000000
POST done in 13 ms
Hit any key to stop autoboot: 0
## Booting kernel from Legacy Image at 70800000 ...
Image Name: Linux-2.6.31-rt11-lab126
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4777568 Bytes = 4.6 MB
Load Address: 70008000
Entry Point: 70008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
[snip]
Welcome to Kindle!
kindle login:
Отлично, это загрузка при помощи uboot-загрузчика, после чего происходит загрузка Linux и запрос логина.
Если попытаться войти как root, система запросит пароль, хм-м-м… Однако из предыдущего опыта работы с Kindle я знал, что пароль можно сгенерировать из серийного номера. Я нашёл этот веб-сайт, генерирующий несколько возможных паролей для конкретного устройства: мой пароль оказался третьим в списке.
На случай смерти сайта вот самый важный фрагмент кода на Javascript:
var md5 = hex_md5(serial);
document.getElementById("rootpw").innerHTML = "fiona" + md5.substring(7,11);
document.getElementById("rootpw2").innerHTML = "fiona" + md5.substring(7,10);
document.getElementById("rootpw3").innerHTML = "fiona" + md5.substr(13,3);
А, я забыл сказать, как извлёк серийный номер устройства. Подключение по USB не «срабатывает» — такие демо-устройства нельзя монтировать как диски. Однако под Linux оно всё равно выводит серийный номер в вывод dmesg Linux (также его можно получить при помощи printenv в uboot, если нажать на Enter при отображении сообщения «Hit any key to stop autoboot»):
[128033.676587] usb 1-2: new high-speed USB device number 51 using xhci_hcd
[128033.829631] usb 1-2: New USB device found, idVendor=1949, idProduct=0004, bcdDevice= 1.00
[128033.829638] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[128033.829642] usb 1-2: Product: Amazon Kindle
[128033.829645] usb 1-2: Manufacturer: Amazon
[128033.829648] usb 1-2: SerialNumber: XXXXXXXXXXXXXXXX
Отлично! У нас есть root и мы можем выполнить вход! Теперь разберёмся, как чуть упростить себе работу.
Выполняем дамп системы
Первым делом обычно делают дамп дисков для анализа на другом компьютере.
Проверив
/proc/mounts
, мы увидим множество разделов основного диска на /dev/mmcblk0
.Выполнив
fdisk /dev/mmcblk0
, получим следующее:Units = cylinders of 64 * 512 = 32768 bytes
Device Boot Start End Blocks Id System
/dev/mmcblk0p1 * 1025 12224 358400 83 Linux
/dev/mmcblk0p2 12225 14272 65536 83 Linux
/dev/mmcblk0p3 14273 15296 32768 83 Linux
/dev/mmcblk0p4 15297 59776 1423360 b Win95 FAT32
- Итак, есть четыре раздела — три Linux, один FAT32.
- Первый диск начинается довольно далеко: оказалось, что в этой «отсутствующей» области хранится ядро.
- После изучения становится ясно, что раздел 1 — это обычная система, 2 — что-то вроде раздела для инструментов диагностики, 3 — для хранения внутреннего приватного состояния Kindle (например, паролей WiFi). 4 — это тот раздел, который вы видите при подключении Kindle по USB: на нём хранятся все книги.
- Раздел 4 смонтирован на /mnt/us.
С помощью dd я сдампил начало диска и разделы 1-3 на /mnt/us (мне нравится делать полный сырой образ, чтобы можно было его восстановить на случай, если что-то пойдёт не так):
dd if=/dev/mmcblk0 of=/mnt/us/kindle.img bs=32768 count=15297
Хотя этот Kindle не отображает диск по USB, поскольку у меня есть root, я могу просто заставить отобразить его:
rmmod g_file_storage
modprobe g_file_storage file=/dev/mmcblk0p4
После этого я скопировал всё на ноутбук.
Анализ системы
Далее я смонтировал разделы из kindle.img на свой ноутбук:
kpartx -v kindle.img
После чего я смог монтировать отдельные разделы на ноутбук. Я извлёк все файлы в папку, чтобы можно было их просматривать и исследовать grep. Выяснилось следующее:
- В качестве системы инициализации используется
rc.d
, поэтому там много скриптов, написанных обычным текстом. - Уровень инициализации 5 — это «обычная» система, запускающая ПО электронной книги
- ПО электронной книги находится в
/opt/amazon
, оно написано на Java (я вроде бы уже знал это, но мне понадобилось освежить память). - Там есть целая куча интересных скриптов diag для тестирования, написанных обычным текстом.
- Есть довольно удобный демон
wifid
для управления wifi-соединением: из скриптов diag я выяснил, как с ним общаться. - Можно выполнять запись на экран eink из командной строки с помощью команды
/usr/sbin/eips
(документация находится здесь). - Я не смог найти очевидного переключателя «отключить демо-режим»: похоже, он встроен в ПО электронной книги на Java.
- Следующие системные сервисы связаны с неподдерживаемыми функциями, ПО электронной книги или общением с Amazon:
S50wan S70wand S75phd S81usbnetd S93webreaderd S94browserd S95framework S96boot_finished
.
Общение с Wifid
Можно использовать встроенный wifid для подключения к wifi и управления профилями wifi. О, и надо помнить о том, что многие Kindle поддерживают WiFi только на 2,4 ГГц, имейте это в виду, если что-то не будет работать.
Перечисление количества профилей WIFI:
lipc-get-prop com.lab126.wifid profileCount
Показ содержимого профиля WIFI:
echo "{index=(0)}" | lipc-hash-prop com.lab126.wifid profileData
Удаление профиля WIFI:
lipc-set-prop com.lab126.wifid deleteProfile WIFIESSID
Создание профиля WIFI:
echo '{essid="WIFIESSID", smethod="wpa2", secured="yes", psk="WIFIPSK"}' | lipc-hash-prop com.lab126.wifid createProfile
Возможные варианты smethod: open,wep,wpa,wpa2 (если вы выберете open, то задайте для secured значение «no»).
WIFIPSK — это WIFI PSK, сгенерированный утилитой
wpa_passphrase
(которая есть в Kindle): обычная «wifi passphrase» не сработает.Подключение профиля WIFI:
lipc-set-prop com.lab126.wifid cmConnect WIFIESSID
Отображение состояния подключения WIFI:
echo "{index = (0)}" | lipc-hash-prop -n com.lab126.wifid currentEssid
Внесение изменений в Root
Во многих из представленных ниже инструкций требуется изменение root-диска в kindle. Однако по умолчанию он монтируется в режиме read only. Чтобы решить эту проблему, запустим на kindle следующую команду:
mntroot rw
После завершения верните диск в режим read only, чтобы избежать нежелательных изменений:
mntroot ro
Установка Dropbear SSH
Я хотел иметь возможность подключения к kindle по ssh, поэтому решил установить ssh-демон dropbear. Разумеется, это устройство на ARM, поэтому мне нужно было или скомпилировать его самостоятельно, или где-то найти. К счастью, существует поддерживаемый разработчиками хак USBNET для kindle: я решил не использовать этот хак у себя, потому что хотел полностью контролировать своё устройство, но всё равно смог позаимствовать из него двоичный файл dropbear.
К сожалению, USBNET поставляется в собственном странном формате обновления Kindle, поэтому нужно извлечь из него двоичный файл:
На компьютере:
- Скачать этот репозиторий git и скомпилировать его — это позволит нам декодировать обновления kindle.
- Скачать kindle-usbnetwork-0.57.N-k4.zip отсюда и скопировать его в
KindleTool/Release/
. cd KindleTool/Release/
Распаковать kindle-usbnetwork-0.57.N-k4.zip
./kindletool extract Update_usbnetwork_0.57.N_k4_install.bin usbnet
cd usbnet
tar Jxf usbnet.tar.xz
- Скопировать
src/usbnet/bin/dropbearmulti
на Kindle (я перемонтировал его как USB-устройство и скопировал файлы).
В Kindle:
cd /
mv /mnt/us/dropbearmulti /
chmod a+x /dropbearmulti
ln -sf /dropbear /dropbearmulti
ln -sf /dropbearkey /dropbearmulti
ln -sf /bin/scp /dropbearmulti
/dropbearkey -t rsa /dropbear_rsa_host_key
Преобразуем всё под мои проекты
Я переименовал все ненужные системные сервисы:
cd /etc/rc5.d; mv S95framework DISABLED.S95framework
Добавил собственный скрипт инициализации в
/etc/rc5.d/S99adq
, чтобы вносить свои изменения:#!/bin/sh
NAME="adq"
case "$1" in
start)
# display some stuff!
/usr/sbin/eips -c 20 20 "HELLO ADQ"
IP=`ifconfig wlan0 | awk '/t addr:/{gsub(/.*:/,"",$2);print$2}'`
/usr/sbin/eips 1 1 "IP Address: $IP"
/usr/sbin/eips 1 2 "Root Password: <MY ROOT PASSWORD>"
/usr/sbin/eips ""
# connect to wifi and allow ssh in
lipc-set-prop com.lab126.wifid cmConnect MYWIFISSID
iptables -A INPUT -i wlan0 -p tcp --dport 22 -j ACCEPT
/dropbear -r /dropbear_rsa_host_key
mkdir -p /mnt/us/usbnet/etc
echo "<MY SSH PUBKEY>" > /mnt/us/usbnet/etc/authorized_keys
# expose shell over usb
modprobe -r g_file_storage
modprobe g_serial
/sbin/getty -L 115200 ttyGS0 -l /bin/login &
;;
stop)
;;
*)
msg "Usage: /etc/init.d/$NAME {start|stop}" W >&2
exit 1
;;
esac
exit 0
Теперь устройство может:
- При загрузке отображать на экране полезную информацию
- Подключаться к wifi.
- Использовать SSH через файрвол.
- Запускать ssh-демон dropbear.
- Добавлять мой публичный ключ ssh в нужное для dropbear место.
- Удалять USB-функцию «притворяемся диском»
- Заставлять его «притворяться последовательным устройством» через USB и отображать запрос логина: если подключить его через USB и использовать minicom, я получу запрос логина на случай, если что-то пойдёт не так.
Теперь при загрузке мой kindle выглядит так и я могу подключаться как root по ssh.
Всё практически готово: теперь я могу подключаться по ssh к kindle и у меня есть несколько уровней последовательной консоли на случай, если что-то пойдёт не так. Это довольно удобная система разработки под Linux с e-ink, подключением по wifi и с работой от аккумулятора.
Последнее улучшение — я убрал некоторые защёлки с задней крышки и установил её на место.
Дальнейшее развитие
Похоже, что эта библиотека (FBInk) сможет заменить ПО Amazon eips; вероятно, оно будет удобнее, если я захочу интегрировать дисплей с моим собственным ПО.
На правах рекламы
Эпичные серверы — это надёжные серверы на Linux или Windows с мощными процессорами семейства AMD EPYC и очень быстрой файловой системой, используем исключительно NVMe диски от Intel. Попробуйте как можно быстрее!
rotor
Спасибо за перевод. Очень крутая статья.