Add a Syscall

Add a syscall to kernel and replace linux kernel of RPi.


Prepare:

  1. Cross compiler
  2. Linux Kernel for RPi

Reference:

Official guide


Firstly, get the latest kernel:

git clone https://github.com/raspberrypi/linux

Assume that the kernel directory is 'linux' and you have already installed cross-compiler tool.


Secondly, modify the source to add a simple syscall.

1. linux/arch/arm/kernel/sys_arm.c

Add syscall definition.

In order to simplify the process, we add the definition directly in the source that exists, so that we need not to modify the Makefile. And sys_arm.c is what we need.

Add the following definition to sys_arm.c

asmlinkage long sys_mysyscall(int num)
{
printk("My syscall with argument: %d\n",num);
return 0;
}

There is a second file(Call.S) in the same directory that we need to modify. But, in order to make the process more clear, we change another file first.

2.linux/arch/arm/include/unistd.h

Add macro define of our syscall to this file.

In this file, __NR_SYSCALL_BASE define the base address of syscall. And we will use this macro to define the address of our own function. Like this:

#define __NR_mysyscall (__NR_SYSCALL_BASE+223)

We use the 223th address, because this address is unused.

3.linux/arch/arm/kernel/call.S

Bind the definition and the address of our syscall function.

We have function definition in sys_arm.c and function address in unistd.h. Then we should tell the system, these two is associated.

Add this line in the file:

CALL(sys_mysyscall)

Be sure that this line is added in the 223th entry.

4. linux/include/linux/syscalls.h

Add the declaration of the syscall.

We must let system know 'ther is' a syscall 223. As we usually do, add the feclaration of the function to *.h:

asmlinkage long sys_mysyscall(int num);

Now the syscall is added in the linux kernel. Begin to compile the kernel.


Compile kernel

Personally, I create a new directory kernel-build for output.

That is /home/darren/opt/raspberry/kernel-build. It is not necessary.

Clean

Firstly, clean the project.

#Do you know that who is Mr.Proper? Ha...
make mrproper

Configure

Secondly, configure for your Raspberry.

There are some differences between RPi1 and RPi2. But luckily, the official offer us a template. We need not to do this by our own.

#RPi1
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
O=/home/darren/opt/raspberry/kernel-build bcm_defconfig

#RPi2
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
O=/home/darren/opt/raspberry/kernel-build bcm2709_defconfig

Okay, that is so easy...

Make

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
O=/home/darren/opt/raspberry/kernel-build -j 12

Here '-j n' is the number of thread (Is it right? ). To speed up, let it be the 1.5 * the number of processors of your pc.

And you may know the nomber of processor by

cat /proc/cpuinfo | grep processor | wc -l 

Install

Insert the sd card to computer. You may get two directories--root and boot.

Denote them like these two:

/media/boot/
/media/root/

Then run this command:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=/home/darren/opt/raspberry/kernel-build -j 12 INSTALL_MOD_PATH=/media/root/ modules

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=/home/darren/opt/raspberry/kernel-build -j 12 INSTALL_MOD_PATH=/media/root/ modules_install

Your could replace the kernel.img(or kernel7.img for RPi2) with linux/arch/arm/boot/Image

cp linux/arch/arm/boot/Image /media/boot/

Reboot and all is well.


Syscall

Finally, write a function to call our function:

void inline_asm(int num)
{
    asm volatile (
        "mov r7, #223\n"     //系统调用号
        "mov r0, %[value]\n" //参数
        "svc #0\n"           //监督调用
        :: [value] "r" (num) //return 留空,并将 num 作为传入参
    );
}

int main()
{
    int num = 10;
    syscall(223, num); //直接使用 223 号系统调用
    num = num << 2;
    inline_asm(num);
    return 0;
}

posted @ 2016-01-21 22:30  DarryO  阅读(303)  评论(0编辑  收藏  举报