赞
踩
uboot 通过 tftp 下载 uImage 到 ddr 到 地址 A
uboot 根据 uImage 的要求 搬运 zImage 到 地址 B
zImage boot
zImage 根据 是否会覆盖Image 搬运 自身 到 地址 C
zImage 跳转到 地址C处的 zImage
zImage 解压 出 Image 到某地址 到 地址 D
Image boot
过程中涉及到 4个boot 地址(ABCD)
地址A : tftp 0x60003000 uImage; bootm 0x60003000 中的 0x60003000
地址B : ZTEXTADDR // 值于 Load Address 相同 // Entry Point 一般也和 Load Address 一致
地址C : TODO
地址D : ZRELADDR
uboot 在 加载 内核最后一步, MMU 肯定是关的 // 不太关心 uboot 过程中会不会开MMU
zImage 运行过程中 , MMU 全程关闭
Image 运行过程中 , MMU 会在 start_kernel 前 打开
开了 MMU 之后
物理地址 : 虚拟地址
ZRELADDR : TEXTADDR
Image启动的虚拟地址 TEXTADDR = 0xC0008000
Image启动的物理地址 ZRELADDR = 0x30008000
$ ls -l arch/arm/boot/Image //25.2M
-rwxrwxr-x 1 suweishuai suweishuai 26430588 May 27 21:19 arch/arm/boot/Image
$ ls -l arch/arm/boot/zImage //9.55M
-rwxrwxr-x 1 suweishuai suweishuai 10019328 May 27 21:20 arch/arm/boot/zImage
$ ls arch/arm/boot/Image -l
-rwxrwxr-x 1 suweishuai suweishuai 26430588 May 27 21:19 arch/arm/boot/Image
$ file arch/arm/boot/Image
arch/arm/boot/Image: data
地址A : 没有研究 qemu virt arm32 的 u-boot
地址B : 0x40010000 // 即 ZTEXTADDR
地址C : 0x41B3C460
地址D : 0x40208000 // 即 ZRELADDR
PHYS_OFFSET : 0x40000000
PAGE_OFFSET : 0xc0000000
TEXT_OFFSET : 0x00208000
TEXTADDR : 0xc0208000
swapper_pg_dir : 0xc0204000
ZBSSADDR := ALIGN(8)
c1b9ee68 B _end
c0208000 T _text
页表描述
arm32 两级映射,对于section 映射,只有1级别
下面所有的表项都是PGD表项(即PMD表项)
每个表项4字节,寻址1M空间
// mmu_on 4030 0000 - 4040 0000
// __turn_mmu_on - __turn_mmu_on_end : 0x40300000 - 0x40300020
0xc0205000: 0x00000000 0x00000000 0x00000000 0x40311c0e
// Image+Image前的地址页表 4000 0000 - 40b0 0000
0xc0207000: 0x40011c0e 0x40111c0e 0x40211c0e 0x40311c0e // 0x40011c0e 0x40111c0e Image前的地址
0xc0207010: 0x40411c0e 0x40511c0e 0x40611c0e 0x40711c0e
0xc0207020: 0x40811c0e 0x40911c0e 0x40a11c0e 0x40b11c0e
0xc0207030: 0x40c11c0e 0x40d11c0e 0x40e11c0e 0x40f11c0e
0xc0207040: 0x41011c0e 0x41111c0e 0x41211c0e 0x41311c0e
0xc0207050: 0x41411c0e 0x41511c0e 0x41611c0e 0x41711c0e
0xc0207060: 0x41811c0e 0x41911c0e 0x41a11c0e 0x41b11c0e
// fdt 页表 4800 0000 - 48100000
0xc0207fe0: 0x48011c0e 0x48111c0e 0x00000000 0x00000000
arm32 40000000 - 40204000是干啥的?为啥virt板要预留这么多
arm32为什么要从 40000000 创建映射, arm64 为啥不用?
arm32 只有一个pgd(里面有mmu_on,Image,dtb) , 而 arm64 为什么创建两个 pgd(分别是mmu_on,Image)
PHYS_OFFSET
Physical start address of the first bank of RAM.
RAM第一个bank的物理起始地址,即物理内存的起始地址。
ram的起始地址 : 例如 qemu virt arm 的 0x40000000
https://blog.csdn.net/u011011827/article/details/82995261 Load Address 是 zImage 的住宿地址 // 和 bootm的参数没有关系 make LOADADDR=0x60004000 uImage // 指定 LOADADDR //arch/arm/boot/Makefile // 关注 : UIMAGE_LOADADDR ifneq ($(LOADADDR),) // 可通过 make LOADADDR=0x60004000 uImage 指定 LOADADDR UIMAGE_LOADADDR=$(LOADADDR) else ifeq ($(CONFIG_ZBOOT_ROM),y) UIMAGE_LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT) else UIMAGE_LOADADDR=$(ZRELADDR) endif endif ———————————————— 版权声明:本文为CSDN博主「__pop_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u011011827/article/details/82995261
https://blog.csdn.net/u011011827/article/details/82995261
Entry Point 是 zImage 的控制地址,(从这个地址接收控制权)
// scripts/Makefile.lib // 关注 : UIMAGE_ENTRYADDR
UIMAGE_LOADADDR ?= arch_must_set_this
UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR)
...
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
-C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \
-T $(UIMAGE_TYPE) \
-a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \
-n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT)
————————————————
版权声明:本文为CSDN博主「__pop_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011011827/article/details/82995261
zImage 的代码是位置无关码,随意扔到哪里都可以
ZTEXTADDR
Start address of decompressor. There'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.
解压代码(zImage)运行的开始地址。
没有虚拟地址的概念,因为此时MMU处于关闭状态。
这个地址不一定时RAM的地址,可以是支持读写寻址的flash等存储中介。
ZBSSADDR
Start address of zero-initialised work area for the decompressor.
This must be pointing at RAM. The decompressor will zero initialise
this for you. Again, the MMU will be off.
INITRD_VIRT
Virtual address of the initial RAM disk. The following constraint
must be valid:
__virt_to_phys(INITRD_VIRT) == INITRD_PHYS
PAGE_OFFSET
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.
RAM第一个bank的虚拟起始地址,即内核虚拟地址空间的起始地址。
#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET)
TEXT_OFFSET 内核偏移地址,即内核起始位置相对于内存起始位置的偏移, 对于相对于物理内存还是相对于虚拟内存都是一样的结果。 在arch/arm/makefile中设定。 TEXT_OFFSET := $(textofs-y) 140 # Text offset. This list is sorted numerically by address in order to 141 # provide a means to avoid/resolve conflicts in multi-arch kernels. 142 # Note: the 32kB below this value is reserved for use by the kernel 143 # during boot, and this offset is critical to the functioning of 144 # kexec-tools. 145 textofs-y := 0x00008000 可取范围 0x008000 0x208000 0x408000 ...
// 目前好像没有这个宏了? TEXTADDR 内核启动的虚拟地址,与ZRELADDR相对应。一般内核启动的虚拟地址为RAM的第一个bank地址加上0x8000。 TEXTADDR = PAGE_OFFSET + TEXT_OFFSET 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. TEXTADDR 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. 相应地,内核启动的虚拟地址被设定为TEXTADDR,满足如下条件: TEXTADDR = PAGE_OFFSET + TEXT_OFFSET 内核启动的物理地址和虚拟地址满足入下条件: ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)= virt_to_phys(TEXTADDR)
swapper_pg_dir 的 值 为 "TEXTADDR - 0x4000"
boot时 用来存储 临时页表
运行时 用来存储 内核页表
/*
* swapper_pg_dir is the virtual address of the initial page table.
* We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must
* make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect
* the least significant 16 bits to be 0x8000, but we could probably
* relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000.
*/
VMALLOC_START arch/arm/include/asm/pgtable.h #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) VMALLOC_END Virtual addresses bounding the vmalloc() area. There must not be any static mappings in this area; vmalloc will overwrite them. The addresses must also be in the kernel segment (see above). Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the last virtual RAM address (found using variable high_memory). #define VMALLOC_END 0xff800000UL VMALLOC_OFFSET Offset normally incorporated into VMALLOC_START to provide a hole between virtual RAM and the vmalloc area. We do this to allow out of bounds memory accesses (eg, something writing off the end of the mapped memory map) to be caught. Normally set to 8MB. #define VMALLOC_OFFSET (8*1024*1024)
DATAADDR
// 没有这个宏
Virtual address for the kernel data segment. Must not be defined
when using the decompressor.
// 就是 Load Address 中的那个 ZRELADDR , 如果实在没办法了, 就将 ZRELADDR 的值 赋值给 UIMAGE_LOADADDR ZRELADDR 内核启动在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. 值有要求,值 = PHYS_OFFSET + TEXT_OFFSET 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) 25 PARAMS_PHYS := $(params_phys-y) 26 INITRD_PHYS := $(initrd_phys-y)
INITRD_PHYS
Physical address to place the initial RAM disk. Only relevant if
you are using the bootpImage stuff (which only works on the old
struct param_struct).
PARAMS_PHYS
Physical address of the struct param_struct or tag list, giving the
kernel various parameters about its execution environment.
Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html
Initial definitions
-------------------
The following symbol definitions rely on you knowing the translation that
__virt_to_phys() does for your machine. This macro converts the passed
virtual address to a physical address. Normally, it is simply:
phys = virt - PAGE_OFFSET + PHYS_OFFSET
TASK_SIZE The maximum size of a user process in bytes. Since user space always starts at zero, this is the maximum address that a user process can access+1. The user space stack grows down from this address. Any virtual address below TASK_SIZE is deemed to be user process area, and therefore managed dynamically on a process by process basis by the kernel. I'll call this the user segment. Anything above TASK_SIZE is common to all processes. I'll call this the kernel segment. (In other words, you can't put IO mappings below TASK_SIZE, and hence PAGE_OFFSET).
Architecture Specific Macros ---------------------------- BOOT_MEM(pram,pio,vio) `pram' specifies the physical start address of RAM. Must always be present, and should be the same as PHYS_OFFSET. `pio' is the physical address of an 8MB region containing IO for use with the debugging macros in arch/arm/kernel/debug-armv.S. `vio' is the virtual address of the 8MB debugging region. It is expected that the debugging region will be re-initialised by the architecture specific code later in the code (via the MAPIO function). BOOT_PARAMS Same as, and see PARAMS_PHYS. FIXUP(func) Machine specific fixups, run before memory subsystems have been initialised. MAPIO(func) Machine specific function to map IO areas (including the debug region above). INITIRQ(func) Machine specific function to initialise interrupts.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。