relocate.c 4.7 KB

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