Differences

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

Link to this comparison view

si:laboratoare:06 [2022/11/13 23:06]
florin.stancu
si:laboratoare:06 [2023/11/15 12:03] (current)
florin.stancu fix losetup arg order
Line 1: Line 1:
-====== Laboratorul 06. Yocto ======+====== Laboratorul 06. Root filesystem și servicii de sistem ​======
  
-[[https://​www.yoctoproject.org/​|Yocto]] este o colecție de utilitare, metadate și șabloane ce permit construirea/​compilarea distribuțiilor de Linux pentru platforme embedded. Acest proiect este dezvoltat de Linux Foundation și condus de către Richard Purdie.+===== Root file system =====
  
-Proiectul Yocto se adresează atât utilizatorilor experimentați cât și utilizatorilor noi. Pentru utilizatorii experimentați, Yocto oferă posibilitatea de a crea distribuții personalizate pornind ​de la 0 sau de la imagini scheleticeUtilizatorii noi au la dispoziție o serie de exemple ​și un kernel ​ce poate fi folosit ca punct de pornire. De asemeneaaceste imagini de bază sunt disponibile pentru diferite platforme: ARMPPC, MIPS, x86 etc.+Pentru ca sistemul să fie inițializat corect după pornirea kernel-ului,​ este necesar ca toate script-urile ​și executabilele necesare pentru a porni daemon-ul de inițializare, //init//, șrestul proceselor //​user-space//​să existe în anumite locații în sistemul ​de fișiereAcest sistem minimal de fișiere necesar ​la inițializare poartă numele ​de **root file system** sau **rootfs**. În cazul sistemelor Unix, //​rootfs//​-ul are ca rădăcină directorul ''/'' ​și înglobează o serie de directoare ​ce contin restul ​de fișiere necesare. De obiceiîn directorul ''/''​ nu se află niciun fișierdoar subdirectoareAceste subdirectoare sunt organizate în funcție de fișierele pe care le conțin:
  
-Pentru a-și ajuta utilizatorii,​ Yocto vine cu o serie de aplicații: un sistem ​de build numit ''​Bitbake''​, o interfață grafică numită ''​Hob''​ (we don't do that here :Dcât și alte unelte ​de dezvoltare, ​și, cel mai important[[https://docs.yoctoproject.org/ref-manual/|o documentație stufoasă]].+  * ''/​bin'' ​conține programe ​și comenzi necesare la inițializare ce pot fi folosite apoi de către un utilizator neprivilegiat în timpul unei sesiuni 
 +  * ''​/sbin'' ​- conține programe asemănătoare cu cele din /bin ca utilitate, dar care pot fi utilizate în general doar de utilizatorul privilegiat //root// 
 +  * ''​/etc'' ​- conține fișierele de configurare specifice sistemului 
 +  * ''/​lib''​ - conține bibliotecile folosite de programele din //​rootfs// ​(cele din ''/​bin''​ și ''/​sbin'​') 
 +  * ''/​dev''​ - conține referințe la toate dispozitivele periferice; aceste referințe sunt în general fișiere speciale 
 +  * ''/​boot''​ - conține fișierele necesare bootării ​și imaginea kernel-ului;​ este posibil ca acestea să fie păstrate pe un sistem ​de fișiere separat de //​rootfs//​ 
 +  * ''/​tmp''​ - conține fișiere temporare ​și este de obicei curățat la repornirea sistemului 
 +  * ''/​opt''​ - conține în principal aplicațiile third-party 
 +  * ''/​proc''​''/​usr''​''​/mnt'',​ ''​/var'',​ ''​/home'' ​sunt directoare care, în general, reprezintă puncte în care se pot monta alte sisteme de fișiere pentru a stoca log-uri, biblioteci și alte aplicații și programe folosite de către utilizatori.
  
-Sursele Yocto pot fi găsite atât la adresa oficială **[[http://git.yoctoproject.org/cgit/cgit.cgi/poky]]**cât și [[https://​github.com/yoctoproject/​poky|la un mirror pe GitHub]] (pentru cine preferă).+<​note>​ 
 +Organizarea unui rootfs Linux în termeni de directoare este bine definită de standardul ierarhiei sistemului de fișiere: ​[[https://refspecs.linuxfoundation.org/fhs.shtml|Filesystem Hierarchy Standard]], ultimul standard FHS 3.0 fiind definit in 2015. 
 +</note>
  
-Acum noi, la toate laboratoarele de Yocto ce urmează (cât și la temă), vom folosi [[https://github.com/cs-pub-ro/SI-Lab-VM/​releases/​tag/​y2022-yocto|mașina virtuală de laborator]] cu toate utilitarele necesare instalateprecum ​și întreaga distribuție precompilată (de aici rezultă ​și dimensiunea marede ''​20GB''​, a disk-ului virtual).+Standardul Unix recomandă ca //rootfs//-ul să aibe dimensiuni relativ micideoarece orice problemă sau corupere a acestuia poate împiedica inițializarea corectă a sistemului. Dacă, totuși, rootfs-ul devine corupt, există modalități prin care poate fi remediat. O soluție des folosită este de a monta acest sistem de fișiere într-un alt sistemfuncționalpentru ​putea fi explorat și verificat.
  
-===== Descriere componente ​unelte Yocto =====+În cazul sistemelor embedded, de multe ori spațiul de stocare pe care îl avem la dispoziție este deja limitat: < 32MB. De cele mai multe ori, o bună parte din acest spațiu este ocupat de imaginea kernel-ului. De aceea, în majoritatea cazurilor, ​//​rootfs//​-ul pentru aceste sisteme este fie compus doar din minimul de programe necesar pentru funcționare,​ fie este stocat pe un server accesibil prin rețea și montat de către kernel la inițializare (e.g., folosind protocolul NFS).
  
-Pentru început, vom face o descriere componentelor și utilitarelor folosite în cadrul laboratoarelor de Yocto Linux: +===== Pseudo Filesystems =====
-Reveniți asupra acestora oricând aveți nelămuriri despre sintaxă / variabile pe parcursul exercițiilor.+
  
-==== Bitbake ====+Un kernel Linux expune mai multe pseudo-sisteme de fișiere, precum ''/​dev''​ (unde există noduri pentru toate dispozitivele detectate), ''/​proc''​ sau ''/​sys''​. Unele aplicații ce gestionează sistemul de operare au nevoie ca aceste mountpointuri să existe, ele fiind folosite pentru a interfața cu kernelul (mai ales în sisteme incorporate,​unde programele trebuie să comunice cu hardware-ul).
  
-[[http://​docs.openembedded.org/​bitbake/​html/​|Bitbake]] este sistemul de build folosit de Yocto. Acesta este asemănător sistemului folosit uzual pe distribuțiile Linux, ''​make''​. Ca și ''​make'',​ ''​bitbake''​ trebuie să determine ce acțiuni trebuie executate și apoi să le lanseze efectiv în execuție. Aceste acțiuni se determină în funcție de: comenzile date de către utilizator, datele proiectului și starea curentă a build-ului. Toate operațiile ce trebuie executate, dependențele dintre acestea, variabilele și instrucțiunile sunt ținute și citite din fișiere scrise în sintaxa specifică ''​bitbake'':​+==== Sistemul virtual proc ====
  
-<code make HelloWorld.bb> +Acest sistem de fișiere există de când există și Linux-ul și permite expunerea de statistici despre procesele rulate în sistem dar și ajustarea la runtime a diverșilor parametrii ce implică managementul proceselor, ale memoriei etc. Este utilizat de majoritatea aplicațiilor standard. Aplicații precum **ps** și **top** nu pot funcționa fără acest filesystem.
-DESCRIPTION = "Hello World"​ +
-LICENSE = "​CLOSED"​+
  
-PR = "​r0"​ +Pentru a monta **proc** se poate folosi comanda<​code>​ mount -t proc nodev /proc </code>
-SRC_URI = "file://myhelloworld.c \ +
-           ​file://​README.txt"​+
  
-TARGET_CC_ARCH += "​${LDFLAGS}" ​ +Printre conținutul aflat în **proc** putem găsi: 
-           ​ +  * ///​proc/​interrupts,​ /​proc/​iomem,​ /​proc/​cpuinfo//:​ ce conțin informații specifice de device 
-do_compile() { +  * ///​proc/<​pid>,​ /​proc/​3840/​cmdline//:​ conține detalii despre fișierele deschise de proces, utilizarea memoriei, procesorului etc. 
-        ${CC} ${CFLAGS} ${LDFLAGS} ${WORKDIR}/myhelloworld.-o ${WORKDIR}/myhelloworld +  ​* ​///​proc/​cmdline//:​ conține linia de comandă cu care a fost pornită imaginea kernel-ului 
-}+  * ///​proc/​sys//:​ conține ​ fișiere care pot fi scrise pentru a ajusta parametrii ai kernel-uluiPoartă numele de **sysctl**. Mai multe detalii despre asta aici: [[https://​www.kernel.org/​doc/​html/​latest/​admin-guide/sysctl/​|documentație sysctl]].
  
-do_install() { +==== Sistemul virtual sys ====
-        install -d ${D}${bindir}+
  
-        install ​-m 0755 -t ${D}${bindir} ${WORKDIR}/myhelloworld +Permite reprezentarea în userspace a viziunii pe care o are kernel-ul asupra magistralelor,​ dispozitivelor și driverelor din sistem. Este util pentru diverse aplicații din userspace care trebuie să enumere și să interogheze hardware-ul disponibil, de exemplu **udev** sau **mdev**: 
-}+ 
 +<​code>​ls /sys
 +block bus class dev devices firmware fs kernel module power
 </​code>​ </​code>​
  
-Asemănător cu un Makefile, putem folosi variabile de sistem ​pentru ​a specifica flag-uri, executabile,​ căi etc. Principala diferență constă în modul de organizare a fișierului. În aceste fișiere de configurare ne este permis să definim task-uri pentru fiecare etapă a procesului de build ce trebuie executată. Astfel, codul este mult mai bine organizat, mai ușor de urmărit și de depanat.+===== Utilitare folosite ​pentru ​crearea / inspecția unui RootFS =====
  
-Un alt avantaj al lui ''​bitbake''​ este organizarea sa ierarhică. Atunci când se pornește ​un build, ''​bitbake''​ are o viziune de ansamblu asupra distribuției. Se vor citi mai întâi toate fișierele ​de configurare (rețetele) ce au legătură cu acea distribuție și abia apoi se va decide ​care sunt task-urile ce trebuie executate și în ce ordine se vor executa.+Uneori vom fi în situația în care nu avem acces la un server ​și imaginea ​de care dispunem pentru sistemul nostru nu este satisfăcătoare. În aceste condiții va trebui să ne creăm propriul //rootfs// pe care să îl scriem ​în memoria sistemului embedded.
  
-A se observa că este posibilă definirea de funcții în alte limbaje integrate (SHell sau chiar Python) ce se vor executa într-un anumit pas al procesului de build (vedeți [[https://docs.yoctoproject.org/dev-manual/common-tasks.html#​overview|diagrama din documentația oficială]] pentru ​idee).+Imaginea recomandată pentru RaspberryPi,​ Raspbian, conține două partiții: o partiție ''​FAT''​ folosită pentru boot șo partiție ''​ext4''​ pentru ​//rootfs//. Fiecare dintre aceste partiții începe de la un anumit offset în cadrul imaginii. Atunci când dorim să creăm ​imagine nouă pentru RaspberryPi,​ trebuie să ne asigurăm că respectăm aceste partiții și formatele lorPașii pe care trebuie să îi urmăm sunt:
  
-==== Fișiere speciale ​și variabile ​de sistem ====+  * Stabilirea dimensiunii imaginii ​și inițializarea acesteia cu zero-uri 
 +  * Crearea tabelei de partiții ​și a celor două partiții necesare 
 +  * Formatarea partițiilor cu formatul corespunzător 
 +  * Pentru popularea rootfs-ului,​ putem fie să montam partiția și să copiem manual directoarele și fișierele, fie putem să copiem o partiție întreagă ​de pe o altă imagine
  
-Observațcă fișierul din exemplul de mai sus are extensia ''​.bb''​. Aceasta este o extensie specială specifică unei categorii de fișiere de configurare pentru ''​bitbake''​. Există mai multe categorii de astfel de fișiere, fiecare exprimând un set diferit de metadate (dependențe, patch-uri, instrucțiuni) pentru o anumită componentăCategoriile importante (în funcție de extensie):+Pentru fiecare dintre acești pașexistă utilitare ce ne ajută să realizăm operațiile necesare.
  
-  * ''​.bb'':​ fișiere concise ce definesc operațiile ce trebuie executate. Poartă numele de **rețete**. O rețetă poate include alte rețete și poate moșteni dintr-o altă rețetă +==== dd ====
-  * ''​.bbclass'':​ fișiere folosite pentru a preciza metadatele folosite uzual pentru operațiile comune de build sau împachetare. Aceste fișiere sunt de obicei moștenite de către rețete +
-  * ''​.inc'':​ fișiere ce conțin un anumit set de definiții. Sunt folosite atunci când vrem să particularizăm procesul de build pentru o anumită versiune, arhitectură etc. +
-  * ''​.bbappend'':​ fișiere ce conțin adăugiri sau componente opționale pentru rețete +
-  * ''​.conf'':​ fișierul local de configurare al unui proiect+
  
-Pe lângă aceste ​fișiere, pentru a personaliza un proiect/buildavem la dispoziție șo serie de variabile de sistem:+Pentru copierea, și eventual convertirea,​ unui fișier, la nivel de byte, se poate folosit utilitarul //dd//.. Folosind //dd//, putem de asemenea genera ​fișiere ​de anumite dimensiuni și le putem stabili conținutul. În cazul nostru//dd// este util pentru a inițializa o imagine și pentru a copia în acea imagine conținutul care ne interesează. Dintre parametrii lui //dd//, cei mai des utilizați sunt:
  
-  * ''​BBFILES''​: variabila ce spune sistemului ''​bitbake''​ care sunt rețetele disponibile +  * ''​if'' ​fișierul de intrare; dacă nu se specifică acest parametruse va citi de la //standard input// 
-  * ''​SRC_URI'':​ identifică ​fișierele care trebuiesc incluse în directorul ​de lucru special făcut pentru rețeta respectivă +  * ''​of'' ​fișierul de ieșire; ca și la ''​if'',​ dacă nu este specificat, se scrie la //standard output// 
-  * ''​BB_NUMBER_THREADS'':​ denotă numărul de thread-uri de ''​bitbake''​ care să ruleze +  * ''​count'' ​- numărul de blocuri de input ce vor fi copiate 
-  * ''​PARALLEL_MAKE'':​ modul în care va fi făcută compilarea și numărul de thread-uri de compilare care vor porni. Valoarea acestei variabile este aceeași ca în cazul sistemului ''​make'':​ -j <​num_threads>​ +  ​''​bs'' ​- numărul de bytes dintr-un bloc
-  * ''​MACHINE'':​ denumirea sistemului (mașinii) pentru care se realizează compilarea +
-  * ''​BBMASK'':​ lista de pachete ce vor fi ignorate în momentul compilării +
- +
-==== Rețete ==== +
- +
-Fișierele de configurare prezentate anterior poartă denumirea de rețete și au uzual extensia ''​.bb''​. În cadrul unui proiect (o distribuție) acestea definesc operațiile ce trebuie executate. În funcție de complexitatea și dimensiunea proiectuluiacesta ​va parcurge un anumit număr de etape. Dacă proiectul este mic și presupune, spre exemplu, doar compilarea unor surse, atunci este suficientă o rețetă ce conține un task ''​do_compile''​. Un proiect mai mare va trece însă cel puțin prin etapele de ''​fetch'',​ ''​configure'',​ ''​compile''​ și ''​install''​. +
- +
-Pentru un astfel de proiect va exista câte o rețetă ce conține un task de tip ''​do_''​ pentru fiecare operație. Folosind apoi proprietatea rețetelor de a include sau a specifica dependențe față de alte rețete, se creează o ierarhie ce pornește ​de la o rețetă top level și parcurge și execută în ordine toate operațiile. +
- +
-Directivele ce pot fi folosite într-o rețetă pentru a include sau moșteni alte fișiere de configurare sunt: +
-  * ''​include <​file_name>​''​: include ​fișierul ​cu numele <​file_name>​. Este folosită variabila ''​BBPATH''​ pentru a căuta fișierul +
-  * ''​require [<​path>​]<​file_name>'':​ un tip special ​de includere a fișierului <​file_name>​. Se va încerca includerea fișierului ​ca și în cazul lui ''​include'', ​dar operația va eșua dacă nu există fișierul în locația ​specificată +
-  * ''​inherit <​file_name>​''​: include definițiile din fișierul <​file_name>​.bbclass,​ dacă acesta există  +
- +
-==== Layer ==== +
- +
-Un set de rețete și alte fișiere specifice ''​bitbake'' ​ce au legătura cu o anumită funcționalitate sau o anumită componentă pot fi organizate într-un **layer**. Layer-ul este un fișier ce conține referința către o configurație și setul de rețete ce trebuiesc executate pentru a obține o anumită distribuție. +
- +
-<code yaml LayerExample>​ +
-meta-layer: ​ +
-  ​- conf +
-  - recipes-core +
-      - important_recipe +
-          - x.bb +
-  - recipes-category1 +
-      - recipe-1a +
-          - y.bb +
-          - t.bbappend +
-      - recipe-1b +
-          - ... +
-  - recipes-category2 +
-      - recipe-2a +
-          - ...  +
-      - recipe-2b +
-          - ... +
-</​code>​ +
- +
-Structura unui layer este următoarea:​ denumirea layer-ului urmată de o serie de categorii de rețete. Fiecare categorie conține lista rețetelor componente și fișierele de configurare aferente fiecarei dintre acestea. +
- +
-Atunci când parsează un fișier de tip ''​bblayer''​, ''​bitbake''​ va configura variabila de sistem ''​BBPATH''​ cu locațiile în care se găsesc rețetele necesare. În cadrul acestui proces ​de construire a variabilei ''​BBPATH'',​ dacă ierarhia conține rețete cu nume duplicat, pot apărea conflincte sau situații neașteptate în timpul compilării,​ deoarece fișierele de configurare pentru o rețetă pot fi incărcate ​dintr-o locație diferită față de cea dorită.+
  
 <note tip> <note tip>
-Pentru a automatiza procesul ​de creare ​unui layer se poate folosi comanda: +Un exemplu ​de utilizare ​lui ''​dd'' ​pentru ​a inițializa cu zerouri un fișier de o dimensiune exactă:
-<code bash> +
-pentru ​kas, intrați în shell mai întâi: +
-# apoi rulați: +
-bitbake-layers create-layer meta-mylayer +
-</​code>​ +
-</​note>​+
  
-Specificarea layer-elor ce se doresc a fi incluse într-un proiect se face prin scrierea unui fișier numit ''​bblayers.conf''​. Structura acestuia este următoarea:​ +<​code ​shell
- +$ dd if=/dev/zero of=<filebs=1M count=2048
-<​code ​bash+
-BBLAYERS ?" \ +
-<​path_to>​/poky-rasp/meta \ +
-<path_to>/​poky-rasp/​meta-yocto \ +
-<​path_to>/​poky-rasp/​meta-yocto-bsp \ +
-<​path_to>/​poky-rasp/​meta-raspberrypi \ +
-"+
 </​code>​ </​code>​
  
-Acest fișier pune în variabila de sistem ​''​BBLAYERS'' ​căile către fiecare locație în care se găsește fișierul ​''​bblayer'' ​al layer-ului dorit. +Observați valorile lui ''​count'' ​si ''​bs''​. ​Se vor copia în total 2048 de blocuri de câte 1MB fiecare, rezultând o dimensiune de 2GB. Fișierul de intrare ​''​/dev/zero'' ​este un fișier special din care se pot citi oricâte caractere ASCII NUL (0x00).
- +
-<note important>​ +
-**De ținut cont:** modalitățile ​de personalizare a parametrilor în fișiere precum ​''​bblayers.conf''​ și ''​local.conf''​ diferă atunci când folosim utilitarul **kas**, deoarece acestea vor fi generate automat!+
 </​note>​ </​note>​
  
-===== Mediul de lucru =====+==== parted ​====
  
-Pentru ​început, aveți nevoie ​de [[https://github.com/cs-pub-ro/SI-Lab-VM/releases/tag/y2022-yocto|mașina virtuală cu Yocto]] descărcată.+Pentru ​manipularea tabelei ​de partiții (crearea sau ștergerea partițiilor) se poate folosi utilitarul ​//parted//. Acesta recunoaște și poate manipula multiple formate de partiții: DOS SUN GNU GPT etc. Utilitarul primește ca parametru device-ul a cărui tabelă de partiții dorim să o modificămUn exemplu de apel este:
  
-Se recomandă să aveți ultima versiune de VMWare Workstation instalată, pe care o puteți descărca gratis de pe portalul [[https://vmware.pub.ro/]] (vă autentificați cu contul unic al facultății).+<code shell> 
 +$ parted ​/dev/<​device>​ 
 +</code>
  
-Recomandat ar fi să faceți uz de funcționalitatea de VM snapshotting pe care o pune VMWare la dispoziție, astfel încât să puteți pleca de la imaginea de bază (pe care să o țineți nemodificată!) și să aveți mai multe instanțe separate ​(sub forma unor snapshot-uri) pe care le puteți comuta manual după caz. De exemplu, doriți să experimentați ceva cu Yocto: faceți ​un snapshot nou, vă jucați liberi în acea instanță apoi, dacă experimentul a eșuat, puteți reveni mereu la starea anterioară a snapshot-ului (cu fișierele de atunci).+Rezultatul acestei comenzi este un prompt nou (similar cu //fdisk//) în care putem folosi tasta ''​m''​ pentru a afișa un meniu cu opțiunile disponibile. Opțiuni utile pentru crearea șștergerea ​de partiții sunt: 
 +  
 +  * ''​print'' ​(sau simplu, ''​p''​) - afișează tabela curentă
 +  * ''​mklabel <​type>''​ - șterge tot și crează o tabelă nouă de partiții (type poate fi ''​msdos'',​ ''​gpt''​ etc.); 
 +  * ''​mkpart [type] [fstype] <​START>​ <​END>'' ​crează o partiție nouă (type poate fi ''​primary''​ / ''​logical''​ / ''​extended''​);​ singurii parametrii obligatorii sunt cele 2 offseturi;​ 
 +  * ''​set <​partition>​ <​flag>​ <​state>''​ - setează un flag unei partiții; 
 +  * ''​rm <​NUMBER>''​ - șterge o partiție; 
 +  * ''​quit'' ​iese din program ​(toate comenzile salvează automat).
  
-Pentru un ghid de folosire a snapshot-urilor în VMWare, vedeți [[https://linuxhint.com/take-virtual-machines-snapshots-vmware-workstation/|pagina aceasta]]**TLDR:** Ctrl+în VMWare pentru Snapshot Manager ;)+Trebuie reținut că, în mod normal ​//parted// operează cu sectoare și nu cu octețiAșadar, este de preferat să punem unitatea de măsură (K, M, G etc.ca sufix la orice offset cerut de comenzi (e.g., ''​120MB''​).
  
 <​note>​ <​note>​
-Un snapshot ocupă spațiu cât doar pentru modificările aduse la imaginea lui de bază (sau un alt snapshot pe care este bazat). +  * Dimensiunea standard a unui sector ​de disc este ''​512 bytes''​Aceasta poate fi schimbată folosind opțiunea ''​-b''​. 
-Folosiți cu încredere, însă este posibil ca spațiul de modificări făcute la un build să aibe ''​~2 GB'' ​(puteți oricând combina snapshoturile reușite pentru a reduce spațiul)+  Există două tipuri de partiții''​primary''​ ș''​extended''​Un device ce folosește sistemul ​de partiții ''​DOS''​ nu poate avea mai mult de 4 partiții primare ​(la GPT s-au eliminat aceste restricții). 
-</​note>​ +  * Exemplu ​de creare ​celor 2 partiții necesare ​pentru ​o imagine bootabilă Raspberry PI:<​code>​ 
- +(parted) mklabel msdos 
-<note tip> +(parted) mkpart primary fat32 1MiB 120MiB 
-Proiectul de VM al laboratorului ​**NU** are snapshot inițial făcut (pentru a putea fi compatibil și cu VMWare Player, care nu permite acest lucru), deci ar fi o idee bună să-i faceți unul; dacă stricați ceva va trebui să-l re-descărcați ​:( (sau îl dezarhivați din nou, dacă țineți .zip-ul original la seed :D). +(parted) mkpart primary ext4 120MiB 100% 
-</​note>​ +(parted) print 
- +(parted) quit
-<note tip> +
-Yocto beneficiază ​de viteză cu cât are mai multe resurse hardware disponibile. +
-De aceea, este recomandat să utilizați VM-ul de pe un SSD și să-i configurați ~8GB ram și 4 nuclee ​(este important dacă doriți ​să recompilați kernelul sau alte componente mai mari). +
-</​note>​ +
- +
-Mai jos aveți instrucțiunile manuale ​de instalare dacă nu aveți VM-ul sau doriți să vedeți cum se face asta (atenție: compilarea inițială poate dura câteva ore bune!) +
- +
-<​spoiler>​ +
-Este recomandat să folosiți VM-ul pus la dispoziție pentru ​nu fi nevoiți să recompilați toată distribuția de la zero. +
-De asemenea, **kas** poate rula majoritatea pașilor de descărcare + compilare automat ​pentru ​noi! +
- +
-Pentru început, trebuie să ne asigurăm că utilitarele folosite de Yocto / ''​bitbake''​ sunt instalate în sistem ca să putem compila imaginea. În cazul în care acestea nu există, se pot instala folosind una din comenzile de mai jos, în funcție de distribuție: +
- +
-<​code ​bash Ubuntu 22.04+
-sudo apt-get -y install gawk wget git sed diffstat unzip texinfo gcc build-essential \ +
- chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils \ +
- iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \ +
- python3-pylint-common python3-subunit mesa-common-dev zstd liblz4-tool+
 </​code>​ </​code>​
- +  * Observați, în exemplu ​anterior, la ultima partiție s-a folosit ​unitate specială, procentul, ceea ce înseamnă că ultimei partiții i s-a repartizat tot spațiul rămas.
-<code bash Fedora>​ +
-sudo yum groupinstall "​development tools"​ +
-</​code>​ +
- +
-Apoi, sursele proiectului Yocto pot fi descărcate urmărind instrucțiunile de [[https://​www.yoctoproject.org/​downloads|aici]] sau clonate direct din repository-urile mentionate la începutul laboratorului. +
- +
-Următorul pas este să obținem layer-ele șconfigurațiile necesare pentru a compila imaginea corespunzătoare pentru sistemul dorit. În cazul nostruacest sistem este ''​RaspberryPi''​. Acest layer poate fi obținut clonând repository-ul de la adresa: [[https://​github.com/​djwillis/​meta-raspberrypi.git]] +
- +
-După ce avem sursele Yocto și layer-ul necesar pentru dezvoltarea unei imagini de RaspberryPi,​ trebuie să inițializăm mediul de compilare și directorul de lucru. Pentru aceasta, trebuie rulată următoarea comandă ​în directorul ce conține sursele Yocto: +
- +
-<code bash> +
-source oe-init-build-env <​path_to_working_directory>/<​rpi_build_folder>/​ +
-</​code>​ +
- +
-Apoi vom adăuga intrări în fișierele de configurare a mediului pentru a ne asigura că parametrii folosiți la compilare sunt corecți și că va fi inclus layer-ul pentru RaspberryPi. În directorul inițializat mai devreme, ''<​path_to_working_directory>/<​rpi_build_folder>/'',​ se găsește directorul ''​conf''​ ce conține fișierul de configurare ''​local.conf''​. Trebuie să ne asigurăm că: +
-  - ''​BB_NUMBER_THREADS''​ are valoarea egală cu numărul de thread-uri de build ce dorim să fie create. Valoarea inițială este 4 +
-  - ''​PARALLEL_MAKE''​ are valoarea egală cu numărul de procesoare disponibile. +
-<note important>​Valoarea trebuie să aibă forma ''​-j x'',​ unde x este numărul de procesoare disponibile.</​note>​ +
-  - ''​MACHINE''​ are valoarea "​raspberrypi"​ +
-  - ''​BBMASK''​ va exclude pachetele ce nu sunt suportate de core-ul Yocto. Spre exemplu, ​în unele versiuni mai vechi ale layer-ului de RaspberryPi,​ acestea erau: "​meta-raspberrypi/​recipes-multimedia/​libav|meta-raspberrypi/​recipes-core/​systemd"​ +
- +
-<note tip> Toate valorile acestor variabile sunt șiruri de caractere! O atribuire precum ''​MACHINE = my_machine_name''​ va genera eroare ​la parsare. Atribuirea corectă este ''​MACHINE = "​my_machine_name"''​ (i.e., ghilimelele sunt obligatorii)</​note>​ +
- +
-Tot în directorul ''​conf''​ există și fișierul ''​bblayers.conf''​ ce conține informația legată de layer-ele ce vor fi compilate. Trebuie să adăugăm la variabila ''​BBLAYERS''​ o cale către layer-ul de RaspberryPi. Revedeți secțiunea **Layers** și exemplul de acolo. +
- +
-Compilarea unei imagini inițiale pentru o arhitectură poate dura de la cateva ore la zeci de ore, în funcție de performanța sistemului pe care se face compilarea. Procesul este unul îndelungat deoarece sistemul de build Yocto își va construi singur toate componentele necesare precum biblioteci, cross-compiler,​ etc. Spre exemplu, observați că nu mai este necesară instalarea unui cross-compiler. Acesta va fi creat la începutul build-ului, în două etape: mai întâi va fi compilată biblioteca ''​glibc''​ pentru platforma aleasă și apoi se va crea cross-compiler-ul propriu-zis. +
- +
-Avantajul acestui mod de lucru este că efortul necesar pentru pregătirea și inițializarea unui build este mic și nu există dependențe numeroase față de alte biblioteci externe sau alte utilitare. Dezavantajul major este timpul necesar pentru o compilare. +
-</​spoiler>​ +
-\\ +
- +
-===== Exerciții ===== +
- +
-==== 0. Starea / build-ul inițial, introducere kas ==== +
- +
-Considerăm starea inițială a distribuției descărcată / precompilată în VM cu următoarea structură:​ +
-<​code>​ +
-/​home/​student/​yocto:​ +
-|-- build/ ​  # (generat de Yocto bitbake) +
-|   |-- conf/  # generate automat din kas.yml +
-|   ​| ​  |-- bblayers.conf +
-|   ​| ​  |-- local.conf +
-|   ​| ​  `-- templateconf.cfg +
-|   `-- tmp/ +
-|   ​| ​  |-- deploy/ ​ # resurse generate +
-|   ​| ​      |-- images/ ​ # aici se află imaginile generate +
-|   ​| ​      |-- ipk/     # aici se află pachetele generate +
-|   |-- cache/ ​ # nimic important aici ;) +
-|-- layers/ ​ # (descărcate de `kas`) +
-|   |-- meta-raspberrypi/ ​ # layer-ul de la RPI +
-|   `-- poky/  # distribuția poky +
-|-- kas.yml ​    # fișierul de configurare kas +
-|-- Makefile ​   # un makefile ajutător (poate) +
-|-- runqemu.sh ​ # experiment eșuat, puteți ​să-l ștergeți :D fost uitat acolo +
-</​code>​ +
- +
-Per parcursul acestui document, vom considera strict acest director de bază (neavând treabă în alte locuri). +
- +
-În VM a fost deja invocat utilitarul ''​[[https://​kas.readthedocs.io/​en/​latest/​|kas]]''​ (vedeți și documentația oficială), care a avut următoarele efecte: +
- +
-  * a clonat (descărcat) de pe git-ul oficial proiectele [[https://​git.yoctoproject.org/​poky/​tree/​|poky]] (ce conține sursele și scripturile principale ale Yocto) și [[https://​github.com/​agherzan/​meta-raspberrypi/​|meta-raspberrypi]] (Layer oficial pentru dispozitivele RaspberryPi);​ toate acestea pe baza descrierii din secțiunea ''​repos''​ a fișierului ''​kas.yml''​. +
-  * a generat fișierele de configurare ale build-ului Yocto: ''​build/​conf/​{bblayers.conf,​ local.conf, templateconf.cfg}''​. +
-  * a făcut un ''​bitbake build''​ inițial la imaginea de bază a distribuției Poky (''​core-image-base''​),​ lucru ce poate dura chiar și câteva ore (pentru compilarea atât a cross toolchain-ului,​ cât și ale kernelului și ale tuturor pachetelor instalate în distribuția de bază); din fericire, ​dată compilateaceste pachete vor rămâne în cache și vor fi refolosite la toate build-urile ulterioare (decât dacă schimbați versiunea layerelor descărcate sau doriți să upgradați pachetele -- we don't do that here!). +
- +
-Deși acest mic tool ne-a automatizat din munca de setup a unui proiect nou Yocto, acesta vine cu inconvenientul că, dacă dorim să modificăm unul dintre fișierele generate (din ''​build/​conf/''​),​ va trebui s-o facem prin intermediul fișierului de configurare ''​kas.yml''​ (more on this later). +
- +
-De menționat ar fi faptul că imaginea de bază conține strict pachetele prevăzute de către fișierele implicite de configurare ale Poky și atât. Nu este nici măcar folosibilă în starea aceasta inițială (neavând parolă la contul de ''​root''​). +
-Pentru a schimba aceste lucruri avem nevoie să ne construim propriul layer, ceea ce vom și face într-un exercițiu viitor. +
- +
-Observați faptul că nu puteți rula ''​bitbake''​ (dă ''​command not found''​). Acesta un executabil care nu se află de obicei în ''​$PATH''​-ul normal al sistemelor Linux, putând fi accesat doar după inițializarea mediului Yocto.  +
-Reamintim ​că utilitarul ''​kas''​ ne-a descărcat codul sursă al ''​poky''​ în calea ''​layers/​poky/''​. +
- +
-Tot aici găsim și scriptul ''​oe-init-build-env''​ responsabil de inițializarea. +
-Astfel, dacă încărcăm acest script în shell-ul curent: <code bash> +
-student@vm:​~/​yocto$ source layers/​poky/​oe-init-build-env +
-### Shell environment set up for builds. ### +
-You can now run '​bitbake <​target>'​ +
-... +
-# sau, alternativa prin kas: +
-student@vm:​~/​yocto$ kas shell kas.yml +
-# (se pornește un subshell unde puteți da comenzi yocto) +
-</​code>​ +
-După aceasta, utilitarele Yocto devin accesibile (însă doar în shell-ul actual, dacă utilizați mai multe terminale sau îl re-deschideți pe acesta, va trebui ​să repetați comanda în fiecare). **Atenție!** Comanda ne schimbă directorul nostru actual în ''​build/'',​ dați ''​cd ..''​ pentru a reveni în rădăcina proiectului nostru. +
- +
-În final, dorim să testăm distribuția precompilată din VM: +
-<​code>​ +
-# atenție: rulați într-un shell inițializat prin Yocto ca mai sus: +
-student@vm:​~/​yocto$ runqemu qemuarm slirp nographic +
-</​code>​ +
- +
-Argumentele ce vor fi pasate (ușor modificate) comenzii qemu: ''​slirp''​ - activează un tunel cu gazda prin care se furnizează acces la Internet, și ''​nographic''​ - folosește consola doar (nu avem server grafic în VM, mai adăuga câțiva GB în plus + mai multă memorie consumată :D). +
- +
-<note important>​ +
-Pentru ​ieși din qemu, folosiți combinația ''​Ctrl+a,​ x''​ (adică ctrl+a care va intra într-un mod invizibil de comandă a monitorului qemu, apoi, separat, tasta x).+
 </​note>​ </​note>​
  
-==== 1. Layere și rețete ​====+==== losetup ​====
  
-[[https://docs.yoctoproject.org/overview-manual/yp-intro.html#​the-yocto-project-layer-model|Un layer]] este, practic, o colecție de sine stătătoare de scripturimetadate și alte resurse construcție a unui sistem Linux. +Dacă se lucrează cu imagini din fișiere, este util să le putem //monta// pentru a vedea ce conținÎnsă acest lucru nu se poate realiza pe Linux fără a avea un dispozitiv ​de tip bloc. Din fericireutilitarul ''​losetup''​ ne poate salva în aceste situații, el permițând conectarea ​unui fișier imagine la un dispozitiv bloc virtual de forma ''/​dev/​loop<​N>'',​ unde //N// este un numădin intervalul //[0-9]//.
-O distribuție Yocto este, practic, compusă din unul sau mai multe straturi așezate unul peste altul (iar Poky, desigur, stă la baza acestora) ce aplică operații de build într-o anumită ordine pentru a obține rezultatul dorit.+
  
-Pentru a crea un layer nou, putem folosi comanda ​''​bitbake-layers''​: <code bash> +**Atenție**: ​''​losetup'' ​nu poate fi utilizat decât cu privilegii de **root** (e.g.folosiți **sudo** la toate comenzile de manipulare a dispozitivelor de sistem)!
-# asigurațivă că sunteți într-un shell Yoctocitiți mai sus ^^ ;) +
-student@vm:​~/​yocto/​build$ cd ../  # navigăm în afara directorului build/ +
-student@vm:​~/​yocto$ bitbake-layers create-layer meta-tutorial-si +
-NOTE: Starting bitbake server... +
-Add your new layer with '​bitbake-layers add-layer meta-tutorial-si'​ +
-</​code>​+
  
-<note info+Exemplu folosire: ​<code bash
-Nu recomandăm utilizarea directorului ''​build/''​ pentru a stoca codul layerelor, deoarece va fi ignorat de scriptul care împachetează arhiva cu sursele. La fel și cu directorul ''​layers/''​ (aici sunt stocate layerele third-party ce au fost vor fi descărcate automat prin //kas//). +# conectăm fișierul la un dispozitiv loop 
-</​note>​ +losetup ​/dev/loop0 ./path/to/your-image.bin 
- +# scanăm dispozitivul bloc de partiții
-Această comandă va genera scheletul pentru noul nostru layer într-un director cu numele furnizat ca parametru+partprobe ​/dev/loop0 
-Structura layer-ului nou creat va fi următoarea<​code>​ +ls -l /dev/loop0* 
-meta-tutorial-si+^ ar trebui să vedeți cele 2 partiții ale imaginii RPI: loop0p1 ​și loop0p2
-|-- conf +
-|   `-- layer.conf ​  # variabile de configurație utilizate de layer +
-|-- COPYING.MIT +
-|-- README +
-`-- recipes-example  ​ce drăguț, avem și exemplu de o rețetă ;) +
-    `-- example +
-        `-- example_0.1.bb+
 </​code>​ </​code>​
  
-Un ghid oficial pentru creare layere puteți [[https://​docs.yoctoproject.org/dev-manual/common-tasks.html#​understanding-and-creating-layers|găsi aici]] (să îl puteți consulta ulterior). +**Important / NU uitați:** la final, trebuie să deconectăm dispozitivul pentru a sincroniza cele scrise înapoi în fișier: ''​losetup -d /dev/loop<​N>''​!
  
-=== Recipes (rețete) ​===+==== mkfs ====
  
-Pentru ​a fi util, un layer conține una sau mai multe rețete. +Crearea unei partiții nu este suficient pentru ​putea stoca fișiereAvem nevoie ca partiția să conțină și un sistem de fișiereUtilitarul folosit ​pentru a crea (formata) sisteme de fișiere ​Linux este //mkfs//Parametrii pe care îi primește ​//mkfs// sunt device-ul ce trebuie formatat și tipul sistemului de fișiere dorit, specificat cu parametrul ''​-t''​.
-O rețetă este un fișier ''​.bb''​ cu sintaxă specială Bitbake ce descriu pașii de urmat de către sistemul de build pentru a genera pachete sau altera configurația unei distribuții. Apoi mai avem fișiere ​''​.bbappend'' ​care ne permit să re-configurăm rețetele din alte layere fără a le rescrie. +
-[[https://docs.yoctoproject.org/dev-manual/common-tasks.html#​writing-a-new-recipe|Ghid oficial aici]].+
  
-Rețetele se aflăde obicei, într-un director cu prefixul **//​recipes-//​** în denumirea lor, însă comportamentul real este definit în fișierul layer.conf:<​code ​make+Spre exemplucomanda ​<​code ​shell
-# We have recipes-* directories,​ add to BBFILES +mkfs -t ext4 -L MyRootFS ​/dev/fd0
-BBFILES += "${LAYERDIR}/​recipes-*/*/*.bb \ +
-            ${LAYERDIR}/​recipes-*/*/*.bbappend"​+
 </​code>​ </​code>​
-A se observa regula de globbing: se caută recursiv în orice director ce urmează această convenție, precum și sufixul de versionare ([[https://​docs.yoctoproject.org/​dev-manual/​common-tasks.html#​storing-and-naming-the-recipe|obligatoriu]]). 
-Desigur, nu avem de ce să o schimbăm, așa că trecem mai departe ;) 
  
-Pentru a folosi layer-ul nou creat, este necesar ca acesta să fie introdus în fișierul (global) de configurație al Yocto referitor la acestea: ''​bblayers.conf''​. Ne reamintim, însă, faptul că tool-ul nostru helper de build va suprascrie orice modificări vom face. +Va crea pe device-ul //fd0// un sistem de fișiere ​//ext4// cu label-ul (denumire logică//MyRootFS//. În Linuxutilitarul ​//mkfs// este împărțit în câte un executabil ​pentru ​fiecare tip de sistem de fișiere suportatPentru a le vedea pe cele disponibiledeschideți un terminalscrieți ​''​mkfs.'' ​(punct ​la coadă!și apasați tab.
-Defapt, ne generează lista de straturi ​pe baza unui fișier de configurație ''​kas.yml'',​ deci vom adăuga layer-ul nostru acolo: <code yaml> +
-# ... +
-repos: +
-  # adăugăm, pur și simplu, o cheie nouă (opțional, putem să modificăm calea către layer) +
-  meta-tutorial-si:​ +
-    path: './meta-tutorial-si'​ +
-    # atenție la identare! contează... yaml s-a inspirat din python :( +
- +
-  # ... restul de layere au fost descărcate prin URL de git... +
-  meta-raspberrypi:​ +
-    url: git://git.yoctoproject.org/meta-raspberrypi +
-  # ... +
-</code> +
- +
-Rulăm apoi ''​kas build kas.yml''​. Observăm că, în ''​build/conf/bblayers.conf''​ ne-a apărut layer-ul:<​code make> +
-BBLAYERS ?= " \ +
-    ​/home/​student/​yocto/​layers/​meta-raspberrypi \ +
-    ... +
-    /​home/​student/​yocto/​meta-tutorial-si" ​ # <-- here it is +
-</​code>​ +
- +
-Doar că trebuia să ne printeze mesajul acela din rețeta //Example// la build, ceea ce nu se întâmplă... de ce oare? (heheee) +
-Să facem altfel: <code bash> +
-# REMINDER: să aveți oe-init-build-env activat! +
-student@vm:​~/​yocto$ bitbake example ​ # să aveți oe-init-build-env activat! +
-Loading cache: 100% |##########​| Time: 0:00:00 +
-... +
-NOTE: Executing Tasks +
-*********************************************** +
-*                                             * +
-*  Example recipe created by bitbake-layers ​  * +
-*                                             * +
-*********************************************** +
-</​code>​ +
- +
-Now we're getting somewhere! Mai rămâne, deci, să adăugăm această rețetă undeva să fie executată la build-ul imaginii principale ​(//​reminder://​ denumită **''​core-image-base''​**:​ +
-<code bash> +
-student@vm:​~/yocto$ cd meta-tutorial-si/ +
-student@vm:​~/yocto/meta-tutorial-si$ mkdir -p recipes-core/​images/​ +
-student@vm:​~/​yocto/​meta-tutorial-si$ vim recipes-core/​images/​core-image-base.bbappend +
-# iar în fișier vom scrie: (suntem în vimdeci apăsăm un '​i'​ înainte pentru insert mode) +
-IMAGE_INSTALL += " example"​ +
-# <​esc>:​wq ca să nu rămânem blocați :P +
-student@vm:​~/yocto$ cd ../ +
-student@vm:​~/yocto$ kas build kas.yml +
-</code> +
- +
-... //et voila!// +
- +
-**Cum funcționează:** am extins rețeta imaginii de bază printr-un fișier ''​.bbappend''​ (pentru ​asta au fost concepute). Codul nostru va fi procesat după fișierul ''​.bb''​ originalastfel putând modifica [[https://​docs.yoctoproject.org/​singleindex.html#​term-IMAGE_INSTALL|variabila IMAGE_INSTALL]] pentru a ne fi incluse pachete custom de către task-urile rețetei generatoare de imagine. +
-Also check [[https://​docs.yoctoproject.org/​singleindex.html#​ref-features-image|these goodies]] (chestii gata făcute incluzabile printr-o linie de cod). +
- +
-Ca alternativă,​ puteam construi o nouă imagine (e.g., ''​tutorial-si-image''​) care să pornească de la prima. Doar că trebuia să build-uim noua noastră imagine (''​bitbake tutorial-si-image''​ în loc de ''​core-image-base''​).+
  
 <​note>​ <​note>​
-Am fi putut să facem același lucru prin modificarea ​''​conf/local.conf'' ​și adăugarea unei linii:<​code make> +Dacă etichetați sistemele de fișiere, le putețaccesa ulterior după căi speciale din ''/​dev/​disk/​by-label/​''​! ​
-IMAGE_INSTALL_append = " example"​ +
-</​code>​ +
-... dar este, desigur, anti-practicăVrem să avem toată funcționalitatea încapsulată în layer bine definit, păi ce facem noi aici... :P+
 </​note>​ </​note>​
  
 +==== mount ====
  
-==== 2Configurarea distribuției + pachete adiționale ====+În sistemele Unix, sistemul de fișiere este unul arborescent unde directoarele pot fi considerate noduri, iar fișierele frunzeUtilitarul //mount// ne permite să atașăm unui arbore existent un alt subarbore (sistem de fișiere). Apelată fără niciun parametru, această comandă va afișa toate device-urile montate, locația în care sunt montate și opțiunile cu care au fost montate.
  
-Înainte de a continua**să avețun layer creat** (e.g., ''​meta-tutorial-si''​ de la pasul anteror sau, desigur, puteți să folosiți ce altă denumire doriți) pe care îl vom extinde.+Formatul general al comenzii este ''​mount -t <​type>​ <​device>​ <mount path>''​unde //<​type>//​ este acelașca la //mkfs//De cele mai multe oriargumentul ​''​-t <​type>​'' ​poate fi omis, acesta fiind autodetectat ​de către kernel.
  
-Pentru a avea o distribuție Linux utilizabilă va trebui, desigur, ​să avem creat un utilizator ;) +Și, desigur, ​pentru de-montarea de la final a dispozitivelor,​ putem folosi ''​umount''​ cu argumentul ori dispozitivul sursă, ori mountpointul (oricare ne este mai la îndemână -- va face același lucru).
-Apoi vom demonstra adăugarea de resurse (fișiereîn imaginea de bază.+
  
-=== 2.1. Adăugare utilizator nou ===+===== Exerciții =====
  
-Momentanimaginea este configurată în modul de debugging ​prin această linie din ''​local.conf''​-ul generat ​(vedeți ​în ''​kas.yml''​):​ +<​note>​ 
-<​code>​ +**În laboratorvom folosi echipamente Raspberry PI 4!** conectate ​prin USB Type-C și un adaptor UART la USB pentru vizualizarea consolei dispozitivului ​(din păcate, nu dispunem de suficiente monitoare HDMI în laborator + cabluri adaptoare).
-EXTRA_IMAGE_FEATURES = "​debug-tweaks"​ +
-</​code>​+
  
-Aceasta ne setează parola goală la contul root. +Înainte de începe exercițiileasigurați-vă că aveți cel puțin 10GB de storage disponibili în mașină virtuala de laborator
-Pentru ​spori securitatea imaginii implicitese pot crea utilizatori noi / schimba parolele, +</​note>​
-[[https://​docs.yoctoproject.org/​ref-manual/​classes.html#​extrausers-bbclass|vedeți tutorialul acesta]]+
-Cum se citește:+
  
-//"​uses this class in an image recipe:"//. Deci ''​vim meta-tutorial-si/recipes-core/​images/​core-image-base.bbappend'':​ +**0.** Descărcați [[https://github.com/cs-pub-ro/SI-rpi-debian-scripts/​releases|de aici arhiva rootfs referință pentru ​laborator (v2)]] ​imaginea partiției de boot ''​rpi-boot.img''​ (pe care o vom clona mai târziu și îi vom adăuga ​partiție nouă pentru ​Linux).
-<code make> +
-# vechiul conținut: +
-IMAGE_INSTALL += "​example"​ +
-# mai adăugăm: +
-inherit extrausers +
-pentru ​a schimba parola la root: +
-EXTRA_USERS_PARAMS ​+= "​usermod ​-P student root;"​ +
-# pentru a adăuga ​un utilizator nou: +
-EXTRA_USERS_PARAMS += "​useradd -P parolalastudent student;"​ +
-# atenție: trebuie să muncim în plus pentru ​a-i da drept de sudo utilizatorului,​ deci recomand root-ul +
-</​code>​+
  
-Apoi construim imaginea din nou: ''​kas build kas.yml''​. +  * Pentru cei cu Windows, descărcați șinstalați utilitarul [[https://​www.raspberrypi.com/​software/​|Raspberry Pi Imager]]pe care îl vom folosi ​să scriem imaginea pe dispozitivul fizic.
-Și rulăm:<​code>​ +
-# nu uitați să facețsource la oe-init-build-env dacă nu aveți utiltarele în PATH +
-runqemu qemuarm slirp nographic +
-# pentru a ieșitrebuie ​să apăsăm combinația Ctrl+a, apoi separat tasta `x` +
-</​code>​+
  
-=== 2.2. Inspectare rootfs ===+1Dorim să creăm propria imagine pe care, ulterior, s-o urcăm pe Raspberry PI și să bootăm Linux-ul (prin U-Boot și modul ''​ums''​ -- USB Mass Storage Device):
  
-Următoarea întrebare care se pune este: cum vedem conținutul unei imagini generate? +  * Imaginea de //​rpi-boot.img//​ a RaspberryPi are dimensiunea de ~150MB. Folosiț''​dd'' ​(citiți și documentația din laborator mai sus) și creați o imagine nouă, plină de zerouri, de 2GB (să zicem, ''​rpi-full.img''​)
-Din fericire, suntem pe un sistem Linux, așadar putem folosi ​''​mount'' ​pentru a inspecta local partiția ext3/4 generată:<code bash> +  * Dorim să copiem ​de-a întregul prima partiție din imaginea ''​rpi-boot.img''​ în cea de 2GB proaspăt creată. Putem folosi ''​dd''​ pentru asta:<​code>​ 
-student@vm:​~/​yocto$ sudo mount -o loop build/​tmp/​deploy/​images/​qemuarm/​core-image-base-qemuarm.ext4 /mnt +dd if=rpi-boot.img of=rpi-full.img conv=notrunc
-student@vm:​~/​yocto$ ls -l /mnt +
-student@vm:​~/​yocto$ cat /etc/passwd | grep student +
-student:​x:​1000:​1000::/​home/​student:/​bin/​sh +
-# cool! +
-# NU UITAȚI: ​să de-montați ​partiția la final!!! +
-# (altfel s-ar putea să se corupă imaginea de la dublă utilizare) +
-student@vm:~/yocto$ sudo umount /mnt+
 </​code>​ </​code>​
- +  * Folosind ''​parted'',​ inspectați dacă există partiția de boot în noua imagine (cea //full//)Apoi creați pe cea de-a doua partiție (ce va conține un sistem de tip ext4)Vedeți mai sus în laborator pentru exemple ​de folosire a utilitarului;​ 
- +  * Formatați sistemul de fișiere a celei de-a doua partiții ​în ext4Pentru aceasta, va trebui, mai întâi, să conectați imaginea într-un dispozitiv de tip bloc prin ''​losetup'',​ apoi ''​mkfs''​ pentru a o formata (urmați documentația din laborator a acestor utilitare); ​ 
-=== 2.3Instalare pachete ​de bază === +  * Montați noua partiție ''​ext4''​ (puteți folosi ''/​mnt''​ ca mountpoint) și copiați conținutul arhivei rootfs descărcate mai sus; folosiți argumentul ​''​-C''​ al ''​tar''​ pentru a preciza directorul destinație,​ adică mountpointul partiției)**Atenție**:​ folosiți contul ​de ''​root'',​ deoarece dorim să dezarhivăm fișierele și să păstrăm permisiunile originale (imaginea este un root filesystem de Linux pre-instalat!): <code bash> 
- +tar xf <​ARCHIVE_FILE> ​-C <​DEST_MOUNTPOINT>​ 
-Deseori vom dori să instalăm pachete standard ​în imaginea noastră. +# inspectați calea dezarhivată
- +ls -l <​DEST_MOUNTPOINT>​ 
-Ca un prim pastrebuie ​să aflăm denumirile pachetelor disponibile în distribuția standard. +ar trebui să vedețtoate directoarele unui rootfs clasic: /bin, /usr, /dev, /opt etc.
-Pentru acesta, folosim ​''​bitbake show-recipes''​ pentru a vedea lista întreagă de rețeteMod de folosire:<code bash> +
-student@vm:​~/​yocto$ bitbake-layers show-recipes | grep -A 1 python3 +
-python3+
-  ​meta ​                ​3.10.7 +
-... șmulte alte subpachete ale bibliotecilor populare+
 </​code>​ </​code>​
- +  * Încă nu am terminat. Montați partiția de boot (prim partiție din loop deviceîntr-o cale (puteți crea directorul ​''​/​mnt/​boot/​rpi'' ​și să-l folosiți); apoi copiați fișierele ''​/boot/vmlinuz-<​versiune>''​ ''​/mnt/boot/initrd.img-<​versiune>''​ pe prima partiție (în mountpointul acesteia, ofc); acestea sunt necesare deoarece bootloaderul RPI nu știe să citească partiții ''​ext4'' ​(ci doar FAT32). 
-Problema este că acestea sunt denumiri de rețete, însă o rețetă poate defini mai multe pachete ​(de obicei, se păstrează o convenție de nume prin prefixare)+  * Tot pe partiția de bootcreați fișierul ​''​cmdline.txt'' ​și scrieți argumentele kernelului Linux:<​code>​ 
-Din păcate, va trebui să ne uităm pe codul sursă al rețetelor de oricâte ori nu există pachetele cu numele lor. +earlycon=pl011,​mmio32,​0xfe201000 console=tty1 console=serial0,​115200 root=/dev/mmcblk0p2 rw rootwait fsck.repair=yes
-Pentru pachetele standard din Poky (versiunea ​''​kirkstone''​), [[https://github.com/yoctoproject/poky/tree/​kirkstone-4.0.1/​meta|puteți explora rețetele aici]] ​(a se observa categorizarea acestora)+
- +
-Pentru a instala un pachet într-o imagine, trebuie ​să edităm rețeta imaginii (fișierul ​''​.bb'' ​dacă este imaginea noastrăaltfel prin ''​.bbappend'' ​să modificăm imaginea standard, ca mai sus):<​code ​bash+
-student@vm:​~/yocto$ vim meta-tutorial-si/recipes-core/​images/​core-image-base.bbappend +
-# adăugăm pachetele prin variabila IMAGE_INSTALL:​ +
-IMAGE_INSTALL +"​python3 python3-pip"​+
 </​code>​ </​code>​
 +  * **Acum (atenție!):​** demontați partițiile (mai întâi pe cea de boot, montată ultima oară, apoi pe cea ext4) și deconectați dispozitivul ''​loop''​!
  
-Desigurputem face același lucru prin folosirea variabilei ​''​IMAGE_INSTALL_append'' ​a lui ''​local.conf''​, dar vrem să păstrăm gruparea corectă a funcționalității în layere ;)+2. Acum că imaginea noastră este gatavrem să vedem că funcționează. Pentru aceasta, va trebui să pornim u-boot în modul ''​ums'' ​(vedeți [[:​si:​laboratoare/​05|laboratorul anterior]]) și folosim un utilitar de Raw Disk Imager (precum cel descărcat mai sus) sau ''​dd'' ​(pentru cei cu Linux nativ sau cărora le funcționează USB Device Passthrough ​în mașina virtualăpentru a scrie imaginea obținută anterior.
  
-<​note ​warning+<​note ​important
-Pentru fiecare pachet nou adăugatbitbake va porni un proces ​de compilare care s-ar putea să dureze câteva minute (posibil ​și zeci)+  * **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 argumentiar, ca destinație,​ o cale de pe PC-ul fizic, e.g., ''​C:​\Users\..etc''​)! 
-Să țineți cont acest timp de așteptare când vă planificați activitatea!+  * **Notă pentru VirtualBox**:​ va trebui ​să folosiți argumentul ''​-P 2023'' ​și ''​student@localhost:<​cale>''​ ca sursă
 +  * **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 termineAsta 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ă).
 </​note>​ </​note>​
  
-Finally, dorim să testăm noua imagine<code bash> +3. Reporniți Raspberry PI-ul. Vom încerca ​să bootăm kernelul și rootfs-ul din prompt-ul ''​u-boot''​:
-student@vm:​~/​yocto$ kas build kas.yml +
-# (sudo make coffee ...) +
-NOTE: Tasks Summary: ... all succeeded. ​ # doamne-ajută!+
  
-student@vm:​~/​yocto$ runqemu qemuarm slirp nographic +  * Deoarece kernelul este compresatoperațiunea este un pic mai complicatătrebuind să-i spunem o zonă de memorie folosibilă pentru extracția imaginii<code
-# ... +load bootargs from device tree (contains BL2-modified cmdline.txt data
-qemuarm login: root +fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs 
-Password: +set decompression zone in RAM at 400MB, 64MB in size 
-root@qemuarm:​~#​ ip a sh eth0 +setenv kernel_comp_addr_r 0x19000000 
-2: eth0: <​BROADCAST,MULTICAST,UP,​LOWER_UP>​ mtu 1500 qdisc pfifo_fast qlen 1000 +setenv kernel_comp_size 0x04000000 
-    link/ether 52:54:​00:​12:​34:​02 brd ff:​ff:​ff:​ff:​ff:​ff +# load kernel ​from file 
-    inet 192.168.7.2/​24 brd 192.168.7.255 scope global eth0 +fatload mmc 0:1 ${kernel_addr_r} vmlinuz-6.1.61-rpi+ 
-       ​valid_lft forever preferred_lft forever +boot without initrdfor now 
-# ... +booti ${kernel_addr_r} - ${fdt_addr}
-root@qemuarm:​~#​ echo "​nameserver 8.8.8.8" ​/​etc/​resolv.conf +
-root@qemuarm:​~ping google.com +
-PING 8.8.8.8 ​(8.8.8.8): 56 data bytes +
-64 bytes from 8.8.8.8: seq=0 ttl=127 time=30.050 ms +
-64 bytes from 8.8.8.8: seq=1 ttl=127 time=20.487 ms +
-root@qemuarm:​~pip3 install youtube-dl +
-root@qemuarm:​~#​ python3 +
-Python 3.10.7 (main, Sep  5 2022, 13:12:31) [GCC 11.3.0] on linux +
-Type "​help",​ "​copyright",​ "​credits"​ or "​license"​ for more information. +
->>> ​from youtube_dl import YoutubeDL +
->>>​ ydl = YoutubeDL() +
->>>​ ydl.add_default_info_extractors() +
->>>​ info = ('​https://www.youtube.com/​watch?​v=ITRBsXrPOn8'​) +
->>>​ info['​title'​] +
-mulțumițiputem ieși ;) +
-# dacă rămâneți blocați în qemu console, căutați mai sus cum ieșiți :P+
 </​code>​ </​code>​
 +  * Dacă vă printează mesajul cu ''​waiting for device /​dev/​mmcblk0p2''​ și nu se termină procesul, verificați dacă ați rulat kernel-ul 6.1 (este în comanda de mai sus) și dacă partiția a doua există (''​part list mmc 0''​).
  
-=== 2.4. Adăugare resurse ​în imagine ​===+4. Dorim să instalăm pachete ​în imagine. Deoarece pe Raspberry PI nu avem Internet, vom face asta pe mașina virtuală, lucrând direct cu imaginea și utilitarele ''​systemd-nspawn''​ (pornește facil un chroot container) și ''​qemu-user-static''​ (ce ne va permite emularea unei arhitecturi străine direct dintr-un container)!
  
-O dată instalate pachetele necesare ​(e.g., ​interpretorul python), vom dori să configurăm sau să instalăm scripturi custom-made+  * Folosind ''​losetup'',​ ''​partprobe''​ și ''​mount'',​ montați partiția a doua (e.g., ​în ''/​mnt''​). 
- +  * Copiați utilitarul ​''​qemu-<​arch>​-static'' ​pentru arhitectura emulată (AArch64) în rootfs (în ''/​mnt/usr/bin''​):​ <​code>​ 
-Putem face asta prin intermediul rețetelor. Reamintim că acestea execută anumite acțiuni într-o ordine bine definită. +vedem unde e executabilul:​ 
-Printre primele task-uri efectuate se numără cel de //fetch source files//, ce de multe ori constă în descărcarea codului de pe un server. +which qemu-aarch64-static 
-Într-o rețetă, se face asta prin intermediul variabilei de configurare ​''​[[https://​docs.yoctoproject.org/​ref-manual/​variables.html#​term-SRC_URI|SRC_URI]]'' ​care ne permite inclusiv prin căi locale. +# /usr/bin/​qemu-aarch64-static 
- +cp -f /usr/​bin/​qemu-aarch64-static ​/mnt/usr/bin 
-De exemplu, edităm rețeta exemplu ​(''​meta-tutorial-si/recipes-example/example/example_0.1.bb''​):<​code ​make+chmod +/mnt/usr/bin/qemu-aarch64-static
-... (după descrierea din antet) +
-LICENSE = "​MIT"​ +
- +
-adăugăm fișiere sursă +
-SRC_URI = "file://hello.py \ +
-           file://example.conf"​ +
-# sau pe linii separate: +
-#​SRC_URI ​+= "file://example.conf"​ +
-# fișierele sursă vor fi copiate ​descărcate în ${WORKDIR}! +
- +
-# va trebui să intervenim cu un pas de instalare pentru a le copia în imagine: +
-do_install() { +
-    # atenție: ${D} represintă directorul destinație în procesul de împachetare! +
-    #          orice generați în afara acestuia nu va fi inclus în pachet! +
-    # copiem scriptul în bin+
-    install -D -m 0755 -t ${D}${bindir} ${WORKDIR}/hello.py +
-    # copiem conf-ul în /etc: +
-    install ​-D -m 0644 -t ${D}/etc ${WORKDIR}/​example.conf +
-+
- +
-python do_display_banner() { +
-# ... restul rămâne+
 </​code>​ </​code>​
- +  * Rulăm containerul: <​code>​ 
-Dacă încercați să build-uiți pachetul sau imaginea (''​bitbake example''​),​ veți obține o eroare cum că nu poate găsi fișierele incluse (și vă dă și căile unde le puteți crea). +systemd-nspawn ​--as-pid2 --resolv-conf=copy-host -D "/mnt" ​bash
-O convenție foarte bună ar fi subdirectorul ''​files'',​ deci: <​code ​bash+
-student@vm:​~/​yocto$ mkdir -p meta-tutorial-si/recipes-example/​example/​files/​ +
- +
-student@vm:​~/​yocto$ vim meta-tutorial-si/recipes-example/​example/​files/​hello.py +
-#​!/​usr/​bin/​python3 +
-with open("/​etc/​example.conf", "​r"​) as f: +
-  name f.readline().strip() +
-print("Hello, I am " + name) +
- +
-# <​esc>:​wq pentru a ieși din vim ;) +
- +
-student@vm:​~/yocto$ echo "STUDENT"​ > meta-tutorial-si/​recipes-example/​example/​files/​example.conf +
-student@vm:​~/​yocto$ bitbake example+
 </​code>​ </​code>​
- +  * Ar trebui să fiți în containerul de Debian pe arhitectură străină (AArch64), emulat ​prin qemu-user-static ​cu ajutorul funcționalității din kernel ​''​binfmt_misc''​. ​Rulați ''​apt update''​ și instalați pachetele ​''​wpasupplicant''​ (pentru autentificare prin WiFi) și ce alte utilitare mai doriți. 
-Desigur, obținem iar o eroare, plângându-se că fișierele adăugate nu au precizată licența șchecksum-urile (pentru securitate sporită). +  * La final, **nu uitați** să de-montați + deconectați dispozitivele loop utilizare! 
-Modificăm iar fișierul ''​example_0.1.bb'':<​code make> +  * Bonus: testați noua imagine ​pe dispozitivul RPI4 (va trebui să repetați pașii copiere + burn folosind Disk Imager)!
-LICENSE = "​CLOSED"​ +
-</​code>​ +
- +
-Iar ''​bitbake example'',​ iar o erorare despre [[https://​www.google.com/​search?​q=yocto+rdepends+python3|RDEPENDS la python3]], iar rezolvă(''​example_0.1.bb''​):<code make> +
-# Yocto detectează automat (prin shebang-ul pus la script) că avem nevoie de python3 +
-RDEPENDS:​${PN} += "​python3-core"​ +
-</​code>​ +
- +
-Generăm imaginea: ''​kas build kas.yml''​ apoi o rulăm (prin ''​runqemu''​). +
- +
-În qemu, rulăm scriptul:<​code bash> +
-root@qemuarm:​~#​ hello.py +
-Hello, I am STUDENT +
-</​code>​ +
- +
-<​hidden>​ +
-==== 3. Bonus / extra tasks ==== +
- +
-Pentru a modifica numele pe care îl publică un RaspberryPi este suficient să modificăm ''/​etc/​hostname''​. Pentru aceasta am putea modifica fișierul din imagine, dar dezavantajul este că ar trebui să facem această modificare la fiecare recompilare. Am prefera să obținem direct o imagine ​cu numele nou, iar ca să obținem acest lucru trebuie să modificăm rețetele Bitbake care stau la baza pachetelor instalate în imagine. +
-Fisierul ​''​hostname''​ ar trebui sa fie plasat aici: ''<​poky_path>/​meta/​recipes-core/​base-files/​''​. +
- +
-Pentru a adăuga un fișier ''​hostname''​ în imagine trebuie să:  +
-  * aveți un fișier ​''​hostname'' ​în locația unde sunt toate fișierele de inclus +
-  * modificați fișierul ​''​.bbappend''​ (adăugirea la rețetă), adăugând în variabila ''​SRC_URI''​ noul fișier (cu += ) și implementând o funcție cu numele ''​do_install_append()'',​ care se va executa în cadrul rețetei după ''​do_install''​ +
-  * Rulați apoi ''​bitbake core-image-base''​ +
-  * Verificați rezultatul rulând ​noua imagine ​cu Qemu! +
- +
-</​hidden>​+
  
 ===== Resurse ===== ===== Resurse =====
  
-  * [[https://​github.com/​cs-pub-ro/​SI-Lab-VM/​releases/​tag/​y2022-yocto|Yocto Lab VM y2022]] +  * [[https://​github.com/​cs-pub-ro/​SI-rpi-debian-scripts|Cod sursă scripturi compilare bootloader ​kernel ​generare rootfs]]
-  * [[https://docs.yoctoproject.org/​ref-manual/​|Yocto Reference Manual]] +
-  * [[https://​docs.yoctoproject.org/​ref-manual/​variables.html|Yocto Variables Reference]]+
  
  
si/laboratoare/06.1668373610.txt.gz · Last modified: 2022/11/13 23:06 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