Skip to content

Instantly share code, notes, and snippets.

@starwing
Created July 5, 2013 23:18
Show Gist options
  • Save starwing/5937805 to your computer and use it in GitHub Desktop.
Save starwing/5937805 to your computer and use it in GitHub Desktop.
a kernel module used to read chipid of cubieboard
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
/* procfs routines */
int chipid_show(struct seq_file *p, void *v) {
#define SW_VA_SID_IO_BASE ((const volatile void __iomem*)0xf1c23800)
return seq_printf(p, "Chipid\t\t: %08x-%08x-%08x-%08x\n",
readl(SW_VA_SID_IO_BASE),
readl(SW_VA_SID_IO_BASE + 0x4),
readl(SW_VA_SID_IO_BASE + 0x8),
readl(SW_VA_SID_IO_BASE + 0xC)
);
}
int chipid_single_open(struct inode *inode, struct file *file) {
return single_open(file, chipid_show, NULL);
}
struct file_operations chipid_single_seq_file_operations = {
.open = chipid_single_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
struct proc_dir_entry *entry = NULL;
/* initialize routines */
static int __init chipid_init(void)
{
printk(KERN_ALERT "chipid module loading ...\n");
entry = proc_create("chipid", 0, NULL, &chipid_single_seq_file_operations);
if (entry) {
printk(KERN_ALERT "chipid module load ok, entry = %p\n", entry);
return 0;
}
return -EFAULT;
}
static void __exit chipid_exit(void)
{
printk(KERN_ALERT "chipid module unloading ..., entry = %p\n", entry);
if (entry) {
remove_proc_entry("chipid", NULL);
printk(KERN_ALERT "chipid module unloaded.\n");
entry = NULL;
}
}
MODULE_AUTHOR("Xavier-Wang");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("kernel module used to get chipid of cubieboard!\n");
MODULE_ALIAS("retrieve chipid from procfs");
module_init(chipid_init);
module_exit(chipid_exit);
obj-m := chipid.o
sw@sw-acer:~/Work/Code/procfsk$ make -C /usr/src/linux-headers-3.8.0-25-generic SUBDIRS=$PWD modules
make:进入目录'/usr/src/linux-headers-3.8.0-25-generic'
CC [M] /home/sw/Work/Code/procfsk/chipid.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/sw/Work/Code/procfsk/chipid.mod.o
LD [M] /home/sw/Work/Code/procfsk/chipid.ko
make:离开目录“/usr/src/linux-headers-3.8.0-25-generic”
sw@sw-acer:~/Work/Code/procfsk$ sudo insmod chipid.kosw@sw-acer:~/Work/Code/procfsk$ cat /proc/chipid
Chipid : 63682074-65645f69-682a2076-2c766564
sw@sw-acer:~/Work/Code/procfsk$ sudo rmmod chipid sw@sw-acer:~/Work/Code/procfsk$
sw@sw-acer:~/Work/Code/procfsk$ dmesg | tail
[354923.091725] type=1400 audit(1373061974.062:42): apparmor="DENIED" operation="open" parent=3490 profile="/usr/bin/evince" name="/media/sw/Private/Downloads/vilua.love" pid=29762 comm="pool" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[354923.092409] type=1400 audit(1373061974.062:43): apparmor="DENIED" operation="open" parent=3490 profile="/usr/bin/evince" name="/media/sw/Private/Downloads/Soundbanks.for.Guitar.Pro.6.rar.emule.td" pid=29762 comm="pool" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[358156.365857] chipid module loading .../n
[358156.365875] chipid module load ok/nchipid module unloaded/n
[358575.034287] chipid module loading .../n<1>[358592.043926] chipid module unloading ..., entry = ce6bf480
[358592.043931] chipid module unloaded.
[358947.262917] chipid module loading ...
[358947.262942] chipid module load ok, entry = e5430ae0
[358970.715428] chipid module unloading ..., entry = e5430ae0
[358970.715434] chipid module unloaded.
sw@sw-acer:~/Work/Code/procfsk$
@ownwaterloo
Copy link

关于$ make -C /usr/src/linux-headers-3.8.0-25-generic SUBDIRS=$PWD modules。
早上我只是发现和我自己编译时的方式不同:
$ touch Makefile # 至少得有一个空的Makefile
$ make -C "$KDIR" "M=$PWD" modules obj-m=hello.o
但当时我不记得这条命令的来源了。

来源在这: https://www.kernel.org/doc/Documentation/kbuild/modules.txt (而且还有将-D传入的方法)
$KDIR 可以是:

  1. source tree的根
    比如 https://github.com/maxnet/linux-allwinner-aufs34 的情况。
  2. "/lib/modules/$(uname -r)/build"
    比如 $ sudo apt-get install "linux-headers-$(uname -r)" 的情况。
  3. "lib/modules/$(uname -r)/build"
    比如
    $ apt-get download "linux-headers-$(uname -r)"
    $ dpkg -x "linux-headers-$(uname -r)*.deb" "linux-headers-$(uname -r)"
    $ cd "linux-headers-$(uname -r)/lib/modules/$(uname -r)/build"
    $ export KDIR="$PWD"

apt-get download不需要root权限, 但我印象中deb解压后 ./usr/src/... 作KDIR是不行的, 软链接是无效的。 用./lib/... 是直接就可以:
$ make -C "$KDIR" "M=$PWD" modules obj-m=hello.o
但之前有遇见过需要到kernel里make module_prepare还是make scripts的情况。 忘了到底是以 usr 还是以 lib 作为KDIR, 也忘了是apt得到的还是cb的还是berryboot的kernel tree。

这些就是我说的清理工作的一部分。
最终虽然是弄出来了,但这个过程中犯过不少错,而且在弄出来之前也没有耐心和时间一个一个去排查,而是直接试下一个方法。
现在在有一些经验后回过头再去看那些错误也许就能解决,比如发现其实是自己某些步骤搞错了,或者是资料过时了。

虽然目前看来是没时间仔细做这个工作了,但至少得把7-8个conkeror里的打开的页面都再刷一遍吧?
比如: https://www.kernel.org/doc/Documentation/printk-formats.txt
其他语言里的format-string和C有些区别都还可以忍 —— 至少有运行时类型检查。
C里的format-string要是弄错了,编译时就靠gcc那点检查很弱,而运行时根本就没有。
再比如:http://unix.stackexchange.com/questions/24704/how-to-generate-module-symvers#24760
这家伙说$ make modules 就可以得到Module.symvers。
他说得没错,确实可以产生Module.symvers。 但通过这个产生的.ko插不进去。 为什么我也忘了, 反正当时已经耐心全无,直接 $ make 了事。

CONFIG_STRICT_DEVMEM会限制内存访问以及/proc/config.gz 是从这里知道的: https://bbs.archlinux.org/viewtopic.php?id=121964#p956271
但为什么ubuntu上没有 /proc/config.gz? 是哪个参数造成的?
而 $ make sun4i_aufs_defconfig 是从这里找到的: https://github.com/maxnet/berryboot/blob/berryboot2.0/rebuild-berryboot-a10.sh

还有 /proc/kallsyms, /proc/modules, /sys/module/$MODULE/parameters/ 等等这些货我到底是从哪知道的?
提供这些信息的网页上有没有更多相关的有用的信息
诸如此类。

如果时间允许,再多花一些时间,把这些经历小结一下,再下一次遇见这些问题时(这是说不准的事,比如工作站上的wireless现在都没法用)就有门路,不会又无头绪的反复地问google。
不过等个10天半个月的去做这事我也能接受, 记忆力还没衰退到半个月的事完全记不住。 但长期记忆的话, 烂笔头更靠谱。

@ownwaterloo
Copy link

还有一部分(不多,但也不能忽略不计)的时间是花在shell上。

之前的想法是: bash, sed, awk... 这些东西有什么用? 我需要深入学习的只是少数 真正的 编程语言而已。
但大致应该是在学git的时候, 我感觉到一件事: 这套东西是一套用代码而不是文字描述要做什么的方法。
就像讨论其他编程语言的各种问题一样, 用文字很难准确描述, 上代码才是王道。

比如"将/proc/config.gz"的内容解压到.config, 再修改或添加CONFIG_STRICT_DEVMEM=y一行",如果再附带一条shell命令:
$ zcat /proc/config.gz | sed 's|^CONFIG_STRICT_DEVMEM=.*$|CONFIG_STRICT_DEVMEM=n|w/dev/stderr' > .config
读者(可能就是半年后的自己)只要看明白其中任意一项就可以知道要做什么了。甚至不需要看明白, 只要把这个命令复制到终端里执行就可以了, 之后在慢慢体会去。

另外,我还有(也许是坏的)习惯将命令输出的内容作一些变换。
比如将"/usr/src/linux-headers-3.8.0-25-generic"中的3.8.0-25-generic再替换回$(uname -r), "63682074-65645f69-682a2076-2c766564"替换成星号, 将"[354923.092409]"给删除掉,等等。
尽量在其他环境下重复执行指令能有相同的输出。
还会将[354923.091725] type=1400 audit(1373061974.062:42): apparmor="DENIED" operation="open" parent=3490 profile="/usr/bin/evince" name="/media/sw/Private/Downloads/vilua.love" pid=29762 comm="pool" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
这种与问题无关的杂乱信息给去掉。

$ ls -1 /boot/config* | sed "s|$(uname -r)|"'$(uname -r)|'
/boot/config-$(uname -r)
$ sed -r -n 's|^Chipid\t\t: [0-9a-z]{8}-[0-9a-z]{8}-[0-9a-z]{8}-[0-9a-z]{8}$|Chipid\t\t: -**-**-**|p' /proc/cpuinfo
Chipid : ***
-**-**-*******
$ dmesg | sed '$!d;s|^[[ 0-9]+.[0-9]+] ||'
去掉dmesg的时间戳还可以 $ echo N | sudo tee /sys/module/printk/parameters/time

具体config-后跟的是什么,chipid是多少,dmesg的最后一条的时间戳其实都是噪音信息。

@ownwaterloo
Copy link

因为就这两天要把sd卡还给同学,所以打算睡觉前在nand上再编译一次,结果忘记编译前screen一下。
如果关掉工作站(省电)就会断开ssh, cb上的make就挂了。。。

终于编译完了,睡觉去。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment