Upload
dongpyo-lee
View
259
Download
0
Embed Size (px)
DESCRIPTION
arch/arm/boot/compressed/head.S 의 dtb_check_done, wont_overwirte label 부분 분석
Citation preview
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
mallocstackbss
zImage
!!! Overwrite 과 Wont_Overwrite 여부를 판단하기 위한 4 가지 경우의 수 (2), (4) 번은 Overwrite 가 발생하므로 이미지 재배치 필요 .
Page Table (16k)
r10
Uncompressed
Image
r4Page Table
(16k)
Uncompressed
Image
r4
mallocstackbss
zImage
r10
Page Table (16k)
r10
Uncompressed
Image
r4
r9
wont_overwrite
r4 – 16k >= r10OK
wont_overwrite 분기
r4 – 16k < r10Overwrite
Relocation 필요
r4 + r9 <= r10OK
wont_overwrite 분기
r10 wont_overwrite
Page Table (16k)
Uncompressed
Image
r4
r9
r4 + r9 > r10Overwrite
Relocation 필요
(1)
(2)
(3)
(4)
!!! (2) 번과 (4) 번의 경우 Overwrite 을 회피하기 위해 이미지의 재배치 목적지를
어디로 해야할까 ? 개념적으로 보면 아래와 같다 .
Page Table (16k)
Uncompressed
Image
mallocstackbss
zImage
r10
(2)
mallocstackbss
zImage
원래의 이미지를 UncompressedImage 의 End 위로 배치해야 한다 .
r10 wont_overwrite
Page Table (16k)
Uncompressed
Image
r4
(4)
r4
mallocstackbss
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_vectors1:#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)
UncompressedImage
Current Image(zImage ~ dtb end)
r10r4
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_vectors1:#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)
UncompressedImage
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_vectors1:#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)
UncompressedImage
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_vectors1:#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)
UncompressedImage
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_vectors1:#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)
UncompressedImage
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_vectors1:#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
UncompressedImage
이제 재배치가 필요한 (2) 번과 (4) 번 , 즉 Overwrite 되는 경우라서 wont_overwrite 로 분기하지 않았던 Case 만 남았다 .
!!!
Page Table (16k)
Uncompressed
Image
mallocstackbss
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_vectors1:#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_overwriteUncompressed
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_vectors1:#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_overwriteUncompressed
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_vectors1:#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_overwriteUncompressed
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_vectors1:#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_overwriteUncompressed
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_vectors1:#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_overwriteUncompressed
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_vectors1:#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_overwriteUncompressed
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_vectors1:#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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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, r01: 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
UncompressedImage
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)
UncompressedImage
r10 r6 : 재배치했다면 이전 dtb end 를 가리키고 , 재배치 안했다면 현재의 dtb _end 를 가리킴 .
r4
r9
r0 : delta offsetr1 : temp
dtb
bss start
재배치한 대상
r7 : architecture ID
r8 : dtb 가 있다면 dtb start 를 가리키고 , 없다면 atags pointer 임 .
restart
r5 : dtb sizeLC0
GOT start
GOT end
bss end
r2
r3
GOT 의 각 Entry 는 bss 영역을 가리킴
sp
r11
r12
zImage