Differences

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

Link to this comparison view

si:laboratoare:03 [2022/10/25 13:57]
florin.stancu [7. Rulați programul compilat la punctul 2 pe //guest//]
si:laboratoare:03 [2024/10/23 20:48] (current)
robert_ionut.alexa
Line 1: Line 1:
-====== Laboratorul 03. QEMU ======+===== Laboratorul 03. NuttX - Wi-Fi, Bootloader ​=====
  
-<note important>​ +În laboratorul ​de astăzi vom configura placa Esp32 să acceseze internetul prin intermediul Wi-Fi-ului ​(denumit station mode), iar mai apoi vom conecta laptopul la Esp32 (care va rula într-configurație denumită SoftAP) ​pentru a avea conectivitate la internet.
-Atenție! Pentru rezolvarea laboratorului,​ recomandăm folosirea sistemului ​de operare Ubuntu 22.04. +
-Puteți descărca o mașina virtuală Ubuntu 22.04 de pe torrent ​([[https://​ocw.cs.pub.ro/​courses/​_media/​si/​lab/​si_lab_vm_2022.torrent.zip|.torrent.zip]]sau variantă de pe OSBoxes [[https://​www.osboxes.org/​ubuntu/​|osboxes]] și apoi folosiți [[https://​www.vmware.com/​content/​vmware/​vmware-published-sites/​us/​products/​workstation-player/​workstation-player-evaluation.html.html|VmWare Player]] ​pentru a o rula. +
-</​note>​+
  
-===== Introducere =====+În final, vor fi prezentate câteva noțiuni despre procesul de boot de pe Esp32.
  
-Până acum am interacționat cu sisteme embedded simple, niște ceasuri FitBit, care au fost programate folosind JavaScript.+==== Wi-Fi ====
  
-În continuare, laboratorul își propune să vă familiarizeze cu sisteme embedded care rulează Linux, începând ​de la dezvoltare ​și configurare,​ până la mentenanță. Vom trata subiecte precum: +Plăcile Esp32 încorporează un modul RF (Radio Frequency) prin intermediul căruia dispun ​de Wi-Fi, Bluetooth ​și BLE (Bluetooth Low Energy). Deoarece toate cele trei tehnologii funcționează la frecvențde 2.4GHznu putem să primim ​și să trimitem date în același timp și pe Wi-Fi și prin Bluetooth. Pentru a fi posibil acest lucru, se folosește time-division multiplexing.
-  * Rularea/​Compilarea ​de aplicații pe un sistem embedded +
-  * BootloadereKernel, Root FS, Toolchain +
-  * Instalarea ​și configurarea de servicii +
-  * Construirea unei distribuții Linux pentru sisteme embedded +
-  * Emularea sistemelor+
  
 +În comunicația prin Wi-Fi, un device poate să aibă unul dintre rolurile de mai jos:
  
-==== De ce Linux? ====+  * Router - definește o nouă rețea. 
 +  * Access Point - un device care face parte dintr-o rețea, se conectează la router, dar este folosit pentru a crea subrețele. 
 +  * Station - un simplu device conectat în rețea.
  
-Sistemele Linux oferă o mulțime de avantaje dezvoltatorilor de produse, care micșorează timpul de dezvoltare, lucru care este din ce în ce mai important în zilele noastre: +<note tip> 
-  * **versatilitate**:​ Sistemele Linux nu trebuie să fie single-purpose,​ se pot adăuga multiple funcționalități cu ușurință (chiar și în etapa de post-producție) +Un smartphone poate funcționa ca un access point atunci când este configurat hotspot-ul.
-  * **codebase mare**: Sistemele Linux abundă de aplicații user-space, drivere pentru o mulțime de dispozitive,​ suport pentru multe protocoale/​sisteme de fișiere/​etc. +
-  * **securitate**:​ Sistemele care folosesc servicii comune în Linux beneficiază de același nivel de securitate ca pe un sistem desktop sau server +
- +
-De-a lungul anilor Linux a devenit cel mai folosit sistem de operare pentru aplicațiile embedded. Îl puteți găsi folosit în orice: +
-  * telefoane mobile (Android) +
-  * router-e +
-  * DVR, NAS +
-  * quadcoptere +
-  * [[http://​store.steampowered.com/​livingroom/​SteamMachines/​ | console de jocuri]] +
-  * [[http://​www.geek.com/​chips/​this-intelligent-fridge-runs-linux-on-an-arm-chip-1297126/​ |  frigidere ]] +
- +
-După cum se poate vedea, sistemele embedded diferă foarte mult în dimensuni și putere de procesare, unele dintre ele apropiindu-se chiar de puterea de procesare a unui calculator obișnuit. De asemenea, aplicațiile pe care acestea le rulează pot fi foarte variate (ex: smartphone), amestecând diferențele dintre un calculator obișnuit și un sistem embedded. Un lucru care deosebește însă sistemele embedded este modul de interacțiune cu utilizatorii,​ care foarte rar se face printr-un ecran și o tastatură. Lipsa unui mod tradițional de interacțiune cu utilizatorul este și ceea ce face dezvoltarea unui sistem embedded mai grea, dar și mai interesantă. +
- +
-Cele mai întâlnite două metode de interacțiune cu un sistem embedded în timpul dezvoltării sunt: consola serială și conexiunea SSH. Dintre acestea, conexiunea SSH este metoda mai robustă și mai simplu de utilizat, însă ea e disponibilă doar pe sistemele care dispun de o interfață de rețea. Consola serială, însă este de obicei prezentă pe orice sistem și permite interacțiunea cu sistemul chiar și înainte ca interfața de rețea să fie disponibilă (ex: în bootloader sau înainte de ințializarea driver-ului de rețea). +
- +
-Există două concepte importante folosite în dezvoltarea unui sistem embedded: **target** și **host**. //​Target//​-ul este reprezentat de sistemul embedded pe care îl dezvoltăm și la care ne conectăm (ex: RaspberryPi,​ Intel Galileo etc.). //Host//-ul este reprezentat de calculatorul pe care îl folosim pentru dezvoltare și prin care ne conectăm cu sistemul embedded. //Host//-ul beneficiază de obicei de o putere de procesare mult mai mare, care micșorează de exemplu timpul de compilare în comparație cu compilarea pe //​target//​. +
- +
-===== RaspberryPi ===== +
- +
-| {{:​si:​lab:​2015:​intro:​raspberry-pi-3-ports.jpg?​400|}} | +
-^ RaspberryPi Model B ^ +
- +
-Vom lucra în principal cu RaspberryPi 3, un sistem de calcul bazat pe un procesor "​System on Chip" ARM de la Broadcom. Specificațiile complete sunt: +
-  * procesor: 64-bit quad-core ARM Cortex-A53, 1.2GHz +
-  * 1GB RAM +
-  * 4 porturi USB 2.0 +
-  * 1 conector Ethernet +
-  * card microSD +
-  * HDMI, jack audio, RCA +
-  * Diverse alte periferice: GPIO, UART-uri, I²C, SPI, I²S +
- +
-| {{:​si:​lab:​2015:​intro:​rasp-hardware.png?​400|}} | +
-^ Schema perifericelor RaspberryPi ^ +
- +
-==== Schema bloc ==== +
- +
-Din punct de vedere hardware, RaspberryPi este un dispozitiv simplu, care expune diferitele periferice pe care le oferă SoC-ul Broadcom. Singura excepție o reprezintă Hub-ul USB, care dublează numărul de porturi USB disponibile și atașează și un dispozitiv Ethernet la SoC-ul Broadcom.  +
- +
-| {{:​si:​lab:​2015:​intro:​raspberrypi_blockdiagram.png?​direct&​600 | }} | +
-^ Diagrama bloc ^ +
- +
-| {{:​si:​lab:​2015:​intro:​9512_blockdiagram.png?​direct&​600 | }} | +
-^ Diagrama block a chip-ului de USB și Ethernet ^ +
- +
-===== QEMU ===== +
- +
-[[http://​qemu.org| QEMU]] este un emulator / hipervizor, care permite rularea unui sistem de operare complet ca un simplu program în cadrul unui alt sistem. A fost dezvoltat inițial de [[https://​en.wikipedia.org/​wiki/​Fabrice_Bellard| Fabrice Bellard]] și este disponibil gratuit, sub o licență open source. QEMU poate rula atât pe Linux, cât și pe Windows [[#​referinte| [1]]][[#​referinte| [3]]][[#​referinte| [4]]]. +
- +
-Este un hypervizor, deoarece poate virtualiza componentele fizice ale unui sistem de calcul, pentru a permite rularea unui sistem de operare, numit oaspete (//​guest//​),​ în cadrul altui sistem de operare, numit gazdă (//host//). În acest mod de funcționare, atât sistemul //guest//, cât și sistemul //host//, folosesc aceeași arhitectură (ex: x86). QEMU poate folosi ​un modul de nucleu, KVM, pentru a accelera rularea //​guest//​-ului, ​atunci când există suport pentru virtualizare în hardware. În acest caz QEMU poate atinge o performanță comparabilă cu sistemul nativ, deoarece lasă mare parte din cod să se execute direct pe procesorul //host//. Folosind KVM sunt suportate diferite arhitecturi,​ printre care x86, PowerPC și S390 [[#​referinte| [1]]]. +
- +
-Este un emulator deoarece poate rula sisteme de operare și programe compilate pentru o platformă (ex: o placă ARM) pe o altă platformă (ex: un PC x86). Acest lucru este făcut prin translatarea dinamică a intrucțiunilor architecturii //guest// în instrucțiuni pentru arhitectura //host//. Ca un emulator, QEMU poate rula în două moduri [[#​referinte| [2]]][[#​referinte| [4]]]: +
-  * //​[[http://​wiki.qemu.org/​download/​qemu-doc.html#​QEMU-User-space-emulator| User-mode emulation]]//,​ în care un executabil obișnuit (user-space),​ compilat pentru o arhitectură,​ este rulat pe o altă arhitectură. În acest mod de funcționare instrucțiunile din executabil sunt translatate în instrucțiuni ale arhitecturii //host//, iar argumentele apelurilor de sistem sunt convertite pentru a putea fi pasate sistemului de operare //host//. Sistemele de operare emulate sunt: Linux, Mac OS X și BSD. Principalele utilizări sunt cross-debugging-ul și cross-compilarea,​ unde rulăm un compilator nativ al arhitecturii //target//, pe arhitectura //host//. +
-  * //​[[http://​wiki.qemu.org/​download/​qemu-doc.html#​QEMU-System-emulator-for-non-PC-targets| System emulation]]//,​ în care este emulat un sistem de calcul complet. QEMU permite emularea unui număr mare de platforme, bazate pe diferite arhitecturi (ex: x86, ARM, PowerPC, MIPS, SPARC, MicroBlaze etc.), împreună cu perifericele lor.  În acest mod de funcționare pot fi rulate sisteme de operare întregi, printre care Windows, Linux, Solaris, BSD și DOS. +
- +
-În dezvoltarea sistemelor embedded, QEMU este folosit deoarece poate emula un sistem de calcul complet, nefiind necesar ca sistemul țintă (//​target//​) pentru care se face dezvoltarea,​ și sistemul //host//, pe care se face dezvoltarea,​ să folosească aceeași arhitectură. Acest lucru permite ca dezvoltarea software-ului pentru un sistem embedded să poată fi făcută în paralel cu proiectarea hardware-ului,​ lucru crucial pentru obținerea unui timp de dezvoltare scurt. Un alt avantaj pe care il poate avea emularea, mai ales a sistemelor low-end, este o viteză superioară a emulării pe un sistem //host// performant, în comparație cu sistemul //​target//​. +
- +
-==== Instalare ==== +
- +
-Cel mai simplu mod de instalare pe o distribuție Linux este de a folosi //package manager//​-ul. În majoritatea distribuțiilor pachetul principal se numește ''​qemu''​ și cuprinde de obicei toate executabilele aferente diferitelor moduri de funcționare ale QEMU. Dacă se dorește doar modul de virtualizare cu KVM poate fi instalat pachetul ''​qemu-kvm'',​ iar dacă se dorește modul de emulare a unui sistem ARM poate fi instalat pachetul ''​qemu-system-arm''​. +
-<​note>​ +
-<code shell Ubuntu 22.04> +
-sudo apt update +
-sudo apt install qemu qemu-kvm qemu-system-arm qemu-tools +
-</​code>​+
 </​note>​ </​note>​
  
-Dacă distribuția folosită nu oferă un pachet pentru QEMU (ex: Windows) sau pachetul oferit conține o versiune prea veche (ex: Fedora 17)se poate alege instalarea din surse. În acest cazsursele oficiale pot fi downloadate din [[https://​git.qemu.org/?​p=qemu.git;​a=summary| repository]]-ul de Git, iar pentru instrucțiuni de compilare ​se poate urmări [[http://​wiki.qemu.org/​download/​qemu-doc.html#​compilation| pagina ​de manual]]. +În NuttXEsp32 poate rula atât ca un stationcât și ca un access point (software access point SoftAP - deoarece managementul comunicației se întâmplă în cadrul sistemului ​de operare, nu în hardware)Configurațiile precum ​''​esp32-wrover-kit:​wifi'' ​permit plăcii să funcționeze doar ca un stationdar există și ''​esp32-devkitc:​sta_softap'', ​de exemplu, care oferă suport atât pentru station cât și pentru SoftAP.
- +
-==== Rulare ==== +
- +
-Pentru rularea unei mașini virtuale cu KVM se folosește comanda ​''​qemu-kvm'' ​împreună cu imaginea pentru hard disk. În acest caz imaginea hard disk-ului trebuie ​să conțină un sistem compatibil cu arhitectura //host//accelerarea oferită de KVM putând fi folosită doar dacă //​guest//​-ul ​și //host//-ul folosesc arhitecturi compatibile (ex: x86_64).+
  
-Pentru ​rularea în //user-mode emulation// poate fi folosit unul din executabilele de forma ''​qemu-<​arch>''​ împreună cu executabilul pe care vrem să-l rulăm [[#​referinte| [5]]]. Bineînțeles,​ acest executabil trebuie să fie compatibil cu arhitectura aleasă, ''​<arch>''​iar momentan QEMU oferă suport pentru //user-mode emulation// ​ doar pe Linux și BSD. Dintre cele două, suportul pentru BSD nu este însă la fel de complet ca cel pentru Linux [[#​referinte| [6]]]+Pentru ​a putea conecta Esp32 la o rețea Wi-Fi existentă identificată prin <myssid>:<​mypasswd>, se pot folosi comenzile ​de mai jos:
  
-<​note>​ 
-Exemplu de rulare in **user-mode emulation**:​ 
 <​code>​ <​code>​
-qemu-arm -cpu <procesor> <executabil>+ifup wlan0 
 +wapi psk wlan0 <mypasswd
 +wapi essid wlan0 <myssid
 +renew wlan0
 </​code>​ </​code>​
-</​note>​ 
  
-Pentru rularea în modul //system emulation// se folosește unul din executabilele de forma ''​qemu-system-<​arch>​'' ​împreună cu imaginea ​pentru ​hard disk [[#​referinte| [7]]].+''​wapi psk'' ​este folosit ​pentru ​a specifica nivelul de securitate minim pe care rețeaua trebuie să îl îndeplinească,​ precum și algoritmul de criptare - în cazul de față, se folosește WPA2 și algoritmul CCMPÎn total, există patru niveluri de securitate, iar în NuttX sunt suportate doar ultimele trei:
  
-<​note>​ +  * WEP 
-Exemplu de rulare in modul **system emulation**: +  WPA 
-<​code>​ +  ​WPA2 (WPA2-PSK) 
-qemu-system-arm -machine <​arhitectura>​ -cpu <​procesor>​ -kernel <​kernel_file>​ -append "​root=/​dev/​sda2"​ -drive file=<​rootfs_file>,​index=0,​media=disk,​format=raw +  ​WPA3 (WPA3-AES)
-</​code>​ +
-</​note>​+
  
-==== Configurare ====+Deoarece ''​wapi essid''​ doar setează intern numele rețelei, pentru conectarea efectivă la rețea și obținerea unei adrese IP este nevoie de o comandă explicită - ''​renew wlan0''​.
  
-În modul mașină virtuală sau //system emulation// QEMU simulează un întreg sistem ​de calcul. În lipsa unor alte argumente se folosește însă o configurație implicită de sistem, care este specifică fiecărei arhitecuri în parte. QEMU poate însă simula o gamă largă de configurații de sistem. În limbajul QEMU acestea se numesc //mașini// și pot fi selectate cu opțiunea ''​-machine''​.+Pentru a putea configura Esp32 să ruleze ca un SoftAP (prin a doua interfață de rețea disponibilă - wlan1), e nevoie ​de un set asemănător de comenzi:
  
-<​note>​ +<​code>​ 
-<​code ​shell Nokia N800 tablet+ifup wlan1 
-qemu-system-arm -machine n800 <disk image>+dhcpd_start wlan1 
 +wapi psk wlan1 <mypasswd
 +wapi essid wlan1 nuttxapp 1
 </​code>​ </​code>​
-</​note>​ 
  
-QEMU oferă însă și un control mai fin asupra configurației sistemului simulat printr-o serie de alte opțiuni, precum [[#​referinte| [8]]]: +Astfel, se creează rețeaua ''​nuttxapp'', ​protejată tot prin WPA2 si CCMPavând parola <​mypasswd>​Prin ''​dhcpd_start'' ​se pornește daemon-ul ''​dhcpd''​ care va rula un server ​de DHCP și va asigna un IP tuturor device-urile conectate.
-  * ''​-cpu''​ - specifică tipul de procesor care va fi emulat +
-  * ''​-m''​ - specifică dimensiunea memoriei RAM +
-  * ''​-hda'', ​''​-hdb''​ etc. - specifică imaginea pentru primul hard diskrespectiv al doilea hard disk, ș.a.m.+
-  * ''​-fda''​, ''​-fdb''​ - specifică imaginea pentru primul floppy disk, respectiv al doilea floppy disk +
-  * ''​-cdrom''​ - specifică imaginea folosită de cdrom +
-  * ''​-serial'',​ ''​-parallel''​ - specifică porturile seriale, respectiv, paralele ​și modul de interacțiune a acestora cu //host//-ul +
-Configurații mai avansate pot fi obținute cu opțiunile ​''​-device'',​ ''​-drive'',​ ''​-net'',​ ''​-soundhw'',​ ''​-bt''​ care adaugă dispozitive periferice, ​de stocare, plăci de rețea ​și de sunet și, respectiv, dispozitive bluetooth [[#​referinte| [8]]]. [[https://​qemu.weilnetz.de/​doc/​4.2/​qemu-doc.html| Documentația]] oferă informații despre toate aceste opțiuni, precum și multe altele.+
  
-altă opțiune utilă este ''​-kernel''​. Aceasta permite specificarea imaginii de kernel folosite de sistemul ​//guest// direct în comanda QEMU. Astfel, QEMU va încărca kernelul dintr-un fișier aflat pe sistemul ​//host// în loc de a-l cauta în imaginea de hard diskAcest lucru poate reduce semnificativ timpul de iterație în momentul dezvoltării unui sistem embedded, deoarece nu mai este necesară recrearea imaginii de hard disk pentru fiecare modificare a kernel-ului.+descriere mai detaliată a API-ului expus prin WAPI (de exemplu, ​''​wapi show wlan0''​), precum și cum te poți conecta la o rețea nesecurizată (open network), poate fi consultată [[https://nuttx.apache.org/docs/latest/applications/wapi/index.html|aici]].
  
-<note important>​ +De asemenea, o altă comandă utilă pentru a investiga starea interfețelor de rețea ​este ''​ifconfig'', ​asemănătoare cu cea din Linux.
-Pe unele sisteme emulate ​este chiar obligatoriu ca opțiunea ​''​-kernel'' ​să fie prezentădeoarece emularea sistemului nu include și un bootloader. Fără un bootloader, sistemul nu știe altfel cum să găsească imaginea de kernel. +
-</​note>​+
  
-De obicei, împreună cu specificarea imaginii de kernel este nevoie să specificăm și linia de comandă a kernel-ului. Pentru aceasta se folosește opțiunea ''​-append''​ împreună cu string-ul care vrem să fie pasat kernel-ului la bootare.+==== Bootloader ====
  
-O ultimă opțiune, folositoare mai ales pentru debugging, o reprezintă redirectarea monitorului către consolă. Acest lucru se face cu opțiunea ''​-monitor stdio''​. Monitorul oferă o interfață în linie de comandă care permite un control interactiv al modului în care se face emularea.+{{ :​si:​laboratoare:​nuttx_bootloader.png?600 |}}
  
-==== Networking ====+Esp32 folosește două bootloadere într-un proces denumit multi-stage boot:
  
-Pentru a emula o interfață de rețea, QEMU se bazează pe două componente: //​device//​-ul prezentat //guest//-ului, configurat cu opțiunea ''​-device''​ sau ''​-net nic'', ​și //​back-end//​-ul ​care leagă acest device de //host//, configurat cu opțiunea ''​-netdev''​Opțiunea ''​-device''​ nu este limitată ​la a emula doar interfețe ​de rețea, ea putând configura orice dispozitiv suportat de către QEMU însă, unele plăci ​de rețea sunt suportate doar de opțiunea ''​-net nic''​.+  * First-stage bootloader se află în memoria ROM și este primul cod care se execută la un reset de placă. Are rolul de a inițializa accesul la memoria flash externă CPU-ului și de a stoca datele venite pe UART în cazul în care flash-uim placa. 
 +  * Second-stage bootloader preia controlul de la first-stage bootloader, citește tabela ​de partiții și începe să ruleze executabilul ​de NuttX.
  
-Pentru //​back-end//​QEMU suporta mai multe moduri, printre care: +Tabela de partiții definește, în mod implicitdouă tipuri ​de partiții:
-  * ''​-netdev user''​ - //​user-mode//,​ rulează ​în user-space și nu necesită privilegiiînsă interacțiunea cu rețeaua //​host//​-ului este complicată +
-  * ''​-netdev tap''​ - //tap//, conectează o interfață TAP a //​host//​-ului la un VLAN emulat, permițând o configurare detaliată a topologiei folosite ​de //guest//, însă configurarea este mai complicată +
-  * ''​-netdev bridge''​ - //​bridge//, ​ conectează o interfață TAP a //​host//​-ului la un bridge, care permite interacțiunea cu rețeaua fizică a //​host//​-ului +
-  * ''​-netdev socket''​ - //socket//, interconectează VLAN-urile a două sisteme emulate folosind TCP sau UDP.+
  
-În mod implicit QEMU emulează un sistem cu o interfață de rețea reprezentată de un //device// specificat de //mașina// selectată, în modul //​user-mode//​Aceasta configurare implicită nu ne oferă însă toată flexibilitatea unui //target// real, conectat la o rețea fizică. Din acest motiv în cadrul laboratorului ne vom folosi de modul //bridge//.+  * app - partiție care conține cod executabil. 
 +  * data - partiție care conține date.
  
-//Bridge//-ul folosit ​de către //back-end// se configurează cu parametrul ''​br=//<​nume bridge>//''​iar //​device//​-ul pentru opțiunea ''​-net nic'' ​se specifică prin parametrul ​''​model=//<​device>//​''​. ​Legatura dintre cele două componente se face prin adăugarea parametrului ''​netdev=//<​id>//''​ la //​device// ​și a parametrului ​''​id=//<​id>//​'' ​la //​back-end//​. Valoarea ''//<​id>//''​ trebuie bineînteles ​să fie identică pentru ca cele două componente ​să fie legate. În final, cele două opțiuni arată astfel: ​''​-net nic,​model=<​device>,​netdev=<​id>​ -netdev bridge,​br=<​nume bridge>,​id=<​id>​''​+Cu ajutorul partiției ''​otadata''​ se implementează procedeul denumit OTA - Over-the-air update. Atunci când second-stage bootloader-ul citește tabela ​de partiții, caută otadata și, bazându-se pe conținutul acesteiaîncepe execuția partiției ​''​ota_1'' ​sau ''​ota_2''​. ​Astfel, presupunând că sistemul folosește ''​ota_1''​, în cazul în care vrem să reflash-uim placa putem să încărcăm noul binar în ''​ota_2'', ​iar mai apoi doar să dăm un resetÎn cazul în care partiția otadata nu există sau nu este inițializatăbootloader-ul foloseste partiția ''​factory'' ​implicită ​de la adresa ​0x10000.
- +
-<​note>​ +
- ​Înainte de realizarea configurațiilor de rețeadezactivați conectarea automată din setările sistemului de operare (Settings -> Network -> Wired -> Connect Automatically (off)) +
-</​note>​ +
- +
-Pentru a crea și configura //​bridge//​-uri se folosește utilitarul **brctl** din pachetul **bridge-utils**. Crearea unui //bridge// care să ofere unui //guest// accesul la rețea fizică a //​host//​-ului se face astfel: +
- +
-<​code>​ +
-sudo brctl addbr virbr0 #​ creăm bridge-ul +
-sudo brctl addif virbr0 <​interfata fizica>​ #​ adăugam interfața fizică a host-ului la bridge +
-sudo ip address flush dev <​interfata fizica>​  ​               # ștergem adresa IP de pe interfața fizică, doar dacă avem o adresă +
-                                                                # IP pe interfațăVa șterge și ruta default automat +
-sudo dhclient virbr0 ​                                           # obținem adresa IP pentru bridge și ruta default prin DHCP +
-</​code>​ +
- +
-Dacă nu merge obținerea adreselor prin DHCPse poate configura manual adresa și ruta default: +
-<​code>​ +
-ip address show #​ notăm ip-ul și prefixul interfeței fizice +
-ip route show #​ notăm ruta implicită +
-sudo brctl addbr virbr0 #​ creăm bridge-ul +
-sudo brctl addif virbr0 <​interfata fizica>​ #​ adaugăm interfața fizică a host-ului ​la bridge +
-sudo ip address del <​ip>/<​prefix>​ dev <​interfata fizica>​ #​ mutăm ​adresa ​interfeței fizice +
-sudo ip address add <​ip>/<​prefix>​ dev virbr0 # pe bridge +
-sudo ip link set dev virbr0 up +
-sudo ip route add default via <​gateway>​ #​ readăugam ruta implicită +
-</​code>​ +
- +
-Pentru ca //​bridge//​-ul să fie acceptat de QEMU el trebuie configurat și în fișierul ''/​etc/​qemu/​bridge.conf''​ sub forma: +
- +
-<code text bridge.conf>​ +
-allow virbr0 +
-</​code>​ +
- +
-===== Exerciții =====+
  
 <note important>​ <note important>​
-Atenție! Pentru rezolvarea laboratorului recomandăm folosirea sistemului ​de operare Ubuntu 22.04. +În funcție de nevoile aplicației, este posibil să încărcăm executabilul direct la adresa 0x1000 în locul bootloader-ului pentru a fi executat direct de first-stage bootloader.
-Puteți descărca o mașina virtuală Ubuntu 22.04 de pe torrent ([[https://​ocw.cs.pub.ro/​courses/​_media/​si/​lab/​si_lab_vm_2022.torrent.zip|.torrent.zip]]) sau o variantă de pe OSBoxes [[https://​www.osboxes.org/​ubuntu/​|osboxes]] și apoi folosiți [[https://​www.vmware.com/​content/​vmware/​vmware-published-sites/​us/​products/​workstation-player/​workstation-player-evaluation.html.html|VmWare Player]] ​pentru a o rula.+
 </​note>​ </​note>​
  
-Imaginea de VM cu Ubuntu 22, oferită de echipa de SI, are ca login user-ul si parola: student/​student.+==== Exerciții ====
  
-Ca sistem de operare embeddedvom folosi distribuția [[https://​raspi.debian.net/​|Debian Bookworm]] compilată pentru [[https://​raspi.debian.net/​tested-images|ARM64]].+Pentru a putea rula exercițiileeste nevoie să compilați NuttX folosind ''​esp32-devkitc:sta_softap'',​ la care va trebui să activați manual alte câteva config-uri:
  
-==== 0. Instalați programele și utilitarele necesare ==== +  * CONFIG_NET_ROUTE=y 
-  * Actualizați lista de pachete ''​sudo apt update''​ +  * CONFIG_NET_IPFORWARD=y 
-  * Instalați ''​git'',​ ''​vim''​ și ''​bridge-utils''​. +  * CONFIG_NET_NAT=y 
-<​code>​ +  * CONFIG_SYSTEM_IPTABLES=y
-sudo apt install git vim wget bridge-utils +
-</​code>​ +
-  * Instalați toolchain-ul necesar pentru a cross-compila programe pentru RaspberryPi 64 biți: +
-<​code>​ +
-sudo apt install gcc-aarch64-linux-gnu +
-</​code>​ +
-  * Instalați QEMU folosind instrucțiunile următoare. +
-<​code>​ +
-sudo apt install qemu-user ​           # Pentru user-mode emulation +
-sudo apt install qemu-system-aarch64 ​ # Pentru system-mode emulation +
-sudo apt install qemu-utils ​          # Pentru utilitare precum qemu-nbd +
-</​code>​+
  
-  ​Descărcați și dezarhivați o imagine de Debian Bookworm pentru Raspberry PI Model 3B+ [[https://​raspi.debian.net/​tested-images/​|de aici]]. +**1.** Conectați Esp32-ul la rețeaua facultății ​și testați cu ''​ping 8.8.8.8''​ că aveți acces la internet. Folosiți interfata ​''​wlan0''​.
- +
-==== 1. Opțiunile Qemu ==== +
- +
-Aflați parametrii pentru opțiunile ''​-machine''​ și ''​-cpu'' ​necesari pentru a emula sistemul nostru.+
  
 <note tip> <note tip>
-  * Re-citiți despre modalitățile de [[#​rulare|rulare]]. +În cazul în care nu reușiți să vă conectați la rețeaua facultății, puteți folosi hotspot-ul de pe telefonul mobilAcest lucru vă va permite să testați atăt conectarea la o rețea nesecurizată,​ căt și la una securizată (prin WPA2). 
-  * Citiți pagina de manual sau [[https://​qemu.weilnetz.de/​doc/​4.2/​qemu-doc.html| documentația]] online pentru cele două opțiuni. +</note
-  * Hint: +
-<​code>​ +
-qemu-system-aarch64 -machine help +
-qemu-system-aarch64 -machine <​platforma>​ -cpu help +
-</​code>​ +
-</​note>​ +
- +
-==== 2User-mode emulation ==== +
- +
-Compilați următorul program **hello world** pentru RaspberryPi și linkați //static//. Aflați setul de instrucțiuni folosit de executabilul generat ​și apoi rulați-l în QEMU folosind //user-mode emulation// și emulând procesorul Cortex-A53. Salvați comanda folosită pentru emulare. +
- +
-<​code>​ +
-#include <​stdio.h>​ +
-int main(void) +
-+
-    printf("​hello world\n"​);​ +
-} +
-</code> +
- +
-  * Utilizaţi compilatorul **aarch64-linux-gnu-gcc**. +
-  * Folosiți pentru compilator flag-ul ''​-static''​ pentru a obține un executabil linkat //​static//​. +
-  * Utilitarul **file** oferă informații despre conținutul fișierelor primite ca argument. +
-  * Bonus: Ce se întâmplă dacă rulați executabilul direct, fără QEMU? De ce?+
  
 <note important>​ <note important>​
-In mod normal executabilul astfel obtinut nu merge rulat si pe sistemul host. +NuttX nu tratează în mod implicit semnalul SIGINTiar în urma rulării ping-ului vi se va bloca consola ​de nsh. Puteți evita această problemă prin activarea CONFIG_TTY_SIGINT.
-In cazul in care merge rulata aplicatia de hello world si in host explicatie pentru care se intampla asta este: qemu instaleaza un handler care permite aceasta translatia directdoar ca acest lucru se intampla selectiv, deoarece nu pe toate sistemele ​de operare este instalat/​configurat similar.+
 </​note>​ </​note>​
  
-<note tip> +Rulați comanda ''​route''​ și inspectați output-ul acesteiaVa fi relevant la exercițiul 3.
-  * Re-citiți despre modalitățile de [[#​rulare|rulare]]. +
-  * Citiți introducerea acestui [[https://​www.kernel.org/​doc/​Documentation/​admin-guide/​binfmt-misc.rst| kernel feature]]. +
-  * Veti afla mai multe despre cross-compilare in [[04| laboratorul 4]]. +
-</​note>​+
  
-==== 3System-mode emulation ====+**2.** Configurați placa să ruleze în modul SoftAP și conectați-vă cu laptopul la rețea pentru a testa. Folosiți interfața ''​wlan1''​. Rulați din nou comanda ''​route''​ și observați cum s-a modificat tabela de routare.
  
-Rulați distribuția Debian folosind QEMU în modul //system emulation//. Veți avea nevoie ​de următoarele argumente pentru emulare.+**3.** În urma exercițiului 2, laptopul este conectat la Esp32, dar nu are acces la internet. Puteți testa acest lucru din CMD (Windows)/terminal (Linux) folosind ''​ping 8.8.8.8''​. Mai departe, urmăriți pașii ​de mai jos:
  
-  ​* **Kernel-ul** de Linux, prin argumentul “-kernel <​kernel_image_file>​”. +  - De pe Esp32 mai rulați o dată comanda ''​ping 8.8.8.8''​. Observați că nu aveți acces la internet. Configurarea wlan1 ca SoftAP a stricat tabela de routareașa cum se poate observa din output-ul comenzii ''​route''​
-  * Imaginea de **InitRD** (Initial RAM Disk), prin argumentul “-initrd <​initrd_file>"​. +  - Setați regula implicită ​de routare folosind comanda ''​addroute default 192.168.0.1 wlan0''​. Esp32 este conectat din nou la internetputețsă testați folosind ''​ping''​
-  * Pentru a funcționa mașina virtuală, este nevoie sa îi pasați emulatorului si un **Device Tree**prin argumentul “-dtb <​device_tree_file>​”+  - Ultimul pas implică adăugarea unei reguli in iptables ​pentru ​a aplica NAT pe fiecare pachet routat de Esp32''​iptables ​-t nat -A POSTROUTING ​-o wlan0 -j MASQUERADE''​. 
-  ​* Modelul mașinii emulate, prin argumentul “-machine”. Consultați documentația Qemu de [[https://​www.qemu.org/​docs/​master/​system/​arm/​raspi.html|aici]] pentru lista componentelor virtualizate (procesormemory, periferice) șalegeți modelul corespunzător pentru Raspberry Pi 3+  ​- Testați de pe laptopul personal folosind pingiar din browser conectați-vă la ''​www.google.com''​.
-  ​* Pentru imaginea discului (rootfs-ul), fom folosi Debian 12 (Bookworm) ​pentru ​[[https://​raspi.debian.net/​tested-images|RPi 3B+]]. Pasați imaginea discului cu argumentul “-sd <​disk_file>​”,​ deoarece vom emula un SD-card +
-  ​* Folosiți string-ul root=/​dev/​mmcblk0p2 pentru linia de comandă a kernel-uluideoarece rootfs-ul este pe a doua partitie a SD card-ului).+
  
-<​code>​ 
-qemu-system-aarch64 \ 
- -machine … \ 
- -kernel … \ 
- -initrd … \ 
- -dtb … \ 
- -sd … \ 
- -append "​console=ttyS1 root=/​dev/​mmcblk0p2 rw rootwait rootfstype=ext4"​ \ 
- -nographic \ 
- -serial null \ 
- -serial stdio \ 
- -monitor none 
-</​code>​ 
- 
-Extrageți imaginea de kernel, dtb-ul si initrd-ul din imaginea de disc de Debian downloadată 
-<​code>​ 
-sudo losetup --show -fP 20220808_raspi_3_bookworm.img ​  # Notați numărul device-ului /dev/loop returnat de comanda losetup 
-sudo mkdir /mnt/debian 
-sudo mount /​dev/​loop16p1 /​mnt/​debian ​    # Înlocuiți valoarea 16 cu valoarea numărului vostru 
-cp /​mnt/​debian/​vmlinuz-5.18.0-3-arm64 . 
-cp /​mnt/​debian/​initrd.img-5.18.0-3-arm64 . 
-cp /​mnt/​debian/​bcm2837-rpi-3-b.dtb . 
-# facem unmount și deconectăm imaginea din dispozitivul bloc 
-sudo umount /mnt/debian 
-sudo losetup -d /dev/loop16 
-</​code>​ 
- 
-Pentru montare, puteți folosi utilitarul qemu-nbd (care, în plus față de losetup, știe să deschidă mai multe formate de mașini virtuale precum vbox și vmdk): 
-<​code>​ 
-sudo modprobe nbd max_part=8 
-sudo qemu-nbd -c /dev/nbd0 220121_raspi_3_bullseye.img 
-sudo mkdir /mnt/debian /​mnt/​debian/​boot 
-sudo mount /dev/nbd0p2 /mnt/debian 
-sudo mount /dev/nbd0p1 /​mnt/​debian/​boot 
-# acum putem explora partiția de boot din imagine 
-ls -l /​mnt/​debian/​boot 
-# facem unmount și deconectăm imaginea din dispozitivul bloc 
-sudo qemu-nbd -d /dev/nbd0 
-</​code>​ 
- 
-Deoarece discul pasat către Qemu este de tip SD card, Qemu așteaptă ca dimensiunea discului să fie o putere a numărului 2 (ex. 512MB, 1024MB). Din acest motiv trebuie să redimensionăm discul, spre exemplu la 4GB. 
-Qemu dispune, de asemenea, de utilitare pentru manipulat imagini (creare / redimensionare / conversie între formate): 
- 
-<​code>​ 
-qemu-img resize 20220808_raspi_3_bookworm.img 4G 
-</​code>​ 
- 
-<note tip> 
-  * Re-citiți despre modalitățile de [[#​rulare|rulare]]. 
-  * Revedeți parametrii de [[#​configurare| configurare]] ai QEMU și citiți pagina de manual sau [[https://​qemu.weilnetz.de/​doc/​4.2/​qemu-doc.html| documentația]] acestora. 
-  * Pentru a inchide mașina virtuală, folosiți, din cadrul ei, comanda ''​sudo halt''​ sau ''​sudo poweroff''​. Dacă doriți să opriți din terminal de pe host, opriti procesul ''​qemu''​ cu ajutorul comenzii ''​killall qemu-system-aarch64''​. 
-  * Dacă întâlniți probleme de rulare qemu, însă acesta se închide prea repede și nu puteți vedea eroarea, folosiți argumentele ''​-no-reboot -no-shutdown''​. 
-</​note>​ 
- 
-==== 4. Instalați serviciul Libvirt ==== 
- 
-Libvirt este un serviciu ce permite folosirea Qemu mult mai ușor. Împreună cu tool-uri precum ''​virsh''​ (virtual shell) sau ''​virt-manager'',​ utilizatorul poate crea, porni, opri, clona sau migra mașini virtuale foarte ușor si rapid. În acest laborator vom folosi tool-ul ''​virt-install''​ pentru a crea o noua mașină virtuală. 
- 
-<​code>​ 
-sudo apt install virtinst 
-</​code>​ 
- 
-folosiți kernel-ul, initrd-ul si imaginea discului de la ex.3 pentru a crea o mașină virtuală: 
- 
-<​code>​ 
-virt-install --name rpi3-qemu-si \ 
- --arch aarch64 \ 
- --machine virt \ 
-       ​ --os-variant debian11 \ 
- --boot kernel=...,​initrd=...,​kernel_args="​console=ttyama0 root=/​dev/​vda2 rw rootwait rootfstype=ext4"​ \ 
- --disk ... \ 
-       ​ --vcpus 2 \ 
- --nographic \ 
-       ​ --feature acpi=off 
-</​code>​ 
- 
-Pentru a ieși din consola virsh, folosiți combinația ''​ctrl + ]''​. Avem la dispoziție următoarele comenzi: 
- 
-  * ''​virsh list --all''​ - listează toate mașinile virtuale 
-  * ''​virsh destroy NUME_VM''​ - opreste o mașină virtuală 
-  * ''​virsh undefine NUME_VM''​ - șterge o mașină virtuală 
-  * ''​virsh shutdown NUME_VM''​ - trimite o comandă de graceful shutdown, similar cu apăsarea butonul de Power 
- 
-Numele ''​destroy''​ poate induce putin în eroare, deoarece mașina este doar oprită și nu ștearsă. 
- 
-==== 5. Schimbați configurația VM-ului (CPU-ul si RAM) ==== 
- 
-Cu mașina virtuală de la ex. 4 oprită, editați configurația cu ajutorul următoarei comenzi și adăugați 8 procesoare si 32GB de RAM: 
- 
-<​code>​ 
-virsh edit NUME_VM 
-</​code>​ 
- 
-În mod implicit, kernel-ul va refuza alocarea de memorie virtuală pentru un process de user-space, mai mult decât are sistemul disponibil. Dar îl putem convinge cu următoarea comanda executată in VM-ul de Ubuntu 22: 
- 
-<​code>​ 
-sudo sysctl vm.overcommit_memory=1 
-</​code>​ 
- 
-Desigur, în momentul în care VM-ul începe să folosească multă memorie, VM-ul (procesul) va fi automat oprit (killed). 
- 
-Porniți mașina virtuală, deschideți consola cu ajutorul comenzii "virsh console NUME_VM"​ și listați noua configurație:​ 
- 
-<​code>​ 
-cat /​proc/​cpuinfo 
-</​code>​ 
- 
-<​code>​ 
-free -m 
-</​code>​ 
- 
-==== 6. Accesul la Internet ==== 
- 
-Configurați și testați accesul //​guest//​-ului la Internet. Salvați comanda folosită pentru emulare. 
- 
-Pentru aceasta, opriți VM-ul din virsh si reluați comanda de la ex. 3. 
- 
-  * Emulați interfața de rețea folosind un ''​USB network adaptor''​ virtual 
-<​code>​ 
- -device usb-net,​netdev=net0 \ 
- -netdev bridge,​br=...,​id=net0 ​ 
-</​code>​ 
- 
-Pentru a avea Internet in interiorul VM-ului, putem urma pașii din secțiunea [[#​networking| configurare a rețelei]] sau putem instala daemon-ul libvirt, care creează in mod automat bridge-ul "​virbr0"​. 
- 
-<​code>​ 
-sudo apt install libvirt-daemon-system 
-</​code>​ 
- 
-Folosiți numele noului bridge pentru adaptorul de retea virtual. 
- 
-După ce pornește mașina virtuală, listați interfețele de rețea si porniți clientul de DHCP: 
- 
-<​code>​ 
-ip addr 
-dhclient enx405400123457 
-</​code>​ 
- 
-<note tip> 
-  * Înainte de realizarea configurațiilor de rețea, dezactivați conectarea automată din setările sistemului de operare (Settings -> Network -> Wired -> Connect Automatically (off)) și puneți placa de rețea a mașinii virtuale Ubuntu in modul de NAT (Devices -> Network -> Network Settings). Dacă folosiți o rețea wired și nu vă merge cu NAT atunci setați pe modul Bridged Adapter. Atenție, NU setați pe modul "NAT Network"​. 
-{{ :​si:​laboratoare:​screenshot_2020-10-12_at_17.47.41.png |Setare rețea}} 
-  * Recitiți secțiunea de [[#​networking| configurare a rețelei]] în QEMU. 
-  * Folosiți ''​sudo''​ pentru rularea ''​qemu-system-arm''​. 
-</​note>​ 
- 
-<note important>​ 
-In cazul in care aveti doar conexiune prin wifi, nu veti putea folosi configuratia cu bridge, ci va fi nevoie sa folositi o interfata de tip tap. Urmariti configuratia descrisa in al 2-lea raspuns de [[https://​superuser.com/​questions/​694929/​wireless-bridge-on-kvm-virtual-machine/​1009881 | aici]]. 
-</​note>​ 
- 
-==== 7. Rulați programul compilat la punctul 2 pe ''​guest''​ ==== 
- 
-<note tip> 
-  * Copiați executabilul folosind utilitarul ''​scp''​ de pe host pe guest. 
-</​note>​ 
- 
-==== 8. BONUS ==== 
- 
-  * SoC-ul de pe Raspberry PI 3B+ oferă suport atât pentru setul de instrucțiuni ARM pe 64-biți (''​aarch64''​) cât și pentru 32-biți (''​armhf''​ - 32 bit, hard float). Ne propunem să testăm compatibilitatea sa pentru aplicațiile pe 32 biți. 
-  * Pentru acesta, instalați toolchain-ul necesar pentru a cross-compila programe de 32-biți pentru Debian Aarch64. Vedeți instrucțiunile de pe [[https://​github.com/​raspberrypi/​tools|acest repository]]. 
-  * Hint: executabilul compilatorului se numește **arm-linux-gnueabihf-gcc**. 
-  * Compilați programul de la ex. 2 și rulați-l pe guest (în qemu). 
 ==== Resurse ==== ==== Resurse ====
-<​hidden>​ +  ​* [[https://nuttx.incubator.apache.org/docs/12.3.0/applications/wapi/index.html| ​WAPI (Wireless API)]] 
-  ​{{:​si:​laboratoare:​qemu_solutii_2021.txt | Solutii laborator }} +  ​[[https://www.lucadentella.it/en/2016/12/22/esp32-4-flash-bootloader-e-freertos/| Esp32 Bootloader]] 
-</​hidden>​ +  ​[[https://eadalabs.com/esp32-nuttx-and-bridged-networking/|Esp32, NuttX and bridged networking]] 
- +
-===== Referințe ===== +
-  - [[http://wiki.qemu.org/Main_Page| QEMU website]] +
-  - [[https://qemu.weilnetz.de/doc/4.2/qemu-doc.html#​IntroductionQEMU man page (Introduction)]] +
-  ​[[https://en.wikibooks.org/​wiki/​QEMU| QEMU Wikibooks page]] +
-  - [[https://en.wikipedia.org/wiki/QEMU| QEMU Wikipedia page]] +
-  - [[https://qemu.weilnetz.de/​doc/​4.2/​qemu-doc.html#​Linux-User-space-emulator| QEMU man page (Linux User space emulator)]] +
-  - [[https://​wiki.freebsd.org/​QemuUserModeToDo| QEMU BSD user-mode status page]] +
-  - [[https://​qemu.weilnetz.de/​doc/​4.2/qemu-doc.html#​ARM-System-emulator| QEMU man page (ARM System emulator)]] +
-  ​[[https://​qemu.weilnetz.de/​doc/​4.2/​qemu-doc.html#​sec_005finvocationQEMU man page (Invocation)]] +
-  ​- [[http://​elinux.org/​RPi_Hardware| RaspberryPi hardware description]] +
-  - [[https://www.techrepublic.com/article/how-to-enable-copy-and-paste-in-virtualbox/|Copy-paste in VirtualBox]] +
  
si/laboratoare/03.1666695475.txt.gz · Last modified: 2022/10/25 13:57 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