2010年11月9日 星期二

Ubuntu和mainline kernel的版號關係

Ubuntu kernel會自己maintain ABI number,ABI number會被加入kernel meta-package的版號的一部份,也會用來作為kernel image的package name的一部份。這部份比較複雜,可能要專文討論。

如果只是想查詢Ubuntu kernel某個版號和mainline kernel的對應關係,請見:

http://kernel.ubuntu.com/~kernel-ppa/info/kernel-version-map.html

2010年10月13日 星期三

Ubuntu切換外接video的hotkey作法

首先evdev driver必須從kernel input event得到正確的keycode,在/usr/include/linux/input.h定義為:
#define KEY_SWITCHVIDEOMODE     227


然後在xkb-data套件中定義了kernel keycode到X keycode的mapping:在/usr/share/X11/xkb/keycodes/evdev裡:
<I235> = 235;   // #define KEY_SWITCHVIDEOMODE     227


在/usr/share/X11/xkb/symbols/inet裡:
key <I235>   {      [ XF86Display           ]       };


於是當切換外接video的hotkey按下後,也就是scancode產生時,kernel input event會產生出值為227的keycode,evdev讀到之後,Xserver再依據xkbdata的設定轉換為XF86Display。

接下來gnome-settings-daemon會filter這個X key,如gnome-settings-daemon-2.32.0/plugins/xrandr/gsd-xrandr-manager.c:

if (xev->xany.type == KeyPress) {
if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode)
handle_fn_f7 (manager, xev->xkey.time);
else if (xev->xkey.keycode == manager->priv->rotate_windows_keycode)
handle_rotate_windows (manager, xev->xkey.time);


g-s-d每收到一個XF86Display key時,會呼叫gnome-rr-* 相關的函式(請見libgnomeui/gnome-rr.h),透過RandR API切換螢幕顯示的設定,便會切換到如外接投影機等顯示設備。

參考:http://live.gnome.org/RandR

2010年10月6日 星期三

Kernel: 不列入git log的changelog

對Linux kernel或LKML來說,git log是十分正式的紀錄。不過還是有些時候,我們只想寫一些對於這個patch的意見、或是給subsystem maintainer的一些參考說明,這些東西就不是那麼適合列入正式的git log中。

一個常見的情況是maintainer對於你的patch會有不同意見,此時可能會有patch v2, v3...的出現,而這些版本之間如果可以有簡單的說明的話,對於patch review會有很大的幫助。

像是這些「非正式性」的log,可以被紀錄在diffstat之後,如:

From 1709e3f1b68a12ce05039a52182288d0f4e21c7a Mon Sep 17 00:00:00 2001
From: Keng-Yu Lin <keng-yu.lin@canonical.com>
Date: Tue, 28 Sep 2010 11:11:57 +0800
Subject: [PATCH v5] dell-laptop: Add debugfs support

Export the status of RF killswitch through debugfs.

The killswitch status is obtained by the SMI to BIOS. Exporting this status
through debugfs can help identify the issue with the misbehaving firmware.

Signed-off-by: Keng-Yu Lin <keng-yu.lin@canonical.com>
---
drivers/platform/x86/dell-laptop.c | 77 ++++++++++++++++++++++++++++++++++++
1 files changed, 77 insertions(+), 0 deletions(-)

V5 fixed operator precedence mess-up of hwswitch_state, and prints the
bit number so that this debug info is complete for hardare manufacturers.


diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 4413975..cf8a89a 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
(下略)
Patchwork: https://patchwork.kernel.org/patch/213982/

而在Linux Documentation/SubmittingPatches Section 1.15中也有說明:
Other comments relevant only to the moment or the maintainer, not suitable for the permanent changelog, should also go here. A good example of such comments might be "patch changelogs" which describe what has changed between the v1 and v2 version of the patch.

在live-helper config中加入自訂的套件

將要預設安裝的套件放在config/chroot_local-packages目錄中即可。

參考:Debian Live Manual 6.3.1 Using chroot_local-packages to install custom packages

在live-helper config中加入private PPA

首先確定在config目錄中的bootstrap有這一行:

LH_BOOTSTRAP_INCLUDE="apt-transport-https"


因為private PPA是透過HTTPS。

然後在config/chroot_sources/把PPA的source list加入在myppa.chroot當中。

接下來要加入PPA的public key,將它存在同一個目錄的myppa.chroot.gpg檔案中:

apt-key adv --recv-key <KEYID>
apt-key export <KEYID> > myppa.chroot.gpg


這樣lh build時應該就能加入private PPA。

2010年9月12日 星期日

DKMS和KERNELRELEASE變數

當 Makefile 是從 kernel build system 被呼叫執行時,KERNELRELEASE 變數會被 kbuild 定義。

這是一個常見的 Makefile 小技巧,判斷 KERNELRELEASE 是否定義來執行不同的設定。

如下列是compat-wireless的Makefile,就用到這樣的技巧:

  1. (SKIP)

  2. ifneq ($(KERNELRELEASE),)

  3. NOSTDINC_FLAGS := -I$(M)/include/ \
  4. -include $(M)/include/linux/compat-2.6.h \
  5. $(CFLAGS)

  6. obj-y := compat/

  7. obj-$(CONFIG_COMPAT_RFKILL) += net/rfkill/

  8. ifeq ($(BT),)
  9. obj-$(CONFIG_COMPAT_WIRELESS) += net/wireless/ net/mac80211/
  10. obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/


  11. endif


  12. else

  13. export PWD := $(shell pwd)
  14. CFLAGS += \
  15. -DCOMPAT_BASE_TREE="\"$(shell cat compat_base_tree)\"" \
  16. -DCOMPAT_BASE_TREE_VERSION="\"$(shell cat compat_base_tree_version)\"" \
  17. -DCOMPAT_PROJECT="\"Compat-wireless\"" \
  18. -DCOMPAT_VERSION="\"$(shell cat compat_version)\""

  19. # These exported as they are used by the scripts
  20. # to check config and compat autoconf
  21. export COMPAT_CONFIG=config.mk
  22. export CONFIG_CHECK=.$(COMPAT_CONFIG)_md5sum.txt
  23. export COMPAT_AUTOCONF=include/linux/compat_autoconf.h
  24. export CREL=$(shell cat $(PWD)/compat_version)
  25. export CREL_PRE:=.compat_autoconf_
  26. export CREL_CHECK:=$(CREL_PRE)$(CREL)

  27. include $(PWD)/$(COMPAT_CONFIG)

  28. all: modules

  29. modules: $(CREL_CHECK)
  30. @./scripts/check_config.sh
  31. $(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules
  32. @touch $@

  33. (SKIP)

  34. endif


當從 shell 執行 make 時,因為 KERNELRELEASE 沒有定義,所以第23行到第39行之間的一些變數和 CFLAGS 會被設定,然後第45行會呼叫 kbuild 的 Makefile:
$(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules

之後 compat-wireless 的 Makefile 又會被呼叫一次,此時 KERNELRELEASE 已經被 kbuild 所定義,所以第5行到第18行會被執行。而做的事情就如同一般的 module Makefile 將 driver 的路徑加入 obj-$CONFIG_* 中,如第15行:
obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/




不過,DKMS 在 build module 時會自己傳入 KERNELRELEASE 這個參數,如在 /usr/sbin/dkms:function do_build():
local the_make_command=`echo $make_command | sed "s/^make/make KERNELRELEASE=${kernelver_array[0]}/"`


我們可以看到,在 compat-wireless 的 Makefile 中,當 KERNELRELEASE 變數已被設值時,並沒有 target 可以 build,必須是經由 kbuild 的 Makefile 來 make 才可以。

所以一個 workaround 是在 dkms.conf 中將 MAKE[0] 寫成 make -C /lib/modules/`uname -r`/build M=`pwd` modules。但是在這個例子中我們還必須先在 CLFAGS 中加入一些 define。直接呼叫kbuild的話,這些 CFLAGS 都沒設定,這樣並無法正確的 build 出 module。

所以,一個可行的辦法是將 Makefile 拆開,然後在 dkms.conf:MAKE[0] 中自行指定 Makefile,如:
make -f dkms.mk


雖然必須更改原始的 Makefile,但是卻可讓 DKMS 正確運作。

CONFIG_LOCALVERSION_AUTO和git describe

最近在編譯某家大廠的BSP時,發現kernel version在正常的tag之後被加了一大串東西:
include/config/kernel.release:1:2.6.32.11+drm33.2-16040-g98cebdd

2.6.32.11+drm33.2是Ubuntu Lucid kernel的version沒錯,但是後面的-16040-g98cebdd並不是Ubuntu kernel版號的一部份,看起來是像`git describe`的結果。

執行一下,果然沒錯:

$ git describe
v2.6.31-rc4-16040-g98cebdd

v2.6.31-rc4是某個tag,16040表示目前的HEAD是從tag v2.6.31-rc4之後第16040個commit,g98cebdd表示目前commit的git sha1前幾個值是98cebdd...。

而這個版號是因為 CONFIG_LOCALVERSION_AUTO=y 產生出來的。從LOCALVERSION_AUTO的文義有點難聯想到它的行為。

以下是完整的文件說明:


config LOCALVERSION_AUTO
bool "Automatically append version information to the version string"
default y
help
This will try to automatically determine if the current tree is a
release tree by looking for git tags that belong to the current
top of tree revision.

A string of the format -gxxxxxxxx will be added to the localversion
if a git-based tree is found. The string generated by this will be
appended after any matching localversion* files, and after the value
set in CONFIG_LOCALVERSION.

(The actual string used here is the first eight characters produced
by running the command:

$ git rev-parse --verify HEAD

which is done within the script "scripts/setlocalversion".)