1 // SPDX-License-Identifier: GPL-2.0
9 * efi_low_alloc_above() - allocate pages at or above given address
10 * @size: size of the memory area to allocate
11 * @align: minimum alignment of the allocated memory area. It should
13 * @addr: on exit the address of the allocated memory
14 * @min: minimum address to used for the memory allocation
16 * Allocate at the lowest possible address that is not below @min as
17 * EFI_LOADER_DATA. The allocated pages are aligned according to @align but at
18 * least EFI_ALLOC_ALIGN. The first allocated page will not below the address
23 efi_status_t
efi_low_alloc_above(unsigned long size
, unsigned long align
,
24 unsigned long *addr
, unsigned long min
)
26 struct efi_boot_memmap
*map
;
28 unsigned long nr_pages
;
31 status
= efi_get_memory_map(&map
, false);
32 if (status
!= EFI_SUCCESS
)
36 * Enforce minimum alignment that EFI or Linux requires when
37 * requesting a specific address. We are doing page-based (or
38 * larger) allocations, and both the address and size must meet
39 * alignment constraints.
41 if (align
< EFI_ALLOC_ALIGN
)
42 align
= EFI_ALLOC_ALIGN
;
44 size
= round_up(size
, EFI_ALLOC_ALIGN
);
45 nr_pages
= size
/ EFI_PAGE_SIZE
;
46 for (i
= 0; i
< map
->map_size
/ map
->desc_size
; i
++) {
47 efi_memory_desc_t
*desc
;
48 unsigned long m
= (unsigned long)map
->map
;
51 desc
= efi_memdesc_ptr(m
, map
->desc_size
, i
);
53 if (desc
->type
!= EFI_CONVENTIONAL_MEMORY
)
56 if (efi_soft_reserve_enabled() &&
57 (desc
->attribute
& EFI_MEMORY_SP
))
60 if (desc
->num_pages
< nr_pages
)
63 start
= desc
->phys_addr
;
64 end
= start
+ desc
->num_pages
* EFI_PAGE_SIZE
;
69 start
= round_up(start
, align
);
70 if ((start
+ size
) > end
)
73 status
= efi_bs_call(allocate_pages
, EFI_ALLOCATE_ADDRESS
,
74 EFI_LOADER_DATA
, nr_pages
, &start
);
75 if (status
== EFI_SUCCESS
) {
81 if (i
== map
->map_size
/ map
->desc_size
)
82 status
= EFI_NOT_FOUND
;
84 efi_bs_call(free_pool
, map
);
90 * efi_relocate_kernel() - copy memory area
91 * @image_addr: pointer to address of memory area to copy
92 * @image_size: size of memory area to copy
93 * @alloc_size: minimum size of memory to allocate, must be greater or
95 * @preferred_addr: preferred target address
96 * @alignment: minimum alignment of the allocated memory area. It
97 * should be a power of two.
98 * @min_addr: minimum target address
100 * Copy a memory area to a newly allocated memory area aligned according
101 * to @alignment but at least EFI_ALLOC_ALIGN. If the preferred address
102 * is not available, the allocated address will not be below @min_addr.
103 * On exit, @image_addr is updated to the target copy address that was used.
105 * This function is used to copy the Linux kernel verbatim. It does not apply
106 * any relocation changes.
108 * Return: status code
110 efi_status_t
efi_relocate_kernel(unsigned long *image_addr
,
111 unsigned long image_size
,
112 unsigned long alloc_size
,
113 unsigned long preferred_addr
,
114 unsigned long alignment
,
115 unsigned long min_addr
)
117 unsigned long cur_image_addr
;
118 unsigned long new_addr
= 0;
120 unsigned long nr_pages
;
121 efi_physical_addr_t efi_addr
= preferred_addr
;
123 if (!image_addr
|| !image_size
|| !alloc_size
)
124 return EFI_INVALID_PARAMETER
;
125 if (alloc_size
< image_size
)
126 return EFI_INVALID_PARAMETER
;
128 cur_image_addr
= *image_addr
;
131 * The EFI firmware loader could have placed the kernel image
132 * anywhere in memory, but the kernel has restrictions on the
133 * max physical address it can run at. Some architectures
134 * also have a preferred address, so first try to relocate
135 * to the preferred address. If that fails, allocate as low
136 * as possible while respecting the required alignment.
138 nr_pages
= round_up(alloc_size
, EFI_ALLOC_ALIGN
) / EFI_PAGE_SIZE
;
139 status
= efi_bs_call(allocate_pages
, EFI_ALLOCATE_ADDRESS
,
140 EFI_LOADER_DATA
, nr_pages
, &efi_addr
);
143 * If preferred address allocation failed allocate as low as
146 if (status
!= EFI_SUCCESS
) {
147 status
= efi_low_alloc_above(alloc_size
, alignment
, &new_addr
,
150 if (status
!= EFI_SUCCESS
) {
151 efi_err("Failed to allocate usable memory for kernel.\n");
156 * We know source/dest won't overlap since both memory ranges
157 * have been allocated by UEFI, so we can safely use memcpy.
159 memcpy((void *)new_addr
, (void *)cur_image_addr
, image_size
);
161 /* Return the new address of the relocated image. */
162 *image_addr
= new_addr
;