S5PV210——Linux内核移植

时间:2022-04-15 09:04:58

lib:库文件,注意内核中使用的库都是自己实现的,不会使用C库。

Vmlinux:在内核的根目录下,未压缩的ELF格式的内核镜像。

Image:未压缩,经过arm-linux-objcopy 处理后生成只包含内核数据的一个内核镜像文件(6M),直接加载到内存运行。

zImage:压缩,压缩Image生成的内核镜像,压缩50%(3M)+解压启动代码。自解压后,加载到内存中 。

自解压:zImage运行之前,要进行自解压:arch/arm/boot/compressed/head.S:decompress_kernel(定义misc.c)。

uImage:为u-boot 使用 bootm 命令引导的 Linux 压缩内核映像文件格式。是使用工具mkimage对普通的压缩内核映像文件(zImage)加工而得。它是uboot专用的映像文件,它是在zImage之前加上一个长度为 64字节的“头”,说明这个内核的版本、加载位置、生成时间、大小等信息;其0x40之后与zImage没区别。bootloader一般要占用0X0地址,所以,uImage比zImage的好处就是可以和bootloader 共存。

zImage和uImage的区别:其实就是一个自动跟手动的区别,有了uImage头部的描述,u-boot就知道对应Image的信息,如果没有头部则需要自己手动去设置这些参数。

.config:编译内核时,根据该文件的内容,Makefile 决定“哪些选项需要编译及以何种方式编译”到内核 —— CONFIG_XXX_XXXX

Kconfig配置内核的菜单make menuconfig是通过读取内核各目录下的Kconfig(配置选项文件来生成。通过修改Kconfig文件,虽然可以在配置内核的时候进行选择,但实际上编译内核并不能把XXX.c(自定义源文件)编译进内核。还需要修改 Makefile文件,把内核配置选项和真正的源代码联系起来,修改~/linux-2.6.35.7/arch/arm/mach-s5pv210/Makefile<<<<<将Kconfig中添加的文件变量名和文件关联。 

============================================

内核的 Makefile分为5个组成部分

1.最顶层的Makefile ;

2.内核的.config配置文件;

3.在arch/$(ARCH) 目录下的体系结构相关的Makefile;

4.在 s 目录下的 Makefile.* 文件,是一些Makefile的通用规则(链接编译、模块编译等);

5.各级目录下的大概约500个kbuild Makefile文件。

顶层的Makefile文件读取.config文件的内容,并总体上负责build内核和模块。arch Makefile则提供补充体系结构相关的信息。 s目录下的Makefile文件包含了所有用来根据kbuild Makefile 构建内核所需的定义和规则。

============================================

kbuildMakefile:对于Makefiles的不同组成部分,有一些不同的语法规则,针对的对象也不同。对于大部分内核模块或设备驱动的开发者和使用者来说,最常接触到的就是各层目录下基于kbuild架构的Makefile文件。(文件如何进行编译的规则模块编译,编译链接等

Kbuild Makefile 核心内容主要包括:目标定义就是用来定义哪些内容要做为模块编译,哪些要编译链接进内核。

如:

obj-y  += foo.o

表示由 foo.c 或者 foo.s 文件编译得到 foo.o 并链接进内核,而 obj-m 则表示该文件要作为模块编译。 除了y,m外,obj-x形式的目标都不会被编译。更常见的做法是根据.config文件的CONFIG_变量来决定文件的编译方式,如:Makefile在编译时,根据kbuildMakefile规则,读取.config 文件,来选择如何编译文件【链接编译[y],模块编译[m]】 :obj-$(CONFIG_EXT2) += ext2.o

============================================

patch:为内核打补丁

============================================

顶层的Makefile:需要确定体系架构和 使用的交叉编译器。

191 ARCH            = arm

192 CROSS_COMPILE   =arm-linux-

============================================

Linux内核启动过程总体过程:

1.架构/开发板相关的引导过程:通常使用汇编来编写。1.检查内核是否支持当前架构的CPU处理器;2.检查是否支持当前的开发板。

2.内核通用的启动过程:用C语言来编写。进行内核的初始化全部工作,最后调用rest_init函数创建系统的第一个用户进程 —— init进程

============================================

Linux内核启动过程的代码分析:

1)zImage内核进行自解压并进行运行前的两步检查:arch/arm/kernel/head.S

81        mrc    p15, 0, r9, c0, c0//将存储在协处理器中CPU的ID读到ARM处理器的r9寄存器

82        bl     __lookup_processor_type//内核是否支持此CPU的ID号

381   __proc_info_begin = .;

382   *(.proc.info.init)

383   __proc_info_end = .;

//用r9中CPU的ID号到__proc_info_begin至__proc_info_end中匹配,如果匹配不成功,内核不启动。

============================================

85  bl     __lookup_machine_type

      theKernel(0,  2456,  0x20000100)

                      r0   r1       r2

//用 u-boot通过r1寄存器传递来板子的2456号,到以下内存区域匹配。如果匹配成功,返回开发板结构体,内核继续执行;如果不成功,内核不启动

384   __arch_info_begin = .;

385   *(.arch.info.init)

386   __arch_info_end = .;

2)挂载根文件系统

3)启动init进程

============================================

arch/arm/mach-s5pv210/mach-smdkv210.c开发板文件描述信息:struct machine_desc {

  /*

   * Note! The first fourelements are used

   * by assembler code inhead.S, head-common.S

   */

  unsigned int  nr; /*architecture number */

  unsignedint  phys_io; /*start of physical io  */

  unsignedint  io_pg_offst;/* byte offset for io

           * page tabe entry */

  const char  *name;  /*architecture name */

  unsignedlong   boot_params; /*tagged list    */

  unsignedint  video_start;/* start of video RAM  */

  unsignedint  video_end; /*end of video RAM  */

  unsignedint  reserve_lp0:1; /* never has lp0  */

  unsignedint  reserve_lp1:1; /* never has lp1  */

  unsignedint  reserve_lp2:1; /* never has lp2  */

  unsignedint  soft_reboot:1; /* soft reboot   */

  void    (*fixup)(struct machine_desc *,

         struct tag *, char **,

         struct meminfo *);

  void    (*map_io)(void);/* IO mapping function */

  void    (*init_irq)(void);

  structsys_timer *timer;    /* system tick timer */

  void    (*init_machine)(void);

};

~/workdir/tools/linux-2.6.35.7/arch/arm/tools  vi mach-types

MACH_TYPE_SMDKV210

machine_is_xxx     CONFIG_xxxx     MACH_TYPE_xxx               number

static const structmachine_desc __mach_desc_SMDKV210 \

 __used  __attribute__ ((__section__(".arch.info.init")))={ \  /*快速访问*/

  .nr  = MACH_TYPE_SMDKV210,   

  .name  = "SMDKV210",

  /*Maintainer: Kukjin Kim<kgene.kim@samsung.com> */

  .phys_io = S3C_PA_UART& 0xfff00000,

  .io_pg_offst = (((u32)S3C_VA_UART)>> 18) &0xfffc,

  .boot_params = S5P_PA_SDRAM +0x100,

  .init_irq  = s5pv210_init_irq,

  .map_io    = smdkv210_map_io,

  .init_machine =smdkv210_machine_init,

  .timer   = &s3c24xx_timer,

};