Skip to content

Commit 8a3f30c

Browse files
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
2 parents 54701a0 + 762cd28 commit 8a3f30c

10 files changed

Lines changed: 62 additions & 209 deletions

File tree

arch/arm/include/asm/efi.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,24 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
6666
#define MAX_UNCOMP_KERNEL_SIZE SZ_32M
6767

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

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

8383
/* on ARM, the initrd should be loaded in a lowmem region */
84-
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
85-
unsigned long image_addr)
84+
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
8685
{
87-
return dram_base + SZ_512M;
86+
return round_down(image_addr, EFI_PHYS_ALIGN) + SZ_512M;
8887
}
8988

9089
struct efi_arm_entry_state {

arch/arm64/include/asm/efi.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
6565
(SEGMENT_ALIGN > THREAD_ALIGN ? SEGMENT_ALIGN : THREAD_ALIGN)
6666

6767
/* on arm64, the FDT may be located anywhere in system RAM */
68-
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
68+
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
6969
{
7070
return ULONG_MAX;
7171
}
@@ -80,8 +80,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
8080
* apply to other bootloaders, and are required for some kernel
8181
* configurations.
8282
*/
83-
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
84-
unsigned long image_addr)
83+
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
8584
{
8685
return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
8786
}

drivers/firmware/efi/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o
3232
fake_map-y += fake_mem.o
3333
fake_map-$(CONFIG_X86) += x86_fake_mem.o
3434

35-
arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o
35+
arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o
3636
obj-$(CONFIG_ARM) += $(arm-obj-y)
3737
obj-$(CONFIG_ARM64) += $(arm-obj-y)
3838
obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o

drivers/firmware/efi/libstub/arm32-stub.c

Lines changed: 37 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -113,162 +113,58 @@ void free_screen_info(struct screen_info *si)
113113
efi_bs_call(free_pool, si);
114114
}
115115

116-
static efi_status_t reserve_kernel_base(unsigned long dram_base,
117-
unsigned long *reserve_addr,
118-
unsigned long *reserve_size)
119-
{
120-
efi_physical_addr_t alloc_addr;
121-
efi_memory_desc_t *memory_map;
122-
unsigned long nr_pages, map_size, desc_size, buff_size;
123-
efi_status_t status;
124-
unsigned long l;
125-
126-
struct efi_boot_memmap map = {
127-
.map = &memory_map,
128-
.map_size = &map_size,
129-
.desc_size = &desc_size,
130-
.desc_ver = NULL,
131-
.key_ptr = NULL,
132-
.buff_size = &buff_size,
133-
};
134-
135-
/*
136-
* Reserve memory for the uncompressed kernel image. This is
137-
* all that prevents any future allocations from conflicting
138-
* with the kernel. Since we can't tell from the compressed
139-
* image how much DRAM the kernel actually uses (due to BSS
140-
* size uncertainty) we allocate the maximum possible size.
141-
* Do this very early, as prints can cause memory allocations
142-
* that may conflict with this.
143-
*/
144-
alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
145-
nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
146-
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
147-
EFI_BOOT_SERVICES_DATA, nr_pages, &alloc_addr);
148-
if (status == EFI_SUCCESS) {
149-
if (alloc_addr == dram_base) {
150-
*reserve_addr = alloc_addr;
151-
*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
152-
return EFI_SUCCESS;
153-
}
154-
/*
155-
* If we end up here, the allocation succeeded but starts below
156-
* dram_base. This can only occur if the real base of DRAM is
157-
* not a multiple of 128 MB, in which case dram_base will have
158-
* been rounded up. Since this implies that a part of the region
159-
* was already occupied, we need to fall through to the code
160-
* below to ensure that the existing allocations don't conflict.
161-
* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
162-
* EFI_LOADER_DATA, which we wouldn't able to distinguish from
163-
* allocations that we want to disallow.
164-
*/
165-
}
166-
167-
/*
168-
* If the allocation above failed, we may still be able to proceed:
169-
* if the only allocations in the region are of types that will be
170-
* released to the OS after ExitBootServices(), the decompressor can
171-
* safely overwrite them.
172-
*/
173-
status = efi_get_memory_map(&map);
174-
if (status != EFI_SUCCESS) {
175-
efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
176-
return status;
177-
}
178-
179-
for (l = 0; l < map_size; l += desc_size) {
180-
efi_memory_desc_t *desc;
181-
u64 start, end;
182-
183-
desc = (void *)memory_map + l;
184-
start = desc->phys_addr;
185-
end = start + desc->num_pages * EFI_PAGE_SIZE;
186-
187-
/* Skip if entry does not intersect with region */
188-
if (start >= dram_base + MAX_UNCOMP_KERNEL_SIZE ||
189-
end <= dram_base)
190-
continue;
191-
192-
switch (desc->type) {
193-
case EFI_BOOT_SERVICES_CODE:
194-
case EFI_BOOT_SERVICES_DATA:
195-
/* Ignore types that are released to the OS anyway */
196-
continue;
197-
198-
case EFI_CONVENTIONAL_MEMORY:
199-
/* Skip soft reserved conventional memory */
200-
if (efi_soft_reserve_enabled() &&
201-
(desc->attribute & EFI_MEMORY_SP))
202-
continue;
203-
204-
/*
205-
* Reserve the intersection between this entry and the
206-
* region.
207-
*/
208-
start = max(start, (u64)dram_base);
209-
end = min(end, (u64)dram_base + MAX_UNCOMP_KERNEL_SIZE);
210-
211-
status = efi_bs_call(allocate_pages,
212-
EFI_ALLOCATE_ADDRESS,
213-
EFI_LOADER_DATA,
214-
(end - start) / EFI_PAGE_SIZE,
215-
&start);
216-
if (status != EFI_SUCCESS) {
217-
efi_err("reserve_kernel_base(): alloc failed.\n");
218-
goto out;
219-
}
220-
break;
221-
222-
case EFI_LOADER_CODE:
223-
case EFI_LOADER_DATA:
224-
/*
225-
* These regions may be released and reallocated for
226-
* another purpose (including EFI_RUNTIME_SERVICE_DATA)
227-
* at any time during the execution of the OS loader,
228-
* so we cannot consider them as safe.
229-
*/
230-
default:
231-
/*
232-
* Treat any other allocation in the region as unsafe */
233-
status = EFI_OUT_OF_RESOURCES;
234-
goto out;
235-
}
236-
}
237-
238-
status = EFI_SUCCESS;
239-
out:
240-
efi_bs_call(free_pool, memory_map);
241-
return status;
242-
}
243-
244116
efi_status_t handle_kernel_image(unsigned long *image_addr,
245117
unsigned long *image_size,
246118
unsigned long *reserve_addr,
247119
unsigned long *reserve_size,
248-
unsigned long dram_base,
249120
efi_loaded_image_t *image)
250121
{
251-
unsigned long kernel_base;
122+
const int slack = TEXT_OFFSET - 5 * PAGE_SIZE;
123+
int alloc_size = MAX_UNCOMP_KERNEL_SIZE + EFI_PHYS_ALIGN;
124+
unsigned long alloc_base, kernel_base;
252125
efi_status_t status;
253126

254-
/* use a 16 MiB aligned base for the decompressed kernel */
255-
kernel_base = round_up(dram_base, SZ_16M) + TEXT_OFFSET;
256-
257127
/*
258-
* Note that some platforms (notably, the Raspberry Pi 2) put
259-
* spin-tables and other pieces of firmware at the base of RAM,
260-
* abusing the fact that the window of TEXT_OFFSET bytes at the
261-
* base of the kernel image is only partially used at the moment.
262-
* (Up to 5 pages are used for the swapper page tables)
128+
* Allocate space for the decompressed kernel as low as possible.
129+
* The region should be 16 MiB aligned, but the first 'slack' bytes
130+
* are not used by Linux, so we allow those to be occupied by the
131+
* firmware.
263132
*/
264-
status = reserve_kernel_base(kernel_base - 5 * PAGE_SIZE, reserve_addr,
265-
reserve_size);
133+
status = efi_low_alloc_above(alloc_size, EFI_PAGE_SIZE, &alloc_base, 0x0);
266134
if (status != EFI_SUCCESS) {
267135
efi_err("Unable to allocate memory for uncompressed kernel.\n");
268136
return status;
269137
}
270138

271-
*image_addr = kernel_base;
139+
if ((alloc_base % EFI_PHYS_ALIGN) > slack) {
140+
/*
141+
* More than 'slack' bytes are already occupied at the base of
142+
* the allocation, so we need to advance to the next 16 MiB block.
143+
*/
144+
kernel_base = round_up(alloc_base, EFI_PHYS_ALIGN);
145+
efi_info("Free memory starts at 0x%lx, setting kernel_base to 0x%lx\n",
146+
alloc_base, kernel_base);
147+
} else {
148+
kernel_base = round_down(alloc_base, EFI_PHYS_ALIGN);
149+
}
150+
151+
*reserve_addr = kernel_base + slack;
152+
*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
153+
154+
/* now free the parts that we will not use */
155+
if (*reserve_addr > alloc_base) {
156+
efi_bs_call(free_pages, alloc_base,
157+
(*reserve_addr - alloc_base) / EFI_PAGE_SIZE);
158+
alloc_size -= *reserve_addr - alloc_base;
159+
}
160+
efi_bs_call(free_pages, *reserve_addr + MAX_UNCOMP_KERNEL_SIZE,
161+
(alloc_size - MAX_UNCOMP_KERNEL_SIZE) / EFI_PAGE_SIZE);
162+
163+
*image_addr = kernel_base + TEXT_OFFSET;
272164
*image_size = 0;
165+
166+
efi_debug("image addr == 0x%lx, reserve_addr == 0x%lx\n",
167+
*image_addr, *reserve_addr);
168+
273169
return EFI_SUCCESS;
274170
}

drivers/firmware/efi/libstub/arm64-stub.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
5050
unsigned long *image_size,
5151
unsigned long *reserve_addr,
5252
unsigned long *reserve_size,
53-
unsigned long dram_base,
5453
efi_loaded_image_t *image)
5554
{
5655
efi_status_t status;

drivers/firmware/efi/libstub/efi-stub.c

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -87,40 +87,6 @@ static void install_memreserve_table(void)
8787
efi_err("Failed to install memreserve config table!\n");
8888
}
8989

90-
static unsigned long get_dram_base(void)
91-
{
92-
efi_status_t status;
93-
unsigned long map_size, buff_size;
94-
unsigned long membase = EFI_ERROR;
95-
struct efi_memory_map map;
96-
efi_memory_desc_t *md;
97-
struct efi_boot_memmap boot_map;
98-
99-
boot_map.map = (efi_memory_desc_t **)&map.map;
100-
boot_map.map_size = &map_size;
101-
boot_map.desc_size = &map.desc_size;
102-
boot_map.desc_ver = NULL;
103-
boot_map.key_ptr = NULL;
104-
boot_map.buff_size = &buff_size;
105-
106-
status = efi_get_memory_map(&boot_map);
107-
if (status != EFI_SUCCESS)
108-
return membase;
109-
110-
map.map_end = map.map + map_size;
111-
112-
for_each_efi_memory_desc_in_map(&map, md) {
113-
if (md->attribute & EFI_MEMORY_WB) {
114-
if (membase > md->phys_addr)
115-
membase = md->phys_addr;
116-
}
117-
}
118-
119-
efi_bs_call(free_pool, map.map);
120-
121-
return membase;
122-
}
123-
12490
/*
12591
* EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
12692
* that is described in the PE/COFF header. Most of the code is the same
@@ -134,7 +100,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
134100
efi_status_t status;
135101
unsigned long image_addr;
136102
unsigned long image_size = 0;
137-
unsigned long dram_base;
138103
/* addr/point and size pairs for memory management*/
139104
unsigned long initrd_addr = 0;
140105
unsigned long initrd_size = 0;
@@ -174,13 +139,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
174139
goto fail;
175140
}
176141

177-
dram_base = get_dram_base();
178-
if (dram_base == EFI_ERROR) {
179-
efi_err("Failed to find DRAM base\n");
180-
status = EFI_LOAD_ERROR;
181-
goto fail;
182-
}
183-
184142
/*
185143
* Get the command line from EFI, using the LOADED_IMAGE
186144
* protocol. We are going to copy the command line into the
@@ -218,7 +176,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
218176
status = handle_kernel_image(&image_addr, &image_size,
219177
&reserve_addr,
220178
&reserve_size,
221-
dram_base, image);
179+
image);
222180
if (status != EFI_SUCCESS) {
223181
efi_err("Failed to relocate kernel\n");
224182
goto fail_free_screeninfo;
@@ -262,7 +220,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
262220
efi_info("Generating empty DTB\n");
263221

264222
if (!efi_noinitrd) {
265-
max_addr = efi_get_max_initrd_addr(dram_base, image_addr);
223+
max_addr = efi_get_max_initrd_addr(image_addr);
266224
status = efi_load_initrd(image, &initrd_addr, &initrd_size,
267225
ULONG_MAX, max_addr);
268226
if (status != EFI_SUCCESS)
@@ -306,7 +264,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
306264
install_memreserve_table();
307265

308266
status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr,
309-
efi_get_max_fdt_addr(dram_base),
267+
efi_get_max_fdt_addr(image_addr),
310268
initrd_addr, initrd_size,
311269
cmdline_ptr, fdt_addr, fdt_size);
312270
if (status != EFI_SUCCESS)

drivers/firmware/efi/libstub/efistub.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
#include <linux/types.h>
1111
#include <asm/efi.h>
1212

13-
/* error code which can't be mistaken for valid address */
14-
#define EFI_ERROR (~0UL)
15-
1613
/*
1714
* __init annotations should not be used in the EFI stub, since the code is
1815
* either included in the decompressor (x86, ARM) where they have no effect,
@@ -740,6 +737,9 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
740737
efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
741738
unsigned long max, unsigned long align);
742739

740+
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
741+
unsigned long *addr, unsigned long min);
742+
743743
efi_status_t efi_relocate_kernel(unsigned long *image_addr,
744744
unsigned long image_size,
745745
unsigned long alloc_size,
@@ -786,7 +786,6 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
786786
unsigned long *image_size,
787787
unsigned long *reserve_addr,
788788
unsigned long *reserve_size,
789-
unsigned long dram_base,
790789
efi_loaded_image_t *image);
791790

792791
asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,

0 commit comments

Comments
 (0)