Linux - Extraktion der Kernelversion



  • Ich habe hier einen Hardware-Treiber mit Patchfunktion, der die Kernelversion aus
    include/linux/version.h bzw. include/generated/uapi/linux/version.h
    ermittelt. Diese Dateien existieren aber erst nachdem wenigstens make prepare gelaufen ist. Ich möchte das make-File des Treibers gerne so anpassen, dass der Patch auch ohne irgendwelche vorherigen Build-Schritte im Linuxtree aufgespielt werden kann. Gibt es eine offizielle Methode, die Version zu bestimmen?

    Der entsprechende Teil des make-Files sieht gegenwärtig so aus.

    VERSION_H := $(shell sh -c " \
    if test -f $(KERNELDIR)/include/linux/version.h; then \
        echo $(KERNELDIR)/include/linux/version.h; \
    elif test -f $(KERNELDIR)/include/generated/uapi/linux/version.h; then \
        echo $(KERNELDIR)/include/generated/uapi/linux/version.h; \
    fi")
    
    MAJOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\  -f3` / 65536 % 65536)
    MINOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\  -f3` / 256 % 256)
    KERNEL_VER := $(MAJOR).$(MINOR)
    

    und falls die Dateien nicht existieren, ist VERSION_H leer und grep benutzt die Standardeingabe, was nicht optimal ist.



  • version.h wird nach dem Makefile so generiert:

    define filechk_version.h
    	(echo \#define LINUX_VERSION_CODE $(shell                         \
    	expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
    	echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
    endef
    

    Und die relevante Information sollte mit

    # Read KERNELRELEASE from include/config/kernel.release (if it exists)
    KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
    KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
    
    export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
    

    auch dem Modul-Makefile zur Verfügung stehen.

    D.h. wenn ich das richtig überflogen habe, müsste dein gezeigter Code eine umständliche Schreibweise für

    MAJOR := $(VERSION)
    MINOR := $(PATCHLEVEL)
    KERNEL_VER := $(MAJOR).$(MINOR)
    

    sein. Je nachdem, wofür KERNEL_VER verwendet wird, würde ich sogar nur

    KERNEL_VER := $(KERNELVERSION)
    

    schreiben.



  • include/config existiert auch nicht nach einem make mrproper
    Allerdings beginnt bei mir $(KERNELDIR)/Makefile mit

    VERSION = 3
    PATCHLEVEL = 11
    SUBLEVEL = 2
    

    Der Installer des Treibers (für eine RAID-Karte) soll sowohl mit einem vollständigen Linux-Sourcetree zurecht kommen (zwecks Integration), als auch, wenn nur mit den notwendigen Header vorhanden sind (z.B. mit LiveCD) um ein Modul bauen und installieren zu können. In letzterem Fall dürfte das Makefile nicht existieren.

    Ich verwende jetzt

    VERSION_H := $(shell sh -c " \
    if test -f $(KERNELDIR)/include/linux/version.h; then \
        echo $(KERNELDIR)/include/linux/version.h; \
    elif test -f $(KERNELDIR)/include/generated/uapi/linux/version.h; then \
        echo $(KERNELDIR)/include/generated/uapi/linux/version.h; \
    fi")
    
    ifneq ($(VERSION_H),)
    MAJOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\  -f3` / 65536 % 65536)
    MINOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\  -f3` / 256 % 256)
    else
    ifneq ($(strip $(wildcard $(KERNELDIR)/Makefile)),)
    MAJOR := $(shell expr `grep "^VERSION =" $(KERNELDIR)/Makefile | cut -d\  -f3`)
    MINOR := $(shell expr `grep "^PATCHLEVEL =" $(KERNELDIR)/Makefile | cut -d\  -f3`)
    else
    $(error Cannot find kernel version. Check $(KERNELDIR)/include/linux/version.h.)
    endif
    endif
    KERNEL_VER := $(MAJOR).$(MINOR)
    

    was soweit zu funktionieren scheint.



  • Wenn du das aus der Kernel-Makefile ziehen willst und Zeit nicht so kritisch ist (also du ne Extrasekunde hast), geht "make kernelversion" bzw. "$(shell make -f $(KERNELDIR)/Makefile kernelversion)".


Anmelden zum Antworten