现在的位置: 首页 > 综合 > 正文

内核gzip压缩与解压缩介绍

2013年09月30日 ⁄ 综合 ⁄ 共 20409字 ⁄ 字号 评论关闭

通常, arch/$(ARCH)/boot/compressed目录下的文件负责生成linux的自解压内核映象, 生成的自解压内核映象通常名为zImage或bzImage. 在大多数体系结构中这二者是相同的, 但是i386体系结构下有所例外 (关于i386体系结构下, 这两者的不同请参考<<i386 Boot Code Howto>>).

1. 压缩ELF32格式的内核映象linux/vmlinux
-------------------------------------

在生成自解压映象zImage或bzImage之前, 必须对ELF32格式的vmlinux内核映象进行gzip压缩. 其大致的过程如下:

- 用objcopy把ELF32格式的内核映象linux/vmlinux转换成raw binary格式的linux/arch/$(ARCH)/boot/compressed/vmlinux.bin映象.

注: 这个在compressed目录下生成的vmlinux.bin映象是一个可执行的内核映象. 最终执行的就是它. 它与通过"make image"命令在
arch/$(ARCH)/boot/目录下生成的vmlinux.bin映象(也可能叫Image)是完全相同的.

- 用gzip压缩binary格式的linux/arch/$(ARCH)/boot/compressed/vmlinux.bin映象, 从而得到一个压缩过的
linux/$(ARCH)/boot/compressed/vmlinux.bin.gz

NOTE: 用gzip命令进行压缩时, 要指定选项"-9", 也即采用最大的压缩比.

RFC1952文档定义gzip文件的文件格式 :

Component Byte Comment
ID1 1 31 (0x1f, 37)
ID2 1 139 (0x8b, 213)
CM 1 8 - denotes the "deflate" compression method
FLG 1 0 for most cases
MTIME 4 modification time of the original file
XFL 1 2 - compressor used maximum compression, slowest algorithm
OS 1 3 - Unix
extra fields - variable length, field indicated by FLG
compressed blocks - variable length
CRC32 4 CRC value of the uncompressed data
ISIZE 4 the size of the uncompressed input data modulo 2^32

我们可以用hexdump命令"hexdump -x vmlinux.bin.gz -n 10"来看一下vmlinux.bin.gz文件的文件头:

0000000 8b1f 0008 3c52 411b 0302

再用hexdump命令"hexdump -x vmlinux | tail -n 2"来看一下校验和与输入文件的大小:

0072bb0 0000 0000 fb80 9706 fb1e 34d7 5a28 0000
0072bbf

- 接下来, 用链接器ld将压缩映象compressed/vmlinux.bin.gz转换为"compressed/piggy.o" :

ld -m elf_xxx -r -o piggy.o -b binary vmlinux.bin.gz

"-b binary"选项让链接器ld把vmlinux.bin.gz文件中的数据都放入输出文件piggy.o的.data节中. 因此piggy.o实际上是一个伪目标文件,
它里面只有一个数据段 -- ".data"节.

可以用反汇编命令objdump来看一下piggy.o中的.data节的内容:

0: 1f 8b 08 00
4: 52 3c 1b 41
8: 02 03 ec bd
...
...
72bb0: 00 00 00 00
72bb4: 80 fb 06 97
72bb8: 1e fb d7 34
72bbc: 28 5a 00 00

显然, 我们可以看出这个.data节的内容就是vmlinux.bin.gz中的文件数据.

2. 在piggy.o上wrap一个解压缩程序
------------------------------

得到piggy.o后, 我们就要创建一个可以自解压的执行程序, 来将piggy.o中的内核映象解开到相应内核入口地址. 解压过程中,
由于缓冲的原因, 可能会先解到别的内存地址, 如果这样的话, 那么解压缩完成后, 通常还会用一段搬运代码将解开的内核
映象搬运到相应的内核入口地址. 这种情况的一个典型例子就是x86-linux和arm linux.

但是个人认为, 在嵌入式系统中, 这个搬运过程, 会显著地延长OS的启动时间. 因此在我们的设计中, 解压缩程序直接将piggy.o
中的数据解压到相应的内核入口地址. 为了实现这一点, 我们在arch/frvnommu/Makefile中定义了两个变量ZTEXTADDR和TEXTADDR,
分别表示: 1)压缩内核映象zImage的执行入口点地址, 2)未压缩的内核映象vmlinux.bin的执行入口点地址. 而且我们保证:

TEXTADDR - ZTEXTADDR = 0x200000 = 2MB

显然, 这个2MB的空间是就是压缩内核映象zImage的运行地址空间(包括zImage本身的大小).

linux内核的zImage映象通常由compressed目录下的三个程序组成:

- head.S : 负责"清bss段", "设置stack", "调用decompress_kernel()函数", 以及跳转到vmlinux.bin的入口地址, 等等.

- misc.c : 负责实现具体的解压过程. 其唯一的可调用入口就是: decompress_kernel()函数.

- piggy.o : 包含待解压的数据.

一个典型的decompress_kernel()函数实现如下:

void decompress_kernel(void)
{
output_data = (uch *)TEXTADDR;
free_mem_ptr = (long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;

makecrc();
puts("Uncompressing Linux...");
gunzip();
puts(" done, booting the kernel. ");
}

具体的解压缩过程实际上是由gunzip()函数来完成的. 它实现在linux/lib/inflate.c文件中. misc.c文件已经将这个文件包含进来了.

关于misc.c的实现, 最重要的是要设置好输入数据源的位置和输出数据缓冲区的位置. 也即, 要解压什么地方的数据, 解开后的数据放到
哪里去.

gunzip()函数总是用指针inbuf来表示输入数据源, 用变量insize表示输入数据源的大小(字节数), 用inptr来表示下一个待处理的字节.
此外, 它也总是使用get_byte()宏来从输入数据源获取数据. get_byte()宏的定义如下:

#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())

函数fill_inbuf()用来在一开始的时候, 设置输入数据源的位置.

int fill_inbuf(void)
{
if (insize != 0)
error("ran out of input data");

inbuf = input_data;
insize = input_len;
inptr = 1;
return inbuf[0];
}

变量input_data, input_data_end表示输入数据源的起始地址和结束地址, input_len表示输入数据原的大小(字节数). input_len的值
应该等于(input_data_end - input_data), 它们一般定义在链接器脚本文件中. 一个典型的compressed/vmlinux.lds.in模板如下:

#include <linux/config.h>

#ifdef CONFIG_ARCH_LITTLE_ENDIAN
OUTPUT_FORMAT("elf32-little", "elf32-little", "elf32-little")
#else
OUTPUT_FORMAT("elf32-frv", "elf32-frv", "elf32-frv")
#endif

OUTPUT_ARCH(frv)
ENTRY(__startup)

SECTIONS
{
. = ZTEXTADDR;

.text : {
_stext = .;
*(.text)
*(.fixup)
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
. = ALIGN(8);
input_len = .;
LONG(input_data_end - input_data)
input_data = .;
arch/frvnommu/boot/compressed/piggy.o(.data)
input_data_end = .;
. = ALIGN(4);
}
_etext = .;

.data : { *(.data) }
.got : { *(.got) *(.got.plt) }

_edata = .;

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

.stack : {
__stack_start = .;
*(.stack)
__stack_end = .;
}
}

输出数据缓冲区的起始地址是由指针output_data来表示的, 变量output_ptr是输出缓冲区的索引. 变量bytes_out表示到目前为止已经解开了
多少字节. 函数flush_window()被gunzip用来将其临时输出窗口中的数据清洗到输出缓冲区中.

 

 

 

                        
                   

                  Linux-Android启动之zImage生成过程详解
                  可以看到,在顶层makefile的第278行,包含了scripts/Kbuild.include文件,在这里定义了大量的函数和变量,供顶层

makefile和其他makefile文件使用。

                   
                  在顶层makefile文件的第412行,包含了arch/arm
                  /Makefile。这个是体系结构相关makefile文件。它定义了体系结构相关的一些变量及规则。
                   
                  当执行”make” 时,arch/arm/Makefile中的185行的规则将是make遇到的第一个规则:
                   
                  all:   $(KBUILD_IMAGE)
                   
                  KBUILD_IMAGE这个变量是arch/arm/Makefile的第182行定义。
                   
                  KBUILD_IMAGE := zImage
                   
                  然后看zImage的构建规则,在arch/arm/Makefile的第212行开始定义
                   
                  zImage Image xipImage bootpImage uImage: vmlinux
                         $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE)
                  $(boot)/$@
                   
                  build 变量在scripts/Kbuild.include文件中第114行定义:
                   
                  build := -f $(if
                  $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
                   
                  boot变量在 arch/arm/Makefile的187行定义:
                   
                  boot := arch/arm/boot
                   
                  MACHINE 变量的值在arch/arm/Makefile的147行开始定义
                   
                  ifneq ($(machine-y),)
                  MACHINE  := arch/arm/mach-$(machine-y)/
                  else
                  MACHINE  :=
                  endif
                   
                  这里machine-y := s3c2410,所以变量MACHINE的值为
                   
                  MACHINE  := arch/arm/mach-s3c2410
                   
                  所以上面的规则可写为如下形势
                   
                   
                  zImage: vmlinux
                         $(Q)$(MAKE) -f $(if
                  $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj= \
                         arch/arm/boot MACHINE= arch/arm/mach-s3c2410
                  arch/arm/boot/ zImage
                   
                  这个规则的依赖是vmlinux,下面先看看这个依赖目标的创建规则。
                   
                  vmlinux目标的规则在顶层Makefile 的第738行定义。
                   
                  vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main)
                  $(kallsyms.o) FORCE
                  ifdef CONFIG_HEADERS_CHECK
                         $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
                  endif
                         $(call if_changed_rule,vmlinux__)
                         $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
                         $(Q)rm -f .old_version
                   
                  这里涉及到几个变量,先看看这几个变量的定义,前三个变量分别在605、602、603行定义。
                   
                  vmlinux-init := $(head-y) $(init-y)
                  vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
                  vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
                   
                  其中head-y在arch/arm/Makefile中第89 行定义,
                   
                  head-y            := arch/arm/kernel/head$(MMUEXT).o
                  arch/arm/kernel/init_task.o
                   
                  init-y在顶层makefile的433行定义
                   
                  init-y              := init/
                   
                  后又在第567行进行处理
                   
                  init-y              := $(patsubst %/, %/built-in.o, $(init-y))

                   
                  所以变量init-y应为
                   
                  init-y              := init/built-in.o
                   
                  因此
                   
                  vmlinux-init := arch/arm/kernel/head$(MMUEXT).o
                  arch/arm/kernel/init_task.o init/built-in.o
                   
                  同理,其他几个变量也可通过类似方法进行分析,这里不一一分析了。vmlinux-init这个变量的构建规则在748行定义:
                   
                  $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds):
                  $(vmlinux-dirs) ;
                   
                  这里是一个空命令的规则。空命令行可以防止make在执行时试图为重建这个目标去查找隐含命令。其依赖为vmlinux-dirs

,这个变量在顶层Makefile第558行定义:

                   
                  vmlinux-dirs   := $(patsubst %/,%,$(filter %/, $(init-y)
                  $(init-m) \
                                     $(core-y) $(core-m) $(drivers-y)
                  $(drivers-m) \
                                     $(net-y) $(net-m) $(libs-y) $(libs-m)))
                   
                  这个变量指定了一系列要进入的下层目录。他的规则在顶层Makefile第757行定义
                   
                  $(vmlinux-dirs): prepare scripts
                         $(Q)$(MAKE) $(build)=$@
                   
                  这里的两个依赖就不分析了,主要看一下这个规则的命令,build和$@变量展开后如下
                   
                         $(Q)$(MAKE) -f $(if
                  $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build  \
                          obj =$(vmlinux-dirs)
                   
                  这里会再一次进入scripts/Makefile.build执行83行规则
                   
                  __build: $(if $(KBUILD_BUILTIN),$(builtin-target)
                  $(lib-target) $(extra-y)) \
                          $(if $(KBUILD_MODULES),$(obj-m)) \
                          $(subdir-ym) $(always)
                         @:
                   
                  因为KBUILD_BUILTIN在顶层Makefile中被初始化为1,所以这个规则的依赖有一个builtin-
                  target变量。这个变量在scripts/Makefile.build的78行定义
                   
                  ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-)
                  $(lib-target)),)
                  builtin-target := $(obj)/built-in.o
                  endif
                   
                  变量obj就是vmlinux-dirs变量指定的目录。所以这里会构建$(vmlinux-dirs)/built-in.o目标,在

scripts/Makefile.build文件的261行开始,有这个目标的规则及命令的定义

                   
                  ifdef builtin-target
                  quiet_cmd_link_o_target = LD      $@
                  # If the list of objects to link is empty, just create an
                  empty built-in.o
                  cmd_link_o_target = $(if $(strip $(obj-y)),\
                                      $(LD) $(ld_flags) -r -o $@ $(filter
                  $(obj-y), $^),\
                                      rm -f $@; $(AR) rcs $@)
                   
                  $(builtin-target): $(obj-y) FORCE
                         $(call if_changed,link_o_target),
                   
                  scripts/Makefile.build
                  在第16行开始包含了vmlinux-dirs变量指定目录中的Makefile文件,在这些makefile文件中会指定obj-y变量,它指定的都

是一些*.o目标文件,

                   
                  kbuild-dir := $(if $(filter
                  /%,$(src)),$(src),$(srctree)/$(src))
                  include $(if $(wildcard $(kbuild-dir)/Kbuild),
                  $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
                   
                  这些*.o文件的生成方法由scripts/Makefile.build文件202行的模式规则指定
                   
                  %.o: %.c FORCE
                         $(call cmd,force_checksrc)
                         $(call if_changed_rule,cc_o_c)
                   
                  通过上面这一系列的步骤,就编译链接出由变量vmlinux-init指定的目标,vmlinux-main变量指定的目标的构建与此类似

。再看看vmlinux的构建规则

                   
                  vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main)
                  $(kallsyms.o) FORCE
                  ifdef CONFIG_HEADERS_CHECK
                         $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
                  endif
                         $(call if_changed_rule,vmlinux__)
                         $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
                         $(Q)rm -f .old_version
                   
                  现在vmlinux的依赖都处理好了,开始执行这个规则的命令,命令
                   
                  $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
                   
                  是进行头文件的相关检测,这里不作详细分析。看第二条命令
                   
                         $(call if_changed_rule,vmlinux__)
                   
                  这里通过函数调用,执行rule_vmlinux__,在顶层Makefile第636行开始定义
                   
                  define rule_vmlinux__
                         :
                         $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
                   
                         $(call cmd,vmlinux__)
                         $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' >
                  $(@D)/.$(@F).cmd
                   
                         $(Q)$(if $($(quiet)cmd_sysmap),                        
                               \
                           echo '  $($(quiet)cmd_sysmap)  System.map' &&)       
                               \
                         $(cmd_sysmap) $@ System.map;                           
                               \
                         if [ $$? -ne 0 ]; then                                 
                               \
                                rm -f $@;                                       
                              \
                                /bin/false;                                     
                              \
                         fi;
                         $(verify_kallsyms)
                  endef
                   
                  这里主要还是调用 cmd_vmlinux__,定义在顶层Makefile的610行
                   
                        cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o
                  $@ \
                        -T $(vmlinux-lds) $(vmlinux-init)                       
                    \
                        --start-group $(vmlinux-main) --end-group               
                    \
                        $(filter-out $(vmlinux-lds) $(vmlinux-init)
                  $(vmlinux-main) FORCE ,$^)
                   
                  通过这个命令将变量vmlinux-init和vmlinux-main指定的目标链接成vmlinux文件。链接脚本由vmlinux-lds指定。在顶层
                  Makefile 605行定义:
                   
                  vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
                   
                  现在再看一下zImage的构建规则
                   
                  zImage: vmlinux
                         $(Q)$(MAKE) -f $(if
                  $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj= \
                         arch/arm/boot MACHINE= arch/arm/mach-s3c2410
                  arch/arm/boot/ zImage
                   
                  其依赖vmlinux已经构建完成,它的命令同样是执行scripts/Makefile.build文件,它的开头包含了arch/arm
                  /boot/Makefile文件,在这个文件的第56行开始就是arch/arm/boot/zImage的构建规则:
                   
                  $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
                         $(call if_changed,objcopy)
                         @echo '  Kernel: $@ is ready'
                   
                  变量obj的值就是arch/arm/boot,前面已经分析过。其依赖 
                  $(obj)/compressed/vmlinux的构建规则在arch/arm/boot/Makefile的53行开始定义的

                   
                  $(obj)/compressed/vmlinux: $(obj)/Image FORCE
                         $(Q)$(MAKE) $(build)=$(obj)/compressed $@
                   
                  这个规则的依赖$(obj)/Image的构建规则在arch/arm/boot/Makefile的49行开始定义:
                   
                  $(obj)/Image: vmlinux FORCE
                         $(call if_changed, objcopy)
                         @echo '  Kernel: $@ is ready'
                   
                  在这个规则中,将前面创建的vmlinux文件通过二进制工具objcopy进行处理,在
                  scripts/Makefile.build的第19行包含了scripts/Makefile.lib
                   
                  include scripts/Makefile.lib
                   
                  在这个makefile文件中,有cmd_objcopy的定义,在156行开始定义
                   
                  quiet_cmd_objcopy = OBJCOPY $@
                  cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F))
                  $< $@
                   
                  变量OBJCOPY在顶层 Makefile中289行定义:
                   
                  OBJCOPY             = $(CROSS_COMPILE)objcopy
                   
                  OBJCOPYFLAGS变量在arch/arm/Makefile中第15行定义
                   
                  OBJCOPYFLAGS  :=-O binary -R .note -R .comment –S
                   
                  所以命令cmd_objcopy可扩展为
                   
                  cmd_objcopy = $(CROSS_COMPILE)objcopy -O binary -R .note -R
                  .comment –S $< $@
                   
                  这就是处理vmlinux的命令。然后看看规则
                   
                  $(obj)/compressed/vmlinux: $(obj)/Image FORCE
                         $(Q)$(MAKE) $(build)=$(obj)/compressed $@
                   
                  的命令行,变量扩展后为:
                   
                  $(Q)$(MAKE) -f $(if
                  $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj= \
                               $(obj)/compressed $(obj)/compressed/vmlinux
                   
                  于是在
                  scripts/Makefile的开头会包含arch/arm/boot/compressed/Makefile文件,并执行其中的$(obj)
                  /vmlinux目标所在的规则,在这个Makefile文件的第98行开始定义:
                   
                  $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD)
                  $(obj)/piggy.o \
                               $(addprefix $(obj)/, $(OBJS)) FORCE
                         $(call if_changed,ld)
                         @:
                   
                  这里先看$(obj)/piggy.o,在arch/arm/boot/compreseed/Makefile的103行开始
                   
                  $(obj)/piggy.gz: $(obj)/../Image FORCE
                         $(call if_changed,gzip)
                   
                  $(obj)/piggy.o:  $(obj)/piggy.gz FORCE
                   
                  这两个规则的第一个就是把由vmlinux生成的Image进行压缩生成piggy.gz,然后生成piggy.o
                   
                  cmd_ld命令在scripts/Makefile.lib文件149行定义:
                   
                  quiet_cmd_ld = LD      $@
                  cmd_ld = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) \
                                $(filter-out FORCE,$^) -o $@
                   
                  这里根据链接脚本arch/arm/boot
                  /compressed/vmlinux.lds链接生成了arch/arm/boot/compressed/vmlinux文件。然后在arch
                  /arm/boot/Makefile的第56行的规则中
                   
                  $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
                         $(call if_changed,objcopy)
                         @echo '  Kernel: $@ is ready'
                   
                  经过objcopy处理后便生成的最终的zImage 。
                   
                   
                   
                  下面看一下顶层Makefile生成的vmlinux以及arch/arm/boot/compressed
                  /makefile生成的vmlinux的起始地址。
                   
                  通过顶层Makefile中的规则生成vmlinux是根据arch/arm
                  /kernel/vmlinux.lds这个脚本链接生成的。arch/arm/kernel/vmlinux.lds是由arch/arm
                  /kernel/vmlinux.lds.S生成的,其生成规则在scripts/Makefile.build的第246行开始定义

                   
                  quiet_cmd_cpp_lds_S = LDS     $@
                        cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@
                  $<
                   
                  %.lds: %.lds.S FORCE
                         $(call if_changed_dep,cpp_lds_S)
                   
                  在arch/arm/kernel /vmlinux.lds.S的开始处有
                   
                  #ifdef CONFIG_XIP_KERNEL
                         . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
                  #else
                         . = PAGE_OFFSET + TEXT_OFFSET;
                  #endif
                   
                  我们这里的起始地址就是PAGE_OFFSET + TEXT_OFFSET。
                   
                  在include/asm-arm/memory.h的49行开始有
                   
                  #ifndef PAGE_OFFSET
                  #define PAGE_OFFSET        UL(0xc0000000)
                  #endif
                   
                  而arch/arm/kernel/vmlinux.lds.S的开头有
                   
                  #include <asm/memory.h>
                   
                  asm是一个符号,链接到asm-arm上的
                   
                  在arch/arm /Makefile第140行,有
                   
                  TEXT_OFFSET := $(textofs-y)
                   
                  第90行有
                   
                  textofs-y := 0x00008000
                   
                  所以TEXT_OFFSET := 0x00008000
                   
                  在153行有export
                  TEXT_OFFSET将此变量输出。这样arch/arm/kernel/vmlinux.lds.S也就获得了PAGE_OFFSET
                  + TEXT_OFFSET的值。
                   
                   
                  现在看看arch/arm/boot/compressed/makeflie生成的
                  vmlinux。它是根据arch/arm/boot/compressed/vmlinux.lds链接脚本生成的。这个脚本由arch/arm
                  /boot/compressed/vmlinux.lds.in生成,在这个文件的开始处有
                   
                    . = TEXT_START;
                   
                  现在看arch/arm/boot/compressed/Makefile,在110行有
                   
                  $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in
                  arch/arm/boot/Makefile .config
                         @sed "$(SEDFLAGS)" < $ $@
                   
                  这就是由vmlinux.lds.in生成vmlinux.lds的规则,在它的命令中有个变量SEDFLAGS,在74行定义
                   
                  SEDFLAGS    =
                  s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
                   
                  这里就把 TEXT_START换成了ZTEXTADDR。再往上看从66行起
                   
                  ifeq ($(CONFIG_ZBOOT_ROM),y)
                  ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT)
                  ZBSSADDR    := $(CONFIG_ZBOOT_ROM_BSS)
                  else
                  ZTEXTADDR := 0
                  ZBSSADDR    := ALIGN(4)
                  endif
                   
                  如果 zImage是从ram中启动ZTEXTADDR      := 0,否则从rom或flash启动时ZTEXTADDR
                  := $(CONFIG_ZBOOT_ROM_TEXT),这里要在配置时设定CONFIG_ZBOOT_ROM_TEXT的值。
                   
                  到这里,关于zImage的生成过程算是可以结束了。

 

 

抱歉!评论已关闭.