uBoot和Linuxcentos7升级内核到4.4中涉及到的几个地址

没有更多推荐了,
不良信息举报
举报内容:
关于UBOOT,LINUX内核编译,根文件系统的15个弱智问题(转)
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!uboot 与系统内核中 MTD分区的关系:
分区只是内核的概念,就是说A~B地址放内核,C~D地址放文件系统,等等。
1:在内核MTD中可以定义分区A~B,C~D。。。。。。并与以绝对的地址赋上值。
bootloader中只要能将内核下载到A~B区的A地址开始处就可以,C~D区的C起始地址下载文件系统。。。这些起始地址在MTD的分区信息中能找到。bootloader对分区的概念不重要,只要它能把内核烧到A位置,把文件系统烧到C位置。所以,在bootloader对Flash进行操作时,哪块区域放什么是以内核为主。而为了方便操作,bootloader类似也引入分区的概念,如,可以使用&nand write 3000000 kernel&命令将uImage烧到kernel分区,而不必写那么长:nand write 3000000 A &&这要对bootloader对内核重新分区:这需要重新设置一下bootloader环境参数,就可以同步更新内核分区信息
setenv bootargs 'noinitrd console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2
&&&&&&&&&&&&&&&&&&&&&&&&&&&mtdparts=nand_flash:128k(u-boot)ro,64k(u-boot envs),3m(kernel),30m(root.jffs2),30m(root.yaffs)'
内核配置时选上Device Drivers& ---& Memory Technology Device (MTD) support& ---& Command line partition table parsing
在设置了mtdparts变量之后,就可以在nand read/write/erase命令中直接使用分区的名字而不必指定分区的偏移位置.而这需要内核MTD最好没有规划分区。
a&。如果你是通过uboot的内核命令行给MTD层传递MTD分区信息,这种情况下,内核读取到的分区信息始终和u-boot中的保持一致(推荐的做法)
b&。如果你是把分区信息写在内核源代码MTD里定义好的方法,那最好保证它和u-boot中的保持一致,即同步修改uboot及内核的相关部分。
内核通过bootargs找到文件系统,bootargs中的mtdblockx即代表分区,block1,2,3代表哪个分区。
事实上,bootargs中的"root=/dev/mtdblockx"只是告诉内核,root fs从第x个(x=0,1,2...)MTD分区挂载,mtdblock0对应第一个分区,mtdblock1对应第二个分区,以此类推.
3:分区方法
1) MTD层的分区
2) 通过U-boot传递给内核的命令行中的mtdparts=...
3) 其他可以让内核知道分区信息的任何办法,(内核默认的命令参数)
下面说到mtdparts,及它的用法:
要想这个参数起作用,内核中的驱动必须要支持,即内核配置时需要选上
&---& Memory Technology Device (MTD) support&---& Command line partition table parsing
的格式如下:
:= &mtd-id&:&partdef&[,&partdef&]
&partdef& := &size&[@offset][&name&][ro]
&mtd-id&& := unique id used in mapping driver/device
:= standard linux memsize OR "-" to denote all remaining space
&:= (NAME)
因此你在使用的时候需要按照下面的格式来设置:
这里面有几个必须要注意的:
mtd-id必须要跟你当前平台的的一致,不然整个会失效
size在设置的时候可以为实际的,也可以为这表示剩余的所有空间。
相关信息可以查看中的注释找到相关描述。
的环境变量值得注意的有两个:和。
前面有说过是自动启动时默认执行的一些命令,因此你可以在当前环境中定义各种不同配置,不同环境的参数设置,然后设置为你经常使用的那种参数。
bootargs是环境变量中的重中之重,甚至可以说整个环境变量都是围绕着来设置的。的种类非常非常的多,我们平常只是使用了几种而已,感兴趣的可以看看这篇文章说的很全:。非常的灵活,内核和文件系统的不同搭配就会有不同的设置方法,甚至你也可以不设置而直接将其写到内核中去(在配置内核的选项中可以进行这样的设置),正是这些原因导致了使用上的困难。
下面介绍一下常用参数,的种类非常的多,而且随着的发展会出现一些新的参数,使得设置会更加灵活多样。
用来指定的位置,常见的情况有
root=/dev/ram rw&&
root=/dev/ram0 rw
请注意上面的这两种设置情况是通用的,我做过测试甚至和也是可以的,网上有人说在某些情况下是不通用的,即必须设置成或者,但是目前还没有遇到,还需要进一步确认,遇到不行的时候可以逐一尝试。
root=/dev/mtdx rw
root=/dev/mtdblockx rw
root=/dev/mtdblock/x rw
root=31:0x
上面的这几个在一定情况下是通用的,当然这要看你当前的系统是否支持,不过是字符设备,而是块设备,有时候你的挨个的试到底当前的系统支持上面那种情况下,不过比较通用。此外,如果直接指定设备名可以的话,那么使用此设备的设备号也是可以的。
root=/dev/nfs
在文件系统为基于的文件系统的时候使用。当然指定之后,还需要指定,即指明文件系统存在那个主机的那个目录下面。
这个选项需要跟一起配合使用,一般如果根文件系统是的话,有没有这个选项是无所谓的,但是如果是等文件系统的话,就需要指明文件系统的类型,不然会无法挂载根分区
console=tty&n&& 使用虚拟串口终端设备 &n&.
console=ttyS&n&[,options]使用特定的串口&n&,options可以是这样的形式bbbbpnx,这里bbbb是指串口的波特率,p是奇偶校验位,n是指的bits。
console=ttySAC&n&[,options]同上面。
看你当前的环境,有时用,有时用,网上有人说,这是跟内核的版本有关,2.4用,2.6用,但实际情况是官方文档中也是使用,所以应该是跟内核版本没有关联的。可以查看找到相关描述。
指定内存的大小,不是必须的
上面这两个都可以告诉驱动,创建的的,默认情况下是(s390默认),你可以查看找到相关的描述,不过在新版的内核都已经没有提了,不推荐使用。
当你没有使用启动系统的时候,你需要使用这个参数,但是如果使用了的话,就需要指定表示在内存中的位置,表示的大小。
指定的是内核启起来后,进入系统中运行的第一个脚本,一般或者,的内容一般是创建设备节点,运行程序,挂载一些文件系统等等操作。请注意,很多初学者以为是固定写法,其实不然,指的是目录下面的脚本,一般是一个连接罢了。
指定系统启动之后网卡的地址,如果你使用基于的文件系统,那么必须要有这个参数,其他的情况下就看你自己的喜好了。设置有两种方法:
ip = ip addr
ip=ip addr:server ip addr:gateway:netmask::which netcard:off
这两种方法可以用,不过很明显第二种要详细很多,请注意第二种中是指开发板上的网卡,而不是主机上的网卡。
说完常见的几种,那么我们来讨论平常我经常使用的几种组合:
假设文件系统是,且直接就在内存中,的设置应该如下:
init=/linuxrc&
假设文件系统是,且在中,的设置应该如下:
mem=32M console=ttyS0,115200 root=/dev/ram rw init=/linuxrc&
注意这种情况下你应该要在命令中指定在中的地址,如
假设文件系统是类型的,且在中,的设置应该如下
mem=32M console=ttyS0,115200noinitrd root=/dev/mtdblock2 rwrootfstype=jffs2init=/linuxrc&
假设文件系统是基于的,的设置应该如下
&noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5:192.168.0.3:192.168.0.3:255.255.255.0::eth0:off&
&noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5&
&--------------------------------------------------------------------------------------------------------------------------------------------
1. Uboot没有对Nandflash进行分区,通过bootargs参数将file system信息传递给kernel2. 在kernel中对Nandflash分区信息:arch/arm/mach-s3c6410/mach-smdk6410.c中struct mtd_partition s3c_partition_info[] = {&&&&&&& {&&&&&&&&&&&&&&& .name&&&&&&&&&& = "Bootloader",&&&&&&&&&&&&&&& .offset&&&&&&&& = 0,&&&&&&&&&&&&&&& .size&&&&&&&&&& = (512*SZ_1K),&&&&&&&&&&&&&&& /* .mask_flags& = MTD_CAP_NANDFLASH, */&&&&&&& },&&&&&&& {&&&&&&&&&&&&&&& .name&&&&&&&&&& = "Kernel",&&&&&&&&&&&&&&& .offset&&&&&&&& = (512*SZ_1K),&&&&&&&&&&&&&&& .size&&&&&&&&&& = (8*SZ_1M),&&&&&&&&&&&&&&& /* .mask_flags& = MTD_CAP_NANDFLASH, */&&&&&&& },&&&&&&& {&&&&&&&&&&&&&&& .name&&&&&&&&&& = "File System",&&&&&&&&&&&&&&& .offset&&&&&&&& = (8*SZ_1M + 512*SZ_1K),&&&&&&&&&&&&&&& .size&&&&&&&&&& = (128*SZ_1M),&&&&&&& },&&&&&&& {&&&&&&&&&&&&&&& .name&&&&&&&&&& = "User",&&&&&&&&&&&&&&& .offset&&&&&&&& = MTDPART_OFS_APPEND,&&&&&&&&&&&&&&& .size&&&&&&&&&& = MTDPART_SIZ_FULL,&&&&&&& }};struct s3c_nand_mtd_info s3c_nand_mtd_part_info = {&&&&&&& .chip_nr = 1,&&&&&&& .mtd_part_nr = ARRAY_SIZE(s3c_partition_info),&&&&&&& .partition = s3c_partition_info,};3. 分区信息存放在Nandflash的最后一块
阅读(...) 评论()ARM linux内核启动时几个关键地址 - arm-linux - 博客园
1.&&&&&& 内核启动地址
1.1.&& 名词解释
解压代码运行的开始地址。没有物理地址和虚拟地址之分,因为此时MMU处于关闭状态。这个地址不一定时RAM的地址,可以是支持读写寻址的flash等存储中介。
Start address of decompressor. here's no point in talking about virtual or physical addresses here, since the MMU will be off at the time when you call the decompressor code. You normally call&& the kernel at this address to
start it booting. This doesn't have to be located in RAM, it can be in flash or other read-only or&&&&& read-write addressable medium.
&&&&&& 内核启动在RAM中的地址。压缩的内核映像被解压到这个地址,然后执行。
This is the address where the decompressed kernel will be written, and eventually executed. The following constraint must be valid:
&&&&&&&&&&&&& __virt_to_phys(TEXTADDR) == ZRELADDR
&&&&&& The initial part of the kernel is carefully coded to be position independent.
&&&&&& 内核启动的虚拟地址,与ZRELADDR相对应。一般内核启动的虚拟地址为RAM的第一个bank地址加上0x8000。
&&&&&& TEXTADDR = PAGE_OFFSET + TEXTOFFST
&&&&&& Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.This is where the kernel image ends up. With the latest kernels, it must be located at 32768 bytes into a 128MB region. Previous kernels placed a restriction
of 256MB here.
TEXTOFFSET
&&&&&& 内核偏移地址。在arch/arm/makefile中设定。
PHYS_OFFSET
&&&&&& RAM第一个bank的物理起始地址。
Physical start address of the first bank of RAM.
PAGE_OFFSET
RAM第一个bank的虚拟起始地址。
&&&&&& Virtual start address of the first bank of RAM. During the kernel
&&&&&& boot phase, virtual address PAGE_OFFSET will be mapped to physical
&&&&&& address PHYS_OFFSET, along with any other mappings you supply.
&&&&&& This should be the same value as TASK_SIZE.
1.2.&& 内核启动地址确定
内核启动引导地址由bootp.lds决定。 Bootp.lds : arch/arm/bootp
OUTPUT_ARCH(arm)
ENTRY(_start)
&& _stext = .;
&& *(.start)
&& *(.text)
&& initrd_size = initrd_end - initrd_
&& _etext = .;
由上 .= 0可以确定解压代码运行的开始地址在0x0的位置。ZTEXTADDR的值决定了这个值得选取。
Makefile : arch/arm/boot/compressed
如果设定内核从ROM中启动的话,可以在make menuconfig 的配置界面中设置解压代码的起始地址,否则解压代码的起始地址为0x0。实际上,默认从ROM启动时,解压代码的起始地址也是0x0。
feq ($(CONFIG_ZBOOT_ROM),y)
ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT)
ZBSSADDR&&& := $(CONFIG_ZBOOT_ROM_BSS)
ZTEXTADDR :=0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ZBSSADDR := ALIGN(4)
SEDFLAGS&&& = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/mach-s3c2410/Makefile .config
&&&&&& @sed &$(SEDFLAGS)& & $& & $@
@sed &$(SEDFLAGS)& & $& & $@ 规则将TEXT_START设定为ZTEXTADDR。TEXT_START在arch/arm/boot/compressed/vmlinux.lds.in 中被用来设定解压代码的起始地址。
OUTPUT_ARCH(arm)
ENTRY(_start)
. = TEXT_START;&&
_text = .;
&&& _start = .;
&&& *(.start)
&&& *(.text)
*(.text.*)
内核的编译依靠vmlinux.lds,vmlinux.lds由vmlinux.lds.s 生成。从下面代码可以看出内核启动的虚拟地址被设置为PAGE_OFFSET + TEXT_OFFSET,而内核启动的物理地址ZRELADDR在arch/arm/boot/Makefile中设定。
OUTPUT_ARCH(arm)
ENTRY(stext)
#ifdef CONFIG_XIP_KERNEL
&&&&&& . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
&&&&&& . = PAGE_OFFSET + TEXT_OFFSET;&&&
&&&&&& .init : {&&&&&&&&&&&&&&&&& /* Init code and data&&&&&&&&&&&& */
&&&&&&&&&&&&& _stext = .;
&&&&&&&&&&&&&&&&&&&& _sinittext = .;
&&&&&&&&&&&&&&&&&&&& *(.init.text)
&&&&&&&&&&&&&&&&&&&& _einittext = .;
# arch/arm/boot/Makefile
# Note: the following conditions must always be true:
#&& ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
#&& PARAMS_PHYS must be within 4MB of ZRELADDR
#&& INITRD_PHYS must be in RAM
ZRELADDR&&& := $(zreladdr-y)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
#---& zrealaddr-y is specified with 0x in arch/arm/boot/makefile.boot
PARAMS_PHYS := $(params_phys-y)
INITRD_PHYS := $(initrd_phys-y)
export ZRELADDR INITRD_PHYS PARAMS_PHYS
通过下面的命令编译内核映像,由参数-a, -e设置其入口地址为ZRELADDR,此值在上面ZRELADDR&&& := $(zreladdr-y)指定。
quiet_cmd_uimage= UIMAGE $@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&& cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
&&&&&&&&&&&&&&&& -C none -a $(ZRELADDR) -e $(ZRELADDR) \
&&&&&&&&&&&&&&&& -n 'Linux-$(KERNELRELEASE)' -d $& $@
1.3.&& 小结
从上面分析可知道,linux内核被bootloader拷贝到RAM后,解压代码从ZTEXTADDR开始运行(这段代码是与位置无关的PIC)。内核被解压缩到ZREALADDR处,也就是内核启动的物理地址处。相应地,内核启动的虚拟地址被设定为TEXTADDR,满足如下条件:
TEXTADDR = PAGE_OFFSET + TEXT_OFFSET
内核启动的物理地址和虚拟地址满足入下条件:
ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)= virt_to_phys(TEXTADDR)
假定开发板为smdk2410,则有:
内核启动的虚拟地址
TEXTADDR&&&& = 0xC0008000
内核启动的物理地址&&
ZRELADDR&&&& = 0x
如果直接从flash中启动还需要设置ZTEXTADDR地址。
2.&&&&&& 内核启动过程分析
内核启动过程经过大体可以分为两个阶段:内核映像的自引导;linux内核子模块的初始化。
Decompress_kernel()
Call_kernel
Prepare_namespace
Do_basic_setup
Setup_arch ……
Start_kernel
_enable_mmu
Execve(“/sbin/init”))
内核启动流程图
2.1.&& 内核映像的自引导
这阶段的主要工作是实现压缩内核的解压和进入内核代码的入口。
Bootloader完成系统引导后,内核映像被调入内存指定的物理地址ZTEXTADDR。典型的内核映像由自引导程序和压缩的VMlinux组成。因此在启动内核之前需要先把内核解压缩。内核映像的入口的第一条代码就是自引导程序。它在arch/arm/boot/compressed/head.S文件中。
Head.S文件主要功能是实现压缩内核的解压和跳转到内核vmlinux内核的入口。Decompress_kernel(): arch/arm/boot/compressed/misc.c 和call_kernel这两个函数实现了上述功能。在调用decompress_kernel()解压内核之前,需要确保解压后的内核代码不会覆盖掉原来的内核映像。以及设定内核代码的入口地址ZREALADDR。
&&&&&&&&&&&&& .text
&&&&&&&&&&&&& adr&& r0, LC0
&&&&&&&&&&&&& ldmia&&&&&& r0, {r1, r2, r3, r4, r5, r6, ip, sp}
&&&&&&&&&&&&& .type&&&&&& LC0, #object
LC0:&&&&&&&&&&&&& .word&&&&& LC0&&&&&&&&&&&&&& @ r1
&&&&&&&&&&&&& .word&&&&& __bss_start&&&&&&&&&&& @ r2
&&&&&&&&&&&&& .word&&&&& _end&&&&&&&&&&&&&&&&&&&& @ r3
&&&&&&&&&&&&& .word&&&&& zreladdr&&&&&&&&& @ r4
&&&&&&&&&&&&& .word&&&&& _start&&&&&&&&&&&&&&&&&&& @ r5
&&&&&&&&&&&&& .word&&&&& _got_start&&&&&&&&&&&&& @ r6
&&&&&&&&&&&&& .word&&&&& _got_end&&&&&&& @ ip
&&&&&&&&&&&&& .word&&&&& user_stack+4096&&&&&&&&&& @ sp
上面这段代码得到内核代码的入口地址,保存在r4中。
* Check to see if we will overwrite ourselves.
*&& r4 = final kernel address
*&& r5 = start of this image
*&& r2 = end of malloc space (and therefore this image)
* We basically want:
*&& r4 &= r2 -& OK
*&& r4 + image length &= r5 -& OK
&&&&&&&&&&&&& cmp r4, r2
&&&&&&&&&&&&& bhs wont_overwrite
&&&&&&&&&&&&& add r0, r4, # @ 4MB largest kernel size
&&&&&&&&&&&&& cmp r0, r5
&&&&&&&&&&&&& bls&& wont_overwrite
&&&&&&&&&&&&& mov r5, r2&&&&&&&&&&&&&&&&&&& @ decompress after malloc space
&&&&&&&&&&&&& mov r0, r5
&&&&&&&&&&&&& mov r3, r7
&&&&&&&&&&&&& bl&&&& decompress_kernel
&&&&&&&&&&&&& b&&&& call_kernel
上面代码判断解压后的内核代码会不会覆盖原来的内核映像,然后调用内核解压缩函数decompress_kernel()。
decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
&&&&&&&&&&&&&&& int arch_id)
&&&&&& output_data&&&&&&&&&&& = (uch *)output_&&& /* 指定内核执行地址,保存在r4中*/
&&&&&& free_mem_ptr&&&&&&& = free_mem_ptr_p;
&&&&&& free_mem_ptr_end = free_mem_ptr_end_p;
&&&&&& __machine_arch_type&&& = arch_
&&&&&& arch_decomp_setup(); /*解压缩前的初始化和设置,包括串口波特率设置等*/
&&&&&& makecrc();&&&&&&&&&& /*CRC校验*/
&&&&&& putstr(&Uncompressing Linux...&);
&&&&&& gunzip();&&&&&&&&&&& /*调用解压缩函数*/
&&&&&& putstr(& done, booting the kernel.\n&);
&&&&&& return output_没有更多推荐了,
不良信息举报
举报内容:
内核运行之前的引导程序uboot ---
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!没有更多推荐了,
不良信息举报
举报内容:
uboot 引导Linux 内核步骤--经典
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 centos7升级内核到4.4 的文章

 

随机推荐