blob: e60d30973ff798ac7d837da194a8aa9e2eee2ef7 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
#include <asm.h>
#include <zircon/boot/image.h>
// This file lays out the final kernel image seen by the boot loader.
// It concatenates:
// 1. the boot loader headers
// 2. the actual kernel image (converted from the kernel ELF file)
// 3. the fixup code to relocate the kernel image
// The headers must tell the boot loader to load the whole combined image,
// and leave enough space in memory after it for the bss.
// The label arithmetic to define the header fields only works because this
// whole file is all in the same section (.text). Because it's all just
// one big section and there are no relocs to absolute locations within
// this section, it really doesn't matter what memory layout the linker
// thinks it's doing, but nonetheless image.ld produces an ELF segment
// layout faithful to the physical memory picture (except that it's
// actually position-independent). The addresses in the ELF headers of the
// final image.elf file are completely ignored because boot loaders don't
// actually use that file. It only exists to have the contents extracted
// with objcopy -O binary.
// ZBI file header (zbi_header_t)
ZBI_CONTAINER_HEADER(_zbi_file_header, boot_load_end - _zbi_kernel_header)
// ZBI kernel header (zbi_header_t)
.int boot_load_end - _zbi_kernel_payload
.int 0
.int 0
.int 0
// ZBI_TYPE_KERNEL payload (zbi_kernel_t)
// The boot-shim code expects this to be an offset from the beginning
// of the load image, whatever the kernel's virtual address.
.quad IMAGE_ELF_ENTRY - _zbi_file_header
.quad IMAGE_MEMORY_END - boot_load_end
// Include the kernel image itself, skipping the padding left for the headers.
#include ""
// Immediately after the kernel image comes the fixup code.
// The start.S code sees this address as __data_end.
// This code must be purely position-independent and have no relocs.
// This is called with the desired runtime address of __code_start in x0.
// This is the constant address the kernel was linked for.
movlit x9, KERNEL_BASE
sub x0, x0, x9
// The generated invokes this macro for each run of fixups.
.macro fixup addr, n, stride
adr_global x9, FIXUP_LOCATION(\addr)
.if \n >= 4 && \stride == 8
// Do a loop handling adjacent pairs.
mov x16, #(\n / 2)
0: fixup_pair
subs x16, x16, #1 0b
.if \n % 2
// Handle the odd remainder after those pairs.
fixup_single 8
.elseif \n >= 2 && \stride == 8
// Do a single adjacent pair.
.if \n == 3
// Do the third adjacent one.
fixup_single 8
.elseif \n > 1
// Do a strided loop.
mov x16, #\n
0: fixup_single \stride
subs x16, x16, #1 0b
// Do a singleton.
fixup_single 8
.macro fixup_pair
ldp x10, x11, [x9]
add x10, x10, x0
add x11, x11, x0
stp x10, x11, [x9], #16
.macro fixup_single stride
ldr x10, [x9]
add x10, x10, x0
str x10, [x9], #\stride
#include ""
.balign 8
// We don't use any scratch memory after the kernel's bss.