Skip to content

Commit

Permalink
elfloader: port fixup_image_base to C
Browse files Browse the repository at this point in the history
Porting from assembly to a higher level language makes this function
more portable.

Signed-off-by: Kent McLeod <[email protected]>
  • Loading branch information
kent-mcleod committed Feb 1, 2022
1 parent 1829e9c commit f3b5452
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 66 deletions.
68 changes: 2 additions & 66 deletions elfloader-tool/src/arch-arm/64/crt0.S
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ BEGIN_FUNC(_start)
mov x2, x0
/* restore original arguments for next step */
ldp x0, x1, [sp, #-16]!
/* fixup_image_base returns 1 if no need to move */
cmp x2, #1
/* fixup_image_base returns 0 if no need to move */
cmp x2, #0
beq 1f
/* otherwise, jump to the start of the new elfloader */

Expand All @@ -41,70 +41,6 @@ BEGIN_FUNC(_start)
b main
END_FUNC(_start)

#ifdef CONFIG_IMAGE_BINARY
BEGIN_FUNC(fixup_image_base)
stp x29, x30, [sp, #-16]!
mov x29, sp
ldr x0, =IMAGE_START_ADDR
adr x1, _start
cmp x0, x1
beq image_ok

adrp x2, _end
add x2, x2, #:lo12:_end
sub x2, x2, x1

/* sanity check: don't want to overwrite ourselves! we assume
* everything between _start and _archive_start is important
* (i.e. code that might be run while relocating)
* but allow overlap for things after _archive_start.
*/
adrp x3, _archive_start
add x3, x3, #:lo12:_archive_start

add x4, x0, x2 /* Dest end */

/* check: if (end < archive_start && end >= _start) { abort } */
cmp x4, x3
bge 1f

cmp x4, x1
blt 1f

b cant_reloc

1:
/* check: if (dest < archive_start && dest >= _start) { abort } */
cmp x0, x3
bge 2f

cmp x0, x1
blt 2f

cant_reloc:
b abort

2:
/* x0 = desired image base */
/* x1 = current image space */
/* x2 = image size */
bl memmove
/* x0 = dest, save it to a callee-saved register while we invalidate icache */
mov x19, x0
bl flush_dcache
bl invalidate_icache
mov x0, x19
b 1f

image_ok:
/* already in the right place, just keep booting */
mov x0, #1
1:
ldp x29, x30, [sp], #16
ret
END_FUNC(fixup_image_base)
#endif

/* Move the elf loader out of the kernel's way */
BEGIN_FUNC(finish_relocation)
/*
Expand Down
43 changes: 43 additions & 0 deletions elfloader-tool/src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@
#include <platform_info.h> // this provides memory_region
#endif

#include <image_start_addr.h>
#include <abort.h>

extern char _bss[];
extern char _bss_end[];
extern char _start[];
extern char _end[];

/*
* Clear the BSS segment
Expand Down Expand Up @@ -618,3 +623,41 @@ WEAK void platform_init(void)
{
/* nothing by default */
}

#ifdef CONFIG_ARCH_ARM
extern void flush_dcache(void);
extern void invalidate_icache(void);
#endif

/*
* Moves the elfloader to its expected start address in memory.
* This is for when the elfloader needs to be in a specific location
* to ensure that it doesn't occupy memory that it needs to load the
* kernel and user applications into.
*/
char * fixup_image_base(void) {
char *load_base = _start;
char *target_base = (char *) IMAGE_START_ADDR;
if (load_base == target_base) {
/* already in the right place, just keep booting */
return (char *)0;
}

/* Check that the current image location doesn't overlap with the
* destination location. */
size_t image_size = _end - _start;
char *target_end = target_base + image_size;
if ((target_base >= _start && target_base < _end) ||
(target_end >= _start && target_end < _end)) {
abort();
}

/* Perform the move and clean/invalidate caches if necessary */
char *ret = memmove(target_base, load_base, image_size);
#ifdef CONFIG_ARCH_ARM
flush_dcache();
invalidate_icache();
#endif
return ret;

}

0 comments on commit f3b5452

Please sign in to comment.