Анализ и сравнение записанных карт Здесь мы расскажем, какие "следственные" эксперименты были проведены для выяснения структуры записанных SD-карт в двух режимах (StartUp и Product) и понимания принципов действия утилиты Phoenix Card, а также процессов программирования устройства с картой Product. Метод поиска истины прост: для каждого из режимов фиксируем его результаты (логи, содержимое карты, файлы и т.п.), а затем сравниваем, находим различия и анализируем их причины. Все описанные ниже действия и манипуляции при желании можно повторить самостоятельно, чтобы подтвердить, уточнить или опровергнуть сделанные на их основе выводы и представления. Для этих экспериментов используем файл imagewty-образа прошивки для ТВ-бокса на основе SoС Allwinner H616 (конкретная модель не имеет значения), пусть это будет файл с условным именем imagewty.img. Запись будет производиться на две помеченных карты SanDisk емкостью 8Gb. Для сохранения содержимого карт в файлы будем подключать их через кард-ридер к USB-порту устройства с загруженным Android. В нашем случае используется одноплатник OPiZero2, имеющий порт UART с готовым разъемом для подключения его к ПК через переходник, чтобы можно было воспользоваться консольными командами терминала MobaXTerm. Теоретически, можно было бы работать с терминалом (например, Termux) самого Android, но практически это гораздо менее удобно, чем в предыдущем варианте. На этом устройстве любым способом (файловым менеджером или консольными командами) создадим две папки с говорящими (чтобы не запутаться) именами Product и Startup, в которые и будут сохранены бекапы частей соответствующих карт. 1. Сравнение временных файлов Phoenix Card В процессе работы утилиты Phoenix Card в момент выбора в интерфейсе конкретного файла с образом прошивки в текущей папке создаются несколько временных файлов (чуть подробнее о них - Временные файлы PhoenixCard), которые как-то используются в работе утилиты, а по её закрытию - удаляются. Вот список и происхождение этих временных файлов. Проверим, нет ли в них отличий, проливающих свет на особенности записи в разных режимах. StartUp 73728 card.scj 913 config.cfg 16384 dlinfo.fex 8192 gpt.fex 65536 mbr.fex 2143 script.cfg 2143 script.cfgF 4096 thisdata.fexF 3728 card.scj 913 config.cfg 6384 dlinfo.fex 8192 gpt.fex 5536 mbr.fex 2143 script.cfg 2158 script.cfgF 11831296 thisdata.fex 11831296 thisdata.fexF Результаты анализа и сравнения: в StartUp - это пустой файл из нулей размером 4 Кб в Product - файл 11 831 296 = 12 Mb ! При этом файл thisdata.fex - это образ пустого диска FAT32 Выводы. Кроме очевидной замены значения режима записи других существенных отличий в этих временных файлах не обнаружено. 2. Сравнение логов сеанса Phoenix Card ProductStartUpВ обоих режимах есть строки о записи boot0, boot1 и mbr (на самом деле, записывается таблица GPT, а не MBR), но дальше в логи отличаются: 1) запись чего-то с неизвестным именем [] 2) запись с именем [IMG File] ) !!! Поэтому можно предположить, что в режиме Product вместо содержимого разделов, начиная с ENV, на карту записывается какая-то часть исходного imagewty-образа прошивки или даже весь файл образа. Кроме того, есть отличия (непринципиальные) в финальном прогресс-баре: 3. Бекап содержимого карты, записанной в режиме Product console:/ $ su 2|console:/ # sgdisk --print /dev/block/sda Number Start End Size Code Name 1 73728 139263 32.0 MiB 0700 bootloader 2 139264 172031 16.0 MiB 0700 env 3 172032 237567 32.0 MiB 0700 boot 4 237568 5349375 2.4 GiB 0700 super 5 5349376 5382143 16.0 MiB 0700 misc 6 5382144 5447679 32.0 MiB 0700 recovery 7 5447680 8069119 1.3 GiB 0700 cache 8 8069120 8101887 16.0 MiB 0700 vbmeta 9 8101888 8134655 16.0 MiB 0700 vbmeta_system 10 8134656 8167423 16.0 MiB 0700 vbmeta_vendor 11 8167424 8200191 16.0 MiB 0700 metadata 12 8200192 8232959 16.0 MiB 0700 private 13 8232960 8233983 512.0 KiB 0700 frp 14 8233984 8265727 15.5 MiB 0700 empty 15 8265728 8298495 16.0 MiB 0700 media_data 16 8298496 8331263 16.0 MiB 0700 Reserve0 17 8331264 15677405 3.5 GiB 0700 UDISK cd /storage/emulated/0/product dd if=/dev/block/sda of=start.img bs=512 count=73728 conv=fsync В файле start.img должны быть сохранены (с соответствующими смещениями): GPT, boot0 и boot_package 4. Сохраняем в файл bootloader.img содержимое раздела bootloaderdd if=/dev/block/sda1 of=bootloader.img conv=fsync В файле должены быть сохранен boot-resource - диск FAT16 с картинками (bootlogo.bmp и шрифты) dd if=/dev/block/sda bs=1M count=1900 skip=68 | gzip > imagewty.img.gz sync 1. Начальный адрес раздела env = 139264 блоков или 68 MB, поэтому пропускаем эти блоки (skip=68) 2. Размер исходного файла img = 1857141 KB, поэтому в файл сохраняем 1900 Mb (округленно и с запасом) cd /storage/emulated/0/firmwaresd dd if=/dev/block/sda bs=1M count=2048 | gzip > firmware.img.gz sync Файл firmware.img.gz позже можно будет разархивировать и записать на SD-карту с помощью утилит BalenaEtcher или Win32DiskImager или любой аналогичной утилиты на ПК с Windows, т.е. мы получим альтернативный вариант файла для записи "прошивочной" карты Android на ПК с Windows (или Linux) без использования достаточно капризной утилиты Phoenix Card. 4. Бекап содержимого карты, записанной в режиме StartUp console:/ $ su 2|console:/ # sgdisk --print /dev/block/sda Number Start End Size Code Name 1 73728 139263 32.0 MiB 0700 bootloader 2 139264 172031 16.0 MiB 0700 env 3 172032 237567 32.0 MiB 0700 boot 4 237568 5349375 2.4 GiB 0700 super 5 5349376 5382143 16.0 MiB 0700 misc 6 5382144 5447679 32.0 MiB 0700 recovery 7 5447680 8069119 1.3 GiB 0700 cache 8 8069120 8101887 16.0 MiB 0700 vbmeta 9 8101888 8134655 16.0 MiB 0700 vbmeta_system 10 8134656 8167423 16.0 MiB 0700 vbmeta_vendor 11 8167424 8200191 16.0 MiB 0700 metadata 12 8200192 8232959 16.0 MiB 0700 private 13 8232960 8233983 512.0 KiB 0700 frp 14 8233984 8265727 15.5 MiB 0700 empty 15 8265728 8298495 16.0 MiB 0700 media_data 16 8298496 8331263 16.0 MiB 0700 Reserve0 17 8331264 15677405 3.5 GiB 0700 UDISK cd /storage/emulated/0/startup dd if=/dev/block/sda of=start.img bs=512 count=73728 conv=fsync В файле start.img должны быть сохранены (с соответствующими смещениями): GPT, boot0 и boot_package dd if=/dev/block/sda1 of=bootloader.img conv=fsync В файле должены быть сохранен boot-resource - диск FAT16 с картинками (bootlogo.bmp и шрифты) dd if=/dev/block/sda2 of=env.img conv=fsync Делать бекап всех остальных разделов карты StartUp нет смысла, поскольку они отсутствуют на карте Product и сравнивать будет не с чем. 5. Анализ файлов, извлеченных из карты Product Из файла start.img (начало карты) размером 34 MB после распаковки можно извлечь (по их смещениям) следующие следующие блобы, сохранив их в файлы: Сравнение этих файлов из бекапа с аналогичными из файла imagewty-образа дает такие результаты: fc /b boot0.img boot0_sdcard.fex Различия не найдены После распаковки gzip-архива imagewty.img.gz получаем файл imagewty.img, содержимое которого полностью совпадает с исходным файлом imagewty-образа, который был использован для записи прошивочной карты карты в режиме product. ВЫВОДЫ. Таким образом установлено, что в процессе своей работы утилита Phoenix Card в режиме product просто копирует исходный файл образа на карту, начиная с блока 139264, который в таблице разделов GPT соответствует началу второго раздела ENV. То есть таблица GPT фактически используется только для записи в самый первый раздел bootloader графических файлов для U-Boot, а также для определения адреса начального блока раздела ENV, с которого начинается оласть на карте для копирование файла образа. Остальные разделы таблицы игнорируются, а файл записывается поблочным копированием. При этом утилита Phoenix Card, вероятно, выполняет действия, аналогичные команде dd Linux: dd if=imagewtyname.img of=dev/block/sda bs=1M seek=68 dd if=imagewtyname.img of=dev/block/sda bs=512 seek=139264 Механизм этого копирования, наверно, интересен, но сейчас для нас не так уж важен. Скорее всего, он реализован в одном из многочисленных библиотечных файлов, входящих в состав Phoenix Card. 6. Сравнение содержимого двух записанных карт 1. Файлы bootloader.img для product и statrtup слегка отличаются друг от друга ! При этом оба отличаются от исходного файла boot-resource.fex из образа Это говорит о том, что Phoenix Card делает в них при записи какие-то изменения. 2. Файлы gpt.img для product и statrtup слегка отличаются друг от друга, а также от исходной таблицы sunxi_gpt.fex из образа. Отличия такие: Параметр |StartUp | Product То есть используемый размер для Product несколько больше, чем StartUp, это происходит из-за увеличения раздела UDISK на 75 Mb (143600 блоков) При этом в режиме StartUp Phoenix Card записывает после таблицы GPT (со смещением 0x01c00 от начала карты) усеченный заголовок Phoenix Table, который содержит сигнатуру PHOENIX_CARD_IMG (16 байт), и за ней 32-разрядное слово 0x00200100, а также два 16-разрядных слова 0x0c и 0x02. Такой заголовок полностью описывается структурой (см. phoenix_info.c): struct phoenix_ptable { char signature[16]; /* "PHOENIX_CARD_IMG" */ unsigned int unknown1; /* 0x00200100 */ unsigned short parts; /* Number of partitions */ unsigned short unknown2; /* 0x0001 */ unsigned char pad[8]; struct phoenix_entry { unsigned int start; /* 512 bytes blocks */ unsigned int size; /* bytes */ unsigned int unknown; unsigned int sig; /* "add " */ } part[62]; } Однако здесь он имеет какой-то очень урезанный вид. Хотя, не исключено, что эта запись как-то используется загрузчиком при загрузке системы с карты, поскольку такой заголовок в режиме Product вообще не записывается. Отличия в 2-х байтах U-Boot (product -> startup): Не исключено, что эти значения определяют режим работы U-Boot (product - startup) ВНИМАНИЕ. Файл u-boot для StartUp идентичен файлу uboot.img, извлеченному из package исходного образа, а также файлу u_boot.fex из образа. Таким образом, эти два байта в блобе u-boot модифицируются утилитой Phoenix Card в режиме Product. Третий отличающийся байт в package.img с адресом 0x14 - это часть контрольной суммы . |