sdk-hwV1.3/lichee/melis-v3.0/source/ekernel/arch/riscv/compressed/head.S

336 lines
7.8 KiB
ArmAsm
Raw Normal View History

2024-05-07 10:09:20 +00:00
/*
* 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 PARTYS TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
* IN ALLWINNERSSDK 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 PARTYS 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
* 不发生自覆盖的条件: 16KMMU
* 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: