aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/kexec-bzimage64.c146
-rw-r--r--drivers/firmware/efi/runtime-map.c21
-rw-r--r--include/linux/efi.h19
3 files changed, 174 insertions, 12 deletions
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index a8e646458a10..623e6c58081f 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -18,10 +18,12 @@
18#include <linux/kexec.h> 18#include <linux/kexec.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/efi.h>
21 22
22#include <asm/bootparam.h> 23#include <asm/bootparam.h>
23#include <asm/setup.h> 24#include <asm/setup.h>
24#include <asm/crash.h> 25#include <asm/crash.h>
26#include <asm/efi.h>
25 27
26#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */ 28#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */
27 29
@@ -90,7 +92,7 @@ static int setup_cmdline(struct kimage *image, struct boot_params *params,
90 return 0; 92 return 0;
91} 93}
92 94
93static int setup_memory_map_entries(struct boot_params *params) 95static int setup_e820_entries(struct boot_params *params)
94{ 96{
95 unsigned int nr_e820_entries; 97 unsigned int nr_e820_entries;
96 98
@@ -107,8 +109,93 @@ static int setup_memory_map_entries(struct boot_params *params)
107 return 0; 109 return 0;
108} 110}
109 111
110static int setup_boot_parameters(struct kimage *image, 112#ifdef CONFIG_EFI
111 struct boot_params *params) 113static int setup_efi_info_memmap(struct boot_params *params,
114 unsigned long params_load_addr,
115 unsigned int efi_map_offset,
116 unsigned int efi_map_sz)
117{
118 void *efi_map = (void *)params + efi_map_offset;
119 unsigned long efi_map_phys_addr = params_load_addr + efi_map_offset;
120 struct efi_info *ei = &params->efi_info;
121
122 if (!efi_map_sz)
123 return 0;
124
125 efi_runtime_map_copy(efi_map, efi_map_sz);
126
127 ei->efi_memmap = efi_map_phys_addr & 0xffffffff;
128 ei->efi_memmap_hi = efi_map_phys_addr >> 32;
129 ei->efi_memmap_size = efi_map_sz;
130
131 return 0;
132}
133
134static int
135prepare_add_efi_setup_data(struct boot_params *params,
136 unsigned long params_load_addr,
137 unsigned int efi_setup_data_offset)
138{
139 unsigned long setup_data_phys;
140 struct setup_data *sd = (void *)params + efi_setup_data_offset;
141 struct efi_setup_data *esd = (void *)sd + sizeof(struct setup_data);
142
143 esd->fw_vendor = efi.fw_vendor;
144 esd->runtime = efi.runtime;
145 esd->tables = efi.config_table;
146 esd->smbios = efi.smbios;
147
148 sd->type = SETUP_EFI;
149 sd->len = sizeof(struct efi_setup_data);
150
151 /* Add setup data */
152 setup_data_phys = params_load_addr + efi_setup_data_offset;
153 sd->next = params->hdr.setup_data;
154 params->hdr.setup_data = setup_data_phys;
155
156 return 0;
157}
158
159static int
160setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
161 unsigned int efi_map_offset, unsigned int efi_map_sz,
162 unsigned int efi_setup_data_offset)
163{
164 struct efi_info *current_ei = &boot_params.efi_info;
165 struct efi_info *ei = &params->efi_info;
166
167 if (!current_ei->efi_memmap_size)
168 return 0;
169
170 /*
171 * If 1:1 mapping is not enabled, second kernel can not setup EFI
172 * and use EFI run time services. User space will have to pass
173 * acpi_rsdp=<addr> on kernel command line to make second kernel boot
174 * without efi.
175 */
176 if (efi_enabled(EFI_OLD_MEMMAP))
177 return 0;
178
179 ei->efi_loader_signature = current_ei->efi_loader_signature;
180 ei->efi_systab = current_ei->efi_systab;
181 ei->efi_systab_hi = current_ei->efi_systab_hi;
182
183 ei->efi_memdesc_version = current_ei->efi_memdesc_version;
184 ei->efi_memdesc_size = efi_get_runtime_map_desc_size();
185
186 setup_efi_info_memmap(params, params_load_addr, efi_map_offset,
187 efi_map_sz);
188 prepare_add_efi_setup_data(params, params_load_addr,
189 efi_setup_data_offset);
190 return 0;
191}
192#endif /* CONFIG_EFI */
193
194static int
195setup_boot_parameters(struct kimage *image, struct boot_params *params,
196 unsigned long params_load_addr,
197 unsigned int efi_map_offset, unsigned int efi_map_sz,
198 unsigned int efi_setup_data_offset)
112{ 199{
113 unsigned int nr_e820_entries; 200 unsigned int nr_e820_entries;
114 unsigned long long mem_k, start, end; 201 unsigned long long mem_k, start, end;
@@ -140,7 +227,7 @@ static int setup_boot_parameters(struct kimage *image,
140 if (ret) 227 if (ret)
141 return ret; 228 return ret;
142 } else 229 } else
143 setup_memory_map_entries(params); 230 setup_e820_entries(params);
144 231
145 nr_e820_entries = params->e820_entries; 232 nr_e820_entries = params->e820_entries;
146 233
@@ -161,6 +248,12 @@ static int setup_boot_parameters(struct kimage *image,
161 } 248 }
162 } 249 }
163 250
251#ifdef CONFIG_EFI
252 /* Setup EFI state */
253 setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz,
254 efi_setup_data_offset);
255#endif
256
164 /* Setup EDD info */ 257 /* Setup EDD info */
165 memcpy(params->eddbuf, boot_params.eddbuf, 258 memcpy(params->eddbuf, boot_params.eddbuf,
166 EDDMAXNR * sizeof(struct edd_info)); 259 EDDMAXNR * sizeof(struct edd_info));
@@ -214,6 +307,15 @@ int bzImage64_probe(const char *buf, unsigned long len)
214 return ret; 307 return ret;
215 } 308 }
216 309
310 /*
311 * Can't handle 32bit EFI as it does not allow loading kernel
312 * above 4G. This should be handled by 32bit bzImage loader
313 */
314 if (efi_enabled(EFI_RUNTIME_SERVICES) && !efi_enabled(EFI_64BIT)) {
315 pr_debug("EFI is 32 bit. Can't load kernel above 4G.\n");
316 return ret;
317 }
318
217 /* I've got a bzImage */ 319 /* I've got a bzImage */
218 pr_debug("It's a relocatable bzImage64\n"); 320 pr_debug("It's a relocatable bzImage64\n");
219 ret = 0; 321 ret = 0;
@@ -229,7 +331,7 @@ void *bzImage64_load(struct kimage *image, char *kernel,
229 331
230 struct setup_header *header; 332 struct setup_header *header;
231 int setup_sects, kern16_size, ret = 0; 333 int setup_sects, kern16_size, ret = 0;
232 unsigned long setup_header_size, params_cmdline_sz; 334 unsigned long setup_header_size, params_cmdline_sz, params_misc_sz;
233 struct boot_params *params; 335 struct boot_params *params;
234 unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr; 336 unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr;
235 unsigned long purgatory_load_addr; 337 unsigned long purgatory_load_addr;
@@ -239,6 +341,7 @@ void *bzImage64_load(struct kimage *image, char *kernel,
239 struct kexec_entry64_regs regs64; 341 struct kexec_entry64_regs regs64;
240 void *stack; 342 void *stack;
241 unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr); 343 unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr);
344 unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
242 345
243 header = (struct setup_header *)(kernel + setup_hdr_offset); 346 header = (struct setup_header *)(kernel + setup_hdr_offset);
244 setup_sects = header->setup_sects; 347 setup_sects = header->setup_sects;
@@ -285,12 +388,29 @@ void *bzImage64_load(struct kimage *image, char *kernel,
285 388
286 pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr); 389 pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
287 390
288 /* Load Bootparams and cmdline */ 391
392 /*
393 * Load Bootparams and cmdline and space for efi stuff.
394 *
395 * Allocate memory together for multiple data structures so
396 * that they all can go in single area/segment and we don't
397 * have to create separate segment for each. Keeps things
398 * little bit simple
399 */
400 efi_map_sz = efi_get_runtime_map_size();
401 efi_map_sz = ALIGN(efi_map_sz, 16);
289 params_cmdline_sz = sizeof(struct boot_params) + cmdline_len + 402 params_cmdline_sz = sizeof(struct boot_params) + cmdline_len +
290 MAX_ELFCOREHDR_STR_LEN; 403 MAX_ELFCOREHDR_STR_LEN;
291 params = kzalloc(params_cmdline_sz, GFP_KERNEL); 404 params_cmdline_sz = ALIGN(params_cmdline_sz, 16);
405 params_misc_sz = params_cmdline_sz + efi_map_sz +
406 sizeof(struct setup_data) +
407 sizeof(struct efi_setup_data);
408
409 params = kzalloc(params_misc_sz, GFP_KERNEL);
292 if (!params) 410 if (!params)
293 return ERR_PTR(-ENOMEM); 411 return ERR_PTR(-ENOMEM);
412 efi_map_offset = params_cmdline_sz;
413 efi_setup_data_offset = efi_map_offset + efi_map_sz;
294 414
295 /* Copy setup header onto bootparams. Documentation/x86/boot.txt */ 415 /* Copy setup header onto bootparams. Documentation/x86/boot.txt */
296 setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset; 416 setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset;
@@ -298,13 +418,13 @@ void *bzImage64_load(struct kimage *image, char *kernel,
298 /* Is there a limit on setup header size? */ 418 /* Is there a limit on setup header size? */
299 memcpy(&params->hdr, (kernel + setup_hdr_offset), setup_header_size); 419 memcpy(&params->hdr, (kernel + setup_hdr_offset), setup_header_size);
300 420
301 ret = kexec_add_buffer(image, (char *)params, params_cmdline_sz, 421 ret = kexec_add_buffer(image, (char *)params, params_misc_sz,
302 params_cmdline_sz, 16, MIN_BOOTPARAM_ADDR, 422 params_misc_sz, 16, MIN_BOOTPARAM_ADDR,
303 ULONG_MAX, 1, &bootparam_load_addr); 423 ULONG_MAX, 1, &bootparam_load_addr);
304 if (ret) 424 if (ret)
305 goto out_free_params; 425 goto out_free_params;
306 pr_debug("Loaded boot_param and command line at 0x%lx bufsz=0x%lx memsz=0x%lx\n", 426 pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
307 bootparam_load_addr, params_cmdline_sz, params_cmdline_sz); 427 bootparam_load_addr, params_misc_sz, params_misc_sz);
308 428
309 /* Load kernel */ 429 /* Load kernel */
310 kernel_buf = kernel + kern16_size; 430 kernel_buf = kernel + kern16_size;
@@ -365,7 +485,9 @@ void *bzImage64_load(struct kimage *image, char *kernel,
365 if (ret) 485 if (ret)
366 goto out_free_params; 486 goto out_free_params;
367 487
368 ret = setup_boot_parameters(image, params); 488 ret = setup_boot_parameters(image, params, bootparam_load_addr,
489 efi_map_offset, efi_map_sz,
490 efi_setup_data_offset);
369 if (ret) 491 if (ret)
370 goto out_free_params; 492 goto out_free_params;
371 493
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c
index 97cdd16a2169..018c29a26615 100644
--- a/drivers/firmware/efi/runtime-map.c
+++ b/drivers/firmware/efi/runtime-map.c
@@ -138,6 +138,27 @@ add_sysfs_runtime_map_entry(struct kobject *kobj, int nr)
138 return entry; 138 return entry;
139} 139}
140 140
141int efi_get_runtime_map_size(void)
142{
143 return nr_efi_runtime_map * efi_memdesc_size;
144}
145
146int efi_get_runtime_map_desc_size(void)
147{
148 return efi_memdesc_size;
149}
150
151int efi_runtime_map_copy(void *buf, size_t bufsz)
152{
153 size_t sz = efi_get_runtime_map_size();
154
155 if (sz > bufsz)
156 sz = bufsz;
157
158 memcpy(buf, efi_runtime_map, sz);
159 return 0;
160}
161
141void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) 162void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size)
142{ 163{
143 efi_runtime_map = map; 164 efi_runtime_map = map;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index efc681fd5895..45cb4ffdea62 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1156,6 +1156,9 @@ int efivars_sysfs_init(void);
1156#ifdef CONFIG_EFI_RUNTIME_MAP 1156#ifdef CONFIG_EFI_RUNTIME_MAP
1157int efi_runtime_map_init(struct kobject *); 1157int efi_runtime_map_init(struct kobject *);
1158void efi_runtime_map_setup(void *, int, u32); 1158void efi_runtime_map_setup(void *, int, u32);
1159int efi_get_runtime_map_size(void);
1160int efi_get_runtime_map_desc_size(void);
1161int efi_runtime_map_copy(void *buf, size_t bufsz);
1159#else 1162#else
1160static inline int efi_runtime_map_init(struct kobject *kobj) 1163static inline int efi_runtime_map_init(struct kobject *kobj)
1161{ 1164{
@@ -1164,6 +1167,22 @@ static inline int efi_runtime_map_init(struct kobject *kobj)
1164 1167
1165static inline void 1168static inline void
1166efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {} 1169efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {}
1170
1171static inline int efi_get_runtime_map_size(void)
1172{
1173 return 0;
1174}
1175
1176static inline int efi_get_runtime_map_desc_size(void)
1177{
1178 return 0;
1179}
1180
1181static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
1182{
1183 return 0;
1184}
1185
1167#endif 1186#endif
1168 1187
1169/* prototypes shared between arch specific and generic stub code */ 1188/* prototypes shared between arch specific and generic stub code */