В статье подробно, с исходным кодом, описана проведенная работа по переносу и запуску прошивки с ОС Android с SD-карты для устройств на процессоре Amlogic S912. Мне нравятся миниатюрные компьютеры, созданные с использованием технологии «система на кристалле» (SOC).
За свои крошечные размеры и низкое энергопотребление по сравнению с персональными компьютерами.
С помощью таких устройств можно решить широкий спектр задач.
На миникомпьютеры можно установить как ОС Android (как это делает большинство производителей этих «игрушек»), так и различные дистрибутивы Linux или Chrome OS. Моя текущая работа — разработка приложений для Android. В данной работе крайне желательны тесты на реальных устройствах на разных версиях системы.
У меня есть пара миникомпьютеров от Rockchip и Amlogic, на которых я и провожу свои тесты.
Android, как операционная система, развивается достаточно динамично и сейчас на рынке используются его модификации от версии 4.4 до версии 10. И выйдет Android версии 11. Многие компании, разрабатывающие приставки на базе Android, вынуждены иметь короткий период поддержки своих творений из-за быстрого развития как аппаратного, так и программного обеспечения.
Один из моих основных рабочих инструментов для тестирования — приставка КМ8П на процессоре S912 с двумя гигабайтами оперативной памяти и предустановленной операционной системой Android версии 7.1. Проходит время, и в течение пары лет на рынке последовательно появляются версии 8.1, 9.0 и 10.0 ОС Android. Мне бы очень хотелось протестировать свое приложение под этими самыми версиями.
Но что делать? Либо вам нужно покупать зверей на новых процессорах и версиях Android, либо самостоятельно адаптировать новые версии Android на существующие устройства.
Первый способ легкий и простой: заплатив не очень большую сумму, проблему можно легко решить.
Но мы не ищем легких путей, поэтому выбираем второй путь.
Второй путь гораздо сложнее, но интереснее.
Кроме того, сам чип S912 представляет собой отличный 8-ядерный процессор, мало чем уступающий по производительности новейшим процессорам Amlogic на чипе S905x. Итак, второй вариант был выбран как более интересный и отвечающий моим потребностям.
Возник вопрос: куда идти? Текущая версия Android 7.1 под капотом имеет ядро Linux 3.14.29 и NAND-ROM на чипе SK Hynix H27UCG8T2ETR, для которого Amlogic разработала собственный драйвер aml_nftl_dev.ko. Все последние версии Android основаны на ядре 4.9. И желательно этим воспользоваться.
Однако политика Amlogic такова, что последние несколько лет компания предоставляет Android SDK только легальным компаниям, занимающимся производством устройств на базе чипов Amlogic. Однако на github можно найти исходники ядра 4.9 на базе Android SDK от Amlogic 2017-18. Например, Git-репозиторий Компания Хадас.
Однако дело в том, что драйвер aml_nftl_dev для версии ядра 4.9 отсутствует. Что делать? Стоит ли адаптировать этот драйвер для ядра 4.9? Но помимо адаптации драйвера вам придется еще и отредактировать так называемое дерево устройств ядра.
Это трудный путь.
Многие устройства на процессоре S912 имеют более современное ПЗУ с EMMC-контроллером.
К счастью для владельцев таких устройств, совсем недавно (в июне-июле 2020 года) появилась прошивка для Android 9, собранная энтузиастами (можно посмотреть Здесь И Здесь ).
Я не смог использовать эти прошивки из-за отсутствия на моем устройстве чипа EMMC. Однако я прекрасно понимал, что имея на приставке слот для SD-карты, использующей тот же драйвер MMC, что и для работы с чипом EMMC, можно попробовать использовать SD-карту вместо ПЗУ.
К сожалению, ситуация осложнялась тем, что Amlogic изначально не предусматривал запуск системы с SD-карты.
Однако что-то было.
В Amlogic реализована возможность обновления прошивки с SD-карты.
Эта и другие функции были достигнуты компанией Amlogic путем существенной модификации загрузчика u-boot в соответствии с ее потребностями.
В частности, можно запустить ядро системы из FAT-раздела SD-карты.
Итак, было решено узнать, можно ли адаптировать драйвер ММС для возможности запуска с SD-карты.
Я погрузился в изучение исходного кода драйвера.
Изучая исходный код, я выяснил, во-первых, что драйвер монтирования загрузочного раздела ограничен работой только с чипом EMMC, и игнорирует другие устройства.
А такие устройства — это всего лишь слот SDMMC и порт SDIO. Почему бы не изменить код, чтобы драйвер не пропускал устройство SDMMC, а продолжал работать с ним как с EMMC? Во-вторых, было установлено, что разработчики Amlogic используют собственную структуру данных для хранения таблицы разделов диска и записывают ее по некоторому смещению на диске.
Структура данных проста; он хранит смещение, имя, размер и некоторые другие характеристики раздела.
После определения типа устройства драйвер считывает таблицу разделов на диске и создает в системе блочные устройства согласно этой таблице.
Получается, что разрешив драйверу работать с SDMMC как с EMMC и записав таблицу разделов по заранее известному адресу на SD-карте, я таким образом могу смоделировать EMMC и загрузить систему с SD-карты! Я подумал, а почему бы не сделать утилиту, которая будет записывать таблицу разделов в нужном формате и при необходимости проверять ее корректность.
Сказано - сделано.
Причем сделать это было несложно, поскольку практически вся инфраструктура уже была описана в исходном коде драйвера.
Исходный код утилиты выложен на github, репозиторий амлпт .
Утилита создана в ОС Ubuntu. Но думаю, при необходимости, перенести его на винду не составит труда.
Сначала необходимо заполнить параметры таблицы разделов в файле mmcparts_a9.c, указав имена, смещения, размеры и тип разделов.
Для обычных разделов тип — 0x1, для разделов типа кэш — 0x2, а для разделов типа данных — 0x4. Я взял значение 0x2800000 (40 МБ) в качестве начального смещения первого раздела.
Далее я заполнил названия, размеры и типы разделов в структурах разделов согласно таблице разделов из дерева устройств.
Для Android 9 таких разделов было 17. Заполнив данные в файле mmcparts_a9.c, создаем утилиту для записи таблицы разделов, запустив скрипт make_amlptwrt.sh. Этот сценарий создает исполняемый файл amlptwrt, который можно использовать для создания двоичного файла mmc_parts.bin. Это наша таблица разделов, которую читает драйвер MMC. Аналогично запускаем скрипт make_amlptrdr.sh для создания утилиты чтения таблицы разделов amlptrdr, с помощью которой мы можем проверить правильность заполнения этой таблицы.
После запуска amlptrdr в консоли отобразится таблица разделов с названиями, смещениями и размерами в мегабайтах.
Как это: Таблица разделов
@> :~/AML/amlpt$ .Чтобы драйвер MMC работал с устройством SDMMC, я внес два небольших исправления в исходный код драйвера, в файле драйверы/amlogic/mmc/emmc_partitions.c : а) Сначала разрешаем драйверу работать с устройствами, отличными от EMMC. Для этого изменим функцию is_card_emmc следующим образом:/amlptrdr [mmc_verify_partition_tbl] mmc прочитал раздел ОК! show_mmc_partitions [диск p01] логотип, офсет 40 Мб, размер 8 Мб [диск p02] смещение восстановления 48 Мб, размер 24 Мб [диск p03] разное смещение 72 Мб, размер 8 Мб [диск p04] dtbo смещение 80 Мб, размер 8 Мб [диск p05] cri_data смещение 88 Мб, размер 8 Мб [диск p06] rsv смещение 96 Мб, размер 16 Мб [диск p07] смещение метаданных 112 Мб, размер 16 Мб [диск p08] vbmeta смещение 128 Мб, размер 2 Мб [диск p09] смещение параметра 130 Мб, размер 16 Мб [диск p10] загрузочное смещение 146 Мб, размер 16 Мб [диск р11] тройник офсет 162 Мб, размер 32 Мб [диск p12] вендорское смещение 194 Мб, размер 130 Мб [диск p13] odm offset 324 Мб, размер 128 Мб [диск p14] системное смещение 452 Мб, размер 1350 Мб [диск p15] продукт, смещение 1802 Мб, размер 128 Мб [диск p16] смещение кэша 1930 Мб, размер 1120 Мб [диск p17] смещение данных 3050 Мб, размер 4050 Мб
Конечно, это самое бесполезное изменение, которое можно было придумать, но для достижения моей цели его достаточно.static int is_card_emmc(struct mmc_card *card) { //struct mmc_host *mmc = card->host; // emmc port, so it must be an eMMC or TSD //if (!strcmp(mmc_hostname(mmc), "emmc")) return 1; //else // return 0; //return mmc->is_emmc_port; }
Как говорится, материнская лень впереди планеты всей.
б) Определите смещение, с которым будет читаться таблица разделов.
Редактирование осуществляется в функции mmc_read_partition_tbl : //start_blk = get_reserve_partition_off(card);
start_blk = MMC_BOOT_PARTITION_SIZE + MMC_BOOT_PARTITION_RESERVED;
Если посмотреть исходный код драйвера, то сумма констант MMC_BOOT_PARTITION_SIZE + MMC_BOOT_PARTITION_RESERVED равна 36 МБ.
Надо отметить, что данные правки подходят для моего варианта, когда в устройстве нет чипа EMMC или он отключен в дереве устройств.
Для остальных случаев придется придумать более правильный вариант правок.
Итак, смещение, с которым будет записана таблица разделов на SD-карте, составляет 36 МБ.
Для того, чтобы разместить на SD-карте нашу таблицу разделов, созданную утилитой amlptwrt, достаточно выполнить команду: // 36M = 37748736 bytes = 73728 sectors
sudo dd if=mmc_parts.bin of=/dev/sdb seek=73728 bs=512
Предполагается, что /dev/sdb — это SD-карта.
Далее компилируем ядро, создаем boot.img с нулевым initrd и примерно такими параметрами ядра: root=/dev/mmcblk0p14 rootfstype=ext4 rootwait
Напомним, что u-boot от Amlogic может запустить ядро Linux с SD-карты из FAT-раздела.
В самом начале создаем на SD-карте FAT-раздел размером 32 МБ.
Этого вполне достаточно для размещения наших boot.img и dtb.img. В дереве устройств dtb.img нам нужно отключить EMMC, чтобы наша SD-карта называлась /dev/mmcblk0. Или не отключайте, но тогда вам нужно будет изменить параметры ядра в boot.img, чтобы ядро могло успешно смонтировать системный раздел, который в данном случае будет называться /dev/mmcblk0p14.
И, в качестве заключительной части Марлезонского балета, осталось записать на SD-карту разделы прошивки Android. Для этого распакуйте прошивку и запишите на SD-карту подходящие разделы согласно смещениям в таблице разделов: Запись разделов на SD-карту // logo
sudo dd if=logo.PARTITION of=/dev/sdb bs=1M seek=40 conv=sync,fsync status=progress
// recovery
sudo dd if=recovery.PARTITION of=/dev/sdb bs=1M seek=48 conv=sync,fsync status=progress
// misc
sudo dd if=/dev/zero of=/dev/sdb bs=1M seek=72 count=8 conv=sync,fsync status=progress
// dtbo
sudo dd if=dtbo.PARTITION of=/dev/sdb bs=1M seek=80 conv=sync,fsync status=progress
// cri_data
sudo dd if=/dev/zero of=/dev/sdb bs=1M seek=88 count=8 conv=sync,fsync status=progress
// rsv
sudo dd if=/dev/zero of=/dev/sdb bs=1M seek=96 count=16 conv=sync,fsync status=progress
// metadata
sudo dd if=/dev/zero of=/dev/sdb bs=1M seek=112 count=16 conv=sync,fsync status=progress
// vbmeta
sudo dd if=vbmeta.PARTITION of=/dev/sdb bs=1M seek=128 conv=sync,fsync status=progress
// param
sudo dd if=/dev/zero of=/dev/sdb bs=1M seek=130 count=16 conv=sync,fsync status=progress
// boot
sudo dd if=boot.PARTITION of=/dev/sdb bs=1M seek=146 conv=sync,fsync status=progress
// tee
sudo dd if=/dev/zero of=/dev/sdb bs=1M seek=162 count=32 conv=sync,fsync status=progress
// vendor
sudo dd if=vendor.img of=/dev/sdb bs=1M seek=194 conv=sync,fsync status=progress
// odm
sudo dd if=odm.img of=/dev/sdb bs=1M seek=324 conv=sync,fsync status=progress
// system
sudo dd if=system.img of=/dev/sdb bs=1M seek=452 conv=sync,fsync status=progress
// product
sudo dd if=product.img of=/dev/sdb bs=1M seek=1802 conv=sync,fsync status=progress
Я просто залил нулями те разделы, которых не хватало в прошивке.
Некоторые разделы, например системные или поставщикские, а также некоторые другие, могут быть разреженными.
Их предварительно необходимо преобразовать в обычные разделы: simg2img system.PARTITION system.img
С разделами кэша и данных нужно обращаться немного по-другому.
Смотрим на нашу таблицу разделов, созданную утилитой amlptwrt, и с помощью программы fdisk создаем на SD-карте соответствующие разделы с нужными смещениями и размерами и форматируем их в файловую систему ext4: sudo mkfs.ext4 /dev/sdb2
sudo mkfs.ext4 /dev/sdb3
После форматирования той же утилитой fdisk удаляем ненужные разделы /dev/sdb2 и /dev/sdb3. Чтобы загрузчик u-boot распознал необходимость загрузки с SD-карты, помещаем файл aml_autoscript в раздел FAT. Сам файл aml_autoscript можно создать с помощью утилиты mkimage из простого текстового файла следующего содержания: if mmcinfo; then fatload mmc 0 ${loadaddr} boot.img; fatload mmc 0 ${dtb_mem_addr} dtb.img; bootm; fi;
Это все, что нужно для переноса прошивки с Android на плату на SD-карту.
Опубликовано несколько прошивок, сделанных этим методом.
в соответствующей теме на форуме 4PDA. Если что-то неясно, задавайте вопросы в комментариях.
Я помогу, чем смогу.
На этом позвольте откланяться и удачи всем в переносе прошивки! Теги: #Android #github #Программное обеспечение #Будущее уже здесь #с открытым исходным кодом #C++ #прошивка #прошивка #Amlogic #sd-карта #S912
-
Dynamics Gp Работа С Заявлениями Клиентов
19 Oct, 24 -
Знакомство С Kohana 3.0 — Часть 5
19 Oct, 24 -
Проблема Башорга
19 Oct, 24 -
У Высокоразвитого Ии Обязательно Будет Душа
19 Oct, 24