Differences

This shows you the differences between two versions of the page.

Link to this comparison view

si:laboratoare:08 [2024/10/27 09:23]
florin.stancu removed
si:laboratoare:08 [2024/11/24 22:15] (current)
andreea.miu [Text & exercitii]
Line 1: Line 1:
-====== Laboratorul 08. RootFS Bootstrapping ​======+====== Laboratorul 08. Kernel Build System ​======
  
-===== Crearea unei distribuții Linux =====+Kernel-ul reprezintă o parte a sistemului de operare responsabilă cu accesul la hardware și managementul dispozitivelor dintr-un sistem de calcul (ex: procesorul, memoria, dispozitivele de I/O). De asemenea, el are rolul de a simplifica accesul la diferitele dispozitive hardware, oferind o interfață generică pentru aplicații prin intermediul system-call-urilor. În spatele interfeței generice se află porțiuni din kernel, numite drivere, care implementeză comunicația cu dispozitivele hardware. Un alt rol al kernel-ului este de a izola aplicațiile între ele, atât pentru stabilitatea sistemului, cât și din considerente de securitate.
  
-Până acum am folosit Root Filesystem ​de-a gata pre-instalat.+| {{ :​si:​lab:​2015:​kernel:​architecture.png?​300 |Architectura unui sistem ​de operare [By Bobbo (Own work) [CC-BY-SA-3.0 (http://​creativecommons.org/​licenses/​by-sa/​3.0) or GFDL (http://​www.gnu.org/​copyleft/​fdl.html)],​ via Wikimedia Commons]}} | 
 +^ Architectura unui sistem de operare ^
  
-La acest laboratordorim să învățăm procesul ​de generare a unui sistem de bază și modalitățile de personalizare a acestuiaproces numit **rootfs bootstrapping**.+Pentru a îndeplini toate aceste sarcini, codul kernel-ului rulează într-un mod special de lucru al procesoruluifapt care îi permite ​să execute o serie de instrucțiuni privilegiate. Acest mod privilegiat ​de lucru nu este accesibil aplicațiilor obișnuite. Spunem că aplicațiile rulează în //​user-space//​ (modul neprivilegiat)iar kernel-ul rulează în //​kernel-space//​ (modul privilegiat).
  
-Avem 2 variante: +===== Linux =====
-  * plecarea de la o distribuție existentă și alegerea pachetelor pe care să le includem + configurații specifice;​ +
-  * compilarea (manuală sau automată) a tuturor componentelor unui astfel de sistem;+
  
-Prima soluție, ​deși mult mai facilă (atât rapidă, cât și ușor de înțeles)nu ne permite o optimizare ​spațiului utilizat (sisteme bazate pe Debian ocupă de ordinul ''​~1GB''​) și nici fine-tuningul ulterior ​pentru ​îmbunătățirea performanțelor ​în cazul rulării pe anumite ​dispozitive ​(e.g., ARMv8 cu extensii NEON pentru ​SIMD).+Linux este numele unui kernel creat de către Linus Torvaldscare stă la baza tuturor distribuțiilor GNU/Linux. Inițialel fost scris pentru ​procesorul Intel 80386 însă, datorită licenței permisibile,​ a cunoscut o dezvoltare extraordinară, ​în ziua de astăzi el rulând ​pe o gamă largă de dispozitive, de la ceasuri de mână până la super-calculatoareAceastă versatilitatecât și numărul mare de arhitecturi și de periferice suportate, îl face ideal ca bază pentru ​un sistem embedded.
  
-Pe de altă parte, dacă am dori să facem asta de la zero, ar trebui să plecăm de la un toolchain (pe care, de cele mai multe ori, trebuie să-l compilăm tot noi), pe care îl vom folosi să compilăm din cod sursă toate componentele necesare într-un sistem ​Linux: biblioteci standard (LibC), sistem de init (SystemV / SystemD / OpenRC etc.), suita de programe de bază Unix (e.g., ​''​mount''​, ''​cat'',​ ''​ls'',​ ''​cp'',​ ''​sh'',​ ''​awk''​ și multe altele!), device manager (''​udev''​) precum și multe alte servicii (e.g., de networking) și aplicații necesare scopului nostru final (e.g., Python, X11 + QT Toolkit pentru interfețe grafice etc.).+<​note>​ 
 +Arhitecturile suportate ​de kernel-ul Linux se pot afla listând conținutul directorului ​''​arch'' ​din cadrul surselor. 
 +</​note>​
  
-Din fericireexistă suite software ​([[https://​www.yoctoproject.org/|Yocto Linux]][[https://buildroot.org/|Buildroot]]care pot automatiza repetabil acest proces. Însă ​un dezavantaj tot rămâne: timpul de compilare este de ordinul orelor, iar spațiul pe disk necesar între ''​20GB ​-- 50GB''​.+Linux este un kernel cu o arhitectură monoliticăacest lucru însemnând că toate serviciile oferite de kernel rulează în același spațiu de adresă și cu aceleași privilegii. Linux permite însă și încărcarea dinamică de cod (în timpul execuției) în kernel prin intermediul modulelorAstfel, putem avea disponibile o mulțime de drivere, însă cele care nu sunt folosite des nu vor fi încărcate și nu vor rulaSpre deosebire de aplicații însăcare rulează în modul neprivilegiat (//user-space//) și nu pot afecta funcționarea kernel-ului, ​un modul are acces la toată memoria kernel-ului și se execută în //kernel-space// (poate executa orice instrucțiune privilegiată). Un bug într-un modul sau un modul malițios poate compromite întregul sistem.
  
 +Dezvoltarea kernel-ului Linux se face în mod distribuit, folosind sistemul de versionare Git. Versiunea oficială a kernel-ului,​ denumită //​mainline//​ sau //vanilla// este disponibilă în repository-ul lui Linus Torvalds, la adresa [[https://​git.kernel.org/​pub/​scm/​linux/​kernel/​git/​torvalds/​linux.git]].
  
-===== Exerciții =====+Versiunea oficială este însă rar folosită într-un sistem embedded nemodificată. Este foarte comun ca fiecare sistem să folosească o versiune proprie a kernelului (numită un //tree//) bazată mai mult sau mai puțin pe versiunea oficială. Datorită licenței GPLv2 a kernelului, însă, orice producător care folosește o versiune modificată a kernelului este obligat să pună la dispoziție modificările aduse.
  
-Pentru acest laborator, vom încerca ambele abordări!+Aceste modificări sunt puse la dispoziție sub formă de //​patch//​-uri care trebuie aplicate unei anumite versiuni de kernel. O altă modalitate, care este folosită și de către fundația RaspberryPi,​ este de a publica un repository de Git cu versiunea modificată (un //tree// alternativ). Datorită modelului distribuit de dezvoltare suportat de Git, această a doua metodă are avantajul că permite dezvoltarea ușoară în paralel a celor două versiuni. Modificările făcute într-una pot fi portate și în cealaltă, iar Git va ține minte ce diferențe există în fiecare versiune. Cele două versiuni sunt de fapt două //​branch//​-uri de dezvoltare, care se întâmplă să fie găzduite pe servere diferite.
  
-==== 1. Crearea de distribuții bazate ​pe Debian (debootstrap) ====+<​note>​ 
 +Kernel-ul folosit ​pe RaspberryPi,​ care include suportul pentru SoC-ul Broadcom BCM2835 folosit de acesta, se găsește la adresa [[https://​github.com/​raspberrypi/​linux.git]]. 
 +</​note>​
  
-Pentru a genera distribuții personalizate bazate pe Debian (și derivate, e.g., Ubuntu), se poate folosi utilitarul ''​debootstrap''​.+===== Linux kernel build system =====
  
-Acesta descarcă automat din repository-uri pachetele ''​.dpkg''​pe care le instalează într-un prefix (director) precizat de utilizatore.g.: +Pentru compilare și generarea tuturor componentelor kernel-ului (ex: imaginea principală - //vmlinux//module, firmware) Linux folosește un sistem de build dezvoltat o dată cu kernel-ulbazat pe utilitarul //make//Acest sistem de build însă nu seamănă cu clasicul ​//config/make/make install//, deși ambele sunt bazate pe utilitarul ​//make//.
-<code shell> +
-# Sfat: încă nu rulați (veți aștepta mult și vă va da o eroare la final). Vedeți mai jos cauza + soluția! +
-$ sudo debootstrap --verbose --arch="​arm64"​ --include="​netbase,​vim,​bash,​curl"​ \ +
-        --variant=minbase "​bookworm"​ "/root/mydebian/" "http://ftp.de.debian.org/debian"​ +
-</code>+
  
-Puteți alege [[https://www.debian.org/​mirror/​list|alt mirror din lista oficială de aici]] (**recomandat!**). Alegeți la întâmplare o țară din Europa (să nu fiți toți pe același server că s-ar putea să facă throttling!).+Toți pașii de compilare sunt implementați ca target-uri pentru //make//. De exemplu, pentru configurare se poate folosi target-ul ''​config''​Acestă metodă de configurare însă nu este recomandată ​deoarece oferă o interfață foarte greoaie de configurare a kernel-ului.
  
 <note tip> <note tip>
-Aproape ​toate distribuțiile de Linux au câte un utilitar (de multe ori, chiar package managerul distribuției) care permite bootstrappingul RootFS-urilor din pachete (tot așa sunt generate și imaginile ISO live!)+Target-ul ''​help''​ oferă informații despre aproape ​toate operațiile ​suportate ​de către sistemul ​de build
-Spre exemplu, Arch Linux are ''​pacstrap'',​ Alpine Linux are ''​apk.static''​ and so on...+ 
 +<code shell> 
 +$ make help 
 +</​code>​
 </​note>​ </​note>​
  
-De menționat ar fi că instalarea unui pachet are loc în 2 etape+Operațiile oferite sunt grupate ​în diferite categorii
-  * decompresia arhivei (extragerea ​fișierelor ​din pachet ​în directorul rădăcină destinație)+  * //​cleaning//​ - conține target-uri pentru ștergerea ​fișierelor ​generate la compilare 
-  * rularea unor scripturi post-install pentru crearea configurațiilor implicite / upgrade fișiere / integrarea cu alte aplicații / instalarea serviciilor etc.;+    * spre deosebire de ''​clean'',​ ''​mrproper''​ șterge ​în plus toate fișierele generate, plus configurarea și diferite fișiere de backup 
 +  * //​configuration//​ - conține diferite target-uri pentru generarea unei configurări a kernelului; există target-uri care permit: 
 +    * generarea unui fișier de configurare nouex: ''​defconfig'',​ ''​allmodconfig'',​ ... 
 +    * actualizarea unui fișier de configurare existent; ex: ''​olddefconfig'',​ ''​localyesconfig'',​ ... 
 +    * editarea unui fișier de configurare existent; ex: ''​menuconfig'',​ ''​nconfig'',​ ... 
 +  * //​generic// ​conține target-uri generice; există target-uri pentru: 
 +    * compilare; ex: ''​all''​ - target-ul implicit care este executat la o invocare simplă a lui ''​make'',​ iar ''​vmlinux'' ​și ''​modules''​ compilează imaginea kernel-ului și, respectiv, modulele selectate 
 +    * instalare; ex: ''​headers_install'',​ ''​module_install'',​ ... 
 +    * informații; ex: ''​kernelrelease'',​ ''​image_name'',​ ... 
 +  * //​architecture dependent// - conține target-uri dependente de architectură,​ care diferă în funcție de arhitectura selectată; există target-uri pentru; 
 +    * generarea de imagini în diferite formate: compresate (''​zImage''​ și ''​bzImage''​),​ pentru U-Boot (''​uImage''​), ​... 
 +    * generarea de configurări implicite pentru sisteme bazate pe arhitectura selectatăex: ''​*_defconfig''​
  
-Acest aspect devine important când încercăm să generăm un rootfs pentru o arhitectură străină celei gazdă (cross-bootstrapping)! +<​note>​ 
-Pentru a realiza acest lucru, ​va trebui să distingem cele două etape: decompresia va putea avea loc direct pe host (avem utilitarele necesare instalate cu scriptul ​de bootstrapping),​ pe când etapa de execuție a programelor va trebui să fie virtualizată cumva (chroot + ''​qemu-user-static'' ​FTW).+Arhitectura care va fi compilată este selectată de variabila ​de mediu ''​ARCH''​.
  
-Astfel, pentru a realiza ''​debootstrap''​ de pe o arhitectură Intel/AMD ''​x86_64''​ pentru o țintă AArch64 (ARM 64-bit): 
 <code shell> <code shell>
-# a fost adăugat flag-ul `--foreign` în plus la comanda de debootstrap normală: +ARCH=x86 make [<​targets>​] 
-sudo debootstrap --foreign --verbose --arch="​arm64"​ ... /​root/​mydebian ... # restul de argumente normale +sau 
-# apoi copiem emulatorul în noua rădăcină (va fi rulat de binfmt_misc ca în Lab 04) +make ARCH=x86 [<​targets>​]
-sudo cp -af "​$(which qemu-aarch64-static)"​ /​root/​mydebian/​usr/​bin/​ +
-# Acum va trebui să rulăm stagiul 2 al debootstrap,​ însă într-un container / chroot! +
-# Folosim systemd-nspawn pentru a rula binarul de second-stage instalat pe rootfs de la primul: +
-$ sudo systemd-nspawn --as-pid2 --resolv-conf=copy-host -D /​root/​mydebian \ +
-    /​debootstrap/​debootstrap --second-stage --verbose+
 </​code>​ </​code>​
 +</​note>​
  
-<​note>​Este posibil ca descărcarea să dureze cevaîn funcție de viteza de conectare la Internet + mirror-ul ales.</​note>​+<​note ​important> 
 +Dacă arhitectura nu este setată explicitse folosește implicit arhitectura sistemului pe care se face compilarea. 
 +</​note>​
  
-Tehnica cu systemd-nspawn + qemu-user-static (și binfmt_misc) este utilă ​pentru ​a intra într-un chroot pe rootfs-ul nostru ​pentru a-l personaliza (putem chiar și instala programe noi sau configura servicii etc.). Însă va trebui configurat programul de gestionat de pachetele, ''​apt'': ​de adăugat mirror-uri la repo-urile ​de bază (și cele extinse, de preferat) în ''/​etc/​apt/​sources.list'' ​-- [[https://​wiki.debian.org/​SourcesList#​Example_sources.list|găsiți exemplu aici]].+În cele mai multe situații se dorește compilarea unui kernel ​pentru un sistem deja existent, fie pentru a adăuga ​sau elimina funcționalități sau pentru a actualiza versiunea ​de kernel folosită. În aceste cazuri folosirea target-urilor ​de generare a unei configurații noi, chiar și a celor care generează o configurație implicită pentru arhitectura noastră nu sunt neapărat utileEste posibil ca kernel-ul existent să aibă deja o configurație personalizată care se dorește doar a fi actualizată/​modificată folosind target-urile de editare
  
-**Atenție:** momentan, rootfs-ul NU ARE parolă la contul ''​root'' ​(și nu are nici un alt cont) și nu vă veți putea autentifica din niciun ​//tty//+Un kernel care rulează poate conține fișierul de configurare ​(de obicei în format comprimat ​//gzip//) din care a fost compilat, dacă această funcționalitate a fost selectată la build. Acest fișier se regăsește în ''/​proc/config.gz''​. Tot ce rămâne este să extragem acest fișier ​și -l modificăm conform dorințelor.
-Se recomandă accesarea unui chroot (rulaț''/​usr/bin/bash'' ​ca ultim argument al lui ''​systemd-nspawn''​) ​și setarea uneia prin ''​passwd'':​ +
-<code shell> +
-host$ sudo systemd-nspawn --as-pid2 --resolv-conf=copy-host -D /​root/​mydebian bash +
-root@debian$ passwd root +
-root@debian$ apt update && apt install -y wget curl # nu le vom folosi, dar exemplu :P +
-</​code>​+
  
-O dată generat rootfs-ul, acesta trebuie copiat (atenție să nu se piardă permisiunile și atributele unor fișiere speciale -- mai ales symlink-urile) pe o partiție și bootat! Se recomandă arhivarea acestuia folosind utilitarul ''​tar''​ (acesta salvând automat metadatele necesare în arhivă):<​code shell> +===== Device Tree Structure =====
-$ tar czf mydebian.tar.gz -C /​root/​mydebian . +
-</​code>​+
  
-În final, dorim să vedem cât ocupă rootfs-ul nostru: +Device Tree-ul este o structură de date, la nivelul kernel-ului, care descrie componentele hardware prezente pe sistem, care nu pot fi descoperite automat de kernel. El este prezent pe sistemele cu arhitecturi ARM, dar și pe alte sisteme (nu pe cele care se bazează pe arhitectura x86). Fiecare intrare a device tree-ului descrie o componentă individuală.
-<code shell> +
-$ du -hs /​root/​mydebian +
-</​code>​+
  
-<note tip> +Device Tree-ul este stocat în 2 fișiere: ''​.dtb''​ (device tree blob), în format binar, și ''​.dts''​ (device tree source), în format text. Ambele tipuri de fișiere se găsesc în ''​arch/<​arhitectură>/​boot/​dts'',​ fiind generate de target-ul ''​dtbs''​ al comenzii ''​make''​.
-Vom trece să instalăm + rulăm sistemul pe un Raspberry PI 4 fizic imediat ce pornim compilarea unui sistem Buildroot ;) +
-</note>+
  
-==== 2. Compilarea programelor de bază (buildroot) ​====+===== Testare =====
  
-Mai departedescriem procesul ​de utilizare al unui utilitar destul ​de popular (cel mai important fiind ușurința de învățare față de Yocto Linux).+Pentru a testa un nou kernel acesta trebuie instalat pe //target//. Această procedură diferă de la sistem la sistemiar pe RaspberryPi constă în copierea acestuia pe card-ul SD în partiția ​de //boot// sub numele ​de ''​kernel8.img''​. În momentul dezvoltării ​și testării unui nou kernel, instalarea fiecărei versiuni a acestuia pe //target// reprezintă un bottleneck major.
  
-<note warning>​ +O alternativă la instalarea kernel-ului pe //target// o reprezintă încărcarea acestuia prin rețea direct pe de //host//-ul folosit la dezvoltare, dacă există suport din partea bootloader-ului. ​Din păcate, ​bootloader-ul implicit ​de pe RaspberryPi nu are suport pentru a încărca o imagine de kernel de pe rețea. Un bootloader care oferă însă acestă facilitate este //U-Boot// [[#​referinte| [2]]], el folosind protocolul TFTP pentru a boota o imagine de kernel prin rețea.
-Din păcate, ​vom avea nevoie de aproximativ ''​~20-30GB'' ​de spațiu disponibil (în mașina virtuală).+
  
-Cel mai simplu este să creați un Virtual HDD nou de ''​30GB''​ (**nu îi pre-alocați** spațiul, deoarece nu va ajunge să ocupe atât azi -- poate la temă :P ) și atașați-l proiectului VirtualBox ​VMWare ca dispozitiv de stocare suplimentar (din setări / storage, add [hard] disk pe ambele hipervizoare). +===== Instalare pachete/programe ​din surse =====
-Apoi va trebui formatat + montat din VM: ''​mkdir /media/big && mkfs.ext4 /​dev/​sd<​X>​ && mount /​dev/​sd<​X>​ /​media/​big''​. +
-O idee bună ar mai fă să creați director de lucru pentru ''​student'':​ ''​mkdir /​media/​big/​work && chown student:​student /​media/​big/​work -R''​.+
  
-De asemenea, tot acum ar fi momentul să alocați memorie RAM mai multă (3-6GBdacă aveți ​de unde) aproape câte nuclee aveți procesorului virtualizat (să se paralelizeze procesul). +De multe ori ne lovim de problema instalării unui pachet sau a unui program pe care îl găsim doar pe un repository public, de cele mai multe ori bazat pe GitAstfel, pentru a ne putea folosi de acel pachet/​program,​ trebuie ​să cunoaștem următoarele utilitare:
-Și să conectați laptop-ul la 230V ;) +
-</​note>​+
  
-Spre deosebire de ''​debootstrap'',​ care avea nevoie de drepturi de ''​root'',​ aceste utilitare folosesc principiul de ''​fake root''​ (metadatele sistemului de fișiere sunt virtualizate într-o bază de date externă kernelului),​ fiind utilizabile (uneori obligatoriu) și de către conturi non-superuser. Aproape toți pașii va trebui să-i urmați autentificați ca ''​student''​!+==== Git ====
  
-Primul pas, ar fi, desigur descărcarea lui ''​buildroot''​. ​Alegeți o versiune de la [[https://buildroot.org/downloads/]] și descărcați-o + dezarhivați-(sub contul student șpe HDD-ul mare!)<code shell+Opțiuni și comenzi git: 
-$ wget https://buildroot.org/downloads/buildroot-2023.08.tar.xz + 
-$ tar xf ... +   - ''​git clone //<​repo>//''​ - va aduce toate fișierele conținute de repository-ul //repo// pe mașina locală. 
-cd buildroot-*+   - ''​git pull''​ - actualizează un repository deja clonat local la ultima versiune remote. 
 +   - ''​git checkout //<​branch>//''​ sau ''​git checkout //<​tag>//''​ - actualizează fișierele locale la versiunea indicată de //branch// sau de //tag//. Un repository poate avea mai multe branch-uricare pot fi văzute ca niște versiuni diferite ale repository-ului. Un exemplu uzual de folosire a branch-urilor este pentru organizarea diferitelor versiuni ale aceluiași program. 
 +   ​- ​''​git apply //<patch file>//'' ​- aplică pe fișierele locale modificările conținute de fișierul //patch//. 
 + 
 + 
 + 
 +====== Exerciții ====== 
 + 
 +**0.** Pregăriri 
 + 
 +<​hidden>​ 
 +  * **Pentru asistenți:​** descărcați [[https://github.com/cs-pub-ro/SI-rpi-debian-scripts/​releases|de aici imaginea '​rpi-full.img'​ pentru Raspberry PI (v2)]] și scrieți-o pe Raspberry PI folosind un disk imager (ori cu un card reader, ori bootați un U-Boot, schimbați cardul SD, ''​mmc rescan'',​ apoi ''​ums mmc 0'' ​(găsițdisk-ul accesibil de pe calculatorul la care e conectat prin USB Type-C)
 +</hidden
 + 
 +  * Descarcati ultima varianta de kernel Linux pentru Raspberry Pi, de [[https://github.com/raspberrypi/linux.git|aici]]<​code>​ 
 +git clone https://​github.com/​raspberrypi/​linux.git --depth=1</​code>​ 
 + 
 +  * Instalati pachetele necesare: <​code>​ 
 +apt-get install -y bc bison flex libssl-dev libc6-dev libncurses5-dev crossbuild-essential-arm64 </​code>​ 
 + 
 +  * Generati configurarea implicita a kernel-ului (tip: defconfig)<​code>​ 
 +cd linux/ 
 +export KERNEL=kernel8 
 +make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
 </​code>​ </​code>​
  
-Utilitarul Buildroot folosește mecanismul Kconfig (la fel ca U-Boot și kernel-ul Linux), deci: ''​make menuconfig''​. +  * Modificati din ''​menuconfig'' ​numele imaginii de kernel.
-Navigați prin meniuri și schimbați următoarele opțiuni:+
  
-  * ''​Target Options''​ =''​Target Architecture''​ =''​AArch64 (little endian)'';​ +<note tip>Lansati meniul pentru arhitectura selectata anterior:<​code
-  * ''​Target Options'' ​=> ''​Target Architecture Variant'' ​=> ''​cortex-A53''​ (pentru compatibilitate sporită cu mai multe modele Raspberry PI + Qemu); +make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig 
-  * ''​Target Options''​ => ''​Floating point strategy''​ =''​VFPv4''​ (la fel, compatibilitate sporită); +</code
-  * ''​Toolchain''​ => ''​Enable compatibility shims ...'';​ +Optiunea se afla in General Setup -> Local Version</​note>
-  * ''​System Configuration''​ => ''​Root password''​ => ''​student'' ​-- pentru a ne putea autentifica în shell! +
-  * ''​Filesystem images''​ =''​Compression method''​ =''​gzip''​ -- opțional, imaginea ocupă extrem de puțin oricum.+
  
-Apoi rulați ''​make''​! Procesul poate dura între 10 minute și 1h, în funcție ​de numărul de nuclee, frecvența lor (ce poate fi scăzută dacă sunteți pe baterieși memoria RAM disponibilă.+  * Verificati daca driver-ul ​de mmc este activat ​(nu ca modul).
  
-<note tip> +<note tip>Trebuie sa vedeti ''​MMC ​[=y]'' ​</​note>​
-Distribuția de bază Buildroot include doar utilitarele ce vin cu [[https://​busybox.net/​|busybox]]. +
-Aveți, însă, o mulțime de pachete de aplicații pe care le puteți bifa la secțiunea ​''​Target packages''​!+
  
-Însă acest lucru va duce la o mărire drastică a timpului ​de compilare + consum de spațiu pe disk (în funcție de ce / câte pachete + câte dependințe au)+  * Compilati nucleul, device tree blob-urile si modulele ​de nucleu. <​code>​ 
-</note>+make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image Image.gz modules dtbs -j$(nproc)</code>
  
-**Nu așteptați! lăsați-l să ruleze ștreceți la task-ul următor ;)**+<note important>​Procesul de compilare va dura destul de mult. Daca folositi o masina virtuala, dati-i cat mai multe nuclee, pentru a reduce timpul</​note>​
  
-La finalsă inspectați sistemul de fișiere rezultat, îl găsiți la calea ''<​buildroot-dir>/output/images/''​Cât ocupă?+  * Cat se compileaza nucleulinspectati fisierul ​''​.dts''​ corespunzator placii RaspberryPI 4B. <code> 
 +arch/arm64/boot/dts/​broadcom/​bcm2711-rpi-4-b.dts</​code>​
  
-==== 3. Instalarea rootfs-ului în imaginea RPI 4 ====+  * Kernelul nostru experimental se instalează folosind următorii pași: <​code>​ 
 +# se presupune că aveți deja montate imaginea / cardul SD al RPi-ului (citiți mai jos!) 
 +sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_PATH=<​path_catre_partitia_de_boot>​ install 
 +sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=<​path_catre_partitia_de_rootfs>​ modules_install
  
-**0.** Descărcați [[https://github.com/cs-pub-ro/SI-rpi-debian-scripts/releases|de aici imaginea ​rpi-full.img.tar.xz]].+# Notă: nu suprascrieți device tree-ul deoarece o versiune greșită ar strica u-boot-ul :D 
 +# Dar așa s-ar copia: 
 +#sudo cp arch/arm64/boot/dts/​broadcom/bcm2711-rpi-4-b.dtb <​path_catre_partitia_de_boot>​/ 
 +#sudo cp arch/​arm64/​boot/​dts/​overlays/​bcm2711-rpi-4-b.dtb* <​path_catre_partitia_de_boot>/​overlays/​
  
-**1.** Trebuie să montăm ​imaginea ​și să copiem noul RootFs pe cea de a doua partiție ​(pe care o vom formata):+# Redenumim ​imaginea de kernel ​(e deja cea compresata) 
 +sudo mv <​path_catre_partitia_de_boot>/​vmlinuz-<​versiunea-noua>​ <​path_catre_partitia_de_boot>/​vmlinuz-student
  
-  * Dezarhivați fișierul imaginii ''​rpi-full.img'';​ ar trebui să obțineți imaginea de ''​2GB'';​ +# Demontam partitiile 
-  * Verificați că există ambele partiții: ''​parted rpi-full.img print'';​ +sudo umount ​<path_catre_partitia_de_boot
-  * Conectați imaginea la un dispozitiv de tip bloc folosind ''​losetup /dev/loop0 rpi-full.img''​ și ''​partprobe /​dev/​loop0''​ (verificați cu ''​losetup -L''​ ce aveți conectat dacă întâmpinați probleme);​ +sudo umount ​<path_catre_partitia_de_rootfs> 
-  * Formatați sistemul de fișiere a celei de-a doua partiții în ext4: ''​mkfs.ext4 -L RPI_ROOTFS /​dev/​loop0p2''​ (confirmați!);​ + 
-  * Montați noua partiție goală ''​ext4''​ (puteți folosi ''/​mnt''​ ca mountpoint) și copiați conținutul arhivei rootfs generate anterior (ori cea de Debian, ori cea obținută prin Buildroot): ​<code shell+Oprim ums
-tar xf <ARCHIVE_FILE>​ -C <​DEST_MOUNTPOINT+
-inspectați calea dezarhivată:​ +
-ls -l <​DEST_MOUNTPOINT>​+
 </​code>​ </​code>​
-  * Demontați partiția ext4 și deconectați dispozitivul ''​loop''​ folosite! 
  
-**2.** Porniți Raspberry PI-ul în u-boot, apoi intrați în modul ''​ums ​mmc X'' ​(vedeți [[:​si:​laboratoare/​05|laboratorul 5]]); folosiți ori ''​dd''​, ori un utilitar ​de Raw Disk Imager pentru Windows (recomandat:​ Raspberry PI Imager) ca la laboratoarele anterioare pentru a scrie noua imagine pe RPI.+  ​* **Notă**: dacă aveți probleme cu USB device passthrough-ul pe Raspberry PI, este suficient să copiem DOAR fișierul vmlinuz pe partiția de boot, cea FAT32. Pentru aceasta, bootați-l în modul ''​ums'' ​din U-Boot, conectat la USB Type-Cși copiați DOAR fișierul ​''​arch/​arm64/​boot/​Image.gz'' ​sub numele ​de ''​vmlinuz-student''​.
  
-<​note ​important+<​note ​tip>Pentru a porni ums, urmati urmatorii pasi: 
-  * **Atenție**:​ Va trebui, mai întâi, să aduceți imaginea pe Windows (folosiți ​''​scp''​ cu ''​username@<​ip_sursa>:​/cale/catre/​fisier.img''​ ca prim argument, iar, ca destinație,​ o cale de pe PC-ul fizic, e.g., ''​C:​\Users\..etc''​)! +  * conectati adaptorul de seriala la laptop 
-  * **Notă pentru VirtualBox**: va trebui să folosiți argumentul ''​-P 2023'' ​și ''​student@localhost:<​cale>''​ ca sursă. +  ​* ''​picocom ​/dev/ttyUSB0 ​-b 115200''​ 
-  * **Notă pentru cei cu gazda pe Linux**: dacă utilizați ''​dd''​va trebui să rulați comanda ''​sync''​ și să așteptați să se termine! Asta e important deoarece kernelul modern cache-uiește în memoria RAM și scrierea se termină, aproape instant (însă rămâne să se copieze pe SD în background, această operațiune fiind mult mai lentă).+  * conectati cablu de alimentare 
 +  ​la un moment dat va aparea ​**Hit any key to stop autoboot:**; apasati orice tasta 
 +  * daca nu ati intrat in meniul de U-Boot, apasati Ctrl-C 
 +  * din meniul de U-Boot, dati comanda ​''​ums mmc 0''​ 
 +  * partitiile ar trebui sa fie vizibile: ​**/dev/sda1**(root) si **/​dev/​sda2**(rootfs) 
 +  * daca nu vi le monteaza sistemul de operare automatmontati-le 
 </​note>​ </​note>​
  
-3. Reporniți Raspberry PI-ul. Lăsați-l ​să booteze ​normalar trebui să pornească kernel-ul implicit cu rootfs-ul vostru!+<note important>​ 
 +U-boot din imaginea nouă este configurat ​să booteze ​automat ''​vmlinuz-student''​dacă există!
  
-  * Inspectați-l! Cât ocupă pe disk (''​df''​)?​ +Acesta va aștepta 10 secundepermițând să întrerupeți procesul pentru ​putea re-accesa modul ''​ums'' ​pentru a rescrie imaginea pe viitor.
-  * Dacă vă printează mesajul cu ''​waiting for device /​dev/​mmcblk0p2'' ​și nu se termină procesulverificați dacă partiția doua există din u-boot (''​part list mmc 0''​).+
  
-==== 4. [BONUS] Rulați imaginea voastră în QEmu (system) ====+Puteți vedea [[https://​github.com/​cs-pub-ro/​SI-rpi-debian-scripts/​blob/​labsi/​configs/​labsi-rpi4/​files/​uboot-script.txt|codul sursă al scriptului de u-boot aici]].  
 +</​note>​
  
-Observăm că procesul de testare a unei imagini embedded consumă ceva timp (mai ales la scrierea pe cardul SD). +  * Porniti RaspberryPI-ul cu noua versiune, ca in [[https://​ocw.cs.pub.ro/​courses/​si/​laboratoare/​06#​exercitii|laboratorul 6]].
-Dorim să optimizăm!+
  
-Rulați imaginea obținută anterior (va trebui să exrageți kernel-ul din imagine!) prin ''​qemu-system-aarch64''​. +<note warning>​ 
-Re-vedeți instrucțiunile din [[:si:​laboratoare/04|laboratorul 4]].+Dacă nu ați copiat modulele externe pe rootfs-ul de pe Raspberry PI al noului kernel, Linux se va plânge când bootează că lipsesc o parte din modulele necesare de anumite dispozitive hardware / software non-esențiale (//ahemmulte sunt, defapt, necesare pentru a avea suport pentru rețelistică în Linux//), însă procesul de boot ar trebui să se finalizeze. 
 +</​note>​
  
-===== Resurse ​=====+====== Referințe ======
  
-  ​[[https://github.com/cs-pub-ro/SI-rpi-debian-scripts|Cod sursă scripturi ​compilare ​bootloader / kernel ​/ generare rootfs]] +  ​[[https://www.raspberrypi.com/documentation/computers/​linux_kernel.htmlGhid compilare kernel ​RaspberryPi]] 
-  ​[[https://buildroot.org/downloads/manual/manual.html#​_getting_started|Buildroot Manual ​Getting started]]+  ​[[https://www.thegoodpenguin.co.uk/blog/build-boot-linux-on-raspberry-pi-3-model-b/| Ghid compilare U-Boot pentru RaspberryPi]]
  
  
si/laboratoare/08.1730013785.txt.gz · Last modified: 2024/10/27 09:23 by florin.stancu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0