Einleitung

In Linux-Systemen gibt es viele Treiber und Peripheriegeräte auf jeder Zielplattform. Wenn wir uns zum Beispiel das VAR-SOM-AM62 von Variscite ansehen, finden wir Dutzende von On-Chip-Peripheriegeräten zusätzlich zu den externen Peripherie-ICs, die auf einem Carrier Board wie der Symphony-Board-Entwicklungsplattform vorhanden sein können, alle mit mehreren Komponenten, die sowohl den Linux-Benutzer- als auch den Kernel-Bereich abdecken.

Bei Variscite stellen wir umfassende Referenzdesigns für alle unsere System on Modules zur Verfügung und daher sind viele Treiber und Peripheriegeräte in unseren Basis-Linux-Distributionen aktiviert. Es kann jedoch sein, dass einige dieser Geräte auf Ihrem Endprodukt nicht vorhanden sind, sodass Sie sie deaktivieren möchten.

Im Folgenden finden Sie eine nicht vollständige Liste der Gründe für die Deaktivierung nicht verwendeter Treiber/Geräte:

  • Sicherheitsgründe
  • Der Treiber oder die Ressource steht in Konflikt mit einer anderen Funktion
  • Das Vorhandensein des Treibers ohne das Gerät führt zu Laufzeitproblemen auf dem System des Kunden.
  • Sie möchten die Größe des Linux-Images verringern

In diesem Blog werden wir untersuchen, wie wir ungenutzte Treiber und Geräte in Linux deaktivieren können. Während die hier vorgestellten Beispiele unser VAR-SOM-AM62 verwenden, können die Methoden auch auf unsere anderen SoM-Familien erweitert werden.

🅘 Dieser Beitrag konzentriert sich auf Geräte, die kernelbasierte Treiber verwende, und nicht auf im Userspace implementierte Gerätetreiber.


Inhaltsverzeichnis:

Kernel-Treiber/Gerätearchitektur

Auch wenn dieser Blog-Beitrag keine ausführliche Erläuterung der Kernel-Interna bieten wird, ist es wichtig, dass wir die grundlegende Linux-Architektur von Treibern und Geräten besprechen. Lassen Sie uns zunächst einige der Begriffe definieren, die in diesem Beitrag verwendet werden:

Gerät: Ein physisches Hardware-Peripheriegerät irgendeiner Art. Dabei kann es sich um ein speicherbelegtes On-Chip-Peripheriegerät (z. B. einen GPIO-Controller) oder um ein externes Hardwaregerät (z. B. einen ADC-IC) oder sogar um ein externes zusammengesetztes Hardwaregerät (z. B. eine PCIe-Grafikkarte) handeln.

Treiber: Software, die zur korrekten Konfiguration und zum Betrieb eines Geräts unter Linux verwendet wird. Dies umfasst oft mehrere Treiber in realen Geräten. Wir werden uns jedoch auf einfache Anwendungsfälle mit einem Treiber konzentrieren.

Da Linux ein monolithischer Kernel ist, führen die Treiber Kernel-Code mit demselben Zugriff auf Ressourcen aus wie anderer Kernel-Code. Die Treiber können im Allgemeinen in zwei Formen auftreten:

Eingebaut: Der Treibercode wird in das Kernel-Image selbst kompiliert und ist somit zur Laufzeit bereits vorhanden.

LKM (Loadable Kernel Module): Der Treibercode wird als separate binäre Objektdatei erstellt, deren Inhalt irgendwann später zur Laufzeit dynamisch in den Kernel geladen wird (Treiber können auch entladen werden).

Das Kernel-Build-System enthält eine Konfigurationsfunktion (in der Regel mit menuconfig), die es uns ermöglicht, Treiber so zu konfigurieren, dass sie entweder in das Kernel-Image eingebaut oder extern als ladbare Module gebaut werden.

🅘 Viele Treiber können als integrierte oder LKMs konfiguriert werden – einige können jedoch nur als das eine oder das andere konfiguriert werden.

Es ist erwähnenswert, dass zusätzlich zur Erstellung von LKMs aus dem Kernel-Quellcode einige Treiber Code außerhalb des Linux-Kernels enthalten, der nicht „hochgestreamt“ wurde und „out of tree“ erstellt wird.

 

VAR-SOM-AM62 System on Module

TI AM625 System on Module

 

Wie Linux Geräte erkennt

Als Nächstes sollten wir besprechen, wie Geräte erkannt und mit dem entsprechenden Treiber „verheiratet“ werden. Das heißt, wir werden die Frage beantworten: „Wie schafft es ein Treiber, mit dem Gerät zu kommunizieren und es schließlich zu konfigurieren und zu steuern?“

Unter Linux wird davon ausgegangen, dass alle Geräte an einer Art von Bus angeschlossen sind. Dieser Bus ist letztlich ein physikalisches Konzept, kann aber im Kernel auch als virtuelles Konzept betrachtet werden. Als solche fallen diese Geräte letztlich in zwei Hauptkategorien:

Auffindbar: Dies sind Geräte, die auf dem Bus, auf dem sie sich befinden, auffindbar sind. Ein gutes Beispiel dafür ist ein USB-Gerät. Das USB-System ist in der Lage, neue Geräte, die an das System angeschlossen werden, automatisch zu „erkennen“ und stellt somit sicher, dass der richtige Treiber ausgewählt wird, um mit dem Gerät zu kommunizieren.

Nicht auffindbar: In Linux befinden sich diese Geräte oft auf dem „Plattformbus“ (und werden „Plattformgeräte“ genannt). Dies ist bei On-Chip-Peripheriegeräten sehr üblich. Zum Beispiel ist ein On-Chip-GPIO-Controller wahrscheinlich nicht auffindbar. Seine Schnittstelle besteht lediglich aus einigen speicherabhängigen Registern und einem Interrupt. Daher muss das Linux-System über seine Existenz informiert werden, und zwar unter welcher Adresse. Die Konfiguration eines solchen Geräts und seines Treibers erfolgt häufig über den Gerätebaum.

Dies ist eine starke Vereinfachung, aber für unsere Zwecke ist es ausreichend, um zu erörtern, wie wir unbenutzte Treiber und Peripheriegeräte deaktivieren.

Deaktivieren von Treibern und Peripheriegeräten

Schließlich können wir besprechen, wie wir Treiber und Peripheriegeräte in unserem Linux-System tatsächlich deaktivieren. Es gibt mehrere Methoden, und die Wahl der einen hängt in der Regel von dem jeweiligen Treiber und dem Ziel ab, das Sie erreichen wollen. Manchmal kann es wünschenswert oder notwendig sein, mehr als eine dieser Methoden anzuwenden.

Deaktivieren von Treibern in der Kernel-Konfiguration

Dies ist wahrscheinlich der einfachste Ansatz von allen und gilt für eingebaute Treiber oder LKMs, deren Quelle im Kernel-Baum liegt. Mit diesem Ansatz können wir den Treiber einfach in der Kernel-Konfiguration deaktivieren und er wird nicht mehr gebaut. Im Artikel Variscite Kernel Konfigurationshandbuch von Variscite haben wir die Kernel-Konfiguration ausführlich besprochen und Ihnen einen vollständigen Leitfaden zu den Schritten gegeben, die zur Durchführung dieser Methode auf unseren SoMs erforderlich sind.

Deaktivieren des automatischen Ladens von LKMs

Das Standardverhalten der Linux-Distributionen von Variscite ist das automatische Laden der installierten Kernel-Module beim Booten. Wenn ein Modul noch installiert ist, kann man es auch deaktivieren, indem man es einfach nicht zur Laufzeit lädt. Unter Linux kann dies mit einer Abfolge von Befehlen wie dem folgenden erreicht werden:

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

Nach dem Neustart sollte das Modul nicht mehr geladen sein.

Deaktivieren des Geräts im Gerätebaum

Bei Plattformgeräten oder anderen Geräten, die über den Gerätebaum konfiguriert werden, können wir oft Änderungen am Gerätebaum vornehmen, um das Gerät zu deaktivieren. Dieser Teil des Artikels setzt eine gewisse Vertrautheit mit Gerätebäumen voraus. Daher sollten Variscite-Kunden unseren Blog-Leitfaden auf Erste Schritte mit Variscite-Gerätebäumen konsultieren, um die grundlegenden Konzepte von Gerätebäumen kennenzulernen, bevor sie sich an Gerätebaummethoden versuchen.

🅘 Denken Sie daran, dass nicht alle Hardware-Geräte Gerätebaumeinträge verwenden.

Es gibt 3 primäre Methoden, die wir vorstellen werden, die verwendet werden können, um Geräte in einem Gerätebaum zu deaktivieren:
Alle folgenden Beispiele verwenden den folgenden Knoten als Beispiel:

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

Methoden

  1. Entfernen Sie die Definition des Gerätebaumknotens:Dies ist in der Regel der einfachste Ansatz:
    --- a/myfile.dts
    +++ b/myfile.dts
    @@ -1,4 +0,0 @@
    -somedevnode: device@a000000 {
    -    compatible = "foo,device";
    -    status = "okay";
    -};
    
  2. Löschen Sie den Knoten mit der Anweisung /delete-node/:Oftmals werden Geräte verwendet, die in eingebundenen dtsi-Dateien definiert wurden. Dies ist zum Beispiel bei Variscite-SOMs häufig der Fall. Wenn der Knoten in einer solchen eingebundenen dtsi-Datei definiert oder aktiviert wurde, können oder wollen Sie die ursprüngliche Definition möglicherweise nicht entfernen.Stattdessen können Sie eine Anweisung wie folgt hinzufügen:
    /delete-node/ somedevnode;

🅘 Bei gelöschten Knoten müssen auch alle Verweise auf sie aus den Eigenschaften anderer Knoten entfernt werden, da sonst der Gerätebaum nicht kompiliert werden kann.

  1. Setzen Sie den Status Eigenschaft auf „deaktiviert“:
    Oftmals ist es wünschenswert, die ursprüngliche Knotendefinition beizubehalten. In diesem Fall können wir einfach den Status Eigenschaft auf „deaktiviert“
    somedevnode: device@a000000 {
        compatible = "foo,device";
        status = "disabled";
    };
    

Deaktivieren des Geräts über sysfs

Eine andere Methode, die für Entwicklungszwecke oft nützlich ist, besteht darin, die Bindung eines Geräts über die sysfs-Schnittstelle aufzuheben. Dies ist häufig für Test- und Entwicklungszwecke hilfreich und kann eine schnelle Methode zum Deaktivieren des Gerätetreibers bieten, nachdem er beim Booten aktiviert wurde.

🅘 Dadurch wird nicht der Treiber entfernt, sondern das Gerät wird lediglich aus der Geräteliste des Treibers gestrichen, sodass seine Hardwareressourcen freigegeben werden.

In diesem Beispiel werden wir den Treiber leds-gpio untersuchen. Auf unserer Symphony-Board-Entwicklungsplattform verwenden wir diesen Treiber, um uns an eine bestehende GPIO-Leitung zu binden, die mit einer externen LED verbunden ist, und nutzen die „Heartbeat“-Funktion des Treibers, um die LED blinken zu lassen.

Wenn wir diesen GPIO vom Userspace aus mit gpioset steuern wollen, können wir das derzeit nicht:

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

Das liegt daran, dass die GPIO-Leitung derzeit vom Treiber leds-gpio beansprucht wird. Wir müssen die Bindung also aufheben. Wir können den Treiber in sysfs suchen und das Gerät finden, das an ihn gebunden ist:

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 diesem Fall lautet die Bus-ID des Geräts gpio-leds. Auf diese Weise können wir die Bindung wie folgt aufheben:

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

Nachdem wir dies getan haben, werden wir feststellen, dass das Gerät im sysfs-Verzeichnis verschwunden ist, der GPIO als unbenutzt aufgelistet ist und wir nun die Leitung nutzen können:

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

🅘 Diese Methode ist ziemlich brachial und kann in komplexeren Situationen zu Problemen führen. Sie ist am besten für Entwicklungszwecke und nicht für die Produktion geeignet.

Deaktivieren von WLAN-/Bluetooth-Modul-Treibern auf Variscite SoMs

Variscites SoMs haben viele optionale Komponenten, und es gibt viele verschiedene Bestellvarianten jedes SoMs, mit verschiedenen Konfigurationen von Komponenten/Geräten, die darauf bestückt sind. Ein Beispiel für ein solches optionales Gerät ist ein WLAN-/Bluetooth-Modul. Unsere Software ist so geschrieben, dass sie problemlos auf verschiedenen SoM-Varianten der gleichen Familie eingesetzt werden kann, aber wir stellen oft fest, dass Kunden den Treiber und seine Schnittstelle vollständig deaktivieren möchten. Anhand einiger der zuvor erläuterten Konzepte werden wir zeigen, wie wir dies mit dem VAR-SOM-AM62 von Variscite durchführen können.

🅘 Der Leitfaden enthält nicht alle Erstellungsschritte, sondern hauptsächlich die erforderlichen Änderungen am Quellcode. Die Erstellung und Integration wurde in den anderen oben vorgestellten Leitfäden gut dokumentiert.

🅘 Die hier vorgestellte Methode ist stark davon abhängig, welches WLAN-Modul verwendet wird. Die hier vorgestellten Konzepte lassen sich jedoch mit einigen Änderungen auf die verschiedenen SoM von Variscite übertragen.

  1. Deaktivieren Sie die Konfiguration für das Treibermodul im Kernel:Wir beginnen mit der Deaktivierung des Treibers für das WLAN-Modul. Im Falle des VAR-SOM-AM62 verwendet das bestückte Modul den Broadcom WLAN-Treiber (CONFIG_BRCMFMAC). Wie unten zu sehen ist, ist dies derzeit auf „M“ für Modul eingestellt:Disabling Wi-Fi/Bluetooth Module Drivers on Variscite SoMs
    Und deshalb entfernen wir esDisabling Wi-Fi/Bluetooth Module Drivers on Variscite SoMsund speichern dann unsere Konfiguration und beenden das Programm.
  2. Entfernen Sie die zugehörigen Gerätebaumeinträge:Als Nächstes sollten wir alle Geräte in unserem Gerätebaum deaktivieren. In diesem Fall deaktivieren wir einfach das gesamte SD-Peripheriegerät, das für die Schnittstelle des WLAN-Moduls verwendet wird:
    --- 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. Deaktivieren Sie abschließend jegliche unterstützende Firmware, Skripte usw. im BSP:Dies hängt davon ab, welche unserer Distros Sie verwenden, für dieses Beispiel konzentrieren wir uns jedoch auf unsere Yocto-Dunfell-Version. In diesem Fall müssen wir einfach die entsprechenden Rezepte entfernen, die normalerweise hinzugefügt werden. Wir können dies in unserem Image-Rezept oder local.conf wie folgt tun:
    MACHINE_ESSENTIAL_EXTRA_RDEPENDS:remove = " \
    	bcm43xx-utils \
    	brcm-patchram-plus \
    	linux-firmware-bcm4339 \
    	linux-firmware-bcm43430 \
    "

Das ist alles! Wir haben den WLAN-Treiber und das Gerät in unserem Entwurf erfolgreich deaktiviert.

Schlussgedanken

Wie wir hier gezeigt haben, kann das Entfernen von Treibern und das Deaktivieren nicht verwendeter Geräte eine wertvolle und recht einfache Übung für Ihr benutzerdefiniertes Design sein. Variscite hat wesentlich dazu beigetragen, diesen und andere Entwicklungsprozesse zu rationalisieren, indem wir unseren Kunden sofort einsatzbereite Referenzhardware und -software zur Verfügung stellen.

Abonnieren Sie den Newsletter von Variscite für weitere technische Artikel, Updates und bevorstehende Webinare.

 

Verwandte Ressourcen

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