Unstable version of device tree compability. Device tree passes through bootloader, but doesn't parse on this stage.
335 lines
5.0 KiB
ArmAsm
335 lines
5.0 KiB
ArmAsm
_start:
|
|
ldr sp, =stack_top
|
|
mov r9, r2
|
|
|
|
/* Print banner */
|
|
ldr r0, =msg_empty
|
|
bl puts
|
|
ldr r0, =msg_empty
|
|
bl puts
|
|
ldr r0, =msg_banner
|
|
bl puts
|
|
|
|
/* Check if in hypervisor mode */
|
|
mrs r0, cpsr
|
|
and r1, r0, #0x1f
|
|
cmp r1, #0x1a
|
|
bne mode_svc
|
|
|
|
mode_hyp:
|
|
/* In hypervisor mode */
|
|
ldr r0, =msg_hypmode
|
|
bl puts
|
|
|
|
movw r0, #0x1d3
|
|
ldr r1, =mode_svc
|
|
msr ELR_hyp, r1
|
|
msr SPSR_hyp, r0
|
|
eret
|
|
nop
|
|
|
|
mode_svc:
|
|
nop
|
|
ldr sp, =stack_top
|
|
|
|
/* In supervisor mode */
|
|
ldr r0, =msg_svcmode
|
|
bl puts
|
|
|
|
/* Move CPIO archive out of the way */
|
|
ldr r0, =0xA000000
|
|
ldr r1, =stack_top
|
|
mov r2, #0x2000000
|
|
bl memcpy
|
|
|
|
load_files:
|
|
ldr r0, =msg_extract
|
|
bl puts
|
|
/* Load kernel */
|
|
ldr r0, =0x0A000000
|
|
ldr r1, =0x00200000
|
|
bl load_file
|
|
/* Load module */
|
|
ldr r4, =0x02000000
|
|
ldr r5, =0x00800000
|
|
load_files_loop:
|
|
mov r1, r4
|
|
bl load_file
|
|
cmp r0, #0
|
|
beq final_preparations
|
|
add r4, r4, r5
|
|
b load_files_loop
|
|
final_preparations:
|
|
/* Set up args and jump */
|
|
ldr r0, =msg_launch
|
|
bl print
|
|
mov r0, #0x22
|
|
bl putc
|
|
ldr r0, =argv1
|
|
bl print
|
|
mov r0, #0x22
|
|
bl putc
|
|
ldr r0, =msg_empty
|
|
bl puts
|
|
mov r0, #2
|
|
ldr r1, =argv
|
|
mov r2, r9
|
|
b 0x00200000
|
|
|
|
/*
|
|
* Load a file from CPIO archive.
|
|
* r0: address of CPIO archive
|
|
* r1: address to copy the file to
|
|
* Return: address of next entry, or 0 if loading failed
|
|
*/
|
|
load_file:
|
|
push {r4-r8,lr}
|
|
mov r4, r0
|
|
mov r5, r1
|
|
mov r6, r2
|
|
|
|
/* Check header : either 070701 or 070702 */
|
|
ldr r0, [r4]
|
|
ldr r1, =0x37303730
|
|
cmp r0, r1
|
|
bne load_file_failed
|
|
ldr r0, [r4, #4]
|
|
ldr r1, =0xFFFF
|
|
and r1, r1, r0
|
|
ldr r2, =0x3130
|
|
cmp r1, r2
|
|
beq load_file_header_ok
|
|
ldr r2, =0x3230
|
|
cmp r1, r2
|
|
bne load_file_failed
|
|
load_file_header_ok:
|
|
/* Check for trailer */
|
|
ldrh r0, [r4, #0x6e]
|
|
ldr r1, =0x5254
|
|
cmp r1, r0
|
|
beq load_file_failed
|
|
ldrh r0, [r4, #0x6e]
|
|
ldr r1, =0x4941
|
|
cmp r1, r0
|
|
beq load_file_failed
|
|
|
|
/* Get data size */
|
|
add r0, r4, #0x36
|
|
bl hex2bin
|
|
mov r7, r0
|
|
/* Get filename size */
|
|
add r0, r4, #0x5e
|
|
bl hex2bin
|
|
mov r8, r0
|
|
|
|
/* Print file, size and offset */
|
|
add r0, r4, #0x6e
|
|
bl print
|
|
|
|
mov r0, r8
|
|
load_file_name_padding_loop:
|
|
cmp r0, #24
|
|
bgt load_file_name_padding_loop_end
|
|
push {r0}
|
|
mov r0, #0x20
|
|
bl putc
|
|
pop {r0}
|
|
add r0, r0, #1
|
|
b load_file_name_padding_loop
|
|
|
|
load_file_name_padding_loop_end:
|
|
ldr r0, =msg_size
|
|
bl print
|
|
mov r0, r7
|
|
bl print_hex
|
|
ldr r0, =msg_addr
|
|
bl print
|
|
mov r0, r5
|
|
bl print_hex
|
|
/* Add CR/LF */
|
|
mov r0, #0xd
|
|
bl putc
|
|
mov r0, #0xa
|
|
bl putc
|
|
|
|
/* Get pointer to data source */
|
|
add r1, r4, #0x6e
|
|
add r1, r1, r8
|
|
/* Align to 4 bytes */
|
|
and r2, r1, #0x3
|
|
cmp r2, #0
|
|
mov r0, #4
|
|
subne r2, r0, r2
|
|
addne r1, r1, r2
|
|
|
|
mov r0, r5
|
|
mov r2, r7
|
|
push {r1}
|
|
bl memcpy
|
|
|
|
pop {r0}
|
|
add r0, r7
|
|
/* Align to 4 bytes */
|
|
and r2, r0, #0x3
|
|
cmp r2, #0
|
|
mov r1, #4
|
|
subne r2, r1, r2
|
|
addne r0, r0, r2
|
|
|
|
pop {r4-r8,lr}
|
|
bx lr
|
|
load_file_failed:
|
|
mov r0, #0
|
|
pop {r4-r8,lr}
|
|
bx lr
|
|
|
|
/*
|
|
* Send one character to the PL011 UART.
|
|
* r0: character to send
|
|
*/
|
|
putc:
|
|
/* Loop as long as FIFO isn't empty */
|
|
ldr r1, =0x3f201018
|
|
ldr r1, [r1]
|
|
and r1, #0x80
|
|
tst r1, #0x80
|
|
beq putc
|
|
|
|
# Write character
|
|
ldr r1, =0x3f201000
|
|
str r0, [r1]
|
|
|
|
bx lr
|
|
|
|
/*
|
|
* Print an ASCIIZ string to the PL011 UART.
|
|
* r0: address of string to print
|
|
*/
|
|
print:
|
|
push {lr}
|
|
/* If end of string, add newline */
|
|
print_loop:
|
|
ldrb r1, [r0]
|
|
cmp r1, #0
|
|
beq print_end
|
|
|
|
/* Send character */
|
|
push {r0}
|
|
mov r0, r1
|
|
bl putc
|
|
pop {r0}
|
|
/* Advance to next character */
|
|
add r0, r0, #1
|
|
b print_loop
|
|
|
|
print_end:
|
|
pop {lr}
|
|
bx lr
|
|
/*
|
|
* Print an ASCIIZ string to the PL011 UART, followed by CR/LF.
|
|
* r0: address of string to print
|
|
*/
|
|
puts:
|
|
push {lr}
|
|
bl print
|
|
|
|
/* Add CR/LF */
|
|
mov r0, #0xd
|
|
bl putc
|
|
mov r0, #0xa
|
|
bl putc
|
|
|
|
pop {lr}
|
|
bx lr
|
|
|
|
|
|
/*
|
|
* Convert 8 hexadecimal characters to binary.
|
|
* r0: address of string to convert
|
|
* Return: the converted value
|
|
*/
|
|
hex2bin:
|
|
mov r1, #0
|
|
mov r2, #0
|
|
hex2bin_loop:
|
|
ldrb r3, [r0, r2]
|
|
cmp r3, #0x40
|
|
sublt r3, r3, #0x30
|
|
blt hex2bin_add_digit
|
|
cmp r3, #0x60
|
|
sublt r3, r3, #0x37
|
|
blt hex2bin_add_digit
|
|
sub r3, r3, #0x57
|
|
hex2bin_add_digit:
|
|
lsl r1, r1, #4
|
|
add r1, r1, r3
|
|
add r2, r2, #1
|
|
cmp r2, #8
|
|
blt hex2bin_loop
|
|
mov r0, r1
|
|
bx lr
|
|
|
|
/*
|
|
* Print a value as hexadecimal.
|
|
* r0: value to print
|
|
*/
|
|
print_hex:
|
|
push {lr}
|
|
mov r1, #8
|
|
print_hex_loop:
|
|
cmp r1, #0
|
|
ble print_hex_end
|
|
|
|
lsr r2, r0, #28
|
|
cmp r2, #10
|
|
addlt r2, r2, #0x30
|
|
addge r2, r2, #0x37
|
|
|
|
push {r0-r2}
|
|
mov r0, r2
|
|
bl putc
|
|
pop {r0-r2}
|
|
|
|
sub r1, r1, #1
|
|
lsl r0, r0, #4
|
|
b print_hex_loop
|
|
print_hex_end:
|
|
pop {lr}
|
|
bx lr
|
|
|
|
/*
|
|
* Quickly copy a memory area to another.
|
|
* r0: destination
|
|
* r1: source
|
|
* r2: length
|
|
*/
|
|
memcpy:
|
|
push {r5-r11}
|
|
add r2, r0, r2
|
|
memcpy_loop:
|
|
cmp r0, r2
|
|
bge memcpy_done
|
|
ldm r1!, {r3-r11}
|
|
stm r0!, {r3-r11}
|
|
b memcpy_loop
|
|
memcpy_done:
|
|
pop {r5-r11}
|
|
bx lr
|
|
|
|
msg_empty:
|
|
.asciz ""
|
|
msg_banner:
|
|
.asciz "MINIX 3 unpacker for Raspberry Pi"
|
|
msg_svcmode:
|
|
.asciz "Current mode: supervisor"
|
|
msg_hypmode:
|
|
.asciz "Current mode: hypervisor. Switching to supervisor mode..."
|
|
msg_extract:
|
|
.asciz "Extracting modules..."
|
|
msg_launch:
|
|
.asciz "Jumping into kernel, argv[1]="
|
|
msg_size:
|
|
.asciz " size:0x"
|
|
msg_addr:
|
|
.asciz " address:0x"
|