Differences

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

Link to this comparison view

si:laboratoare:05 [2023/11/05 11:17]
florin.stancu
— (current)
Line 1: Line 1:
-====== Laboratorul 05. The embedded boot process ====== 
- 
-Atunci când un microprocesor primește semnalul de reset (prin alimentare ori transmiterea unor comenzi / întreruperi interne etc.), acesta începe să ruleze un program inițial numit bootloader. 
-Sistemele moderne folosesc un proces de boot multi-stagiu,​ însă primul este mereu încărcat dintr-un ROM (Read Only Memory) care, de cele mai multe ori, este integrat în același chip. 
- 
-==== Procesul de boot standard ARM ==== 
- 
-Arhitectura ARMv8 propune următoarea structură: 
- 
-{{:​si:​laboratoare:​arm_booting_process.png?​700}} 
- 
-Se observă numărul mare de pași decât metoda naivă pe care sistemul trebuie să-i realizeze până să pornească kernelul sistemului de operare. 
-Acest lucru se datorează punerii accentului pe securitatea soluțiilor incorporate (prin tehnologia ARM TrustZone, de care doar vom menționa scurt, pe Raspberry PI nefiind implementată în totalitate),​ însă necesitatea a 3 stagii diferite este dată de un motiv simplu: memoria disponibilă în diferitele momente ale procesului. 
- 
-Așadar, prima dată se începe prin rularea primului stagiu, ''​BL1'',​ stocat în memoria ROM. Acesta va încărca, de pe o memorie flash externă (de obicei, prin SPI: eMMC sau SD), următoarele stagii. Dintre acestea, ''​BL2''​ este, de obicei, un firmware foarte mic (//​10-100KB//​) ce este încărcat în memoria SRAM a SOC-ului (care, uneori, funcționează și pe post de cache) și care, mai departe, inițializează toate perifericele chip-ului (printre care, foare important este DRAM-ul -- folosit de următoarele stagii cu consum ridicat de RAM!). 
- 
-Stagiile ''​BL3x''​ devin opționale, totul depinzând dacă ''​BL2''​ conține funcționalitatea de a porni și Kernel-ul de Linux și este suficient de configurabil pentru a putea acoperi o mare parte a cazurilor de utilizare ale sistemului (ceea ce este adevărat pentru RPI, însă deseori nu pentru celelalte SoC-uri) sau dezvoltatorul software dorește să beneficieze de funcționalități avansate de boot (aici, ''​BL31''​ poate oferi partiționare A/B cu toleranță la defecte, actualizări la distanță etc.) sau încărcarea unui sistem de operare securizat (Trusted OS, la pasul ''​BL32''​). 
- 
-În final, ultimul pas al bootloaderului va fi să citească configurația (de pe o partiție de boot sau dintr-o altă memorie ROM re-programabilă) și componentele de rulare (kernel, initrd, device tree blob -- de cele mai multe ori, toate 3 fiind necesare) ale sistemului de opreare, și să încarce în RAM și să paseze execuția CPU-ului către kernel. 
- 
-==== Procesul de boot al Raspberry PI ==== 
- 
-Deși procesul de boot diferă între //Raspberry PI// versiuni mai vechi sau egale cu **3** (ce folosește SoC-ul ''​BCM2837''​) și cele **după 4** (cu ''​BCM2711'',​ și, pe viitor, v5), stagiile se încadrează în arhitectura propusă de ARM. 
- 
-Toate versiunile procesoarelor Broadcom folosite la RPI încep prin rularea stagiului ''​BL1''​ pe microcontrollerul de gestionare a GPU-ul integrat (da, pe bune!), care, mai departe, inițializează memoria cache, interfața SPI (pentru accesarea memoriei flash din eMMC / card SD) și, folosind o bibliotecă incorporată de citire de pe partiții FAT32, scanează după existența firmware-ului pentru următorul stagiu, ''​BL2'',​ pe care îl va încărca în cache-ul L2 al procesorului (DRAM-ul încă nu a fost inițializat). 
- 
-Ordinea de scanare a perifericelor pentru continuarea procesului de boot (e.g., SD Card / eMMC, extenal SPI, USB Mass Storage, LAN boot) diferă în funcție de starea unor GPIO-uri sau a unor regiștri OTP (One Time Programmable). 
- 
-Așadar, un Raspberry PI are nevoie ca dispozitivul de pe care se efectuează bootarea să conțină o primă partiție FAT32 cu cel puțin firmware-urile de inițializare a platformei (''​bootcode.bin'',​ ''​start*.elf'',​ ''​config.txt''​ și altele câteva ce depind de modelul efectiv). 
- 
-<note important>​ 
-Fiecare microprocesor are propriile convenții de stabilire a adreselor de încărcare a stagiului secundar. 
-Cei de la Broadcom au ales să folosească partiții FAT32, însă majoritatea producătorilor de SoC-ul incorporate cu ARM (e.g., Allwinner, NXP) preferă să încarce o imagine specială de la un anumit offset al disk-ului (e.g., la adresa ''​32KB''​ de la începutul cardului SD). De aici vine și recomandarea de a crea prima partiție abia începând cu offset-ul de ''​1MB''​. 
-</​note>​ 
- 
-Pentru [[https://​www.raspberrypi.com/​documentation/​computers/​raspberry-pi.html#​boot-sequence|Raspberry PI 3]], se va încărca fișierul ''​bootcode.bin''​ ca stagiu secundar, care, după inițializarea RAM-ului, va citi și încărca următorul stagiu (care este, de obicei, sistemul de operare propriu-zis,​ însă se poate interpune un alt bootloader -- ''​BL31'',​ e.g., [[https://​www.denx.de/​project/​u-boot/​|U-Boot]]). 
- 
-La versiunile de Raspberry PI ''>​=4'',​ ''​BL2''​ poate fi încărcat doar dintr-un EEPROM prin interfață SPI (și NU de pe SD / eMMC-ul extern -- însă există procedură de recovery în caz că se strică ceva), fapt ce ușurează aplicațiile care făceau network boot. De asemenea, firmware-ul este open-source (ceea ce nu era adevărat până acum). 
- 
-Mai departe, //Secondary Program Loader//-ul va încărca firmware-uri adiționale pentru GPU (pentru a putea afișa text prin HDMI), va analiza conținutul fișierului ''​config.txt''​ și va pune în aplicare procedurile configurate (încărcarea în memorie a fișierelor de kernel / device tree / initramfs). 
- 
-==== Componentele pentru boot ale Linux ==== 
- 
-După cum a fost menționat mai sus, pentru a porni un sistem de operare pe bază de Linux se folosesc, de cele mai multe ori, 3 componente: 
- 
-  - **Imaginea Kernel-ului** (''​kernel*.img''​),​ ce conține codul executabil al nucleului Linux; 
-  - **Device Tree Blob-ul** (''​*.dtb''​):​ conține descrierea și configurația tuturor componentelor specifice platformei hardware (i.e., pentru un anumit model + versiune a unei plăci de bază), însă se pot codifica și anumite setări și meta-informații pentru software (e.g., kernel command line, partiția rădăcină etc.); 
-  - **RamDisk inițial** (''​initrd*.img''​):​ opțional, poate conține o imagine a unui sistem de fișiere minimalist (max. câțiva zeci de MB) cu module și scripturi necesare pentru a monta sistemul de fișiere rădăcină (e.g., dacă se dorește montarea unui sistem la distanță, trebuie mai întâi să se conecteze la rețea și să primească IP prin DHCP). 
- 
-Bootloaderul (ori ''​BL2''​-ul integrat, ori ''​BL31''​ -- dacă a fost inclus) va încărca aceste fișiere în DRAM-ul sistemului și va completa anumiți regiștri (cu pointerii la locația de încărcare a tuturor componentelor necesare) și va executa o instrucțiune de //branch// pentru a lansa kernelul în execuție. 
- 
-Obiectivul final al componentelor de boot Linux va fi să caute și să monteze sistemul de fișiere rădăcină (**roofs**-ul) ce conține toată configurația și programele din //​user-space//,​ de unde se va lansa procesul ''​init''​ care va continua prin pornirea serviciilor predefinite (care pot, la rândul lor, să inițializeze dispozitive hardware noi și să ruleze procese de automatizare). 
- 
- 
-===== Exerciții ===== 
- 
-<note warning> 
-**În laborator, vom 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). 
- 
-Înainte de a începe exercițiile,​ asigurați-vă că aveți cel puțin 10GB de storage disponibili în mașină virtuala de laborator. 
-</​note>​ 
- 
-**0.** Descărcați [[TODO|de aici o arhivă unui sistem de fișiere folosit ca referință laborator]] pentru Raspberry PI 4. 
- 
-  * Dezarhivați arhiva. **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!);​ 
-  * Inspectați căile ''/​boot''​ și ''/​boot/​firmware''​. Care credeți că este conținutul partiției de **BOOT**? 
-  * Apoi, ne vom pregăti să pornim Raspberry PI 4! 
-  * Asigurați-vă că firele ce conectează Raspberry PI-ul la adaptorul de serială nu sunt ieșite. Dacă da, [[https://​pinout.xyz/​|conectați-le corespunzător]] (UART RX/TX la TX/RS-ul adaptorului!) și **chemați asistentul înainte de a-l alimenta**! 
-  * În final, înainte de a-l alimenta, conectați-vă adaptorul serial la USB în laptop și porniți programul preferat de consolă serială (e.g., ''​picocom''​),​ folosind baud rate-ul ''​115200''​. 
- 
-**1.** Alimentați RPI-ul și urmăriți mesajele din consolă. Ar trebui să vă intre în U-Boot (preinstalat pe cardurile SD ca ''​BL31''​),​ apoi: 
- 
-  * Dacă apare că rulează un proces de network boot, apăsați Ctrl+C pentru a-l întrerupe; 
-  * Din prompt-ul u-boot, rulați comanda ''​mmc list''​. O să vă apară o listă de dispozitive MMC (printre care și cardul SD); 
-  * Apoi rulați comanda ''​ums mmc <​N>'',​ unde ''<​N>''​ este numărul perifericului MMC. Acesta va lansa în execuție un program care emulează un Mass Storage Device pe interfața USB Type-C folosită la conectarea la laptop; 
-  * Inspectați noul dispozitiv montat (nu uitați să faceți pass-through la noul device USB în mașina virtuală, dacă este cazul!). 
- 
-**2.** Ne dorim să copiem conținutul fișierelor de pe sistemul de fișiere referință pe cardul SD din Raspberry PI (folosind USB Mass Storage-ul prin USB Type-C). Copiați conținutul directoarelor imaginii oficiale în directoarele imaginii noastre. După ce procesul de copiere s-a terminat, demontați device-urile și ștergeți loop device-urile. 
- 
-<note important>​ 
-Conținutul partiției ''/​boot/​firmware/''​ trebuie copiat în partiția de boot corespondenta din imaginea noastră. 
-În mod similar, copierea trebuie făcută intre partițiile de rootfs. 
-</​note>​ 
- 
-<note warning> 
-In procesul de boot al sistemului, partitiile sunt cautate de kernel dupa label-ul acestora. Pentru a ne asigura ca sistemul booteaza cu succes, va trebui sa denumim partitiile conform imaginii de Debian. 
- 
-Optiunea ''​-L''​ a comenzii ''​mkfs.ext4'',​ respectiv optiunea ''​-n''​ a comenzii ''​mkfs.vfat''​ ne ofera posibilitatea de a atribui un label atunci cand cream sistemul de fisiere. 
- 
-Paritia de boot trebuie sa aiba label-ul ''​RPI_BOOT'',​ iar partitia pentru rootfs trebuie sa aiba label-ul ''​RPI_ROOTFS''​. 
-</​note>​ 
- 
-**3.** Boot Linux! 
- 
-===== Resurse ===== 
- 
-  * [[https://​www.raspberrypi.com/​documentation/​computers/​raspberry-pi.html#​boot-sequence|Procesul de boot al Raspberry PI]] 
-<​hidden>​ 
-  * TODO {{:​si:​si:​lab:​lab5:​sol_lab5.txt | Soluție laborator}} 
-</​hidden>​ 
  
si/laboratoare/05.1699175828.txt.gz · Last modified: 2023/11/05 11:17 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