/* 247 * Check to see if we will overwrite ourselves. 248 * r4 = final kernel address 249 * r5 = start of this image 250 * r2 = end of malloc space (and therefore this image) 251 * We basically want: 252 * r4 >= r2 -> OK 253 * r4 + image length <= r5 -> OK 254 */
We have R4=0x80008000, R5=0x80008000, R2=0x8016E668, R6=0x00555860(imagelen), R7=0x060A
We compare R4 with R2 to see if we ever overwrite. Since we do, we need to adjust it
R0= R4+R6=0x8055D860
cmp r0, r5 and see if we dont overwrite.
In our case, we still fail, so need more adjustment.
We will simply change the decompressing addr. to one above malloc space(R2=0x8016E668)
mov r5, r2 @ decompress after malloc space 264 mov r0, r5 265 mov r3, r7 266 bl decompress_kernel
decompress_kernel is a function() defined in linux/arch/arm/boot/compressed/misc.c
This function decompresses the kernel. Note that if we have putc and getc defined, we
see a print of "Uncompressing Linux..." when we start to decompress kernel.
In our case, we have sucn a definition done in
\linux-2.6\arch\arm\mach-puppybeagle\include\mach\uncompress.h file
NOT SURE OF BELOW EXPLANATION!
ALL WE KNOW IS WE SAVE ALL ARGS PASSED TO FUNCTION PRINT UNCOMPRESS....JUMP DO_DECOMPRESS
@
Here, he starts reading certain offset entries found at address 0x80008A60, 0x80008A64, 0x80008A68,
and 0x80008A68, adds them up to the base address 0x8015D618(GOT START) and save them in the BSS section.
These offset entries are found to be ATAGs passed by the Bootloader.
So ATAGS @0x80008A60
GOT START @ 0x8015D618
BSS Entry value = value @ [GOTSTART+ ATAG]
Decompress function is a standard C function that compresses the zImage and returns back.We have decompressed from 0x8016E668(mallocspace end) till 0x8043B4E8 (Image size of 0x002CCE80)
Now copy relocation code:
reloc_start code addr: R2=@0x80008380
LC1 label: R3=@0x80008814
End of Decompxd. kernel: R1@0x8043B4E8
Now copy data from R2(0x80008380) and store it @R1(0x8043B4E8), ie after decompressed image
We do this copying until R2 == R3 (1172 Bytes)
Also, relocate Stack. SP now points to R13=0x8043BA18
Do a cache_clean_flush
-> Calls call_cache_fn
-> Searches for appropriate proctype flush call (In our case, its __armv7_mmu_cache_flush)
->Jumps to Hierarchial
loop along loop3 3-4 times
loop along loop2 2-3 times
loop along loop1 2 times
finally pop up, invalidate caches and return to __armv7_mmu_cache_off
here again, invalidate TLB, BTC, DSB, ISB
We at the end returned to reloc_start:
Now call relocation code:
ARM( add pc, r5, r0 ) @ call relocation code 294 THUMB( add r12, r5, r0 ) 295 THUMB( mov pc, r12 ) @ call relocation code 296
/* 537 * All code following this line is relocatable. It is relocated by 538 * the above code to the end of the decompressed kernel image and 539 * executed there. During this time, we have no stacks. 540 * 541 * r0 = decompressed kernel length 542 * r1-r3 = unused 543 * r4 = kernel execution address 544 * r5 = decompressed kernel start 545 * r7 = architecture ID 546 * r8 = atags pointer 547 * r9-r12,r14 = corrupted 548 */
Fig: State of the code with only first line of the relocation code is executed:
From fig, we see that R9 holds the source_end addr. We decrement this addr. by 128 bytes to skip copying stack. So, R9=@0x8043B468. We see that R4 holds the expected kernel execution address.(0x80008000)
R1 = R4
R5=@0x8016E668 holds the start addr of the source.
We start copying this image code from R5 and store it at addr pointed to by R1
After relocating kernel image, relocate stack as ell. New stack is now R13=@0x802D4EE0
With everything relocated, do a cache flush and turn cache off.
call_kernel: bl cache_clean_flush 567 bl cache_off
Finally call kernel placed at exact 0x80008000 location!
mov r0, #0 @ must be zero 569 mov r1, r7 @ restore architecture number 570 mov r2, r8 @ restore atags pointer 571 mov pc, r4 @ call kernel
Note R4 value, at which control flow jumps to!
After this, we enter start label inside actual kernel code for the first time!
/arch/arm/kernel/head.S
ENTRY(stext)
No comments:
Post a Comment