4. Как используются разделы
Для операций с разделами Android на загрузочной карте (анализ таблицы разделов, чтение, запись и др.)
совсем не обязательно иметь под рукой ПК с Linux. Для этого можно воспользоваться
самим устройством (платой OpiZero2).
Есть два способа:
Способ 1-й.
Записанная загрузочная SD-карта вставлена в слот устройства, на которое подано питание и
система загружена. Для выполнения консольных команд удобно использовать терминал (например, MobaXTerm)
на ПК, к USB-порту которого через переходник подключен UART устройства. В этом случае можно безболезненно
смотреть таблицу разделов и читать содержимое разделов в файлы (на эту же карту или на подключенную USB-флешку).
Записывать таким способом (на живом теле) разделы тоже можно, но не все и очень осторожно.
Поскольку при неудачной или ошибочной записи устройство с такой карточкой работать перестанет, и придется её
записывать заново. Поэтому такой способ желательно использовать только для бекапа (чтения и сохранения в файлы)
разделов.
Для обращения к разделам в первом способе используются пути:
/dev/block/mmcblk0 - это вся карта полностью
/dev/block/mmcblk0p1 - /dev/block/mmcblk0p17
где (p1...p17 - порядковые номера разделов) -
для обращения к конкретному разделу.
При этом в командах dd в обоих случаях можно обращаться к части раздела, добавляя в комаду
параметры count (количество копируемых блоков) и skip (пропущенных блоков) при чтениии раздела
или seek (пропущенных блоков) при записи раздела. Без явного указания параметра bs
размер копируемого блока равен 512 байт. Именно в таких блоках (секторах) сделана адресация
в таблице разделов GPT, поэтому удобно оставить размер блока по умолчанию, чтобы не заниматься
арифметикой пересчета смещений и размеров.
Способ 2-й.
Предназначенная для чтения-записи разделов SD-карта вставлена в кардридер,
который подключается к USB-порту устройства. При этом система с Андроидом загружается со другой
рабочей загрузочной карты, вставленной в слот SD-карты. В этом варианте на "экспериментальной" карте
можно делать любые операции с разделами, в т.ч. их очистку и запись, не затрагивая целостности основной
рабочей загрузочной карты.
Для обращения к разделам во втором способе используются пути:
/dev/block/sda - это вся карта полностью
/dev/block/sda1 - /dev/block/sda17
где (1...17 - порядковые номера разделов) -
для обращения к конкретному разделу.
Указания об использование других параметров команды dd, приведенные в описании первого способа,
остаются справедливыми и для второго способа (карта подключена к USB).
Заметим, что в случае использования не Андроида, а Линукса пути разделов
записываются несколько иначе: /dev/sda и /dev/sda1 - /dev/sda17 , т.е. без block/
Номера разделов в стоковой версии Android (для использования в командах dd):
1 - bootloader
2 - env
3 - boot
4 - super
5 - misc
6 - recovery
7 - cache
8 - vbmeta
9 - vbmeta_system
10 - vbmeta_vendor
11 - metadata
12 - private
13 - frp
14 - empty
15 - media_data
16 - Reserve0
17 - UDISK
Для анализа содержимого разделов, созданных на карте, используем описанный выше первый способ,
чтобы сохранить разделы в виде файлов с помощью консольной команды DD :
Вариант 1. Команды копирования карты по смещениям разделов
dd if=/dev/block/mmcblk0 of=bootloader-backup.img bs=512 skip=73728 count=65536
dd if=/dev/block/mmcblk0 of=env-backup.img bs=512 skip=139264 count=32768
dd if=/dev/block/mmcblk0 of=boot-backup.img bs=512 skip=172032 count=65536
dd if=/dev/block/mmcblk0 of=super-backup.img bs=512 skip=237568 count=3145728
dd if=/dev/block/mmcblk0 of=misc-backup.img bs=512 skip=3383296 count=32768
dd if=/dev/block/mmcblk0 of=recovery-backup.img bs=512 skip=3416064 count=65536
dd if=/dev/block/mmcblk0 of=cache-backup.img bs=512 skip=3481600 count=1310720
dd if=/dev/block/mmcblk0 of=vbmeta-backup.img bs=512 skip=4792320 count=32768
dd if=/dev/block/mmcblk0 of=vbmeta_system-backup.img bs=512 skip=4825088 count=32768
dd if=/dev/block/mmcblk0 of=vbmeta_vendor-backup.img bs=512 skip=4857856 count=32768
dd if=/dev/block/mmcblk0 of=metadata-backup.img bs=512 skip=4890624 count=32768
dd if=/dev/block/mmcblk0 of=private-backup.img bs=512 skip=4923392 count=32768
dd if=/dev/block/mmcblk0 of=frp-backup.img bs=512 skip=4956160 count=1024
dd if=/dev/block/mmcblk0 of=empty-backup.img bs=512 skip=4957184 count=31744
dd if=/dev/block/mmcblk0 of=media_data-backup.img bs=512 skip=4988928 count=32768
dd if=/dev/block/mmcblk0 of=Reserve0-backup.img bs=512 skip=5021696 count=32768
dd if=/dev/block/mmcblk0 of=UDISK-backup.img bs=512 skip=5054464 count=16
Примечания.
1. В этом варианте нужно точно указывать (в блоках !) смещения skip
и количества count, поэтому для ручной записи команд такой способ неудобен,
но для программной генерации списка команд (или даже скрипта) из таблицы GPT вполне приемлем
(именно так он здесь и появился).
2. Выражения bs=512 и bs=1b должны быть эквивалентны,
здесь b означает блок (block), т.е. 512 байт.
Цитата из man dd
N and BYTES may be followed by the following multiplicative suffixes:
c=1, w=2, b=512, kB=1000, K=1024, MB=1000*1000,
M=1024*1024, xM=M, GB=1000*1000*1000, G=1024*1024*1024,
and so on for T, P, E, Z, Y.
Binary prefixes can be used, too: KiB=K,MiB=M, and so on.
Ещё раз подчеркнем, что смещения skip и количества count указываются в блоках
(в приведенных выше примерах - в блоках размером 512 байт).
Хотя, в принципе существует возможность при необходимости всё указывать в байтах
(но при этом придётся оперировать с существенно большими числами, что повышает вероятность ошибки).
Для этого нужно добавить в dd-команду параметры:
iflag=count_bytes,skip_bytes
oflag=seek_bytes
Цитата из man dd :
count_bytes - treat 'count=N' as a byte count (iflag only)
skip_bytes - treat 'skip=N' as a byte count (iflag only)
seek_bytes - treat 'seek=N' as a byte count (oflag only)
Вариант 2. Команды копирования по номерам разделов
dd if=/dev/block/mmcblk0p1 of=backup1.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p2 of=backup2.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p3 of=backup3.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p4 of=backup4.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p5 of=backup5.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p6 of=backup6.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p7 of=backup7.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p8 of=backup8.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p9 of=backup9.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p10 of=backup10.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p11 of=backup11.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p12 of=backup12.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p13 of=backup13.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p14 of=backup14.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p15 of=backup15.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p16 of=backup16.img bs=512 conv=fsync
dd if=/dev/block/mmcblk0p17 of=backup17.img bs=512 count=16 conv=fsync
Примечания.
1. На карте должно быть свободное место не менее 2 Гбайт
2. Файлы копируются в предварительно назначенный текущий каталог на карте
3. Значение bs=512 задано равным размеру блока (сектора) для удобства, во 2-м варианте может быть другим.
4. Раздел UDISK (mmcblk0p17), занимающий всё оставшееся свободным место, может оказаться очень большим,
поэтому желательно ограничить размер файла принудительно параметром count
5. Разделы Super (mmcblk0p4)и Сache(mmcblk0p7) имеют большие размеры, поэтому для уменьшения файла
желательно копировать их с gzip-сжатием, например:
dd if=/dev/block/mmcblk0p4 | gzip > backup4.img.gz conv=fsync
dd if=/dev/block/mmcblk0p7 | gzip > backup7.img.gz conv=fsync
6. При использовании команд dd в консоли процесс копирования не отображается,
поэтому при копировании достаточно болших разделов нужно терпеливо ждать его завершения и появления
соответствующих сообщений. Желательно также добавить в dd-команды параметр status=progress.
В случае копирования бекапов разделов на USB-флешку команды выглядят так:
dd if=/dev/block/mmcblk0p4 | gzip > /mnt/media_rw/0000-006F/backup4.img.gz conv=fsync
dd if=/dev/block/mmcblk0p7 | gzip > /mnt/media_rw/0000-006F/backup7.img.gz conv=fsync
Здесь /mnt/media_rw/0000-006F/ - это имя конкретной USB-флешки, подключенной к USB-порту
устройства и автоматически монтированной в Андроиде.
Для восстановления бекапов разделов или их модификации при использовании 2-го способа
(карточка подключена к USB-порту) список dd-команд:
dd if=bootloader.img of=/dev/block/sda1 conv=fsync
dd if=env.img of=/dev/block/sda2 conv=fsync
dd if=boot.img of=/dev/block/sda3 conv=fsync
dd if=super.img of=/dev/block/sda4 conv=fsync
dd if=misc.img of=/dev/block/sda5 conv=fsync
dd if=recovery.img of=/dev/block/sda6 conv=fsync
dd if=cache.img of=/dev/block/sda7 conv=fsync
dd if=vbmeta.img of=/dev/block/sda8 conv=fsync
dd if=vbmeta_system.img of=/dev/block/sda9 conv=fsync
dd if=vbmeta_vendor.img of=/dev/block/sda10 conv=fsync
dd if=metadata.img of=/dev/block/sda11 conv=fsync
dd if=private.img of=/dev/block/sda12 conv=fsync
dd if=frp.img of=/dev/block/sda13 conv=fsync
dd if=empty.img of=/dev/block/sda14 conv=fsync
dd if=media_data.img of=/dev/block/sda15 conv=fsync
dd if=Reserve0.img of=/dev/block/sda16 conv=fsync
Примечания.
1. Файлы, имена которых указаны в левой части команды (if=),
должны находиться в текущей папке. Это могут быть файлы предварительно сделанных бекапов
разделов или файлы содержимого разделов из образа прошивки (исходные или модифицированные).
Имена файлов здесь указаны для удобства по имени соответствующего раздела.
2. Карта, на которую производится запись разделов, подключена через кардридер к USB-порту
устройства.
Для справки:
Продолжительность копирования раздела super на USB-флешку составляет 230 сек (примерно 6 минут)
На скорости 6.6 Mb/s скопировано 1610612736 байт (1.5 Gb)
Размер полученного файла gz-архива 399933252 байт (400 Mb), т.е. сжатие в 4 раза
Как ни странно, но разницы в скорости копирования на карту или USB-флешку никакой нет (от слова совсем),
для сравнения два результата dd:
на USB: 1610612736 bytes (1.5 G) copied, 229.706336 s, 6.6 M/s
на карту: 1610612736 bytes (1.5 G) copied, 229.045113 s, 6.7 M/s
Также на скорость не влияет (даже слегка замедляет) копирование не дефолтными блоками по 512 байт,
а большими блоками (например, по 8 Mb):
if=/dev/block/mmcblk0p4 bs=8M | gzip > backup4.img.gz
1610612736 bytes (1.5 G) copied, 248.327665 s, 6.1 M/s
Обратное копирование бекапа gzip-файла super.img.gz в одноименный раздел на карту
c USB-флешки выполняется командой :
gunzip -c /mnt/media_rw/0000-006F/backup4.img.gz | dd of=/dev/block/mmcblk0p4 conv=fsync,noerror bs=8M
Назначение, использование и содержимое разделов
Проверка содержимого файлов сохраненых копий разделов показывает:
1. В разделы, помеченные звездочкой, записаны файлы из образа прошивки
2. Разделы misc, private, empty, media_data - пустые (содержат нули)
3. Разделы cache, metadata, frp, Reserve0 содержат какую-то информацию (ненулевые байты)
1. bootloader - *
2. env - *
3. boot - *
4. super - *
5. misc - пусто
6. recovery - *
7. cache - ненулевых байтов: 24876 из 671088640
8. vbmeta - *
9. vbmeta_system - *
10. vbmeta_vendor - *
11. metadata - ненулевых байтов: 12656
12. private - пусто
13. frp - 36 символов в начале файла, дальше все нули
14. empty - пусто
15. media_data - пусто
16. Reserve0 - ненулевых байтов: 203
Ниже приведены предположения (не подтвержденные документально или пруфами) о предназначении
и использовании отдельных (не пустых) разделов, содержимое которых точно не определено, поэтому
не ясно, что должно (если должно) в них записываться при программировании.
Возможно, эти предположения не очень точные или даже сомнительные.
1. Раздел frp
FRP - это Factory Reset Protection, поэтому одноименный раздел frp имеет прямое
отношение к процедуре защиты Google-аккаунта после сброса на тех устройствах,
где установлены сервисы гугля, и создан гугль-аккаунт. После сброса к заводским (Factory Reset)
на таких устройствах загрузка Андроида блокируется до ввода сохраненных данных гугль-аккаунта.
В разделе FRP хранятся ключи FRP Lock, поэтому его очистка приводит к разблокировке
защиты Google-аккаунта.
Для платы OpiZero2 установка и использование сервисов гугля нецелесообразно и затруднительно
из-за недостаточного (1 Гб) объема оперативной памяти. Поэтому здесь раздел FRP не используется,
и файл, полученный при его бекап-копировании, практически пуст (за исключением первых 36 байт).
2. Раздел Reserve0
Теоретически, в начало этого раздела предполагается запись резервной копия таблицы разделов GPT.
Это видно из совпадения адреса начального блока раздела Reserve0 со значением
Alternate LBA ( N блока резервного GPT-раздела) в заголовке таблицы GPT.
Однако, практически этого не происходит, т.к. об отсутствии резервного GPT сообщают
работающие с GPT утилиты.
Запись резервной копии GPT в раздел Reserve0 возможна, например, командами: (не проверено !)
dd if=/dev/block/mmcblk0 of=resgpt.img bs=512 count=16
dd if=resgpt.img of=/dev/block/mmcblk0p16 bs=512
Анализ содержимого бекап-копии этого раздела показывает, что на нём монтируется какой-то пустой
диск FAT16.
3. Раздел metadata
Из названия раздела видно, что в него предполагается запись каких-то метаданных,
но происходит ли это при программировании карты (и какие конкретно данные записываются) - неизвестно.
4. Раздел cache
Скорее всего, в этот раздел на этапе записи карты ничего не записывается, а раздел
имеет ну очень болшой размер из-за необходимости держать в нём систему при OTA-обновлении,
т.е. на загруженном и работающем устройстве.