Kext as Kext can oder USB 3.0 ohne USBInjectAll

    • Hilfreich

    Worum geht's hier eigentlich ?
    Das Folgende beschreibt eine Möglichkeit USB 3.0 Anschlüsse ohne USBInjectall zum Laufen zu bekommen.
    Der Sinn dieses Artikels ist allerdings nicht einen Ersatz für USBInjectAll zu schaffen, sondern Hintergrundwissen über Kexte zu vermitteln.
    Für eine vollständige Beschreibung der Funktionsweise, Anwendung und Einsatz von Kexten seien Interessierte an die Apple Dokumentation verwiesen.
    Das beschriebene Verfahren lässt sich auf alle Arten von Treibern anwenden, ob Bluetooth, WiFi oder Grafik.
    Das hier gegebene Beispiel wurde unter High Sierra getestet und sollte genauso unter Sierra funktionieren.


    Kext, ein Kext ?
    Kexte erlaube es einem Programme als wären sie Teil des Kernels ablaufen zu lassen.
    Man kann drei generelle Arten von Kexten unterscheiden, die die eine Routine enthalten die einfach gestartet wird, dann Services, die mit Treibern vergleichbar sind und Bibliotheken, die anderen Kexten Routinen zur Verfügung stellen.
    Uns interessieren besonders die Kexte die Treiberfunktion haben.


    Jeder hat sein Bündel zu tragen
    Ein Kext ist ein Bundle - ein Bündel. Ein Bundle tritt nach aussen hin wie eine Datei auf, ist aber ein Ordner. Beim Doppelclick im Finder öffnet sich der Ordner nicht, sondern macht je nach Art des Bundles etwas anderes.
    Apps sind Bundles und was die bei einem Doppelclick machen, weiß jeder.
    Ein Doppelclick auf ein Kext führt zur Nachfrage, was man denn mit dem Ding machen will, wie bei einem unbekannten Dateityp.
    Allerdings kann man doch in ein Bundle hineinsehen. Im Finder macht man einen Rechtsclick auf das Bundle und über den Menüpunkt "Paketinhalt zeigen" kann man das Bundle wie einen Ordner öffnen und seinen Inhalt sehen und bearbeiten.


    Es endet mit einem .kext
    Kexte sind Bundles also Ordner die mit der Endung .kext enden.
    Wie wir schon festgestellt haben, kann man ein Kext nicht mit einem Doppelclick starten. Stattdessen werden Kexte beim Systemstart geladen, wenn sie in einem der folgenden Ordner liegen:

    • /System/Library/Extensions
    • /Library/Extensions

    Es genügt aber nicht, dass das Kext in einem dieser Ordner liegt, es muss auch

    • als Eigentümer "root"
    • als Gruppe "wheel"
    • und die Rechte 755 haben.

    Wenn man ein Kext mit einem Hilfsprogramm wie Kext Utility installiert werden die drei Dinge automatisch angepasst. Kopiert man das Kext händisch muss man selbst Sorge dafür tragen, dass sie angepasst werden.


    Verwendet man Clover kann man Kexte beim Systemstart laden, indem man sie in den EFI/CLOVER/kexts/Other Ordner auf der EFI-Partition legt.
    Clover sind Eigentümer, Gruppe und Rechte egal, deshalb genügt das Kopieren des Kextes in den Ordner.


    Form ohne Inhalt ist nichts.
    Wie gesagt ein Kext ist ein Bundle ist ein Ordner.
    Der Inhalt eines Kextes ist in gewissem Rahmen vorgeschrieben.
    Der eigentliche Inhalt kann direkt im Kext(dem Ordner) liegen. Häufig befindet sich aber im Kext ein Unterordner Contents, der dann den eigentlichen Inhalt enthält.
    Ob man einen Contents Ordner zwischen schaltet oder nicht, bleibt jedem selbst überlassen.
    Beide Varianten sind gleichwertig.

    • Das Kext muss eine Datei Info.plist enthalten.
    • Wenn das Kext ausführbaren Code enthält liegt er im Unter-Ordner MacOS.
    • Wenn ein Kext Unter-Kexte hat, liegen diese im Unter-Ordner PlugIns.
    • Wenn ein Kext signiert ist, liegt die zugehörige Datei im UnterOrdner _CodeSignature. Über SIP kann man die Signatur Überprüfung abschalten. um nicht signierte oder Kexte mit falscher Signatur (weil man was am Kext geändert hat).


    Legt man die Sachen in anderen Ordnern ab, findet macos sie einfach nicht.
    Das Kext kann weitere Dateien und Ordner enthalten.


    Ein schöner Vertreter seiner Art
    Schauen wir uns doch mal ein Kext an.



    IOUSBHostFamily verwendet einen Contents Ordner.
    In dem gibt es die oben angeführten Dinge plus version.plist.
    Die version.plist hat zusätzliche Versionsinformationen und ist für die Funktion nicht interessant.
    Alleine anhand der Namen kann man schon ein paar Rückschlüsse ziehen

    • IO: Ein- Ausgabe
    • USB: betrifft USB :)
    • Host: keine Endgeräte, sondern die, die den Bus kontrollieren.
    • Familiy: Gilt für eine ganze Reihe von Geräten.

    Die allgemeine Funktionalität wird von IOUSBHostFamily zur Verfügung gestellt, aber es gibt PlugIns, die die Details für bestimmte Controller oder Controller Arten abhandeln.
    Auch bei den Plugins helfen die Namen weiter.
    AppleUSB*HCIPCI sind

    • Apple eigene Treiber
    • für USB Controller
    • der Typen OHCI, UHCI, XHCI, EHCI,
    • die am PCI Bus angeschlossen sind.

    Ein stolzer Spross der Familie
    Wir interessieren uns für USB 3.0 d.h. XHCI Controller. Die Controller sind über PCI angeschlossen.
    Schauen wir uns also das AppleUSBXHCIPCI.kext an.


    Es zeigt sich ein inzwischen vertrautes Bild:


    _CodeSignature enthält die Signatur, kümmert uns nicht.
    MacOS enthält die Datei mit der Software, da reinzuschauen und zu analysieren was passiert, führt viel zu weit. Uns genügt es zu wissen, dass, da die Datei AppleUSBXHCIPCI in MacOS liegt, das Kext eigenen Programmcode enthält.
    version.plist ist wie gesagt nur Versionsinformation
    Und das lässt nur noch die Info.plist übrig.


    Informationen sind heutzutage Alles
    Die Info.plist ist an jedem Kext das Interessanteste.
    Eine plist ist eine Datei, die eine Liste von Eigenschaften enthält, eine Property List halt. PLists haben ein festes Format, so wie Word Files auch.
    Eine PList ist ein XML Dokument und es gibt auch eine DTD dazu.
    Man kann eine PList mit einem Text Editor oder einem XML Editor bearbeiten.
    XCode enthält auch einen PList Editor, der das Bearbeiten etwas komfortabler als mit einem Texteditor macht.
    XCode ist jedem zugänglich, also verwende ich im Folgenden dessen PList Editor, denn seine Darstellung ist übersichtlicher als die im Texteditor und er kümmert sich um die Datenstruktur, So werden Fehler bei Änderungen vermieden.


    Die Darstellung ist vergleichbar mit der Listendarstellung im Finder. Statt Dateien haben wir Einträge der Datentypen Bool, Data, Date, Number oder String. Statt Ordner haben wir Container in Form von Dictionary oder Array.


    Wie man Einträge ändert, löscht und hinzufügt, bitte ich, falls es sih einem nicht von selbst erschließt, im Netz zu recherchieren.


    So sieht die Info.plist von AppleUSBXHCIPCI.kext aus

    IOKitPersonalities ist mit Absicht nicht aufgeklappt, denn es ist ellenlang und ich möchte erst über die anderen Dinge sprechen.
    Viele Einträge dienen nur der Information des Lesers, aber einige sind für die Funktion essentiell.


    Wenn ein Kext geladen wird, startet es nicht automatisch. Es wird erstmal im Kernel mit einem Namen versehen abgelegt.
    Diesen Namen findet man unter "Bundle identifier". Es kommt vor, dass man sich auf ein anderes Kext bezieht, dann braucht man diesen Namen.
    Wir haben gesehen, dass dieses Kext Programmcode enthält (Datei im MacOS Ordner). Der Dateiname wird unter "Executable file" eingetragen. Macos sucht im MacOs Ordner des Kextes nach der Datei,
    "OSBundleRequired" gibt an wozu das Kext gebraucht wird. Das ist in den meisten Fällen "Root". Kexte für Netzwerkfunktionen haben oft "Network-Root" und Kexte, die auch im abgesicherten Modus geladen werden sollen "Safe Boot".
    Das Kext kann Bibliotheken benötigen. Welche es benötigt und deren Version steht unter "OSBundleLibraries". Sollte das System keine kompatiblen Bibliotheken finden, startet das Kext nicht.


    Starke Persönlichkeiten oder gespaltene Persönlichkeit ?
    Und jetzt wird es spannend IOKitPersonalities.
    Wenn es diesen Eintrag gibt, liegt ein Kext mit Service (Treiber) Funktion vor.


    Gibt es einen solchen Eintrag, so enthält er einen oder mehrere Einträge für Services, die gestartet werden können.
    Jeder Eintrag enthält Bedingungen, die erfüllt sein müssen damit der Service gestartet wird. Dabei sind die Services voneinander unabhängig, es sein denn man macht einen explizit von einem anderen abhängig.
    Dieser Überprüfung findet zu bestimmten Zeitpunkten bzw. bei bestimmten Ereignissen statt. D.h. auch wenn ein Service nicht gleich gestartet wird, so kann er noch später, sobald alle Bedingungen erfüllt sind, gestartet werden.


    Schauen wir uns solch einen Eintrag an:

    Von diesen Einträgen sind zwei Startbedingungen.
    Die erste ist "IOProviderClass". Dort wird der Name eines Services angegeben. Wird solch ein Service gestartet, dann ist es das Startsignal, dass die Überprüfung losgeht.
    In diesem Fall heißt der Service IOPCIDevice. Für jedes PCI Gerät wird solch ein Service gestartet. Damit ist schon mal klar, dass sich der Service um den es hier geht um ein PCI Gerät kümmert.


    Welches Schweinderl hätten sie denn gerne ?
    Aber welches ?
    "IOPCIClassMatch" gibt an, welcher Geräteklasse, das Gerät angehören muss, damit der Service in Frage kommt. In diesem Falle 0x0c033000. In der PCIe Spezifikation sind die Klassen und ihre Werte beschrieben.

    • 0C Serielles Gerät
    • 03 USB
    • 30 XHCI

    In diesem Fall gibt es keine weiteren Bedingungen.
    Der Service ist also zuständig für alle PCI Geräte mit der Klasse XHCI Controller.
    Der Programmcode des Service steht im Bundle "CFBundleIdentifier" in diesem Falle "com.apple.driver.usb.AppleUSBXHCIPCI".
    Ein kurzer Blick nach oben zeigt und, dass das das Kext selbst ist.
    Der Programmcode kann mehr als einen Service enthalten. "IOClass" gibt an welcher verwendet werden soll. In diesem Fall "AppleUSBXHCIPCI".
    "IOPCIPauseCompatible" und "IOPCITunnelCompatible" haben mit dem Teilen von PCI Kanälen bzw. dem Anschluss über Thunderbolt zu tun und interessieren uns hier nicht.


    Eins geht noch
    Ein zweites Beispiel



    Die Überprüfung beginnt natürlich ebenfalls mit dem Finden eines PCI Gerätes "IOProviderClass".
    Doch diesmal haben wir kein IOPCIClassMatch. Statt dessen haben wir ein IOPCIPrimaryMatch. PCI Geräte haben eine Primary und eine Secondary Id.
    Sie bestehen jeweils aus einer Produkt- und einer Hersteller-Id. Beides sind 16bit Hex Werte, die Produkt Id kommt zuerst.
    Also der Service kommt in Frage, wenn ein Gerät mit der Produkt-Id 0x9c31 und der Hersteller-Id 0x8086 (steht für Intel) gefunden wird.
    Der ProgrammCode befindet sich in diesem Kext und heißt AppleUSBXHCILPT.
    Man kann davon ausgehen dass auch dieses Gerät der PCI Klasse XHCI Controller angehört.


    Es kann nur einen geben
    Woher weiß das System nun welchen Treiber es nehmen soll, diesen oder den den wir uns vorher angeschaut haben ?
    "IOProbeScore" hilft an der Stelle. Es wird der Treiber mit dem höheren IOProbeScore genommen.
    Wird also ein Device mit der Primary-Id 0x9c318086 gefunden so hat der Service AppleUSBXHCILPT ein IOProbeScore von 1000, AppleUSBXHCI einen IOProbeScore von 0 (kein Eintrag bedeutet 0).
    Also wird in dem Fall AppleUSBXHCILPT verwendet. Bei XHCI Geräten mit anderen Primary Ids kommt der Eintrag nicht in Frage, aber AppleUSBXHCI ist für diese immer noch ein Kandidat.


    Soviel hierzu
    Und schon haben wir die erste Gruppe von IOKitPersonalities analysiert


    All diese Einträge stellen Treiber für verschiedene XHCI Controller zur Verfügung.
    Es gibt Treiber für bestimmte Controller und einen generischen Treiber für die Controller, für die es keinen besonderen Eintrag gibt.
    Alle Treiber basieren auf dem AppleUSBXHCI Treiber, sie sind Subklassen von AppleUSBXHCI dem generischen Treiber.


    Wenn wir nun ein Board mit einem macos nicht bekannten XHCI Controller verwenden würden, würde macos den generischen Treiber verwenden, solange der Controller zur PCI-XHCI-Klasse gehört - wovon auszugehen ist.
    Das ist ne tolle Sache, wenn der generische Treiber mit dem Controller funktioniert.
    Nun kann es aber sein, dass es nicht der Fall ist. In diesem Fall könnte man einen neuen Eintrag für diesen Controller anlegen, als IOPrimaryMatch dessen Id eintragen und dann als IOClass alle von den anderen verwendeten Treiber durchprobieren bis man einen findet der funktioniert.
    Später dazu mehr.


    Einen hab ich noch
    In den IOKitPersonalities dieses Kextes gibt es noch eine zweite Art von Einträgen:


    Anhand der Namen kann man darauf schliessen, dass sie dazu dienen Anpassungen in Abhängigkeit vom vorliegenden Rechner durchzuführen.
    In diesem Fall dienen sie dazu dem Treiber mitzuteilen, welche Ports des Controllers bei diesem Computer verwendet werden.


    Wann geht's los ?
    "IOProviderClass" zeigt uns "AppleUSBXHCIPCI". D.h. wird ein Service dieses Namens oder eine Subklasse davon geladen, dann startet die Überprüfung.
    Wir müssen nicht mal raten, wann dies der Fall ist. Wir wissen, dass AppleUSBXHCIPCI oder eine seiner Subklassen gestartet wird, wenn ein Treiber für einen XHCI Controller gefunden wird.


    Und sonst ?
    "IONameMatch" ist der Name dec PCI Gerätes. Damit der Test erfolgreich ist muss der Name "XHC1" sein.
    Das genügt noch nicht das "model" muss vom Typ "iMac17,1" sein.
    Also dieser Service wird gestartet, wenn ein XHCI Treiber geladen wurde, das PCIGerät XHC1 heißt und der Rechner ein iMac17,1 ist.
    Der Service der gestartet wird befindet sich nicht in diesem Kext, denn der "CFBundleIdentifier" ist "com.apple.driver.AppleUSBMergeNub". Wo das Kext tatsächlich steht ist egal, denn alle Kexte wurden ja schon geladen und mit ihrem Bundle-identifier gespeichert.
    Der Service heißt laut "IOClass" Eintrag "AppleUSBMergeNub".
    Merge bedeutet zusammenführen. Da werden wohl Eigenschaften zusammengeführt. D.h. dem USB Treiber (XHCI Controller sind USB Controller) werden Parameter übergeben.
    Der Name "IOProviderMergeProperties" ist ein deutlicher Hinweis, dass es sich hier um die Parameter handelt.


    Wie man sieht, sieht man bei Data nichts. Das liegt daran, dass der PList Editor versucht die Daten als Text anzuzeigen, es aber gar kein Text ist.
    Ein Rechtsclick auf das Fenster und Show Raw Keys/Values angewählt ändert das



    Das kenn ich doch
    Wer sich mit USB und DSDT/SSDT beschäftigt hat, dem kommt das sehr vertraut vor.
    port-count ist die höchste verwendete Port Id.
    Die Ports werden meist einfach durchnummeriert die HS Ports beginnen bei 1, die SS Ports bei 17. 17 macht Sinn, wenn man Hexadezimal denkt, denn dann ist es 0x11.
    Wenn 0x1a, siehe port-count, die höchste verwendete Port Id ist, müssten wir einen SSP10 Eintrag haben. Haben wir aber nicht. Vermutlich hat der Programmierer einfach den höchsten bei diesem Controller möglichen Wert genommen - so ein Faultier.


    HS02 ist der Name unter dem das Port verwaltet wird. Typischerweise HS für High Speed und SS oder SSP für Super Speed Port.
    Unter "USB Connector" wird die Anschlussart angegeben. Damit ist der Stecker bzw. die Buchse gemeint mit dem/der der Port verbunden ist.

    • 0 ist die normale USB2.0 Typ A Buchse - die breite Flache in Schwarz. Nur HS.
    • 3 ist die normale USB3.0 Typ A Buchse - die breite Flache in Blau. SS und HS.
    • 9 ist USB-C mit HS und SS.
    • 255 ist ein unbekannter oder eigener Stecker. MoBo Header fallen in diese Rubrik.

    HS02 liegt also an einer USB3.0 Buchse und die Port Id ist 0x02. Das ist der zweite SS Port am Controller - deshalb auch HS02.


    Das Kext für EHCI is genauso organisiert. Dort gibt es keinen Eintrag für iMac17,1, denn der iMac17,1 hat nur einen XHCI Controller und keinen EHCI Controller.


    Wird ein PCI Gerät erkannt, checkt das Kext ob es sich um einen XHCI Controller handelt und wenn dem so ist, lädt es einen Treiber.
    Wenn es danach einen passenden Eintrag für Rechner und Gerätenamen findet, wählt es die dazu passenden Ports aus und teilt sie dem Treiber mit, findet es keinen Eintrag, verwendet der Treiber die ersten 15 Ports des Controllers.


    Das Problem bei einem Hack ist, dass die Ports meist nicht die sind, die man gerne hätte. Sollte man mit einem Board ein SMBIOS verwenden, das eine Controllerart die das Board hat nicht verwendet, werden die ersten 15 Ports davon eingetragen, was u.U. nicht hilfreich ist.


    Und was hilft mir das ?
    Das sehen wir morgen im nächsten Beitrag.

    4 Mal editiert, zuletzt von Brumbaer ()

  • Respekt für diesen Beitrag! einfach nur top!!!

    Mit freundlichen grüssen KayKun

  • Das ist viel zu viel Wissen auf ein mal für mein Hirn.
    Klasse Job! :)

  • Erst mal Danke für diesen Beitrag. :thumbup:
    Ich persönlich habe es zwar (alles) gelesen, bin aber ziemlich schnell ausgestiegen, entweder liegt es an der Tageszeit oder an meinen geistigen Fähigkeiten.

  • Es ist immer wieder eine Freude deine Beiträge zu lesen...
    Zum einen super informativ und fundiert, zum anderen ein Intellektueller Leckerbissen, bei dem man mit Lesen gar nicht aufhören mag... :D


    vielen Dank für den tollen Beitrag... :thumbup:

    Gruß
    Al6042

    Keine Unterstützung per PN oder Pinnwand... Eure Anfragen gehören ins Forum, nicht in mein Postfach!

  • Vielen Dank für diesen - mal wieder großartigen - Post. Mir geht es ein bisschen wie dem Hackfan, aber ich hoffe, nach dem dritten oder vierten Lesen kommt etwas Licht ins Dunkel... ;)

    iMac19,2: Asus B85M-E, Xeon E3-1230 v3, Sapphire Radeon RX580 8GB, 16GB RAM, Clover 5156, macOS 13.6.4

    MacBookPro11,4: Lenovo Thinkpad W541, i5-4340M, intel HD4600 (+nVidia deaktiviert), 16 GB Ram, Whitelist-BIOS-Mod, Clover, macOS 10.14.6, Windows 10

  • Ran ans Eingemachte.
    Dann wenden wir das Gelernte mal an.


    Ich habe hier ein Asus Strix Z270i Gaming Board.
    Es wird als iMac18,3 betrieben, wegen Kaby Lake und so.


    Ziel ist: Keine Änderungen an der DSDT, kein USB InjectAll.
    USB 2.0 Ports funktionieren, deshalb kann man mit einem USB 2.0 Stick (oder einem USB 3.0 Stick an einem USB2.0 Anschluss oder hinter einem USB 2.0 Hub) macos installieren.


    Wenn ich nur wüsst was drinnen ist.
    Wenn man etwas über Geräte und Services wissen will, hilft IORegistryExplorer weiter.


    Wenn man IORegistryExplorer startet, sieht man die IOService (Plane). Das ist eine Auflistung der installierten Services.
    Da Services häufig an Geräte gebunden sind, sieht es auf den ersten Blick wie eine Auflistung der Geräte aus.
    Man kann sich auch die IOACPIPlane anzeigen lassen. Die zeigt uns dann die Geräte an, wie sie in der DSDT/SSDT verzeichnet sind.


    XHCI Controller werden in der DSDT für gewöhnlich XHC nix oder irgendwas benannt. Gott sei Dank, sonst ging die Sucherei jedes Mal aufs Neue los.
    Die Services verwenden ebenfalls den Namen aus der DSDT/SSDT und somit heißen die auch irgendwas mit XHC.


    Auf der rechten Seite sehen wir, dass die DSDT ein Gerät namens XHC hat, das hat einen RHUB und dann 26 Ports.
    Auf der linken Seite sehen wir keinen RHUB und nur 15 Ports.
    Von der Problematik mit den 15 Ports hat jeder schon gehört. Es werden, wenn wie nicht im ersten Artikel beschrieben, die Ports explizit ausgewählt werden, die ersten 15 mit Services versehen.
    Ein Blick auf die rechte Seite zeigt uns das sind HS01-HS14 und SS01 und tatsächlich genau diese Ports tauchen auf der linken Seite auf.
    Der RHUB taucht auf der linken Seite nicht auf. USB Controller haben interne HUBs an denen die Ports angeschlossen sind.
    Das ist sinngemäß ein eigenes Gerät bzw. eine eigene Funktionalität, aber Treiber-/Service-seitig ist dessen Behandlung Teil des XHC Treibers. Deshalb sieht man ihn auf der ACPI aber nicht auf der Service Seite.
    Auf der rechten Seite sieht man hinter jedem Ports die Portnummer.
    Auf der rechten Seite sieht man die erwarteten Ports plus USR1 und USR2.
    Was sind USR1 und USR2.
    Der Controller nummeriert die Ports durch.
    Port 0x00 ist der Hub !!!!!!!!!
    Port 0x01 bist Port 0x0E sind HS01 bis HS14
    Port 0x11 bist Port 0x1A sind SS01 bis SS10.
    Dem Ordnungsfanatiker fällt auf dass da eine Lücke ist, 0x0F und 0x10 sind nicht belegt.
    0x0F ist nicht belegt, weil es nur 14 HS Ports gibt und 0x10 ist nicht belegt, da es der HUB für die SS Ports wäre.
    Damit die Portnummern aber nicht frei sind und man beim "Durchzählen" nicht auf "Nichts" trifft, werden sie mit zwei Dummy-Ports belegt.


    Was soll mir das sagen ?
    Was wir anhand dieser Daten sagen können ist:
    Der Gerätename des XHCI Controllers ist XHC.
    Die Portnummern sind 0x01 bis 0x0E für HS Ports und 0x11 bis 0x1A für SS Ports.
    Es wird ein Treiber für den Controller geladen, sonst würden die Ports nicht in der Service Plane auftauchen.
    Es gibt keinen Eintrag in AppleUSBXHCIPCI für diese Mactyp/Gerätename Version, sonst wären nicht die ersten 15 Ports in der Service Liste, sondern die die der Original Mac hat.
    HS02,5,7,9 und 11 haben Dreiecke, das heißt die Ports sind in Benutzung. Diese Ports werden auf jeden Fall von meinem Computer benutzt.
    "Entfaltet" man das Port, sieht man welcher Service/Gerät an dem Port aktiv ist. Dann weiss man auch schon welche Buchse am Computer mit diesem Port verbunden ist.
    Wir können sehen, dass Port HS11 mit dem internen BT Adapter verbunden ist.


    Sonst noch was ?
    Auf der linken Seite sehen wir zwei Einträge für XHC, also zwei Services. Warum ?
    Bei unseren gestrigen Betrachtungen haben wir gesehen, dass der XHCI Treiber in Abhängigkeit von einem PCIDevice Treiber gestartet wird.
    Da der PCIDevice Treiber zuerst "da war" steht es oberhalb des XHCI Treibers. Beide heißen XHC, weil das Gerät laut DSDT/SSDT XHC heißt.


    Auf der rechten Seite sehen wir, dass der Treiber AppleUSBXHCIPCI ist und dass er aufgrund von IOPCIClassMatch geladen wurde.
    Erinnern wir uns, das ist der Notfall-Treiber, wenn es keinen Controller-eigenen Treiber gibt.
    Auf der linken Seite Finden wir den class-code, vendor-id und device-id(Produkt-Id). Das sind die Rohdaten aus den Controllerregistern, deshalb sind die Werte etwas verdreht.
    Unter name finden wir eine lesbarere Form. 0x8086 steht für Intel und 0xa2af ist die device-id des XHCI Controllers des Z270 Chipsatzes.


    Geradlinig ist anders
    Voll interessant - na ja vielleicht nicht - aber wir werden es später brauchen.


    AHDS ?
    Treiber wird geladen, Ports sind da, nur nicht genug, meine Aufmerksamkeitsspanne ist am Ende, l. mich.
    Na ja wenn das so ist, den USB-Port-Anzahlveränderungs-Patch rein und weiter bei "Was will man mehr ?".



    Tja, die Aufgabe ohne Patch ist bei obiger Lösung nicht erfüllt. Außerdem ist mir der Patch suspekt. Also die Ports auf 15 begrenzen.


    Port sucht Buchse
    Dazu müssen wir herausfinden welche Ports auf Buchsen oder Header geführt sind.
    Ein paar Ports haben wir schon gefunden, nämlich die die in der Service Plane mit einem Dreieck markiert waren.
    Jetzt stecken wir nacheinander in alle anderen Ports ein USB 2.0 Gerät oder Hub und schauen bei welchem Port dann ein Dreieck erscheint.


    Die Anschlüsse sind

    • HS01 intern USB 3.0
    • HS02 intern USB 3.0
    • HS03 hinten außen rechts USB 3.0
    • HS04 hinten außen rechts USB 3.0
    • HS05 hinten außen links USB 3.0
    • HS07 hinten Mitte USB 2.0 only
    • HS08 hinten Mitte USB 2.0 only
    • HS09 hinten Mitte USB 2.0 only
    • HS10 hinten Mitte USB 2.0 only
    • HS11 intern BCM Bluetooth Module


    Das sind schon mal 10 HS Ports. Davon sind 5 Ports an USB 3.0 Buchsen geführt. Diese haben jedes zusätzlich noch ein SS Port. Macht zusammen 15. Wenn das kein Wink des Schicksals ist.


    Die Frage ist wie bekommen wir raus welche SS Ports an den Buchsen/Headern liegen. Na ja wir tragen die ersten 5 ein und schauen welche Verbindung haben. Werfen die anderen raus probieren wieder mit dem nächsten Satz Ports.
    Oder aber wir schauen in die Dokumentation und graben in der Erfahrungskiste.
    Die Erfahrung sagt uns, das Asus gerne SS und HS Ports mit der selben Nummer an die selbe Buchse legt.
    D.h. das wären dann SS01 bis SS05, weil HS01 bis HS05 an den USB 3.0 Buchsen/Header anliegen.
    Asus benennt in seinen Handbüchern die Stecker/Buchsen nach den Port Nummern. USB3_12 Ist ein USB3.0 Header an dem SS01 und SS02 anliegen.
    Ein kurzer Blick ins Handbuch bestätigt unsere Vermutung bezüglich SS01 bis SS05


    Die komplette Port-/Buchsenliste sieht also so aus:

    • SS01, HS01 intern USB 3.0
    • SS02, HS02 intern USB 3.0
    • SS03, HS03 hinten außen rechts USB 3.0
    • SS04, HS04 hinten außen rechts USB 3.0
    • SS05, HS05 hinten außen links USB 3.0
    • HS07 hinten mitte USB 2.0 only
    • HS08 hinten mitte USB 2.0 only
    • HS09 hinten mitte USB 2.0 only
    • HS10 hinten mitte USB 2.0 only
    • HS11 intern BCM Bluetooth Module


    Ein Blick zurück ohne Zorn
    In der AppleUSBXHCIPCI wurden dem Treiber die Ports mit Hilfe von AppleUSBMergeNub und einer Parameterliste zugewiesen.
    Es wird also ein Service aus einem Kext heraus gestartet. Der Service muss nicht im selben Kext stehen, denn AppleUSBMergeNub ist ja nicht Teil des AppleUSBXHCIPCI.

    Also können wir ein Kext erzeugen, das AppleUSBMergeNub startet und dem Treiber unsere Portliste übergibt. Wir müssen nichts patchen oder verändern, wir fügen einfach nur ein neues Kext hinzu.


    Es ist ein Kext
    Wir legen einen Ordner an, der unser Kext sein wird.
    Der Ordner bekommt den schönen Namen BBStrixUSB.kext oder was auch immer ihr sonst bevorzugt. Hauptsache der Suffix ist kext.
    Das Icon im Finder wird mit dem Umbenennen zum Kext Icon wechseln.
    Ein Rechtclick auf das Icon und "Paketinhalt zeigen" öffnet den Ordner.
    Wir werden keinen Contents Ordner verwenden und so legen wir auch keinen an.
    Nun erzeugen wir die Info.plist Datei.
    XCode hat unter New -> File eine Vorlage für Property Lists. Diese erstellt eine leere PList.
    Es ist wichtig die Datei Info.plist zu nennen sonst funktioniert das Kext nicht. Außerdem schaltet der Name Info.plist im PList Editor PopUps für die Feldnamen frei. Wählt man den Feldnamen, wird auch der Datentyp gleich passend gewählt - praktisch.
    Man kann nun die benötigten Felder hinzufügen. Man kann natürlich auch eine vorhandene Info.plist kopieren und rauswerfen, was man nicht braucht und editieren was nötig ist.
    Wir fangen mit den allgemeinen Kext Feldern an.


    Weniger geht nicht, oder ?
    Das sieht im PList Editor so aus


    Ich will nicht ausschließen, dass Clover auf ein paar dieser Felder verzichten kann, wer will kann es ja mal ausprobieren.
    Der Bundle Identifier muss auf jeden Fall vorhanden sein. Diesen Namen darf sonst kein Kext tragen. Es ist üblich mit der eigenen umgedrehten Webdomain anzufangen und mit dem Projektnamen zu enden. Keine Leerschritte.
    Bundle name, und die zwei Bundle versions, kann man ebenfalls frei vergeben. Bundle version muss allerdings das Format Zahl.Zahl.Zahl haben.
    Den Rest übernimmt man wie er da steht.


    Jetzt wird's persönlich
    Wie wir wissen machen die IOKitPersonalities die Arbeit.
    Also legen wir sie an. Wir nennen unsere Personality Strix 270i Gaming. Apple hätte sie wohl iMac18,3-XHC genannt.



    Die Überprüfung soll starten, wenn ein XHCI Treiber geladen wird (IOProviderClass)
    Der Rechner vom Typ iMac18,3 (model) ist.
    Und unser Gerät XHC heisst (IONameMatch). In AppleUSBXHCIPCI steht an dieser Stelle XHC1, aber wir haben im IORegistryExplorer gesehen, dass unser Device XHC heisst. Statt das Device in der DSDT oder Clover umzubenennen, ändern wir hier den IONameMatch, da wir schon mal hier sind und dann auch nur an einer Stelle Änderungen vornehmen.
    Unser Test hat einen IOProbeScore von 5000, um auch in Zukunft wichtiger als andere Einträge mit den selben Bedingungen zu sein.


    Der Treiber der geladen werden soll ist, wie wir im Original gesehen haben, AppleUSBMergeNub im Kext mit dem Bundle Identifier com.apple.driver.AppleUSBMergeNub.
    Jetzt müssen wir nur noch die Ports eintragen. Die gehören unter IOProviderMergeProperties.



    Der erste Eintrag bei den IOProviderMergeProperties ist der page-count, der die höchste Port-Id enthält.
    Danach kommt die Liste der Ports.
    Die Daten des port-count Eintrages tragen wir später ein, wenn wir die höchste Portnummer kennen.
    Um Platz zu sparen nur der relevante Ausschnitt


    Wie ein Eintrag für ein Port aussieht haben wir ja gestern beim Betrachten von AppleUSBHCIPCI gesehen.
    Für unsere erstes Port HS01 sieht das dann wie folgt aus


    Unser erstes Port ist auch das erste Controller Port und ein HS Port deshalb heißt es HS01.
    Es ist auf einen Header geführt, deshalb ist der USB Connector Typ 255
    Die Port Id ist 0x01


    Der am selben Stecker liegende SS Port ist der erste SS Port des Controllers und heißt deshalb SSP1 - weil es im iMac17,1 Eintrag auch so hieß. Wir könnten es auch SS01 oder XA4R nennen. Das erhöht den Wiedererkennungswert für Eingeweihte, verwirrt aber alle anderen, deshalb verwenden wir einen "Standardnamen".
    Der USB Connector ist der selbe und die Port Id 0x11.


    Das macht man für alle Ports.
    Das Port mit der höchsten Id ist SSP5


    Das liegt an einer USB 3.0 Typ A Buchse, deshalb ist der USB Connector 3. Die Port Id ist 0x15 das ist deshalb erwähnenswert, weil wir die höchste Port Id im port-count Eintrag brauchen.


    Die ganze Datei sieht dann so aus, beachte den bei port-count eingetragenen Wert.


    Feddich, wie en Reddich.
    Yeah, lasst es Konfetti regnen.


    In den EFI/CLOVER/kexts/Other Ordner der EFI Partition kopiert, neugestartet und
    IORegistryEditor zeigt uns


    Was will man mehr ?
    Z.B. das es funktioniert.
    Wir stellen nämlich schnell fest, dass die USB 3.0 Einträge nicht funktionieren.
    Wie wir aus dem IORegistryEditor wissen, wurde der "Notfall Treiber" für XHCI Geräte geladen. der scheint dann wohl nicht zu passen, zumindest nicht für USB 3.0.


    Die Qual der Wahl
    AppleUSBXHCIPCI hat eine Reihe von auf verschiedene Controller zugeschnittene Treiber. Welchen nehmen ?
    Ausprobieren oder einen "educated guess" - gibt's da einen deutschen Ausdruck für ? - wagen.
    Wie wir aus dem IORegistryEditor wissen, hat user USB Controller die Primary-Id 0xa2af8086.
    Bei Durchsicht der Treiber Einträge in AppleUSBXHCIPCI finden wir einen für 0xa12f8086 - das Vorgängermodell.
    Also probieren wir es doch mit dem.


    Um den Treiber starten zu können brauchen wir wieder ein Kext. Na ja wir haben schon eins, also verwenden wir das.
    Die Struktur für einen Treibereintrag haben wir gestern gesehen.
    Also legen wir eine neue Personality an und nennen sie AppleUSBXHCISPTB Z200 oder irgendwie anders.



    Unser Treiber soll geladen werden, wenn ein PCIDevice entdeckt wird und es die Id 0xa2af8086 hat.
    Den IOProbeScore setzen wir auf 5000, damit macht unser Eintrag einen auf wichtig.
    Wir schreiben ja keinen eigenen XHCI Treiber, sondern nehmen einen aus dem AppleUSBXHCIPCI Kext. Das ist dem Kernel als com.apple.driver.usb.AppleUSBXHCIPCI (CFBundleIdentifier) bekannt.
    Der Treiber den 0xa12f8086 (Vorgänger) verwendet ist (IOClass) AppleUSBXHCISPT. Also nehmen wir den auch.
    Die letzten beiden Einträge übernehmen wir, da wir davon ausgehen, dass unser Controller alles kann, was der alte konnte.


    Und war's das ?
    In den Other Ordner, Neustart und
    Alles geht, wie es soll.


    Das war's


    P.S.
    Im Anhang findet ihr das Kext.

  • @Brumbaer
    Vielen Dank dafür, dass du dein hart erarbeitetes Wissen hier mit uns teilst. Einfach grandios deine Beiträge. :thumbsup::danke::dafuer:

    MfG, docplag



  • Na das hat jetzt mal Spaß gemacht. :thumbsup:


    Gerade den ersten Teil gelesen. Vielen Dank für die tolle Erläuterung. Das ist ja hier der Goldstandard.


    Freue mich schon auf Morgen Abend: 2. Teil.


    Ein kleine Anmerkung: Das zweite Bild der Info.plist sollte ein anderes sein, da Du von "IOPCIClassMatch" redest, diese dort aber nicht auftaucht, sondern nur die "IOPCIPrimaryMatch". Es ist also bereits das dritte Bild drin.

    Liebe Grüße aus Berlin

  • andreas_55
    Vielen Dank fürs aufmerksame Lesen. Habe das Bild getauscht .


    P.S.
    Gestern war morgen heute. Der morgige Beitrag von gestern aus gesehen ist ein paar Posts weiter oben.

  • Ich weiss.
    Freue mich ja auch auf mein Morgen. Dein Morgen war ja schon heute. :)

    Liebe Grüße aus Berlin

  • Vielen Dank für die tolle ausführliche Erläuterung. Das ist mal ein richtig guter Batzen Wissen.


    Man braucht aber schon ein paar Anläufe bis man durch ist.
    Bringt aber wichtiges wissen mit.


    Thanks :verneigen:
    StevePeter

    „Die Definition von Wahnsinn ist, immer wieder das Gleiche zu tun und andere Ergebnisse zu erwarten.“ - Albert Einstein

  • Auch von mir vielen Dank für die Mühen und die ausführlichen Erläuterungen. Das ist ein wichtiges Thema und sicher für viele hier sehr aufschlussreich.


    Eine Anmerkung, da mich das beim ersten Lesen selbst verunsichert hatte: Der port-count Eintrag entspricht, wie beschrieben, der höchsten verzeichneten Portnummer. Damit lässt sich aber nicht das nebenbei angesprochene Port Limit von 15 Ports umgehen, da dieses in den Treibern im AppleUSBXHCIPCI Binary fest definiert ist, also nicht auf port-count reagiert. Mit dieser Dummy Kext können beliebig viele Ports definiert werden, auch mehr als 15, wenn vorhanden, jedoch lädt der Treiber nur die ersten maximal 15 davon. Wem das nicht ausreicht, der kann:

    • weiterhin auf den Port Limit Raiser Patch (Clover "KextsToPatch" / Perl / etc - von Entwicklern immer wieder als riskant eingestuft) setzen, um mehr als 15 der definierten Ports ansprechen zu können, oder
    • nicht explizit benötigte Ports (freie interne Header / freie Mainboard Buchsen / bei USB 3.0 Typ A Ports wahlweise auch entweder den 2.0 (HS) oder 3.0 (SS) Teil, wenn man nur den jeweils anderen braucht) nicht in die Info.plist eintragen

    Ich persönlich konnte einen halben USB 2.0 Header und den 2.0 Part zweier rückseitiger Buchsen opfern. Sicher - das lässt sich mit USBInjectAll auch leicht machen. Diese Dummy Kext Methode funktioniert aber seit El Capitan einwandfrei, während USBInjectAll schon bei einigen Versionen des Betriebssystems angepasst werden musste, was für manche Early Adopters sicher nicht unproblematisch war. Also der Aufwand lohnt sich meiner Meinung nach in jeden Fall, wenn nicht nativ alle USB Ports erkannt werden, weil man damit auch in den kommenden Jahren Ruhe haben dürfte (vorausgesetzt Apple findet kein zweites technisches Fauxpas, das uns einen weiteren komplett überarbeiteten USB Stack beschert) ;)

    gez. Thogg Niatiz

  • Wow!! Also das war ja nochmal besser! Super lehrreich!


    Vor ´ner Weile habe ich bei RehabMan gelesen, "... man könnte einen eigenen Kext bauen, muss nur darauf achten, das der IOProbeScore hoch genug ist ..." und ich dachte nur "Wovon redet der Kerl eigentlich?"


    Jetzt weiss ich nicht nur was er meinte sondern freue mich darauf, bald meinen ersten Kext zu bauen!
    Daran hätte ich vorgestern im Traum nicht gedacht.


    Ihr seid hier schon ein toller Haufen.


    :danke:

    Liebe Grüße aus Berlin

  • Dann habe ich wohl nicht die richtigen Worte gefunden.

  • Aber sicher doch, es liegt entweder an meinen begrenzten Möglichkeiten oder der Uhrzeit/Jahreszeit, auf jeden Fall weiss ich nicht was ich wo wie machen soll. :D
    Mal Spaß beiseite, ich habe einfach neben dem Job keinen Kopf um mich in solche Brocken einzulesen und zu verstehen und damit zu arbeiten, zumal dass ja ein ganz anderes Berufsfeld ist.
    Kurz und knapp, die Festplatte ist voll und auslagern in die Cloud geht nicht, meine Frau will nix mehr vom Forum und Hackintosh hören. :kichern:


    Btw: Wie machen die anderen das, lesen, verstehen, Aha Effekt und anschließend umsetzen und freuen? ?(

  • Vielleicht äußert sich ja noch jemand.
    Aber ich sehe schon die Gefahr, dass bei unterschiedlichem Erfahrungshorizont, Dinge nicht umbedingt so aufgenommen werden, wie der Autor es erwartet.
    Vielleicht liegt es aber auch einfach daran, dass im Text ein Fehler ist.
    @andreas_55 hat schon ein paar Dreckfuhler gefunden, die ein Stirnrunzeln erzeugen können, und mit netterweise mitgeteilt. Vielen, vielen Dank dafür.
    Denn egal wie oft ich es lese irgendwann ist Schicht mit dem Finden von Fehlern in eigenen Texten. Das geht dann erst wieder mit Vierzehntagen Abstand.


    Ggf. Fragen, vielleicht kann ich es mit anderen Worten erklären.

  • @derHackfan
    Das Du weniger Zeit hast liegt selbstverständlich auch daran, dass Du unermüdlich im Forum Anderen hilfst.


    The difference between amateurs and professionals:
    "Amateurs think knowledge is power. Professionals pass on wisdom and advice."
    "Amateurs show up inconsistently. Professionals show up every day."


    Du bist ein Profi. :thumbup:


    @Brumbaer
    Unter der Überschrift Sonst noch was ? ist das Bild “IOService” einmal XHC@14 und XHC@14000000:
    Dort findet sich links class-code <30 03 0c 00> und rechts IOPCIClassMatch 0x0c033000


    Ich bin über was gestolpert:
    Das ist nicht die Umwandlung von Little in Big-Endian, denn das ist 30 03 0c 00 -> 00 0c 03 30.
    Also hätte ich eigentlich IOPCIClassMatch 0x000c0330 erwartet.


    Oder ist das in dem Fall nicht der Zusammenhang?

    Liebe Grüße aus Berlin

    Einmal editiert, zuletzt von andreas_55 ()

  • Vielleicht äußert sich ja noch jemand.


    Ich habe die beiden Beiträge ganz in Ruhe durchgelesen und glaube soweit alles verstanden zu haben. Es ist schon beachtlich was da so ineinander greift oder auch nicht, wenn bestimmte Bedingungen nicht gegeben sind.
    Zum Schluss war ich dann die "Faulheit in Person" und habe deinen hochgeladenen Kext einfach an mein System angepasst. Ich bin gerade fertig geworden und werde es gleich testen. Melde mich gleich wieder.


    EDIT: Meine Faulheit wurde postwendend bestraft. Es wurden 15 HS-Ports und ein SS-Port erkannt. Geladen lt. Systembericht wurde der Treiber für den Host-Controller AppleUSBXHCISPT mit der PCI-Geräte-ID 0xa12f.
    Ich habe in meinem Kext auch Bundle Identifier, Bundle name und in IOKitPersonalities das Dictionary angepasst. Vielleicht liegt da irgendwo der Fehler.

    MfG, docplag



    Einmal editiert, zuletzt von Doctor Plagiat ()