ARMv8: add optional Linux kernel image header

Allow placing a Linux kernel image header at the start of the U-Boot
binary. This is useful since the image header reports the amount of memory
(BSS and similar) that U-Boot needs to use, but that isn't part of the
binary size. This can be used by the code that loads U-Boot into memory to
determine where to load U-Boot, based on other users of memory.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
This commit is contained in:
Stephen Warren 2018-01-03 14:31:51 -07:00 committed by Tom Warren
parent f097532d27
commit 8163faf952
5 changed files with 159 additions and 1 deletions

View file

@ -32,6 +32,23 @@ config SYS_INIT_SP_BSS_OFFSET
calculate the stack pointer. This offset should be large enough so
that the early malloc region, global data (gd), and early stack usage
do not overlap any appended DTB.
config LINUX_KERNEL_IMAGE_HEADER
bool
help
Place a Linux kernel image header at the start of the U-Boot binary.
The format of the header is described in the Linux kernel source at
Documentation/arm64/booting.txt. This feature is useful since the
image header reports the amount of memory (BSS and similar) that
U-Boot needs to use, but which isn't part of the binary.
if LINUX_KERNEL_IMAGE_HEADER
config LNX_KRNL_IMG_TEXT_OFFSET_BASE
hex
help
The value subtracted from CONFIG_SYS_TEXT_BASE to calculate the
TEXT_OFFSET value written in to the Linux kernel image header.
endif
endif
config STATIC_RELA

View file

@ -0,0 +1,86 @@
/*
* (C) Copyright 2017 NVIDIA Corporation <www.nvidia.com>
*
* Derived from Linux kernel v4.14 files:
*
* arch/arm64/include/asm/assembler.h:
* Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
* Copyright (C) 1996-2000 Russell King
* Copyright (C) 2012 ARM Ltd.
*
* arch/arm64/kernel/head.S:
* Based on arch/arm/kernel/head.S
* Copyright (C) 1994-2002 Russell King
* Copyright (C) 2003-2012 ARM Ltd.
* Authors: Catalin Marinas <catalin.marinas@arm.com>
* Will Deacon <will.deacon@arm.com>
*
* arch/arm64/kernel/image.h:
* Copyright (C) 2014 ARM Ltd.
*
* SPDX-License-Identifier: GPL-2.0
*/
/*
* There aren't any ELF relocations we can use to endian-swap values known only
* at link time (e.g. the subtraction of two symbol addresses), so we must get
* the linker to endian-swap certain values before emitting them.
*
* Note that, in order for this to work when building the ELF64 PIE executable
* (for KASLR), these values should not be referenced via R_AARCH64_ABS64
* relocations, since these are fixed up at runtime rather than at build time
* when PIE is in effect. So we need to split them up in 32-bit high and low
* words.
*/
#ifdef CONFIG_CPU_BIG_ENDIAN
#define DATA_LE32(data) \
((((data) & 0x000000ff) << 24) | \
(((data) & 0x0000ff00) << 8) | \
(((data) & 0x00ff0000) >> 8) | \
(((data) & 0xff000000) >> 24))
#else
#define DATA_LE32(data) ((data) & 0xffffffff)
#endif
#define DEFINE_IMAGE_LE64(sym, data) \
sym##_lo32 = DATA_LE32((data) & 0xffffffff); \
sym##_hi32 = DATA_LE32((data) >> 32)
#define __MAX(a, b) (((a) > (b)) ? (a) : (b))
#define __CODE_DATA_SIZE (__bss_start - _start)
#define __BSS_SIZE (__bss_end - __bss_start)
#ifdef CONFIG_SYS_INIT_SP_BSS_OFFSET
#define __MAX_EXTRA_RAM_USAGE __MAX(__BSS_SIZE, CONFIG_SYS_INIT_SP_BSS_OFFSET)
#else
#define __MAX_EXTRA_RAM_USAGE __BSS_SIZE
#endif
#define __MEM_USAGE (__CODE_DATA_SIZE + __MAX_EXTRA_RAM_USAGE)
#ifdef CONFIG_CPU_BIG_ENDIAN
#define __HEAD_FLAG_BE 1
#else
#define __HEAD_FLAG_BE 0
#endif
#define __HEAD_FLAG_PAGE_SIZE 1 /* 4K hard-coded */
#define __HEAD_FLAG_PHYS_BASE 1
#define __HEAD_FLAGS ((__HEAD_FLAG_BE << 0) | \
(__HEAD_FLAG_PAGE_SIZE << 1) | \
(__HEAD_FLAG_PHYS_BASE << 3))
#define TEXT_OFFSET (CONFIG_SYS_TEXT_BASE - \
CONFIG_LNX_KRNL_IMG_TEXT_OFFSET_BASE)
/*
* These will output as part of the Image header, which should be little-endian
* regardless of the endianness of the kernel. While constant values could be
* endian swapped in head.S, all are done here for consistency.
*/
#define HEAD_SYMBOLS \
DEFINE_IMAGE_LE64(_kernel_size_le, __MEM_USAGE); \
DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \
DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS);
HEAD_SYMBOLS

View file

@ -19,7 +19,9 @@
.globl _start
_start:
#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
#if defined(LINUX_KERNEL_IMAGE_HEADER)
#include <asm/boot0-linux-kernel-header.h>
#elif defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
/*
* Various SoCs need something special and SoC-specific up front in
* order to boot, allow them to set that in their boot0.h file and then

View file

@ -159,4 +159,8 @@ SECTIONS
/DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) }
#ifdef CONFIG_LINUX_KERNEL_IMAGE_HEADER
#include "linux-kernel-image-header-vars.h"
#endif
}

View file

@ -0,0 +1,49 @@
/*
* (C) Copyright 2017 NVIDIA Corporation <www.nvidia.com>
*
* Derived from Linux kernel v4.14 files:
*
* arch/arm64/include/asm/assembler.h:
* Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
* Copyright (C) 1996-2000 Russell King
* Copyright (C) 2012 ARM Ltd.
*
* arch/arm64/kernel/head.S:
* Based on arch/arm/kernel/head.S
* Copyright (C) 1994-2002 Russell King
* Copyright (C) 2003-2012 ARM Ltd.
* Authors: Catalin Marinas <catalin.marinas@arm.com>
* Will Deacon <will.deacon@arm.com>
*
* arch/arm64/kernel/image.h:
* Copyright (C) 2014 ARM Ltd.
*
* SPDX-License-Identifier: GPL-2.0
*/
/*
* Emit a 64-bit absolute little endian symbol reference in a way that
* ensures that it will be resolved at build time, even when building a
* PIE binary. This requires cooperation from the linker script, which
* must emit the lo32/hi32 halves individually.
*/
.macro le64sym, sym
.long \sym\()_lo32
.long \sym\()_hi32
.endm
.globl _start
_start:
/*
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
*/
b reset /* branch to kernel start, magic */
.long 0 /* reserved */
le64sym _kernel_offset_le /* Image load offset from start of RAM, little-endian */
le64sym _kernel_size_le /* Effective size of kernel image, little-endian */
le64sym _kernel_flags_le /* Informative flags, little-endian */
.quad 0 /* reserved */
.quad 0 /* reserved */
.quad 0 /* reserved */
.ascii "ARM\x64" /* Magic number */
.long 0 /* reserved */