Компіляція ядра¶
Цей розділ пояснює як налаштувати для компіляції джерельний код пристрою, інформацію про пристрій та ядро. У цих настановах очікується, що Ви маєте необхідні знання для роботи з git, такі як клонування, пуш та створення репозиторію.
Налаштування власного середовища для компіляції¶
Assuming you have already installed the tools specified in the section on Setting up the build environment, there are just a few more to add before your build environment is complete. Run this commmand to add them:
sudo apt install bc bison build-essential \
ca-certificates cpio curl flex git kmod libssl-dev libtinfo5 python2 \
sudo unzip wget xz-utils img2simg jq
If you use a RPM based distro such as Mageia, you run:
sudo urpmi gcc make glibc-devel bc bison \
rootcerts cpio curl flex git kmod libopenssl-devel libncurses5 python3 \
unzip wget xz android-tools jq
Примітка
Для деяких старих ядер для компіляції можливо потрібний Python 2. Якщо Ваш дистрибутив не підтримує Python 2, можливо, його буде потрібно встановити вручну.
Установка та налаштування джерела пристрою¶
Створення джерела пристрою¶
Склонуйте наявний репозиторій пристрою з https://gitlab.com/ubports/porting. Найкраще буде вибрати за основу пристрій з такою самою версією SoC/Android.
Переконайтеся, що Ви отримали репозиторій пристрою, а не ядра (Ви отримаєте його на наступному кроці). Наприклад, для Fairphone 3, репозиторії називаються fairphone-fp3 та android_kernel_fairphone_sdm632. Перше — це те, що потрібно.
Файл deviceinfo містить налаштування, потрібні для створення ядра (kernel, boot, в разі необхідності dtb/dtbo + recovery на останніх етапах). Для створення власного deviceinfo, тримайтеся наступних настанов.
Отримання початкового коду ядра пристрою¶
Перша річ, яку потрібно перевірити — це наявність офіційного чи неофіційного порту LineageOS для Вашого пристрою, оскільки можливо його автор вже виконав очищення бітів, необхідне для первісного коду ядра від постачальника пристрою чи вбудував зовнішні модулі до дерева ядра, що значно полегшує життя.
Якщо ні, перевірте чи взагалі виробник пристрою надає джерельний код: ASUS, Lenovo, Samsung, ZTE зазвичай надають код у тарболах на своїх сайтах. Motorola, Realme, OnePlus, Xiaomi зазвичай завантажують код ядра до власних офіційних сторінок на GitHub.
Після того як Ви отримали джерело ядра, Вам потрібно завантажити його в інше місце, щоб можна було вносити зміни та коміти для Ubuntu Touch. Кращим буде GitLab, оскільки після завантаження (pull) порту до UBports org, його можна буде просто звідти скопіювати.
Тепер Вам буде потрібно працювати з двома репозиторіями: клонований репозиторій пристрою, який містить deviceinfo та репозиторій ядра, у якому міститься чи буде міститися Ваш defconfig (див. нижче).
Пошук Вашої правильної конфігурації ядра¶
Існує два шляхи як знайти правильну конфігурацію ядра, власне: 1. Отримання своєї конфігурації на пристрої з /proc/config.gz 2. Отримання свого defconfig з коду ядра
Отримання файлу налаштувань з пристрою¶
Можна отримати поточний конфіг з пристрою, якщо конфігурація наявна на пристрої у /proc/config.gz. Для отримання цього конфігу, скопіюйте файл /proc/config.gz з Вашого пристрою на комп’ютер. Потім запустіть zcat для отримання вмісту цього файлу. Збережіть результат як .config у коді ядра. Після цього виконайте ARCH=<архітектура Вашого пристрою> make savedefconfig, що перетворить Вашу повну конфігурацію на defconfig. Скопіюйте defconfig до arch/<архітектура Вашого пристрою>/configs/<кодова назва Вашого пристрою_defconfig>.
Виконайте настанови для внесення змін/латок до конфігурації.
Отримання свого defconfig з коду ядра¶
Щоб знайти свій defconfig з коду ядра, Вам потрібно шукати його у директорії arch/<your device's architecture/configs. Цей defconfig може мати будь-яку назву, щось схоже на <кодова назва Вашого пристрою>_defconfig чи щось складне типу k61v64_debug_defconfig. Якщо Ви отримали код ядра з OEM, іноді він може містити скрипт build.sh, необхідний для defconfig. В іншому разі, якщо Ваш код ядра з чогось типу LineageOS, їх дерево також посилається на defconfig.
Після знахідки свого defconfig, виконайте настанови для додавання латок.
Виконання мінімальних латок для defconfig¶
Для вдалого завантаження Ubuntu Touch, потрібно увімкнути деякі налаштування, необхідні для ОС. Почніть з перегляду каталогу ядра та arch/<архітектура Вашого пристрою>/configs, куди потрібно додати новий файл halium.config. Додайте такий вміст до цього файлу:
CONFIG_DEVTMPFS=yCONFIG_FHANDLE=yCONFIG_SYSVIPC=yCONFIG_IPC_NS=yCONFIG_NET_NS=yCONFIG_PID_NS=yCONFIG_USER_NS=yCONFIG_UTS_NS=yCONFIG_VT=y
Після цього збережіть та закрийте цей файл. Якщо хочете, можете виконати коміт до репозиторію свого ядра, оскільки назва цього файлу буде додана до deviceinfo.
На цьому місці Ви майже завершили початкові налаштування для ядра, перейдіть до deviceinfo та до компіляції.
Після вдалого завантаження ОС, можна перейти до повного латання defconfig на наступних етапах.
Підказка: можливо Вас здивує чому ми змінюємо окремий файл halium.config замість <кодова назва>_defconfig. Ці файли будуть обрані разом у deviceinfo, «поєднуючи» їх. Таким чином, ми зберігаємо ці зміни ясними та зрозумілими.
Заповнення інформації про deviceinfo¶
Повна назва пристрою, напр. Redmi 9C чи Redmi Note 10S. Замініть за необхідності.
deviceinfo_name="Redmi 9C"
Назва виробника пристрою. За потреби замініть.
deviceinfo_manufacturer="Xiaomi"
Кодова назва телефону. Можна отримати через пошуковий запит, щось типу «<назва пристрою> codename». Замініть назву нижче на назву свого пристрою. Замініть також кодову назву на свою.
deviceinfo_codename="angelica"
Архітектура необхідного Вам ядра. Більшість пристроїв, створених після 2015 року побудовані на процесорі ARM64, але якісь дивні можуть бути armhf. Для пристроїв ARM64 встановіть значення «aarch64». Для armhf — «armv7».
deviceinfo_arch="aarch64"
Цей пункт визначає репозиторій git, де зберігається Ваше ядро. Коли Ви переходите до розділу 1, Ви вже повинні мати це посилання під рукою, але якщо його немає, пройдіть цей шлях знову. Замініть посилання нижче своїм.
deviceinfo_kernel_source="https://github.com/muhammad23012009/android_kernel_xiaomi_dandelion"
Далі йде гілка (branch) цього ядра. ЇЇ можна отримати, переглянувши на GitHub вкладку під вкладкою Код (Code) або вкладку у верхньому лівому куті. За потреби замініть на свою.
deviceinfo_kernel_source_branch="halium10-new"
Defconfig — життєво важлива частина для компіляції ядра. У більшості випадків знайти цей defconfig можна у коді ядра, зі шляхом до нього «arch/<Ваша архітектура>/configs». Ця назва defconfig часто компілюється як «<Ваша кодова назва>_defconfig». Коли знайдете свій defconfig, замініть його за необхідності. Вам також буде потрібно додати у цьому полі
halium.config, через додавання вище латок для конфігурації ядра. (Якщо Ви досі не можете знайти defconfig, зверніться до розділу «Пошук defconfig»)
deviceinfo_kernel_defconfig="angelica_defconfig halium.config"
Командний рядок для ядра — одна з ключових частин, необхідних для завантаження ядра. Він має особливі параметри, які допомагають ядру визначити які функції чи модулі потрібно активувати, а які вимкнути. Кореневий каталог Ubuntu Touch також використовує деякі опції командного рядку, необхідні для завантаження, зокрема «console=tty0». Щоб адаптувати це до свого пристрою, спробуйте розпакувати завантажувальний образ (розділ 8.3) та скопіювати звідти командний рядок або, якщо це доступно, скористайтеся допомогою з дерева пристроїв LineageOS. Команда «console=tty0» є обов’язковою і повинна бути присутньою у будь-якому разі. Решту можна видалити та потім налаштувати все під свій пристрій. Параметр
console=tty0є необхідним для правильного завантаження кореневої системи rootfs. Рядокsystempartдодається, якщо потрібно завантажити rootfs зі свого системного розділу. Він має вказувати на Ваш системний розділ.
deviceinfo_kernel_cmdline="console=tty0 bootopt=64S3,32N2,64N2 systempart=/dev/mapper/system"
Якщо бажаєте скомпілювати своє ядро з clang додайте до deviceinfo цю опцію. Більшість пристроїв, створених з Android 10 чи пізніше, компілюють свої ядра з clang. Якщо не бажаєте використовувати clang, пропустіть цей запис повністю.
deviceinfo_kernel_clang_compile="true"
Потрібне лише якщо Ви бажаєте користуватися для лінкування LLD та активувати LTO. Для більшості тарих ядер LTO не працює. Якщо все ж таки бажаєте мати таку опцію, додайте її до свого deviceinfo, в іншому разі пропустіть це.
deviceinfo_kernel_use_lld="true"
Це налаштування допоможе Вам скомпілювати своє ядро з LLVM та LTO, якщо це підтримується. Це елегантний шлях поєднання
clangтаld.lld. Зазвичай це потрібно пристроям GKI. (Увімкнувши тут, не потрібно зазначатиdeviceinfo_kernel_use_lld)
deviceinfo_kernel_llvm_compile="true"
Цією опцією користуйтеся для увімкнення „dtc_ext“ під час компіляції dtb/dtbo. Але робіть це лише якщо розумієте, що робите. Типовий компілятор працює у більшості випадків.
deviceinfo_kernel_use_dtc_ext="true"
Використовуйте цей параметр, якщо хочете вказати назву образу ядра після компіляції ядра. Найчастіше це не потрібно, тому це можна видалити зі свого опису пристрою deviceinfo. Якщо Вам це потрібно, змініть назву образу.
deviceinfo_kernel_image_name="Image.gz"
Щоб указати алгоритм стиснення оперативного диска, скористайтеся наведеною нижче опцією. Стандартно використовується gzip. У більшості випадків корисно для пристроїв GKI (зі стандартним ядром).
deviceinfo_ramdisk_compression="lz4"
Використовуйте це для уточнення версії Halium. Наразі підтримується до Halium 13.
deviceinfo_halium_version="11"
Ця опція визначає версію заголовка завантажувального образу. Це важливо вказати правильно, інакше пристрій може не завантажитися. Для пристроїв з версією Android до 8 (Oreo) вказуйте 0, для 9 (Pie) — версія 1, для Android 10 — версія 2, а для пристроїв GKI — версія 3/4 (залежно від версії Android, наприклад, Android 12 з GKI використовує версію 4).
deviceinfo_bootimg_header_version="2"
Ця опція потрібна для визначення попередньо скомпільованого dtb, отриманого з джерел. Шлях відносний до Вашого каталогу з файлом deviceinfo. Виправте назву dtb відповідно до того, що вже маєте. Якщо версія заголовка дорівнює 3 або більша (пристрій GKI), це включатиме dtb у vendor_boot.
deviceinfo_bootimg_prebuilt_dtb="mt6765.dtb"
Ця опція використовує файли dtb, які створюються під час компіляції ядра, та які можна вказати як «mediatek/mt6765.dtb mediatek/angelica.dtb». Шлях, в якому скрипт шукає файли dtb з увімкненою опцією «KERNEL_OBJ/arch/<архітектура>/boot/dts», де <архітектура> це arm64 чи arm, залежно від того, що Ви встановили у deviceinfo_arch (aarch64 — це arm64 мовою ядра). Якщо версія Вашого заголовка 3 чи більше (пристрій GKI), це буде включати dtb у Вашому vendor_boot.
deviceinfo_dtb="mediatek/mt6765.dtb"
Цей вибір створить образ DT, який Ви обрали в завантажувальному образі. Шлях відносний до Вашого поточного каталогу, у якому Ви змінюєте deviceinfo. (Підказка: Це насправді потрібно лише для пристроїв Samsung/Exynos.)
deviceinfo_bootimg_prebuilt_dt="exynos8890-dt.img"
Користуйтеся цим для направлення скомпільованих наперед dtbo до Ваших OTA та для компіляції recovery (образу відновлення) з цим dtbo, якщо він ще не був скомпільований. Шлях знову відносний до каталогу компіляції. В разі потреби внесіть зміни.
deviceinfo_prebuilt_dtbo="angelica-dtbo.img"
В разі, якщо Ви не бажаєте спрямовувати образ DTBO до OTA, цей вибір лише вилучить dtbo з пакунка OTA, але образ для відновлення (recovery) буде зібраний з цим dtbo, якщо dtbo досі не скомпільовано.
deviceinfo_skip_dtbo_partition="true"
Якщо хочете скомпілювати свій DTBO з ядра, скористайтеся цією опцією для вибору скомпільованих у вихідному каталозі ядра файлів dtbo. Шлях, за яким цей параметр здійснюватиме пошук, це KERNEL_OBJ/arch/<архітектура>/boot/dts. Можна створити декілька dtbo, як у прикладі. Налаштуйте назви за власним бажанням. Якщо параметр skip_dtbo_partition не вибрано, отриманий образ dtbo буде надіслано до OTA, та у будь-якому випадку recovery також буде зібрано з цим dtbo. Цей параметр несумісний із попередньо зібраним параметром dtbo.
deviceinfo_dtbo="mediatek/galahad.dtbo mediatek/lancelot.dtbo"
Використання цього параметру визначає назву плати у Вашому завантажувальному (boot) образі, яка необхідна деяким завантажувачам (bootloaders) для вдалого завантаження образу. Користуйтеся цією опцією лише якщо Ваш рідний завантажувальний образ має цей флаг та має це значення заголовка. Внесіть необхідні зміни, якщо це потрібно.
deviceinfo_bootimg_board="EXYNOS4412"
Через цю опцію можна встановити розмір boot-образу. Також це стане необхідним, коли забажаєте додати до свого образу образ vbmeta чи хеш-футер. Припасуйте цей розмір до стокового розміру boot-образу. (Підказка: Розмір у байтах).
deviceinfo_bootimg_partition_size="67713847"
Досить зрозуміло. Встановіть значення true, якщо для Вашого пристрою потрібно додати образ vbmeta (це не стосується більшості пристроїв з окремим розділом vbmeta).
deviceinfo_bootimg_append_vbmeta="true"
Користуйтеся цією опцією, якщо хочете створити recovery.img для завантаження відновлення UBports (Насправді це буває потрібно лише на етапі завершення створення порту). У більшості випадків, мабуть, Ви захочете на ранніх етапах цього уникнути та додати лише при спробі його отримати в інсталяторі. Значення true створить образ відновлення, а значення false або пропуск запису скаже, що його збирати взагалі не потрібно.
deviceinfo_has_recovery_partition="true"
Використовуйте цей пункт для припасування розміру образу відновлення. Також необхідно, якщо бажаєте додати хеш-футер до образу. Поставте розмір зі свого заводського образу відновлення. (Працює лише з компіляцією recovery!)
deviceinfo_recovery_partition_size="67713847"
Це потрібно насправді лише для деяких старих/нових Samsung, де через футер «SEAndroid» у цих завантажувальних образах виконується перевірка чи образ офіційний. Якщо bootloader його не знайде у зверху екрана з’явиться потворна червона смужка. Додавши цей пункт до свого deviceinfo, він буде також доданий до образу boot. (Обережно! Використання цієї опції на інших пристроях може зламати образ!)
deviceinfo_bootimg_tailtype="SEAndroid"
Це налаштування визначає які модулі повинні (чи ні) бути скомпільованими та встановлені до кореневого каталогу rootfs. Пропуск цього пункту визначить стандартну поведінку, тобто модулі скомпілюються та будуть встановлені до rootfs. Додавання цієї опції до Вашого deviceinfo зі значенням true (як у зразку) вимкне компіляцію модулів. Насправді це потрібно лише якщо Ви робите щось дійсно серйозне.
deviceinfo_kernel_disable_modules="true"
Ця опція встановлює усі оверлейні файли (у каталозі overlay/) до /system/opt/halium-overlay, таким чином перекриваючи файли у rootfs цими файлами, замість того, щоб повністю їх замінювати. Це необхідно починаючи з версії 20.04 та не підходить для 16.04.
deviceinfo_use_overlaystore="true"
Ця опція найчастіше використовується у деяких пристроях Qualcomm. Додавання її до Вашого deviceinfo пов’яже усі Ваші файли dtbo з Вашими dtbs. Використовуйте це лише якщо Ви впевненні, що Вам це потрібно.
deviceinfo_kernel_apply_overlay="true"
Додайте це налаштування до свого deviceinfo для визначення фіксованого розміру rootfs, який потрібно прошити до системного образу. Типово, якщо опцію не встановлено, це 3000M. Користуйтеся цим лише за потреби.
deviceinfo_system_partition_size="4000M"
Це налаштування релевантне лише для нових пристроїв з флешсховищами UFS
deviceinfo_rootfs_image_sector_size="4096"
Далі йдуть адреси для прошивки. Якщо Ви робите тільки boot.img для пристроїв GKI, це можна пропустити, але для складання vendor_boot.img це необхідні дані. Якщо версія Вашого заголовка більша чи дорівнює 3, ці адреси застосовуються для vendor_boot автоматично. Отримати ці значення можна за наведеними нижче настановами.
Отримання значень з заводських образів boot.img/vendor_boot.img¶
Для завантаження будь-якого порту деякі значення повинні бути отримані з рідного boot.img. Перше та найважливіше, спробуйте отримати свою заводську прошивку. Деякі виробники, такі як Samsung, люблять шифрувати свої прошивки, але все ж існують деякі інструменти, які можуть допомогти з цим. Інші, наприклад, Xiaomi надають прошивки, але потрібен Google, щоб їх знайти. І так, цей спритний хлопець Google може допомогти отримати повні прошивки. Одним словом, Вам потрібно принаймні знайти свою заводську прошивку, і отримати з неї boot.img. Коли у Вас буде boot.img, виконайте наступні кроки:
Створіть каталог, де Ви будете зберігати усі свої розпаковані дані. Це може бути будь-де, та можете називати цей каталог на власний розсуд. А поки ми назвемо його temp.
Для створення каталогу виконайте «mkdir ~/temp» та «cd ~/temp», щоб туди перейти.
Для розпакування образу boot є декілька утиліт. Одна з них — це скрипт на python від Android. Скористаємося зараз ним. Для завантаження його до свого поточного каталогу виконайте «wget https://raw.githubusercontent.com/LineageOS/android_system_tools_mkbootimg/lineage-19.1/unpack_bootimg.py». Так Ви отримаєте скрипт unpack_bootimg.py, який Ви тепер використаєте для отримання адреси ядра та інших подібних значень
Скопіюйте свій boot.img до каталогу temp.
Тепер виконайте скрипт. Звичайний синтаксис: «python3 unpack_bootimg.py –boot_img <boot.img or vendor_boot.img> –out out». Ця команда розпакує образ boot, збереже файли з результатом до вихідного каталогу та виведе на екран адреси/зміщення для прошивки.
Приклад результату обробки boot.img виглядає приблизно так:
boot magic: ANDROID!
kernel_size: 11399060
kernel load address: 0x40080000
ramdisk size: 6576255
ramdisk load address: 0x51b00000
second bootloader size: 0
second bootloader load address: 0xc0ff0000
kernel tags load address: 0x47880000
page size: 2048
os version: 10.0.0
os patch level: None
boot image header version: 2
product name:
command line args: bootopt=64S3,32N2,64N2 buildvariant=user systempart=/dev/mapper/system:ro
additional command line args:
recovery dtbo size: 0
recovery dtbo offset: 0x0000000000000000
boot header size: 1660
dtb size: 216417
dtb address: 0x0000000047880000
тоді як для vendor_boot.img це виглядатиме так:
boot magic: VNDRBOOT
vendor boot image header version: 4
page size: 0x00001000
kernel load address: 0x10008000
ramdisk load address: 0x10000000
vendor ramdisk total size: 13685168
vendor command line args: bootconfig loop.max_part=7
kernel tags load address: 0x10000000
product name: SRPUK23A007
vendor boot image header size: 2128
dtb size: 231604
dtb address: 0x0000000011f00000
vendor ramdisk table size: 216
vendor bootconfig size: 28
Тепер починається найцікавіше.
«kernel load address» — це зміщення ядра. Вам потрібне значення після двокрапки, наприклад, 0x40080000. У Вашому випадку може бути щось інше.
«ramdisk load address» — буде зміщенням Вашого ramdisk. Візміть значення з цього рядка. Наприклад, 0x51b00000.
«second bootloader load address» у більшості непотрібне за теперішніми стандартами. Але якщо Ваш образ boot має це значення, візьміть його. Наприклад, 0xc0ff0000.
«kernel tags load address» — це особливе й використовується для kernel tags та dtb, але у деяких випадках ці значення різні. Також візьміть це. Наприклад, 0x47880000.
Адреса «dtb address» іноді така сама, як і «kernel tags load address», але якщо вони різні, для dtb та tags for tags краще взяти цю.
«page size» потрібно для ramdisk для розуміння які розміри сторінок використовує ваш чіп. Вам потрібно значення після двокрапки. Наприклад, 2048.
«os version» — це значення, де визначена версія Android, яку використовує boot.img. Деякі завантажувачі (bootloader) це використовують. Наприклад, 10.0.
«os patch level» має схожу історію. Вам буде потрібно також взяти це значення, наприклад, 2021-11.
Аргументи «command line args» йдуть прямо до deviceinfo_kernel_cmdline. Переконайтеся, що там є «console=tty0». Тут без прикладів :(
Якщо Ви створюєте vendor_boot, ця команда збереже файл
bootconfigдо Вашого вихідного каталогу. Перенесіть його до кореневого каталогу свого джерельного дерева.Окрім цих згаданих значень, Ви захочете мабуть все інше пропустити.
Тепер, відповідно до згаданих настанов, заповніть свої адреси (offsets):
Додайте до цих налаштувань значення «page size».
deviceinfo_flash_pagesize="2048"
Базовий зсув завжди буде 0x00000000.
deviceinfo_flash_offset_base="0x00000000"
Візьміть це з рядка «kernel load address».
deviceinfo_flash_offset_kernel="0x40080000"
Це бере своє значення з «ramdisk load address».
deviceinfo_flash_offset_ramdisk="0x51b00000"
Хоча це не критично, але якщо у Вас є це значення, додайте його з «second bootloader load address».
deviceinfo_flash_offset_second="0xc0ff0000"
Теги потрібно взяти з «kernel tags load address».
deviceinfo_flash_offset_tags="0x47880000"
Адреса DTB береться з «dtb load address».
deviceinfo_flash_offset_dtb="0x47880000"
Це — з «os version». Не обов’язково потрібно, але деякі виробники це використовують.
deviceinfo_bootimg_os_version="10.0"
Тут скоріше за все Ви захочете додати значення os patch level».
deviceinfo_bootimg_os_patch_level="2021-11"
Якщо Ви створюєте vendor_boot та перенесли файл
bootconfigдо кореня свого дерева, додайте наступне:
deviceinfo_vendor_bootconfig_path="bootconfig"
Й як тільки Ви правильно заповните deviceinfo, можна продовжити портування!
Створення, встановлення та запуск¶
Коли закінчите зі своїм deviceinfo та заповните усе потрібне, час перейти до головної частини — збирання. Для цього виконайте: ./build.sh -b workdir
Після цього на ПК завантажаться усі необхідні інструменти, ядро, й почнеться магія. Процес компіляції ядра може тривати від 5 до 50 хвилин.
Після завершення компіляції ядра можна перейти до наступного кроку — встановлення та завантаження.