arm32-stub.c 7.5 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
R
Roy Franz 已提交
2 3 4 5 6 7
/*
 * Copyright (C) 2013 Linaro Ltd;  <roy.franz@linaro.org>
 */
#include <linux/efi.h>
#include <asm/efi.h>

8 9
#include "efistub.h"

10 11 12 13 14 15 16 17 18 19 20 21 22
static efi_guid_t cpu_state_guid = LINUX_EFI_ARM_CPU_STATE_TABLE_GUID;

struct efi_arm_entry_state *efi_entry_state;

static void get_cpu_state(u32 *cpsr, u32 *sctlr)
{
	asm("mrs %0, cpsr" : "=r"(*cpsr));
	if ((*cpsr & MODE_MASK) == HYP_MODE)
		asm("mrc p15, 4, %0, c1, c0, 0" : "=r"(*sctlr));
	else
		asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(*sctlr));
}

23
efi_status_t check_platform_features(void)
24
{
25 26
	efi_status_t status;
	u32 cpsr, sctlr;
27 28
	int block;

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
	get_cpu_state(&cpsr, &sctlr);

	efi_info("Entering in %s mode with MMU %sabled\n",
		 ((cpsr & MODE_MASK) == HYP_MODE) ? "HYP" : "SVC",
		 (sctlr & 1) ? "en" : "dis");

	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
			     sizeof(*efi_entry_state),
			     (void **)&efi_entry_state);
	if (status != EFI_SUCCESS) {
		efi_err("allocate_pool() failed\n");
		return status;
	}

	efi_entry_state->cpsr_before_ebs = cpsr;
	efi_entry_state->sctlr_before_ebs = sctlr;

	status = efi_bs_call(install_configuration_table, &cpu_state_guid,
			     efi_entry_state);
	if (status != EFI_SUCCESS) {
		efi_err("install_configuration_table() failed\n");
		goto free_state;
	}

53 54 55 56 57 58 59
	/* non-LPAE kernels can run anywhere */
	if (!IS_ENABLED(CONFIG_ARM_LPAE))
		return EFI_SUCCESS;

	/* LPAE kernels need compatible hardware */
	block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
	if (block < 5) {
60
		efi_err("This LPAE kernel is not supported by your CPU\n");
61 62
		status = EFI_UNSUPPORTED;
		goto drop_table;
63 64
	}
	return EFI_SUCCESS;
65 66 67 68 69 70 71 72 73 74 75 76

drop_table:
	efi_bs_call(install_configuration_table, &cpu_state_guid, NULL);
free_state:
	efi_bs_call(free_pool, efi_entry_state);
	return status;
}

void efi_handle_post_ebs_state(void)
{
	get_cpu_state(&efi_entry_state->cpsr_after_ebs,
		      &efi_entry_state->sctlr_after_ebs);
77 78
}

79 80
static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;

81
struct screen_info *alloc_screen_info(void)
82 83 84 85 86 87 88 89 90 91
{
	struct screen_info *si;
	efi_status_t status;

	/*
	 * Unlike on arm64, where we can directly fill out the screen_info
	 * structure from the stub, we need to allocate a buffer to hold
	 * its contents while we hand over to the kernel proper from the
	 * decompressor.
	 */
92 93
	status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
			     sizeof(*si), (void **)&si);
94 95 96 97

	if (status != EFI_SUCCESS)
		return NULL;

98 99
	status = efi_bs_call(install_configuration_table,
			     &screen_info_guid, si);
100 101 102
	if (status == EFI_SUCCESS)
		return si;

103
	efi_bs_call(free_pool, si);
104 105 106
	return NULL;
}

107
void free_screen_info(struct screen_info *si)
108 109 110 111
{
	if (!si)
		return;

112 113
	efi_bs_call(install_configuration_table, &screen_info_guid, NULL);
	efi_bs_call(free_pool, si);
114 115
}

116
static efi_status_t reserve_kernel_base(unsigned long dram_base,
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
					unsigned long *reserve_addr,
					unsigned long *reserve_size)
{
	efi_physical_addr_t alloc_addr;
	efi_memory_desc_t *memory_map;
	unsigned long nr_pages, map_size, desc_size, buff_size;
	efi_status_t status;
	unsigned long l;

	struct efi_boot_memmap map = {
		.map		= &memory_map,
		.map_size	= &map_size,
		.desc_size	= &desc_size,
		.desc_ver	= NULL,
		.key_ptr	= NULL,
		.buff_size	= &buff_size,
	};

	/*
	 * Reserve memory for the uncompressed kernel image. This is
	 * all that prevents any future allocations from conflicting
	 * with the kernel. Since we can't tell from the compressed
	 * image how much DRAM the kernel actually uses (due to BSS
	 * size uncertainty) we allocate the maximum possible size.
	 * Do this very early, as prints can cause memory allocations
	 * that may conflict with this.
	 */
	alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
	nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
146 147
	status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
			     EFI_BOOT_SERVICES_DATA, nr_pages, &alloc_addr);
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
	if (status == EFI_SUCCESS) {
		if (alloc_addr == dram_base) {
			*reserve_addr = alloc_addr;
			*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
			return EFI_SUCCESS;
		}
		/*
		 * If we end up here, the allocation succeeded but starts below
		 * dram_base. This can only occur if the real base of DRAM is
		 * not a multiple of 128 MB, in which case dram_base will have
		 * been rounded up. Since this implies that a part of the region
		 * was already occupied, we need to fall through to the code
		 * below to ensure that the existing allocations don't conflict.
		 * For this reason, we use EFI_BOOT_SERVICES_DATA above and not
		 * EFI_LOADER_DATA, which we wouldn't able to distinguish from
		 * allocations that we want to disallow.
		 */
	}

	/*
	 * If the allocation above failed, we may still be able to proceed:
	 * if the only allocations in the region are of types that will be
	 * released to the OS after ExitBootServices(), the decompressor can
	 * safely overwrite them.
	 */
173
	status = efi_get_memory_map(&map);
174
	if (status != EFI_SUCCESS) {
175
		efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
		return status;
	}

	for (l = 0; l < map_size; l += desc_size) {
		efi_memory_desc_t *desc;
		u64 start, end;

		desc = (void *)memory_map + l;
		start = desc->phys_addr;
		end = start + desc->num_pages * EFI_PAGE_SIZE;

		/* Skip if entry does not intersect with region */
		if (start >= dram_base + MAX_UNCOMP_KERNEL_SIZE ||
		    end <= dram_base)
			continue;

		switch (desc->type) {
		case EFI_BOOT_SERVICES_CODE:
		case EFI_BOOT_SERVICES_DATA:
			/* Ignore types that are released to the OS anyway */
			continue;

		case EFI_CONVENTIONAL_MEMORY:
199 200 201 202 203
			/* Skip soft reserved conventional memory */
			if (efi_soft_reserve_enabled() &&
			    (desc->attribute & EFI_MEMORY_SP))
				continue;

204 205 206 207 208 209 210
			/*
			 * Reserve the intersection between this entry and the
			 * region.
			 */
			start = max(start, (u64)dram_base);
			end = min(end, (u64)dram_base + MAX_UNCOMP_KERNEL_SIZE);

211 212 213 214 215
			status = efi_bs_call(allocate_pages,
					     EFI_ALLOCATE_ADDRESS,
					     EFI_LOADER_DATA,
					     (end - start) / EFI_PAGE_SIZE,
					     &start);
216
			if (status != EFI_SUCCESS) {
217
				efi_err("reserve_kernel_base(): alloc failed.\n");
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
				goto out;
			}
			break;

		case EFI_LOADER_CODE:
		case EFI_LOADER_DATA:
			/*
			 * These regions may be released and reallocated for
			 * another purpose (including EFI_RUNTIME_SERVICE_DATA)
			 * at any time during the execution of the OS loader,
			 * so we cannot consider them as safe.
			 */
		default:
			/*
			 * Treat any other allocation in the region as unsafe */
			status = EFI_OUT_OF_RESOURCES;
			goto out;
		}
	}

	status = EFI_SUCCESS;
out:
240
	efi_bs_call(free_pool, memory_map);
241 242 243
	return status;
}

244
efi_status_t handle_kernel_image(unsigned long *image_addr,
R
Roy Franz 已提交
245 246 247 248 249 250
				 unsigned long *image_size,
				 unsigned long *reserve_addr,
				 unsigned long *reserve_size,
				 unsigned long dram_base,
				 efi_loaded_image_t *image)
{
251
	unsigned long kernel_base;
R
Roy Franz 已提交
252 253
	efi_status_t status;

254 255
	/* use a 16 MiB aligned base for the decompressed kernel */
	kernel_base = round_up(dram_base, SZ_16M) + TEXT_OFFSET;
R
Roy Franz 已提交
256

257 258 259 260 261 262 263
	/*
	 * Note that some platforms (notably, the Raspberry Pi 2) put
	 * spin-tables and other pieces of firmware at the base of RAM,
	 * abusing the fact that the window of TEXT_OFFSET bytes at the
	 * base of the kernel image is only partially used at the moment.
	 * (Up to 5 pages are used for the swapper page tables)
	 */
264 265
	status = reserve_kernel_base(kernel_base - 5 * PAGE_SIZE, reserve_addr,
				     reserve_size);
R
Roy Franz 已提交
266
	if (status != EFI_SUCCESS) {
267
		efi_err("Unable to allocate memory for uncompressed kernel.\n");
R
Roy Franz 已提交
268 269 270
		return status;
	}

271 272
	*image_addr = kernel_base;
	*image_size = 0;
R
Roy Franz 已提交
273 274
	return EFI_SUCCESS;
}