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:
		
							parent
							
								
									f097532d27
								
							
						
					
					
						commit
						8163faf952
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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 */ | ||||
		Loading…
	
		Reference in New Issue