forked from eeply/ps4-kexec
-
Notifications
You must be signed in to change notification settings - Fork 4
/
linux_thunk.S
90 lines (78 loc) · 2.57 KB
/
linux_thunk.S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
* ps4-kexec - a kexec() implementation for Orbis OS / FreeBSD
*
* Copyright (C) 2015-2016 shuffle2 <[email protected]>
* Copyright (C) 2015-2016 Hector Martin "marcan" <[email protected]>
*
* This code is licensed to you under the 2-clause BSD license. See the LICENSE
* file for more information.
*/
.intel_syntax noprefix
.equ setup_sects, 0x1f1
.equ shdr_syssize, 0x1f4
.equ pref_address, 0x258
.text
#void jmp_to_linux(
# uintptr_t image_base, rdi
# uintptr_t bootargs, rsi
# uintptr_t new_cr3, rdx
# uintptr_t gdt_ptr rcx
#);
.globl jmp_to_linux
jmp_to_linux:
# switch to new gdt + data segments
cli
lgdt [rcx]
#xor eax, eax
mov eax, 0x18
mov ds, eax
mov ss, eax
mov es, eax
mov fs, eax
mov gs, eax
# switch to our own page tables (in low mem)
mov cr3, rdx
# now we're on our own page tables, so we can obliterate the rest of memory
# TODO make sure we don't inadvertently overwrite (important) smap regions
# I think on ps4 we'll actually want to load to 0x700000
# since we have tons of free room there.
# on 4.00/4.01, bzImage might be allocated at 0x800000 accidently. We
# should choose a higher address as pref_address.
# save args
mov r12, rdi
mov r13, rsi
# memmove(pref_address, , (syssize * 0x10) / 8)
#mov rdi, [r12 + pref_address] # dst = [image_base + pref_address] ; where linux image wants to go
#mov rdi, 0x700000 # where ps4 freebsd kernel is loaded (before relocating itself)
mov rdi, 0x6000000 # should be far from bzImage and initramfs
mov r14, rdi # r14 = pref_address
xor edx, edx
mov dl, [r12 + setup_sects]
inc rdx
shl rdx, 9 # rdx = offsetof(image_base, startup_32)
lea rsi, [r12 + rdx] # src = image_base + startup_32
mov ecx, [r12 + shdr_syssize]
shl rcx, 4
add rdi, rcx
add rsi, rcx
sub rdi, 8
sub rsi, 8
shr rcx, 3
std
rep movsq
cld
# make a tiny stack - we just need it for the lretq.
# what we jump to will not use this stack
lea rsp, [rip + jmp_to_linux_end + 0x200]
and rsp, -0x10
#push 0 # retaddr
push 0x10 # cs = GDT[2]
add r14, 0x200 # pref_address + startup_64
push r14 # rip
mov rsi, r13 # bootargs
lretq
jmp_to_linux_end:
.data
.globl jmp_to_linux_size
jmp_to_linux_size: .quad jmp_to_linux_end - jmp_to_linux
.att_syntax prefix