Unverified Commit 8a3f30c4 authored by Palmer Dabbelt's avatar Palmer Dabbelt
Browse files

Merge tag 'efi-riscv-shared-for-v5.10' of...

Merge tag 'efi-riscv-shared-for-v5.10' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/efi/efi into for-next

Stable branch for v5.10 shared between the EFI and RISC-V trees

The RISC-V EFI boot and runtime support will be merged for v5.10 via
the RISC-V tree. However, it incorporates some changes that conflict
with other EFI changes that are in flight, so this tag serves as a
shared base that allows those conflicts to be resolved beforehand.

* tag 'efi-riscv-shared-for-v5.10' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/efi/efi:
  efi/libstub: arm32: Use low allocation for the uncompressed kernel
  efi/libstub: Export efi_low_alloc_above() to other units
  efi/libstub: arm32: Base FDT and initrd placement on image address
  efi: Rename arm-init to efi-init common for all arch
  include: pe.h: Add RISC-V related PE definition
parents 54701a0d 762cd288
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -66,25 +66,24 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
#define MAX_UNCOMP_KERNEL_SIZE	SZ_32M

/*
 * The kernel zImage should preferably be located between 32 MB and 128 MB
 * from the base of DRAM. The min address leaves space for a maximal size
 * uncompressed image, and the max address is due to how the zImage decompressor
 * picks a destination address.
 * phys-to-virt patching requires that the physical to virtual offset fits
 * into the immediate field of an add/sub instruction, which comes down to the
 * 24 least significant bits being zero, and so the offset should be a multiple
 * of 16 MB. Since PAGE_OFFSET itself is a multiple of 16 MB, the physical
 * base should be aligned to 16 MB as well.
 */
#define ZIMAGE_OFFSET_LIMIT	SZ_128M
#define MIN_ZIMAGE_OFFSET	MAX_UNCOMP_KERNEL_SIZE
#define EFI_PHYS_ALIGN		SZ_16M

/* on ARM, the FDT should be located in the first 128 MB of RAM */
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
/* on ARM, the FDT should be located in a lowmem region */
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
{
	return dram_base + ZIMAGE_OFFSET_LIMIT;
	return round_down(image_addr, EFI_PHYS_ALIGN) + SZ_512M;
}

/* on ARM, the initrd should be loaded in a lowmem region */
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
						    unsigned long image_addr)
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
{
	return dram_base + SZ_512M;
	return round_down(image_addr, EFI_PHYS_ALIGN) + SZ_512M;
}

struct efi_arm_entry_state {
+2 −3
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
	(SEGMENT_ALIGN > THREAD_ALIGN ? SEGMENT_ALIGN : THREAD_ALIGN)

/* on arm64, the FDT may be located anywhere in system RAM */
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
{
	return ULONG_MAX;
}
@@ -80,8 +80,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
 * apply to other bootloaders, and are required for some kernel
 * configurations.
 */
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
						    unsigned long image_addr)
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
{
	return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
}
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o
fake_map-y				+= fake_mem.o
fake_map-$(CONFIG_X86)			+= x86_fake_mem.o

arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
arm-obj-$(CONFIG_EFI)			:= efi-init.o arm-runtime.o
obj-$(CONFIG_ARM)			+= $(arm-obj-y)
obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
obj-$(CONFIG_EFI_CAPSULE_LOADER)	+= capsule-loader.o
+37 −141
Original line number Diff line number Diff line
@@ -113,162 +113,58 @@ void free_screen_info(struct screen_info *si)
	efi_bs_call(free_pool, si);
}

static efi_status_t reserve_kernel_base(unsigned long dram_base,
efi_status_t handle_kernel_image(unsigned long *image_addr,
				 unsigned long *image_size,
				 unsigned long *reserve_addr,
					unsigned long *reserve_size)
				 unsigned long *reserve_size,
				 efi_loaded_image_t *image)
{
	efi_physical_addr_t alloc_addr;
	efi_memory_desc_t *memory_map;
	unsigned long nr_pages, map_size, desc_size, buff_size;
	const int slack = TEXT_OFFSET - 5 * PAGE_SIZE;
	int alloc_size = MAX_UNCOMP_KERNEL_SIZE + EFI_PHYS_ALIGN;
	unsigned long alloc_base, kernel_base;
	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;
	status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
			     EFI_BOOT_SERVICES_DATA, nr_pages, &alloc_addr);
	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.
	 * Allocate space for the decompressed kernel as low as possible.
	 * The region should be 16 MiB aligned, but the first 'slack' bytes
	 * are not used by Linux, so we allow those to be occupied by the
	 * firmware.
	 */
	}

	/*
	 * 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.
	 */
	status = efi_get_memory_map(&map);
	status = efi_low_alloc_above(alloc_size, EFI_PAGE_SIZE, &alloc_base, 0x0);
	if (status != EFI_SUCCESS) {
		efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
		efi_err("Unable to allocate memory for uncompressed kernel.\n");
		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:
			/* Skip soft reserved conventional memory */
			if (efi_soft_reserve_enabled() &&
			    (desc->attribute & EFI_MEMORY_SP))
				continue;

	if ((alloc_base % EFI_PHYS_ALIGN) > slack) {
		/*
			 * Reserve the intersection between this entry and the
			 * region.
		 * More than 'slack' bytes are already occupied at the base of
		 * the allocation, so we need to advance to the next 16 MiB block.
		 */
			start = max(start, (u64)dram_base);
			end = min(end, (u64)dram_base + MAX_UNCOMP_KERNEL_SIZE);

			status = efi_bs_call(allocate_pages,
					     EFI_ALLOCATE_ADDRESS,
					     EFI_LOADER_DATA,
					     (end - start) / EFI_PAGE_SIZE,
					     &start);
			if (status != EFI_SUCCESS) {
				efi_err("reserve_kernel_base(): alloc failed.\n");
				goto out;
		kernel_base = round_up(alloc_base, EFI_PHYS_ALIGN);
		efi_info("Free memory starts at 0x%lx, setting kernel_base to 0x%lx\n",
			 alloc_base, kernel_base);
	} else {
		kernel_base = round_down(alloc_base, EFI_PHYS_ALIGN);
	}
			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;
		}
	}
	*reserve_addr = kernel_base + slack;
	*reserve_size = MAX_UNCOMP_KERNEL_SIZE;

	status = EFI_SUCCESS;
out:
	efi_bs_call(free_pool, memory_map);
	return status;
	/* now free the parts that we will not use */
	if (*reserve_addr > alloc_base) {
		efi_bs_call(free_pages, alloc_base,
			    (*reserve_addr - alloc_base) / EFI_PAGE_SIZE);
		alloc_size -= *reserve_addr - alloc_base;
	}
	efi_bs_call(free_pages, *reserve_addr + MAX_UNCOMP_KERNEL_SIZE,
		    (alloc_size - MAX_UNCOMP_KERNEL_SIZE) / EFI_PAGE_SIZE);

efi_status_t handle_kernel_image(unsigned long *image_addr,
				 unsigned long *image_size,
				 unsigned long *reserve_addr,
				 unsigned long *reserve_size,
				 unsigned long dram_base,
				 efi_loaded_image_t *image)
{
	unsigned long kernel_base;
	efi_status_t status;

	/* use a 16 MiB aligned base for the decompressed kernel */
	kernel_base = round_up(dram_base, SZ_16M) + TEXT_OFFSET;
	*image_addr = kernel_base + TEXT_OFFSET;
	*image_size = 0;

	/*
	 * 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)
	 */
	status = reserve_kernel_base(kernel_base - 5 * PAGE_SIZE, reserve_addr,
				     reserve_size);
	if (status != EFI_SUCCESS) {
		efi_err("Unable to allocate memory for uncompressed kernel.\n");
		return status;
	}
	efi_debug("image addr == 0x%lx, reserve_addr == 0x%lx\n",
		  *image_addr, *reserve_addr);

	*image_addr = kernel_base;
	*image_size = 0;
	return EFI_SUCCESS;
}
Loading