uboot加载linux内核加载那些内容,几个地址参数及uboot加载启动内核过程的理解

关于uBoot和Linux内核中几个地址参数及uboot加载启动内核过程的理解

uboot一般使用mkimage工具先制作一个启动映象文件来引导识别内核的,uboot源代码的tools/目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头,记录参数所指定的信息,这样uboot才能识别这个映象是针对哪个CPU体系结构的,哪个OS的,哪种类型,加载内存中的哪个位置, 入口点在内存的那个位置以及映象名是什么

vim arch/arm/Makefile

31 # defines filename extension depending memory management type.

32 ifeq ($(CONFIG_MMU),)

33 MMUEXT          := -nommu

34 endif

121 #Default value

122 head-y          := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task    .o

123 textofs-y       := 0x00008000

124 textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000

125 # We don't want the htc bootloader to corrupt kernel during resume

126 textofs-$(CONFIG_PM_H1940)      := 0x00108000

127 # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memo    ry

128 ifeq ($(CONFIG_ARCH_SA1100),y)

129 textofs-$(CONFIG_SA1111) := 0x00208000

130 endif

222 # The byte offset of the kernel image in RAM from the start of RAM.

223 TEXT_OFFSET := $(textofs-y)

241 export  TEXT_OFFSET GZFLAGS MMUEXT

./scripts/mkuboot.sh

#!/bin/bash

#

# Build U-Boot image when `mkimage' tool is available.

#

MKIMAGE=$(type -path "${CROSS_COMPILE}mkimage")

if [ -z "${MKIMAGE}" ]; then

MKIMAGE=$(type -path mkimage)

if [ -z "${MKIMAGE}" ]; then

# Doesn't exist

echo '"mkimage" command not found - U-Boot images will not be built' >&2

exit 1;

fi

fi

# Call "mkimage" to create U-Boot image

${MKIMAGE} "$@"

./arch/arm/mach-s3c2410/Makefile.boot

1 ifeq ($(CONFIG_PM_H1940),y)

2         zreladdr-y              := 0x30108000

3         params_phys-y   := 0x30100100

4 else

5         zreladdr-y              := 0x30008000

6         params_phys-y   := 0x30000100

7 endif

vim arch/arm/boot/Makefile

14 MKIMAGE         := $(srctree)/scripts/mkuboot.sh

16 ifneq ($(MACHINE),)

17 include $(srctree)/$(MACHINE)/Makefile.boot  //即arch/arm/mach-s3c2410/Makefile.boot

18 endif

20 # Note: the following conditions must always be true:

21 #   ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)

22 #   PARAMS_PHYS must be within 4MB of ZRELADDR

23 #   INITRD_PHYS must be in RAM

24 ZRELADDR    := $(zreladdr-y)  //内核加载地址ZRELADDR

25 PARAMS_PHYS := $(params_phys-y)

26 INITRD_PHYS := $(initrd_phys-y)

27

28 export ZRELADDR INITRD_PHYS PARAMS_PHYS

29

30 targets := Image zImage xipImage bootpImage uImage

62 quiet_cmd_uimage = UIMAGE  $@

63       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \

64                    -C none -a $(LOADADDR) -e $(STARTADDR) \

65                    -n 'Linux-$(KERNELRELEASE)' -d $< $@

66

67 ifeq ($(CONFIG_ZBOOT_ROM),y)

68 $(obj)/uImage: LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT)

69 else

70 $(obj)/uImage: LOADADDR=$(ZRELADDR)

71 endif

72

73 $(obj)/uImage: STARTADDR=$(LOADADDR)

cmd_uimage展开相当于:

mkimage -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -n 'Linux-3.0" -d zImage uImage

-A:CPU类型

-O:操作系统

-T:用于指定image类型,比如Kernel

-C:采用的压缩方式

-a:内核加载地址

-e:内核入口地址

-d 无头信息的image文件名

Boot options  --->

[ ] Flattened Device Tree support

(0x0) Compressed ROM boot loader base address

(0x0) Compressed ROM boot loader BSS address

430:CONFIG_ZBOOT_ROM_TEXT=0x0

431:CONFIG_ZBOOT_ROM_BSS=0x0

arch/arm/boot/compressed/Makefile

ifeq ($(CONFIG_ZBOOT_ROM),y)

ZTEXTADDR       := $(CONFIG_ZBOOT_ROM_TEXT)  //自解压程序地址ZTEXTADDR

ZBSSADDR        := $(CONFIG_ZBOOT_ROM_BSS)

else

ZTEXTADDR       := 0

ZBSSADDR        := ALIGN(8)

endif

默认值ZTEXTADDR= 0x00000000表示不使用。(只能通过uBoot的gunzip解压加载)

include/configs/st2410.h -n

127:#define     CFG_LOAD_ADDR           0x33000000      /* default load address*///uImage存放地址

uBoot的do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);

函数将检验存放到0x33000000地址处的经过mkimage格式化的uImage数据的头部

typedef struct image_header {

uint32_t    ih_magic;    /* Image Header Magic Number    */

uint32_t    ih_hcrc;    /* Image Header CRC Checksum    */

uint32_t    ih_time;    /* Image Creation Timestamp    */

uint32_t    ih_size;    /* Image Data Size        */

uint32_t    ih_load;    /* Data     Load  Address        */

uint32_t    ih_ep;        /* Entry Point Address        */

uint32_t    ih_dcrc;    /* Image Data CRC Checksum    */

uint8_t        ih_os;        /* Operating System        */

uint8_t        ih_arch;    /* CPU architecture        */

uint8_t        ih_type;    /* Image Type            */

uint8_t        ih_comp;    /* Compression Type        */

uint8_t        ih_name[IH_NMLEN];    /* Image Name        */

} image_header_t;

(ih_ep值为0x30008000,ih_load值为0x30008000)

如果头部各个域值和crc合法,那么do_bootm将调用如下gunzip解压函数对

0x33000000 +sizeof(image_header_t)地址处的压缩内核进行解压:

gunzip((void*)ntohl(hdr->ih_load),unc_len,(uchar *)data,(int*)&len);

1.hdr->ih_load   为输出数据地址0x30008000

2.unc_len        为gunzip解压输出数据上限值-8M,do_bootm函数前有定义#define CFG_BOOTM_LEN    0x800000,uint    unc_len = CFG_BOOTM_LEN;

3.data           为输入数据地址data=0x33000000 +sizeof(image_header_t);

4.Len            为输入数据长度len = ntohl(hdr->ih_size );

解压完成后将会存储解压后数据的实际大小

压缩的Linux内核文件uImage,经由gunzip解压函数后,通过

do_bootm_linux (cmdtp, flag, argc, argv,addr, len_ptr, verify);

函数向Linux内核传递内核运行所需的3个参数,在bootm执行的流程中,可以看到会调用do_bootm_linux()在执行Linux内核,内核的起始地址如下:

void (*theKernel)(int zero, int arch, uint params);

image_header_t *hdr = &header;

theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);

header是uImage的头部,通过头部,得到内核映像起始的执行地址hdr->ih_ep为0x30008000,标识为theKernel。从中也可以看到,内核接受三个参数,第一个为0,第二个为系统的ID号,第三个是传入内核的参数。

在do_bootm_linux()的最后,会跳到内核去执行:

theKernel (0, bd->bi_arch_number, bd->bi_boot_params);

这样完成了Linux系统启动所需要3个参数的传递,至此uBoot的工作已经结束,Linux将在0x30008000地址处正式运行。

阅读(4021) | 评论(0) | 转发(0) |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>