35
Linux Kernel 코코코코 (Ver 3.12.20) arch/arm/boot/compressed/head.S (dtb_check_done, wont_overwrite)

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

Embed Size (px)

DESCRIPTION

arch/arm/boot/compressed/head.S 의 dtb_check_done, wont_overwirte label 부분 분석

Citation preview

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

Linux Kernel 코드분석(Ver 3.12.20)

arch/arm/boot/compressed/head.S(dtb_check_done, wont_overwrite)

Page 2: 커널코드분석 20140628(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)

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

!!! (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 들의 역할이다 .

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

restart ~ wont_overwrite 부분의 Code 는 앞에서 살펴보았던 4 가지 경우 각각을 가정하면서 분석해야 한다 !!!

Page 5: 커널코드분석 20140628(head.s dtb check_done, 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

Current Image 가 Page Table 및 Uncompressed Image 와 Overwrite 되는지 검사 .

Page Table (16k)

UncompressedImage

Current Image(zImage ~ dtb end)

r10r4

r9

Page 6: 커널코드분석 20140628(head.s dtb check_done, 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 되지 않으면 wont_overwrite 로 분기 (1) 번 경우

Page Table (16k)

UncompressedImage

Current Image(zImage ~ dtb end)

r10

r4

r9

Page 7: 커널코드분석 20140628(head.s dtb check_done, 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

Current Image 가 Page Table 및 Uncompressed Image 와 Overwrite 됨 .r10 Pointer 변경 .

Page Table (16k)

UncompressedImage

Current Image(zImage ~ dtb end)

r10

r4

r9

wont_overwrite

Page 8: 커널코드분석 20140628(head.s dtb check_done, 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

Page 9: 커널코드분석 20140628(head.s dtb check_done, 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

wont_overwrite 이 Uncompressed Image End 위에 있는지 검사 (3) 번 경우인지 (4) 번 경우인지 검사

Page Table (16k)

UncompressedImage

Current Image(zImage ~ dtb end)

r10

r4

r9wont_overwrite

Page 10: 커널코드분석 20140628(head.s dtb check_done, 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

(3) 번 경우 분기 Decompressed Image End 가 Current Image 의 wont_overwrite 를 Overwrite 하지 않음 .

Page Table (16k)

Current Image(zImage ~ dtb end)

r10

r4

r9wont_overwrite

UncompressedImage

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

이제 재배치가 필요한 (2) 번과 (4) 번 , 즉 Overwrite 되는 경우라서 wont_overwrite 로 분기하지 않았던 Case 만 남았다 .

!!!

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

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 할 가능성이 있는 경우이다 .

Page 13: 커널코드분석 20140628(head.s dtb check_done, wont_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

Page 14: 커널코드분석 20140628(head.s dtb check_done, 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

Page 15: 커널코드분석 20140628(head.s dtb check_done, 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)

r4

r9wont_overwriteUncompressed

Image

r5 = restart 주소 (32 byte align)

reloc_code_end

r10

restartr5

restart ~ reloc_code_end

Page 16: 커널코드분석 20140628(head.s dtb check_done, 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)

r4

r9wont_overwriteUncompressed

Image

Hyper mode 가 아니면 1f 분기

reloc_code_end

r10

restartr5

restart ~ reloc_code_end

Page 17: 커널코드분석 20140628(head.s dtb check_done, 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)

r4

r9

wont_overwriteUncompressed

Image

restart ~ dtb end 차이 값을 32 byte align r9

reloc_code_end

r10

restartr5

r6

restart ~ reloc_code_end

Page 18: 커널코드분석 20140628(head.s dtb check_done, 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)

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

Page 19: 커널코드분석 20140628(head.s dtb check_done, 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)

r4

r9

wont_overwriteUncompressed

Image

r9 위치 설정 r9 의 위치는 재배치의 Destination 위치임 .

reloc_code_end

r10

restartr5

r6

r9

restart ~ dtb end

restart ~ reloc_code_end

Page 20: 커널코드분석 20140628(head.s dtb check_done, 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)

r4

r9

UncompressedImage

r6 ~ restart 까지를 모두 r9 위치로 decremental 로 복사함 .

r10

restartr5

r6

restart ~ dtb end

restart ~ reloc_code_end

Current Image(zImage ~ dtb end)

restart

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 내에 포함되는지를 검사하는 것일까 ?

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

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

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

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