diff --git a/README.md b/README.md index 6c0ccb3..5074a49 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # avbroot +(This page is also available in: [Russian (Русский)](./README.ru.md).) + avbroot is a program for patching Android A/B-style OTA images for root access while preserving AVB (Android Verified Boot) using custom signing keys. It is compatible with both Magisk and KernelSU. If desired, it can also just re-sign an OTA without enabling root access. Having a good understanding of how AVB and A/B OTAs work is recommended prior to using avbroot. At the very least, please make sure the [warnings and caveats](#warnings-and-caveats) are well-understood to avoid the risk of hard bricking. diff --git a/README.ru.md b/README.ru.md new file mode 100644 index 0000000..599ec16 --- /dev/null +++ b/README.ru.md @@ -0,0 +1,460 @@ +# avbroot + +avbroot – это программа для модификации OTA-образов Android A/B-формата с целью получения root-прав при сохранении прохождения AVB (Android Verified Boot) с использованием кастомных (пользовательских) ключей подписи. Она совместима как с Magisk, так и с KernelSU. При необходимости можно просто переподписать OTA, без получения root-доступа. + +Прежде чем использовать avbroot, рекомендуется иметь хорошее понимание того, как работают AVB и OTA в формате A/B. Как минимум, следует ознакомиться с [разделом предостережений,](#предостережения) чтобы избежать хардбрика устройства. + +**ПРИМЕЧАНИЕ:** avbroot 2.0 была переписана на Rust и больше не имеет в основе никакого кода AOSP, а CLI полностью обратно совместим. Тем не менее, старую реализацию на Python можно найти в одноименной ветке `python`. + +## Требования + +* Поддерживаются только устройства, использующие современную A/B-разметку. Это большинство девайсов, выпускаемых с Android 10 и новее (за исключением устройств от Samsung). Чтобы проверить, использует ли ваш телефон необходимую схему разметки, откройте zip-архив OTA и проверьте: + + * наличие файла `payload.bin` (обычно находится в корне архива) + * наличие файла `META-INF/com/android/metadata` (Android 10-11) или `META-INF/com/android/metadata.pb` (Android 12+) + +* Устройство должно поддерживать установку пользовательского публичного ключа для подтверждения статуса доверия загрузчика. Обычно это делается с помощью команды `fastboot flash avb_custom_key`. Все устройства Pixel с разблокируемым загрузчиком, начиная с Pixel 2, поддерживают эту функцию. Другие устройства тоже могут поддерживать её, но достоверно убедиться в этом можно только проверив лично. + + * ПРИМЕЧАНИЕ: Некоторые девайсы от OnePlus имеют некорректную реализацию, где возможна установка кастомного публичного ключа, но устройство все равно не будет загружаться, несмотря на наличие корректной подписи. Понижение загрузчика до версии, поставляемой вместе с Android 11, потенциально может помочь. Уже сообщалось о наличии этой проблемы на нескольких устройствах OnePlus ([#186,](https://github.com/chenxiaolong/avbroot/issues/186) [#195,](https://github.com/chenxiaolong/avbroot/discussions/195) [#212](https://github.com/chenxiaolong/avbroot/issues/212)). + +## Патчи + +avbroot модифицирует следующие образы: + +* `boot` или `init_boot`, в зависимости от устройства, модифицируется для получения root-доступа. В случае с Magisk, патч будет эквивалентен тому, что производится в самом приложении Magisk. + +* `boot`, `recovery` или `vendor_boot`, в зависимости от устройства, модифицируется для замены сертификата проверки подписи OTA на пользовательский. Это позволяет устанавливать будущие пропатченные OTA через режим Recovery уже после блокировки загрузчика, то есть в качестве обновления. Также это предотвращает случайную установку оригинального непропатченного OTA. + +* `system` тоже модифицируется для замены сертификата проверки подписи OTA. Это не позволит системному приложению обновлений ОС установить оригинальный непропатченный OTA и дает возможность использовать сторонние приложения для установки пропатченных OTA. + +## Предостережения + +* **Всегда оставляйте опцию `Заводской разблокировки`** (или OEM unlocking в англ.) **включенной при наличии root-прав с заблокированным загрузчиком.** Это очень важно. Доступ к root-правам потенциально позволяет перезаписать загрузочный раздел из-под системы, будь то сделано случайно или намеренно, файлом, который не был подписан должным образом. В таком случае, система и режим Recovery больше не смогут загрузиться, а команда `fastboot flashing unlock` будет недоступна, потому что параметр Заводской разблокировки отключен. То есть, это приведет к **_хардбрику устройства_**. + + Повторюсь: **_ВСЕГДА оставляйте `Заводскую разблокировку` включенной при наличии root-прав._** + +* Любая операция, приводящая к прошивке некорректно подписанного загрузочного образа, приведет к тому, что устройство больше не сможет загрузиться в систему/режим Recovery, а для его восстановления потребуется повторная разблокировка загрузчика (и, следовательно, стирание всех пользовательских данных). Это же относится и к методу `Прямой установки` для обновления Magisk. Обновление Magisk **должно выполняться только путем обновления OTA,** а не через Magisk Manager. + + Если в загрузочный раздел были внесены какие-либо изменения, **не перезагружайтесь**. Обратитесь за помощью, [открыв Issue,](https://github.com/chenxiaolong/avbroot/issues/new) и четко разъясните, какие конкретные действия привели к возникновению такой ситуации. Если Android всё еще работает и доступ к root-правам сохранился – вероятно, получится откатить изменения до исходного состояния, не стирая ваши данные. + +## Использование + +1. Убедитесь, что вы ознакомились и поняли указанные выше [предостережения.](#предостережения) + +2. Скачайте последнюю версию со страницы [релизов.](https://github.com/chenxiaolong/avbroot/releases) Чтобы сверить цифровую подпись, см. раздел [проверки цифровых подписей.](#проверка-цифровых-подписей) + + avbroot – это отдельный исполняемый файл. Он не требует установки и может быть запущен из любого места на диске. + +3. [Сгенерируйте ключи подписи.](#генерация-ключей) + +4. Пропатчите ОТА-архив с помощью команды: + + ```bash + avbroot ota patch \ + --input /путь/к/ota.zip \ + --key-avb /путь/к/avb.key \ + --key-ota /путь/к/ota.key \ + --cert-ota /путь/к/ota.crt \ + ``` + + Добавьте следующие аргументы в конец команды в зависимости от того, как вы хотите получить root-доступ. + + * Для получения root-доступа с использованием Magisk: + + ```bash + --magisk /путь/к/magisk.apk \ + --magisk-preinit-device <имя> + ``` + + Если вы не знаете имени раздела предварительной инициализации Magisk, следуйте инструкции [в соответствующем разделе.](#предварительная-инициализация-устройства-для-magisk) + + Если вы пропатчили загрузочный образ вручную через приложение Magisk (вместо автоматического идентичного патчинга через avbroot), используйте следующий аргумент: + + ```bash + --prepatched /путь/к/magisk_patched-xxxxx_yyyyy.img + ``` + + * Для получения root-доступа с использованием KernelSU: + + ```bash + --prepatched /путь/к/kernelsu_boot.img + ``` + + * Без root-доступа: + + ```bash + --rootless + ``` + + Больше информации про существующие аргументы можно найти в разделе [расширенного использования.](#расширенное-использование) + + Если название для `--output` не указывается, то готовый файл будет записан как `<название-ota-zip-в-input>.patched`. + +5. Готово! Для прошивки пропатченного OTA следуйте инструкции в разделе [первоначальной настройки.](#первоначальная-настройка) Для последующих обновлений тоже есть соответствующий [раздел обновлений.](#обновления) + +## Генерация ключей + +Во время патчинга OTA, avbroot подписывает несколько компонентов: + +* загрузочный образ (boot) +* образ vbmeta +* payload из OTA +* сам архив OTA + +Первые два компонента подписываются ключом AVB, а последние два – ключом OTA. Можно использовать один и тот же ключ, однако в следующих шагах описано, как сгенерировать два отдельных. + +Если вы патчите OTA сразу для нескольких устройств, настоятельно рекомендуется генерировать уникальные ключи для каждого девайса – так вы защитите себя от случайной прошивки неподходящего OTA для другого телефона. + +1. Сгенерируйте ключи подписи для AVB и OTA. + + ```bash + avbroot key generate-key -o avb.key + avbroot key generate-key -o ota.key + ``` + +2. Преобразуйте публичную часть ключа подписи AVB в формат метаданных публичного ключа AVB. Именно этот формат используется в загрузчике устройства для установки пользовательского ключа. + + ```bash + avbroot key extract-avb -k avb.key -o avb_pkmd.bin + ``` + +3. Сгенерируйте самоподписанный сертификат для ключа подписи OTA. Он используется режимом Recovery для проверки подписи OTA при сайдлоадинге обновления. + + ```bash + avbroot key generate-cert -k ota.key -o ota.crt + ``` + +avbroot совместим с любым стандартным 4096-битным приватным ключом RSA в кодировке PKCS8 и сертификатом X509 в кодировке PEM, например с теми, которые генерируются openssl. + +Если вы потеряете ключ(-и) подписи AVB или OTA, вы больше не сможете подписывать новые OTA-архивы. Придется генерировать новые ключи подписи и разблокировать загрузчик (что приведет к стиранию всех данных). В таком случае возвращайтесь к инструкции в разделе [использования.](#использование) + +## Первоначальная настройка + +1. Перезагрузитесь в режим fastboot и разблокируйте загрузчик, если не сделали этого ранее. Это приведет к стиранию всех пользовательских данных. + + ```bash + fastboot flashing unlock + ``` + +2. Перед первой установкой, на устройстве уже должна быть установлена в оригинальном виде та прошивка, пропатченную версию которой вы собираетесь ставить. Если это не так, сначала установите оригинальную непропатченную OTA. + +3. Извлекаем из пропатченного OTA модифицированные образы: + + ```bash + avbroot ota extract \ + --input /путь/к/ota.zip.patched \ + --directory extracted \ + --fastboot + ``` + + Если вы на всякий случай хотите прошить вообще все разделы из ОТА, извлечь их можно, указав аргумент `--all`. + +4. Прошейте извлеченные образы разделов. + + ```bash + ANDROID_PRODUCT_OUT=extracted fastboot flashall --skip-reboot + ``` + + Обратите внимание, что так прошиваются лишь те образы, что относятся к системе. Разделы загрузчика и модема же остаются нетронутыми из-за ограничений fastboot. Если они не обновлены до необходимой версии, или вы не уверены в этом, после прошивки перейдите к пункту [обновлений](#обновления) и установите пропатченный OTA-архив сайдлоадом в режиме Recovery. Прошивка полного OTA гарантирует, что абсолютно все разделы будут обновлены. + + Для устройств Pixel есть ещё один вариант: запуск скрипта `flash-base.sh` из папки заводских образов (factory images) обновит загрузчик и модем. + +5. После перезагрузки из fastbootd в загрузчик (bootloader), установите пользовательский публичный ключ AVB в загрузчик: + + ```bash + fastboot reboot-bootloader + fastboot erase avb_custom_key + fastboot flash avb_custom_key /путь/к/avb_pkmd.bin + ``` + +6. **[Опционально]** Перед блокировкой загрузчика загрузитесь в систему, дабы убедиться, что все подписано правильно. + + Установите приложение Magisk или KernelSU и выполните следующую команду: + + ```bash + adb shell su -c 'dmesg | grep libfs_avb' + ``` + + Если AVB работает корректно, будет выведено следующее сообщение: + + ```bash + init: [libfs_avb]Returning avb_handle with status: Success + ``` + +7. Перезагрузитесь в fastboot и заблокируйте загрузчик. Это снова приведет к стиранию данных. + + ```bash + fastboot flashing lock + ``` + + Подтвердите нажатием клавиш уменьшения громкости и включения, а после перезагрузитесь в систему. + + Напоминаю: **не отключайте `Заводскую разблокировку`!** + + **ПРЕДУПРЕЖДЕНИЕ**: Если вы прошили CalyxOS, мастер настройки [автоматически отключит опцию `Заводской разблокировки`.](https://github.com/CalyxOS/platform_packages_apps_SetupWizard/blob/7d2df25cedcbff83ddb608e628f9d97b38259c26/src/org/lineageos/setupwizard/SetupWizardApp.java#L135-L140) Не забудьте снова включить её вручную в настройках для разработчиков. Для перестраховки можете использовать [модуль `OEMUnlockOnBoot`,](https://github.com/chenxiaolong/OEMUnlockOnBoot) который автоматически включает пункт Заводской разблокировки при каждом запуске системы. + +8. Готово. Установка последующих обновлений системы, Magisk или KernelSU, описывается в [следующем разделе.](#обновления) + +## Обновления + +Обновления Android, Magisk и KernelSU выполняются одинаково – исключительно путем обновления или репатчинга того же самого OTA. + +1. Если Magisk или KernelSU обновились, сначала установите их новый `.apk`. Если вы случайно открыли приложение после обновления, убедитесь, что оно не начало прошивать загрузочный образ. Если появится предложение обновить сам загрузочный образ – отклоните его. + +2. Следуйте инструкции в разделе [использования,](#использование) чтобы пропатчить OTA уже с новым .apk Magisk'а/предварительно пропатченным образом с Magisk или KernelSU. + +3. Перезагрузитесь в режим Recovery. Если устройство повисло на сплеше с сообщением "No command", удерживайте кнопку питания, а затем нажмите кнопку увеличения громкости один раз. + +4. Обновитесь (Apply update from adb → `adb sideload `). + +5. Готово! + +## Возврат на заводскую прошивку + +Если вы хотите отказаться от использования avbroot и вернуться на стоковую прошивку: + +1. Перезагрузитесь в режим fastboot и разблокируйте загрузчик. Это приведет к стиранию всех пользовательских данных. + +2. Удалите пользовательский публичный ключ AVB. + + ```bash + fastboot erase avb_custom_key + ``` + +3. Прошейте стоковую прошивку. Готово. + +## OTA-обновления + +avbroot заменяет `/system/etc/security/otacerts.zip` в разделах системы и Recovery на новый архив, содержащий пользовательский сертификат подписи OTA. Это предотвращает случайную установку непропатченных OTA как при загрузке в Android, так и при сайдлоадинге через Recovery. + +Рекомендуется отключить приложение обновлений системы, чтобы оно не пыталось установить непропатченные OTA: + +* Стоковая прошивка: Отключите `Автоматические обновления системы` (Automatic system updates в англ.) в настройках для разработчиков. +* Кастомная прошивка: Отключите приложение обновлений системы (или запретите ему доступ к Интернету) через Настройки -> Приложения -> Все приложения -> (меню/три точки) -> Показать системные -> (найдите приложение обновлений, например Обновления системы/Updater). + +Это особенно важно для некоторых кастомных прошивок, поскольку их фирменное приложение для обновления системы может уйти в бесконечный цикл, загружая OTA-обновление, а затем повторяя попытку загрузки и установки при неудачной проверке подписи. + +Если вы хотите поднять собственный сервер для ОТА-обновлений, вам может быть интересно приложение [Custota.](https://github.com/chenxiaolong/Custota) + +## Режим обслуживания + +Некоторые устройства поставляются с режимом обслуживания, который загружает систему с чистым образом `userdata`, благодаря чему специалист по ремонту может проводить диагностику устройства, не имея доступа к пользовательским данным владельца. + +Если на устройстве есть root-права, использовать этот режим небезопасно. Если у вас обычная сборка Magisk/KernelSU, не подписанная вашим собственным ключом, кто угодно может установить официальное приложение Magisk/KernelSU в режиме обслуживания и запросто получить root-права без какой-либо аутентификации. + +Потому, чтобы безопасно использовать режим обслуживания: + +1. Отключите root-доступ на устройстве, пропатчив OTA с аргументом `--rootless` (вместо `--magisk` или `--prepatched`) и прошив его. + +2. Включите режим обслуживания. + +3. Получив отремонтированное устройство обратно, выйдите из режима обслуживания. + +4. Прошейте рутированный OTA в обычном режиме. + +Поскольку удаление root-прав и повторное их получение выполняются путем перепрошивки OTA, данные устройства стёрты не будут. + +## Предварительная инициализация устройства для Magisk + +Magisk версии 25211 и новее требует наличие раздела, доступного для записи пользовательских правил SELinux, к которым необходимо обращаться на ранних этапах загрузки. Его можно определить только на реальном устройстве, поэтому avbroot требует указания точного названия с помощью аргумента `--magisk-preinit-device <имя>`. Чтобы получить имя раздела: + +1. Извлеките загрузочный образ из оригинального, непропатченного OTA: + + ```bash + avbroot ota extract \ + --input /path/to/ota.zip \ + --directory . \ + --boot-only + ``` + +2. Теперь нужно пропатчить загрузочный образ с помощью приложения Magisk. Это **ДОЛЖНО** быть сделано именно на целевом устройстве или устройстве той же модели! Имя раздела будет неверным и не подойдет, если пропатчить образ на устройстве иной модели. + + Приложение Magisk выведет в лог строку, подобную следующей: + + ``` + - Pre-init storage partition device ID: <имя> + ``` + + Также и avbroot может вывести информацию о разделе, обнаруженном Magisk, для этого выполните команду: + + ```bash + avbroot boot magisk-info \ + --image magisk_patched-*.img + ``` + + Имя раздела будет выведено как: `PREINITDEVICE=<имя>`. + + Теперь, когда имя раздела известно, его нужно указать avbroot с помощью команды `--magisk-preinit-device <имя>`. Имя раздела стоит запомнить или сохранить где-нибудь на будущее, оно вряд ли изменится при обновлении Magisk. + +Если запустить приложение Magisk на целевом устройстве невозможно (например, телефон не загружается), пропатчите OTA с аргументом `--ignore-magisk-warnings` и прошейте его. Затем выполните указанные выше шаги и повторно пропатчите OTA, но уже с указанием аргумента `--magisk-preinit-device <имя>`. + +## Проверка OTA + +Чтобы проверить все подписи и хэши, связанные с установкой OTA и процессом загрузки AVB, выполните команду: + +```bash +avbroot ota verify \ + --input /путь/к/ota.zip \ + --cert-ota /путь/к/ota.crt \ + --public-key-avb /путь/к/avb_pkmd.bin +``` + +Эта команда работает для любого OTA, независимо от того, пропатчено оно или нет. + +Если опции `--cert-ota` и `--public-key-avb` не указаны, то подписи проверяются только на корректность, не проверяя, совпадают ли они внутри всех файлов. + +## Подсказки через Tab + +Поскольку avbroot имеет множество опций, будет удобно настроить подсказки с автозаполнением для используемой оболочки. Конфигурации генерируются в самом avbroot. + +#### bash + +Добавьте в `~/.bashrc`: + +```bash +eval "$(avbroot completion -s bash)" +``` + +#### zsh + +Добавьте в `~/.zshrc`: + +```bash +eval "$(avbroot completion -s zsh)" +``` + +#### fish + +Добавьте в `~/.config/fish/config.fish`: + +```bash +avbroot completion -s fish | source +``` + +#### PowerShell + +Добавьте в загрузочный скрипт PowerShell (`profile.ps1`): + +```powershell +Invoke-Expression (& avbroot completion -s powershell) +``` + +## Расширенное использование + +### Использование заранее пропатченного boot.img + +avbroot может подменить используемый загрузочный образ на заранее пропатченный (вместо того, чтобы самостоятельно применять патч). Это пригодится в случае, если у вас уже имеется пропатченный через приложение Magisk образ ядра или образ с поддержкой KernelSU. Для этого используйте аргумент `--prepatched <загрузочный образ>` вместо `--magisk `. То есть, указав `--prepatched`, avbroot пропустит применение патчинга Magisk'ом, но по-прежнему применит патч OTA-сертификата. + +Обратите внимание, что avbroot проверяет совместимость предварительно пропатченного образа с оригинальным. Например, если поля заголовка образа не совпадают, или вовсе указан иной, незагрузочный образ, то процесс патча будет прерван. Эти проверки, конечно, ничего не гарантируют, но должны предостеречь от случайного использования некорректного образа. Чтобы обойти базовые проверки безопасности, укажите аргумент `--ignore-prepatched-compat`. Если вы хотите убрать вообще все проверки (чего делать крайне не рекомендуется), укажите его дважды. + +### Пропуск патчей для root-доступа + +avbroot можно использовать для простого переподписания OTA, указав аргумент `--rootless` вместо `--magisk`/`--prepatched`. В таком случае пропатченный OTA не будет рутирован. Единственная модификация, которая будет применена – это замена сертификата проверки OTA, чтобы систему можно было обновлять с помощью будущих пропатченных OTA. + +### Подмена разделов + +avbroot поддерживает подмену целых образов в OTA, даже тех, что не являются загрузочными (например, `vendor_dlkm`). Образ можно заменить, указав аргумент `--replace <имя раздела> /путь/к/образу.img`. + +Единственное, что меняется – это то, откуда считывается раздел. При использовании `--replace` вместо использования образа раздела из оригинального `payload.bin` в OTA, он берется напрямую по указанному вами пути. Таким образом, заменяющие образы разделов должны иметь правильные колонтитулы vbmeta, соответствующие оригинальным. + +Это не влияет на ход применения пачтей. Например, при использовании Magisk, патч получения root-прав применяется к загрузочному образу одинаково, независимо от того, был ли он получен из оригинального `payload.bin` или это файл, указанный через `--replace`. + +### Очистка флагов vbmeta + +Некоторые сборки Android-прошивок могут поставляться с образом `vbmeta`, в котором флаги установлены таким образом, что AVB фактически отключен. Если avbroot сталкивается с такими образом, процесс патчинга завершается ошибкой с сообщением следующего типа: + +``` +Verified boot is disabled by vbmeta's header flags: 0x3 +``` + +Чтобы принудительно включить AVB (очистив флаги), укажите аргумент `--clear-vbmeta-flags`. + +### Использование в неинтерактивном режиме + +По умолчанию avbroot интерактивно запрашивает пароли к приватным ключам. Чтобы запустить avbroot в неинтерактивном режиме, можно: + +* Предоставить пароли через файлы: + + ```bash + avbroot ota patch \ + --pass-avb-file /путь/к/avb.passphrase \ + --pass-ota-file /путь/к/ota.passphrase \ + <...> + ``` + + На Unix-подобных системах "файлы" могут быть каналами ("pipes"). В оболочках, поддерживающих подстановку процесса (bash, zsh и т. д.), пароль можно запросить с помощью команды (например, запрашивая у менеджера паролей). + + ```bash + avbroot ota patch \ + --pass-avb-file <(команда для запроса пароля AVB) \ + --pass-ota-file <(команда для запроса пароля OTA) \ + <...> + ``` + +* Предоставить пароли через переменные среды. Это менее безопасно, поскольку любой процесс, запущенный от имени того же пользователя, может видеть значения переменных среды. + + ```bash + export PASSPHRASE_AVB="пароль AVB" + export PASSPHRASE_OTA="пароль OTA" + + avbroot ota patch \ + --pass-avb-env-var PASSPHRASE_AVB \ + --pass-ota-env-var PASSPHRASE_OTA \ + <...> + ``` + +* Использовать незашифрованные приватные ключи. Крайне не рекомендуется. + +### Извлечение всей OTA + +Чтобы извлечь все образы, содержащиеся в `payload.bin`, используйте команду: + +```bash +avbroot ota extract \ + --input /путь/к/ota.zip \ + --directory extracted \ + --all +``` + +## Сборка из исходного кода + +Убедитесь, что у вас установлен [набор инструментов Rust.](https://www.rust-lang.org/ru/) Затем выполните: + +```bash +cargo build --release +``` + +Исполняемый файл будет записан в `target/release/avbroot`. + +Дебаг-сборки тоже работают, но они будут работать значительно медленнее (в вычислениях sha256), потому что оптимизации компилятора отключены. + +По умолчанию исполняемый файл ссылается на системные библиотеки bzip2 и liblzma, от которых зависит avbroot. Чтобы скомпилировать и статически связать эти две библиотеки, укажите аргумент `--features static`. + +## Проверка цифровых подписей + +Сначала сохраните открытый ключ в файл, перечисляющий ключи, которым можно доверять. Это тот же ключ, который указан [в профиле автора.](https://github.com/chenxiaolong/) + +```bash +echo 'avbroot ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDOe6/tBnO7xZhAWXRj3ApUYgn+XZ0wnQiXM8B7tPgv4' > avbroot_trusted_keys +``` + +Затем проверьте подпись zip-файла, используя список доверенных ключей. + +```bash +ssh-keygen -Y verify -f avbroot_trusted_keys -I avbroot -n file -s .zip.sig < .zip +``` + +Если файл успешно проверен, вывод будет следующим: + +``` +Good "file" signature for avbroot with ED25519 key SHA256:Ct0HoRyrFLrnF9W+A/BKEiJmwx7yWkgaW/JvghKrboA +``` + +## Вклад + +Буду рад вашему вкладу в разработку! Однако я вряд ли приму изменения для поддержки устройств, которые ведут себя значительно иначе, чем устройства Pixel. + +## Лицензия + +avbroot распространяется по лицензии GPLv3. Полный текст лицензии см. в [`LICENSE`.](./LICENSE) +