2011年1月13日 星期四

platfrom_match trace

在kernel內,許多結構內都會包含一個父結構成員,以利結構的轉換。
今天trace platform device,看如何利用platform device structure內的device structure pointer得知platform device structure的位址

呼叫platform_match in drivers/base/platform.c
static  __init struct platform_device *
early_platform_match(struct early_platform_driver *epdrv, int id)
{
    struct platform_device *pd;

    list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
        if (platform_match(&pd->dev, &epdrv->pdrv->driver))
            if (pd->id == id)
                return pd;

    return NULL;
}

這是platform_match的定義
static int platform_match(struct device *dev, struct device_driver *drv)
{
    struct platform_device *pdev = to_platform_device(dev);
    struct platform_driver *pdrv = to_platform_driver(drv);

    /* match against the id table first */
    if (pdrv->id_table)
        return platform_match_id(pdrv->id_table, pdev) != NULL;

    /* fall-back to driver name match */
    return (strcmp(pdev->name, drv->name) == 0);
}

主要今天目標是這行,之前上課時老師有說過,現在才拿出來看 T _ T
struct platform_device *pdev = to_platform_device(dev);

define to_platform_device in include/linux/platform_device.h
#define to_platform_device(x) container_of((x), struct platform_device, dev)


define container_of in include/linux/kernel.h
#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

define offsetof in include/linux/stddef.h
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif /* __KERNEL__ */

offsetof 將0轉換成(TYPE *),即指向0的TYPE指標,((size_t) &((TYPE *)0)->MEMBER)就可以取得此MEMBER在這結構內位址值。

比如說platform_device structure(pd) 內的 device structure(dev)成員位置在0x1004。
假設dev在pd內的相對位址為4,那0x1004減去4就可以得到pd的指標位址。

2010年12月16日 星期四

Virtualbox 上跑 ubuntu10.04 文字模式速度跟烏龜一樣!!

一肚子火...買了Q8400,想說支援VT-x,可以讓Virtualbox編譯快一點,但是事與願違阿...

開了四核,但是編譯速度跟單核差不多...(圖形化下)
但是我的Dell NB(Intel Core i5),在Win7下安裝Virtualbox跑ubuntu10.04多核心卻沒問題阿!!現在在ubuntu10.04下安裝Virtualbox來跑卻有這個大問題!!

想說會不會是ubuntu10.04太肥,那就開個文字模式來編譯,結果更是慘不忍睹...每一行文字都慢得不像話...一怒之下就換8.04.3來測試...文字模式比起10.04好太多了,但是依然要1小時才能make完8.04的kernel source code。

正在Virtualbox官網論壇找解決方法時,突然想到,會不會是因為現在那該死的kernel mode set造成的...所以8.04沒問題,10.04卻慢得可以。

就去google一下答案,果然很快就發現解決文字模式非常慢的方法:
參考網站 : 點我 (ubuntu 官方論壇)

~$ sudo vi /etc/modprobe.d/blacklist-framebuffer.conf
add "blacklist vga16fb" to blacklist-framebuffer.conf

就解決問題了...雖然文字模式不會慢的那麼離譜了...但是編譯時速度依然慢的跟烏龜一樣阿...(怒)

之後有解決方式再來寫...

嗯,不想多開文章,直接加在這。
因為我想要大一點的Console Mode,而Grub2.0與Grub1.5設定不同,故在此記錄。

~$ sudo vi /etc/default/grub
add two line
GRUB_GFXMODE=1024x768x32
GRUB_GFXPAYLOAD_LINUX=keep

~$ sudo update-grub
~$ reboot

這樣console mode就有1024x768啦

2010年11月26日 星期五

dd & skip

看i.MX51文件時,一個蠻有意思的用法,用man的話,資質駑鈍的我實在抓不到他的意思...XD

~$ man dd | grep skip
skip = BLOCKS
skip BLOCS ibs-sized blocks at start of input

文件內有一段是這樣說︰The above u-boot.bin has 1024KB padding at the head of file,for example first executable instruction is at the offset 1KB. If you want to generate a no-padding image, you need do below dd command in host.
$ sudo dd if=./u-boot.bin of=./u-boot-no-padding.bin bs=1024 skip=1
Usually this no-padding uboot image is used in the SD card, for example, program this no-padding uboot image into 1KB offset of SD card so that we do not overwrite the MBR (including partition table) within first 512B on the SD card.

看完man以及文件說明後,就可以推敲出來skip的實際用意。
用上面那個例子簡單來說︰
原本的u-boot填滿前面1KB而不使用,從1K開始的位置開始有實際資料,而後來的u-boot-no-padding,則不填滿那前面的1KB,在寫入SD Card時,則是從offset 1KB開始寫入,前面則是保留給MBR來使用(因為會用到partition table)。

2010年11月22日 星期一

Chome & iBus

揪竟~會擦出什麼火花呢!?

就是...iBus在chrome上會有輸入的Bug...按下Backspace後,就無法看到輸入的字,必須要重新切換輸入法才可以再次輸入... 囧,使用上真的有時候會用得很火大...

這個大Bug還蠻容易Google到的: Google表示...

簡易說明: 因為我本身是使用ubuntu 10.04,所以這邊介紹如何在ubuntu10.04上更新iBus和安裝符合新版iBus的新酷音!

1. 加入 repository PPA address: https://launchpad.net/~shawn-p-huang/+archive/ppa

~$ sudo add-apt-repository ppa:shawn-p-huang/ppa
~$ sudo apt-get update
~$ sudo apt-get install ibus-gtk ibus-qt4 ibus-pinyin ibus-pinyin-db-open-phrase
~$ im-switch -s ibus

Logout and re-login

2. 此時只有拼音可以用...(廢話,剛才下載了一堆pinyin套件XD)
~$ sudo apt-get install ibus-chewing

就可以用iBus和新酷音~在chrome上面也沒有!

新的問題產生...選字時,會將上一次輸入的字也加入一 一...

2010年11月17日 星期三

如何透過RPMS,取得原始碼呢!?

工作要應付客戶千奇百怪的問題,所以複製相同的環境變成很重要的一個課題。

之前就有遇到一個問題,客戶端使用Fedora 14,告知我們kernel version是2.6.35。
我去kernel.org抓下kernel 2.6.35的版本來修改,但是客戶那邊卻回覆我們與他們使用的kernel不同(比較後得知)。怕有些地方會出問題,所以請我們跟他們要用相同的檔案!

原因是因為每一個發行版本都會去將使用的kernel version做自己的一些patch,像著名的RHEL(CentOS)就是patch到跟2.6.18的kernel差非常多XD

那如何取得發行版本所使用的真正kernel source呢!?

Debian系列很簡單,只要透過 apt-get source 套件名稱 即可。
Redhat系列就相對麻煩,因為必須要透過RPMS來取得source code(有錯請告知^^)。

所以進入主題了,如何透過RPMS來取得source code呢!?

1. 取得RPMS的spec
~$ rpm -ivh kernel-2.6.35.6-45.fc14.src.rpm
這時候就會有kernel source以及相當多的patch被放在 ~/rpmbuild/BUILD下面
以及被放在~/rpmbuild/SPECS下面的kernel.spec

2. 透過spec,讓rpmbuild做到將kernel patch完畢然後停止,不然等rpmbuild做完,他也會順道將BUILD底下的東西砍光...
~$ rpmbuild -bp ~/rpmbuild/SPECS/kernel.spec
-bp : Executes the "%prep" stage from the spec file. Normally this involves unpacking the sources and applying any patches.
所以就作到這邊就好! patch好的kernel source就會被放在 ~/rpmbuild/BUILD下面^^

雖然rpm -ivh *.src.rpm會將source and patch放置到BUILD下面,但是避免手動patch出錯,這樣的方式是比較快而且正確的。不然以前都傻傻的rpmbuild到make時強制中斷XD

2010年10月5日 星期二

RALINK RT3070

最近很常用到這個模組,紀錄一下安裝方式。

~$ tar jxf DPO_RT3070_LinuxSTA_V2.3.0.2_20100412.tar.bz2
~$ cd DPO_RT3070_LinuxSTA_V2.3.0.2_20100412


由於make後insmod時會產生很多Unknown symbol,所以修改以下檔案
~$ vi os/linux/rt_linux.c
35 #endif // OS_ABL_SUPPORT //
36 #endif //RTMP_MAC_USB //
37 MODULE_LICENSE("GPL") << 加入這個

~$ make
~$ make install (雖然會產生不少錯誤訊息,但是還是讓他做一些事情 XD)

由於 rt3070sta這隻驅動在載入時會去讀 /etc/Wireless/RT2870STA/RT2870STA.dat (由 kernel message得知)
~$ mkdir -p /etc/Wireless/RT2870STA/
~$ cp RT2870STA.dat /etc/Wireless/RT2870STA/


原先kernel會載入不對得module - rt2800usb,所以必須將他disable。
將以下這幾個加入blacklist
~$ vi /etc/modprobe.d/blacklist.conf

blacklist rt2800usb
blacklist rt2x00usb
blacklist rt2x00lib
blacklist crc_ccitt

再將新的module搬到對的位置就結束了!
~$ cp os/linux/rt3070sta.ko /lib/modules/`uname -r`/kernel/net/wireless/
~$ depmod -a


重開機~結束!

linux/bounds.h No such file or directory

make clean後,會刪除一些檔案,除了.ko之外,也會刪除一些include檔

linux/bounds.h並不是一開始就在kernel source內,而是透過Kbuild產生

~$ make prepare

CHK include/linux/version.h
CHK include/linux/utsrelease.h
SYMLINK include/asm -> include/asm-x86
CC kernel/bounds.s
GEN include/linux/bounds.h
CC arch/x86/kernel/asm-offsets.s
GEN include/asm/asm-offsets.h
CALL scripts/checksyscalls.h

linux/bounds.h就產生了。