Для программирования (записи прошивки) устройств на основе SoC Allwinner H616 (H618) с помощью SD-карты используется утилита (точнее, программный пакет) PhoenixCard. Ниже будут показаны некоторые детали и подробности процесса такого программирования. Исходные данные: Примечание. Конкретная модель приставки указана для примера. На самом деле, всё сказанное ниже будет справедливо и для любой другой приставке на Allwinner H618 (и на каких-то других SoC Allwinner) с точностью до имен разделов и их адресов. Cодержимое прошивочной карты Product Утилитой PhoenixCard428 на карте создана таблица разделов, состоящая из двух записей, т.е. на карте образовано два раздела. Если такую карту подключить к USB-порту Android-устройства, то консольная команда sgdisk покажет такой результат: # sgdisk --print /dev/block/sda Disk /dev/block/sda: 62333952 sectors, 29.7 GiB Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): AB6F3888-569A-4926-9668-80941DCB40BC Partition table holds up to 4 entries Main partition table begins at sector 73727 and ends at sector 73727 First usable sector is 73728, last usable sector is 62333949 Partitions will be aligned on 4-sector boundaries Total free space is 3464138 sectors (1.7 GiB) Number Start (sector) End (sector) Size Code Name 1 73728 139263 32.0 MiB 0700 bootloader_a 2 3601356 62331903 28.0 GiB 0700 bootloader_b Примечание. В приведенном выше выводе команды sgdisk для указания на единицу адресации использован термин сектор (sector), доставшийся в наследство от механических накопителей с диском круглой формы. Однако мы будем в описании использовать вместо него термин блок, что более точно соответствует понятию логического блока LBA (Logical block addressing) в современных таблицах разделов GPT. Один блок равен 512 байтам. При чтении можно считать блок и сектор идентичными понятиями (для привыкших к термину сектор). В первом разделе bootloader_a размером 32 Mb на карте записан файл boot-resource.fex из образа прошивки, представляющий собой образ диска формата FAT16, cодержащий из самого нужного bootlogo.bmp, который однако в процессе программирования приставки никак не используется (а отображается в виде загрузочного бутлого при старте). Сразу после первого раздела находится неразмеченная область, в которую в режиме Product записывается полностью и без каких-либо изменений содержимое файла образа прошивки. Обычный размер которого лежит в пределах 1.5 - 2.0 Гигабайт. Адрес, по которому этот образ лежит на карте, определяется по конечному адресу первого раздела (стартовый адрес + длина) в таблице разделов, имеющейся на карте: В обоих случаях конечный адрес первого раздела (в блоках): 139263 , поэтому IMAGEWTY-образ прошивки на прошивочной карте начинается с блока 139264 (запомним это число). Второй раздел bootloader_b (для Android 10 имя раздела env) представляет собой пустой диск, отформатированный в FAT32, который в процессе программирования приставки также не используется. Начальный адрес этого раздела определяется размером записанного на карту IMAGEWTY-образа, а его размер - всё оставшееся на карте место, т.е. размер карты минус стартовый адрес раздела 2. Примечание. Из-за необходимости выравнивания границ разделов начало второго раздела не совпадает с концом блоба образа, а может отстоять от него на 16 или 32 Mb (это значение вычисляется в процессе записи карты). В сказанном выше легко убедиться, если сохранить три файла командами: dd if=/dev/block/sda1 of=part1.bin conv=fsync dd if=/dev/block/sda2 of=part2.bin bs=1M count=16 conv=fsync dd if=/dev/block/sda of=imagewty.bin skip=139264 count=128 conv=fsync А затем посмотреть любым HEX-редактором или вьюером содержимое этих файлов. В частности, в самом начале файла imagewty.bin мы увидим заветный заголовок IMAGEWTY: Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 49 4D 41 47 45 57 54 59 00 03 00 00 60 00 00 00 IMAGEWTY....`... 00000010 00 00 D0 04 34 02 10 00 00 98 A7 67 00 00 00 00 ..Р.4.....§g.... 00000020 00 04 00 00 34 12 00 00 43 87 00 00 00 01 00 00 ....4...C‡...... 00000030 00 01 00 00 01 00 00 00 00 04 00 00 2D 00 00 00 ............-... 00000040 00 04 00 00 00 00 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 ................ На карте образ записан по адресу 0x4400000 (71303168) в байтах, что соответствует такой арифметике:
73728 (36864 Kb - 36 Mb) 37748736 0x2400000 - это начало первого раздела bootloader_a Теперь самое важное: в начале прошивочной карты находится неразмеченная область размером 36 Mбайт (73728 блоков). В неё утилитой PhoenixCard записываются загрузчик boot0, а также пакет bootpackage.fex, содержащий несколько блобов: U-Boot, monitor, и дерево устройств (DTB и DTBO)/ (подробности см. Содержимое файла boot_package.php ) Такое содержимое начальной неразмеченной области прошивочной карты полностью (за исключением одного байта !) совпадает с аналогичным содержимым загрузочной карты, поэтому при подаче питания на прставку с вставленной прошивочной картой стартует обычный режим загрузки, такой-же как и при старте загрузочной карты (или старте прошивки из внутренней памяти). Но эти процессы совпадают только до определенного момента, после которого всё пойдёт не так. Чем определяется режим записи прошивки в память приставки (Product) Процедура установки прошивки на приставку с прошивочной (Product) карты выполняется запущенным с этой карты загрузчиком U-Boot, режим работы которого определяется значением байта режима работы WORK_MODE в его заголовке, расположенном со смещением 0xe0 = 20 от его начала. При записи на карту образа прошивки в режиме Product в начало карты записываются загрузчики Boot0 и U-Boot, при этом в его заголовке устанавливается значение WORK_MODE = 17, которое является признаком работы U-Boot в режиме записи прошивки с карты во внутреннюю eMMC-память приставки. В исходных текстах U-Boot имеется файл spare_head.h, содержащий все возможные значения для байта WORK_MODE и соответствующие им режимы работы запущенного U-Boot. Ниже - фрагмент этого файла (перевод коментариев мой, достаточно условный).
Итак, на загрузочной карте WORK_MODE = 0, на прошивочной карте WORK_MODE = 17 Ниже будет рассказано о процессах, происходящих при записи прошивки с карты, начиная с момента подачи питания на приставку с вставленной прошивочной картой. Описание иллюстрируется фрагментами исходного кода, а также строками сообщений из лога, полученного на терминале при реальной записи прошивки. Весь процесс записи разбит на 10 условных этапов, которые пронумерованы от 1 до 10. В меню с этими номерами - ссылки на краткое описание этапа с фрагментами сообщений терминального лога и исходных текстов. Кроме того, приведены полностью тексты некоторых конфигурационных файлов и исходных текстов. Этапы записи прошивки с карты Product 1. Старт вторичного загрузчика SPL (Boot0) 2. Старт основного загрузчика U-Boot 3. Проверка и настройка параметров карты (MMC) 5. Старт записи прошивки в eMMC 7. Чтение содержимого файла sunxi_MBR 8. Очистка разделов флеш-памяти eMMC 9. Запись содержимого разделов 10. Запись boot0 и U-Boot, завершение операций Ссылки на тексты: Заголовочный файл GPT part_efi.h Заголовочный файл констант spare_head.h Текстовый файл разделов sys_partition.fex Текстовый файла sys_config.fex Содержимое папки SPRITE в исходных текстах U-Boot Исходный текст sunxi_card_sprite_main Полный лог записи прошивки Product |