^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <asm/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "efistub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * efi_low_alloc_above() - allocate pages at or above given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * @size: size of the memory area to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * @align: minimum alignment of the allocated memory area. It should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * a power of two.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * @addr: on exit the address of the allocated memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * @min: minimum address to used for the memory allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Allocate at the lowest possible address that is not below @min as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * EFI_LOADER_DATA. The allocated pages are aligned according to @align but at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * least EFI_ALLOC_ALIGN. The first allocated page will not below the address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * given by @min.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Return: status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned long *addr, unsigned long min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long map_size, desc_size, buff_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) efi_memory_desc_t *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned long nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct efi_boot_memmap boot_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) boot_map.map = ↦
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) boot_map.map_size = &map_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) boot_map.desc_size = &desc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) boot_map.desc_ver = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) boot_map.key_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) boot_map.buff_size = &buff_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) status = efi_get_memory_map(&boot_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Enforce minimum alignment that EFI or Linux requires when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * requesting a specific address. We are doing page-based (or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * larger) allocations, and both the address and size must meet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * alignment constraints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (align < EFI_ALLOC_ALIGN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) align = EFI_ALLOC_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) size = round_up(size, EFI_ALLOC_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) nr_pages = size / EFI_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) for (i = 0; i < map_size / desc_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) efi_memory_desc_t *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned long m = (unsigned long)map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u64 start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) desc = efi_early_memdesc_ptr(m, desc_size, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (desc->type != EFI_CONVENTIONAL_MEMORY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (efi_soft_reserve_enabled() &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) (desc->attribute & EFI_MEMORY_SP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (desc->num_pages < nr_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) start = desc->phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) end = start + desc->num_pages * EFI_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (start < min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) start = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) start = round_up(start, align);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if ((start + size) > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) EFI_LOADER_DATA, nr_pages, &start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (status == EFI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *addr = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (i == map_size / desc_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) status = EFI_NOT_FOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) efi_bs_call(free_pool, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * efi_relocate_kernel() - copy memory area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @image_addr: pointer to address of memory area to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @image_size: size of memory area to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @alloc_size: minimum size of memory to allocate, must be greater or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * equal to image_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @preferred_addr: preferred target address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @alignment: minimum alignment of the allocated memory area. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * should be a power of two.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @min_addr: minimum target address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Copy a memory area to a newly allocated memory area aligned according
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * to @alignment but at least EFI_ALLOC_ALIGN. If the preferred address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * is not available, the allocated address will not be below @min_addr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * On exit, @image_addr is updated to the target copy address that was used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * This function is used to copy the Linux kernel verbatim. It does not apply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * any relocation changes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Return: status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) efi_status_t efi_relocate_kernel(unsigned long *image_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned long image_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned long alloc_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned long preferred_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned long alignment,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned long min_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long cur_image_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned long new_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned long nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) efi_physical_addr_t efi_addr = preferred_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (!image_addr || !image_size || !alloc_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return EFI_INVALID_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (alloc_size < image_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return EFI_INVALID_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) cur_image_addr = *image_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * The EFI firmware loader could have placed the kernel image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * anywhere in memory, but the kernel has restrictions on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * max physical address it can run at. Some architectures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * also have a preferred address, so first try to relocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * to the preferred address. If that fails, allocate as low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * as possible while respecting the required alignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) nr_pages = round_up(alloc_size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) EFI_LOADER_DATA, nr_pages, &efi_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) new_addr = efi_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * If preferred address allocation failed allocate as low as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (status != EFI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) status = efi_low_alloc_above(alloc_size, alignment, &new_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) min_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (status != EFI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) efi_err("Failed to allocate usable memory for kernel.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * We know source/dest won't overlap since both memory ranges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * have been allocated by UEFI, so we can safely use memcpy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) memcpy((void *)new_addr, (void *)cur_image_addr, image_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* Return the new address of the relocated image. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *image_addr = new_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }