伟东山学习--1--内核makefile,启动过程.

--------------------/arch/arm/Makefile-----------------
# Convert bzImage to zImage
bzImage: zImage


zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@




------------------./Makefile------------------
# The all: target is the default when no target is given on the
# command line.
# This allow a user to issue only 'make' to build a kernel including modules
# Defaults vmlinux but it is usually overridden in the arch makefile
all: 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-init := $(head-y) $(init-y)
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o  #这里 $(MMUEXT) 是个空的
init-y := init/
init-y := $(patsubst %/, %/built-in.o, $(init-y))   #这里返回 init/build-in.o  .就是说init下所有的文件会编译成build-in.o


vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
core-y := usr/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y := $(patsubst %/, %/built-in.o, $(core-y))  
#返回usr/build-in.o   kernel/build-in.o   mm/build-in.o   fs/build-in.o   ipc/build-in.o  
# security/build-in.o   crypto/build-in.o   block/build-in.o     
libs-y := lib/
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)    #返回 lib/built-in.o lib/lib.a


drivers-y := drivers/ sound/
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) #返回 drivers/built-in.o sound/built-in.o

vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds


-------------------------------------------------------------------------------
-----------------/arch/arm/Makefil---------------------------------------
 








生成vmlinux命令查看方法:make uImage V=1: 
 链接的顺序是由.o文件在命令中出现的顺序决定.
 查看命令知道 第一个文件 是arch/arm/kernel/head.s
各个段的排放顺序是由链接脚本arch/arm/kernel/vmlinux.lds 决定.
首先放置.text.head段.然后是 .init.text段
arch/arm/kernel/vmlinux.lds 是自动生成的
 
 放置文件的顺序 放置.离LD命令越近的越放在前面.第一个文件是head.s 
 第二个文件是arch/arm/kernel/init_task.o


 
--------------------------------------
#启动过程:
1:处理 uboot传入的参数.
2:挂载根文件系统
3.....
a:判断是否是这个cpu
b:判断是否机器号是否和启动参数匹配.
c:建立页表,启动mmu,程序是连接地址是从0xc000 8000开始的.
d:__mmap_switched 函数 :复制数据段,清楚bss段,设置栈,
d:跳转到init/main.c:start_kernel函数  #内核的第一个c函数. 
-------------------------------
#head.o分析
 是怎么处理启动参数的:
{


3: .long .
.long __arch_info_begin
.long __arch_info_end




.type __lookup_machine_type, %function
__lookup_machine_type:
adr r3, 3b    #3b就是前面3那里,物理地址.. r3值,因为lds文件中定义的是虚拟地址.所以这里是虚拟地址.
ldmia r3, {r4, r5, r6}   #r4 valtual addr of '3' r5=__arch_info_begin r6=__arch_info_end
sub r3, r3, r4 @ get offset between virt&phys  r3=r3-r4
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
teq r3, r1 @ matches loader number?
beq 2f @ found
add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
cmp r5, r6
blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr


 
 __arch_info_begin是定义在lds文件中标号.是在段 *(.arch.info.init)中
 那么这个段有些什么内容呢,Arch.h (include\asm-arm\mach):
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
 __used \
 __attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,


#define MACHINE_END \
};
#Mach-smdk2440.c (arch\arm\mach-s3c2440):
static const struct machine_desc __mach_desc_S3C2440
/* Maintainer: Ben Dooks <ben@fluff.org> */
.nr = MACH_TYPE_S3C2440,
.name = "SMDK2440",
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,


.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
};
-----------------------------------
#start_kernel函数分析
#问题:printk是怎么初始化的?
#解析从uboot传递过来的启动参数.
启动参数就通过 setup_arch() setup_command_line()初始化的.
||                     ||
||                     ||
||   bootargs字符参数  ||     
|| tag:0x5441 0009     ||             
|| size : ...          ||     
                       ||
|| start:0x3000 0000   ||               
|| size:0x400 0000     ||            
|| tag:0x5441 0002     ||            
|| sieze 4             ||
                       ||
|| rootdev:0           ||
|| pagesize :0        ||
||  flag :0            ||
|| tag :0x5441 0001    ||              
|| size 5              ||
-------------------------
start_kernel()
setup_arch() #解析从uboot传递过来的启动参数.
setup_command_line() #解析从uboot传递过来的启动参数.
parase_early_param
do_early_param
从__setup_start到__setup_end 调用early函数
unknown_bootoption
obsolete_checksetup函数
从__setup_start到__setup_end 调用非early函数
reset_init()
kernel_thread() //内核线程,他会调用kernel_init函数.
kernel_init()
prepare_namespace()  
mount_root  //挂载根文件系统.
init_post()
//打开/dev/console ,
执行应用程序./sbin/init
--------------------------机器号判断过程






-------------------------------------------
内核是怎么知道在哪里挂载文件系统的?


bootargs = noinitrd root=dev/mtdblock3 init=/linuxrc console=ttySAC0
prepare_namespace()

savred_root_name[0]   //该变量在 root_dev_setup()中初始化
ROOT_DEV= Root_RAM0;
宏 __setup("root=", root_dev_setup) 会去解析命令行参数找到"root="后,
会保存后面的字符到变量savred_root_name[0]
宏__setup 位于include/linux/init.h中



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值