ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年9月30日 星期五

看來好像掛掉。
再 trace 一下 mailinglist:

LKML 的一封:https://lkml.org/lkml/2011/5/21/69
"Rafael J. Wysocki" <>
Subject	[PATCH 0/3] Hibernate cleanups
Date	Sat, 21 May 2011 14:08:28 +0200

Hi,

Following are three hibernate patches I didn't have the time to
work on before.

[1/3] - Update comments in kernel/power/hibernate.c
[2/3] - Remove arch_prepare_suspend()
[3/3] - Update kerneldoc comments in kernel/power/hibernate.c

Since they don't make any functional changes, I don't think it makes sense
to wait with them for the next merge window, so I'd like to push them
for 2.6.40 if no one objects.

Thanks,
Rafael
慘的是..後來 Linus 宣佈沒有 2.6.40,而是 3.0 ...

LKML 的 interface 很好心,會把相關的 repy-discuss 放在一個 tree (頁面的左邊),每點一個 message,要是裡面包含 path,就會出現一個 "diff" 的link,讓你把 patch 拿下來。




這是samsung 基於那個 NOKIA initial work 所做的:
http://permalink.gmane.org/gmane.linux.power-management.general/22773

有提到那個 lds.S 修改。另外他還加上 A9 的 support。


還有 ,當 使用 eMMC /SD 作 resume partition 時,要等待 driver ready,所以
http://www.spinics.net/lists/arm-kernel/msg142548.html

這個 patch 加上 resumewait 參數,等 dev open success..

bookmark : kernel pm mantainer 說明 suspend, hibernation

寫在 https://lkml.org/lkml/2006/7/25/105

bookmark : webcore 導致 browser 當機,VM 重開問題

這個中國人有解答:
http://blog.csdn.net/a345017062/article/details/6394864

問題有列在 google code issue tracker :
http://code.google.com/p/android/issues/detail?id=12987

大概是 java function return class not match 問題。

不過他很大方的寫出 trace bug 的方法,可以學一下。
說要加上 Will Deacon 的 cpu_reset patch。
查一下,在 arch/arm/mm

誰用到?

宣告的地方:./arch/arm/include/asm/cpu-single.h #ifdef __STDC__ #define __catify_fn(name,x) name##x #else #define __catify_fn(name,x) name/**/x #endif #define __cpu_fn(name,x) __catify_fn(name,x) /* * If we are supporting multiple CPUs, then we must use a table of * function pointers for this lot. Otherwise, we can optimise the * table away. */ #define cpu_proc_init __cpu_fn(CPU_NAME,_proc_init) #define cpu_proc_fin __cpu_fn(CPU_NAME,_proc_fin) #define cpu_reset __cpu_fn(CPU_NAME,_reset) #define cpu_do_idle __cpu_fn(CPU_NAME,_do_idle) #define cpu_dcache_clean_area __cpu_fn(CPU_NAME,_dcache_clean_area) #define cpu_do_switch_mm __cpu_fn(CPU_NAME,_switch_mm) #define cpu_set_pte_ext __cpu_fn(CPU_NAME,_set_pte_ext) #include struct mm_struct; /* declare all the functions as extern */ extern void cpu_proc_init(void); extern void cpu_proc_fin(void); extern int cpu_do_idle(void); extern void cpu_dcache_clean_area(void *, int); extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); 所以 cpu_reset( ) 會變成 CPU_NAME_reset

CPU_NAME 定義在 ./arch/arm/include/asm/proc-fns.h # ifdef CONFIG_CPU_V6 # ifdef CPU_NAME # undef MULTI_CPU # define MULTI_CPU # else # define CPU_NAME cpu_v6 # endif # endif # ifdef CONFIG_CPU_V7 # ifdef CPU_NAME # undef MULTI_CPU # define MULTI_CPU # else # define CPU_NAME cpu_v7 # endif # endif 所以 cortext A8 的 kernel config 是: CONFIG_CPU_V7=y 也就是會變成 cpu_v7_reset( )

所以 assembly 的部份要看 cpu_v7_reset, c source 的部份要看 cpu_reset ().
.. 有一堆 source call cpu_reset...



ref:
  1. http://comments.gmane.org/gmane.linux.ports.arm.kernel/119552
  2. http://lists.infradead.org/pipermail/linux-arm-kernel/2011-July/057302.html

2011年9月29日 星期四

build TINY_ANDROID && some worklog on hibernate

問題應該還是在 kernel,android framework 在 suspend/resume 好像沒有限制,只有在特殊的情況會用 wakelock 防止suspend (跟hardware 相關,或是 charging)。
其他部份好像都無關 (pure software component ?)



BUILD_TINY_ANDROID
make -j4 BUILD_TINY_ANDROID=true TARGET_NO_RECOVERY=true showcommands 來 build TINY_ANDROID。
 TINY_ANDROID 不會rebuild recovery,但是 Makefile 卻還是去 make recoveryimage,所以要手動加上 TARGET_NO_RECOVERY=true

build 出來後,到 out 去看 installed-files,果然有一堆沒包 (vimdiff with original build result)


兩個問題:
  1. pmic_adc 在 resume 的時候會 hang 住一陣子
  2. resume 後,shell , rx 沒動作 ,tx好像還 OK,-- 從 shell 的 output 來看

about pmic_adc:
  1. 先回到 resume OK 版本 -- 至少 screen 恢復
  2. 移除 pmic_backlight 和 pmic_XXX (?) -- 看看是否OK
  3. pmic_adc 的 suspend/resume 似乎是以 adc wq 不終止的情況 考慮....

2011年9月28日 星期三

enable LL (Low Level Debugging 後): /toolchain/arm-eabi-4.4.3/bin/arm-eabi-gcc -Wp,-MD,arch/arm/kernel/.debug.o.d -nostdinc -isystem /toolchain/arm-eabi-4.4.3/bin/../lib/gcc/arm-eabi/4.4.3/include -I/kernel_imx/arch/arm/include -Iinclude -include include/generated/autoconf.h -D__KERNEL__ -mlittle-endian -Iarch/arm/mach-mx5/include -Iarch/arm/plat-mxc/include -D__ASSEMBLY__ -mabi=aapcs-linux -mno-thumb-interwork -funwind-tables -D__LINUX_ARM_ARCH__=7 -march=armv7-a -include asm/unified.h -msoft-float -c -o arch/arm/kernel/debug.o arch/arm/kernel/debug.S /toolchain/arm-eabi-4.4.3/bin/arm-eabi-gcc -Wp,-MD,arch/arm/mm/.iomap.o.d -nostdinc -isystem /toolchain/arm-eabi-4.4.3/bin/../lib/gcc/arm-eabi/4.4.3/include -I/kernel_imx/arch/arm/include -Iinclude -include include/generated/autoconf.h -D__KERNEL__ -mlittle-endian -Iarch/arm/mach-mx5/include -Iarch/arm/plat-mxc/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -marm -mabi=aapcs-linux -mno-thumb-interwork -funwind-tables -D__LINUX_ARM_ARCH__=7 -march=armv7-a -msoft-float -Uarm -Wframe-larger-than=1024 -fno-stack-protector -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(iomap)" -D"KBUILD_MODNAME=KBUILD_STR(iomap)" -c -o arch/arm/mm/.tmp_iomap.o arch/arm/mm/iomap.c arch/arm/kernel/debug.S: Assembler messages: arch/arm/kernel/debug.S:167: Error: garbage following instruction -- `ldrne r3,=MX51_AIPS1_IO_ADDRESS(MX51_UART1_BASE_ADDR)' arch/arm/kernel/debug.S:183: Error: garbage following instruction -- `ldrne r3,=MX51_AIPS1_IO_ADDRESS(MX51_UART1_BASE_ADDR)' make[1]: *** [arch/arm/kernel/debug.o] Error 1 make: *** [arch/arm/kernel] Error 2 make: *** Waiting for unfinished jobs.... trace debug.S :167 addruart r3, r1 addruart 定義在 debug-macro.S: .macro addruart, rx, tmp mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? ldreq \rx, =UART_PADDR @ physical ldrne \rx, =UART_VADDR @ virtual 所以是 UART_VADDR 的定義: (debug-macro.S): #include #define UART_PADDR MX51_UART1_BASE_ADDR #define UART_VADDR MX51_AIPS1_IO_ADDRESS(MX51_UART1_BASE_ADDR) 的 MX51_AIPS1_IO_ADDRESS( ) 沒有展開 (定義)。
這個是定義在 mx51.h。
用 git blame 找一下 debug-macro.S ,發現原來是 include mx51.h ,後來在新增 mx5x.h 後,才改為 include mx51.h..

改回去就 build OK...
... 但是..

在 boot argument 加上 earlyprintk 後,bootmessage 在 Uncompressing Linxu... done, booting the kernel. 後,就沒有 message 了...
  1. 先看一下 _LL 造成 Assembly MACRO 展開的 error : 大概看一下就好
  2. 加上 framework, build 一版,注意 partition 問題。 recovery partition不能用,不然就要重新 partition
  3. 那個 DPLL 的 patch 有沒有上

2011年9月27日 星期二

early_printk, DEBUG_LL

http://r40eubuntu.blogspot.com/2011/09/initcall.html

單看 console 的部份。

在 start_kernel 的最後 reset_init 用 kernel_thread 執行 kernel_init

console 好像是 kernel 中很重要的東西(?),在 kerne/printk.c 中。
說明 cosole 依照開機的階段,分為兩種,這說明寫在 regisgter_console( ) 的前面: /* * The console driver calls this routine during kernel initialization * to register the console printing procedure with printk() and to * print any messages that were printed by the kernel before the * console driver was initialized. * * This can happen pretty early during the boot process (because of * early_printk) - sometimes before setup_arch() completes - be careful * of what kernel features are used - they may not be initialised yet. * * There are two types of consoles - bootconsoles (early_printk) and * "real" consoles (everything which is not a bootconsole) which are * handled differently. * - Any number of bootconsoles can be registered at any time. * - As soon as a "real" console is registered, all bootconsoles * will be unregistered automatically. * - Once a "real" console is registered, any attempt to register a * bootconsoles will be rejected */ 大概翻譯一下:
為了要讓 printk, early_printk能正常送出 message,要儘早 call register_console( ) 把 console 掛起來。
console 分為兩種:
1. bootconsole : 為了應付kernel boot 前段,真正的 (real) console 還沒決定的時候,所使用的 console
2. real consol : 就真正的 console。
在real console 被 register 後,bootconsole 就會自動被 unregister,然後就再也不允許有人註冊 boot_console 了。
在 arch/arm/kernal/ 下有 early_prink.c,但是要 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 才會 build 進去。

在 arch/arm/Kconfig include 的 Kconfig.debug 有option:
config EARLY_PRINTK
 bool "Early printk"
 depends on DEBUG_LL
 help
   Say Y here if you want to have an early console using the
   kernel low-level debugging functions. Add earlyprintk to your
   kernel parameters to enable this console.
所以要 enable DEBUG_LL (Kernel low-level debugging functions),才會顯示出來。

2011年9月26日 星期一

vt : virtual terminal (?), 就是 console (?).
在 driver/char/vt.c 有: struct vc vc_cons [MAX_NR_CONSOLES]; MAX_NR_CONSOLES 定義在 include/linux/vt.h: struct vc vc_cons [MAX_NR_CONSOLES];

Accessing Registers from User space

imxwiki有一篇,用 mmap 方式存取整個 imx51 register 的 user tool:
http://www.imxdev.org/wiki/index.php?title=All_Boards_AccessingRegisters
跟以前寫的一篇一樣:http://r40eubuntu.blogspot.com/2011/05/read-soc-register-from-devmem.html

source code 是 GPLed,所以把他copy 到 github (免得不見 XD).
https://github.com/checko/imx_io_test
Wiki 中有說明從 data sheet 對應到 register address 的方法(?).

2011年9月23日 星期五

hibernate . code trace

echo disk > /sys/power/state 收到的是
kernek/power/main.c : static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) suspend to disk 部份超快,就.. if (len == 4 && !strncmp(buf, "disk", len)) { error = hibernate(); goto Exit; } 直接 call kernel/power/hibernate.c 的 hibernate( )



snapshot_device_available 被用作 snaphot 的 mutex,初始是 1,使用時 -1。
也就是說: 1 可用,0 不行。
所以 kernel code 要操作 snapshot 時,都要先作: atomic_add_unless(&snapshot_device_available, -1 ,0) 用來確認 snaphot_device_available 是不是 1 (available),
再繼續動作。

實際上依靠 snaphost_device_avaiable 的 function 有:
  1. hibernate()
  2. software_resume( )
  3. snapshot_open( ) -- user interface of device "snapshot'
pm_notifier_call_chain : call blocking_notifier_call_chain( ).
好像有以下幾個 chain:
  1. PM_HIBERNATION_PREPARE
  2. PM_POST_HIBERNATION
  3. PM_RESTORE_PREPARE
  4. PM_POST_RESTORE

定義在:notifier.h /* Hibernation and suspend events */ #define PM_HIBERNATION_PREPARE 0x0001 /* Going to hibernate */ #define PM_POST_HIBERNATION 0x0002 /* Hibernation finished */ #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ #define PM_POST_SUSPEND 0x0004 /* Suspend finished */ #define PM_RESTORE_PREPARE 0x0005 /* Going to restore a saved image */ #define PM_POST_RESTORE 0x0006 /* Restore failed */
RCU : Read-Copy-Update



static int orig_fgconsole, orig_kmsg; int pm_prepare_console(void) { orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1); if (orig_fgconsole < 0) return 1; orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE); return 0; } void pm_restore_console(void) { if (orig_fgconsole >= 0) { vt_move_to_console(orig_fgconsole, 0); vt_kmsg_redirect(orig_kmsg); } }
driver/char/vt.c
切換 console:
使用 want_console 跟 console_callback( ) 來完成動作:
  1. want_console = new_console;

atomic_add_unless

是說:add unless valus is the given number

arm 版 在 arch/arm/include/asm : atomic.h: static inline int atomic_add_unless(atomic_t *v, int a, int u) { int c, old; c = atomic_read(v); while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) c = old; return c != u; } 然後 cmpxchg 是 static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) { unsigned long oldval, res; smp_mb(); do { __asm__ __volatile__("@ atomic_cmpxchg\n" "ldrex %1, [%3]\n" "mov %0, #0\n" "teq %1, %4\n" "strexeq %0, %5, [%3]\n" : "=&r" (res), "=&r" (oldval), "+Qo" (ptr->counter) : "r" (&ptr->counter), "Ir" (old), "r" (new) : "cc"); } while (res); smp_mb(); return oldval; } 就是 swp. armv6 版.

所以重點在 atomic_cmpxchg((v),c , c+a))


關於 atomic 的操作,可以看 Documentation/atomic_ops.txt

		Semantics and Behavior of Atomic and
		         Bitmask Operations
這個 documsnt 的說明好像跟實做一饃一樣。

atomic_t 宣告在 linux/types.h typedef struct { int counter; } atomic_t; 宣告後,要初始化: (atomic.h) #define ATOMIC_INIT(i) { (i) }


這一篇說得很清楚喔: http://blog.roodo.com/use_the_force/archives/3420371.html

vmware - install vmware tool in ubuntu guest os

會要重 build module,所以要安裝 build-essential, linux-header-$(uname -r)。
還有 path 的問題,所以要手動建 link,否則就會有 kernel-header 找不到的問題。
不然就要改 install script。

2011年9月21日 星期三

initcall, & hibernate, resume, console.

在 include/linux/init.h 有定義: #define early_initcall(fn) __define_initcall("early",fn,early) /* * A "pure" initcall has no dependencies on anything else, and purely * initializes variables that couldn't be statically initialized. * * This only exists for built-in code, not for modules. */ #define pure_initcall(fn) __define_initcall("0",fn,0) #define core_initcall(fn) __define_initcall("1",fn,1) #define core_initcall_sync(fn) __define_initcall("1s",fn,1s) #define postcore_initcall(fn) __define_initcall("2",fn,2) #define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s) #define arch_initcall(fn) __define_initcall("3",fn,3) #define arch_initcall_sync(fn) __define_initcall("3s",fn,3s) #define subsys_initcall(fn) __define_initcall("4",fn,4) #define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s) #define fs_initcall(fn) __define_initcall("5",fn,5) #define fs_initcall_sync(fn) __define_initcall("5s",fn,5s) #define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs) #define device_initcall(fn) __define_initcall("6",fn,6) #define device_initcall_sync(fn) __define_initcall("6s",fn,6s) #define late_initcall(fn) __define_initcall("7",fn,7) #define late_initcall_sync(fn) __define_initcall("7s",fn,7s) 其中 __define_initcall 是: #define __define_initcall(level,fn,id) \ static initcall_t __initcall_##fn##id __used \ __attribute__((__section__(".initcall" level ".init"))) = fn 會把 function 放在 .initcall + level 這個section..

在 init/main.c : kernel_init 會 do_basic_setup( ) --> do_initcalls() static void __init do_initcalls(void) { initcall_t *fn; for (fn = __early_initcall_end; fn < __initcall_end; fn++) do_one_initcall(*fn); /* Make sure there is no pending stuff from the initcall sequence */ flush_scheduled_work(); } 在 vmlinux.lds : . = ALIGN(16); __setup_start = .; *(.init.setup) __setup_end = .; __initcall_start = .; *(.initcallearly.init) __early_initcall_end = .; *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init) __initcall_end = .; ? 為什摩中間有一個 initcallrootfs ?
.. 也就是說各 kernel module 中宣告 xxx_initcall( ) 的 function ,都會以上面 define 的次序,在 start_kernel( ) 時,一一被呼叫..


hibernate.c : late_initcall(software_resume); 因為在 開完後,手動 resume , sh console 是 OK 的,所以改一下 software_resume( ) 的位置...
從 late_initcall( ) 拿出來,在做完 /* Open the /dev/console on the rootfs, this should never fail */ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING "Warning: unable to open an initial console.\n"); 以後再 call,就 OK 了
----> why ?



init/main.c : start_kernel( ) ----> console_init() ----> reset_init( ) -------->kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); ------------>sys_open("/dev/console",..) console_init( ) 跟 上面的 initcall 一樣: void __init console_init(void) { initcall_t *call; /* Setup the default TTY line discipline. */ tty_ldisc_begin(); /* * set up the console device so that later boot sequences can * inform about problems etc.. */ call = __con_initcall_start; while (call < __con_initcall_end) { (*call)(); call++; printk("*"); } } 可以打開 System.map 看 symbol:
800301c4 T __con_initcall_start
800301c4 t __initcall_con_init
800301c4 T __initcall_end
800301c8 t __initcall_mxcuart_console_init
800301cc T __con_initcall_end
其中 __initcall_con_init 和 __initcall_end 是同一個位置,所以實際上只有兩個 function
boot log 會有兩個 *.

editor : sublimetext2

http://lucifr.com/139225/sublime-text-2-tricks-and-tips/

挺不錯的 (可惜要錢,還挺貴的 $60)。
但是開發中免費 (?)

還可以用 vim 的 command 喔...
http://net.tutsplus.com/tutorials/tools-and-tips/sublime-text-2-tips-and-tricks/

開啟 Preference -Global Setting - default

跟 geany 比:

  1. 字型漂亮
  2. 排版漂亮
  3. 有支援 vi command
  4. command line 啟動,每次都會開一個新 session
  5. 沒有 function list --- 要自己弄 ctags ?

build linux dist for imx51

解開 _boundle.tar.gz,會有 doc 跟 source。
解開 source,會要你指定 解開的 目錄,也是以後工作的目錄。
解開後,會要確認 license,然後繼續,最後提醒你,到工作目錄去 run ltib

bsp 用的是 ltib : Linux Target Image Bullder : http://ltib.org/pages/LTIB_generic_v1.4_-_version_6.4.1.pdf
整個 build 動作用 rpm,所以會檢查: Package Minimum ver Installed info ------- ----------- --------------- rpm 0 not installed rpm-build 0 not installed 這兩個command都在 rpm 這個 package,所以 aptitude install rpm 就可以了。

會先 build 自己需要的 tool (即使 host 已經有一套),會放在 /opt/freescale/ltib/
出現 error。
看一下 host_config.log.. compr_lzo.c:29:23: error: lzo/lzo1x.h: No such file or directory 因為沒有 liblzo2-dev。
裝完後繼續 ./ltib,會有 error,所以手動把 /opt/freescale/ltib/usr/src/rpm/BUILD/mtd-utils 目錄刪除,再作 ./ltib

又有 error: mkfs.ubifs.h:48:23: error: uuid/uuid.h: No such file or directory 裝 uuid-dev ,手動刪掉 /opt/freescale/ltib/usr/src/rpm/BUILD/mtd-utils 後繼續..

host tool 都 build 完後,開始 build target image,會出現一個 selection menu..
選好繼續....



build gnome dist 的話,會要一堆 lib-dev,碰到 error 時再裝就可以。

有一個 error: make[2]: Entering directory `/home/charles-chang/L2.6.35/ltib/rpm/BUILD/gtk+-2.14.3/demos' no --raw --build-list \ apple_red ./apple-red.png \ gnome_foot ./gnome-foot.png \ > test-inline-pixbufs.h \ || (rm -f test-inline-pixbufs.h && false) /bin/bash: no: command not found make[2]: *** [test-inline-pixbufs.h] Error 1 make[2]: Leaving directory `/home/charles-chang/L2.6.35/ltib/rpm/BUILD/gtk+-2.14.3/demos' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/home/charles-chang/L2.6.35/ltib/rpm/BUILD/gtk+-2.14.3' make: *** [all] Error 2 error: Bad exit status from /home/charles-chang/L2.6.35/ltib/tmp/rpm-tmp.29984 (%build) 在這一篇 (http://ubuntuforums.org/showthread.php?t=962233 ) 說是缺 mono-mcs。
sudo apt-get install libgdk-pixbuf2.0-dev

這一篇 : http://forums.freescale.com/t5/i-MX-Microprocessors/iMX25-SDK-LTIB-error-with-Ubuntu/td-p/52117

說,安裝後,要刪掉 BUILD/gtk+ .. 後再 build 一次。



哪個 no : command not found,去 gtk/demo/Makefile 看,是 某個 tool : csource 變數設定是 no。
猜是這個是 autoconfig probe 出來的,system 沒有,就寫 no。所以 install necessary package 後,要刪掉 build folder,這樣才會重 run 一次 autoconfig,重新產生 Makefile..

2011年9月20日 星期二

github kerel source of various android tablet

這人很好新的蒐集了一些 android tablet 的 kernel source code:
https://github.com/richardtrip

2011年9月19日 星期一

swsusp for imx51 : worklog

software_resume ( ) 進行 image check, image restore 後,就做 hiberate_restore( ),然後就不會回來了 (?) ...
/** * hibernation_restore - quiesce devices and restore the hibernation * snapshot image. If successful, control returns in hibernation_snaphot() * @platform_mode - if set, use the platform driver, if available, to * prepare the platform firmware for the transition. * * Must be called with pm_mutex held */ int hibernation_restore(int platform_mode) { int error; gfp_t saved_mask; pm_prepare_console(); suspend_console(); saved_mask = clear_gfp_allowed_mask(GFP_IOFS); error = dpm_suspend_start(PMSG_QUIESCE); if (!error) { error = resume_target_kernel(platform_mode); dpm_resume_end(PMSG_RECOVER); } set_gfp_allowed_mask(saved_mask); resume_console(); pm_restore_console(); return error; } 根據 comment, run 完會回到 hibernate_snapshot( ) , 猜是 stack 變更,所以這個 function return 回去會到 hibnation_snapshot( ).



卡在 kernel_imx/driver/base/power/main.c 的 dpm_resume( ) 的: while (!list_empty(&dpm_list)) { dev = to_device(dpm_list.next); get_device(dev); if (dev->power.status >= DPM_OFF && !is_async(dev)) { int error; mutex_unlock(&dpm_list_mtx); error = device_resume(dev, state, false); mutex_lock(&dpm_list_mtx); if (error) pm_dev_err(dev, state, "", error); } else if (dev->power.status == DPM_SUSPENDING) { /* Allow new children of the device to be registered */ dev->power.status = DPM_RESUMING; } if (!list_empty(&dev->power.entry)) list_move_tail(&dev->power.entry, &list); put_device(dev); } 中間有 mmc0: error -110 during reumse (card was remved?) 的 error.
==> 拿掉 mmc0 的 driver ,雖然 error 不再發生了,但是還是一樣卡住...約 48 sec 後才完成這個section。

拿掉 使用 dma 的 uart 後,經過 48 sec 的 resume後,沒有 core dump 了, kernel msg 可以正常的輸出,但是 console input 還是沒回應。
==> 將所有uart 的 DMA 都關掉後,雖然還是要 48 sec,但是 resume 後已經沒有 core dump 了 .... console 依然不回應 ..

在 get_device( )後印出 device 的 init_name,還有 dev->driver->name。發現好像是 pmic_adc 和 pmic_leds 卡住。

拿掉 pmic_led, pmic_backlight (從 menuconfig 拿掉).
==> 剩下 pmic_adc 需要 10 幾秒的 resume 時間,而且是卡在 pmic_adc_resume( ) 中..

拿掉 pmic_adc_resume( ) 中 對 register 的 read/write code 後,就沒有卡住了。
==> 但是 console 還是沒反應..

拿到 uboot 的 resume=? 參數,等開機進入 kernel 後,再用手動 echo 179:4 > /sys/power/resume
==> console 有反應.....所以原因是? .. root 是 ramdisk ?.. console not setup correctly ?

因為 android dev 在 mmcblk 加入一層 block,和kernel 不一樣。
所以,在kernel boot phase,要用以前的 /dev/mmcblk0p4,而不是開機完後的,/dev/block/mmcblk0p4

2011年9月16日 星期五

root only , enable shell

想要建立一個最小 root , 但是要有 shell 跟 busybox。
所以...
但是 android 的 system/core/sh 不是 static executable,有用到 share library。
所以要改一下 Android.mk。
加上: LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_STATIC_LIBRARIES := liblinenoise libc 這樣build 出來的 sh 會變大 (很多)

另外我們自己寫的小程式 oxstub,如果也要放進 root,也要改寫一下 Android.mk. LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_STATIC_LIBRARIES := libcutils libc
附上 使用的 init.rc: on early-init start ueventd on init sysclktz 0 loglevel 7 # setup the global environment export PATH /sbin:/bin on boot class_start default start console start mcustub ## Daemon processes to be run by init. ## service ueventd /sbin/ueventd service mcustub /sbin/xostub service console /sbin/sh console


root : lrwxrwxrwx 1 charles-chang charles-chang 4 Sep 16 15:45 bin -> sbin drwxr-xr-x 2 charles-chang charles-chang 4096 Sep 16 15:45 data -rw-r--r-- 1 charles-chang charles-chang 118 Sep 16 15:45 default.prop drwxr-xr-x 2 charles-chang charles-chang 4096 Sep 16 15:45 dev -rwxr-xr-x 1 charles-chang charles-chang 90132 Sep 16 15:45 init -rwxr-xr-x 1 charles-chang charles-chang 5 Sep 16 15:45 init.freescale.rc -rwxr-xr-x 1 charles-chang charles-chang 363 Sep 16 15:45 init.rc drwxr-xr-x 2 charles-chang charles-chang 4096 Sep 16 15:45 proc drwxr-xr-x 2 charles-chang charles-chang 4096 Sep 16 15:47 sbin drwxr-xr-x 2 charles-chang charles-chang 4096 Sep 16 15:45 sys drwxr-xr-x 2 charles-chang charles-chang 4096 Sep 16 15:45 system -rw-r--r-- 1 charles-chang charles-chang 2089 Sep 16 15:45 ueventd.freescale.rc -rw-r--r-- 1 charles-chang charles-chang 0 Sep 16 15:45 ueventd.goldfish.rc -rw-r--r-- 1 charles-chang charles-chang 3764 Sep 16 15:45 ueventd.rc root tree: myroot2/ |-- bin -> sbin |-- data |-- default.prop |-- dev |-- init |-- init.freescale.rc |-- init.rc |-- proc |-- sbin | |-- adbd | |-- busybox | |-- mcustub | |-- sh | `-- ueventd -> ../init |-- sys |-- system |-- ueventd.freescale.rc |-- ueventd.goldfish.rc `-- ueventd.rc
附上 手動 make root image 的 command: mkbootfs myroot2 | minigzip > myramdisk.img 然後 imx51 的 uboot 需要在做: mkimage -A arm -O linux -T ramdisk -C none -a 0x90308000 -n "Android Root Filesystem" -d myramdisk2.img myuramdisk2.img 填入 64 bytes 的 uboot info



如果要加自己寫的 script,在 boot 的時候 run,要注意,rootfs 的 make system 會修改 file attrib,所以要:
ref :
  1. http://r40eubuntu.blogspot.com/2012/01/root-fs-copy-to-file-attribute.html



製作 static build 的 e2fs tool:

e2fs 相關的 tool 在 /external/e2fsprogs 目錄。
其中... misc.. e2fsck.. 兩個 folder 包涵 tool program。

static build 的方法,就跟上面的一樣,修改 Android.mk:
  1. 增加 LOCAL_FORCE_STATIC_EXECUTABLE := true
  2. 把 LOCAL_SYSTEM_SHARED_LIBRARIES 改為 LOCAL_STATIC_LIBRARIES,並且加入 libc
但是這個 project 還用了很多自己的 library,這些library 都要改成 static: e2fsck/Android.mk | 6 ++++-- lib/blkid/Android.mk | 2 +- lib/e2p/Android.mk | 2 +- lib/et/Android.mk | 2 +- lib/ext2fs/Android.mk | 2 +- lib/uuid/Android.mk | 2 +- misc/Android.mk | 13 ++++++++++--- 其中 lib 的部份都是 build library:
  1. 把 BUILD_SHARED_LIBRARY 改成 BUILD_STATIC_LIBRARY

enable wifi proxy in X10 mini pro

要使用 proxy,要用 iptable,所以 kernel 要 support netfilter。
但是 X10 mini /pro 的 kernel 好像沒有 enable netfilter,所以找到 netfilter的 kernel module,手動 install。
像這一篇說的:http://forum.xda-developers.com/showthread.php?t=1208185 在 xda 的 x8 thread,有人這樣作了。

大概就是這一篇吧: http://forum.xda-developers.com/archive/index.php/t-1184907.html
有build好的 ko 和 install script。

另外 這一篇好像是 build kernel module 的 thread..
http://forum.xda-developers.com/archive/index.php/t-1032270.html

還有,有人說 opera mobile 10.1 版有 proxy 選項,在這裡可以 download:
http://ftp.opera.com/pub/opera/android/mobile/10.1/

2011年9月14日 星期三

Android, imx51 , swsusp -- hibernation .Worklog

grep 一下 *defconfig 的 HIBERNATION。
mips, ppc, sh, x86 都有,但是 ARM 沒有。

在 kernel/power/ 下就有 hibernate.c 等需要的 source code。

在 kernel/power/Makefile 中可以看到: obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \ block_io.o 所以只要在 .config 中 開啟 CONFIG_HIBERNATION=y 就可以了(?)

但是在 make menuconfig 中,沒有 hiberanation 可以選 (Power Management)。

找一下 kernel/power/Kconfig: config HIBERNATION bool "Hibernation (aka 'suspend to disk')" depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE select SUSPEND_NVS if HAS_IOMEM 所以要找 PM 跟 SWAP 跟 ARCH_HIBERNATION_POSSIBLE。
find . -type f -name 'Kconfig' | xargs grep --color ARCH_HIBERNATION_POSSIBLE 結果 arch 下的 mips, sh, x86, s390, powerpc, 都有 這個選項, arm 沒有。
所以修改一下 arch/arm/Kconfig,抄一下其他 arch 的 ARCH_HIBERNATION_POSSIBLE 選項,,
大概就是... config ARCH_HIBERNATION_POSSIBLE bool default y 學一下,寫在 ARCH_SUSPEND_POSSIBLE 後面,因為是在 Power management options ,所以待會 make menuconfig 在 Powermanagement 中會有 hibernation 可以選
因為 default y,所以是 checked

這樣做完就 build 的話,會有 error: kernel/power/hibernate.c:27:25: error: asm/suspend.h: No such file or directory kernel/power/hibernate.c: In function 'create_image': kernel/power/hibernate.c:245: error: implicit declaration of function 'arch_prepare_suspend' make[2]: *** [kernel/power/hibernate.o] Error 1 make[1]: *** [kernel/power] Error 2 make: *** [kernel] Error 2 make: *** Waiting for unfinished jobs.... 缺 asm/suspend.h,就學簡單的,create 一個 arch/arm/include/suspend.h ,宣告一下.. static inline int arch_prepare_suspend(void) { return 0; } 接著 build,出現的 error 是: arm-eabi-4.4.3/bin/arm-eabi-ld: kernel/built-in.o: in function hibernation_restore:elfcore.c(.text+0x349a8): error: undefined reference to 'save_processor_state' arm-eabi-4.4.3/bin/arm-eabi-ld: kernel/built-in.o: in function hibernation_restore:elfcore.c(.text+0x349b8): error: undefined reference to 'swsusp_arch_resume' arm-eabi-4.4.3/bin/arm-eabi-ld: kernel/built-in.o: in function hibernation_restore:elfcore.c(.text+0x349d8): error: undefined reference to 'restore_processor_state' arm-eabi-ld: kernel/built-in.o: in function hibernation_snapshot:elfcore.c(.text+0x34d40): error: undefined reference to 'save_processor_state' arm-eabi-ld: kernel/built-in.o: in function hibernation_snapshot:elfcore.c(.text+0x34d44): error: undefined reference to 'swsusp_arch_suspend' arm-eabi-ld: kernel/built-in.o: in function hibernation_snapshot:elfcore.c(.text+0x34d5c): error: undefined reference to 'restore_processor_state' arm-eabi-ld: kernel/built-in.o: in function saveable_page:snapshot.c(.text+0x36458): error: undefined reference to 'pfn_is_nosave' make: *** [.tmp_vmlinux1] Error 1 沒作的有:
save_processor_state,restore_processor_state ---- kernel/power/hibernate.c使用
swsusp_arch_suspend, swsusp_arch_resume ---- kernel/power/hibernate.c 使用
pfn_is_nosave --- kernel/power/snapshot.c 使用

就抄那個 HIYOSHI 的 patch。
其中 NOSAVEDATA section in lds.S 上了 build 會有錯 (MACRO的原因?)。
ok 後,把 busybox 放上root。開始測試..

開機,make swap ...
# busybox mkswap /dev/block/mmcblk0p4 #busybox swapon /dev/block/mmcblk0p4 開始 hiberate.. # echo disk > /sys/power/state 會看到進suspend, user process 進 refrigerator. write image into partition..
最後是 manually power off ..

斷電,開機進入 uboot command console, 修改 boot argument..
要加上resume=???告訴 kernel 從哪一個 partition 拿 image。
原來想用resume=/dev/block/mmcblk0p4 但是這樣 resume 會說 "/dev/block/mmcblk0p4" 是 null device。
查一下是 init/do_mount.c : name_to_dev_t( ) 的問題,好像不 support 兩層 path。
funciton 的說明是: /* * Convert a name into device number. We accept the following variants: * * 1) device number in hexadecimal represents itself * 2) /dev/nfs represents Root_NFS (0xff) * 3) /dev/ represents the device number of disk * 4) /dev/ represents the device number * of partition - device number of disk plus the partition number * 5) /dev/p - same as the above, that form is * used when disk name of partitioned disk ends on a digit. * * If name doesn't have fall into the categories above, we return (0,0). * block_class is used to check if something is a disk name. If the disk * name contains slashes, the device name has them replaced with * bangs. */只好用第一項 device number in hexdecimal represets itself
ls -l /dev/block 來看,
/dev/block/mmcblk0p4 是 179:4
所以改一下 boot argument.. resume=179:4 就可以正確找到 resume partition, restor

但是 resume 後...卡住...停很久....然後才出現 left refrigerator 的 message。
然後出現 console prompt...但是沒反應..

2011年9月13日 星期二

bookmark : swsusp for arm.

http://patchwork.ozlabs.org/patch/100518/
http://patchwork.ozlabs.org/patch/99297/
http://patchwork.ozlabs.org/patch/97341/
http://patchwork.ozlabs.org/patch/96977/
http://patchwork.ozlabs.org/patch/96719/
http://patchwork.ozlabs.org/patch/96434/

http://ftp.arm.linux.org.uk/git/gitweb.cgi?p=linux-2.6-arm.git;a=commitdiff;h=f6b0fa02e8b0708d17d631afce456524eadf87ff

http://lists.arm.linux.org.uk/lurker/message/20110520.123937.760c528f.en.html


http://www.spinics.net/lists/arm-kernel/msg113025.html
http://www.spinics.net/lists/arm-kernel/msg113709.html

http://elinux.org/Sw_Suspend_Porting_Notes

work_queue

work_queue, work, callback -- 三個組合起來。
  1. work_queue 是一個 linking list,由一個 thread 負責,在 "適當時機" 把 queue 中的 work 取出來一一處理完畢。
  2. work 是一組資料結構,其實重要的地方是 call back function。
  3. work_queue 的"處理 thread" 實際上就是 把 work_queue 中的 work 一一取出,執行 work 裡面的 callback function。
以suspend 為例子:
宣告 work_queue
struct workqueue_struct *suspend_work_queue; 然後 create work queue:
suspend_work_queue = create_singlethread_workqueue("suspend");
要放到 work_queue 的資料 "work",linux 有提供一個MACRO,方便宣告
static DECLARE_WORK(suspend_work, suspend); suspend_work 就是新宣告的 work 資料, suspend 就是這個work 的callback function。
static void suspend(struct work_struct *work) { int ret; int entry_event_num; if (has_wake_lock(WAKE_LOCK_SUSPEND)) { if (debug_mask & DEBUG_SUSPEND) pr_info("suspend: abort suspend\n"); return; ,,,,,
宣告完後,在需要的時候,把 work 放到 work_queue 中,,, queue_work(suspend_work_queue, &suspend_work);
這樣就 OK 了..

work_queue 既然是 queue,所以可以放進很多 work。
以 kernel/power 為例,裡面共 create 了兩個 workqueue: suspend_work_queue,pm_wq。

suspend_work_queue 只有 kernel/power 自己使用,pm_wq 則是 public symbol, kernel 所有的 module 都可以用 (都可以放東西進 pm_wq workqueue裡)。

suspend_work_queue 在 kernel/power 中,被放進去的 work 有:
  1. suspend_work
  2. early_suspend_work
  3. late_resume_work..
.... 那...放進 work_queue 的 work 什麼時候會執行呀?.....



為了方便 kernel module 使用 workqueue, kernel 提供一個 global 的 workqueue,使用這個 workqueue,就不用自己 create_workqueue..
這個 workqueue 就叫做 "公共workqueue"。

使用這個公共 workqueue,就不必用 queue_work( ),因為 work_queue 的名稱已經是 kernel 決定了。
在 kernel/workqueue.c 可以看到: int schedule_work(struct work_struct *work) { return queue_work(keventd_wq, work); } EXPORT_SYMBOL(schedule_work); 用 schedule_work( ) 就是對公共 workqueue keventd_wq 作 queue_work( )。

keventd_wq 也是在 kernel/workqueue.c 產生:
void __init init_workqueue() { .... keventd_wq = create_workqueue("events"); .... --- 所以這個公共的workqueue 的名子叫 "events"...
ref: http://www.ibm.com/developerworks/linux/library/l-tasklets/index.html

sysfs

sysfs 很有趣。

sysfs 好像是 kernel 和 user 間的 interface,kernel module 決定要開放出來的 interface 有哪些。
然後就會在對應的 sys node 中顯示出 interface .

像.. static DEVICE_ATTR(control, 0644, control_show, control_store); 就會在 sys node 中顯示 control 這個 interface。
cat control ,就會呼叫到 control_show。
對 control 的寫入動作,會對應到 contol_store

2011年9月8日 星期四

Change system image size

在此之前,先把 基本的 release ver 做好。
遇到 error: do_inode_allocate_extents: Failed to allocate 32769 blocks 因為 system folder 放了太多東西。

system.img 是用 system/extras/ext4_utils/mkuserimg.sh 做的。
裡面決定一些 default 的 參數。 SIZE=$5 if [ -z $SIZE ]; then SIZE=128M fi default 的 size 是 128M。
是 第 5 個 argument。
在 core/Makefile : define build-systemimage-target @echo "Target system fs image: $(1)" $(call build-userimage-ext-target, $(TARGET_OUT),$(1),system,$(INTERNAL_USERIMAGES_EXT_VARIANT),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)) endef size 是 BOARD_SYSTEMIMAGE_PARTITION_SIZE

所以就 先作 export BOARD_SYSTEMIMAGE_PARTITION_SIZE=384M
再 build 就可了。

可以直接寫在 device/.../BoardConfig.mk 裡 BOARD_SYSTEMIMAGE_PARTITION_SIZE=180M

2011年9月6日 星期二

fastboot : simple protocl to bootloader

在 android source : bootable/bootable/legacy/fastboot_protocol.tx  有說明
The fastboot protocol is a mechanism for communicating with bootloaders
over USB.  It is designed to be very straightforward to implement, to
allow it to be used across a wide range of devices and from hosts running
Linux, Windows, or OSX.
然後剩下的就是 protocol 內容的說明....

由於是bootloader 的 protocol,所以通常拿來作 system image 的 update 用。 以 freescale imx51 為例:
開機後,按下 ENTER 中斷 uboot 開機,進入 command console,輸入 fastboot,進入 fastboot 模式。
PC 端接上 usb,輸入 fastboot devices ,會顯示出目前連線的fastboot 裝置。

PC 端輸入 fastboot help,會顯示 fastboot command。

有關 燒錄 image : bootloader, kernel, ramdisk, system,command 是 fast flash partition file partition 是 uboot 預先定義的,以 emmc 為 boot 裝置時,partition 的切割是:
static int fastboot_init_mmc_sata_ptable(void) { .... /* MBR */ strcpy(ptable[PTN_MBR_INDEX].name, "mbr"); ptable[PTN_MBR_INDEX].start = ANDROID_MBR_OFFSET / dev_desc->blksz; ptable[PTN_MBR_INDEX].length = ANDROID_MBR_SIZE / dev_desc->blksz; /* Bootloader */ strcpy(ptable[PTN_BOOTLOADER_INDEX].name, "bootloader"); ptable[PTN_BOOTLOADER_INDEX].start = ANDROID_BOOTLOADER_OFFSET / dev_desc->blksz; ptable[PTN_BOOTLOADER_INDEX].length = ANDROID_BOOTLOADER_SIZE / dev_desc->blksz; /* kernel */ strcpy(ptable[PTN_KERNEL_INDEX].name, "kernel"); ptable[PTN_KERNEL_INDEX].start = ANDROID_KERNEL_OFFSET / dev_desc->blksz; ptable[PTN_KERNEL_INDEX].length = ANDROID_KERNEL_SIZE / dev_desc->blksz; /* uramdisk */ strcpy(ptable[PTN_URAMDISK_INDEX].name, "uramdisk"); ptable[PTN_URAMDISK_INDEX].start = ANDROID_URAMDISK_OFFSET / dev_desc->blksz; ptable[PTN_URAMDISK_INDEX].length = ANDROID_URAMDISK_SIZE / dev_desc->blksz; /* system partition */ strcpy(ptable[PTN_SYSTEM_INDEX].name, "system"); if (get_partition_info(dev_desc, CONFIG_ANDROID_SYSTEM_PARTITION_MMC, &info)) printf("Bad partition index:%d\n", CONFIG_ANDROID_SYSTEM_PARTITION_MMC); else { ptable[PTN_SYSTEM_INDEX].start = info.start; ptable[PTN_SYSTEM_INDEX].length = info.size; } /* recovery partition */ strcpy(ptable[PTN_RECOVERY_INDEX].name, "recovery"); if (get_partition_info(dev_desc, CONFIG_ANDROID_RECOVERY_PARTITION_MMC, &info)) printf("Bad partition index:%d\n", CONFIG_ANDROID_RECOVERY_PARTITION_MMC); else { ptable[PTN_RECOVERY_INDEX].start = info.start; ptable[PTN_RECOVERY_INDEX].length = info.size; } for (i = 0; i <= PTN_RECOVERY_INDEX; i++) fastboot_flash_add_ptn(&ptable[i]); 也就是...

  1. bootlaoder
  2. kernel
  3. uramdisk
  4. system
  5. recovery
其中 system, recovery 是讀取 emmc 的 parition table 得到的。
所以 eMMC 要預先partition 好..
這樣,燒路的動作就是 fastboot flash kernel uImagefastboot flash uramdisk uramdisk.img 還有 fastboot flash system system.img 燒完之後可以直接下 reboot command: fastboot reboot

2011年9月1日 星期四


  1. 使用 html mode
  2. 選 解譯 html 標記
  3. 使用 br 標記

variable argument list

就是像 printf 一樣的可變個數的參數列。
在 wikipedia 裡說明得很清楚。
printf(const char *fmt,...)
後面的三個 ... 就代表參數個數可變。

可變參數是由 compiler 實做的,在C99 後引入 _VA_ARGS_ 這個 MACRO,用來代表這個功能。
http://en.wikipedia.org/wiki/Variadic_macro

實際implement 這類function 時,利用 va_start,  va_arg, va_end 依序取出參數列內的參數。

但是要作一個 var agumet 的 wrapper function 就麻煩了。
所以 variable argument 的 function 都實做兩個版本:
printf ---> vprintf
sprintf --> vsprintf.

一個是 直接使用 var argument 作為 interface,一個用 va_start 取出的 argument array pointer 作為參數。
所以要作一個 wrapper function 時,就要用 va_start( ) 取出 argument array pointer,再呼叫 v 字頭的 function..
void myprintf(const char *fmt,...) { va_list ap; va_start(ap,fmt); vprintf(fmt,ap); va_end(ap); } --- 用 vprintf,不是 printf。
-I bionic/libc/stdlib -I bionic/libc/string -I bionic/libc/stdio -I bionic/libc -I out/target/product/im/obj/STATIC_LIBRARIES/libc_common_intermediates -I dalvik/libnativehelper/include/nativehelper -I system/core/include -I hardware/libhardware/include -I hardware/libhardware_legacy/include -I hardware/ril/include -I dalvik/libnativehelper/include -I frameworks/base/include -I frameworks/base/opengl/include -I frameworks/base/native/include -I external/skia/include -I out/target/product/im/obj/include -I bionic/libc/arch-arm/include -I bionic/libc/include -I bionic/libstdc++/include -I bionic/libc/kernel/common -I bionic/libc/kernel/arch-arm -I bionic/libm/include -I bionic/libm/include/arch/arm -I bionic/libthread_db/include

標籤

網誌存檔