From owner-freebsd-arch@FreeBSD.ORG Sun Sep 28 10:19:28 2008 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 873EA106569C for ; Sun, 28 Sep 2008 10:19:28 +0000 (UTC) (envelope-from luigi@onelab2.iet.unipi.it) Received: from onelab2.iet.unipi.it (onelab2.iet.unipi.it [131.114.9.129]) by mx1.freebsd.org (Postfix) with ESMTP id 10EF78FC0A for ; Sun, 28 Sep 2008 10:19:27 +0000 (UTC) (envelope-from luigi@onelab2.iet.unipi.it) Received: by onelab2.iet.unipi.it (Postfix, from userid 275) id 18598730A8; Sun, 28 Sep 2008 12:07:31 +0200 (CEST) Date: Sun, 28 Sep 2008 12:07:31 +0200 From: Luigi Rizzo To: freebsd-arch@freebsd.org Message-ID: <20080928100731.GA49323@onelab2.iet.unipi.it> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.3i Subject: dynamic update of usb/pci/quirks tables X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 28 Sep 2008 10:19:28 -0000 For some time I have been thinking of a way to solve the problem in the subject., which is hitting me almost every time i try to connect a newly bought device (scanner, phone, camera, mp3 player, even some flash keys) to FreeBSD. I was wondering what you people think about the following approach, which can be implemented by a trivial userland program (kldpatch) and probably be used with little effort or code bloat also in the loader. PROBLEM DESCRIPTION: A common problem with newer USB (but also other) peripheral is that often the kernel does not have the correct product and vendor numbers in its internal tables used for device matching or for applying quirks to certain devices. The problem arises quite often with e.g. uscanner (where the matching must be done through the table because there is no specific device class), or with various umass devices (flash keys, cameras, phones, etc.) which tend to require quirks because they do not implement all the default features used by the umass driver. APPROACH: The following approach can be used to patch the in-kernel structures used to store the match/quirks tables: + use kldfind and kldsym to locate the module, address and size for the desired data structure; + use kvm_open/kvm_read/kvm_write to read and possibly update the table. Of course patching the live kernel is dangerous, so one way to make the process a little less risky is to put some additional controls in the frontend program which implements the above. In particular, the frontend will contain a table of the form module symbol record_size record_format... which defines which modules/symbols can be patched and how each record is supposed to be structured. As an example: uscanner.ko uscanner_devs 8 2 2 4 umass.ko umass_devdescrs 16 4 4 4 2 2 if_sis.ko sis_devs 8 2 2 %s tells that uscanner has 8-byte records made of 3 numeric fields of size 2 2 4, umass.ko has 16-byte records with 5 numeric fields, if_sis has 8-byte records whose last one is a string pointer, (I could not find an instance with a fixed-size string). The frontend will accept commands of the form kldpatch if_sis.ko sis_devs write @3 0x1234 0x5678 "temporary entry" which means 'patch record 3 with the values specified". The frontend will make sure that operands are of the required size, that the table entry is within the table, and that (in case of patching constant strings) the replacement does not exceed the original length of the string. DISCUSSION: This approach does not address one case which is the "translation" of one PCI/USB/bus id into another one to make a driver believe that device X is instead device Y. It does address, however, the relatively common case where recognised IDs are in an explicit device or quirks table. I believe the same functionality can be added to the loader/kernel itself, e.g. by telling /boot/loader to load a text file with all the patches (i.e. the arguments to kldpatch) to be applied, and hooking into the kernel so that right after boot, and right after a module has been kldloaded, the patches are applied. In terms of preventing the user from doing mistakes, there are a few safety checks implemented by the internal table, which should at least prevent the user from writing outside the allowed areas. Clearly there is the issue of a possible mismatch between the record structure as known to kldpatch, and the actual record structure as defined in the .ko files -- but i don't know of a reasonably simple method to extract the structure info from the C source and pass them to kldpatch -- one way could be, perhaps, to add a special symbol to the module itself so perhaps at least the structure info can be declared within the module, and it is easier to be kept in sync. ---- comments ? cheers luigi