1
0

Import changes from 2021-2022

This commit is contained in:
Jacques Supcik
2023-02-23 20:46:06 +01:00
committed by GitHub
parent ea25559612
commit b3e2882bf5
78 changed files with 14234 additions and 2 deletions

View File

@@ -0,0 +1,16 @@
{
"folders": [
{
"path": ".."
},
{
"path": "../src/02_modules/exercice01"
}
],
"settings": {
"files.associations": {
"moduleparam.h": "c",
"ranges": "c"
}
}
}

View File

@@ -0,0 +1,11 @@
{
"folders": [
{
"path": ".."
},
{
"path": "../src/01_environment/core_dumps"
}
],
"settings": {}
}

View File

@@ -29,6 +29,7 @@ services:
-s "rootfs;/rootfs;no;no"
-s "workspace;/workspace;no;no"
-s "home;/root-home;no;no"
-g "unix extensions = yes"
-g "vfs objects = catia fruit"
ports:
- "139:139"

View File

@@ -0,0 +1,11 @@
{
"folders": [
{
"path": ".."
},
{
"path": "../src/01_environment/fibonacci"
}
],
"settings": {}
}

24
.gitignore vendored
View File

@@ -3,3 +3,27 @@ buildroot-images
src/*/app
.obj
.deleted
.DS_Store
src/**/.Module.*
src/**/Module.symvers
src/**/.mymodule.*
src/**/mymodule.*
src/**/.modules.*
src/**/.*.cmd*
src/**/app
src/**/core
src/**/modules.order
src/**/.skeleton.*
src/**/*.o
src/**/*.dtb
src/**/*.ovl
src/02_modules/procstat/procstat
src/02_modules/procstat/procstat_s
src/03_drivers/sample01/main1
src/03_drivers/sample01/main2
src/03_drivers/sample01/main3

20
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/buildroot/output/build/linux-5.15.21/include",
"/buildroot/output/build/linux-5.15.21/arch/arm64/include",
"/buildroot/output/build/linux-5.15.21/arch/arm64/include/generated",
"/buildroot/output/build/linux-5.15.21/**"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cStandard": "c99",
"cppStandard": "c++14",
"intelliSenseMode": "linux-clang-arm64"
}
],
"version": 4
}

14
src/.clang-format Normal file
View File

@@ -0,0 +1,14 @@
---
BasedOnStyle: Google
IndentWidth: 4
---
Language: Cpp
ColumnLimit: 80
BreakBeforeBraces: Custom
AlignConsecutiveAssignments: true
DerivePointerAlignment: false
PointerAlignment: Left
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterFunction: true

View File

@@ -4,7 +4,6 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",

5
src/02_modules/Makefile Normal file
View File

@@ -0,0 +1,5 @@
DIRS=$(filter-out Makefile, $(wildcard *))
all clean install:
for dir in $(DIRS); do $(MAKE) $@ -C $$dir; done

View File

@@ -0,0 +1,19 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/buildroot/output/build/linux-5.15.21/include",
"/buildroot/output/build/linux-5.15.21/arch/arm64/include",
"/buildroot/output/build/linux-5.15.21/arch/arm64/include/generated"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cStandard": "c99",
"cppStandard": "c++14",
"intelliSenseMode": "linux-clang-arm64"
}
],
"version": 4
}

View File

@@ -0,0 +1,30 @@
export PATH := /buildroot/output/host/usr/sbin$\
:/buildroot/output/host/usr/bin/$\
:/buildroot/output/host/sbin$\
:/buildroot/output/host/bin/$\
:$(PATH)
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
CFLAGS_skeleton.o := -DDEBUG
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
echo $(PATH)
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,31 @@
// skeleton.c
#include <linux/module.h> // needed by all modules
#include <linux/init.h> // needed for macros
#include <linux/kernel.h> // needed for debugging
#include <linux/moduleparam.h> // needed for module parameters
static char* text = "dummy text";
module_param(text, charp, 0664);
static int elements = 1;
module_param(elements, int, 0);
static int __init skeleton_init(void)
{
pr_info ("Linux module 01 skeleton loaded\n");
pr_debug (" text: %s\n elements: %d\n", text, elements);
return 0;
}
static void __exit skeleton_exit(void)
{
pr_info ("Linux module skeleton unloaded\n");
}
module_init (skeleton_init);
module_exit (skeleton_exit);
MODULE_AUTHOR ("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION ("Module skeleton");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,27 @@
export PATH := /buildroot/output/host/usr/sbin$\
:/buildroot/output/host/usr/bin/$\
:/buildroot/output/host/sbin$\
:/buildroot/output/host/bin/$\
:$(PATH)
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,16 @@
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
endif

View File

@@ -0,0 +1,64 @@
/* skeleton.c */
#include <linux/module.h> /* needed by all modules */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/moduleparam.h> /* needed for module parameters */
#include <linux/slab.h> /* needed for dynamic memory allocation */
#include <linux/list.h> /* needed for linked list processing */
#include <linux/string.h> /* needed for string handling */
static char* text = "dummy text";
module_param(text, charp, 0);
static int elements = 0;
module_param(elements, int, 0);
struct element {
char text[100];
int ele_nr;
struct list_head node;
};
static LIST_HEAD (my_list);
static int __init skeleton_init(void)
{
int i;
pr_info ("Linux module 04 skeleton loaded\n");
pr_info (" text: %s\n elements: %d\n", text, elements);
for (i = 0; i < elements; i++) {
struct element* ele = kzalloc (sizeof(*ele), GFP_KERNEL);
if (ele != 0) {
strncpy (ele->text, text, 99);
ele->ele_nr = i;
list_add_tail (&ele->node, &my_list);
}
}
return 0;
}
static void __exit skeleton_exit(void)
{
struct element* ele;
int nb_eles = 0;
list_for_each_entry (ele, &my_list, node) {
pr_info ("ele [%d/%d/%d] = %s\n", nb_eles, ele->ele_nr, elements, ele->text);
nb_eles++;
}
while (!list_empty (&my_list)) {
ele = list_entry (my_list.next, struct element, node);
list_del (&ele->node);
kfree (ele);
}
pr_info ("All elements (%d/%d) of the list have been removed and deleted!\n", nb_eles, elements);
pr_info ("Linux module skeleton unloaded\n");
}
module_init (skeleton_init);
module_exit (skeleton_exit);
MODULE_AUTHOR ("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION ("Module skeleton");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,83 @@
/* skeleton.c */
#include <linux/module.h> /* needed by all modules */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/moduleparam.h> /* needed for module parameters */
#include <linux/slab.h> /* needed for dynamic memory allocation */
#include <linux/list.h> /* needed for linked list processing */
#include <linux/string.h> /* needed for string handling */
#include <linux/ioport.h> /* needed for memory region handling */
#include <linux/io.h> /* needed for mmio handling */
static struct resource* res[3]={[0]=0,};
static int __init skeleton_init(void)
{
unsigned char* regs[3]={[0]=0,};
unsigned int chipid[4]={[0]=0,};
long temp = 0;
unsigned int addr[2] = {[0]=0,};
pr_info ("Linux module 05 skeleton loaded\n");
res[0] = request_mem_region (0x01c14000, 0x1000, "allwiner h5 sid");
//res[1] = request_mem_region (0x01C25000, 0x1000, "allwiner h5 ths");
//res[2] = request_mem_region (0x01C30000, 0x1000, "allwiner h5 emac");
if ((res[0] == 0))// || (res[1] == 0) ||(res[2] == 0))
pr_info ("Error while reserving memory region... [0]=%d, [1]=%d, [2]=%d\n", res[0]==0, res[1]==0, res[2]==0);
regs[0] = ioremap (0x01c14000, 0x1000);
regs[1] = ioremap (0x01C25000, 0x1000);
regs[2] = ioremap (0x01C30000, 0x1000);
if ((regs[0] == 0) || (regs[1] == 0) ||(regs[2] == 0)) {
pr_info ("Error while trying to map processor register...\n");
return -EFAULT;
}
chipid[0] = ioread32 (regs[0]+0x200);
chipid[1] = ioread32 (regs[0]+0x204);
chipid[2] = ioread32 (regs[0]+0x208);
chipid[3] = ioread32 (regs[0]+0x20c);
pr_info("chipid=%08x'%08x'%08x'%08x\n",
chipid[0], chipid[1], chipid[2], chipid[3]);
temp = -1191 * (int)ioread32(regs[1]+0x80) / 10 + 223000;
pr_info ("temperature=%ld (%d)\n", temp, ioread32(regs[1]+0x80));
addr[0]=ioread32(regs[2]+0x50);
addr[1]=ioread32(regs[2]+0x54);
pr_info("mac-addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
(addr[1]>> 0) & 0xff,
(addr[1]>> 8) & 0xff,
(addr[1]>>16) & 0xff,
(addr[1]>>24) & 0xff,
(addr[0]>> 0) & 0xff,
(addr[0]>> 8) & 0xff
);
iounmap (regs[0]);
iounmap (regs[1]);
iounmap (regs[2]);
return 0;
}
static void __exit skeleton_exit(void)
{
pr_info ("Linux module skeleton unloaded\n");
if (res[0] != 0) release_mem_region (0x01c14000, 0x1000);
//release_mem_region (0x01C25000, 0x1000);
//release_mem_region (0x01C30000, 0x1000);
}
module_init (skeleton_init);
module_exit (skeleton_exit);
MODULE_AUTHOR ("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION ("Module skeleton");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,55 @@
/* skeleton.c */
#include <linux/module.h> /* needed by all modules */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/moduleparam.h> /* needed for module parameters */
#include <linux/slab.h> /* needed for dynamic memory allocation */
#include <linux/list.h> /* needed for linked list processing */
#include <linux/string.h> /* needed for string handling */
#include <linux/ioport.h> /* needed for memory region handling */
#include <linux/io.h> /* needed for mmio handling */
#include <linux/kthread.h> /* needed for kernel thread management */
#include <linux/delay.h> /* needed for delay fonctions */
static struct task_struct* my_thread;
static int skeleton_thread (void* data)
{
pr_info ("skeleton thread is now active...\n");
while(!kthread_should_stop()) {
ssleep (5);
pr_info ("skeleton thread is kick every 5 seconds...\n");
}
return 0;
}
static int __init skeleton_init(void)
{
pr_info ("Linux module 06 skeleton loaded\n");
my_thread = kthread_run (skeleton_thread, 0, "s/thread");
return 0;
}
static void __exit skeleton_exit(void)
{
kthread_stop (my_thread);
pr_info ("Linux module skeleton unloaded\n");
}
module_init (skeleton_init);
module_exit (skeleton_exit);
MODULE_AUTHOR ("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION ("Module skeleton");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,81 @@
/* skeleton.c */
#include <linux/module.h> /* needed by all modules */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/kthread.h> /* needed for kernel thread management */
#include <linux/wait.h> /* needed for waitqueues handling */
#include <linux/delay.h> /* needed for delay fonctions */
static struct task_struct* my_thread[2];
DECLARE_WAIT_QUEUE_HEAD (queue_1);
static atomic_t is_kicked;
static int skeleton_thread_1 (void* data)
{
pr_info ("skeleton thread_1 is now active...\n");
while(!kthread_should_stop()) {
int status = wait_event_interruptible
(queue_1, (atomic_read(&is_kicked) != 0)
|| kthread_should_stop());
if (status == -ERESTARTSYS) {
pr_info ("skeleton thread_1 has been interrupted\n");
break;
}
atomic_dec (&is_kicked);
pr_info ("skeleton thread_1 has been kicked\n");
}
return 0;
}
static int skeleton_thread_2 (void* data)
{
wait_queue_head_t queue;
pr_info ("skeleton thread_2 is now active...\n");
init_waitqueue_head (&queue);
while(!kthread_should_stop()) {
ssleep(5);
/*
int status = wait_event_interruptible_timeout
(queue, kthread_should_stop(), 5*HZ);
if (status == -ERESTARTSYS) {
pr_info ("skeleton thread_2 has been interrupted\n");
break;
}
*/
pr_info ("skeleton thread_2 timout elapsed...\n");
atomic_set (&is_kicked, 1);
wake_up_interruptible (&queue_1);
}
return 0;
}
static int __init skeleton_init(void)
{
pr_info ("Linux module 07 skeleton loaded\n");
atomic_set (&is_kicked, 0);
my_thread[0] = kthread_run (skeleton_thread_1, 0, "s/thread/%d", 1);
my_thread[1] = kthread_run (skeleton_thread_2, 0, "s/thread/2");
return 0;
}
static void __exit skeleton_exit(void)
{
kthread_stop (my_thread[1]);
kthread_stop (my_thread[0]);
pr_info ("Linux module skeleton unloaded\n");
}
module_init (skeleton_init);
module_exit (skeleton_exit);
MODULE_AUTHOR ("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION ("Module skeleton");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,74 @@
/* skeleton.c */
#include <linux/module.h> /* needed by all modules */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/interrupt.h> /* needed for interrupt handling */
#include <linux/gpio.h> /* needed for i/o handling */
#define K1 0
#define K2 2
#define K3 3
static char* k1="gpio_a.0-k1";
static char* k2="gpio_a.2-k2";
static char* k3="gpio_a.3-k3";
irqreturn_t gpio_isr(int irq, void* handle)
{
pr_info ("interrupt %s raised...\n", (char*)handle);
return IRQ_HANDLED;
}
static int __init skeleton_init(void)
{
int status = 0;
// install k1
if (status == 0) status = gpio_request (K1, "k1");
if (status == 0)
status = request_irq(gpio_to_irq(K1), gpio_isr,
IRQF_TRIGGER_FALLING | IRQF_SHARED, k1, k1);
// install k2
if (status == 0) status = gpio_request (K2, "k2");
if (status == 0)
status = request_irq(gpio_to_irq(K2), gpio_isr,
IRQF_TRIGGER_FALLING | IRQF_SHARED, k2, k2);
// install k3
if (status == 0) status = gpio_request (K3, "k3");
if (status == 0)
status = request_irq(gpio_to_irq(K3), gpio_isr,
IRQF_TRIGGER_FALLING | IRQF_SHARED, k3, k3);
pr_info ("Linux module 08 skeleton loaded\n");
return status;
}
static void __exit skeleton_exit(void)
{
gpio_free(K1);
free_irq(gpio_to_irq(K1), k1);
gpio_free(K2);
free_irq(gpio_to_irq(K2), k2);
gpio_free(K3);
free_irq(gpio_to_irq(K3), k3);
pr_info ("Linux module skeleton unloaded\n");
}
module_init (skeleton_init);
module_exit (skeleton_exit);
MODULE_AUTHOR ("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION ("Module skeleton");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,50 @@
EXE=procstat
SRCS=$(wildcard *.c)
ifeq ($(TARGET), host)
CC=gcc
LD=gcc
STRIP=strip
CFLAGS=-Wall -Wextra -g -c -O0 -MD -std=c99
OBJDIR=.obj/host
EXEC=$(EXE)_h
else
TOOLCHAIN_PATH=/buildroot/output/host/usr/bin/
TOOLCHAIN=$(TOOLCHAIN_PATH)aarch64-buildroot-linux-gnu-
CC=$(TOOLCHAIN)gcc
LD=$(TOOLCHAIN)gcc
STRIP=$(TOOLCHAIN)strip
CFLAGS+=-pedantic -Wall -Wextra -g -c -mcpu=cortex-a53 -O0 -MD -std=gnu11
CPPFLAGS+=-pedantic -Wall -Wextra -g -c -mcpu=cortex-a53 -O0 -MD -std=gnu11
OBJDIR=.obj/odroid
EXEC=$(EXE)
endif
OBJS= $(addprefix $(OBJDIR)/, $(ASRC:.s=.o) $(SRCS:.c=.o))
all: $(OBJDIR)/ $(EXEC)
$(EXEC): $(OBJS) $(LINKER_SCRIPT)
$(LD) $(OBJS) $(LDFLAGS) -o $@_s
$(STRIP) -g -o $@ $@_s
$(OBJDIR)/%o: %c
$(CC) $(CFLAGS) $< -o $@
$(OBJDIR)/:
mkdir -p $(OBJDIR)
clean:
rm -Rf $(OBJDIR) $(EXEC) $(EXEC)_s
clean_all:
rm -Rf .obj $(EXE) $(EXE)_h $(EXE)_s $(EXE)_h_s *~
.PHONY: all clean clean_all
-include $(OBJS:.o=.d)

View File

@@ -0,0 +1,240 @@
/*
* Displays linux /proc/pid/stat in human-readable format
*
* Build: gcc -o procstat procstat.c
* Usage: procstat pid
* cat /proc/pid/stat | procstat
*
* Homepage: http://www.brokestream.com/procstat.html
* Version : 2009-03-05
*
* Ivan Tikhonov, http://www.brokestream.com, kefeer@netangels.ru
*
* 2007-09-19 changed HZ=100 error to warning
*
* 2009-03-05 tickspersec are taken from sysconf (Sabuj Pattanayek)
*
*/
/* Copyright (C) 2009 Ivan Tikhonov
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Ivan Tikhonov, kefeer@brokestream.com
*/
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <linux/limits.h>
#include <sys/times.h>
typedef long long int num;
num pid;
char tcomm[PATH_MAX];
char state;
num ppid;
num pgid;
num sid;
num tty_nr;
num tty_pgrp;
num flags;
num min_flt;
num cmin_flt;
num maj_flt;
num cmaj_flt;
num utime;
num stimev;
num cutime;
num cstime;
num priority;
num nicev;
num num_threads;
num it_real_value;
unsigned long long start_time;
num vsize;
num rss;
num rsslim;
num start_code;
num end_code;
num start_stack;
num esp;
num eip;
num pending;
num blocked;
num sigign;
num sigcatch;
num wchan;
num zero1;
num zero2;
num exit_signal;
num cpu;
num rt_priority;
num policy;
long tickspersec;
FILE *input;
void readone(num *x) { fscanf(input, "%lld ", x); }
void readunsigned(unsigned long long *x) { fscanf(input, "%llu ", x); }
void readstr(char *x) { fscanf(input, "%s ", x);}
void readchar(char *x) { fscanf(input, "%c ", x);}
void printone(char *name, num x) { printf("%20s: %lld\n", name, x);}
void printonex(char *name, num x) { printf("%20s: %016llx\n", name, x);}
void printunsigned(char *name, unsigned long long x) { printf("%20s: %llu\n", name, x);}
void printchar(char *name, char x) { printf("%20s: %c\n", name, x);}
void printstr(char *name, char *x) { printf("%20s: %s\n", name, x);}
void printtime(char *name, num x) { printf("%20s: %f\n", name, (((double)x) / tickspersec));}
int gettimesinceboot() {
FILE *procuptime;
int sec, ssec;
procuptime = fopen("/proc/uptime", "r");
fscanf(procuptime, "%d.%ds", &sec, &ssec);
fclose(procuptime);
return (sec*tickspersec)+ssec;
}
void printtimediff(char *name, num x) {
int sinceboot = gettimesinceboot();
int running = sinceboot - x;
time_t rt = time(NULL) - (running / tickspersec);
char buf[1024];
strftime(buf, sizeof(buf), "%m.%d %H:%M", localtime(&rt));
printf("%20s: %s (%lu.%lus)\n", name, buf, running / tickspersec, running % tickspersec);
}
int main(int argc, char *argv[]) {
tickspersec = sysconf(_SC_CLK_TCK);
input = NULL;
if(argc > 1) {
chdir("/proc");
if(chdir(argv[1]) == 0) { input = fopen("stat", "r"); }
if(!input) {
perror("open");
return 1;
}
} else {
input = stdin;
}
readone(&pid);
readstr(tcomm);
readchar(&state);
readone(&ppid);
readone(&pgid);
readone(&sid);
readone(&tty_nr);
readone(&tty_pgrp);
readone(&flags);
readone(&min_flt);
readone(&cmin_flt);
readone(&maj_flt);
readone(&cmaj_flt);
readone(&utime);
readone(&stimev);
readone(&cutime);
readone(&cstime);
readone(&priority);
readone(&nicev);
readone(&num_threads);
readone(&it_real_value);
readunsigned(&start_time);
readone(&vsize);
readone(&rss);
readone(&rsslim);
readone(&start_code);
readone(&end_code);
readone(&start_stack);
readone(&esp);
readone(&eip);
readone(&pending);
readone(&blocked);
readone(&sigign);
readone(&sigcatch);
readone(&wchan);
readone(&zero1);
readone(&zero2);
readone(&exit_signal);
readone(&cpu);
readone(&rt_priority);
readone(&policy);
{
printone("pid", pid);
printstr("tcomm", tcomm);
printchar("state", state);
printone("ppid", ppid);
printone("pgid", pgid);
printone("sid", sid);
printone("tty_nr", tty_nr);
printone("tty_pgrp", tty_pgrp);
printone("flags", flags);
printone("min_flt", min_flt);
printone("cmin_flt", cmin_flt);
printone("maj_flt", maj_flt);
printone("cmaj_flt", cmaj_flt);
printtime("utime", utime);
printtime("stime", stimev);
printtime("cutime", cutime);
printtime("cstime", cstime);
printone("priority", priority);
printone("nice", nicev);
printone("num_threads", num_threads);
printtime("it_real_value", it_real_value);
printtimediff("start_time", start_time);
printone("vsize", vsize);
printone("rss", rss);
printone("rsslim", rsslim);
printone("start_code", start_code);
printone("end_code", end_code);
printone("start_stack", start_stack);
printone("esp", esp);
printone("eip", eip);
printonex("pending", pending);
printonex("blocked", blocked);
printonex("sigign", sigign);
printonex("sigcatch", sigcatch);
printone("wchan", wchan);
printone("zero1", zero1);
printone("zero2", zero2);
printonex("exit_signal", exit_signal);
printone("cpu", cpu);
printone("rt_priority", rt_priority);
printone("policy", policy);
}
return 0;
}

5
src/03_drivers/Makefile Normal file
View File

@@ -0,0 +1,5 @@
DIRS=$(filter-out Makefile, $(wildcard *))
all clean install:
for dir in $(DIRS); do $(MAKE) $@ -C $$dir; done

View File

@@ -0,0 +1,37 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
ccflags-y += -Wno-declaration-after-statement -std=gnu11
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
INCL+=-I. -I$(KDIR)/include -I$(KDIR)/arch/arm64/boot/dts
DTB = mydt.dtb
DTS = $(DTB:.dtb=.dts)
all: dtb boot
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
dtb: $(DTB)
$(DTB) : $(DTS)
ln -s $(KDIR)/arch/arm/boot/dts arm
-cpp $(INCL) -E -P -x assembler-with-cpp $(DTS) | dtc -I dts -O dtb -o $(DTB) -
rm arm
boot:
mkimage -T script -A arm -C none -d boot.cmd boot.ovl
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
rm -f *.dtb *.ovl
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,10 @@
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
fatload mmc 0 $kernel_addr_r Image
#fatload mmc 0 $fdt_addr_r nanopi-neo-plus2.dtb
fatload mmc 0 $fdt_addr_r mydt.dtb
fdt addr $fdt_addr_r
fdt resize
booti $kernel_addr_r - $fdt_addr_r

View File

@@ -0,0 +1,12 @@
/dts-v1/;
#include "allwinner/sun50i-h5-nanopi-neo-plus2.dts"
/ {
/delete-node/ leds;
mydevice {
compatible = "mydevice";
attribute = "text";
};
};

View File

@@ -0,0 +1,135 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
static int skeleton_open(struct inode* i, struct file* f)
{
pr_info("skeleton : open operation... major:%d, minor:%d\n",
imajor(i),
iminor(i));
return 0;
}
static int skeleton_release(struct inode* i, struct file* f)
{
pr_info("skeleton: release operation...\n");
return 0;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
pr_info("skeleton: read operation... read=%ld\n", count);
return 0;
}
static ssize_t skeleton_write(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
pr_info("skeleton: write operation... written=%ld\n", count);
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
struct miscdevice misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.fops = &fops,
.name = "mydevice",
.mode = 0777,
};
int skeleton_probe(struct platform_device* pdev)
{
pr_info("skeleton - driver probe %llx (%s)- M.m=%d.%d\n",
(unsigned long long)pdev,
pdev->name,
MAJOR(pdev->dev.devt),
MINOR(pdev->dev.devt));
// register misc device ...
int ret = misc_register(&misc_device);
// read device tree attribute
struct device_node* dt_node = pdev->dev.of_node;
const char* prop = 0;
if (dt_node)
ret = of_property_read_string(dt_node, "attribute", &prop);
else
pr_info("mymodule not found!\n");
if ((prop != 0) && (ret == 0))
pr_info("attribute=%s (ret=%d)\n", prop, ret);
return 0;
}
int skeleton_remove(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver remove %llx\n", (unsigned long long)pdev);
misc_deregister(&misc_device);
return 0;
}
void skeleton_shutdown(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver shutdown %s\n", pdev->name);
}
struct of_device_id of_skeleton[] = {
{
.compatible = "mydevice",
},
{},
};
MODULE_DEVICE_TABLE(of, of_skeleton);
static struct platform_driver sysfs_driver = {
.probe = skeleton_probe,
.remove = skeleton_remove,
.shutdown = skeleton_shutdown,
.driver =
{
.name = "mydriver",
.of_match_table = of_match_ptr(of_skeleton),
},
};
static int __init skeleton_init(void)
{
pr_info("Linux module skeleton loading...\n");
int status = platform_driver_register(&sysfs_driver);
pr_info("Linux module skeleton loaded\n");
return status;
}
static void __exit skeleton_exit(void)
{
pr_info("Linux module skeleton exiting...\n");
platform_driver_unregister(&sysfs_driver);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,44 @@
EXE=app
SRCS=$(wildcard *.c)
ifeq ($(target),)
target=nano
endif
CFLAGS=-Wall -Wextra -g -c -O0 -MD -std=gnu11
TOOLCHAIN_PATH=/buildroot/output/host/usr/bin/
TOOLCHAIN=$(TOOLCHAIN_PATH)aarch64-linux-
CFLAGS+=-mcpu=cortex-a53 -funwind-tables
##CFLAGS+=-O2 -fno-omit-frame-pointer
OBJDIR=.obj/nano
EXEC=$(EXE)
CC=$(TOOLCHAIN)gcc
LD=$(TOOLCHAIN)gcc
AR=$(TOOLCHAIN)ar
STRIP=$(TOOLCHAIN)strip
OBJDIR=.obj/$(target)
OBJS= $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
$(OBJDIR)/%o: %c
$(CC) $(CFLAGS) $< -o $@
all: $(OBJDIR)/ $(EXEC)
$(EXEC): $(OBJS) $(LINKER_SCRIPT)
$(LD) $(OBJS) $(LDFLAGS) -o $@
$(OBJDIR)/:
mkdir -p $(OBJDIR)
clean:
rm -Rf $(OBJDIR) $(EXEC) $(EXEC)_s *~
clean_all: clean
rm -Rf .obj $(EXE) $(EXE)_s $(EXE)_a $(EXE)_a_s $(EXE)_h $(EXE)_h_s
-include $(OBJS:.o=.d)
.PHONY: all clean clean_all

View File

@@ -0,0 +1,53 @@
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/mman.h>
#include <unistd.h>
int main()
{
/* open memory file descriptor */
int fd = open("/dev/mem", O_RDWR);
if (fd < 0) {
printf("Could not open /dev/mem: error=%i\n", fd);
return -1;
}
size_t psz = getpagesize();
off_t dev_addr = 0x01c14200;
off_t ofs = dev_addr % psz;
off_t offset = dev_addr - ofs;
printf(
"psz=%lx, addr=%lx, offset=%lx, ofs=%lx\n", psz, dev_addr, offset, ofs);
/* map to user space nanopi internal registers */
volatile uint32_t* regs =
mmap(0, psz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
if (regs == MAP_FAILED) // (void *)-1
{
printf("mmap failed, error: %i:%s \n", errno, strerror(errno));
return -1;
}
uint32_t chipid[4] = {
[0] = *(regs + (ofs + 0x00) / sizeof(uint32_t)),
[1] = *(regs + (ofs + 0x04) / sizeof(uint32_t)),
[2] = *(regs + (ofs + 0x08) / sizeof(uint32_t)),
[3] = *(regs + (ofs + 0x0c) / sizeof(uint32_t)),
};
printf("NanoPi NEO Plus2 chipid=%08x'%08x'%08x'%08x\n",
chipid[0],
chipid[1],
chipid[2],
chipid[3]);
munmap((void*)regs, psz);
close(fd);
return 0;
}

View File

@@ -0,0 +1,23 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../buildroot_path
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,123 @@
/* skeleton.c */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/moduleparam.h> /* needed for module parameters */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#define BUFFER_SZ 10000
static char s_buffer[BUFFER_SZ];
static dev_t skeleton_dev;
static struct cdev skeleton_cdev;
static int skeleton_open(struct inode* i, struct file* f)
{
pr_info("skeleton : open operation... major:%d, minor:%d\n",
imajor(i),
iminor(i));
if ((f->f_flags & (O_APPEND)) != 0) {
pr_info("skeleton : opened for appending...\n");
}
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) != 0) {
pr_info("skeleton : opened for reading & writing...\n");
} else if ((f->f_mode & FMODE_READ) != 0) {
pr_info("skeleton : opened for reading...\n");
} else if ((f->f_mode & FMODE_WRITE) != 0) {
pr_info("skeleton : opened for writing...\n");
}
return 0;
}
static int skeleton_release(struct inode* i, struct file* f)
{
pr_info("skeleton: release operation...\n");
return 0;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
// compute remaining bytes to copy, update count and pointers
ssize_t remaining = BUFFER_SZ - (ssize_t)(*off);
char* ptr = s_buffer + *off;
if (count > remaining) count = remaining;
*off += count;
// copy required number of bytes
if (copy_to_user(buf, ptr, count) != 0) count = -EFAULT;
pr_info("skeleton: read operation... read=%ld\n", count);
return count;
}
static ssize_t skeleton_write(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
// compute remaining space in buffer and update pointers
ssize_t remaining = BUFFER_SZ - (ssize_t)(*off);
pr_info("skeleton: at%ld\n", (unsigned long)(*off));
// check if still remaining space to store additional bytes
if (count >= remaining) count = -EIO;
// store additional bytes into internal buffer
if (count > 0) {
char* ptr = s_buffer + *off;
*off += count;
ptr[count] = 0; // make sure string is null terminated
if (copy_from_user(ptr, buf, count)) count = -EFAULT;
}
pr_info("skeleton: write operation... written=%ld\n", count);
return count;
}
static struct file_operations skeleton_fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
static int __init skeleton_init(void)
{
int status = alloc_chrdev_region(&skeleton_dev, 0, 1, "mymodule");
if (status == 0) {
cdev_init(&skeleton_cdev, &skeleton_fops);
skeleton_cdev.owner = THIS_MODULE;
status = cdev_add(&skeleton_cdev, skeleton_dev, 1);
}
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit skeleton_exit(void)
{
cdev_del(&skeleton_cdev);
unregister_chrdev_region(skeleton_dev, 1);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,23 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../buildroot_path
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,147 @@
/* skeleton.c */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/moduleparam.h> /* needed for module parameters */
#include <linux/slab.h> /* needed for dynamic memory management */
#include <linux/uaccess.h> /* needed to copy data to/from user */
static int instances = 3;
module_param(instances, int, 0);
#define BUFFER_SZ 10000
static char** buffers = 0;
static int skeleton_open(struct inode* i, struct file* f)
{
pr_info("skeleton : open operation... major:%d, minor:%d\n",
imajor(i),
iminor(i));
if (iminor(i) >= instances) {
return -EFAULT;
}
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) != 0) {
pr_info("skeleton : opened for reading & writing...\n");
} else if ((f->f_mode & FMODE_READ) != 0) {
pr_info("skeleton : opened for reading...\n");
} else if ((f->f_mode & FMODE_WRITE) != 0) {
pr_info("skeleton : opened for writing...\n");
}
f->private_data = buffers[iminor(i)];
pr_info("skeleton: private_data=%p\n", f->private_data);
return 0;
}
static int skeleton_release(struct inode* i, struct file* f)
{
pr_info("skeleton: release operation...\n");
return 0;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
// compute remaining bytes to copy, update count and pointers
ssize_t remaining = BUFFER_SZ - (ssize_t)(*off);
char* ptr = (char*)f->private_data + *off;
if (count > remaining) count = remaining;
*off += count;
// copy required number of bytes
if (copy_to_user(buf, ptr, count) != 0) count = -EFAULT;
pr_info("skeleton: read operation... read=%ld\n", count);
return count;
}
static ssize_t skeleton_write(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
// compute remaining space in buffer and update pointers
ssize_t remaining = BUFFER_SZ - (ssize_t)(*off);
// check if still remaining space to store additional bytes
if (count >= remaining) count = -EIO;
// store additional bytes into internal buffer
if (count > 0) {
char* ptr = f->private_data + *off;
*off += count;
ptr[count] = 0; // make sure string is null terminated
if (copy_from_user(ptr, buf, count)) count = -EFAULT;
}
pr_info("skeleton: write operation... private_data=%p, written=%ld\n",
f->private_data,
count);
return count;
}
static struct file_operations skeleton_fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
static dev_t skeleton_dev;
static struct cdev skeleton_cdev;
static int __init skeleton_init(void)
{
int i;
int status = -EFAULT;
if (instances <= 0) return -EFAULT;
status = alloc_chrdev_region(&skeleton_dev, 0, instances, "mymodule");
if (status == 0) {
cdev_init(&skeleton_cdev, &skeleton_fops);
skeleton_cdev.owner = THIS_MODULE;
status = cdev_add(&skeleton_cdev, skeleton_dev, instances);
}
if (status == 0) {
buffers = kzalloc(sizeof(char*) * instances, GFP_KERNEL);
for (i = 0; i < instances; i++)
buffers[i] = kzalloc(BUFFER_SZ, GFP_KERNEL);
}
pr_info("Linux module skeleton loaded\n");
pr_info("The number of instances: %d\n", instances);
return status;
}
static void __exit skeleton_exit(void)
{
int i;
cdev_del(&skeleton_cdev);
unregister_chrdev_region(skeleton_dev, instances);
for (i = 0; i < instances; i++) kfree(buffers[i]);
kfree(buffers);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,37 @@
EXEC=app
SRCS=$(wildcard *.c)
TOOLCHAIN_PATH=/buildroot/output/host/usr/bin/
TOOLCHAIN=$(TOOLCHAIN_PATH)aarch64-linux-
CFLAGS+=-Wall -Wextra -g -c -O0 -MD -std=gnu11
CFLAGS+=-mcpu=cortex-a53 -funwind-tables
OBJDIR=.obj
CC=$(TOOLCHAIN)gcc
LD=$(TOOLCHAIN)gcc
AR=$(TOOLCHAIN)ar
STRIP=$(TOOLCHAIN)strip
OBJS+=$(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
.PHONY: all clean
$(OBJDIR)/%o: %c
$(CC) $(CFLAGS) $< -o $@
all: $(OBJDIR)/ $(EXEC)
clean: $(EXTRA_CLEAN)
rm -Rf .obj
rm -Rf $(EXEC) *.map *~
$(EXEC): $(OBJS) $(LINKER_SCRIPT)
$(LD) $(OBJS) $(LDFLAGS) -o $@
$(OBJDIR)/:
mkdir -p $(OBJDIR)
-include $(OBJS:.o=.d)

View File

@@ -0,0 +1,47 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static const char* text =
"\n"
"bonjour le monde\n"
"ce mois d'octobre est plutot humide...\n"
"ce n'est qu'un petit texte de test...\n";
static const char* text2 =
"\n"
"et voici un complement au premier text..\n"
"ce n'est qu'un deuxieme petit texte de test...\n";
static const char* blabla =
"blabla blabla blabla blabla blabla blabla blabla\n";
int main(int argc, char* argv[])
{
if (argc <= 1) return 0;
int fdw = open(argv[1], O_RDWR);
write(fdw, argv[1], strlen(argv[1]));
write(fdw, text, strlen(text));
write(fdw, text2, strlen(text2));
int s;
do {
s = write(fdw, blabla, strlen(blabla));
} while (s >= 0);
close(fdw);
int fdr = open(argv[1], O_RDONLY);
while (1) {
char buff[100];
ssize_t sz = read(fdr, buff, sizeof(buff) - 1);
if (sz <= 0) break;
buff[sizeof(buff) - 1] = 0;
printf("%s", buff);
}
close(fdr);
return 0;
}

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,249 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
//#define MISC
//#define PLATFORM
#define CLASS
struct skeleton_config {
int id;
long ref;
char name[30];
char descr[30];
};
static struct skeleton_config config;
static int val;
ssize_t sysfs_show_val(struct device* dev,
struct device_attribute* attr,
char* buf)
{
sprintf(buf, "%d\n", val);
return strlen(buf);
}
ssize_t sysfs_store_val(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
val = simple_strtol(buf, 0, 10);
return count;
}
DEVICE_ATTR(val, 0664, sysfs_show_val, sysfs_store_val);
ssize_t sysfs_show_cfg(struct device* dev,
struct device_attribute* attr,
char* buf)
{
sprintf(buf,
"%d %ld %s %s\n",
config.id,
config.ref,
config.name,
config.descr);
return strlen(buf);
}
ssize_t sysfs_store_cfg(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
sscanf(buf,
"%d %ld %s %s",
&config.id,
&config.ref,
config.name,
config.descr);
return count;
}
DEVICE_ATTR(cfg, 0664, sysfs_show_cfg, sysfs_store_cfg);
#define BUFFER_SZ 10000
static char s_buffer[BUFFER_SZ];
static dev_t skeleton_dev;
static struct cdev skeleton_cdev;
static int skeleton_open(struct inode* i, struct file* f)
{
pr_info("skeleton : open operation... major:%d, minor:%d\n",
imajor(i),
iminor(i));
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) != 0) {
pr_info("skeleton : opened for reading & writing...\n");
} else if ((f->f_mode & FMODE_READ) != 0) {
pr_info("skeleton : opened for reading...\n");
} else if ((f->f_mode & FMODE_WRITE) != 0) {
pr_info("skeleton : opened for writing...\n");
}
return 0;
}
static int skeleton_release(struct inode* i, struct file* f)
{
pr_info("skeleton: release operation...\n");
return 0;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
// compute remaining bytes to copy, update count and pointers
ssize_t remaining = BUFFER_SZ - (ssize_t)(*off);
char* ptr = s_buffer + *off;
if (count > remaining) count = remaining;
*off += count;
// copy required number of bytes
if (copy_to_user(buf, ptr, count) != 0) count = -EFAULT;
pr_info("skeleton: read operation... read=%ld\n", count);
return count;
}
static ssize_t skeleton_write(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
// compute remaining space in buffer and update pointers
ssize_t remaining = BUFFER_SZ - (ssize_t)(*off);
// check if still remaining space to store additional bytes
if (count >= remaining) count = -EIO;
// store additional bytes into internal buffer
if (count > 0) {
char* ptr = s_buffer + *off;
*off += count;
ptr[count] = 0; // make sure string is null terminated
if (copy_from_user(ptr, buf, count)) count = -EFAULT;
}
pr_info("skeleton: write operation... written=%ld\n", count);
return count;
}
static struct file_operations skeleton_fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
#ifdef MISC
static struct miscdevice misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.fops = &fops
.name = "my_misc_module",
.mode = 0,
};
#endif
#ifdef PLATFORM
static void sysfs_dev_release (struct device *dev)
{
pr_info ("skeleton - sysfs dev release\n");
}
static struct platform_device platform_device = {
.name = "my_platform_module",
.id = -1,
.dev.release = sysfs_dev_release
};
#endif
#ifdef CLASS
static struct class* sysfs_class;
static struct device* sysfs_device;
#endif
static int __init skeleton_init(void)
{
int status = 0;
#ifndef MISC
status = alloc_chrdev_region(&skeleton_dev, 0, 1, "mymodule");
if (status == 0) {
cdev_init(&skeleton_cdev, &skeleton_fops);
skeleton_cdev.owner = THIS_MODULE;
status = cdev_add(&skeleton_cdev, skeleton_dev, 1);
}
#endif
#ifdef MISC
if (status == 0) status = misc_register(&misc_device);
if (status == 0) status = device_create_file(misc_device.this_device, &dev_attr_val);
if (status == 0) status = device_create_file(misc_device.this_device, &dev_attr_cfg);
#endif
#ifdef PLATFORM
platform_device.dev.devt = skeleton_dev;
if (status == 0) status = platform_device_register (&platform_device);
if (status == 0) status = device_create_file (&platform_device.dev, &dev_attr_val);
if (status == 0) status = device_create_file (&platform_device.dev, &dev_attr_cfg);
#endif
#ifdef CLASS
sysfs_class = class_create(THIS_MODULE, "my_sysfs_class");
sysfs_device = device_create(sysfs_class, NULL, skeleton_dev, NULL, "my_sysfs_device");
if (status == 0) status = device_create_file(sysfs_device, &dev_attr_val);
if (status == 0) status = device_create_file(sysfs_device, &dev_attr_cfg);
#endif
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit skeleton_exit(void)
{
#ifdef MISC
misc_deregister(&misc_device);
#endif
#ifdef PLATFORM
device_remove_file (&platform_device.dev, &dev_attr_cfg);
device_remove_file (&platform_device.dev, &dev_attr_val);
platform_device_unregister (&platform_device);
#endif
#ifdef CLASS
device_remove_file(sysfs_device, &dev_attr_val);
device_remove_file(sysfs_device, &dev_attr_cfg);
device_destroy(sysfs_class, 0);
class_destroy(sysfs_class);
#endif
#ifndef MISC
cdev_del(&skeleton_cdev);
unregister_chrdev_region(skeleton_dev, 1);
#endif
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,23 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../buildroot_path
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,153 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
//#define MISC
//#define PLATFORM
#define CLASS
struct skeleton_config {
int id;
long ref;
char name[30];
char descr[30];
};
static struct skeleton_config config;
static int val;
ssize_t sysfs_show_val(struct device* dev,
struct device_attribute* attr,
char* buf)
{
sprintf(buf, "%d\n", val);
return strlen(buf);
}
ssize_t sysfs_store_val(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
val = simple_strtol(buf, 0, 10);
return count;
}
DEVICE_ATTR(val, 0664, sysfs_show_val, sysfs_store_val);
ssize_t sysfs_show_cfg(struct device* dev,
struct device_attribute* attr,
char* buf)
{
sprintf(buf,
"%d %ld %s %s\n",
config.id,
config.ref,
config.name,
config.descr);
return strlen(buf);
}
ssize_t sysfs_store_cfg(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
sscanf(buf,
"%d %ld %s %s",
&config.id,
&config.ref,
config.name,
config.descr);
return count;
}
DEVICE_ATTR(cfg, 0664, sysfs_show_cfg, sysfs_store_cfg);
#ifdef MISC
static struct miscdevice misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mymodule",
.mode = 0,
};
#endif
#ifdef PLATFORM
static void sysfs_dev_release (struct device *dev)
{
pr_info ("skeleton - sysfs dev release\n");
}
static struct platform_device platform_device = {
.name = "mymodule",
.id = -1,
.dev.release = sysfs_dev_release
};
#endif
#ifdef CLASS
static struct class* sysfs_class;
static struct device* sysfs_device;
#endif
static int __init skeleton_init(void)
{
int status = 0;
#ifdef MISC
if (status == 0) status = misc_register(&misc_device);
if (status == 0) status = device_create_file(misc_device.this_device, &dev_attr_val);
if (status == 0) status = device_create_file(misc_device.this_device, &dev_attr_cfg);
#endif
#ifdef PLATFORM
if (status == 0) status = platform_device_register (&platform_device);
if (status == 0) status = device_create_file (&platform_device.dev, &dev_attr_val);
if (status == 0) status = device_create_file (&platform_device.dev, &dev_attr_cfg);
#endif
#ifdef CLASS
sysfs_class = class_create(THIS_MODULE, "my_sysfs_class");
sysfs_device = device_create(sysfs_class, NULL, 0, NULL, "my_sysfs_device");
if (status == 0) status = device_create_file(sysfs_device, &dev_attr_val);
if (status == 0) status = device_create_file(sysfs_device, &dev_attr_cfg);
#endif
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit skeleton_exit(void)
{
#ifdef MISC
misc_deregister(&misc_device);
#endif
#ifdef PLATFORM
device_remove_file (&platform_device.dev, &dev_attr_cfg);
device_remove_file (&platform_device.dev, &dev_attr_val);
platform_device_unregister (&platform_device);
#endif
#ifdef CLASS
device_remove_file(sysfs_device, &dev_attr_val);
device_remove_file(sysfs_device, &dev_attr_cfg);
device_destroy(sysfs_class, 0);
class_destroy(sysfs_class);
#endif
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,36 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
INCL+=-I. -I$(KDIR)/include -I$(KDIR)/arch/arm64/boot/dts
DTB = mydt.dtb
DTS = $(DTB:.dtb=.dts)
all: dtb boot
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
dtb: $(DTB)
$(DTB) : $(DTS)
ln -s $(KDIR)/arch/arm/boot/dts arm
-cpp $(INCL) -E -P -x assembler-with-cpp $(DTS) | dtc -I dts -O dtb -o $(DTB) -
rm arm
boot:
mkimage -T script -A arm -C none -d boot.cmd boot.ovl
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
rm -f *.dtb *.ovl
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,13 @@
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
fatload mmc 0 $kernel_addr_r Image
#fatload mmc 0 $fdt_addr_r sun50i-h5-nanopi-neo-plus2.dtb
fatload mmc 0 $fdt_addr_r mydt.dtb
fdt addr $fdt_addr_r
fdt resize
#fdt mknode / mymodule2
#fdt set /mymodule2 compatible mymodule2
booti $kernel_addr_r - $fdt_addr_r

View File

@@ -0,0 +1,34 @@
/dts-v1/;
#include "allwinner/sun50i-h5-nanopi-neo-plus2.dts"
/ {
/delete-node/ leds;
mydevice {
compatible = "mydevice";
#address-cells = <1>;
#size-cells = <0>;
attribute = "idle";
mydevice@0 {
reg = <0x0>;
attribute = "on";
};
mydevice@1 {
reg = <0x1>;
attribute = "off";
};
mydevice@2 {
reg = <0x2>;
attribute = "off";
};
mydevice@3 {
reg = <0x3>;
attribute = "off";
};
};
};

View File

@@ -0,0 +1,253 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/list.h> /* needed for linked list processing */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
#define BUFFER_SZ 10000
struct mydata {
char buffer[BUFFER_SZ];
struct miscdevice misc;
struct list_head node;
};
static int skeleton_open(struct inode* i, struct file* f)
{
pr_info("skeleton : open operation... major:%d, minor:%d, p_data=%llx\n",
imajor(i),
iminor(i),
(long long)f->private_data);
return 0;
}
static int skeleton_release(struct inode* i, struct file* f)
{
pr_info("skeleton: release operation...p_data=%llx\n",
(long long)f->private_data);
return 0;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
struct mydata* mydata = container_of(f->private_data, struct mydata, misc);
// compute remaining bytes to copy, update count and pointers
ssize_t remaining = strlen(mydata->buffer) - (ssize_t)(*off);
char* ptr = mydata->buffer + *off;
if (count > remaining) count = remaining;
*off += count;
// copy required number of bytes
if (copy_to_user(buf, ptr, count) != 0) count = -EFAULT;
pr_info("skeleton: read operation...p_data=%llx read=%ld\n",
(long long)f->private_data,
count);
return count;
}
static ssize_t skeleton_write(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
struct mydata* mydata = container_of(f->private_data, struct mydata, misc);
// compute remaining space in buffer and update pointers
ssize_t remaining = sizeof(mydata->buffer) - (ssize_t)(*off);
char* ptr = mydata->buffer + *off;
*off += count;
// check if still remaining space to store additional bytes
if (count >= remaining) count = -EIO;
// store additional bytes into internal buffer
if (count > 0) {
ptr[count] = 0; // make sure string is null terminated
if (copy_from_user(ptr, buf, count)) count = -EFAULT;
}
pr_info("skeleton: write operation... written=%ld\n", count);
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
int drv_probe(struct platform_device* pdev)
{
int ret = 0;
struct device_node* dt_node = pdev->dev.of_node;
struct mydata* mydata = 0;
const char* prop_str = 0;
pr_info("skeleton - driver probe %llx (%s)- M.m=%d.%d, dtnode=%p\n",
(unsigned long long)pdev,
pdev->name,
MAJOR(pdev->dev.devt),
MINOR(pdev->dev.devt),
dt_node);
ret = of_property_read_string(dt_node, "attribute", &prop_str);
if (prop_str && ret == 0) pr_info("attribute=%s (ret=%d)\n", prop_str, ret);
if (pdev->num_resources) {
pr_info("resources: name=%s, start=%lld, end=%lld\n",
pdev->resource[0].name,
pdev->resource[0].start,
pdev->resource[0].end);
}
if (dt_node) {
int ret = 0;
const char* prop_str = 0;
const unsigned int* prop_reg = 0;
struct device_node* child = 0;
struct list_head* list = devm_kzalloc(&pdev->dev, sizeof(struct list_head), GFP_KERNEL);
if (list == 0) {
dev_err(&pdev->dev,
"Failed to allocate resource for miscdev\n");
return -ENOMEM;
}
INIT_LIST_HEAD(list);
platform_set_drvdata(pdev, list);
for_each_available_child_of_node(dt_node, child)
{
mydata = devm_kzalloc(&pdev->dev, sizeof(*mydata), GFP_KERNEL);
pr_info("miscdev=%llx\n", (long long)mydata);
if (mydata == 0) {
dev_err(&pdev->dev,
"Failed to allocate resource for miscdev\n");
return -ENOMEM;
}
list_add_tail (&(mydata->node), list);
pr_info("child found: name=%s, fullname=%s\n",
child->name,
child->full_name);
prop_reg = of_get_property(child, "reg", NULL);
if (prop_reg != 0) {
unsigned long reg = of_read_ulong(prop_reg, 1);
pr_info("reg:%lu\n", reg);
}
ret = of_property_read_string(child, "attribute", &prop_str);
if (prop_str && ret == 0)
pr_info("attribute=%s (ret=%d)\n", prop_str, ret);
/* register misc device ... */
mydata->misc.minor = MISC_DYNAMIC_MINOR;
mydata->misc.fops = &fops;
mydata->misc.name = child->full_name;
mydata->misc.mode = 0664;
ret = misc_register(&(mydata->misc));
if (ret != 0) {
dev_err(&pdev->dev, "Failed to register miscdev\n");
return ret;
}
}
}
return 0;
}
int drv_remove(struct platform_device* pdev)
{
struct mydata* mydata;
struct list_head* list = platform_get_drvdata(pdev);
pr_info("skeleton - sysfs driver remove %s\n", pdev->name);
list_for_each_entry (mydata, list, node) {
misc_deregister(&(mydata->misc));
}
return 0;
}
void drv_shutdown(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver shutdown %s\n", pdev->name);
}
int drv_suspend(struct platform_device* pdev, pm_message_t state)
{
pr_info("skeleton - sysfs driver suspend %s (state=%d)\n",
pdev->name,
state.event);
return 0;
}
int drv_resume(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver resume %s\n", pdev->name);
return 0;
}
struct of_device_id of_drv[] = {
{
.compatible = "mydevice",
},
{},
};
MODULE_DEVICE_TABLE(of, of_drv);
static struct platform_driver sysfs_driver = {
.probe = drv_probe,
.remove = drv_remove,
.shutdown = drv_shutdown,
.suspend = drv_suspend,
.resume = drv_resume,
.driver =
{
.name = "mydriver",
.of_match_table = of_match_ptr(of_drv),
},
};
#if 1
static int __init sysfs_driver_init(void)
{
int status = 0;
pr_info("Linux module skeleton loading...\n");
/* install sysfs */
if (status == 0) status = platform_driver_register(&sysfs_driver);
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit sysfs_driver_exit(void)
{
pr_info("Linux module skeleton exiting...\n");
/* uninstall sysfs */
platform_driver_unregister(&sysfs_driver);
pr_info("Linux module skeleton unloaded\n");
}
module_init(sysfs_driver_init);
module_exit(sysfs_driver_exit);
#else
module_platform_driver(sysfs_driver);
#endif
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,40 @@
export PATH := /buildroot/output/host/usr/sbin$\
:/buildroot/output/host/usr/bin/$\
:/buildroot/output/host/sbin$\
:/buildroot/output/host/bin/$\
:$(PATH)
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all: dtb
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
DTB = mydt.dtb
DTS = mydt.dts
INCL+=-I. -I$(KDIR)/include -I$(KDIR)/arch/arm64/boot/dts
dtb: $(DTB)
$(DTB) : $(DTS)
ln -s $(KDIR)/arch/arm/boot/dts arm
-cpp $(INCL) -E -P -x assembler-with-cpp $(DTS) | dtc -I dts -O dtb -o $(DTB) -
rm arm
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
rm -f *.dtb
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,13 @@
/dts-v1/;
#include "allwinner/sun50i-h5-nanopi-neo-plus2.dts"
/ {
/delete-node/ leds;
mydevice {
compatible = "mydevice";
attribute = "on";
};
};

View File

@@ -0,0 +1,255 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
#define BUFFER_SZ 10000
struct mydata {
char buffer[BUFFER_SZ];
struct miscdevice misc;
};
static int skeleton_open(struct inode* i, struct file* f)
{
pr_info("skeleton : open operation... major:%d, minor:%d, p_data=%llx\n",
imajor(i),
iminor(i),
(long long)f->private_data);
return 0;
}
static int skeleton_release(struct inode* i, struct file* f)
{
pr_info("skeleton: release operation...p_data=%llx\n",
(long long)f->private_data);
return 0;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
struct mydata* mydata = container_of(f->private_data, struct mydata, misc);
// compute remaining bytes to copy, update count and pointers
ssize_t remaining = strlen(mydata->buffer) - (ssize_t)(*off);
char* ptr = mydata->buffer + *off;
if (count > remaining) count = remaining;
*off += count;
// copy required number of bytes
if (copy_to_user(buf, ptr, count) != 0) count = -EFAULT;
pr_info("skeleton: read operation...p_data=%llx read=%ld\n",
(long long)f->private_data,
count);
return count;
}
static ssize_t skeleton_write(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
struct mydata* mydata = container_of(f->private_data, struct mydata, misc);
// compute remaining space in buffer and update pointers
ssize_t remaining = sizeof(mydata->buffer) - (ssize_t)(*off);
char* ptr = mydata->buffer + *off;
*off += count;
// check if still remaining space to store additional bytes
if (count >= remaining) count = -EIO;
// store additional bytes into internal buffer
if (count > 0) {
ptr[count] = 0; // make sure string is null terminated
if (copy_from_user(ptr, buf, count)) count = -EFAULT;
}
pr_info("skeleton: write operation... written=%ld\n", count);
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
int drv_probe(struct platform_device* pdev)
{
int ret = 0;
struct device_node* dt_node = pdev->dev.of_node;
struct mydata* mydata = 0;
pr_info("skeleton - driver probe %llx (%s)- M.m=%d.%d\n",
(unsigned long long)pdev,
pdev->name,
MAJOR(pdev->dev.devt),
MINOR(pdev->dev.devt));
mydata = devm_kzalloc(&pdev->dev, sizeof(*mydata), GFP_KERNEL);
pr_info("miscdev=%llx\n", (long long)mydata);
if (mydata == 0) {
dev_err(&pdev->dev, "Failed to allocate resource for miscdev\n");
return -ENOMEM;
}
if (pdev->num_resources) {
pr_info("resources: name=%s, start=%lld, end=%lld\n",
pdev->resource[0].name,
pdev->resource[0].start,
pdev->resource[0].end);
}
if (dt_node) {
int ret = 0;
const char* prop_str = 0;
const unsigned int* prop_reg = 0;
prop_reg = of_get_property(dt_node, "reg", NULL);
if (prop_reg != 0) {
unsigned long reg = of_read_ulong(prop_reg, 1);
pr_info("reg:%lu\n", reg);
}
ret = of_property_read_string(dt_node, "attribute", &prop_str);
if (prop_str && ret == 0)
pr_info("attribute=%s (ret=%d)\n", prop_str, ret);
}
/* register misc device ... */
platform_set_drvdata(pdev, mydata);
mydata->misc.minor = MISC_DYNAMIC_MINOR;
mydata->misc.fops = &fops;
mydata->misc.name = pdev->name;
mydata->misc.mode = 0664;
ret = misc_register(&(mydata->misc));
if (ret != 0) {
dev_err(&pdev->dev, "Failed to register miscdev\n");
return ret;
}
return 0;
}
int drv_remove(struct platform_device* pdev)
{
struct mydata* mydata = platform_get_drvdata(pdev);
pr_info("skeleton - sysfs driver remove %s\n", pdev->name);
misc_deregister(&(mydata->misc));
return 0;
}
void drv_shutdown(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver shutdown %s\n", pdev->name);
}
int drv_suspend(struct platform_device* pdev, pm_message_t state)
{
pr_info("skeleton - sysfs driver suspend %s (state=%d)\n",
pdev->name,
state.event);
return 0;
}
int drv_resume(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver resume %s\n", pdev->name);
return 0;
}
struct of_device_id of_drv[] = {
{
.compatible = "mydevice",
},
{},
};
MODULE_DEVICE_TABLE(of, of_drv);
static struct platform_driver sysfs_driver = {
.probe = drv_probe,
.remove = drv_remove,
.shutdown = drv_shutdown,
.suspend = drv_suspend,
.resume = drv_resume,
.driver =
{
.name = "mydriver",
.of_match_table = of_match_ptr(of_drv),
},
};
//#define INIT
//#define MACRO
#define BOTH
#ifdef INIT
static int __init sysfs_driver_init(void)
{
int status = 0;
pr_info("Linux module skeleton loading...\n");
/* install sysfs */
if (status == 0) status = platform_driver_register(&sysfs_driver);
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit sysfs_driver_exit(void)
{
pr_info("Linux module skeleton exiting...\n");
/* uninstall sysfs */
platform_driver_unregister(&sysfs_driver);
pr_info("Linux module skeleton unloaded\n");
}
module_init(sysfs_driver_init);
module_exit(sysfs_driver_exit);
#endif
#ifdef MACRO
module_platform_driver(sysfs_driver);
#endif
#ifdef BOTH
static int __init sysfs_driver_init(void)
{
pr_info("Linux module skeleton loading...\n");
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit sysfs_driver_exit(void)
{
pr_info("Linux module skeleton exiting...\n");
pr_info("Linux module skeleton unloaded\n");
}
module_init(sysfs_driver_init);
module_exit(sysfs_driver_exit);
module_platform_driver(sysfs_driver);
#endif
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,5 @@
DIRS=$(filter-out Makefile, $(wildcard *))
all clean install:
for dir in $(DIRS); do $(MAKE) $@ -C $$dir; done

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,126 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/poll.h> /* needed for polling handling */
#include <linux/sched.h> /* needed for scheduling constants */
#include <linux/wait.h> /* needed for wating */
#include <linux/gpio.h> /* needed for i/o handling */
#include <linux/interrupt.h> /* needed for interrupt handling */
#include <linux/io.h> /* needed for mmio handling */
#include <linux/ioport.h> /* needed for memory region handling */
#include <linux/miscdevice.h>
#define K1 0
#define K2 2
#define K3 3
static char* k1 = "gpio_a.0-k1";
static char* k2 = "gpio_a.2-k2";
static char* k3 = "gpio_a.3-k3";
static atomic_t nb_of_interrupts;
DECLARE_WAIT_QUEUE_HEAD(queue);
irqreturn_t gpio_isr(int irq, void* handle)
{
atomic_inc(&nb_of_interrupts);
wake_up_interruptible(&queue);
pr_info("interrupt %s raised...\n", (char*)handle);
return IRQ_HANDLED;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t sz,
loff_t* off)
{
return 0;
}
static unsigned int skeleton_poll(struct file* f, poll_table* wait)
{
unsigned mask = 0;
poll_wait(f, &queue, wait);
if (atomic_read(&nb_of_interrupts) != 0) {
mask |= POLLIN | POLLRDNORM; /* read operation */
/* mask |= POLLOUT | POLLWRNORM; write operation */
atomic_dec(&nb_of_interrupts);
pr_info("polling thread waked-up...\n");
}
return mask;
}
static struct file_operations skeleton_fops = {
.owner = THIS_MODULE,
.read = skeleton_read,
.poll = skeleton_poll,
};
struct miscdevice misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.fops = &skeleton_fops,
.name = "mymodule",
.mode = 0777,
};
static int __init skeleton_init(void)
{
int status = 0;
atomic_set(&nb_of_interrupts, 0);
status = misc_register(&misc_device);
// install k1
if (status == 0)
status = devm_request_irq(misc_device.this_device,
gpio_to_irq(K1),
gpio_isr,
IRQF_TRIGGER_FALLING | IRQF_SHARED,
k1,
k1);
// install k2
if (status == 0)
status = devm_request_irq(misc_device.this_device,
gpio_to_irq(K2),
gpio_isr,
IRQF_TRIGGER_RISING | IRQF_SHARED,
k2,
k2);
// install k3
if (status == 0)
status = devm_request_irq(
misc_device.this_device,
gpio_to_irq(K3),
gpio_isr,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_SHARED,
k3,
k3);
pr_info("Linux module skeleton loaded(status=%d)\n", status);
return status;
}
static void __exit skeleton_exit(void)
{
misc_deregister(&misc_device);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,5 @@
DIRS=$(filter-out Makefile, $(wildcard *))
all clean install:
for dir in $(DIRS); do $(MAKE) $@ -C $$dir; done

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,85 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/mm.h> /* needed for mmap handling */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/platform_device.h> /* needed for sysfs handling */
static int skeleton_mmap(struct file* f, struct vm_area_struct* vma)
{
int status = 0;
unsigned long size = vma->vm_end - vma->vm_start;
if (size > PAGE_SIZE) status = -EINVAL;
vma->vm_pgoff = 0x01c14000 >> PAGE_SHIFT;
if (status == 0)
status = remap_pfn_range(
vma, vma->vm_start, vma->vm_pgoff, size, vma->vm_page_prot);
if (status != 0) status = -EAGAIN;
pr_info("skeleton: mmap (size=%lu, shift=%d) status=%d\n",
size,
PAGE_SHIFT,
status);
return status;
}
static struct file_operations skeleton_fops = {
.owner = THIS_MODULE,
.mmap = skeleton_mmap,
};
static dev_t skeleton_dev;
static struct cdev skeleton_cdev;
static void sysfs_dev_release(struct device* dev)
{
pr_info("skeleton - sysfs dev release\n");
}
static struct platform_device sysfs_device;
static int __init skeleton_init(void)
{
int status;
status = alloc_chrdev_region(&skeleton_dev, 0, 1, "mymodule");
if (status == 0) {
cdev_init(&skeleton_cdev, &skeleton_fops);
skeleton_cdev.owner = THIS_MODULE;
status = cdev_add(&skeleton_cdev, skeleton_dev, 1);
}
sysfs_device.name = "mymodule";
sysfs_device.id = -1;
sysfs_device.dev.release = sysfs_dev_release;
sysfs_device.dev.devt = skeleton_dev;
if (status == 0) status = platform_device_register(&sysfs_device);
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit skeleton_exit(void)
{
platform_device_unregister(&sysfs_device);
cdev_del(&skeleton_cdev);
unregister_chrdev_region(skeleton_dev, 1);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,5 @@
DIRS=$(filter-out Makefile, $(wildcard *))
all clean install:
for dir in $(DIRS); do $(MAKE) $@ -C $$dir; done

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,99 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/ioctl.h> /* needed for ioctl handling */
#include "skeleton.h"
static struct skeleton_config config;
static int val;
static long skeleton_ioctl(struct file* f, unsigned int cmd, unsigned long arg)
{
int status = 0;
switch (cmd) {
case SKELETON_IO_RESET:
val = 0;
memset(&config, 0, sizeof(config));
pr_info("skeleton-ioctl: reset command\n");
break;
case SKELETON_IO_WR_REF:
if (_IOC_SIZE(cmd) == sizeof(config))
status =
copy_from_user(&config, (char __user*)arg, _IOC_SIZE(cmd));
else
status = -EFAULT;
pr_info("skeleton-ioctl: write config\n");
break;
case SKELETON_IO_RD_REF:
if (_IOC_SIZE(cmd) == sizeof(config))
status =
copy_to_user((char __user*)arg, &config, _IOC_SIZE(cmd));
else
status = -EFAULT;
pr_info("skeleton-ioctl: read config\n");
break;
case SKELETON_IO_WR_VAL:
val = arg;
pr_info("skeleton-ioctl: write value=%d\n", val);
break;
case SKELETON_IO_RD_VAL:
status = val;
pr_info("skeleton-ioctl: read value=%d\n", status);
break;
default:
pr_info("skeleton-ioctl: unknown command (cmd=%d)\n", cmd);
status = -EFAULT;
break;
}
return status;
}
static struct file_operations skeleton_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = skeleton_ioctl,
};
static dev_t skeleton_dev;
static struct cdev skeleton_cdev;
static int __init skeleton_init(void)
{
int status;
status = alloc_chrdev_region(&skeleton_dev, 0, 1, "mymodule");
if (status == 0) {
cdev_init(&skeleton_cdev, &skeleton_fops);
skeleton_cdev.owner = THIS_MODULE;
status = cdev_add(&skeleton_cdev, skeleton_dev, 1);
}
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit skeleton_exit(void)
{
cdev_del(&skeleton_cdev);
unregister_chrdev_region(skeleton_dev, 1);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,20 @@
#ifndef SKELETON_H
#define SKELETON_H
#include <linux/ioctl.h>
struct skeleton_config {
int id;
long ref;
char name[30];
char descr[30];
};
#define SKELETON_IOMAGIC 'g'
#define SKELETON_IO_RESET _IO(SKELETON_IOMAGIC, 0)
#define SKELETON_IO_WR_REF _IOW(SKELETON_IOMAGIC, 1, struct skeleton_config)
#define SKELETON_IO_RD_REF _IOR(SKELETON_IOMAGIC, 2, struct skeleton_config)
#define SKELETON_IO_WR_VAL _IOW(SKELETON_IOMAGIC, 3, int)
#define SKELETON_IO_RD_VAL _IOR(SKELETON_IOMAGIC, 4, int)
#endif

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,120 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/proc_fs.h> /* needed for procfs handling */
struct skeleton_config {
int id;
long ref;
char name[50];
char descr[50];
};
static struct skeleton_config config = {.id = 11,
.ref = 33,
.name = "config structure",
.descr = "procfs test driver"};
static int val = 55;
static ssize_t skeleton_read_config(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
char temp[200];
int len = snprintf(temp,
sizeof(temp),
"id=%d\nref=%ld\nname=%s\ndescr=%s\n",
config.id,
config.ref,
config.name,
config.descr);
len -= (ssize_t)(*off);
if (count > len) count = len;
*off += count;
if (copy_to_user(buf, temp, count) != 0) count = -EFAULT;
return count;
}
static const struct proc_ops fops_config = {
.proc_read = skeleton_read_config,
};
static ssize_t skeleton_read_val(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
char temp[20];
int len = snprintf(temp, sizeof(temp), "%d\n", val);
len -= (ssize_t)(*off);
if (count > len) count = len;
*off += count;
if (copy_to_user(buf, temp, count) != 0) count = -EFAULT;
return count;
}
static ssize_t skeleton_write_val(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
char temp[20];
if (count > sizeof(temp)) return -EIO;
if (copy_from_user(temp, buf, count)) return -EFAULT;
val = simple_strtol(temp, 0, 10);
return count;
}
static const struct proc_ops fops_val = {
.proc_read = skeleton_read_val,
.proc_write = skeleton_write_val,
};
static struct proc_dir_entry* procfs_dir = 0;
static int __init skeleton_init(void)
{
int status = 0;
/* create procfs node and attributes */
procfs_dir = proc_mkdir("mymodule", NULL);
proc_create("config", 0, procfs_dir, &fops_config);
proc_create("val", 0, procfs_dir, &fops_val);
if (procfs_dir == 0) status = -EFAULT;
pr_info("Linux module skeleton loaded (status=%d)\n", status);
return status;
}
static void __exit skeleton_exit(void)
{
/* remove procfs attributes and node */
remove_proc_entry("val", procfs_dir);
remove_proc_entry("config", procfs_dir);
remove_proc_entry("mymodule", NULL);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,19 @@
objects = main1 main2 main3
TOOLCHAIN_PATH=/buildroot/output/host/usr/bin/
TOOLCHAIN=$(TOOLCHAIN_PATH)aarch64-linux-
CFLAGS+=-Wall -Wextra -g -O0 -std=gnu11
CFLAGS+=-mcpu=cortex-a53 -funwind-tables
CC=$(TOOLCHAIN)gcc
all: $(objects)
$(objects): %: %.c
$(CC) $(CFLAGS) -o $@ $<
clean:
rm -f *.txt
rm -f *~
rm $(objects)

View File

@@ -0,0 +1,14 @@
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static const char* msg1 = "1234567890abcdefghijklmnopqrstuvwxyz\n";
int main()
{
int fd = open("test1.txt", O_RDWR | O_CREAT | O_TRUNC, 0664);
for (int i = 0; i < 10000; i++) write(fd, msg1, strlen(msg1));
close(fd);
}

View File

@@ -0,0 +1,28 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define FILE_SZ (10 * 1024 * 1024)
static const char* msg2 = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
int main()
{
// open again 1st file generated by the main1 application
int fd = open("test1.txt", O_RDWR, 0664);
char* file = mmap(0, FILE_SZ, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
printf("the file after mapping...\n");
// modify every 10th lines
for (int i = 0; i < 10000; i += 10)
memcpy(file + i * strlen(msg2), msg2, strlen(msg2));
printf("the file after filling...\n");
close(fd);
return 0;
}

View File

@@ -0,0 +1,28 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define FILE_SZ (5 * 1024 * 1024)
static const char* msg1 = "1234567890abcdefghijklmnopqrstuvwxyz\n";
int main()
{
int fd = open("test3.txt", O_RDWR | O_CREAT | O_TRUNC, 0664);
char* file = mmap(0, FILE_SZ, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
lseek(fd, FILE_SZ, SEEK_SET);
write(fd, "", 1);
printf("the file after mapping...\n");
for (int i = 0; i < 10000; i += 1)
memcpy(file + i * strlen(msg1), msg1, strlen(msg1));
printf("the file after filling...\n");
close(fd);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,101 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
#define BUFFER_SZ 10000
static struct mydata {
struct device* device;
struct skeleton_attr {
char buffer[BUFFER_SZ];
struct device_attribute dev_attr;
} attr;
} mydevices[5];
#define ATTR_INSTANCE(a) \
{ \
a.attr.buffer[0] = 0; \
a.attr.dev_attr.attr.name = "val"; \
a.attr.dev_attr.attr.mode = 0664; \
a.attr.dev_attr.show = sysfs_show_attr; \
a.attr.dev_attr.store = sysfs_store_attr; \
}
// --- sysfs file opers ------------------------------------------------------
ssize_t sysfs_show_attr(struct device* dev,
struct device_attribute* attr,
char* buf)
{
struct mydata* mydata = container_of(attr, struct mydata, attr.dev_attr);
strcpy(buf, mydata->attr.buffer);
return strlen(buf);
}
ssize_t sysfs_store_attr(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
struct mydata* mydata = container_of(attr, struct mydata, attr.dev_attr);
int len = sizeof(mydata->attr.buffer) - 1;
if (len > count) len = count;
strncpy(mydata->attr.buffer, buf, len);
mydata->attr.buffer[len] = 0;
return len;
}
static struct class* sysfs_class;
static int __init skeleton_init(void)
{
int status = 0;
int i =0;
sysfs_class = class_create(THIS_MODULE, "myclass");
for (i=0; i<ARRAY_SIZE(mydevices); i++) {
struct mydata* mydev = &mydevices[i];
mydev->device = device_create(sysfs_class, NULL, i, NULL, "mydevice.%d", i);
ATTR_INSTANCE((*mydev));
status = device_create_file(mydev->device, &(mydev->attr.dev_attr));
}
pr_info("Linux module skeleton loaded\n");
return status;
}
static void __exit skeleton_exit(void)
{
int i = 0;
for (i=0; i<ARRAY_SIZE(mydevices); i++) {
struct mydata* mydev = &mydevices[i];
device_remove_file(mydev->device, &(mydev->attr.dev_attr));
device_destroy(sysfs_class, i);
}
class_destroy(sysfs_class);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,59 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/device.h> /* needed for sysfs handling */
static char sysfs_buf[1000];
ssize_t sysfs_show_attr(struct device* dev,
struct device_attribute* attr,
char* buf)
{
strcpy(buf, sysfs_buf);
return strlen(buf);
}
ssize_t sysfs_store_attr(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
int len = sizeof(sysfs_buf) - 1;
if (len > count) len = count;
strncpy(sysfs_buf, buf, len);
sysfs_buf[len] = 0;
return len;
}
DEVICE_ATTR(attr, 0664, sysfs_show_attr, sysfs_store_attr);
static struct class* sysfs_class;
static struct device* sysfs_device;
static int __init skeleton_init(void)
{
int status = 0;
sysfs_class = class_create(THIS_MODULE, "myclass");
sysfs_device = device_create(sysfs_class, NULL, 0, NULL, "mydevice");
status = device_create_file(sysfs_device, &dev_attr_attr);
pr_info("Linux module skeleton loaded\n");
return status;
}
static void __exit skeleton_exit(void)
{
/* uninstall sysfs */
device_remove_file(sysfs_device, &dev_attr_attr);
device_destroy(sysfs_class, 0);
class_destroy(sysfs_class);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,22 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,217 @@
/* skeleton.c */
#include <linux/module.h> /* needed by all modules */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/moduleparam.h> /* needed for module parameters */
#include <linux/slab.h> /* needed for dynamic memory management */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/platform_device.h> /* needed for sysfs handling */
#define INSTANCES 3
// --- sysfs operations --------------------------------------------------------
struct skeleton_attr {
long val;
int id;
struct device_attribute dev_attr;
};
#define ATTR_INSTANCE(i,v)\
{\
.val = v,\
.id = i,\
.dev_attr = {\
.attr = {.name = "val", .mode=0664, },\
.show = sysfs_show_val,\
.store = sysfs_store_val,\
},\
}
static ssize_t sysfs_show_val(
struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct skeleton_attr* s_attr =
container_of(attr, struct skeleton_attr, dev_attr);
sprintf (buf, "%ld\n", s_attr->val);
pr_info ("skeleton-sysfs_show: val[%d]=%ld\n", s_attr->id, s_attr->val);
return strlen(buf);
}
static ssize_t sysfs_store_val(
struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct skeleton_attr* s_attr =
container_of(attr, struct skeleton_attr, dev_attr);
int err = kstrtol (buf, 10, &s_attr->val);
//pr_info ("skeleton-sysfs_store: val[%d]=%ld\n", s_attr->id, s_attr->val);
return err == 0 ? count : err;
}
static struct skeleton_attr skeleton_attr[INSTANCES] = {
[0] = ATTR_INSTANCE(0,10),
[1] = ATTR_INSTANCE(1,11),
[2] = ATTR_INSTANCE(2,12),
};
static void sysfs_dev_release (struct device *dev)
{
pr_info ("skeleton-sysfs_dev_release\n");
}
static struct platform_device sysfs_device[INSTANCES];
// --- fops operations ---------------------------------------------------------
#define BUFFER_SZ 10000
static char buffers[INSTANCES][BUFFER_SZ];
static int skeleton_open (struct inode *i, struct file *f)
{
pr_info ("skeleton-open operation... major:%d, minor:%d\n",
imajor (i), iminor(i));
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) != 0) {
pr_info (" o--> opened for reading & writing...\n");
} else if (iminor(i) >= INSTANCES) return -EFAULT;
if ((f->f_mode & FMODE_READ) != 0) {
pr_info (" o--> opened for reading...\n");
} else if ((f->f_mode & FMODE_WRITE) != 0) {
pr_info (" o--> opened for writing...\n");
}
f->private_data = buffers[iminor(i)];
pr_info (" o--> private_data address = %p\n", f->private_data);
return 0;
}
static int skeleton_release (struct inode *i, struct file *f)
{
pr_info ("skeleton-release operation...\n");
return 0;
}
static ssize_t skeleton_read (struct file *f, char __user *buf,
size_t count, loff_t *off)
{
// compute remaining bytes to copy, update count and pointers
ssize_t remaining = strlen(f->private_data) - (ssize_t)(*off);
char* ptr = (char*)f->private_data + *off;
if (count > remaining) count = remaining;
*off += count;
// copy required number of bytes
if (copy_to_user (buf, ptr, count) != 0) count = -EFAULT;
pr_info("skeleton-read: buf=%p, read=%ld\n", f->private_data, count);
return count;
}
static ssize_t skeleton_write (struct file *f, const char __user *buf,
size_t count, loff_t *off)
{
// compute remaining space in buffer and update pointers
ssize_t remaining = BUFFER_SZ - (ssize_t)(*off);
char* ptr = (char*)f->private_data + *off;
*off += count;
// check if still remaining space to store additional bytes
if (count >= remaining) count = -EIO;
// store additional bytes into internal buffer
if (count > 0) {
ptr[count] = 0; // make sure string is null terminated
if (copy_from_user (ptr, buf, count)) count = -EFAULT;
}
pr_info ("skeleton-write: buf=%p, written=%ld\n", f->private_data, count);
return count;
}
static struct file_operations skeleton_fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
static dev_t skeleton_dev;
static struct cdev skeleton_cdev;
static int __init skeleton_init(void)
{
int i;
int status = -EFAULT;
status = alloc_chrdev_region (&skeleton_dev, 0, INSTANCES, "mymodule");
if (status == 0) {
cdev_init (&skeleton_cdev, &skeleton_fops);
skeleton_cdev.owner = THIS_MODULE;
status = cdev_add (&skeleton_cdev, skeleton_dev, INSTANCES);
}
/* install sysfs */
for (i = 0; i < INSTANCES; i++) {
sysfs_device[i].name = "mymodule";
sysfs_device[i].id = i;
sysfs_device[i].dev.release = sysfs_dev_release;
sysfs_device[i].dev.devt = MKDEV (MAJOR(skeleton_dev), i);
if (status == 0)
status = platform_device_register (&sysfs_device[i]);
if (status == 0)
status = device_create_file (
&sysfs_device[i].dev,
&skeleton_attr[i].dev_attr);
}
pr_info ("Linux module skeleton loaded\n");
return status;
}
static void __exit skeleton_exit(void)
{
int i;
for (i = 0; i < INSTANCES; i++) {
device_remove_file (
&sysfs_device[i].dev,
&skeleton_attr[i].dev_attr);
platform_device_unregister (&sysfs_device[i]);
}
cdev_del (&skeleton_cdev);
unregister_chrdev_region (skeleton_dev, INSTANCES);
pr_info ("Linux module skeleton unloaded\n");
}
module_init (skeleton_init);
module_exit (skeleton_exit);
MODULE_AUTHOR ("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION ("Module skeleton");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,42 @@
export PATH := /buildroot/output/host/usr/sbin$\
:/buildroot/output/host/usr/bin/$\
:/buildroot/output/host/sbin$\
:/buildroot/output/host/bin/$\
:$(PATH)
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
obj-m += mymodule.o ## name of the generated module
mymodule-objs := skeleton.o ## list of objects needed for that module
# Part executed when called from standard make in module source directory:
else
include ../../kernel_settings
PWD := $(shell pwd)
INCL+=-I. -I$(KDIR)/include -I$(KDIR)/arch/arm64/boot/dts
DTB = mydt.dtb
DTS = $(DTB:.dtb=.dts)
all: dtb boot
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules
dtb: $(DTB)
$(DTB) : $(DTS)
ln -s $(KDIR)/arch/arm/boot/dts arm
-cpp $(INCL) -E -P -x assembler-with-cpp $(DTS) | dtc -I dts -O dtb -o $(DTB) -
rm arm
boot:
mkimage -T script -A arm -C none -d boot.cmd boot.ovl
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
rm -f *.dtb *.ovl
install:
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
endif

View File

@@ -0,0 +1,13 @@
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
fatload mmc 0 $kernel_addr_r Image
#fatload mmc 0 $fdt_addr_r sun50i-h5-nanopi-neo-plus2.dtb
fatload mmc 0 $fdt_addr_r mydt.dtb
fdt addr $fdt_addr_r
fdt resize
#fdt mknode / mymodule2
#fdt set /mymodule2 compatible mymodule2
booti $kernel_addr_r - $fdt_addr_r

View File

@@ -0,0 +1,29 @@
/dts-v1/;
#include "allwinner/sun50i-h5-nanopi-neo-plus2.dts"
/ {
/delete-node/ leds;
mydevice {
compatible = "mydevice";
#address-cells = <1>;
#size-cells = <0>;
attribute = "idle";
mydevice@0 {
reg = <0x0>;
attribute = "on";
};
mydevice@1 {
reg = <0x1>;
attribute = "off";
};
mydevice@2 {
reg = <0x2>;
attribute = "off";
};
};
};

View File

@@ -0,0 +1,304 @@
/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
#define BUFFER_SZ 10000
struct mydata {
char buffer[BUFFER_SZ];
struct class* sysfs_class;
struct device* sysfs_device;
struct miscdevice misc;
struct skeleton_attr {
long val;
int id;
struct device_attribute dev_attr;
} attr;
};
#define ATTR_INSTANCE(a, i, v) \
{ \
a.attr.val = v; \
a.attr.id = i; \
a.attr.dev_attr.attr.name = "val"; \
a.attr.dev_attr.attr.mode = 0664; \
a.attr.dev_attr.show = sysfs_show_val; \
a.attr.dev_attr.store = sysfs_store_val; \
}
// --- sysfs file opers ------------------------------------------------------
static ssize_t sysfs_show_val(struct device* dev,
struct device_attribute* attr,
char* buf)
{
struct mydata* mydata = container_of(attr, struct mydata, attr.dev_attr);
sprintf(buf, "%ld\n", mydata->attr.val);
pr_info("skeleton-sysfs_show: val[%d]=%ld\n",
mydata->attr.id,
mydata->attr.val);
return strlen(buf);
}
static ssize_t sysfs_store_val(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
struct mydata* mydata = container_of(attr, struct mydata, attr.dev_attr);
int err = kstrtol(buf, 10, &mydata->attr.val);
pr_info("skeleton-sysfs_store: val[%d]=%ld\n",
mydata->attr.id,
mydata->attr.val);
return err == 0 ? count : err;
}
// --- file opers ------------------------------------------------------------
static int skeleton_open(struct inode* i, struct file* f)
{
pr_info("skeleton : open operation... major:%d, minor:%d, p_data=%llx\n",
imajor(i),
iminor(i),
(long long)f->private_data);
return 0;
}
static int skeleton_release(struct inode* i, struct file* f)
{
pr_info("skeleton: release operation...p_data=%llx\n",
(long long)f->private_data);
return 0;
}
static ssize_t skeleton_read(struct file* f,
char __user* buf,
size_t count,
loff_t* off)
{
struct mydata* mydata = container_of(f->private_data, struct mydata, misc);
// compute remaining bytes to copy, update count and pointers
ssize_t remaining = strlen(mydata->buffer) - (ssize_t)(*off);
char* ptr = mydata->buffer + *off;
if (count > remaining) count = remaining;
*off += count;
// copy required number of bytes
if (copy_to_user(buf, ptr, count) != 0) count = -EFAULT;
pr_info("skeleton: read operation...p_data=%llx read=%ld\n",
(long long)f->private_data,
count);
return count;
}
static ssize_t skeleton_write(struct file* f,
const char __user* buf,
size_t count,
loff_t* off)
{
struct mydata* mydata = container_of(f->private_data, struct mydata, misc);
// compute remaining space in buffer and update pointers
ssize_t remaining = sizeof(mydata->buffer) - (ssize_t)(*off);
char* ptr = mydata->buffer + *off;
*off += count;
// check if still remaining space to store additional bytes
if (count >= remaining) count = -EIO;
// store additional bytes into internal buffer
if (count > 0) {
ptr[count] = 0; // make sure string is null terminated
if (copy_from_user(ptr, buf, count)) count = -EFAULT;
}
pr_info("skeleton: write operation... written=%ld\n", count);
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = skeleton_open,
.read = skeleton_read,
.write = skeleton_write,
.release = skeleton_release,
};
int drv_probe(struct platform_device* pdev)
{
int ret = 0;
struct device_node* dt_node = pdev->dev.of_node;
struct mydata* mydata = 0;
const char* prop_str = 0;
pr_info("skeleton - driver probe %llx (%s)- M.m=%d.%d\n",
(unsigned long long)pdev,
pdev->name,
MAJOR(pdev->dev.devt),
MINOR(pdev->dev.devt));
ret = of_property_read_string(dt_node, "attribute", &prop_str);
if (prop_str && ret == 0) pr_info("attribute=%s (ret=%d)\n", prop_str, ret);
if (pdev->num_resources) {
pr_info("resources: name=%s, start=%lld, end=%lld\n",
pdev->resource[0].name,
pdev->resource[0].start,
pdev->resource[0].end);
}
if (dt_node) {
int ret = 0;
const char* prop_str = 0;
const unsigned int* prop_reg = 0;
unsigned long reg = 0;
struct device_node* child;
for_each_available_child_of_node(dt_node, child)
{
mydata = devm_kzalloc(&pdev->dev, sizeof(*mydata), GFP_KERNEL);
pr_info("miscdev=%llx\n", (long long)mydata);
if (mydata == 0) {
dev_err(&pdev->dev,
"Failed to allocate resource for miscdev\n");
return -ENOMEM;
}
pr_info("child found: name=%s, fullname=%s\n",
child->name,
child->full_name);
prop_reg = of_get_property(child, "reg", NULL);
if (prop_reg != 0) {
reg = of_read_ulong(prop_reg, 1);
pr_info("reg:%lu\n", reg);
}
ret = of_property_read_string(child, "attribute", &prop_str);
if (prop_str && ret == 0)
pr_info("attribute=%s (ret=%d)\n", prop_str, ret);
// register misc device ...
platform_set_drvdata(pdev, mydata);
mydata->misc.minor = MISC_DYNAMIC_MINOR;
mydata->misc.fops = &fops;
mydata->misc.name = child->full_name;
mydata->misc.mode = 0664;
ret = misc_register(&(mydata->misc));
if (ret != 0) {
dev_err(&pdev->dev, "Failed to register miscdev\n");
return ret;
}
// register misc device sysfs attribute...
ATTR_INSTANCE((*mydata), reg, reg);
ret = device_create_file(mydata->misc.this_device,
&mydata->attr.dev_attr);
if (ret != 0) {
dev_err(&pdev->dev,
"Failed to register miscdev sysfs attribute\n");
return ret;
}
}
}
return 0;
}
int drv_remove(struct platform_device* pdev)
{
struct mydata* mydata = platform_get_drvdata(pdev);
pr_info("skeleton - sysfs driver remove %s\n", pdev->name);
misc_deregister(&(mydata->misc));
return 0;
}
void drv_shutdown(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver shutdown %s\n", pdev->name);
}
int drv_suspend(struct platform_device* pdev, pm_message_t state)
{
pr_info("skeleton - sysfs driver suspend %s (state=%d)\n",
pdev->name,
state.event);
return 0;
}
int drv_resume(struct platform_device* pdev)
{
pr_info("skeleton - sysfs driver resume %s\n", pdev->name);
return 0;
}
struct of_device_id of_drv[] = {
{
.compatible = "mydevice",
},
{},
};
MODULE_DEVICE_TABLE(of, of_drv);
static struct platform_driver sysfs_driver = {
.probe = drv_probe,
.remove = drv_remove,
.shutdown = drv_shutdown,
.suspend = drv_suspend,
.resume = drv_resume,
.driver =
{
.name = "mydriver",
.of_match_table = of_match_ptr(of_drv),
},
};
#if 1
static int __init sysfs_driver_init(void)
{
int status = 0;
pr_info("Linux module skeleton loading...\n");
/* install sysfs */
if (status == 0) status = platform_driver_register(&sysfs_driver);
pr_info("Linux module skeleton loaded\n");
return 0;
}
static void __exit sysfs_driver_exit(void)
{
pr_info("Linux module skeleton exiting...\n");
/* uninstall sysfs */
platform_driver_unregister(&sysfs_driver);
pr_info("Linux module skeleton unloaded\n");
}
module_init(sysfs_driver_init);
module_exit(sysfs_driver_exit);
#else
module_platform_driver(sysfs_driver);
#endif
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");

5
src/buildroot_path Normal file
View File

@@ -0,0 +1,5 @@
export PATH := /buildroot/output/host/usr/sbin$\
:/buildroot/output/host/usr/bin/$\
:/buildroot/output/host/sbin$\
:/buildroot/output/host/bin/$\
:$(PATH)

8
src/kernel_settings Normal file
View File

@@ -0,0 +1,8 @@
CVER := aarch64-buildroot-linux-gnu-
KVER := 5.15.21
CPU := arm64
KDIR := /buildroot/output/build/linux-$(KVER)/
TOOLS := /buildroot/output/host/usr/bin/$(CVER)
MODPATH := /rootfs
#MODPATH := /buildroot/output/target