2012-09-10 15:38:21 taozi343805436 阅读数 1781

1.获取内核移植源码

http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.2.tar.bz2

2.解压内核源码

(1).bzip2 -d linux-2.6.32.2.tar.bz2

(2).tar -xvf  linux-2.6.32.2.tar

3.修改总目录下的Makefile

原:

export KBUILD_BUILDHOST := $(SUBARCH)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=


改为
export KBUILD_BUILDHOST := $(SUBARCH)
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
其中,ARCH 是指定目标平台为 arm, CROSS_COMPILE 是指定交叉编译器,这里指定的是系统默认的交叉编译器,如要使用其它的,则要把编译器的全路径在这里写出。

4.测试一下linux编译是否能通过

 #make s3c2410_defconfig ;使用缺省内核配置文件,s3c2410_defconfig 是 SMDK2440 的缺省配置文件
 #make ;编译时间较长

5.克隆建立自己的平台

5.1 linux-2.6.32.2/arch/arm/mach-s3c2440 目 录 下 有 个mach-mini2440.c 文件,它其实就是国外爱好者为 mini2440 移植添加的主要内容了,但我们不需要,直接删除。

5.2 将 linux-2.6.32.2/arch/arm/mach-s3c2440/目录下的 mach-smdk2440.c 复制一份。命名为mach-mini2440.c , 找 到 MACHINE_START(S3C2440, "SMDK2440") , 修 改 为
MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board")

5.3修改时钟源频率

mach-mini2440.c( 就 是 我 们 刚 刚 通 过 复 制mach-smdk2440.c 得到的)的第 160 行 static void __init smdk2440_map_io(void)函数中,把其中的 16934400(代表SMDK2440 目标板上的晶振是 16.9344MHz)改为 mini2440 开发板上实际使用的 12000000(代表 mini2440 开发板上的晶振 12MHz,元器件标号为 X2)

因为我们要制作自己的 mini2440 平台体系,因此把 mach-mini2440.c 中所有的smdk2440 字样改为 mini2440,可以使用批处理命令修改,在 vim 的命令模式下输入:
%s/smdk2440/mini2440/g
上面这句的意思是:把所有和“smdk2440”匹配的字符串全部替换为“mini2440”,前面的“%s“代表字符串匹配,最后的“g”代表 global,是全局的意思。
除此之外,还有一个地方需要改动,在 mini2440_machine_init(void)函数中,把smdk_machine_init()函数调用注释掉,因为我们后面会编写自己的初始化函数,不需要调用smdk2440 原来的。

6.在 Linux 源代码根目录下执行
#make mini2440_defconfig ;使用 Linux 官方自带的 mini2440 配置
#make zImage ;编译内核,时间较长,最后会生成 zImage
重新编译并把生成的内核文件 zImage(位于 arch/arm/boot 目录)下到板子中,可以看到内核已经可以正常启动了。








2011-09-29 00:38:28 qb_2008 阅读数 2668

虽然一直对linux抱有企图,但直到前几天才开始实际动手。首先是自己编译linux内核。

编译在ubuntu 10.04下进行,系统使用的版本是linux-2.6.32-28,自己编译的是linux-2.6.32。

现在linux编译配置变得比较傻瓜化,默认会把许多不必要的模块编译进来,也基本可以满足启动需要。

但在实际编译过程中还是遇到了一些问题,以下分点列出,以供参考。


1、编译进去的文件系统。因为现在ubuntu安装都会使用最新的ext4文件系统,自己编译时也要注意将其编译进去。


2、编译进去的硬盘驱动。本来个人的pc或笔记本都是SATA接口(这主要是由于intel芯片组的选择),但linux会通过libata把SATA接口抽象成SCSI接口。所以编译时最好把SATA和SCSI的都加上去。其中SATA中有一个AHCI的驱动选项,这个是Intel HM55/3400系列芯片组中需要的驱动,没有的话无法访问硬盘。ubuntu原本内核的做法是将其编译成模块,放到initrd.img中。如果要把AHCI编译成模块,就要使用initrd,不过也很方便,直接用mkinitrd 命令就可以了,只是这样生成的initrd.img会很大,grub2加载起来有明显的延迟。最方便的还是直接把AHCI编译进内核。


3、NVIDIA驱动。其实只要注意前面的问题,我编译的内核就已经可以正常启动ubuntu了。只是电脑使用的是NVIDIA的显卡,还没有开源模块,需要使用NVIDIA官方提供的驱动nvidia-current。但nvidia-current使用了dkms工具管理的。而dkms对驱动在不同linux内核版本下的兼容问题是否注意,所以我原有的nvidia-current.ko在linux-2.6.32中加载不了。解决方法很简单,在新内核下再编译安装一次nvidia-current。先是dkm build,再是dkms install,就可以在两个内核下都使用nvidia显卡了。


2013-04-12 11:53:03 yanceylu 阅读数 379

说明:修改linux2.6.32.2内核源码,编写一个新的系统调用。



已上传至资源

2019-02-02 19:16:04 zuowanbishe 阅读数 35

transplant LZMA compression algo from linux2.6.32 to linux2.6.29

不同的压缩算法的压缩效率、压缩/解压缩时间不同。LZMA的压缩率要比gzip高的多。最近项目中遇到系统镜像超出分区大小的问题,这个问题可以通过改变内核压缩算法来解决。可惜项目中所使用的内核linux2.6.29版本太低,仅支持gzip压缩,不支持LZMA压缩,所以我们从高版本内核中移植LZMA和bzip2压缩算法来解决这一问题。

目标

  • 从linux2.6.32移植LZMA和bzip2到linux2.6.29
  • 目标架构为powerpc
  • initramfs采用LZMA压缩,image镜像采用gzip压缩

如何选择LZMA来压缩initramfs

在内核配置中,需要选择支持LZMA并且选择built-in initramfs compression mode 为LZMA

    General setup --->
         [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support                             
         (../../../product/s3000gb/rootfs) Initramfs source file(s)                                 
         (0)     User ID to map to 0 (user root)    
         (0)     Group ID to map to 0 (group root)  
         [*]   Support initial ramdisks compressed using gzip                                           
         [ ]   Support initial ramdisks compressed using bzip2                                          
         [*]   Support initial ramdisks compressed using LZMA                                           
               Built-in initramfs compression mode (LZMA)  --->       

移植过程

我们先查找与Support initial ramdisks compressed using LZMA 相关的代码,我们可以通过查看此配置选项的help信息来找到具体的文件,help信息中有两个相关的宏

Symbol: RD_LZMA [=y]
Depends on: BLK_DEV_INITRD [=y] && EMBEDDED [=y]
Selects: DECOMPRESS_LZMA

我们在2.6.32中搜索 RD_LZMA, 会发现大部分的引用都是在/arch/xx/config/xxx_defconfig文件中,我们不去关心,下面列出了我们需要关心的所有搜索结果

usr/Kconfig: config RD_LZMA
usr/Kconfig:    depends on RD_LZMA

我们发现其实RD_LZMA仅在usr目录下有引用,其实在内核编译时,usr/built-in.o 主要就是initramfs的镜像,我们定制initramfs是通过创建一个cpio格式的档案文件来实现的,我们就是要实现用LZMA来压缩这个cpio文件。

我们查看一下usr目录下的文件, 单从文件名已经能够推理出各个文件的关系,我们可以直接同步到linux2.6.29中

root@99-252:~/V2.1.5.67086/kernel/uClinux/linux-2.6.32.x/usr# ls -al

-rw-r--r--  1 13448 6406 12543  5月 17  2016 gen_init_cpio.c
-rw-r--r--  1 13448 6406  1024  5月 17  2016 initramfs_data.bz2.S
-rw-r--r--  1 13448 6406  1023  5月 17  2016 initramfs_data.gz.S
-rw-r--r--  1 13448 6406  1025  5月 17  2016 initramfs_data.lzma.S
-rw-r--r--  1 13448 6406  1021  5月 17  2016 initramfs_data.S
-rw-r--r--  1 13448 6406  4514  5月 17  2016 Kconfig
-rw-r--r--  1 13448 6406  2154  5月 17  2016 Makefile

这些文件具体的功能是什么呢?具体到每个文件里面去看一下,发现其实这些文件里面没做什么有价值的操作,仅仅是根据kconfig指定了cpio的压缩格式。

接下来我们再去找另一个宏DECOMPRESS_LZMA,找的方法和上一个一样,我们先在linux2.6.32中查找这个宏,同样的,会有很多arch/xx/configs/xxx_defconfig文件中有引用,这些我们不去关系,下面列出了除defconfig之外的引用。

// squashfs是压缩只读文件系统,能够压缩系统内的文档,inode以及目录,显然这个我们也无需关心
fs/squashfs/Kconfig:    select DECOMPRESS_LZMA
fs/squashfs/Kconfig:    select DECOMPRESS_LZMA_NEEDED

// 头文件,显然这个必须移植
include/linux/decompress/unlzma_mm.h:#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)

// 解压缩相关的文件,显然这个我们必须移植
lib/decompress.c:#ifndef CONFIG_DECOMPRESS_LZMA
lib/Makefile:lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
lib/Kconfig:config DECOMPRESS_LZMA
lib/Kconfig:config DECOMPRESS_LZMA_NEEDED
lib/decompress_unlzma.c:#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)

// 已经同步过了,不再需要关心
usr/Kconfig:    select DECOMPRESS_LZMA

我们发现其实我们只需要移植头文件和lib目录下的解压缩文件就可以了,移植的方法是对比相应的目录找到相关的代码,同步,需要注意makefile和kconfig也需要相应的修改。

移植完成后咱们来尝试编译一下kernel, 先进入menuconfig设置一下新增的配置,勾选之前描述的选项,然后编译

我们发现确实生成了lzma的cpio文件

make kernel
scripts/kconfig/conf -s arch/powerpc/Kconfig
  CHK     include/linux/version.h
  CHK     include/linux/utsrelease.h
  SYMLINK include/asm -> include/asm-powerpc
  CALL    scripts/checksyscalls.sh
sed: can't read /home/chenhao/ros5.4/br_ros5.4_rsp_dev_20161214/rsp/kernel/linux-2.6.29.6-bmw/arch/x86/include/asm/unistd_32.h: No such file or directory
  CHK     include/linux/compile.h
  GEN     usr/initramfs_data.cpio.lzma
  AS      usr/initramfs_data.lzma.o
  LD      usr/built-in.o

但最终编译出的镜像大小没有改变,这是什么原因呢?

我们相信LZMA的压缩率是比gzip高的多的,而且我们也可以实际验证这一点

root@ubuntu:~/test_lzma# lzma -k initramfs_data.cpio 
root@ubuntu:~/test_lzma# gzip initramfs_data.cpio
root@ubuntu:~/test_lzma# ls -al
-rw-r--r--  1 root    root    63202304 Jul 11 05:10 initramfs_data.cpio
-rw-r--r--  1 root    root    21340431 Jul 11 05:10 initramfs_data.cpio.gz
-rw-r--r--  1 root    root    13816814 Jul 11 05:10 initramfs_data.cpio.lzma

那么极大可能是压缩时没有真正的使用LZMA压缩算法,我们先去看一下cpio压缩文件

root@ubuntu:~/ros5.4/br_ros5.4_rsp_dev_20161214/rsp/kernel/linux-2.6.29.6-bmw/usr# lzmainfo initramfs_data.cpio.lzma 

lzmainfo: initramfs_data.cpio.lzma: Not a .lzma file

看来真的是这样,仅仅是压缩文件名变成了lzma,其实压缩算法没有改变。那么具体initramfs是怎样压缩的呢?还记得我们前面说的usr目录下的那几个文件吗?那几个文件不就是决定压缩算法的吗?一定是那个地方出了问题。

我们先看一下linux2.6.32/usr目录下的Makefile文件

 26 #####
 27 # Generate the initramfs cpio archive
 28 
 29 hostprogs-y := gen_init_cpio
 30 initramfs   := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
 31 ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
 32                         $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
 33 ramfs-args  := \
 34         $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
 35         $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID))
 36 
 37 # .initramfs_data.cpio.d is used to identify all files included
 38 # in initramfs and to detect if any files are added/removed.
 39 # Removed files are identified by directory timestamp being updated
 40 # The dependency list is generated by gen_initramfs.sh -l
 41 ifneq ($(wildcard $(obj)/.initramfs_data.cpio.d),)
 42         include $(obj)/.initramfs_data.cpio.d
 43 endif
 44 
 45 quiet_cmd_initfs = GEN     $@
 46       cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
 47 
 48 targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 initramfs_data.cpio.lzma initramfs_data.cpio
 49 # do not try to update files included in initramfs
 50 $(deps_initramfs): ;

我想大家也发现了,整个makefile没有说压缩什么事,但是30行46行明显是在编译的时候调用了scripts目录下的gen_initramfs_list.sh 的脚本,很多资料都会讲到这个文件的作用,压缩算法一定在这个脚本中指定了,我们去linux2.6.32中看一下

227 is_cpio_compressed=
228 compr="gzip -9 -f"
229 
230 arg="$1"
231 case "$arg" in
232         "-l")   # files included in initramfs - used by kbuild
233                 dep_list="list_"
234                 echo "deps_initramfs := \\"
235                 shift
236                 ;;
237         "-o")   # generate compressed cpio image named $1
238                 shift
239                 output_file="$1"
240                 cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
241                 output=${cpio_list}
242                 echo "$output_file" | grep -q "\.gz$" && compr="gzip -9 -f"
243                 echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
244                 echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
245                 echo "$output_file" | grep -q "\.cpio$" && compr="cat"
246                 shift
247                 ;;
248 esac

282 # If output_file is set we will generate cpio archive and compress it
283 # we are carefull to delete tmp files
284 if [ ! -z ${output_file} ]; then
285         if [ -z ${cpio_file} ]; then
286                 cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
287                 usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
288         else
289                 cpio_tfile=${cpio_file}
290         fi
291         rm ${cpio_list}
292         if [ "${is_cpio_compressed}" = "compressed" ]; then
293                 cat ${cpio_tfile} > ${output_file}
294         else
295                 (cat ${cpio_tfile} | ${compr}  - > ${output_file}) \
296                 || (rm -f ${output_file} ; false)
297         fi
298         [ -z ${cpio_file} ] && rm ${cpio_tfile}
299 fi

确实这里面实现了cpio的压缩,那么不多说,把这些都同步过去。

同步完成之后,再次编译,编译通过,镜像大小已经由23M变为15M,显然第一步压缩搞定;接下来我们就要启动一下这个镜像,看看启动时根文件系统解压缩是否有问题。

很不幸,启动时内核报错

Kernel panic - not syncing: bad gzip magic numbers

不要慌,有错误打印就好办,从打印看很明显是内核还以为根文件系统是gzip压缩格式的。

我们先找到具体打印的位置

2.6.32内核

// lib/inflate.c
1187 /*
1188  * Do the uncompression!
1189  */
1190 static int INIT gunzip(void)
1191 {

1203     if (magic[0] != 037 ||
1204         ((magic[1] != 0213) && (magic[1] != 0236))) {
1205             error("bad gzip magic numbers");
1206             return -1;
1207     }

// lib/decompress.c
 static const struct compress_format {
 27         unsigned char magic[2];
 28         const char *name;
 29         decompress_fn decompressor;
 30 } compressed_formats[] = {
 31         { {037, 0213}, "gzip", gunzip },
 32         { {037, 0236}, "gzip", gunzip },
 33         { {0x42, 0x5a}, "bzip2", bunzip2 },
 34         { {0x5d, 0x00}, "lzma", unlzma },
 35         { {0, 0}, NULL, NULL }
 36 };
 37 
 38 decompress_fn decompress_method(const unsigned char *inbuf, int len,
 39                                 const char **name)
 40 {
 41         const struct compress_format *cf;
 42 
 43         if (len < 2)
 44                 return NULL;    /* Need at least this much... */
 45 
 46         for (cf = compressed_formats; cf->name; cf++) {
 47                 if (!memcmp(inbuf, cf->magic, 2))
 48                         break;
 49 
 50         }
 51         if (name)
 52                 *name = cf->name;
 53         return cf->decompressor;
 54 }
 
// init/initramfs.c
414 static char * __init unpack_to_rootfs(char *buf, unsigned len)
415 {
447                 decompress = decompress_method(buf, len, &compress_name);

2.6.29内核

479 static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
480 {
515                 gunzip();

相信通过上面的代码片段大家已经了解了initramfs是如何解压缩的,不多说,接着同步代码,主要是将decompress_method 移植过来,其他的不动。

修改完后,我们再次编译,启动,initramfs已经能够正常解压缩了,至此,移植活动就完成了。

后记

在做这个的时候也想过直接去找内核的path,但找起来比较复杂,就放弃了这个思路。

对于内核的编译、压缩、解压缩需要进一步深入研究。

2019-09-29 14:00:43 liuqiang55888 阅读数 14

编译linux2.6.x内核问题记录

Ubuntu16.04 内核版本4.15.10 gcc版本4.4(gcc版本问题不明确,也许高了也行)

编译linux2.6.10内核遇到的问题
  • gcc 版本太高 解决方案
  • 编译时代码中出现三次如下错误:error: array type has incomplete element type 未解决
编译Linux2.6.32内核遇到的问题
  • 编译时gcc版本为4.4
  • 出现如下错误
Can't use '!defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373.

解决方法是按照提示将对应行defined()删去 参考网址

  • make时使用命令 make -j8 2> warn.log将错误和警告信息输入到日志文件 -j8表示采用8个进程编译,使用几个进程根据CPU线程数确定。
  • make install时出现错误 参考网址 错误图片
    由于Ubuntu版本太高,尝试更换为Ubuntu14.04或更低
将系统版本更换为Ubuntu12.04, 内核版本3.x gcc版本为4.6
  • 编译Linux2.6.10内核时仍然出现了前面的错误
  • 按照正常步骤编译Linux2.6.39内核时成功编译并安装
  • 编译Linux2.6.18内核时遇到的问题及解决方案
没有更多推荐了,返回首页