分类: LINUX
2006-03-17 19:24:40
/arch 所有硬件结构特定的kernel代码。多平台设计所用,如i386,alpha,arm(与体系结构相关的代码都存放在arch/
/drivers 内核中所有的设备驱动程序,如usb和sound;
/fs 所有的文件系统的代码,如ntfs,ext3,jffs2等;
/include 建立内核代码时所需要的大部分库文件,这个模块利用其他模块重建内核。该目录也包括了不同平台需要的库文件,如asm-arm是arm平台需要的库文件;
/init 内核的初始化代码,内核从此处开始工作;
/ipc 进程间通信代码;
/kernel 主内核代码;
/mm 所有内存管理代码;
/net 和网络相关的代码,如atm,ipv6等;
一般在每个目录下都有一个.depend文件和一个Makefile文件。这两个文件都是编译时使用的辅助文件。
1./arch
linux系统能支持如此多平台的部分原因是因为内核把sourcecode清晰地划分为与体系结构无关部分和体系结构相关部分。/arch包含与体系结构相关的代码.其中每一个目录代表一种硬件平台,such as arm,i386.对任何平台,都必须包括以下几个目录:
/boot:启动内核所使用的部分或全部平台特有代码;
/kernel:存放支持体系结构特有的(如信号处理和SMP)特征的实现;
/lib:存放告诉的体系结构特有的(如strlen和memcpy)通用的函数的实现;
/mm:存放体系结构特有的内存管理程序的实现;
/math-emu:模拟FPU的代码。对于arm处理器来说,此目录用mach-xxx代替。
So,移植工作的重点就是 /arch目录下的文件。
2./dirvers
所有的设备驱动程序。它占整个内核发行版本代码的一半以上,非常庞大。有些驱动程序是与硬件平台无关的而有些是相关的。
3./fs
所有的文件系统的代码。如ntfs,ext3,jffs2等。一般来说,文件系统也与硬件平台无关。
4./include
建立编译内核代码时所需要的大部分头文件,例如与平台无关的头文件在/include/linux下。不同的平台需要的头文件会有所不同,因此该目录和/arch一样,按平台划分了多个sub-dir,such as asm-arm.
5./init
内核的初始化代码(不是系统的引导代码),有main.c和version.c两个文件。这是研究核心如何工作的好起点。
6./ipc
进程间通信代码.
7./kernel
内核管理的核心代码。与处理器相关的代码都放在arch/*/kernel目录下。
8./lib
与平台无关的如strlen和memcpy等通用函数.
9./mm
所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于/arch/*/mm下。
10./net
和网络相关的代码,如atm,ipv6等.其每一个子目录对应网络的一个方面。
11./其他
还有两个dir.:/documentation including many docs和/scripts主要在配置内核时用到,存放了配置内核的一些脚本文件,如make menuconfig.
-----------------------------------------
二、 Linux操作系统的移植
假定内核代码存放在/usr/src/linux-
1.根目录
只需要修改Makefile文件。这里Makefile的任务是:产生vmlinux文件和产生内核模块.
它将递归进入到内核的各个子目录中,分别调用位于这些子目录中的Makefile.起到组织内核的各模块,记录各模块的相互联系和以来关系。(建议一定读懂Makefile文件。)
对最上层的Makefile的修改:
a:指定目标平台
before: ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
after: ARCH := arm
b:指定交叉编译器
before: CROSS_COMPILE =
after: CROSS_COMPILE = /opt/host/armv
//反正是指定交叉编译程序的目录.
Note that if you reset the CROSS_COMPILE,
CC = $(CROSS_COMPILE)gcc
if not reset,
CC = $(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else \
$(CONFIG_SHELL) scripts/kwhich gcc296 2>/dev/null || echo cc; fi)
另外,你可能需要设置:
----------------
TMPDIR = /dev/shm
而不需要
AWK = awk
TMPPREFIX =
-------------
在export中好象不要FINDHPATH,其他基本都加上。
-----------------
# INSTALL_PATH specifies where to place the updated kernel and system map
# images. Uncomment if you want to place them anywhere other than root.
这个应该不要。
#export INSTALL_PATH=/boot
----------------------
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots. This is not defined in the
# makefile but the arguement can be passed to make if needed.
需要加入
export INSTALL_MOD_PATH=/tmp
------------------
2.arch目录
这里存放着和体系结构相关部分的内核代码。
2.1 Makefile
手动add:
ifeq ($(CONFIG_ARCH_S
TEXTADDR = 0xC0008000
MACHINE = s
endif
TEXTADDR决定内核起始运行地址,即image.ram应下载的地址。
要点:根据自己的电路设置TEXTADDR变量。
这里我们的电路地址是0xC0008000:从地址0xC0000000开始,总共32MB的空间。
2.2 config.in
配置文件,运行make menuconfig命令时出现的菜单就是config配置的。
a.添加CONFIG_ARCH_S
if [ "$CONFIG_ARCH_S
comment 'S
dep_bool ' SMDK (MERI TECH BOARD)' CONFIG_S
dep_bool ' change AIJI' CONFIG_SMDK_AIJI
dep_tristate 'S
dep_tristate ' Support for S
fi # /* CONFIG_ARCH_S
b. other options
if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
"$CONFIG_ARCH_SHARK" = "y" -o \
"$CONFIG_ARCH_CLPS7500" = "y" -o \
"$CONFIG_ARCH_EBSA110" = "y" -o \
"$CONFIG_ARCH_CDB89712" = "y" -o \
"$CONFIG_ARCH_EDB7211" = "y" -o \
"$CONFIG_ARCH_S
"$CONFIG_ARCH_S
"$CONFIG_ARCH_SA1100" = "y" ]; then
define_bool CONFIG_ISA y
else
define_bool CONFIG_ISA n
fi
---------
类似的添加项不只一处,读者可以根据需要在需要的地方加入。
移植要点:config文件决定了menuconfig菜单的内容。把使用的平台加在需要的地方,这样在配置linux内核时就能够选择是否支持你的平台了。
3 arch/arm/boot目录
编译出来的内核是存放在这个目录中。这里将指定内核解压到目标板的地址,所以如果内核无法正常启动,很有可能是这里的地址指定错误。
3.1 Makefile
ifeq ($(CONFIG_ARCH_S
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif
------
ZRELADDR决定内核解压后数据输出的地址。
ZTEXTADDR为bootloader的压缩内核文件烧入flash的起始地址,即从哪个位置开始执行bootloader,若启动时直接运行,则将其设为0;若自带bios可以跳到想要的地址,则可改为所要的位置。
移植要点:要根据自己的电路设置ZTEXTADDR和ZRELADDR变量。
3.2 compressed/Makefile
通过这个文件将从vmlinux创建一个压缩的vmlinuz镜像。此文件中用到的SYSTEM,ZTEXTADDR,ZBSSADDR和ZRELADDR是从arch/arm/boot/Makefile获得的。
ifeq ($(CONFIG_ARCH_S
OBJS += head-s
endif
移植要点:加入head-s
3.3 arch/arm/boot/compressed/head-s
主要用来init处理器。好好研究下汇编代码//如何进行初始化需要仔细研究处理器的手册。
#include
#include
#include
.section ".start", #alloc, #execinstr
__S
@ Preserve r8/r7 i.e. kernel entry values
@ What is it?
@ Nandy
@ Data cache, Intstruction cache, MMU might be active.
@ Be sure to flush kernel binary out of the cache,
@ whatever state it is, before it is turned off.
@ This is done by fetching through currently executed
@ memory to be sure we hit the same cache
bic r2, pc, #0x
add r3, r2, #0x4000 @ r3<-r2+0x4000(16 kb is quite enough)
1: ldr r0, [r2], #32 @r0<-r2,r2<-r2+32
teq r2, r3 @compare contents of two regs
bne 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches
#if 0
@ disabling MMU and caches禁用mmu和caches
mrc p15, 0, r0, c1, c0, 0 @ read control register
bic r0, r0, #0x05 @ disable D cache and MMU
bic r0, r0, #1000 @ disable I cache
mcr p15, 0, r0, c1, c0, 0 @使前面的设置生效
#endif
/*
* Pause for a short time so that we give enough time
* for the host to start a terminal up.
*暂停一段时间,等待主机启动终端
*/
mov r0, #0x00200000
1: subs r0, r0, #1
bne 1b
-------------------
Note that:arm的D cache必须和MMU一起打开,而I cache可以单独打开。
3.4 arch/arm/def-configs目录
定义了一些平台的config文件,比如lart和assert等.把配置好的文件复制到这里就可以了。
3.5 arch/arm/kernel目录
与硬件平台相关的内核代码
a.add the support for s
no-irq-arch := $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \
$(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
$(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \
$(CONFIG_ARCH_S
$(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_PXA)
b.add other function
obj-$(CONFIG_MIZI) += event.o
obj-$(CONFIG_APM) += apm2.o
移植要点:有任何新加的功能都要告知Makefile文件。上述两条语句的目的是编译event.c和apm2.c.
在适当的地方加入如下代码,目的是关闭全部外围设备的时钟,从而保证系统正确运行.
#elif defined(CONFIG_ARCH_S
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled 查看是否运行mmu?
moveq \rx, #0x50000000 @ physical base address
movne \rx, #0xf0000000 @ virtual address
.endm
.macro senduart,rd,rx
str \rd, [\rx, #0x20] @ UTXH
.endm
.macro waituart,rd,rx
.endm
.macro busyuart,rd,rx
1001: ldr \rd, [\rx, #0x10] @ read UTRSTAT
tst \rd, #1 << 2 @ TX_EMPTY ?
beq 1001b
.endm
加入cpu的中断部分。
#elif defined(CONFIG_ARCH_S
#include
.macro disable_fiq
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #INTBASE @ virtual address of IRQ registers
ldr \irqnr, [r4, #0x8] @ read INTMSK
ldr \irqstat, [r4, #0x10] @ read INTPND
bics \irqstat, \irqstat, \irqnr
bics \irqstat, \irqstat, \irqnr
beq
mov \irqnr, #0
1001: tst \irqstat, #1
bne
add \irqnr, \irqnr, #1
mov \irqstat, \irqstat, lsr #1
cmp \irqnr, #32
bcc 1001b
1002:
.endm
.macro irq_prio_table
.endm
---
移植要点:了解cpu初始化时是如何处理中断的。寄存器在s
这个文件中有一个非常重要的函数setup_arch。这个函数用来完成和体系相关的初始化工作,比如对物理内存结构meminfo的初始化。这个结构将在后面的内存初始化中起到很重要的作用。其中,nr_banks指定了内存块的数量,bank指定了每块内存的范围。用来指定块开始及长度的PAGE_OFFSET和MEM——SIZE都在include/asm-arm/arch-s
3.6 arch/arm/mm目录
此目录下的文件是和arm平台相关的内存管理内容,只有mm-armv.c文件需要移植。
把init_maps->bufferable = 0;
改为:
init_maps->bufferable = 1;
init_maps是一个map_desc性数据结构。map_desc定义在/include/asm-arm/mach/map.h中
struct map_desc {
unsigned long virtual;
unsigned long physical;
unsigned long length;
int domain:4,
prot_read:1,
prot_write:1,
cacheable:1,
bufferable:1,
last:1;
};
3.7 arch/arm/mach-s
这里只是对处理器的基本信息提供了支持,有关开发板的外设,如usb,powermanage等都需要用户自己添加。(可参考相应开发板配套cd).
三、 编译linux内核
之前要配置内核:
make config;
make oldconfig;
make menuconfig;
make xconfig.
无论哪个命令都产生一个.config文件,并在每个.c文件中加上
查看内核的配置:
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
执行make dep
make zImage
make modules
make modules_install
安装内核需要copy 4个文件:没压缩的内核镜像zImage,压缩的内核镜像vmlinux,内核符号映射文件System.map以及配置文件.config.
zImage文件是和平台无关的,它在Makefile文件中设置。这里使用arm平台,so生成的镜像文件在/arch/arm/boot/zImage下。其他三个文件在内核代码的根目录/usr/src/linux-
对创建的内核进行backup的好处是能通过配置文件知道内核的功能。比如是否lcd的驱动,是否有bluetooth等。代码如下:
cp arch/arm/boot/zImage $(YOURBAKPATH)/image/zImage-
cp System.map $(YOURBAKPATH)/image/System.map-
cp vmlinux $(YOURBAKPATH)/image/vmlinux-
cp .config $(YOURBAKPATH)/image/