Linux编译后的文件是vmlinux,这是一个elf文件。一般不会直接用这个文件去启动,而是把这个文件压缩,
在前面再加上一段代码,负责代码定位,解压缩,初始化,并跳转到实际的内核代码。这段代码一般在放在
arch/xxx/boot下面。
PowerPC系统除了上述功能外,还要加入设备树的维护功能。
crt0.S
======
从zImage.lds.S可以看到,boot入口是_zImage_start。这段代码在crt0.S中。crt0.S作了以下工作:
获取当前实际运行地址
重定位boot代码
清cache,清bss段
调用platform_init
跳转到c语言的start入口
platform_init
=============
根据选择的硬件平台的不同,这个函数由不同的文件实现。一般是根据硬件的具体情况,做些初始化的工作。
platform_ops
============
这个结构包含了几个接口函数:
fixups : 特定硬件平台的参数微调。在start里面调用。这部分工作之所以不在platform_init
里面完成,是因为platform_init里面很多初始化工作还没完成,所以要分两步。
exit : 重启动函数,貌似没有被调用过。
这两个接口都需要在platform_init中填充。
malloc :
free :
realloc : 内存非配函数,在simple_alloc.c里面实现。
在platform_init里面需要调用simple_alloc_init。
image_hdr :
vmlinux_alloc : OpenFirmware特有的接口。
串口控制台
==========
控制台功能由console_ops描述。有4个接口: open write edit_cmdline close。
serial.c提供了一个通用的控制台框架。serial_console_init在运行时检查设备树中的串口设备类型,
并调用具体的硬件的串口驱动程序。serial_console_init在platform_init里面调用。
start
=====
在main.c里面实现。主要的工作:
打开串口控制台。在platform_init里面已经调用了serial_console_init,初始化了必要的硬件接口。
这里只是调用一下console_ops.open。
调用platform_ops.fixups。
调用prep_kernel解压vmlinux。
调用prep_initrd解压 initrd镜像。
调用prep_cmdline初始化cmdline。你甚至可以在启动时编辑cmdline。
一切准备好以后,就跳转到vmlinux的入口去了。
PowerPC系统的Image类型
=======================
cuImage:
向后兼容的uImage,针对不支持dtb功能的老的uboot版本。cuImage里面内置了dtb,并有一段代码处理
uboot传来的bd_info参数,将相关参数更新到dtb中。
simpleImage:
与固件无关的内嵌dtb的zImage。当从调试器加载镜像时(此时没有任何固件存在)可以选择simpleImage。
simpleImage假定系统内存初始化完毕,并且内存映射到0地址处。simpleImage不与固件做任何沟通。
dtbImage:
内嵌dtb的zImage,针对不支持dtb功能的固件系统。与simpleImage不同的是,dtbImage可以接受固件传来
的参数。
treeImage:
用于OpenBIOS固件的内嵌dtb的镜像。
uImage:
用于较新的U-Boot的镜像。它不包含任何额外的代码,只是把压缩的vmlinux放入uImage包中。uImage需要
U-Boot传入一个dtb。
zImage:
用于OpenFirmware或支持dtb的固件。
如何编译PowerPC内核
===================
PowerPC内核可以配置为支持多种不同的平台,同一个vmlinux镜像可以在不同的硬件上启动。但有些加入
了boot代码以后的镜像,只能在特定硬件平台上使用。
如果在配置时选择了硬件平台"board1"和"board2",并且选择使用zImage和dtbImage,可以在编译时用以下
命令:
make zImage.board1 dtbImage.board2
这样就会编译生成这两个平台的启动镜像。
如果选择的镜像包含有dtb,那么在arch/powerpc/boot/dts下必须有一个同名的dts文件,如board2.dts。
如果只执行"make zImage",则所有支持的硬件平台镜像都会被编译出来。