arch: aarch64: Fix up the Linux kernel image header

The current header implementation is incomplete: the text_offset and
image_size slots are overlaid with internal relocation metadata
(_rel_stack_base / _rel_stack_size), and the flags field is zero,
which makes some bootloaders unhappy. Fill up the the missing props and
while at it, stub out the image header into a header file to avoid duplicating.

image_size is computed in the linker script as _stack_end - _start
so the early stack page is included in the runtime memory footprint
advertised to the previous-stage bootloader.

Patch inspired by work from @Trijal08 and cleaned up to not account for
ELF PiE.
This commit is contained in:
Ivaylo Ivanov
2026-05-27 17:39:59 +03:00
committed by Igor Bełwon
parent 673a070d36
commit 56f8caa1fa
4 changed files with 64 additions and 17 deletions

View File

@@ -85,4 +85,7 @@ SECTIONS
#ifdef CONFIG_POSITION_INDEPENDENT
_reloc_size = _reloc_end - _reloc_start;
#endif
#ifdef CONFIG_LINUX_KRNL_HEADER_IMG
_kernel_size = _stack_end - _start;
#endif
}

View File

@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Derived info from arch/arm64/kernel/head.S in the Linux kernel.
*/
#ifndef _AARCH64_LINUX_KERNEL_IMAGE_HEADER_H
#define _AARCH64_LINUX_KERNEL_IMAGE_HEADER_H
/*
* Image header flags (Documentation/arm64/booting.rst):
* Bit 0 Kernel endianness.
1 if BE, 0 if LE.
* Bit 1-2 Kernel Page size.
0 - Unspecified.
1 - 4K
2 - 16K
3 - 64K
* Bit 3 Kernel physical placement
0
2MB aligned base should be as close as possible
to the base of DRAM, since memory below it is not
accessible via the linear mapping
1
2MB aligned base such that all image_size bytes
counted from the start of the image are within
the 48-bit addressable range of physical memory
*/
#define LINUX_IMAGE_FLAGS ((1 << 1) | (1 << 3))
.macro linux_image_header entry
/*
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
*/
b \entry
.long 0 /* reserved */
.quad 0 /* text_offset */
.quad _kernel_size /* image_size, see linker script */
.quad LINUX_IMAGE_FLAGS /* flags */
.quad 0 /* reserved */
.quad 0 /* reserved */
.quad 0 /* reserved */
.ascii "ARM\x64" /* magic number */
.long 0 /* reserved */
.endm
#endif /* _AARCH64_LINUX_KERNEL_IMAGE_HEADER_H */

View File

@@ -4,26 +4,27 @@
*/
#include "asmdefs.h"
#ifdef CONFIG_LINUX_KRNL_HEADER_IMG
#include "linux-kernel-image-header.h"
#endif
.extern _reloc_size
.extern _start
ENTRY_ALIAS(_head)
#ifdef CONFIG_LINUX_KRNL_HEADER_IMG
linux_image_header _reloc_entry
#else
adr x1, _relocated_uni
b _reloc_entry
#endif
ENTRY_ALIAS(_rel_stack_base)
.quad _start
ENTRY_ALIAS(_rel_stack_size)
.quad _reloc_size
#ifdef CONFIG_LINUX_KRNL_HEADER_IMG
.quad 0
.quad 0
.quad 0
.quad 0
.ascii "ARM\x64"
.long 0
#endif
ENTRY_ALIAS( _reloc_entry)
adr x4, _start
ldr x5, _rel_stack_base

View File

@@ -4,23 +4,21 @@
*/
#include "asmdefs.h"
.section .text
#ifdef CONFIG_LINUX_KRNL_HEADER_IMG
#include "linux-kernel-image-header.h"
#endif
.section .text
#if defined(CONFIG_LINUX_KRNL_HEADER_IMG) && !defined(CONFIG_POSITION_INDEPENDENT)
_head:
ldr x1, =_start
b _start
linux_image_header _start
_stack_base:
.quad 0x0
_stack_size:
.quad _stack_end
.quad 0
.quad 0
.quad 0
.quad 0
.ascii "ARM\x64"
.long 0
.align 4
#endif