hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/firmware/efi/libstub/arm64-stub.c
....@@ -1,31 +1,21 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org>
34 *
45 * This file implements the EFI boot stub for the arm64 kernel.
56 * Adapted from ARM version by Mark Salter <msalter@redhat.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation.
10
- *
117 */
128
13
-/*
14
- * To prevent the compiler from emitting GOT-indirected (and thus absolute)
15
- * references to the section markers, override their visibility as 'hidden'
16
- */
17
-#pragma GCC visibility push(hidden)
18
-#include <asm/sections.h>
19
-#pragma GCC visibility pop
209
2110 #include <linux/efi.h>
2211 #include <asm/efi.h>
2312 #include <asm/memory.h>
13
+#include <asm/sections.h>
2414 #include <asm/sysreg.h>
2515
2616 #include "efistub.h"
2717
28
-efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
18
+efi_status_t check_platform_features(void)
2919 {
3020 u64 tg;
3121
....@@ -34,126 +24,145 @@
3424 return EFI_SUCCESS;
3525
3626 tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
37
- if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
27
+ if (tg < ID_AA64MMFR0_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_TGRAN_SUPPORTED_MAX) {
3828 if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
39
- pr_efi_err(sys_table_arg, "This 64 KB granular kernel is not supported by your CPU\n");
29
+ efi_err("This 64 KB granular kernel is not supported by your CPU\n");
4030 else
41
- pr_efi_err(sys_table_arg, "This 16 KB granular kernel is not supported by your CPU\n");
31
+ efi_err("This 16 KB granular kernel is not supported by your CPU\n");
4232 return EFI_UNSUPPORTED;
4333 }
4434 return EFI_SUCCESS;
4535 }
4636
47
-efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
48
- unsigned long *image_addr,
37
+/*
38
+ * Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
39
+ * to provide space, and fail to zero it). Check for this condition by double
40
+ * checking that the first and the last byte of the image are covered by the
41
+ * same EFI memory map entry.
42
+ */
43
+static bool check_image_region(u64 base, u64 size)
44
+{
45
+ unsigned long map_size, desc_size, buff_size;
46
+ efi_memory_desc_t *memory_map;
47
+ struct efi_boot_memmap map;
48
+ efi_status_t status;
49
+ bool ret = false;
50
+ int map_offset;
51
+
52
+ map.map = &memory_map;
53
+ map.map_size = &map_size;
54
+ map.desc_size = &desc_size;
55
+ map.desc_ver = NULL;
56
+ map.key_ptr = NULL;
57
+ map.buff_size = &buff_size;
58
+
59
+ status = efi_get_memory_map(&map);
60
+ if (status != EFI_SUCCESS)
61
+ return false;
62
+
63
+ for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
64
+ efi_memory_desc_t *md = (void *)memory_map + map_offset;
65
+ u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE;
66
+
67
+ /*
68
+ * Find the region that covers base, and return whether
69
+ * it covers base+size bytes.
70
+ */
71
+ if (base >= md->phys_addr && base < end) {
72
+ ret = (base + size) <= end;
73
+ break;
74
+ }
75
+ }
76
+
77
+ efi_bs_call(free_pool, memory_map);
78
+
79
+ return ret;
80
+}
81
+
82
+efi_status_t handle_kernel_image(unsigned long *image_addr,
4983 unsigned long *image_size,
5084 unsigned long *reserve_addr,
5185 unsigned long *reserve_size,
52
- unsigned long dram_base,
5386 efi_loaded_image_t *image)
5487 {
5588 efi_status_t status;
5689 unsigned long kernel_size, kernel_memsize = 0;
57
- void *old_image_addr = (void *)*image_addr;
58
- unsigned long preferred_offset;
59
- u64 phys_seed = 0;
90
+ u32 phys_seed = 0;
91
+
92
+ /*
93
+ * Although relocatable kernels can fix up the misalignment with
94
+ * respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
95
+ * subtly out of sync with those recorded in the vmlinux when kaslr is
96
+ * disabled but the image required relocation anyway. Therefore retain
97
+ * 2M alignment if KASLR was explicitly disabled, even if it was not
98
+ * going to be activated to begin with.
99
+ */
100
+ u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
60101
61102 if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
62
- if (!nokaslr()) {
63
- status = efi_get_random_bytes(sys_table_arg,
64
- sizeof(phys_seed),
103
+ if (!efi_nokaslr) {
104
+ status = efi_get_random_bytes(sizeof(phys_seed),
65105 (u8 *)&phys_seed);
66106 if (status == EFI_NOT_FOUND) {
67
- pr_efi(sys_table_arg, "EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
107
+ efi_info("EFI_RNG_PROTOCOL unavailable, KASLR will be disabled\n");
108
+ efi_nokaslr = true;
68109 } else if (status != EFI_SUCCESS) {
69
- pr_efi_err(sys_table_arg, "efi_get_random_bytes() failed\n");
70
- return status;
110
+ efi_err("efi_get_random_bytes() failed (0x%lx), KASLR will be disabled\n",
111
+ status);
112
+ efi_nokaslr = true;
71113 }
72114 } else {
73
- pr_efi(sys_table_arg, "KASLR disabled on kernel command line\n");
115
+ efi_info("KASLR disabled on kernel command line\n");
74116 }
75117 }
76118
77
- /*
78
- * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
79
- * a 2 MB aligned base, which itself may be lower than dram_base, as
80
- * long as the resulting offset equals or exceeds it.
81
- */
82
- preferred_offset = round_down(dram_base, MIN_KIMG_ALIGN) + TEXT_OFFSET;
83
- if (preferred_offset < dram_base)
84
- preferred_offset += MIN_KIMG_ALIGN;
119
+ if (image->image_base != _text)
120
+ efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
121
+
122
+ if (!IS_ALIGNED((u64)_text, SEGMENT_ALIGN))
123
+ efi_err("FIRMWARE BUG: kernel image not aligned on %dk boundary\n",
124
+ SEGMENT_ALIGN >> 10);
85125
86126 kernel_size = _edata - _text;
87127 kernel_memsize = kernel_size + (_end - _edata);
128
+ *reserve_size = kernel_memsize;
88129
89130 if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
90
- /*
91
- * If CONFIG_DEBUG_ALIGN_RODATA is not set, produce a
92
- * displacement in the interval [0, MIN_KIMG_ALIGN) that
93
- * doesn't violate this kernel's de-facto alignment
94
- * constraints.
95
- */
96
- u32 mask = (MIN_KIMG_ALIGN - 1) & ~(EFI_KIMG_ALIGN - 1);
97
- u32 offset = !IS_ENABLED(CONFIG_DEBUG_ALIGN_RODATA) ?
98
- (phys_seed >> 32) & mask : TEXT_OFFSET;
99
-
100
- /*
101
- * With CONFIG_RANDOMIZE_TEXT_OFFSET=y, TEXT_OFFSET may not
102
- * be a multiple of EFI_KIMG_ALIGN, and we must ensure that
103
- * we preserve the misalignment of 'offset' relative to
104
- * EFI_KIMG_ALIGN so that statically allocated objects whose
105
- * alignment exceeds PAGE_SIZE appear correctly aligned in
106
- * memory.
107
- */
108
- offset |= TEXT_OFFSET % EFI_KIMG_ALIGN;
109
-
110131 /*
111132 * If KASLR is enabled, and we have some randomness available,
112133 * locate the kernel at a randomized offset in physical memory.
113134 */
114
- *reserve_size = kernel_memsize + offset;
115
- status = efi_random_alloc(sys_table_arg, *reserve_size,
116
- MIN_KIMG_ALIGN, reserve_addr,
117
- (u32)phys_seed);
118
-
119
- *image_addr = *reserve_addr + offset;
135
+ status = efi_random_alloc(*reserve_size, min_kimg_align,
136
+ reserve_addr, phys_seed);
120137 } else {
121
- /*
122
- * Else, try a straight allocation at the preferred offset.
123
- * This will work around the issue where, if dram_base == 0x0,
124
- * efi_low_alloc() refuses to allocate at 0x0 (to prevent the
125
- * address of the allocation to be mistaken for a FAIL return
126
- * value or a NULL pointer). It will also ensure that, on
127
- * platforms where the [dram_base, dram_base + TEXT_OFFSET)
128
- * interval is partially occupied by the firmware (like on APM
129
- * Mustang), we can still place the kernel at the address
130
- * 'dram_base + TEXT_OFFSET'.
131
- */
132
- if (*image_addr == preferred_offset)
133
- return EFI_SUCCESS;
134
-
135
- *image_addr = *reserve_addr = preferred_offset;
136
- *reserve_size = round_up(kernel_memsize, EFI_ALLOC_ALIGN);
137
-
138
- status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
139
- EFI_LOADER_DATA,
140
- *reserve_size / EFI_PAGE_SIZE,
141
- (efi_physical_addr_t *)reserve_addr);
138
+ status = EFI_OUT_OF_RESOURCES;
142139 }
143140
144141 if (status != EFI_SUCCESS) {
145
- *reserve_size = kernel_memsize + TEXT_OFFSET;
146
- status = efi_low_alloc(sys_table_arg, *reserve_size,
147
- MIN_KIMG_ALIGN, reserve_addr);
142
+ if (!check_image_region((u64)_text, kernel_memsize)) {
143
+ efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
144
+ } else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
145
+ /*
146
+ * Just execute from wherever we were loaded by the
147
+ * UEFI PE/COFF loader if the alignment is suitable.
148
+ */
149
+ *image_addr = (u64)_text;
150
+ *reserve_size = 0;
151
+ return EFI_SUCCESS;
152
+ }
153
+
154
+ status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
155
+ ULONG_MAX, min_kimg_align);
148156
149157 if (status != EFI_SUCCESS) {
150
- pr_efi_err(sys_table_arg, "Failed to relocate kernel\n");
158
+ efi_err("Failed to relocate kernel\n");
151159 *reserve_size = 0;
152160 return status;
153161 }
154
- *image_addr = *reserve_addr + TEXT_OFFSET;
155162 }
156
- memcpy((void *)*image_addr, old_image_addr, kernel_size);
163
+
164
+ *image_addr = *reserve_addr;
165
+ memcpy((void *)*image_addr, _text, kernel_size);
157166
158167 return EFI_SUCCESS;
159168 }