SlideShare a Scribd company logo
1 of 35
Linux Kernel 코드분석
(Ver 3.12.20)
arch/arm/boot/compressed/head.S
(dtb_check_done, wont_overwrite)
!!! 분석 전에 잠깐 !!!
dtb_check_done 을 시작하는 시점에서 주요 register 의 상태는 다음과
같다 .
* r4 = final kernel address (possibly with LSB set)
* r9 = size of decompressed image
* r10 = end of this image, including bss/stack/malloc space if
non XIP
malloc
stack
bss
zImage
!!! Overwrite 과 Wont_Overwrite 여부를 판단하기 위한 4 가지 경우의 수
 (2), (4) 번은 Overwrite 가 발생하므로 이미지 재배치 필요 .
Page Table (16k)
r10
Uncompressed
Image
r4
Page Table (16k)
Uncompressed
Image
r4
malloc
stack
bss
zImage
r10
Page Table (16k)
r10
Uncompressed
Image
r4
r9
wont_overwrite
r4 – 16k >= r10
OK
 wont_overwrite 분기
r4 – 16k < r10
Overwrite
 Relocation 필요
r4 + r9 <= r10
OK
 wont_overwrite 분기
r10 wont_overwrite
Page Table (16k)
Uncompressed
Image
r4
r9
r4 + r9 > r10
Overwrite
 Relocation 필요
(1
)
(2
)
(3
)
(4
)
!!! (2) 번과 (4) 번의 경우 Overwrite 을 회피하기 위해 이미지의 재배치 목적지를
어디로 해야할까 ? 개념적으로 보면 아래와 같다 .
Page Table (16k)
Uncompressed
Image
malloc
stack
bss
zImage
r10
(2
)
malloc
stack
bss
zImage
원래의 이미지를 Uncompressed
Image 의 End 위로 배치해야 한다
.
r10 wont_overwrite
Page Table (16k)
Uncompressed
Image
r4
(4
)
r4
malloc
stack
bss
zImage
재배치 시 현재의 Code 를
Overwrite 하지 않도록 마찬가지로
Uncompressed Image End 위로 배
치해야 한다 .
위와 같이 재배치를 수행한 후 PC 를 재배치한 이미지의 restart label 로 설정하여 , 다
시 restart 부터 수행하게 된다는 것이 restart, dtb_check_done, wont_overwrite label
들의 역할이다 .
restart ~ wont_overwrite 부분의 Code 는 앞에서 살펴보았던 4 가
지 경우 각각을 가정하면서 분석해야 한다 !!!
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Current Image 가 Page
Table 및 Uncompressed
Image 와 Overwrite 되는지
검사 .
Page Table (16k)
Uncompressed
Image
Current Image
(zImage ~ dtb end)
r10
r4
r9
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 되지 않으면 wont_overwrite
로 분기  (1) 번 경우
Page Table (16k)
Uncompressed
Image
Current Image
(zImage ~ dtb end)
r10
r4
r9
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Current Image 가 Page
Table 및 Uncompressed
Image 와 Overwrite 됨 .
r10 Pointer 변경 .
Page Table (16k)
Uncompressed
Image
Current Image
(zImage ~ dtb end)
r10
r4
r9
wont_overwrite
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
r9 Pointer 변경 .
Page Table (16k)
Uncompressed
Image
Current Image
(zImage ~ dtb end)
r10
r4
r9wont_overwrite
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
wont_overwrite 이 Uncompressed Image
End 위에 있는지 검사
 (3) 번 경우인지 (4) 번 경우인지 검사
Page Table (16k)
Uncompressed
Image
Current Image
(zImage ~ dtb end)
r10
r4
r9wont_overwrite
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
(3) 번 경우 분기
 Decompressed Image End 가 Current Image 의 wont_overwrite 를
Overwrite 하지 않음 .
Page Table (16k)
Current Image
(zImage ~ dtb end)
r10
r4
r9wont_overwrite
Uncompressed
Image
이제 재배치가 필요한 (2) 번과 (4) 번 , 즉 Overwrite 되는 경우라서
wont_overwrite 로 분기하지 않았던 Case 만 남았다 . !!!
Page Table (16k)
Uncompressed
Image
malloc
stack
bss
zImage
(2
)
그런데 , (2) 번과 (4) 번이 다른 Case 인가 ?
 그렇지 않다 .
wont_overwrite
Page Table (16k)
Uncompressed
Image
(4
)
그냥 Current Image 가 조금 위에 있거나 아래에 있는게 다를 뿐이다 .
(2) 번은 아래쪽에 있어서 Page Table 및 Uncompressed Image 와
Overwrite 될 가능성이 있는 경우이고 , (4) 는 그보다 좀더 위쪽에 있
어서 Uncompress 시 Current Image 를 Overwrite 할 가능성이 있는
경우이다 .
그렇다면 , 이를 어쩌나 ?
 Current Image 의 위치를 재배치하고 다시 수행해야겠지 .
어느 위치로 ?
 재배치 후의 restart 가 최소한 Decompressed Image 위에 오도록
Page Table (16k)
Uncompressed
Image
(2
)
restart
Page Table (16k)
Uncompressed
Image
restart
Page Table (16k)
Uncompressed
Image
Page Table (16k)
Uncompressed
Image
restart
(4
)
wont_overwrite
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 가 발생하는 경우임 . (2), (4)
Page Table (16k)
Current Image
(zImage ~ dtb end)
r10
r4
r9wont_overwrite
Uncompressed
Image
r10 의 위치 변경 (256 byte align)
재배치를 앞두고 이 만큼을 추가로 확보하는 이유는 ?
reloc_code_end
r10
restart
왜 하필 256 byte align 일까 ?  확인 필
요
restart ~ reloc_code_end
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 가 발생하는 경우임 . (2), (4)
Page Table (16k)
Current Image
(zImage ~ dtb end)
r4
r9wont_overwrite
Uncompressed
Image
r5 = restart 주소 (32 byte align)
reloc_code_end
r10
restartr5
restart ~ reloc_code_end
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 가 발생하는 경우임 . (2), (4)
Page Table (16k)
Current Image
(zImage ~ dtb end)
r4
r9wont_overwrite
Uncompressed
Image
Hyper mode 가 아니면 1f 분기
reloc_code_end
r10
restartr5
restart ~ reloc_code_end
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 가 발생하는 경우임 . (2), (4)
Page Table (16k)
Current Image
(zImage ~ dtb end)
r4
r9
wont_overwrite
Uncompressed
Image
restart ~ dtb end 차이 값을 32 byte
align  r9
reloc_code_end
r10
restartr5
r6
restart ~ reloc_code_end
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 가 발생하는 경우임 . (2), (4)
Page Table (16k)
Current Image
(zImage ~ dtb end)
r4
r9
wont_overwrite
Uncompressed
Image
32 byte align 된 r5 와 r9 을 더하여 r6 위치 32
byte align 위치로 살짝 조정
 이건 재배치의 Source 자리임 .
reloc_code_end
r10
restartr5
r6
restart ~ reloc_code_end
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 가 발생하는 경우임 . (2), (4)
Page Table (16k)
Current Image
(zImage ~ dtb end)
r4
r9
wont_overwrite
Uncompressed
Image
r9 위치 설정  r9 의 위치는 재배치의 Destination
위치임 .
reloc_code_end
r10
restartr5
r6
r9
restart ~ dtb end
restart ~ reloc_code_end
dtb_check_done:
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
add r10, r10, #((reloc_code_end - restart
+ 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
#ifdef CONFIG_ARM_VIRT_EXT
mrs r0, spsr
and r0, r0, #MODE_MASK
cmp r0, #HYP_MODE
bne 1f
bl __hyp_get_vectors
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
1:
#endif
sub r9, r6, r5
add r9, r9, #31
bic r9, r9, #31
add r6, r9, r5
add r9, r9, r10
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
Overwrite 가 발생하는 경우임 . (2), (4)
Page Table (16k)
r4
r9
Uncompressed
Image
r6 ~ restart 까지를 모두 r9 위치로 decremental 로
복사함 .
r10
restartr5
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
restartr5
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
r6 = 신규 dtb end 위치 (r9) 과 기존 dtb end (r6) 와의
offset
즉 , r6 는 재배치로 인해 이동한 Offset
r6
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
restartr5
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
기존의 sp 위치도 재배치 후의 위치로 변경시켜줌 .
r6
sp
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
restartr5
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
cache_on 을 skip 했을 경우 r4 의 LSB 가 1 로 설정되어
있다 .
cache_on 을 했다고 가정하면 flush 해야 함 .
r6
sp
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
restartr5
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
r0 값을 현재의 restart label 에서 재배치한 위치의 restart 값
으로 설정
r6
sp
r0
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
pc 값을 재배치한 restart 로 설정하여 restart 부터 다시 수행 .
다시 수행하게 되면 그 때부터는 Overwrite 가 발생하지 않는 (3)
번
Case 로 수행하게 되어 중간에 wont_overwrite 로 분기하게 된다 .
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
재배치를 거쳤건 안거쳤건 restart 에서 분기해온 상태에서
r0 = delta offset (LC0 label 과 LC0 word 값 차이 )
r5 = dtb size
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
(1) r0 = 0 | r5 = 0 -> 0 -> not reloc
(2) r0 = 1 | r5 = 0 -> 1 -> reloc
(3) r0 = 0 | r5 = 1 -> 1 -> reloc
(4) r0 = 1 | r5 = 1 -> 1 -> reloc
(1)의 경우는 확실히 재배치가 발생하지 않은 경우이다 .
재배치가 발생해서 restart 쪽을 다시 거쳤다면 delta offset 이 0 일
수가 없다 .
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
GOT start (r11) 와 GOT end (r12) 의 위치도 재배치를 고려하여 delta
offset (r0) 만큼 이동시켜준다 .
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
BSS start (r2) 와 BSS end (r3) 의 위치도 재배치를 고려하여 delta
offset (r0) 만큼 이동시켜준다 .
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
GOT 의 첫번째 entry 값을 가져와서 delta offset 을 더해준다 .
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
Delta offset 조정된 GOT Entry 값이 bss start ~ bss end 사이의 값이
면
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
Entry 값에 dtb size 값을 더해준다 .
r6
sp
r0pc
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
다음 GOT Entry 에 대해 동일한 작업을 하기 위해 1b 로 이동한다 .
GOT end 를 만나면 Loop 를 끝낸다 .
결국 이는 GOT 의 모든 Entry 값들을 delta offset 과 dtb size 를 고
려하여 조정하는 것이다 . ( 재배치가 발생했을 수도 있으므로 )
r6
sp
r0pc
그런데 , 왜 GOT Entry 의 값이 bss start ~ end 내에 포함되는지를 검사하는 것일까
?
sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
add sp, sp, r6
#endif
tst r4, #1
bleq cache_clean_flush
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
wont_overwrite:
orrs r1, r0, r5
beq not_relocated
add r11, r11, r0
add r12, r12, r0
#ifndef CONFIG_ZBOOT_ROM
add r2, r2, r0
add r3, r3, r0
1: ldr r1, [r11, #0]
add r1, r1, r0
cmp r1, r2
cmphs r3, r1
addhi r1, r1, r5
str r1, [r11], #4
cmp r11, r12
blo 1b
add r2, r2, r5
add r3, r3, r5
#else
…
#endif
Page Table (16k)
r4
r9
Uncompressed
Image
r10
r6
restart ~ dtb end
restart ~ reloc_code_end
Current Image
(zImage ~ dtb end)
restart
bss start 와 bss end 의 값도 dtb size 를 더한 값으로 조정해준다 .
( 위쪽에서 delta offset 값은 이미 더해주었다 .)
r6
sp
r0pc
stack
bss
wont_overwrite 을 마친 후의 memory map 및 register 상태
 재배치가 완료되었을 수도 있고 재배치가 불필요했을 수도 있다 .
Page Table (16k)
Uncompressed
Image
r10 r6 :
재배치했다면 이전 dtb end
를 가리키고 , 재배치 안했다
면 현재의 dtb _end 를 가리
킴 .
r4
r9
r0 : delta offset
r1 : temp
dtb
bss start
재배치한 대상
r7 : architecture ID
r8 :
dtb 가 있다면 dtb start 를
가리키고 , 없다면 atags
pointer 임 .
restart
r5 : dtb size
LC0
GOT start
GOT end
bss end
r2
r3
GOT 의 각 Entry 는 bss 영
역을 가리킴
sp
r11
r12
zImage

More Related Content

Viewers also liked

Syllabus course- Fall 2013(1)
Syllabus course- Fall 2013(1)Syllabus course- Fall 2013(1)
Syllabus course- Fall 2013(1)
Abdalrazzaq Moaz
 

Viewers also liked (6)

Cindy vs. the Huffle Puffle
Cindy vs. the Huffle PuffleCindy vs. the Huffle Puffle
Cindy vs. the Huffle Puffle
 
Estrategia digital rev1
Estrategia digital rev1Estrategia digital rev1
Estrategia digital rev1
 
커널코드분석 20140621(head.s restart)
커널코드분석 20140621(head.s restart)커널코드분석 20140621(head.s restart)
커널코드분석 20140621(head.s restart)
 
Oil and gas industry manpower recruitment in pakistan
Oil and gas industry manpower recruitment in pakistanOil and gas industry manpower recruitment in pakistan
Oil and gas industry manpower recruitment in pakistan
 
Redacción de textos
Redacción de textosRedacción de textos
Redacción de textos
 
Syllabus course- Fall 2013(1)
Syllabus course- Fall 2013(1)Syllabus course- Fall 2013(1)
Syllabus course- Fall 2013(1)
 

커널코드분석 20140628(head.s dtb check_done, wont_overwrite)

  • 1. Linux Kernel 코드분석 (Ver 3.12.20) arch/arm/boot/compressed/head.S (dtb_check_done, wont_overwrite)
  • 2. !!! 분석 전에 잠깐 !!! dtb_check_done 을 시작하는 시점에서 주요 register 의 상태는 다음과 같다 . * r4 = final kernel address (possibly with LSB set) * r9 = size of decompressed image * r10 = end of this image, including bss/stack/malloc space if non XIP malloc stack bss zImage !!! Overwrite 과 Wont_Overwrite 여부를 판단하기 위한 4 가지 경우의 수  (2), (4) 번은 Overwrite 가 발생하므로 이미지 재배치 필요 . Page Table (16k) r10 Uncompressed Image r4 Page Table (16k) Uncompressed Image r4 malloc stack bss zImage r10 Page Table (16k) r10 Uncompressed Image r4 r9 wont_overwrite r4 – 16k >= r10 OK  wont_overwrite 분기 r4 – 16k < r10 Overwrite  Relocation 필요 r4 + r9 <= r10 OK  wont_overwrite 분기 r10 wont_overwrite Page Table (16k) Uncompressed Image r4 r9 r4 + r9 > r10 Overwrite  Relocation 필요 (1 ) (2 ) (3 ) (4 )
  • 3. !!! (2) 번과 (4) 번의 경우 Overwrite 을 회피하기 위해 이미지의 재배치 목적지를 어디로 해야할까 ? 개념적으로 보면 아래와 같다 . Page Table (16k) Uncompressed Image malloc stack bss zImage r10 (2 ) malloc stack bss zImage 원래의 이미지를 Uncompressed Image 의 End 위로 배치해야 한다 . r10 wont_overwrite Page Table (16k) Uncompressed Image r4 (4 ) r4 malloc stack bss zImage 재배치 시 현재의 Code 를 Overwrite 하지 않도록 마찬가지로 Uncompressed Image End 위로 배 치해야 한다 . 위와 같이 재배치를 수행한 후 PC 를 재배치한 이미지의 restart label 로 설정하여 , 다 시 restart 부터 수행하게 된다는 것이 restart, dtb_check_done, wont_overwrite label 들의 역할이다 .
  • 4. restart ~ wont_overwrite 부분의 Code 는 앞에서 살펴보았던 4 가 지 경우 각각을 가정하면서 분석해야 한다 !!!
  • 5. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Current Image 가 Page Table 및 Uncompressed Image 와 Overwrite 되는지 검사 . Page Table (16k) Uncompressed Image Current Image (zImage ~ dtb end) r10 r4 r9
  • 6. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 되지 않으면 wont_overwrite 로 분기  (1) 번 경우 Page Table (16k) Uncompressed Image Current Image (zImage ~ dtb end) r10 r4 r9
  • 7. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Current Image 가 Page Table 및 Uncompressed Image 와 Overwrite 됨 . r10 Pointer 변경 . Page Table (16k) Uncompressed Image Current Image (zImage ~ dtb end) r10 r4 r9 wont_overwrite
  • 8. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b r9 Pointer 변경 . Page Table (16k) Uncompressed Image Current Image (zImage ~ dtb end) r10 r4 r9wont_overwrite
  • 9. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b wont_overwrite 이 Uncompressed Image End 위에 있는지 검사  (3) 번 경우인지 (4) 번 경우인지 검사 Page Table (16k) Uncompressed Image Current Image (zImage ~ dtb end) r10 r4 r9wont_overwrite
  • 10. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b (3) 번 경우 분기  Decompressed Image End 가 Current Image 의 wont_overwrite 를 Overwrite 하지 않음 . Page Table (16k) Current Image (zImage ~ dtb end) r10 r4 r9wont_overwrite Uncompressed Image
  • 11. 이제 재배치가 필요한 (2) 번과 (4) 번 , 즉 Overwrite 되는 경우라서 wont_overwrite 로 분기하지 않았던 Case 만 남았다 . !!!
  • 12. Page Table (16k) Uncompressed Image malloc stack bss zImage (2 ) 그런데 , (2) 번과 (4) 번이 다른 Case 인가 ?  그렇지 않다 . wont_overwrite Page Table (16k) Uncompressed Image (4 ) 그냥 Current Image 가 조금 위에 있거나 아래에 있는게 다를 뿐이다 . (2) 번은 아래쪽에 있어서 Page Table 및 Uncompressed Image 와 Overwrite 될 가능성이 있는 경우이고 , (4) 는 그보다 좀더 위쪽에 있 어서 Uncompress 시 Current Image 를 Overwrite 할 가능성이 있는 경우이다 .
  • 13. 그렇다면 , 이를 어쩌나 ?  Current Image 의 위치를 재배치하고 다시 수행해야겠지 . 어느 위치로 ?  재배치 후의 restart 가 최소한 Decompressed Image 위에 오도록 Page Table (16k) Uncompressed Image (2 ) restart Page Table (16k) Uncompressed Image restart Page Table (16k) Uncompressed Image Page Table (16k) Uncompressed Image restart (4 ) wont_overwrite
  • 14. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 가 발생하는 경우임 . (2), (4) Page Table (16k) Current Image (zImage ~ dtb end) r10 r4 r9wont_overwrite Uncompressed Image r10 의 위치 변경 (256 byte align) 재배치를 앞두고 이 만큼을 추가로 확보하는 이유는 ? reloc_code_end r10 restart 왜 하필 256 byte align 일까 ?  확인 필 요 restart ~ reloc_code_end
  • 15. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 가 발생하는 경우임 . (2), (4) Page Table (16k) Current Image (zImage ~ dtb end) r4 r9wont_overwrite Uncompressed Image r5 = restart 주소 (32 byte align) reloc_code_end r10 restartr5 restart ~ reloc_code_end
  • 16. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 가 발생하는 경우임 . (2), (4) Page Table (16k) Current Image (zImage ~ dtb end) r4 r9wont_overwrite Uncompressed Image Hyper mode 가 아니면 1f 분기 reloc_code_end r10 restartr5 restart ~ reloc_code_end
  • 17. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 가 발생하는 경우임 . (2), (4) Page Table (16k) Current Image (zImage ~ dtb end) r4 r9 wont_overwrite Uncompressed Image restart ~ dtb end 차이 값을 32 byte align  r9 reloc_code_end r10 restartr5 r6 restart ~ reloc_code_end
  • 18. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 가 발생하는 경우임 . (2), (4) Page Table (16k) Current Image (zImage ~ dtb end) r4 r9 wont_overwrite Uncompressed Image 32 byte align 된 r5 와 r9 을 더하여 r6 위치 32 byte align 위치로 살짝 조정  이건 재배치의 Source 자리임 . reloc_code_end r10 restartr5 r6 restart ~ reloc_code_end
  • 19. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 가 발생하는 경우임 . (2), (4) Page Table (16k) Current Image (zImage ~ dtb end) r4 r9 wont_overwrite Uncompressed Image r9 위치 설정  r9 의 위치는 재배치의 Destination 위치임 . reloc_code_end r10 restartr5 r6 r9 restart ~ dtb end restart ~ reloc_code_end
  • 20. dtb_check_done: add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr and r0, r0, #MODE_MASK cmp r0, #HYP_MODE bne 1f bl __hyp_get_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors 1: #endif sub r9, r6, r5 add r9, r9, #31 bic r9, r9, #31 add r6, r9, r5 add r9, r9, r10 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b Overwrite 가 발생하는 경우임 . (2), (4) Page Table (16k) r4 r9 Uncompressed Image r6 ~ restart 까지를 모두 r9 위치로 decremental 로 복사함 . r10 restartr5 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart
  • 21. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 restartr5 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart r6 = 신규 dtb end 위치 (r9) 과 기존 dtb end (r6) 와의 offset 즉 , r6 는 재배치로 인해 이동한 Offset r6
  • 22. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 restartr5 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart 기존의 sp 위치도 재배치 후의 위치로 변경시켜줌 . r6 sp
  • 23. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 restartr5 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart cache_on 을 skip 했을 경우 r4 의 LSB 가 1 로 설정되어 있다 . cache_on 을 했다고 가정하면 flush 해야 함 . r6 sp
  • 24. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 restartr5 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart r0 값을 현재의 restart label 에서 재배치한 위치의 restart 값 으로 설정 r6 sp r0
  • 25. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart pc 값을 재배치한 restart 로 설정하여 restart 부터 다시 수행 . 다시 수행하게 되면 그 때부터는 Overwrite 가 발생하지 않는 (3) 번 Case 로 수행하게 되어 중간에 wont_overwrite 로 분기하게 된다 . r6 sp r0pc
  • 26. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart 재배치를 거쳤건 안거쳤건 restart 에서 분기해온 상태에서 r0 = delta offset (LC0 label 과 LC0 word 값 차이 ) r5 = dtb size r6 sp r0pc
  • 27. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart (1) r0 = 0 | r5 = 0 -> 0 -> not reloc (2) r0 = 1 | r5 = 0 -> 1 -> reloc (3) r0 = 0 | r5 = 1 -> 1 -> reloc (4) r0 = 1 | r5 = 1 -> 1 -> reloc (1)의 경우는 확실히 재배치가 발생하지 않은 경우이다 . 재배치가 발생해서 restart 쪽을 다시 거쳤다면 delta offset 이 0 일 수가 없다 . r6 sp r0pc
  • 28. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart GOT start (r11) 와 GOT end (r12) 의 위치도 재배치를 고려하여 delta offset (r0) 만큼 이동시켜준다 . r6 sp r0pc
  • 29. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart BSS start (r2) 와 BSS end (r3) 의 위치도 재배치를 고려하여 delta offset (r0) 만큼 이동시켜준다 . r6 sp r0pc
  • 30. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart GOT 의 첫번째 entry 값을 가져와서 delta offset 을 더해준다 . r6 sp r0pc
  • 31. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart Delta offset 조정된 GOT Entry 값이 bss start ~ bss end 사이의 값이 면 r6 sp r0pc
  • 32. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart Entry 값에 dtb size 값을 더해준다 . r6 sp r0pc
  • 33. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart 다음 GOT Entry 에 대해 동일한 작업을 하기 위해 1b 로 이동한다 . GOT end 를 만나면 Loop 를 끝낸다 . 결국 이는 GOT 의 모든 Entry 값들을 delta offset 과 dtb size 를 고 려하여 조정하는 것이다 . ( 재배치가 발생했을 수도 있으므로 ) r6 sp r0pc 그런데 , 왜 GOT Entry 의 값이 bss start ~ end 내에 포함되는지를 검사하는 것일까 ?
  • 34. sub r6, r9, r6 #ifndef CONFIG_ZBOOT_ROM add sp, sp, r6 #endif tst r4, #1 bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 wont_overwrite: orrs r1, r0, r5 beq not_relocated add r11, r11, r0 add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM add r2, r2, r0 add r3, r3, r0 1: ldr r1, [r11, #0] add r1, r1, r0 cmp r1, r2 cmphs r3, r1 addhi r1, r1, r5 str r1, [r11], #4 cmp r11, r12 blo 1b add r2, r2, r5 add r3, r3, r5 #else … #endif Page Table (16k) r4 r9 Uncompressed Image r10 r6 restart ~ dtb end restart ~ reloc_code_end Current Image (zImage ~ dtb end) restart bss start 와 bss end 의 값도 dtb size 를 더한 값으로 조정해준다 . ( 위쪽에서 delta offset 값은 이미 더해주었다 .) r6 sp r0pc
  • 35. stack bss wont_overwrite 을 마친 후의 memory map 및 register 상태  재배치가 완료되었을 수도 있고 재배치가 불필요했을 수도 있다 . Page Table (16k) Uncompressed Image r10 r6 : 재배치했다면 이전 dtb end 를 가리키고 , 재배치 안했다 면 현재의 dtb _end 를 가리 킴 . r4 r9 r0 : delta offset r1 : temp dtb bss start 재배치한 대상 r7 : architecture ID r8 : dtb 가 있다면 dtb start 를 가리키고 , 없다면 atags pointer 임 . restart r5 : dtb size LC0 GOT start GOT end bss end r2 r3 GOT 의 각 Entry 는 bss 영 역을 가리킴 sp r11 r12 zImage