2410的linux内核启动地址30008000 由来探讨

发 布 时 间 : 2008-11-19 来 源 : 来自网络 作 者 : 匿名 浏 览 :
以下就2.4内核中的文件对此问题进行分析。

内核编译链接过程是依靠vmlinux.lds文件,以arm为例vmlinux.lds文件位于kernel/arch/arm/vmlinux.lds,

vmlinux-armv.lds的生成过程在kernel/arch/arm/Makefile中

ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
TEXTADDR = 0xC0008000
LDSCRIPT = arch/arm/vmlinux-armv.lds.in
endif

arch/arm/vmlinux.lds: $(LDSCRIPT) dummy
@sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@

查看arch/arm/vmlinux.lds 中

OUTPUT_ARCH(arm)
ENTRY(stext)
SECTIONS
{
. = 0xC0008000;
.init : { /* Init code and data */
_stext = .;
__init_begin = .;
*(.text.init)
__proc_info_begin = .;
*(.proc.info)
__proc_info_end = .;
__arch_info_begin = .;
*(.arch.info)
__arch_info_end = .;
__tagtable_begin = .;
*(.taglist)
__tagtable_end = .;
*(.data.init)
. = ALIGN(16);
__setup_start = .;
*(.setup.init)
__setup_end = .;
__initcall_start = .;
*(.initcall.init)
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
}

/DISCARD/ : { /* Exit code and data */
*(.text.exit)
*(.data.exit)
*(.exitcall.exit)
}

.text : { /* Real text segment */
_text = .; /* Text and read-only data */
*(.text)
*(.fixup)
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
*(.got) /* Global offset table */

_etext = .; /* End of text section */
}

.kstrtab : { *(.kstrtab) }

. = ALIGN(16);
__ex_table : { /* Exception table */
__start___ex_table = .;
*(__ex_table)
__stop___ex_table = .;
}

__ksymtab : { /* Kernel symbol table */
__start___ksymtab = .;
*(__ksymtab)
__stop___ksymtab = .;
}

. = ALIGN(8192);

.data : {
/*
* first, the init task union, aligned
* to an 8192 byte boundary.
*/
*(.init.task)

/*
* then the cacheline aligned data
*/
. = ALIGN(32);
*(.data.cacheline_aligned)

/*
* and the usual data section
*/
*(.data)
CONSTRUCTORS

_edata = .;
}

.bss : {
__bss_start = .; /* BSS */
*(.bss)
*(COMMON)
_end = . ;
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}

arch/arm/Makefile中:

vmlinux: arch/arm/vmlinux.lds

arch/arm/vmlinux.lds: $(LDSCRIPT) dummy
@sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@


MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot

bzImage zImage zinstall Image bootpImage install: vmlinux
@$(MAKEBOOT) $@

但在kernel/arch/arm/boot/Makefile

ifeq ($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif

zImage: $(CONFIGURE) compressed/vmlinux
$(OBJCOPY) -O binary -R .note -R .comment -S compressed/vmlinux $@

compressed/vmlinux: $(TOPDIR)/vmlinux dep
@$(MAKE) -C compressed vmlinux

在compressed目录下的Makefile中

ZLDFLAGS = -p -X -T vmlinux.lds

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

all: vmlinux

vmlinux: $(HEAD) $(OBJS) piggy.o vmlinux.lds
$(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(LIBGCC) -o vmlinux


vmlinux.lds: vmlinux.lds.in Makefile $(TOPDIR)/arch/$(ARCH)/boot/Makefile $(TOPDIR)/.config
@sed "$(SEDFLAGS)" < vmlinux.lds.in > $@


vmlinux-armv.lds.in文件的内容:

OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = LOAD_ADDR;
_load_addr = .;

. = TEXT_START;
_text = .;

.text : {
_start = .;
*(.start)
*(.text)
*(.fixup)
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
input_data = .;
piggy.o
input_data_end = .;
. = ALIGN(4);
}

_etext = .;

_got_start = .;
.got : { *(.got) }
_got_end = .;
.got.plt : { *(.got.plt) }
.data : { *(.data) }
_edata = .;

. = BSS_START;
__bss_start = .;
.bss : { *(.bss) }
_end = .;

.stack (NOLOAD) : { *(.stack) }

.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}

vmlinux.lds内容为

OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x30008000;
_load_addr = .;

. = 0;
_text = .;

.text : {
_start = .;
*(.start)
*(.text)
*(.fixup)
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
input_data = .;
piggy.o
input_data_end = .;
. = ALIGN(4);
}

_etext = .;

_got_start = .;
.got : { *(.got) }
_got_end = .;
.got.plt : { *(.got.plt) }
.data : { *(.data) }
_edata = .;

. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;

.stack (NOLOAD) : { *(.stack) }

.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}


一般情况下都在生成vmlinux后,再对内核进行压缩成为zImage,压缩的目录是kernel/arch/arm/boot。
下载到flash中的是压缩后的zImage文件,zImage是由压缩后的vmlinux和解压缩程序组成,如下图所示:
|-----------------|\ |-----------------|
| | \ | |
| | \ | decompress code |
| vmlinux | \ |-----------------| zImage
| | \| |
| | | |
| | | |
| | | |
| | /|-----------------|
| | /
| | /
| | /
|-----------------|/

zImage链接脚本也叫做vmlinux.lds,位于kernel/arch/arm/boot/compressed。
是由同一目录下的vmlinux.lds.in文件生成的

在kernel/arch/arm/boot/Makefile文件中定义了:


ifeq ($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif

ZTEXTADDR就是解压缩代码的ram偏移地址,ZRELADDR是内核ram启动的偏移地址,这里看到指定ZTEXTADDR的地址为30008000,



以上就是我对内核启动地址的分析,总结一下内核启动地址的设置:


设置kernel/arch/arm/boot/Makefile文件中的

ifeq ($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif
# We now have a PIC decompressor implementation. Decompressors running
# from RAM should not define ZTEXTADDR. Decompressors running directly
# from ROM or Flash must define ZTEXTADDR (preferably via the config)
#


查看2410的datasheet ,发现内存映射的基址是0x3000 0000 ,那么 0x30008000又是如何来的呢?


在内核文档kernel/Document/arm/Booting 文件中有:

Calling the kernel image

Existing boot loaders: MANDATORY
New boot loaders: MANDATORY

There are two options for calling the kernel zImage. If the zImage is stored in flash, and is linked correctly to be run from flash, then it is legal for the boot loader to call the zImage in flash directly.

The zImage may also be placed in system RAM (at any location) and called there. Note that the kernel uses 16K of RAM below the image to store page tables. The recommended placement is 32KiB into RAM.

看来在image下面用了32K(0x8000)的空间存放内核页表,
0x30008000就是2410的内核在RAM中的启动地址,这个地址就是这么来的。



上一篇:PPP拨号在ARM2410平台上的移植 下一篇:基于WINCE.NET4.2系统的PDA使用PPC2003软件全攻略