Linux Audio

Check our new training course

Loading...
v6.8
 1// SPDX-License-Identifier: GPL-2.0
 2/*
 3 * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
 4 *
 5 * This file implements the EFI boot stub for the arm64 kernel.
 6 * Adapted from ARM version by Mark Salter <msalter@redhat.com>
 
 
 
 
 
 7 */
 8
 9
10#include <linux/efi.h>
11#include <asm/efi.h>
12#include <asm/memory.h>
13#include <asm/sections.h>
 
14
15#include "efistub.h"
16
17efi_status_t handle_kernel_image(unsigned long *image_addr,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18				 unsigned long *image_size,
19				 unsigned long *reserve_addr,
20				 unsigned long *reserve_size,
21				 efi_loaded_image_t *image,
22				 efi_handle_t image_handle)
23{
24	efi_status_t status;
25	unsigned long kernel_size, kernel_codesize, kernel_memsize;
26
27	if (image->image_base != _text) {
28		efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
29		image->image_base = _text;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30	}
31
32	if (!IS_ALIGNED((u64)_text, SEGMENT_ALIGN))
33		efi_err("FIRMWARE BUG: kernel image not aligned on %dk boundary\n",
34			SEGMENT_ALIGN >> 10);
 
 
 
 
 
35
36	kernel_size = _edata - _text;
37	kernel_codesize = __inittext_end - _text;
38	kernel_memsize = kernel_size + (_end - _edata);
39	*reserve_size = kernel_memsize;
40	*image_addr = (unsigned long)_text;
41
42	status = efi_kaslr_relocate_kernel(image_addr,
43					   reserve_addr, reserve_size,
44					   kernel_size, kernel_codesize,
45					   kernel_memsize,
46					   efi_kaslr_get_phys_seed(image_handle));
47	if (status != EFI_SUCCESS)
48		return status;
49
50	return EFI_SUCCESS;
51}
52
53asmlinkage void primary_entry(void);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
55unsigned long primary_entry_offset(void)
56{
57	/*
58	 * When built as part of the kernel, the EFI stub cannot branch to the
59	 * kernel proper via the image header, as the PE/COFF header is
60	 * strictly not part of the in-memory presentation of the image, only
61	 * of the file representation. So instead, we need to jump to the
62	 * actual entrypoint in the .text region of the image.
63	 */
64	return (char *)primary_entry - _text;
65}
 
 
66
67void efi_icache_sync(unsigned long start, unsigned long end)
68{
69	caches_clean_inval_pou(start, end);
70}
v4.6
 
  1/*
  2 * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
  3 *
  4 * This file implements the EFI boot stub for the arm64 kernel.
  5 * Adapted from ARM version by Mark Salter <msalter@redhat.com>
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License version 2 as
  9 * published by the Free Software Foundation.
 10 *
 11 */
 
 
 12#include <linux/efi.h>
 13#include <asm/efi.h>
 
 14#include <asm/sections.h>
 15#include <asm/sysreg.h>
 16
 17#include "efistub.h"
 18
 19extern bool __nokaslr;
 20
 21efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 22{
 23	u64 tg;
 24
 25	/* UEFI mandates support for 4 KB granularity, no need to check */
 26	if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
 27		return EFI_SUCCESS;
 28
 29	tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
 30	if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
 31		if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
 32			pr_efi_err(sys_table_arg, "This 64 KB granular kernel is not supported by your CPU\n");
 33		else
 34			pr_efi_err(sys_table_arg, "This 16 KB granular kernel is not supported by your CPU\n");
 35		return EFI_UNSUPPORTED;
 36	}
 37	return EFI_SUCCESS;
 38}
 39
 40efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
 41				 unsigned long *image_addr,
 42				 unsigned long *image_size,
 43				 unsigned long *reserve_addr,
 44				 unsigned long *reserve_size,
 45				 unsigned long dram_base,
 46				 efi_loaded_image_t *image)
 47{
 48	efi_status_t status;
 49	unsigned long kernel_size, kernel_memsize = 0;
 50	void *old_image_addr = (void *)*image_addr;
 51	unsigned long preferred_offset;
 52	u64 phys_seed = 0;
 53
 54	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
 55		if (!__nokaslr) {
 56			status = efi_get_random_bytes(sys_table_arg,
 57						      sizeof(phys_seed),
 58						      (u8 *)&phys_seed);
 59			if (status == EFI_NOT_FOUND) {
 60				pr_efi(sys_table_arg, "EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
 61			} else if (status != EFI_SUCCESS) {
 62				pr_efi_err(sys_table_arg, "efi_get_random_bytes() failed\n");
 63				return status;
 64			}
 65		} else {
 66			pr_efi(sys_table_arg, "KASLR disabled on kernel command line\n");
 67		}
 68	}
 69
 70	/*
 71	 * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
 72	 * a 2 MB aligned base, which itself may be lower than dram_base, as
 73	 * long as the resulting offset equals or exceeds it.
 74	 */
 75	preferred_offset = round_down(dram_base, MIN_KIMG_ALIGN) + TEXT_OFFSET;
 76	if (preferred_offset < dram_base)
 77		preferred_offset += MIN_KIMG_ALIGN;
 78
 79	kernel_size = _edata - _text;
 
 80	kernel_memsize = kernel_size + (_end - _edata);
 
 
 
 
 
 
 
 
 
 
 81
 82	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
 83		/*
 84		 * If KASLR is enabled, and we have some randomness available,
 85		 * locate the kernel at a randomized offset in physical memory.
 86		 */
 87		*reserve_size = kernel_memsize + TEXT_OFFSET;
 88		status = efi_random_alloc(sys_table_arg, *reserve_size,
 89					  MIN_KIMG_ALIGN, reserve_addr,
 90					  phys_seed);
 91
 92		*image_addr = *reserve_addr + TEXT_OFFSET;
 93	} else {
 94		/*
 95		 * Else, try a straight allocation at the preferred offset.
 96		 * This will work around the issue where, if dram_base == 0x0,
 97		 * efi_low_alloc() refuses to allocate at 0x0 (to prevent the
 98		 * address of the allocation to be mistaken for a FAIL return
 99		 * value or a NULL pointer). It will also ensure that, on
100		 * platforms where the [dram_base, dram_base + TEXT_OFFSET)
101		 * interval is partially occupied by the firmware (like on APM
102		 * Mustang), we can still place the kernel at the address
103		 * 'dram_base + TEXT_OFFSET'.
104		 */
105		if (*image_addr == preferred_offset)
106			return EFI_SUCCESS;
107
108		*image_addr = *reserve_addr = preferred_offset;
109		*reserve_size = round_up(kernel_memsize, EFI_ALLOC_ALIGN);
110
111		status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
112					EFI_LOADER_DATA,
113					*reserve_size / EFI_PAGE_SIZE,
114					(efi_physical_addr_t *)reserve_addr);
115	}
116
117	if (status != EFI_SUCCESS) {
118		*reserve_size = kernel_memsize + TEXT_OFFSET;
119		status = efi_low_alloc(sys_table_arg, *reserve_size,
120				       MIN_KIMG_ALIGN, reserve_addr);
121
122		if (status != EFI_SUCCESS) {
123			pr_efi_err(sys_table_arg, "Failed to relocate kernel\n");
124			*reserve_size = 0;
125			return status;
126		}
127		*image_addr = *reserve_addr + TEXT_OFFSET;
128	}
129	memcpy((void *)*image_addr, old_image_addr, kernel_size);
130
131	return EFI_SUCCESS;
 
 
132}