1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2016 Linaro Ltd; <ard.biesheuvel@linaro.org>
7 #include <linux/log2.h>
13 * Return the number of slots covered by this entry, i.e., the number of
14 * addresses it covers that are suitably aligned and supply enough room
17 static unsigned long get_entry_num_slots(efi_memory_desc_t
*md
,
19 unsigned long align_shift
,
20 u64 alloc_min
, u64 alloc_max
)
22 unsigned long align
= 1UL << align_shift
;
23 u64 first_slot
, last_slot
, region_end
;
25 if (md
->type
!= EFI_CONVENTIONAL_MEMORY
)
28 if (efi_soft_reserve_enabled() &&
29 (md
->attribute
& EFI_MEMORY_SP
))
32 region_end
= min(md
->phys_addr
+ md
->num_pages
* EFI_PAGE_SIZE
- 1,
34 if (region_end
< size
)
37 first_slot
= round_up(max(md
->phys_addr
, alloc_min
), align
);
38 last_slot
= round_down(region_end
- size
+ 1, align
);
40 if (first_slot
> last_slot
)
43 return ((unsigned long)(last_slot
- first_slot
) >> align_shift
) + 1;
47 * The UEFI memory descriptors have a virtual address field that is only used
48 * when installing the virtual mapping using SetVirtualAddressMap(). Since it
49 * is unused here, we can reuse it to keep track of each descriptor's slot
52 #define MD_NUM_SLOTS(md) ((md)->virt_addr)
54 efi_status_t
efi_random_alloc(unsigned long size
,
57 unsigned long random_seed
,
59 unsigned long alloc_min
,
60 unsigned long alloc_max
)
62 struct efi_boot_memmap
*map
__free(efi_pool
) = NULL
;
63 unsigned long total_slots
= 0, target_slot
;
64 unsigned long total_mirrored_slots
= 0;
68 status
= efi_get_memory_map(&map
, false);
69 if (status
!= EFI_SUCCESS
)
72 if (align
< EFI_ALLOC_ALIGN
)
73 align
= EFI_ALLOC_ALIGN
;
75 size
= round_up(size
, EFI_ALLOC_ALIGN
);
77 /* count the suitable slots in each memory map entry */
78 for (map_offset
= 0; map_offset
< map
->map_size
; map_offset
+= map
->desc_size
) {
79 efi_memory_desc_t
*md
= (void *)map
->map
+ map_offset
;
82 slots
= get_entry_num_slots(md
, size
, ilog2(align
), alloc_min
,
84 MD_NUM_SLOTS(md
) = slots
;
86 if (md
->attribute
& EFI_MEMORY_MORE_RELIABLE
)
87 total_mirrored_slots
+= slots
;
90 /* consider only mirrored slots for randomization if any exist */
91 if (total_mirrored_slots
> 0)
92 total_slots
= total_mirrored_slots
;
94 /* find a random number between 0 and total_slots */
95 target_slot
= (total_slots
* (u64
)(random_seed
& U32_MAX
)) >> 32;
98 * target_slot is now a value in the range [0, total_slots), and so
99 * it corresponds with exactly one of the suitable slots we recorded
100 * when iterating over the memory map the first time around.
102 * So iterate over the memory map again, subtracting the number of
103 * slots of each entry at each iteration, until we have found the entry
104 * that covers our chosen slot. Use the residual value of target_slot
105 * to calculate the randomly chosen address, and allocate it directly
106 * using EFI_ALLOCATE_ADDRESS.
108 status
= EFI_OUT_OF_RESOURCES
;
109 for (map_offset
= 0; map_offset
< map
->map_size
; map_offset
+= map
->desc_size
) {
110 efi_memory_desc_t
*md
= (void *)map
->map
+ map_offset
;
111 efi_physical_addr_t target
;
114 if (total_mirrored_slots
> 0 &&
115 !(md
->attribute
& EFI_MEMORY_MORE_RELIABLE
))
118 if (target_slot
>= MD_NUM_SLOTS(md
)) {
119 target_slot
-= MD_NUM_SLOTS(md
);
123 target
= round_up(max_t(u64
, md
->phys_addr
, alloc_min
), align
) + target_slot
* align
;
124 pages
= size
/ EFI_PAGE_SIZE
;
126 status
= efi_bs_call(allocate_pages
, EFI_ALLOCATE_ADDRESS
,
127 memory_type
, pages
, &target
);
128 if (status
== EFI_SUCCESS
)