\documentclass[addpoints,12pt]{exam} \usepackage{ngerman} \usepackage{listings,color} \usepackage{graphicx} \usepackage[T1]{fontenc} \firstpageheadrule \runningheadrule \lhead{Manuel Traut\\Sommersemester 2018} \chead{Hochschule Ravensburg-Weingarten\\Linux-Kernelprogrammierung} \rhead{MatrNr:\\Datum:} \firstpagefootrule \runningfootrule \firstpagefooter{Page \thepage\ of \numpages} {} {Punkte: \makebox[.5in]{\hrulefill}\\ von \pointsonpage{\thepage} Punkten} \runningfooter{Page \thepage\ of \numpages} {} {} \pagestyle{headandfoot} \pointsinrightmargin \pointpoints{Punkt}{Punkte} \begin{document} \begin{coverpages} \begin{titlepage} \title{Pr\"ufung Linux-Kernelprogrammierung} \author{Dozent: Manuel Traut} \date{10. Juli 2018 10:30 Uhr} \maketitle \begin{center} Hochschule Ravensburg-Weingarten \vspace{1cm} Raum: H142 Dauer: 60 Minuten, erlaubte Hilfsmittel: alle \end{center} \vspace{2cm} Name:\enspace\hrulefill \vspace{2cm} MatrNr:\enspace\hrulefill \begin{center} \begin{lstlisting} a8888b. d888888b. 8P"YP"Y88 (((((((()))))))))) 8|o||o|88 ||VIEL ERFOLG !!|| 8' .88 ((((((((((((())))) 8`._.' Y8. d/ `8b. .dP . Y8b. d8:' " `::88b. d8" `Y88b :8P ' :888 8a. : _a88P ._/"Yaa_ : .| 88P| \ YP" `| 8P `. / \._____.d| .' `--..__)888888P`._.' \end{lstlisting} \end{center} \end{titlepage} \end{coverpages} \lstset{ % basicstyle=\scriptsize, % the size of the fonts that are used for the code breaklines=true, % sets automatic line breaking frame=single, % adds a frame around the code language=C, % the language of the code numbers=left, % where to put the line-numbers; numbersep=5pt, % how far the line-numbers are from the code numberstyle=\tiny, % the style that is used for the line-numbers tabsize=8, % sets default tabsize to 2 spaces } \begin{questions} \question Sie haben einen IoT Toaster entwickelt. Um die Sensoren (Temperatur, Luftfeuchtigkeit, Strommesser, Spannungsmesser, Lagemesser, sowie zwei Wegsensoren) und Aktoren (je eine PWM für Heizspirale und die zwei Motoren) des Toasters vom User-space zugreifbar zu machen haben Sie den Linuxkernel um entsprechende Treiber erweitert. Die Toasterapplikation im Userspace liest die Sensordaten aus und übermittelt Sie über ein Netzwerkinterface und WLAN Kerneltreiber in eine Cloudapplikation. Ausserdem ermöglicht die Toasterapplikation, dass in der Cloud definierte Toastprogramme (z.B. auftauen, bräunen, Holzkohle) die PWMs via Userspaceinterface programmieren. Die Toasterapplikation ist in JAVA geschrieben und verwendet ausschliesslich JAVA Module welche unter MIT oder LGPL Lizenz stehen. \begin{parts} \part[4] Argumentieren Sie weshalb es f\"ur zuk\"unftige Entwicklungen am Toaster f\"ur Ihre Firma von Vorteil ist, die neu entwickelten Kerneltreiber in den 'mainline Kernel' zu integrieren. \part[6] Sie wollen Ihre Treiber welche Sie gegen Kernelversion 4.5 entwickelt haben in Mainline Linux integriert haben. Wie gehen Sie vor? \part[2] Welche Aufgaben haben die Kernel Maintainer in diesem Zusammenhang? \part[12] Für die Temperatursensoren können Sie die Funktionen des 'thermal Subsystems' nutzen. Für den Luftfeuchtigkeitssensor gibt es kein passendes Subsystem. Der Sensor befindet sich auf einer PCI Karte, der Sensorwert (uint\_8) kann ohne Umrechnung von Memoryoffset 0x100 von PCI Bar 2 im Kernel gelesen werden. Verwenden Sie zur Beantwortung der folgenden Punkte Pseudocode oder beschreiben Sie textuell: \begin{enumerate} \item Was tut Ihre init Funktion? \item Was implementieren Sie in der probe Funktion? \item Wie ermöglichen Sie den Zugriff auf den Messwert vom Userspace aus? \item Beschreiben Sie wie Sie den Wert in der Toasterapplikation auslesen. \end{enumerate} \part[1] M\"ussen Sie die K\"aufer des Toasters informieren, dass Sie Linux einsetzen? \part[1] M\"ussen Sie auf Anfrage eines Käufers die verwendeten Kernelsourcen zur Verf\"ugung stellen? \part[1] Wem m\"ussen Sie auf Anfrage den Quellcode der Toasterapplikation zur Verf\"ugung stellen? \end{parts} \question [6] Beschreiben Sie stichwortartig den Releasezyklus des Linuxkernels. Erkl\"aren Sie in diesem Zusammenhang auch die Begriffe 'Release Candidate', 'Release', 'stable Kernel' und 'staging'. \question [6] Ein von Ihnen entwickelter Kerneltreiber funktioniert nicht wie erwartet. Welche Debugingm\"oglichkeiten haben Sie? Nennen Sie zwei Möglichkeiten und beschreiben Sie Vor- und Nachteile \newpage \question Im Linux Source gibt es einen Ordner 'staging'. \begin{parts} \part[1] Was findet man in diesem Ordner? \part[2] Wann wird der Code aus diesem Ordner gel\"oscht / verschoben? \end{parts} \question \question Die folgenden Fragen beziehen sich auf den Quellcode 1 im Anhang. \begin{parts} \part[2] Der Treiber wird in einem System geladen, welches 2 PCI Devices mit Vendor ID 0x186c und Device ID 0x0624 besitzt. Wie oft wird mf624\_pci\_probe und mf624\_init aufgerufen? \part[4] Egal auf welches Device Sie zugreifen, Sie interagieren immer nur mit einer der zwei PCI Karten. Wie m\"usssen Sie den Treiber modifizieren, damit beide Karten funktionieren? \part[6] Suchen Sie sich drei Codezeilen aus, erkl\"aren Sie jeweils in welchem Zusammenhang die Codezeile ausgeführt wird und was diese bewirkt. \end{parts} \question Die folgenden Frage bezieht sich auf den Quellcode 2 im Anhang. \begin{parts} \part[10] Mit den Funktionen 'set\_latch\_green und get\_latch\_green' (welche in asm/mach-rc32434/gpio.h definiert sind) kann analog zu den bereits verwendeten Funktionen 'set\_latch\_u5 / get\_latch\_u5' eine gr\"une LED angesteuert werden. Erweitern Sie den Treiber so, dass die gr\"une LED z.B. mit 'echo 1 > /sys/class/leds/huhu/brightness' eingeschaltet werden kann. \end{parts} \end{questions} \vspace{1cm} Punkte: \_\_\_\_ von \numpoints \hspace{1cm} Note: \newpage \begin{appendix} Quellcode 1: \begin{lstlisting} /* * UIO driver fo Humusoft MF624 DAQ card. * Copyright (C) 2011 Rostislav Lisovy , * Czech Technical University in Prague * * Copyright (C) 2016 Manuel Traut , * modified for usage in kernel exams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #define PCI_VENDOR_ID_HUMUSOFT 0x186c #define PCI_DEVICE_ID_MF624 0x0624 /* BAR0 Interrupt control/status register */ #define INTCSR 0x4C #define INTCSR_ADINT_ENABLE (1 << 0) #define INTCSR_CTR4INT_ENABLE (1 << 3) #define INTCSR_PCIINT_ENABLE (1 << 6) #define INTCSR_ADINT_STATUS (1 << 2) #define INTCSR_CTR4INT_STATUS (1 << 5) enum mf624_interrupt_source {ADC, CTR4, ALL}; static void mf624_disable_interrupt(enum mf624_interrupt_source source, struct uio_info *info) { void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR; switch (source) { case ADC: iowrite32(ioread32(INTCSR_reg) & ~(INTCSR_ADINT_ENABLE | INTCSR_PCIINT_ENABLE), INTCSR_reg); break; case CTR4: default: iowrite32(ioread32(INTCSR_reg) & ~(INTCSR_CTR4INT_ENABLE | INTCSR_PCIINT_ENABLE), INTCSR_reg); break; } } static irqreturn_t mf624_irq_handler(int irq, struct uio_info *info) { void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR; if ((ioread32(INTCSR_reg) & INTCSR_ADINT_ENABLE) && (ioread32(INTCSR_reg) & INTCSR_ADINT_STATUS)) { mf624_disable_interrupt(ADC, info); return IRQ_HANDLED; } if ((ioread32(INTCSR_reg) & INTCSR_CTR4INT_ENABLE) && (ioread32(INTCSR_reg) & INTCSR_CTR4INT_STATUS)) { mf624_disable_interrupt(CTR4, info); return IRQ_HANDLED; } return IRQ_NONE; } static struct uio_info mf624_info = { .name = "mf624"; .version = "0.0.1"; }; static int mf624_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct uio_info *info = &mf624_info; if (pci_enable_device(dev)) return -1; if (pci_request_regions(dev, "mf624")) goto out_disable; /* BAR0 */ info->mem[0].name = "PCI chipset, interrupts, status " "bits, special functions"; info->mem[0].addr = pci_resource_start(dev, 0); if (!info->mem[0].addr) goto out_release; info->mem[0].size = pci_resource_len(dev, 0); info->mem[0].memtype = UIO_MEM_PHYS; info->mem[0].internal_addr = pci_ioremap_bar(dev, 0); if (!info->mem[0].internal_addr) goto out_release; /* BAR2 */ info->mem[1].name = "ADC, DAC, DIO"; info->mem[1].addr = pci_resource_start(dev, 2); if (!info->mem[1].addr) goto out_unmap0; info->mem[1].size = pci_resource_len(dev, 2); info->mem[1].memtype = UIO_MEM_PHYS; info->mem[1].internal_addr = pci_ioremap_bar(dev, 2); if (!info->mem[1].internal_addr) goto out_unmap0; info->irq = dev->irq; info->irq_flags = IRQF_SHARED; info->handler = mf624_irq_handler; if (uio_register_device(&dev->dev, info)) goto out_unmap1; pci_set_drvdata(dev, info); return 0; out_unmap1: iounmap(info->mem[1].internal_addr); out_unmap0: iounmap(info->mem[0].internal_addr); out_release: pci_release_regions(dev); out_disable: pci_disable_device(dev); return -ENODEV; } static void mf624_pci_remove(struct pci_dev *dev) { struct uio_info *info = pci_get_drvdata(dev); mf624_disable_interrupt(ALL, info); uio_unregister_device(info); pci_release_regions(dev); pci_disable_device(dev); iounmap(info->mem[0].internal_addr); iounmap(info->mem[1].internal_addr); kfree(info); } static const struct pci_device_id mf624_pci_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_HUMUSOFT, PCI_DEVICE_ID_MF624) }, { 0, } }; static struct pci_driver mf624_pci_driver = { .name = "mf624", .id_table = mf624_pci_id, .probe = mf624_pci_probe, .remove = mf624_pci_remove, }; MODULE_DEVICE_TABLE(pci, mf624_pci_id); int mf624_init(void) { return pci_driver_register(&mf624_pci_driver); } void mf624_exit(void) { pci_driver_unregister(&mf624_pci_driver); } module_init(mf624_init); module_exit(mf624_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Rostislav Lisovy "); \end{lstlisting} \newpage Quellcode 2: \begin{lstlisting} /* * LEDs driver for the "User LED" on Routerboard532 * * Copyright (C) 2009 Phil Sutter * * Based on leds-cobalt-qube.c by Florian Fainelly and * rb-diag.c (my own standalone driver for both LED and * button of Routerboard532). */ #include #include #include #include #include static void rb532_led_set(struct led_classdev *cdev, enum led_brightness brightness) { if (brightness) set_latch_u5(LO_ULED, 0); else set_latch_u5(0, LO_ULED); } static enum led_brightness rb532_led_get(struct led_classdev *cdev) { return (get_latch_u5() & LO_ULED) ? LED_FULL : LED_OFF; } static struct led_classdev rb532_uled = { .name = "uled", .brightness_set = rb532_led_set, .brightness_get = rb532_led_get, .default_trigger = "nand-disk", }; static int rb532_led_probe(struct platform_device *pdev) { return led_classdev_register(&pdev->dev, &rb532_uled); } static int rb532_led_remove(struct platform_device *pdev) { led_classdev_unregister(&rb532_uled); return 0; } static struct platform_driver rb532_led_driver = { .probe = rb532_led_probe, .remove = rb532_led_remove, .driver = { .name = "rb532-led", }, }; module_platform_driver(rb532_led_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("User LED support for Routerboard532"); MODULE_AUTHOR("Phil Sutter "); MODULE_ALIAS("platform:rb532-led"); \end{lstlisting} \end{appendix} \end{document}