336 lines
7.8 KiB
ArmAsm
336 lines
7.8 KiB
ArmAsm
|
/*
|
|||
|
* Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
|
|||
|
*
|
|||
|
* Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
|
|||
|
* the the People's Republic of China and other countries.
|
|||
|
* All Allwinner Technology Co.,Ltd. trademarks are used with permission.
|
|||
|
*
|
|||
|
* DISCLAIMER
|
|||
|
* THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
|
|||
|
* IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
|
|||
|
* IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
|
|||
|
* ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
|
|||
|
* ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
|
|||
|
* COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
|
|||
|
* YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
|
|||
|
*
|
|||
|
*
|
|||
|
* THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
|
|||
|
* PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
|
|||
|
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
|
|||
|
* THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
|
|||
|
* OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|||
|
* IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|||
|
* LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
|
|||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
*/
|
|||
|
|
|||
|
#include <compiler.h>
|
|||
|
|
|||
|
#define HEAP_SIZE (0x10000)
|
|||
|
|
|||
|
.section ".start", "ax", @progbits
|
|||
|
.align
|
|||
|
|
|||
|
.type start, %function
|
|||
|
.option norvc
|
|||
|
start:
|
|||
|
j 1f
|
|||
|
|
|||
|
.word _magic_sig # 魔数
|
|||
|
.word _magic_comp
|
|||
|
.word _magic_start # zImage 绝对运行地址
|
|||
|
.word _magic_end # zImage 结束地址
|
|||
|
.word input_data_end - 4 # decompress image size
|
|||
|
.word 0x04030201 # 结束标志位
|
|||
|
|
|||
|
1:
|
|||
|
# mask all interrupts
|
|||
|
csrw mie, 0
|
|||
|
csrw mip, 0
|
|||
|
|
|||
|
# Enable thead extens
|
|||
|
li t0, (1 << 22) | (1 << 15)
|
|||
|
csrs mxstatus, t0
|
|||
|
|
|||
|
rdtime s8
|
|||
|
/*
|
|||
|
* t0 = 当前pc
|
|||
|
* t4 = 解压Image 起始地址
|
|||
|
* if t0 < t4 :
|
|||
|
* t0 = LC0[8] = _end - restart + = 当前镜像大小
|
|||
|
* t0 = t0 + pc = 当镜像结束地址
|
|||
|
* if t4 < t0 :(这种情况会发生自覆盖)
|
|||
|
* t4 |= 0x1
|
|||
|
* else :
|
|||
|
* bl cache_on
|
|||
|
* else :
|
|||
|
* bl cache_on
|
|||
|
*/
|
|||
|
#ifdef CONFIG_KERNEL_COMPRESS_ELF
|
|||
|
la t4, zelfaddr
|
|||
|
bnez t4, 1f
|
|||
|
|
|||
|
la t0, LC0
|
|||
|
lw s0, 0 * 4(t0) # LC0
|
|||
|
lw t4, 7 * 4(t0) # .L_user_stack_end
|
|||
|
sub t0, t0, s0 # calculate the delta offset
|
|||
|
|
|||
|
add t4, t4, t0
|
|||
|
li t0, HEAP_SIZE
|
|||
|
add t4, t4, t0 # 解压到 当前镜像 结束地址
|
|||
|
#else
|
|||
|
la t4, zreladdr
|
|||
|
#endif
|
|||
|
1:
|
|||
|
auipc t0, 0
|
|||
|
bgeu t0, t4, 1f
|
|||
|
|
|||
|
la t1, LC0
|
|||
|
lw t2, 8 * 4(t1)
|
|||
|
auipc t0, 0
|
|||
|
add t0, t0, t2
|
|||
|
|
|||
|
bltu t4, t0, 2f
|
|||
|
1:
|
|||
|
jal cache_on
|
|||
|
j restart
|
|||
|
2:
|
|||
|
ori t4, t4, 1 # remember we skipped cache_on
|
|||
|
restart:
|
|||
|
la t0, LC0
|
|||
|
lw s0, 0 * 4(t0) # LC0
|
|||
|
lw s1, 1 * 4(t0) # __bss_start
|
|||
|
lw s2, 2 * 4(t0) # _end
|
|||
|
lw s3, 3 * 4(t0) # _edata
|
|||
|
lw s4, 4 * 4(t0) # input+data_end - 4
|
|||
|
lw s5, 5 * 4(t0) # _got_start
|
|||
|
lw s6, 6 * 4(t0) # _got_end
|
|||
|
lw sp, 7 * 4(t0) # .L_user_stack_end
|
|||
|
|
|||
|
/*
|
|||
|
* r0 -= r1 计算偏移, 编译地址与运行地址的差值,以此来修正其他符号的地址
|
|||
|
* r6 += r0 重新计算_edata, 获得_edata的实际运行地址
|
|||
|
* r10 += r0 重新获得压缩后的内核大小数据位置
|
|||
|
*/
|
|||
|
sub t0, t0, s0 # calculate the delta offset
|
|||
|
add s3, s3, t0 # _edata
|
|||
|
add s4, s4, t0 # inflated kernel size location
|
|||
|
|
|||
|
/*
|
|||
|
* 将解压后的内核大小数据正确地放入t1中(避免了大小端问题)
|
|||
|
*/
|
|||
|
lbu t1, 0(s4)
|
|||
|
|
|||
|
lbu t2, 1(s4)
|
|||
|
slli t2, t2, 8
|
|||
|
or t1, t1, t2
|
|||
|
|
|||
|
lbu t2, 2(s4)
|
|||
|
slli t2, t2, 16
|
|||
|
or t1, t1, t2
|
|||
|
|
|||
|
lbu t2, 3(s4)
|
|||
|
slli t2, t2, 24
|
|||
|
or t1, t1, t2
|
|||
|
|
|||
|
/*
|
|||
|
* sp += r0
|
|||
|
* s4 = sp + HEAP_SIZE (预留空间出来给作为后续C环境的堆空间)
|
|||
|
*/
|
|||
|
add sp, sp, t0
|
|||
|
li t5, HEAP_SIZE
|
|||
|
add s4, sp, t5
|
|||
|
|
|||
|
/*
|
|||
|
* 检查是否发生自覆盖.
|
|||
|
* t4 = 解压后镜像的 起始地址
|
|||
|
* t1 = 解压后镜像的 大小
|
|||
|
* s4 = 当前镜像的 结束地址, 包含 bss/stack/malloc 空间
|
|||
|
* 不发生自覆盖的条件: 16K是MMU的页表大小
|
|||
|
* t4 >= s4 -> OK
|
|||
|
* t4 + t1 <= 当前PC -> OK
|
|||
|
*/
|
|||
|
# addi s4, s4, 0x4000
|
|||
|
bgeu t4, s4, wont_overwrite
|
|||
|
add s4, t4, t1
|
|||
|
auipc t1, 0
|
|||
|
bgeu t1, s4, wont_overwrite
|
|||
|
|
|||
|
/*
|
|||
|
* 将自己拷贝到 解压后内核的后面.
|
|||
|
* s3 = _edata 本镜像结束地址 (text+data+bss段,已修正)
|
|||
|
* s4 = 解压后镜像的结束地址
|
|||
|
* Because we always copy ahead, we need to do it from the end and go
|
|||
|
* backward in case the source and destination overlap.
|
|||
|
*/
|
|||
|
/*
|
|||
|
* 复制到解压后的镜像后
|
|||
|
* 对齐到 256B边界
|
|||
|
* s4 = ALIGN_UP(s4, 0xff)
|
|||
|
*/
|
|||
|
# la t5, ((reloc_code_end - restart + 256) & ~255)
|
|||
|
la t5, reloc_code_end
|
|||
|
la t3, restart
|
|||
|
sub t5, t5, t3
|
|||
|
addi t5, t5, 256
|
|||
|
li t3, ~0xff
|
|||
|
and t5, t5, t3
|
|||
|
|
|||
|
add s4, s4, t5
|
|||
|
andi s4, s4, ~0xff
|
|||
|
/*
|
|||
|
* 对齐到32B
|
|||
|
*/
|
|||
|
la t1, restart
|
|||
|
andi t1, t1, ~0x1f
|
|||
|
/*
|
|||
|
* 自复制
|
|||
|
* NOTE:
|
|||
|
* t1 当前 restart 地址
|
|||
|
* s3 当前镜像结束地址
|
|||
|
*/
|
|||
|
sub t2, s3, t1 # size to copy
|
|||
|
addi t2, t2, 0x1f # rounded up to a multiple
|
|||
|
andi t2, t2, ~0x1f # ... of 32 bytes
|
|||
|
add t3, t2, t1 # src t3
|
|||
|
add t2, t2, s4 # dst t2
|
|||
|
|
|||
|
/*
|
|||
|
* 逐个byte复制,直到 t3 <= t1
|
|||
|
* 从后往前复制
|
|||
|
*/
|
|||
|
1: lw a0, 0 * 4(t3)
|
|||
|
lw a0, 1 * 4(t3)
|
|||
|
lw a0, 2 * 4(t3)
|
|||
|
lw a0, 3 * 4(t3)
|
|||
|
addi t3, t3, 4 * 4
|
|||
|
sw a0, 0 * 4(t2)
|
|||
|
sw a0, 1 * 4(t2)
|
|||
|
sw a0, 2 * 4(t2)
|
|||
|
sw a0, 3 * 4(t2)
|
|||
|
addi t2, t2, 4 * 4
|
|||
|
bgeu t3, t1, 1b
|
|||
|
|
|||
|
/* 保留重定位代码的偏移 */
|
|||
|
sub t6, t2, t3
|
|||
|
/* cache_clean_flush may use the stack, so relocate it */
|
|||
|
add sp, sp, t6
|
|||
|
|
|||
|
jal cache_clean_flush
|
|||
|
|
|||
|
la t1, restart
|
|||
|
add t1, t1, t6
|
|||
|
jr t1
|
|||
|
|
|||
|
wont_overwrite:
|
|||
|
/*
|
|||
|
* t0 = delta(编译地址与运行地址的差值)
|
|||
|
* s0 = LC0
|
|||
|
* s1 = BSS start
|
|||
|
* s2 = BSS end
|
|||
|
* s3 = _edata
|
|||
|
* s4 = input+data_end - 4
|
|||
|
* t4 = 解压后镜像的 起始地址
|
|||
|
* s5 = _got_start
|
|||
|
* s6 = _got_end
|
|||
|
* sp = .L_user_stack_end
|
|||
|
*/
|
|||
|
beqz t0, not_relocated
|
|||
|
|
|||
|
/* 重定位 GOT */
|
|||
|
add s5, s5, t0
|
|||
|
add s6, s6, t0
|
|||
|
/* 重定位 BSS */
|
|||
|
add s1, s1, t0
|
|||
|
add s2, s2, t0
|
|||
|
|
|||
|
not_relocated:
|
|||
|
1: sw t0, 0(s1)
|
|||
|
addi s1, s1, 4
|
|||
|
bltu s1, s2, 1b
|
|||
|
|
|||
|
/*
|
|||
|
* 如果前面跳过了 cache_on, t4的最低位=1
|
|||
|
* 这里补上 开 cache
|
|||
|
*/
|
|||
|
andi t0, t4, 0x1
|
|||
|
beqz t0, 2f
|
|||
|
li t5, 1
|
|||
|
sub t4, t4, t5
|
|||
|
jal cache_on
|
|||
|
2:
|
|||
|
/*
|
|||
|
* 准备跳到C执行代码
|
|||
|
* a0 = 内核代码的开始地址
|
|||
|
*/
|
|||
|
mv x3, t4
|
|||
|
mv a0, t4
|
|||
|
mv a1 , sp # free_mem_start
|
|||
|
li t5, HEAP_SIZE
|
|||
|
add a2, sp, t5 # free_mem_end
|
|||
|
mv a3, x0 # architecture ID
|
|||
|
jal decompress_kernel
|
|||
|
jal cache_clean_flush
|
|||
|
#ifdef CONFIG_KERNEL_COMPRESS_ELF
|
|||
|
mv a0, x3
|
|||
|
jal load_elf_image
|
|||
|
mv a0, x3
|
|||
|
jal elf_get_entry_addr
|
|||
|
mv x3, a0
|
|||
|
jal cache_clean_flush
|
|||
|
#endif
|
|||
|
jal cache_off
|
|||
|
|
|||
|
mv a0, s8
|
|||
|
jr x3 # __enter_kernel
|
|||
|
|
|||
|
.align 5
|
|||
|
.type LC0, %object
|
|||
|
LC0:
|
|||
|
.word LC0 # s0
|
|||
|
.word __bss_start # s1
|
|||
|
.word _end # s2
|
|||
|
.word _edata # s3
|
|||
|
.word input_data_end - 4 # s4 (inflated size location)
|
|||
|
.word _got_start # s5
|
|||
|
.word _got_end # s6
|
|||
|
.word .L_user_stack_end # sp
|
|||
|
.word _end - restart # s7
|
|||
|
.size LC0, . - LC0
|
|||
|
|
|||
|
.align 5
|
|||
|
cache_on:
|
|||
|
li t0, 0x11ff
|
|||
|
csrw mhcr, t0
|
|||
|
li t0, 0x638000
|
|||
|
csrw mxstatus, t0
|
|||
|
li t0, 0x11ff
|
|||
|
csrw mhint, t0
|
|||
|
fence
|
|||
|
sync
|
|||
|
ret
|
|||
|
cache_off:
|
|||
|
li t0, 0x3
|
|||
|
csrc mhcr, x0
|
|||
|
fence
|
|||
|
sync
|
|||
|
ret
|
|||
|
cache_clean_flush:
|
|||
|
dcache.call
|
|||
|
icache.iall
|
|||
|
fence
|
|||
|
sync
|
|||
|
ret
|
|||
|
|
|||
|
reloc_code_end:
|
|||
|
.align 6
|
|||
|
.section ".stack", "aw", %nobits
|
|||
|
.L_user_stack: .space 4096
|
|||
|
.L_user_stack_end:
|