首页 > 其他分享 >zImage自解压起始地址:ZRELADDR

zImage自解压起始地址:ZRELADDR

时间:2023-07-01 11:14:29浏览次数:33  
标签:解压 r4 ZRELADDR zreladdr memblock zImage

由于内存较小,zImage的起始地址受限。按照内存规划,修改zImage的加载地址,但是解压后Linux运行产生异常,可能是DataAbort,或者PrefetchAbort,或者Undefined Instruction。

1. 定位zImage自解压后,Kernel启动异常问题

T32启动运行后发现Kernel进入异常处理。大概位置在zImage自解压成功后,Linun earlyprintk之前。

T32跟踪从start_kernel开始的执行流程,发现问题异常在arm_memblock_init(),这属于memblock一部分。

尝试打开对memblock的调试,在bootargs中增加:

bootargs = "xxx earlyprintk memblock=debug"

从T32中可以看出memblock_reserve()的区间不符合预期。从启动日志打印的memblock_reserver信息:

Memory policy: Data cache writeback
memblock reserve: [0x80100000-0x8125113b] arm memblock init+0x30/0x158
memblock reserve: [0x80004000-0x80007fff] arm memblock init+0x108/0x158
memblock reserve: [0x86dfb@00-0x86dfcfff] arm memblock init+0x11c/0x1583

由于zImage位于0x82E00000,期望解压后镜像位于之后的地址。但是实际解压到了0x80000000后的地址。问题指向解压缩地址。

2. ZREALADDR定义解压缩地址

分析zImage解压缩代码,decompress_kernel()是入口。分析可知r0是解压目的起始地址,来自于r4。

/*
 * The C runtime environment should now be setup sufficiently.
 * Set up some pointers, and start decompressing.
 *   r4  = kernel execution address
 *   r7  = architecture ID
 *   r8  = atags pointer
 */
        mov    r0, r4
        mov    r1, sp            @ malloc space above stack
        add    r2, sp, #0x10000    @ 64k max
        mov    r3, r7
        bl    decompress_kernel

往前追溯r4的来源,可知对当前PC地址往前进行128MB对齐,然后加上0x8000偏移。对于0x82XXXXXX地址,最终r4即为0x80008000。

#ifdef CONFIG_AUTO_ZRELADDR
        /*
         * Find the start of physical memory.  As we are executing
         * without the MMU on, we are in the physical address space.
         * We just need to get rid of any offset by aligning the
         * address.
         *
         * This alignment is a balance between the requirements of
         * different platforms - we have chosen 128MB to allow
         * platforms which align the start of their physical memory
         * to 128MB to use this feature, while allowing the zImage
         * to be placed within the first 128MB of memory on other
         * platforms.  Increasing the alignment means we place
         * stricter alignment requirements on the start of physical
         * memory, but relaxing it means that we break people who
         * are already placing their zImage in (eg) the top 64MB
         * of this range.
         */
        mov    r4, pc
        and    r4, r4, #0xf8000000
        /* Determine final kernel image address. */
        add    r4, r4, #TEXT_OFFSET
#else
        ldr    r4, =zreladdr
#endif

所以找到了问题根源。关闭CONFIG_AUTO_ZRELADDR,配置zreladdr的值。

3. 配置zreladdr指定解压地址

在arch/arm/boot/Makefile中将zreladdr-y的值赋给ZRELADDR。

# 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)
PARAMS_PHYS := $(params_phys-y)
INITRD_PHYS := $(initrd_phys-y)

在arch/arm/boot/compressed/Makefile中将ZRELADDR的值赋给符号zreladdr,传入compressed vmlinux编译。

# Supply kernel BSS size to the decompressor via a linker symbol.
KBSS_SZ = $(shell echo $$(($$($(CROSS_COMPILE)nm $(obj)/../../../../vmlinux | \
        sed -n -e 's/^\([^ ]*\) [AB] __bss_start$$/-0x\1/p' \
               -e 's/^\([^ ]*\) [AB] __bss_stop$$/+0x\1/p') )) )
LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
# Supply ZRELADDR to the decompressor via a linker symbol.
ifneq ($(CONFIG_AUTO_ZRELADDR),y)
LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
endif

通用的做法是在mach-xxx的Makefile.boot中增加zreladdr-y的赋值。

   zreladdr-y    += 0x82E08000

这里相对于zImage的实际加载地址有一个0x00008000的偏移。是因为前面存在内核启动参数以及MMU页表。

或者增加一个配置选项CONFIG_ZRELADDR_ADDR,然后赋值给ZRELADDR。

ZRELADDR := $(CONFIG_ZRELADDR_ADDR)

 更多zImage自解压流程参考:《Linux 启动流程之自解压(一)》、《Linux 启动流程之自解压(二)》、《Linux 启动流程之自解压(三)》、《Linux 启动流程之自解压(四)》。《Linux内核源码分析--内核启动之zImage自解压过程

标签:解压,r4,ZRELADDR,zreladdr,memblock,zImage
From: https://www.cnblogs.com/arnoldlu/p/17515078.html

相关文章

  • linux把文件压缩成.tar.gz的命令&各个压缩解压命令大全--九五小庞
    针对LINUX中解压和压缩的命令,一直以来使用都模糊不清,今天在此进行整理01-.tar格式解包:[*******]$tarxvfFileName.tar打包:[*******]$tarcvfFileName.tarDirName(注:tar是打包,不是压缩!)02-.gz格式解压1:[*******]$gunzipFileName.gz解压2:[*******]$gzip-dFileName.gz压缩:[*******]$gzipFileName03-......
  • epub文件解压
    <dependency><groupId>com.positiondev.epublib</groupId><artifactId>epublib-core</artifactId><version>3.1</version></dependency><!--html解析--><dependency><groupId>org.jsoup<......
  • 语音信号的哈夫曼编码压缩解压缩算法matlab仿真,输出编码后数据大小,编码树等指标
    1.算法仿真效果matlab2022a仿真结果如下:     2.算法涉及理论知识概要        利用哈夫曼编码进行信息通信可以较大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码......
  • gz后缀的文件怎么解压
    windows10下解压.gz后缀文件解压缩从linux系统下备份的.gz格式的文件,1、打开windows下,搜索行输入windowspowerShell,如下图2、打开windowspowerShell界面,(1)输入cddesktop(文件的存储位置,示例为存储在电脑桌面上),(2)输入tar-zxvf需要解压的文件名称,(3)回车(4)解压完成3、桌面......
  • Linux 下分卷压缩,windows 解压
    1.Linux分卷压缩tarczf-/mnt/import2023/|split-b3G-/mnt/hq2023.tar.gz压缩后形成的文件: 2.将这些文件复制到windows,然后运行命令copy/bhq2023.tar.*hq2023.tar.gz 3.完成后,用winrar打开hq2023.tar.gz即可看到完成文件夹目录 ......
  • Node rar压缩/解压文件
    暂时未发现node有好用的rar解压/压缩库,所以就自己搜索了一下,简单写了一个,并做了个简单的封装。rar文件的压缩/解压是通过命令行来完成的,所以就需要node的child_process库,这个npmixxx就可以了。大概了解了下rar的语法,这个在WinRAR的安装文件目录下可以看到,我的是:C:/ProgramFiles......
  • RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2 新增解压缩工具类ZipHelper
    在项目对文件进行解压缩是非常常用的功能,对文件进行压缩存储或传输可以节省流量与空间。压缩文件的格式与方法都比较多,比较常用的国际标准是zip格式。压缩与解压缩的方法也很多,在.NET2.0开始,在System.IO.Compression中微软已经给我们提供了解压缩的方法GZipStream。对于GZipSt......
  • ubuntu解压ZIP文件名乱码问题
    背景一个windows压缩的zip文件,再ubuntu中解压后,文件名全是乱码,试过很多GBK、UTF-8的转换方法后找到该方法解决办法安装包sudoapt-getinstallunar使用假设需要解压的ZIP包是foo.zip列出所有文件lsarfoo.zip>如果列出的文件名已经正确解压所有文件unarfoo.z......
  • Linux解压缩常用命令
    01-.tar格式解包:[*******]$tarxvfFileName.tar打包:[*******]$tarcvfFileName.tarDirName(注:tar是打包,不是压缩!)02-.gz格式解压1:[*******]$gunzipFileName.gz解压2:[*******]$gzip-dFileName.gz压缩:[*******]$gzipFileName03-.tar.gz格式解压:[*******]$tarzxvfFileNa......
  • 解压gzip数据流 和 file_get_contents()函数支持SSL错误和header
    file_get_contents()函数的相关参数,支持SSL错误和header $options=array("ssl"=>array("verify_peer"=>false,"verify_peer_name"=>false,), "http"=>array('timeout......