Introduzione

Nei sistemi Linux, su qualsiasi piattaforma di destinazione ci sono molti driver e periferiche. Ad esempio, nel VAR-SOM-AM62 di Variscite troviamo decine di periferiche su chip, oltre a quei circuiti integrati che fungono da periferiche esterne talvolta presenti sulla scheda portante, come la piattaforma di sviluppo Symphony-Board, il tutto condito da diverse componenti per l’utente Linux e gli spazi kernel.

In Variscite forniamo modelli di riferimento completi con tutti i nostri System on Modules e quindi ci sono molti driver e periferiche attivati nelle nostre distribuzioni Linux di base. Tuttavia, alcuni di questi dispositivi potrebbero non essere presenti nel prodotto finale, per cui il cliente potrebbe volerli disattivare.

Di seguito un elenco non esaustivo dei motivi per disattivare driver o dispositivi non utilizzati:

  • Motivi di sicurezza
  • Il driver o la risorsa sono in conflitto con un’altra funzione
  • La presenza del driver senza il dispositivo causa problemi di runtime nel sistema del cliente
  • Desiderio di ridurre la dimensione dell’immagine Linux

In questo blog esamineremo come disattivare driver e dispositivi inutilizzati su Linux. Sebbene gli esempi qui presentati utilizzino il nostro VAR-SOM-AM62, i metodi possono essere estesi anche alle altre nostre famiglie SoM.

🅘 Questo post si concentrerà sui dispositivi che utilizzano driver operanti sul kernel e non driver di dispositivo operanti nello spazio utente.


Tabella dei contenuti:

Architettura del driver o dispositivo nel kernel

Sebbene questo post sul blog non fornisca una spiegazione dettagliata e approfondita del funzionamento interno del kernel, è importante esaminare e discutere l’architettura di base di driver e dispositivi su Linux. Iniziamo dandoci la definizione di alcuni dei termini utilizzati in questo post:

dispositivo: una periferica hardware fisica di qualche tipo. Potrebbe trattarsi di una periferica mappata in memoria su chip come un controller GPIO o di un dispositivo hardware non su chip come un circuito integrato ADC, o ancora di un dispositivo hardware composito esterno come una scheda video PCIe.

driver: software utilizzato per configurare e far funzionare correttamente un dispositivo su Linux. Spesso si tratta di più driver nei dispositivi reali, tuttavia ci concentreremo su semplici casi di utilizzo di driver singoli.

Poiché Linux è un kernel monolitico, i driver eseguono il codice del kernel con lo stesso accesso alle risorse degli altri codici analoghi. Pertanto, i driver possono generalmente essere presenti in due forme:

Integrati: il codice del driver viene compilato nell’immagine del kernel stessa ed è quindi già presente durante l’esecuzione.

LKM (Loadable Kernel Module): il codice del driver si presenta come un file oggetto binario separato il cui contenuto viene caricato dinamicamente nel kernel in un momento successivo durante l’esecuzione (questi driver possono anche essere scaricati).

Il sistema interno del kernel contiene una funzione di configurazione (di solito eseguita con menuconfig) che ci consente di configurare i driver, in modo che siano incorporati nell’immagine del kernel od operino esternamente come moduli caricabili.

🅘 Molti driver possono essere configurati come integrati o LKM, ma per alcuni è disponibile solo una di queste due opzioni.

Vale la pena ricordare che, oltre a creare LKM dalla sorgente dell’albero del kernel, alcuni driver contengono del codice esterno al kernel Linux che non vi viene “innestato” e opera esternamente rispetto all’albero.

 

VAR-SOM-AM62 System on Module

TI AM625 System on Module

 

Come Linux rileva i dispositivi

A questo punto, vediamo come i dispositivi vengono rilevati e «accoppiati» con il driver giusto. Risponderemo cioè alla domanda: «Come fa un driver a comunicare e, in definitiva, a configurare e controllare il dispositivo in questione?»

Su Linux, tutti i dispositivi sono considerati come operanti su una sorta di bus. Questo bus è in definitiva un concetto fisico, ma nel kernel può anche essere pensato come un concetto virtuale. Pertanto, questi dispositivi ricadono in definitiva in due categorie principali:

rilevabili: si tratta di dispositivi rilevabili sul bus su cui esistono. Un buon esempio è un dispositivo USB. Il sistema USB è in grado di «rilevare» automaticamente tutti i nuovi dispositivi ad esso collegati e fa in modo che venga selezionato il driver corretto per comunicare con tali dispositivi.

non rilevabili: su Linux, questi dispositivi spesso operano sul «bus piattaforma» (e sono chiamati «dispositivi di piattaforma»). Sono solitamente così le periferiche su chip. Ad esempio, un controller GPIO su chip probabilmente non sarà rilevabile. La sua interfaccia è costituita semplicemente da alcuni registri mappati in memoria e da un interrupt. Pertanto, il sistema Linux deve essere informato della sua esistenza e indirizzo. La configurazione di un tale dispositivo e del relativo driver viene spesso eseguita tramite albero dei dispositivi.

Stiamo semplificando molto, ma è sufficiente per la nostra finalità di disamina della disattivazione di driver e periferiche non utilizzati.

Disattivazione di driver e periferiche

Infine, possiamo vedere come disattivare effettivamente driver e periferiche nel nostro sistema Linux. Esistono diversi metodi e quale scegliere di solito dipende dal driver in questione e da ciò che si sta cercando di fare. A volte potrebbe essere consigliabile o necessario usarne più di uno.

Disattivare il driver nella configurazione del kernel

Questo è probabilmente l’approccio più diretto e si applica ai driver integrati o agli LKM la cui fonte risiede nell’albero del kernel. Con questo approccio, possiamo semplicemente disattivare il driver nella configurazione del kernel, in modo che non sia più operativo. Nell’articolo Guida alla configurazione del kernel Variscite abbiamo sviscerato la configurazione del kernel offrendo una guida completa dei passaggi necessari per usare questo metodo sui nostri SoM.

Disattivare il caricamento automatico degli LKM

Come impostazione predefinita, le distribuzioni Linux di Variscite caricano automaticamente i moduli del kernel installati al momento dell’avvio. Se un modulo è ancora installato, un altro metodo per disattivarlo consiste semplicemente nel non caricarlo in fase di esecuzione. Ciò può essere ottenuto con una sequenza di comandi come i seguenti su Linux:

echo "blacklist module_name" >> /etc/modprobe.d/modulename-config.conf
echo "install module_name /bin/false" >> /etc/modprobe.d/modulename-config.conf
sync

Al riavvio, il modulo non dovrebbe più essere caricato.

Disattivare dispositivo nell’albero dei dispositivi

Nel caso di dispositivi di piattaforma o altri dispositivi configurati tramite l’albero dei dispositivi, spesso possiamo apportare modifiche all’albero dei dispositivi per disattivarli. Questa parte dell’articolo presuppone una certa familiarità con gli alberi dei dispositivi. Si consiglia pertanto ai clienti Variscite di consultare la nostra guida sul blog all’indirizzo Guida introduttiva alla Struttura ad Albero dei Dispositivi Variscite per rivedere i concetti di base dell’albero dei dispositivi prima di provare qualsiasi metodo di questo tipo.

🅘 Si ricorda che non tutti i dispositivi hardware utilizzano le voci dell’albero dei dispositivi

Presenteremo 3 metodi principali che possono essere utilizzati per disattivare i dispositivi su un albero dei dispositivi.
Tutti gli esempi che seguono utilizzeranno il seguente ipotetico nodo:

somedevnode: device@a000000 {
    compatible = "foo,device";
    status = "okay";
};

Metodi

  1. Rimuovere la definizione del dispositivo dal nodo dell’albero.Questo è di solito l’approccio più semplice:
    --- a/myfile.dts
    +++ b/myfile.dts
    @@ -1,4 +0,0 @@
    -somedevnode: device@a000000 {
    -    compatible = "foo,device";
    -    status = "okay";
    -};
    
  2. Eliminare il nodo tramite la direttiva /delete-node/:spesso utilizziamo dispositivi che potrebbero essere stati definiti nei file dtsi inclusi. Ad esempio, questo è spesso il caso dei SoM Variscite. Se il nodo è stato definito o attivato in tale file dtsi incluso, si potrebbe non essere in grado o non voler rimuovere la definizione originale.In alternativa, è possibile aggiungere una direttiva come segue:

🅘 Se si eliminano dei nodi, andranno rimossi anche tutti i riferimenti ai medesimi nelle proprietà degli altri nodi; altrimenti, l’albero dei dispositivi non riuscirà a effettuare la compilazione.

  1. Impostare la proprietà stato su «disattivato»:
    spesso è preferibile mantenere la definizione sul nodo originale. In tal caso, è possibile semplicemente impostare la proprietà stato su «disattivato»
    somedevnode: device@a000000 {
        compatible = "foo,device";
        status = "disabled";
    };
    

Disabilitare il dispositivo tramite sysfs

Un altro metodo che è spesso utile per finalità di sviluppo è quello di scollegare un dispositivo tramite l’interfaccia sysfs. Ciò risulta spesso utile per scopi di test e sviluppo e può essere un metodo rapido per disattivare il driver del dispositivo dopo che è stato attivato all’avvio.

🅘 Questa operazione non rimuove il driver, ma semplicemente rimuove il dispositivo dall’elenco dei dispositivi del driver, liberandone le risorse hardware.

In questo esempio, esamineremo il driver leds-gpio. Sulla nostra piattaforma di sviluppo Symphony-Board, utilizziamo questo driver per collegarci a una linea GPIO esistente collegata a sua volta a un LED esterno e utilizziamo la funzione «Lampeggiare» del driver per far lampeggiare il LED.

Se vogliamo controllare questo GPIO dallo spazio utente usando gpioset, al momento non possiamo farlo:

root@am62x-var-som:~# gpioinfo 3     
gpiochip3 - 8 lines:
        line   0:      unnamed  "Heartbeat"  output   active-low [used]
...

root@am62x-var-som:~# gpioset 3 0=1
gpioset: error setting the GPIO line values: Device or resource busy

Questo perché la linea GPIO è attualmente utilizzata dal driver leds-gpio. Cerchiamo quindi di scollegarlo. Possiamo cercare il driver in sysfs e trovare il dispositivo ad esso associato:

root@am62x-var-som:~# ls /sys/bus/platform/drivers/leds-gpio/ -l
total 0
--w------- 1 root root 4096 Sep 15 14:26 bind
lrwxrwxrwx 1 root root    0 Sep 15 14:26 gpio-leds -> ../../../../devices/platform/gpio-leds
--w------- 1 root root 4096 Sep 13 02:30 uevent
--w------- 1 root root 4096 Sep 15 14:25 unbind

In questo caso, il nome del dispositivo su bus è gpio-leds. Quindi, in questo modo, possiamo scollegarlo come segue:

root@am62x-var-som:~# echo gpio-leds > /sys/bus/platform/drivers/leds-gpio/unbind 

Dopo averlo fatto, scopriremo che il dispositivo è scomparso dalla directory sysfs; il GPIO vi è riportato come “non utilizzato” e ora possiamo utilizzare la linea:

root@am62x-var-som:~# ls /sys/bus/platform/drivers/leds-gpio/ -l
total 0
--w------- 1 root root 4096 Sep 15 14:26 bind
--w------- 1 root root 4096 Sep 13 02:30 uevent
--w------- 1 root root 4096 Sep 15 14:26 unbind
root@am62x-var-som:~# gpioinfo 3
gpiochip3 - 8 lines:
        line   0:      unnamed       unused  output  active-high 
...

root@am62x-var-som:~# gpioset 3 0=1
root@am62x-var-som:~# echo $?
0

🅘 Questo metodo è piuttosto rozzo e può causare problemi in situazioni più complesse. È meglio usarlo in sviluppo piuttosto che in produzione.

Disattivazione dei driver del modulo Wi-Fi/Bluetooth sui SoM Variscite

I SOM di Variscite hanno molti componenti opzionali e ci sono molte diverse varianti in cui si può ordinare ciascun SoM, con diverse configurazioni di componenti e dispositivi. Un esempio di dispositivo opzionale è un modulo Wi-Fi/Bluetooth. Il nostro software è stato scritto in modo da poter essere utilizzato su diverse varianti SoM della stessa famiglia senza problemi, ma spesso scopriamo che i clienti preferiscono disattivare completamente il driver e la sua interfaccia. Utilizzando alcuni dei concetti che abbiamo delineato in precedenza, mostreremo come possiamo eseguire questa operazione sul VAR-SOM-AM62 di Variscite.

🅘 Questa guida non presenta tutti i passaggi operativi, ma principalmente le modifiche alla sorgente necessarie. La messa in opera e integrazione sono state ben illustrate nelle altre guide di cui sopra.

🅘 Il metodo qui presentato dipende molto dal modulo Wi-Fi utilizzato. Tuttavia, i concetti esposti in questa sede possono essere estesi ai vari SoM di Variscite con alcune modifiche.

  1. Disattivare la configurazione per il modulo driver nel kernel:inizieremo disattivando il driver per il modulo Wi-Fi. Nel caso del VAR-SOM-AM62, il modulo utilizza il driver WLAN Broadcom (CONFIG_BRCMFMAC). Come si vede di seguito, scopriamo che esso è attualmente impostato come «M» di modulo:
    Disabling Wi-Fi/Bluetooth Module Drivers on Variscite SoMse quindi lo rimuoviamoDisabling Wi-Fi/Bluetooth Module Drivers on Variscite SoMse poi salviamo la configurazione e usciamo.
  2. Rimuovere le voci correlate dall’albero dei dispositivi:successivamente si dovranno disattivare tutti i dispositivi sul nostro albero dei dispositivi. In questo caso, disattiveremo semplicemente l’intera periferica SD utilizzata per l’interfaccia del modulo Wi-Fi:
    --- a/arch/arm64/boot/dts/ti/k3-am625-var-som-symphony.dts
    +++ b/arch/arm64/boot/dts/ti/k3-am625-var-som-symphony.dts
    @@ -639,3 +639,7 @@ &wkup_uart0 {
            /* WKUP UART0 is used by DM firmware */
            status = "reserved";
     };
    +
    +&sdhci2 {
    +       status = "disabled";
    +};
    
  3. Infine, disabilitare qualsiasi firmware, script, ecc. di supporto nel BSP:questo passaggio cambierà a seconda della nostra distribuzione che si sta utilizzando, ma per questo esempio ci concentreremo sulla nostra Yocto Dunfell. In questo caso, dobbiamo semplicemente rimuovere le relative ricette che normalmente vengono aggiunte. Possiamo farlo nella nostra ricetta immagine o in local.conf come segue:
    MACHINE_ESSENTIAL_EXTRA_RDEPENDS:remove = " \
    	bcm43xx-utils \
    	brcm-patchram-plus \
    	linux-firmware-bcm4339 \
    	linux-firmware-bcm43430 \
    "

Questo è tutto! Abbiamo disattivato correttamente il driver e il dispositivo Wi-Fi nel nostro modello.

Considerazioni finali

Come abbiamo visto, rimuovere i driver e disattivare i dispositivi non utilizzati può essere un’operazione utile e abbastanza semplice da eseguire sul proprio modello personalizzato. Variscite ha contribuito notevolmente a semplificare questo e altri processi di sviluppo fornendo ai suoi clienti hardware e software di riferimento pronti all’uso chiavi in mano.

Iscriviti alla newsletter di Variscite per articoli più tecnici, aggiornamenti e prossimi webinar.

 

Risorse correlate

Webinar: Getting Started with Device Trees on Variscite SOMs
Post sul blog: i.MX Device Tree Pinmux Settings
Post sul blog: Variscite Kernel Configuration Guide
Post sul blog: Creating a Custom Yocto BSP Layer
Post sul blog: Getting Started with Variscite Device Trees