为uClinux 2.6.x建立bzImage映像

又是一个相当郁闷的过程……

在之前我写的那篇《将uClinux(linux-2.6.14核)移植到Samsung S3C44B0X》中,由make(或make linux)生成的映像文件为linux-2.6.x/arch/arm/boot/Image,由于没有经过压缩,文件比较大,为1.3MB。于是就想到2.4里对映像文件进行压缩的方法。

打开Makefile,发现在make linux对应块中的“LINUXTARGET”没有定义:

    271 linux linux%_only:
    272         @if [ $(LINUXDIR) != linux-2.5.x -a $(LINUXDIR) != linux-2.6.x -a ! -f $(LINUXDIR)/.depend ] ; then \
    273                 echo "ERROR: you need to do a 'make dep' first" ; \
    274                 exit 1 ; \
    275         fi
    276         $(MAKEARCH_KERNEL) -C $(LINUXDIR) $(LINUXTARGET) || exit 1
    277         if [ -f $(LINUXDIR)/vmlinux ]; then \
    278                 ln -f $(LINUXDIR)/vmlinux $(LINUXDIR)/linux ; \
    279         fi

对比了一下2.4.x中的Makefile,发现在2.6.x的Makefile中少了对LINUXTARGET的赋值,于是在Makefile头部加上:

     41 BUILD_START_STRING = $(shell date)
     42 BUILD_START_UNIX = $(shell date +%s)
     43 LINUXTARGET = bzImage

ok,make一下,又出错了……

linux:/home/work/uclinux/uClinux-dist # make linux
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x bzImage || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  Kernel: arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head-s3c44b0.o
arch/arm/boot/compressed/head-s3c44b0.S:114: unterminated character constant
make[3]: *** [arch/arm/boot/compressed/head-s3c44b0.o] 错误 1
make[2]: *** [arch/arm/boot/compressed/vmlinux] 错误 2
make[1]: *** [zImage] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

打开linux-2.6.x/arch/arm/boot/compressed/head-s3c44b0.S:

    114                                                 @ if delta is zero, we're
    115                 beq     not_relocated           @ running at the address we
    116                                                 @ were linked at.

这是一个该死的错误!!我查错花了大半个下午,却没想到问题出在注释里。AS把注释中的we’re的’re当作一个字符串的开始,真是%^$#%#@……保持其原意改为:

    114                                                 @ if delta is zero, we are
    115                 beq     not_relocated           @ running at the address we
    116                                                 @ were linked at.

make linux通过这个bug,又一个错误出现:

linux:/home/work/uclinux/uClinux-dist # make linux
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x bzImage || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  Kernel: arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head-s3c44b0.o
  LD      arch/arm/boot/compressed/vmlinux
arch/arm/boot/compressed/head-s3c44b0.o(.text+0xd4): In function `wont_overwrite':
: undefined reference to `_load_addr'
make[3]: *** [arch/arm/boot/compressed/vmlinux] 错误 1
make[2]: *** [arch/arm/boot/compressed/vmlinux] 错误 2
make[1]: *** [zImage] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

打开linux-2.6.x/arch/arm/boot/compressed/Makefile,对比2.4.x版中的Makefile,发现其中没有对LOAD_ADDR进行替换:

     85 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/

因此将其改为:

     85 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;

然后打开linux-2.6.x/arch/arm/boot/compressed/vmlinux.lds.in:

     10 OUTPUT_ARCH(arm)
     11 ENTRY(_start)
     12 SECTIONS
     13 {
     14   . = TEXT_START;
     15   _text = .;
     16
     17   .text : {
     18     _start = .;

在第14行插入_load_addr的定义:

     10 OUTPUT_ARCH(arm)
     11 ENTRY(_start)
     12 SECTIONS
     13 {
     14   . = LOAD_ADDR;
     15   _load_addr = .;
     16
     17   . = TEXT_START;
     18   _text = .;
     19
     20   .text : {
     21     _start = .;

[注意] 请确保在配置内核时有将CONFIG_ZBOOT_ROM设置为y,否则ZTEXTADDR和ZBSSADDR的取值将不是我们需要的。linux-2.6.x/arch/arm/boot/compressed/Makefile中:

     77 ifeq ($(CONFIG_ZBOOT_ROM),y)
     78 ZTEXTADDR       := $(CONFIG_ZBOOT_ROM_TEXT)
     79 ZBSSADDR        := $(CONFIG_ZBOOT_ROM_BSS)
     80 else
     81 ZTEXTADDR       := 0
     82 ZBSSADDR        := ALIGN(4)
     83 endif

vendors/Samsung/44B0X/config.linux-2.6.x中默认没有设置CONFIG_ZBOOT_ROM,我们可以手动加上“CONFIG_ZBOOT_ROM=y”:

    142 #
    143 # Boot options
    144 #
    145 CONFIG_ZBOOT_ROM=y
    146 CONFIG_ZBOOT_ROM_TEXT=0x00010000
    147 CONFIG_ZBOOT_ROM_BSS=0x0C400000
    148 CONFIG_CMDLINE=""
    149 # CONFIG_XIP_KERNEL is not set

改变了配置选项后,我不知道怎么样局部修改配置,只好先make distclean,然后重新配置内核……
make linux时又出现问题:

linux:/home/work/uclinux/uClinux-dist # make linux
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x bzImage || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  Kernel: arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head-s3c44b0.o
  CC      arch/arm/boot/compressed/misc.o
In file included from include/asm/arch/uncompress.h:31,
                 from arch/arm/boot/compressed/misc.c:23:
include/asm/arch/uncompress.c:8: warning: function declaration isn't a prototype
include/asm/arch/uncompress.c: In function `s3c44b0x_decomp_setup':
include/asm/arch/uncompress.c:9: warning: control reaches end of non-void function
include/asm/arch/uncompress.c: In function `s3c44b0x_putc':
include/asm/arch/uncompress.c:17: warning: control reaches end of non-void function
  LD      arch/arm/boot/compressed/vmlinux
arch/arm/boot/compressed/misc.o(.text+0x27b8): In function `flush_window':
/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/boot/compressed/misc.c:283: undefined reference to `putstr'
arch/arm/boot/compressed/misc.o(.text+0x2804): In function `error':
/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/boot/compressed/misc.c:288: undefined reference to `putstr'
arch/arm/boot/compressed/misc.o(.text+0x280c):/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/boot/compressed/misc.c:289: undefined reference to `putstr'
arch/arm/boot/compressed/misc.o(.text+0x2818):/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/boot/compressed/misc.c:290: undefined reference to `putstr'
arch/arm/boot/compressed/misc.o(.text+0x2884): In function `decompress_kernel':
/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/boot/compressed/misc.c:309: undefined reference to `putstr'
arch/arm/boot/compressed/misc.o(.text+0x2894):/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/boot/compressed/misc.c:311: more undefined references to `putstr' follow
make[3]: *** [arch/arm/boot/compressed/vmlinux] 错误 1
make[2]: *** [arch/arm/boot/compressed/vmlinux] 错误 2
make[1]: *** [zImage] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

很想杀人,但幸亏没有,不然这问题解决不了了。
打开linux-2.6.x/include/asm/arch/uncompress.h,把:

 39 #define puts(s)                       s3c44b0x_puts(s)

改为

 39 #define putstr(s)                       s3c44b0x_puts(s)

整个世界清静了……

linux:/home/work/uclinux/uClinux-dist # make linux
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x bzImage || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  Kernel: arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head-s3c44b0.o
  CC      arch/arm/boot/compressed/misc.o
In file included from include/asm/arch/uncompress.h:31,
                 from arch/arm/boot/compressed/misc.c:23:
include/asm/arch/uncompress.c: In function `s3c44b0x_putc':
include/asm/arch/uncompress.c:13: warning: control reaches end of non-void function
  LD      arch/arm/boot/compressed/vmlinux
  OBJCOPY arch/arm/boot/zImage
  Kernel: arch/arm/boot/zImage is ready
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
if [ -f linux-2.6.x/vmlinux ]; then \
        ln -f linux-2.6.x/vmlinux linux-2.6.x/linux ; \
fi

看看结果:

linux:/home/work/uclinux/uClinux-dist # ll linux-2.6.x/arch/arm/boot/
总用量 1980
drwxrwxrwx   4 root root     272 2006-09-07 20:21 .
drwxrwxrwx  41 root root    1304 2006-09-07 17:24 ..
drwxrwxrwx   2 root root     176 2005-10-28 08:02 bootp
drwxrwxrwx   2 root root    1048 2006-09-07 20:21 compressed
-rwxr-xr-x   1 root root 1400132 2006-09-07 20:16 Image
-rw-r--r--   1 root root     106 2006-09-07 20:16 .Image.cmd
-rw-rw-rw-   1 root root    1326 2005-10-28 08:02 install.sh
-rw-rw-rw-   1 root root    2405 2005-10-28 08:02 Makefile
-rwxr-xr-x   1 root root  605384 2006-09-07 20:21 zImage
-rw-r--r--   1 root root     133 2006-09-07 20:21 .zImage.cmd

差点没哭出来……

— EOF —

将uClinux(linux-2.6.14核)移植到Samsung S3C44B0X

声明:因本人刚接触embedded不足一个月,乃embedded菜鸟。本文旨在帮助和我一样的菜鸟们少走些弯路,文中若有不对的地方还望各路英豪不吝赐教。

Hily Jiang
Email&Gtalk: hilyjiang at Gmail
Blog: http://hily.me/blog/

经过几天的浴血奋战,总算有点成果了,废话不多说,赶紧把过程记下来。

准备工作花了我不少时间,光是下载uClinux-dist就用了两天,其间还看了些移植相关的文章,不过多数是使用2.4.x核的linux。
准备工作:

开发板:Samsung S3C44B0X
uClinux大礼包:uClinux-dist-20051110.tar.gz(点击下载)
开发工具链:arm-elf-tools-20040427.sh(点击下载)
2.6.14内核:linux-2.6.14.tar.bz2(点击下载)
2.6.14内核的uClinux补丁:linux-2.6.14-uc0.patch.gz(点击下载)
韩国人Hyok S. Choi做的ARM补丁 linux-2.6.14-hsc0.patch.gz(点击下载)

开始前请准备好足够大的空间,我下载了好几个版本的dist和内核源码,差不多用了2.9G。当然,实际上用不到这么大。
我的工作目录结构如下:

linux:/home/work/uclinux # ll
总用量 322030
drwxr-xr-x  2 root root       280 2006-09-05 13:39 .
drwxr-xr-x  7 root root       632 2006-09-05 13:39 ..
-rwxr--r--  1 root root  17589174 2006-09-03 18:49 arm-elf-tools-20040427.sh
-rw-r--r--  1 root root    203995 2006-09-04 14:03 linux-2.6.14-hsc0.patch.gz
-rw-r--r--  1 root root  39172170 2006-09-04 13:44 linux-2.6.14.tar.bz2
-rw-r--r--  1 root root     29942 2006-09-04 14:29 linux-2.6.14-uc0.patch.gz
-r-xr-xr-x  1 root root 272430004 2006-08-30 16:30 uClinux-dist-20051110.tar.gz

工具链的建立:
这一部比较简单,直接运行下载的arm-elf-tools-20040427.sh即可:

linux:/home/work/uclinux # chmod u+x arm-elf-tools-20040427.sh
linux:/home/work/uclinux # ./arm-elf-tools-20040427.sh

准备代码树:
解压uClinux-dist-20051110.tar.gz:

linux:/home/work/uclinux # tar -zxf uClinux-dist-20051110.tar.gz
linux:/home/work/uclinux # ll uClinux-dist
总用量 60
drwxr-xr-x   17 root root    536 2005-11-10 12:20 .
drwxr-xr-x    3 root root    312 2006-09-05 13:45 ..
drwxrwxr-x    2  500   500   608 2005-11-10 12:21 bin
drwxrwxr-x    3  500   500   248 2005-11-10 12:21 config
-rw-rw-r--    1  500   500 18007 1999-11-22 11:46 COPYING
drwxrwxr-x    3  500   500  1600 2005-11-10 12:10 Documentation
drwxrwxr-x   11  500   500   704 2005-11-10 12:21 freeswan
drwxr-xr-x   68  500 users  3128 2005-11-10 12:16 glibc
drwxrwxr-x    2  500   500    72 2005-11-10 12:19 include
drwxrwxr-x   29  500   500   736 2005-11-10 12:21 lib
drwxrwxr-x   15  500   500   528 2005-11-10 12:10 linux-2.0.x
drwxrwxr-x   16  500   500   584 2005-11-10 12:12 linux-2.4.x
drwxr-xr-x   18  500 users   600 2005-11-10 12:21 linux-2.6.x
-rw-r--r--    1  500 users 10303 2005-08-25 11:37 Makefile
drwxrwxr-x   13  500   500   680 2005-11-10 12:14 openswan
-rw-rw-r--    1  500   500  4931 2004-11-11 12:19 README
-rw-rw-r--    1  500   500  1743 2004-01-21 07:49 SOURCE
drwxrwxr-x    5  500   500   312 2005-11-10 12:20 tools
drwxr-xr-x   18  500 users   704 2005-11-10 12:21 uClibc
drwxrwxr-x  212  500   500  5600 2005-11-10 12:21 user
drwxrwxr-x   59  500   500  1504 2005-11-10 12:21 vendors

移除linux-2.6.x,准备用新核替换:

linux:/home/work/uclinux # cd uClinux-dist/
linux:/home/work/uclinux/uClinux-dist # rm -rf linux-2.6.x/

解压linux-2.6.14内核包:

linux:/home/work/uclinux # cd ..
linux:/home/work/uclinux # tar -jxf linux-2.6.14.tar.bz2

为新内核打上补丁:

linux:/home/work/uclinux # cd linux-2.6.14/
linux:/home/work/uclinux/linux-2.6.14 # gzip -dc ../linux-2.6.14-uc0.patch.gz | patch -p1
......
linux:/home/work/uclinux/linux-2.6.14 # gzip -dc ../linux-2.6.14-hsc0.patch.gz | patch -p1
......

将新核移到uClinux代码树中:

linux:/home/work/uclinux/linux-2.6.14 # cd ..
linux:/home/work/uclinux # mv linux-2.6.14 uClinux-dist/linux-2.6.x
linux:/home/work/uclinux # cd uClinux-dist/
linux:/home/work/uclinux/uClinux-dist # ll
总用量 60
drwxr-xr-x   17 root root    536 2006-09-05 13:56 .
drwxr-xr-x    3 root root    312 2006-09-05 13:56 ..
drwxrwxr-x    2  500   500   608 2005-11-10 12:21 bin
drwxrwxr-x    3  500   500   248 2005-11-10 12:21 config
-rw-rw-r--    1  500   500 18007 1999-11-22 11:46 COPYING
drwxrwxr-x    3  500   500  1600 2005-11-10 12:10 Documentation
drwxrwxr-x   11  500   500   704 2005-11-10 12:21 freeswan
drwxr-xr-x   68  500 users  3128 2005-11-10 12:16 glibc
drwxrwxr-x    2  500   500    72 2005-11-10 12:19 include
drwxrwxr-x   29  500   500   736 2005-11-10 12:21 lib
drwxrwxr-x   15  500   500   528 2005-11-10 12:10 linux-2.0.x
drwxrwxr-x   16  500   500   584 2005-11-10 12:12 linux-2.4.x
drwxr-xr-x   18 root root    656 2006-09-05 13:54 linux-2.6.x
-rw-r--r--    1  500 users 10303 2005-08-25 11:37 Makefile
drwxrwxr-x   13  500   500   680 2005-11-10 12:14 openswan
-rw-rw-r--    1  500   500  4931 2004-11-11 12:19 README
-rw-rw-r--    1  500   500  1743 2004-01-21 07:49 SOURCE
drwxrwxr-x    5  500   500   312 2005-11-10 12:20 tools
drwxr-xr-x   18  500 users   704 2005-11-10 12:21 uClibc
drwxrwxr-x  212  500   500  5600 2005-11-10 12:21 user
drwxrwxr-x   59  500   500  1504 2005-11-10 12:21 vendors

在vendors目录下建立Samsung S3C44B0X相关的目录,并准备好相关文件。否则在后面的make menuconfig的vendors中将不会出现44b0的选项。

linux:/home/work/uclinux/uClinux-dist # mkdir vendors/Samsung/44B0X
linux:/home/work/uclinux/uClinux-dist # cp vendors/Samsung/4510B/* vendors/Samsung/44B0X/
linux:/home/work/uclinux/uClinux-dist # cp linux-2.6.x/arch/arm/configs/s3c44b0x_defconfig vendors/Samsung/44B0X/config.linux-2.6.x

内核的配置:
好了,现在可以运行make menuconfig进行内核的配置了:

linux:/home/work/uclinux/uClinux-dist # make menuconfig

如果你的系统中装了ncurse,则会出现以下菜单:

Vendor/Product Selection  --->
Kernel/Library/Defaults Selection  --->
---
Load an Alternate Configuration File
Save Configuration to an Alternate File

在“Vendor/Product Selection”中选择Vendor为Samsung,Product为44B0X

--- Select the Vendor you wish to target
(Samsung) Vendor
--- Select the Product you wish to target
(44B0X) Samsung Products

在Kernel/Library/Defaults Selection中选择内核版本为linux-2.6.x,Libc选择uClibc,其余选项不动:

(linux-2.6.x) Kernel Version
(uClibc) Libc Version
[ ] Default all settings (lose changes) (NEW)
[ ] Customize Kernel Settings (NEW)
[ ] Customize Vendor/User Settings (NEW)
[ ] Update Default Vendor Settings (NEW)

[EXIT]后保存内核配置,将会出现如下信息:

Saving your kernel configuration...

*** End of Linux kernel configuration.
*** Check the top-level Makefile for additional configuration.
*** Next, you must run 'make dep'.

make[1]: Entering directory `/home/work/uclinux/uClinux-dist'
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x oldconfig
make[2]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/split-include
  HOSTCC  scripts/basic/docproc
  SHIPPED scripts/kconfig/zconf.tab.h
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/kxgettext.o
  HOSTCC  scripts/kconfig/mconf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/lex.zconf.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf -o arch/arm/Kconfig
#
# using defaults found in .config
#
.config:13: trying to assign nonexistent symbol GENERIC_IOMAP
.config:265: trying to assign nonexistent symbol IP_TCPDIAG
.config:266: trying to assign nonexistent symbol IP_TCPDIAG_IPV6
.config:297: trying to assign nonexistent symbol KGDBOE
.config:478: trying to assign nonexistent symbol REISER4_FS
.config:497: trying to assign nonexistent symbol FSCACHE
.config:518: trying to assign nonexistent symbol DEVFS_FS
*
* Linux Kernel Configuration
*
Memory Management Support
  1. MMU (MMU)
  2. MPU (MPU)
> 3. NONE (NO_MU)
choice[1-3?]: 3
*
* Code maturity level options
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?] y
  Select only drivers expected to compile cleanly (CLEAN_COMPILE) [N/y/?] n
*
* General setup
*
Local version - append to kernel release (LOCALVERSION) []
Automatically append version information to the version string (LOCALVERSION_AUTO) [Y/n/?] (NEW)

有一些选项已经在config.linux-2.6.x中设定了,但还有一些选项需要手动进行设置。
这步请根据自己的需要进行设置,注意不要将太多的选项设置为y,否则会增加后面的编译时间。
配置完成会回到一个ncurse的界面,在这里可以对您刚才选错的应用程序部分重新进行配置:

Core Applications  --->
Library Configuration  --->
Flash Tools  --->
Filesystem Applications  --->
Network Applications  --->
Miscellaneous Applications  --->
BusyBox  --->
Tinylogin  --->
MicroWindows  --->
Games  --->
Miscellaneous Configuration  --->
Debug Builds  --->
---
Load an Alternate Configuration File
Save Configuration to an Alternate File

然后退出保存,这样内核的配置就完成了。

内核的编译

完成内核的配置后直接运行make进行编译。
这一步是最让人郁闷的,不仅要等待漫长的编译过程,还有好多意想不到的bug会发生。
准备接受挑战吧:

linux:/home/work/uclinux/uClinux-dist # make
make -C tools/ucfront
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
cc -g -Werror -Wall -DHAVE_MKSTEMP -o ucfront ucfront.c args.c util.c execute.c vasprintf.c
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-gcc
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-g++
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x  || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
  UPD     include/linux/version.h
  SPLIT   include/linux/autoconf.h -> include/config/*
  SYMLINK include/asm-arm/arch -> include/asm-arm/arch-s3c44b0x
  Generating include/asm-arm/mach-types.h
  SYMLINK include/asm -> include/asm-arm
  CC      arch/arm/kernel/asm-offsets.s
arch/arm/kernel/asm-offsets.c:37: warning: `__GNUC_PATCHLEVEL__' is not defined
  GEN     include/asm-arm/asm-offsets.h
  CC      init/main.o
  CHK     include/linux/compile.h
  UPD     include/linux/compile.h
  CC      init/version.o
  CC      init/do_mounts.o
  CC      init/do_mounts_rd.o
  CC      init/do_mounts_initrd.o
  LD      init/mounts.o
  CC      init/initramfs.o
  CC      init/calibrate.o
  LD      init/built-in.o
  HOSTCC  usr/gen_init_cpio
  CHK     usr/initramfs_list
  UPD     usr/initramfs_list
  CPIO    usr/initramfs_data.cpio
  GZIP    usr/initramfs_data.cpio.gz
  AS      usr/initramfs_data.o
  LD      usr/built-in.o
  CC      arch/arm/kernel/compat.o
  CC      arch/arm/kernel/dma.o
  AS      arch/arm/kernel/entry-armv.o
  AS      arch/arm/kernel/entry-common.o
  CC      arch/arm/kernel/irq.o
  CC      arch/arm/kernel/process.o
  CC      arch/arm/kernel/ptrace.o
  CC      arch/arm/kernel/semaphore.o
  CC      arch/arm/kernel/setup.o
arch/arm/kernel/setup.c: In function `cpu_init':
arch/arm/kernel/setup.c:357: warning: implicit declaration of function `dump_cpu_info'
arch/arm/kernel/setup.c: In function `request_standard_resources':
arch/arm/kernel/setup.c:541: warning: assignment makes integer from pointer without a cast
  CC      arch/arm/kernel/signal.o
  CC      arch/arm/kernel/sys_arm.o
  CC      arch/arm/kernel/time.o
  CC      arch/arm/kernel/traps.o
  CC      arch/arm/kernel/io.o
  LD      arch/arm/kernel/built-in.o
  AS      arch/arm/kernel/../mach-s3c44b0x/head.o
  CC      arch/arm/kernel/init_task.o
  LDS     arch/arm/kernel/vmlinux.lds
  CC      arch/arm/mm/consistent-nommu.o
  CC      arch/arm/mm/extable.o
  CC      arch/arm/mm/fault.o
  CC      arch/arm/mm/init.o
arch/arm/mm/init.c: In function `bootmem_init':
arch/arm/mm/init.c:435: warning: assignment makes integer from pointer without a cast
  CC      arch/arm/mm/ioremap.o
  CC      arch/arm/mm/mm-armv.o
  CC      arch/arm/mm/alignment.o
  AS      arch/arm/mm/cache-v4.o
  AS      arch/arm/mm/proc-arm7tdmi.o
arch/arm/mm/proc-arm7tdmi.S:16: asm/constants.h: ?????????
make[2]: *** [arch/arm/mm/proc-arm7tdmi.o] 错误 1
make[1]: *** [arch/arm/mm] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第一击 找不到asm/constants.h:
这个好解决,打开linux-2.6.x/arch/arm/mm/proc-arm7tdmi.S,将#include 删掉即可。
重新make,进入第二击:

linux:/home/work/uclinux/uClinux-dist # make
make -C tools/ucfront
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
make[1]: “ucfront”是最新的。
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-gcc
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-g++
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x  || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  AS      arch/arm/mm/proc-arm7tdmi.o
  LD      arch/arm/mm/built-in.o
  CC      arch/arm/common/rtctime.o
  LD      arch/arm/common/built-in.o
  CC      arch/arm/mach-s3c44b0x/arch.o
arch/arm/mach-s3c44b0x/arch.c:50: warning: `CONFIG_DEBUG_NICKMIT' is not defined
arch/arm/mach-s3c44b0x/arch.c:95: warning: `CONFIG_NICKMIT_DEBUG' is not defined
arch/arm/mach-s3c44b0x/arch.c:93: warning: `struct param_struct' declared inside parameter list
arch/arm/mach-s3c44b0x/arch.c:93: warning: its scope is only this definition or declaration, which is probably not what you want.
arch/arm/mach-s3c44b0x/arch.c:102: warning: implicit declaration of function `MAINTAINER'
arch/arm/mach-s3c44b0x/arch.c:103: initializer element is not constant
arch/arm/mach-s3c44b0x/arch.c:103: (near initialization for `__mach_desc_S3C44B0.boot_params')
arch/arm/mach-s3c44b0x/arch.c:103: parse error before `FIXUP'
arch/arm/mach-s3c44b0x/arch.c:107: initializer element is not constant
arch/arm/mach-s3c44b0x/arch.c:107: (near initialization for `__mach_desc_S3C44B0')
make[2]: *** [arch/arm/mach-s3c44b0x/arch.o] 错误 1
make[1]: *** [arch/arm/mach-s3c44b0x] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第二击 语法错误:
这一击耗了我不少时间,惨痛的过程就不再多说。
出错原因是程序中用到的一些宏没有定义,打开linux-2.6.x/arch/arm/mach-s3c44b0x/arch.c,跳到101行。

    101 MACHINE_START(S3C44B0, "S3C44B0X Development Board")
    102         MAINTAINER("nickmit ")
    103         FIXUP(s3c44b0x_fixup)
    104         INITIRQ(s3c44b0x_init_irq)
    105         INIT_MACHINE(s3c44b0x_init_machine)
    106         INITTIME(s3c44b0x_time_init)
    107 MACHINE_END

再打开linux-2.6.x/include/asm/mach/arch.h,跳到52行,发现上述代码中的MAINTAINER、FIXUP等多个宏都没有定义:

     52 /*
     53  * Set of macros to define architecture features.  This is built into
     54  * a table by the linker.
     55  */
     56 #define MACHINE_START(_type,_name)              \
     57 const struct machine_desc __mach_desc_##_type   \
     58  __attribute__((__section__(".arch.info.init"))) = {    \
     59         .nr             = MACH_TYPE_##_type,    \
     60         .name           = _name,
     61
     62 #define MACHINE_END                             \
     63 };

增加对它们的定义即可解决该问题(INITTIME不知道怎么定义:():

     52 /*
     53  * Set of macros to define architecture features.  This is built into
     54  * a table by the linker.
     55  */
     56 #define MACHINE_START(_type,_name)              \
     57 const struct machine_desc __mach_desc_##_type   \
     58  __attribute__((__section__(".arch.info.init"))) = {    \
     59         .nr             = MACH_TYPE_##_type,    \
     60         .name           = _name,
     61
     62 #define MAINTAINER(n)
     63
     64 #define BOOT_MEM(_pram,_pio,_vio)               \
     65         .phys_ram       = _pram,                \
     66         .phys_io        = _pio,                 \
     67         .io_pg_offst    = ((_vio)>>18)&0xfffc,
     68
     69 #define BOOT_PARAMS(_params)                    \
     70         .param_offset   = _params,
     71
     72 #define VIDEO(_start,_end)                      \
     73         .video_start    = _start,               \
     74         .video_end      = _end,
     75
     76 #define DISABLE_PARPORT(_n)                     \
     77         .reserve_lp##_n = 1,
     78
     79 #define SOFT_REBOOT                             \
     80         .soft_reboot    = 1,
     81
     82 #define FIXUP(_func)                            \
     83         .fixup          = _func,
     84
     85 #define MAPIO(_func)                            \
     86         .map_io         = _func,
     87
     88 #define INITIRQ(_func)                          \
     89         .init_irq       = _func,
     90
     91 #define INIT_MACHINE(_func)                     \
     92         .init_machine   = _func,
     93
     94 #define INITTIME(_func)                         \
     95         .timer	= _func,
     96
     97 #define MACHINE_END                             \
     98 };

再make:

linux:/home/work/uclinux/uClinux-dist # make
make -C tools/ucfront
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
make[1]: “ucfront”是最新的。
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-gcc
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-g++
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x  || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CC      arch/arm/kernel/asm-offsets.s
arch/arm/kernel/asm-offsets.c:37: warning: `__GNUC_PATCHLEVEL__' is not defined
  GEN     include/asm-arm/asm-offsets.h
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  CC      arch/arm/kernel/compat.o
  AS      arch/arm/kernel/entry-armv.o
  AS      arch/arm/kernel/entry-common.o
  CC      arch/arm/kernel/setup.o
arch/arm/kernel/setup.c: In function `cpu_init':
arch/arm/kernel/setup.c:357: warning: implicit declaration of function `dump_cpu_info'
arch/arm/kernel/setup.c: In function `request_standard_resources':
arch/arm/kernel/setup.c:541: warning: assignment makes integer from pointer without a cast
  LD      arch/arm/kernel/built-in.o
  AS      arch/arm/kernel/../mach-s3c44b0x/head.o
  CC      arch/arm/mm/init.o
arch/arm/mm/init.c: In function `bootmem_init':
arch/arm/mm/init.c:435: warning: assignment makes integer from pointer without a cast
  AS      arch/arm/mm/cache-v4.o
  LD      arch/arm/mm/built-in.o
  CC      arch/arm/mach-s3c44b0x/arch.o
arch/arm/mach-s3c44b0x/arch.c:50: warning: `CONFIG_DEBUG_NICKMIT' is not defined
arch/arm/mach-s3c44b0x/arch.c:95: warning: `CONFIG_NICKMIT_DEBUG' is not defined
arch/arm/mach-s3c44b0x/arch.c:93: warning: `struct param_struct' declared inside parameter list
arch/arm/mach-s3c44b0x/arch.c:93: warning: its scope is only this definition or declaration, which is probably not what you want.
arch/arm/mach-s3c44b0x/arch.c:103: warning: initialization from incompatible pointer type
arch/arm/mach-s3c44b0x/arch.c:106: warning: implicit declaration of function `INITTIME'
arch/arm/mach-s3c44b0x/arch.c:107: warning: excess elements in struct initializer
arch/arm/mach-s3c44b0x/arch.c:107: warning: (near initialization for `__mach_desc_S3C44B0')
  CC      arch/arm/mach-s3c44b0x/irq.o
  CC      arch/arm/mach-s3c44b0x/mm.o
arch/arm/mach-s3c44b0x/mm.c:16: warning: `s3c44b0x_map_io' defined but not used
  CC      arch/arm/mach-s3c44b0x/dma.o
  CC      arch/arm/mach-s3c44b0x/time.o
arch/arm/mach-s3c44b0x/time.c:26: warning: `CONFIG_ARM_CLK_ADJUST' is not defined
arch/arm/mach-s3c44b0x/time.c:52: warning: `CONFIG_ARM_CLK_ADJUST' is not defined
arch/arm/mach-s3c44b0x/time.c:64: warning: `CONFIG_DEBUG_NICKMIT' is not defined
arch/arm/mach-s3c44b0x/time.c: In function `s3c44b0x_time_init':
arch/arm/mach-s3c44b0x/time.c:95: `gettimeoffset' undeclared (first use in this function)
arch/arm/mach-s3c44b0x/time.c:95: (Each undeclared identifier is reported only once
arch/arm/mach-s3c44b0x/time.c:95: for each function it appears in.)
arch/arm/mach-s3c44b0x/time.c:99: warning: implicit declaration of function `s3c44b0x_clear_pb'
arch/arm/mach-s3c44b0x/time.c:100: warning: implicit declaration of function `s3c44b0x_unmask_irq'
make[2]: *** [arch/arm/mach-s3c44b0x/time.o] 错误 1
make[1]: *** [arch/arm/mach-s3c44b0x] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第三击 未声明的变量gettimeoffset:
这个也好办,打开linux-2.6.x/arch/arm/mach-s3c44b0x/time.c,将95行注释掉即可:

     95         //gettimeoffset     = s3c44b0x_gettimeoffset;

再make,这次正常地编译了比较长的时间,终于可以歇口气了。
好吧,就来说点其它的。说说我的惨痛过程吧,在编译成功之前我试过许多版本的uClinux以及linux内核,但是每次在编译的过程中都会出错,有些错误在网上可以找到答案,而大多数没有。我在碰到那些网上找不到答案的问题时,往往选择放弃,再换用其它版本。直到大多数新版本的uClinux都被试过后,我才发现没有一个版本是没有问题的。而我解决问题的方式仍然停留在如果在网上找到解决方法上,譬如上面的第二击,我曾用google搜索“arch/arm/mach-s3c44b0x/arch.c”,发现uClinux的邮件列表中有人遇到了和我一样的问题(http://mailman.uclinux.org/pipermail/uclinux-dev/2006-June/038774.html)。这个问题好几个月了都没有人回复,于是我想,他们都解决不了的问题,我应该也没有能力解决吧,弃之……
但是后来我还是自己解决了那个问题,只是个简单的语法问题。搜索引擎能够帮助我们快速地解决问题,但是也容易让人失去独立解决问题的锻炼机会。我太依赖于网络,导致本来自己能够解决的问题没能及早解决,希望各位引以为戒。也许有人(在某个论坛上看到的)说的对:“能在搜索引擎中找到答案的都不是问题。”,用另一种方式来歪解就是:“所有问题只有在搜索引擎中找不到答案时才需要自己动手解决。”。好啦,不说了,又出错了,再来看看

......(略过正常的信息)
/usr/local/bin/arm-elf-ld.real:arch/arm/kernel/vmlinux.lds:919: parse error
make[1]: *** [vmlinux] 错误 1
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第四击 vmlinux.lds分析错误:
老方法,打开linux-2.6.x/arch/arm/kernel/vmlinux.lds,注释掉出错的两行:

    918 /* those must never be empty */
    919 /*
    920 ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
    921 ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
    922 */

担心这样的注释方法会导致其它问题,于是上网搜,发现有些人也是这么解决的:
http://www.handhelds.org/hypermail/familiar/301/30180.html

Delete the line “ASSERT ((__procXXXX …)” in the file vmlinux.lds

And then try to recompile

make zImage

安心了,进入下一个问题。

arch/arm/kernel/built-in.o(.text+0x34d0): In function `cpu_init':
/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/kernel/setup.c:357: undefined reference to `dump_cpu_info'
make[1]: *** [vmlinux] 错误 1
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第五击 dump_cpu_info调用出错:
网上找到说法:
http://www.kernel.org/hg/linux-2.6/?cs=c176368cddac

date:  	Sun Nov 6 19:49:21 2005 +0000 (10 months ago)
files: 	arch/arm/kernel/setup.c
description: 	[ARM] Don't call dump_cpu_info unless we're booting

We don't want to call dump_cpu_info() from cpu_init() after boot since
it produces a lot of unnecessary noise - since cpu_init() gets called
on resume and hotplug cpu insertion events.

既然不需要,那么就直接将它删除掉。
继续make,你会发现,后面的路太平坦了……
一帆风顺绝对不是什么好事,因为祸乱往往就隐匿在平静之中,我肯定后边的配置过程还会出现更多奇怪的问题。
本篇待续……

参考文献:

— EOF —

艰辛的uClinux下载过程!

昨天开始在http://www.uclinux.org/上下载dist版的uclinux(2**MB), 速度真够慢的, 不到10k/s, 又找不到其它镜像, 只好硬着头皮下载了….

今天早上来公司, 发现http://www.uclinux.org/连不上了, 网页都打不开, 难道是服务器挂了?

约半小时后(9:10)再次打开http://www.uclinux.org/, 页面显示如下:

Welcome to the status page for the Toronto and area AMPRnet gateway.

gw.ve3pnx.ampr.org

This is a router only AMPRnet gateway. No public services are available on this machine. However it has replaced the original Toronto AMPRnet gateway that was operated by RYEHAM, the Ryerson Amateur Radio Club. bbs.ve3rpi.ampor.org RYEHAM:VE3RPI has discontinued its operations. As well the bbs.VE3THA.ampr.org has closed operations and was replaced by the SOPRA node VE3CON. Routing for Toronto 44.135.88.0/24, Brampton 44.135.91.0/24, Etobicoke North/West 44.135.93.0/24 and Halton Hills 44.135.95.0/24 has been forwarded by a link from gw.ve3pnx.ampr.org to the bbs.VE3CON.ampr.org machine.

VE3CON:WESTON (44.135.88.3)

At present this SOPRA node VE3CON:WESTON BBS and TCP/IP access point is operational with only limited access on its 1200 BPS 144.910 MHz. The 220MHz link radio to VE3INF:MAIL in Georgetown while in service does not have connectivity as the intermediate 220MHz node VE3PKG-2 is off the air. The system is running a stable verson 2.40 TNOS.
The system has AXIP and netrom interconnections with several Amateur Packet gateways and BBS machine. Including reliable AX.25 mail forwarding with VE3MCH and, VE7RXD

VE3PNX:WSRC (44.135.88.93)

At present this node is experimenting with verson 3.0 TNOS. It is a project of one of the members of the West Side Radio Club of Toronto. If things go well it will replace the existing VE3CON machine.


The West Side Radio club of Toronto and the Southern Ontartio Packet Radio Association (SOPRA) both sponsor the VE3CON:WESTON TNOS bbs.

看来是在换路由器, 不知道什么时候能换好呀?
写的时候发现又连不上了..

哪位朋友已经下载好的, 可否传我一份? 

已下载完毕

 

— EOF —