aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform/efi
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/platform/efi')
-rw-r--r--arch/x86/platform/efi/Makefile1
-rw-r--r--arch/x86/platform/efi/efi.c127
-rw-r--r--arch/x86/platform/efi/efi_64.c335
-rw-r--r--arch/x86/platform/efi/efi_stub_64.S1
-rw-r--r--arch/x86/platform/efi/efi_thunk_64.S65
5 files changed, 496 insertions, 33 deletions
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index b7b0b35c1981..d51045afcaaf 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o 1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o 2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
3obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o 3obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
4obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index b96ae7918a16..39f5b7bba695 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -588,37 +588,85 @@ static int __init efi_systab_init(void *phys)
588 return 0; 588 return 0;
589} 589}
590 590
591static int __init efi_runtime_init(void) 591static int __init efi_runtime_init32(void)
592{ 592{
593 efi_runtime_services_t *runtime; 593 efi_runtime_services_32_t *runtime;
594
595 runtime = early_ioremap((unsigned long)efi.systab->runtime,
596 sizeof(efi_runtime_services_32_t));
597 if (!runtime) {
598 pr_err("Could not map the runtime service table!\n");
599 return -ENOMEM;
600 }
594 601
595 /* 602 /*
596 * Check out the runtime services table. We need to map 603 * We will only need *early* access to the following two
597 * the runtime services table so that we can grab the physical 604 * EFI runtime services before set_virtual_address_map
598 * address of several of the EFI runtime functions, needed to 605 * is invoked.
599 * set the firmware into virtual mode.
600 */ 606 */
607 efi_phys.get_time = (efi_get_time_t *)
608 (unsigned long)runtime->get_time;
609 efi_phys.set_virtual_address_map =
610 (efi_set_virtual_address_map_t *)
611 (unsigned long)runtime->set_virtual_address_map;
612 /*
613 * Make efi_get_time can be called before entering
614 * virtual mode.
615 */
616 efi.get_time = phys_efi_get_time;
617 early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
618
619 return 0;
620}
621
622static int __init efi_runtime_init64(void)
623{
624 efi_runtime_services_64_t *runtime;
625
601 runtime = early_ioremap((unsigned long)efi.systab->runtime, 626 runtime = early_ioremap((unsigned long)efi.systab->runtime,
602 sizeof(efi_runtime_services_t)); 627 sizeof(efi_runtime_services_64_t));
603 if (!runtime) { 628 if (!runtime) {
604 pr_err("Could not map the runtime service table!\n"); 629 pr_err("Could not map the runtime service table!\n");
605 return -ENOMEM; 630 return -ENOMEM;
606 } 631 }
632
607 /* 633 /*
608 * We will only need *early* access to the following 634 * We will only need *early* access to the following two
609 * two EFI runtime services before set_virtual_address_map 635 * EFI runtime services before set_virtual_address_map
610 * is invoked. 636 * is invoked.
611 */ 637 */
612 efi_phys.get_time = (efi_get_time_t *)runtime->get_time; 638 efi_phys.get_time = (efi_get_time_t *)
639 (unsigned long)runtime->get_time;
613 efi_phys.set_virtual_address_map = 640 efi_phys.set_virtual_address_map =
614 (efi_set_virtual_address_map_t *) 641 (efi_set_virtual_address_map_t *)
615 runtime->set_virtual_address_map; 642 (unsigned long)runtime->set_virtual_address_map;
616 /* 643 /*
617 * Make efi_get_time can be called before entering 644 * Make efi_get_time can be called before entering
618 * virtual mode. 645 * virtual mode.
619 */ 646 */
620 efi.get_time = phys_efi_get_time; 647 efi.get_time = phys_efi_get_time;
621 early_iounmap(runtime, sizeof(efi_runtime_services_t)); 648 early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
649
650 return 0;
651}
652
653static int __init efi_runtime_init(void)
654{
655 int rv;
656
657 /*
658 * Check out the runtime services table. We need to map
659 * the runtime services table so that we can grab the physical
660 * address of several of the EFI runtime functions, needed to
661 * set the firmware into virtual mode.
662 */
663 if (efi_enabled(EFI_64BIT))
664 rv = efi_runtime_init64();
665 else
666 rv = efi_runtime_init32();
667
668 if (rv)
669 return rv;
622 670
623 return 0; 671 return 0;
624} 672}
@@ -841,6 +889,22 @@ void __init old_map_region(efi_memory_desc_t *md)
841 (unsigned long long)md->phys_addr); 889 (unsigned long long)md->phys_addr);
842} 890}
843 891
892static void native_runtime_setup(void)
893{
894 efi.get_time = virt_efi_get_time;
895 efi.set_time = virt_efi_set_time;
896 efi.get_wakeup_time = virt_efi_get_wakeup_time;
897 efi.set_wakeup_time = virt_efi_set_wakeup_time;
898 efi.get_variable = virt_efi_get_variable;
899 efi.get_next_variable = virt_efi_get_next_variable;
900 efi.set_variable = virt_efi_set_variable;
901 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
902 efi.reset_system = virt_efi_reset_system;
903 efi.query_variable_info = virt_efi_query_variable_info;
904 efi.update_capsule = virt_efi_update_capsule;
905 efi.query_capsule_caps = virt_efi_query_capsule_caps;
906}
907
844/* Merge contiguous regions of the same type and attribute */ 908/* Merge contiguous regions of the same type and attribute */
845static void __init efi_merge_regions(void) 909static void __init efi_merge_regions(void)
846{ 910{
@@ -1023,11 +1087,20 @@ void __init efi_enter_virtual_mode(void)
1023 efi_sync_low_kernel_mappings(); 1087 efi_sync_low_kernel_mappings();
1024 1088
1025 if (!efi_setup) { 1089 if (!efi_setup) {
1026 status = phys_efi_set_virtual_address_map( 1090 if (efi_is_native()) {
1027 memmap.desc_size * count, 1091 status = phys_efi_set_virtual_address_map(
1028 memmap.desc_size, 1092 memmap.desc_size * count,
1029 memmap.desc_version, 1093 memmap.desc_size,
1030 (efi_memory_desc_t *)__pa(new_memmap)); 1094 memmap.desc_version,
1095 (efi_memory_desc_t *)__pa(new_memmap));
1096 } else {
1097 status = efi_thunk_set_virtual_address_map(
1098 efi_phys.set_virtual_address_map,
1099 memmap.desc_size * count,
1100 memmap.desc_size,
1101 memmap.desc_version,
1102 (efi_memory_desc_t *)__pa(new_memmap));
1103 }
1031 1104
1032 if (status != EFI_SUCCESS) { 1105 if (status != EFI_SUCCESS) {
1033 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n", 1106 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
@@ -1043,19 +1116,13 @@ void __init efi_enter_virtual_mode(void)
1043 * Call EFI services through wrapper functions. 1116 * Call EFI services through wrapper functions.
1044 */ 1117 */
1045 efi.runtime_version = efi_systab.hdr.revision; 1118 efi.runtime_version = efi_systab.hdr.revision;
1046 efi.get_time = virt_efi_get_time; 1119
1047 efi.set_time = virt_efi_set_time; 1120 if (efi_is_native())
1048 efi.get_wakeup_time = virt_efi_get_wakeup_time; 1121 native_runtime_setup();
1049 efi.set_wakeup_time = virt_efi_set_wakeup_time; 1122 else
1050 efi.get_variable = virt_efi_get_variable; 1123 efi_thunk_runtime_setup();
1051 efi.get_next_variable = virt_efi_get_next_variable; 1124
1052 efi.set_variable = virt_efi_set_variable;
1053 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
1054 efi.reset_system = virt_efi_reset_system;
1055 efi.set_virtual_address_map = NULL; 1125 efi.set_virtual_address_map = NULL;
1056 efi.query_variable_info = virt_efi_query_variable_info;
1057 efi.update_capsule = virt_efi_update_capsule;
1058 efi.query_capsule_caps = virt_efi_query_capsule_caps;
1059 1126
1060 efi_runtime_mkexec(); 1127 efi_runtime_mkexec();
1061 1128
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 0c2a234fef1e..12112ab4fd40 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -39,6 +39,7 @@
39#include <asm/cacheflush.h> 39#include <asm/cacheflush.h>
40#include <asm/fixmap.h> 40#include <asm/fixmap.h>
41#include <asm/realmode.h> 41#include <asm/realmode.h>
42#include <asm/time.h>
42 43
43static pgd_t *save_pgd __initdata; 44static pgd_t *save_pgd __initdata;
44static unsigned long efi_flags __initdata; 45static unsigned long efi_flags __initdata;
@@ -58,7 +59,8 @@ struct efi_scratch {
58 u64 prev_cr3; 59 u64 prev_cr3;
59 pgd_t *efi_pgt; 60 pgd_t *efi_pgt;
60 bool use_pgd; 61 bool use_pgd;
61}; 62 u64 phys_stack;
63} __packed;
62 64
63static void __init early_code_mapping_set_exec(int executable) 65static void __init early_code_mapping_set_exec(int executable)
64{ 66{
@@ -139,10 +141,40 @@ void efi_sync_low_kernel_mappings(void)
139 141
140void efi_setup_page_tables(void) 142void efi_setup_page_tables(void)
141{ 143{
144 unsigned long text;
145 unsigned npages;
146 struct page *page;
147
142 efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd; 148 efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd;
143 149
144 if (!efi_enabled(EFI_OLD_MEMMAP)) 150 if (efi_enabled(EFI_OLD_MEMMAP))
145 efi_scratch.use_pgd = true; 151 return;
152
153 efi_scratch.use_pgd = true;
154
155 /*
156 * When making calls to the firmware everything needs to be 1:1
157 * mapped and addressable with 32-bit pointers. Map the kernel
158 * text and allocate a new stack because we can't rely on the
159 * stack pointer being < 4GB.
160 */
161 if (!IS_ENABLED(CONFIG_EFI_MIXED))
162 return;
163
164 page = alloc_page(GFP_KERNEL|__GFP_DMA32);
165 if (!page)
166 panic("Unable to allocate EFI runtime stack < 4GB\n");
167
168 efi_scratch.phys_stack = virt_to_phys(page_address(page));
169 efi_scratch.phys_stack += PAGE_SIZE; /* stack grows down */
170
171 npages = (_end - _text) >> PAGE_SHIFT;
172 text = __pa(_text);
173
174 if (kernel_map_pages_in_pgd(__va(efi_scratch.efi_pgt),
175 text >> PAGE_SHIFT, text, npages, 0)) {
176 pr_err("Failed to map kernel text 1:1\n");
177 }
146} 178}
147 179
148static void __init __map_region(efi_memory_desc_t *md, u64 va) 180static void __init __map_region(efi_memory_desc_t *md, u64 va)
@@ -173,6 +205,16 @@ void __init efi_map_region(efi_memory_desc_t *md)
173 */ 205 */
174 __map_region(md, md->phys_addr); 206 __map_region(md, md->phys_addr);
175 207
208 /*
209 * Enforce the 1:1 mapping as the default virtual address when
210 * booting in EFI mixed mode, because even though we may be
211 * running a 64-bit kernel, the firmware may only be 32-bit.
212 */
213 if (!efi_is_native () && IS_ENABLED(CONFIG_EFI_MIXED)) {
214 md->virt_addr = md->phys_addr;
215 return;
216 }
217
176 efi_va -= size; 218 efi_va -= size;
177 219
178 /* Is PA 2M-aligned? */ 220 /* Is PA 2M-aligned? */
@@ -242,3 +284,290 @@ void __init efi_runtime_mkexec(void)
242 if (__supported_pte_mask & _PAGE_NX) 284 if (__supported_pte_mask & _PAGE_NX)
243 runtime_code_page_mkexec(); 285 runtime_code_page_mkexec();
244} 286}
287
288#ifdef CONFIG_EFI_MIXED
289extern efi_status_t efi64_thunk(u32, ...);
290
291#define runtime_service32(func) \
292({ \
293 u32 table = (u32)(unsigned long)efi.systab; \
294 u32 *rt, *___f; \
295 \
296 rt = (u32 *)(table + offsetof(efi_system_table_32_t, runtime)); \
297 ___f = (u32 *)(*rt + offsetof(efi_runtime_services_32_t, func)); \
298 *___f; \
299})
300
301/*
302 * Switch to the EFI page tables early so that we can access the 1:1
303 * runtime services mappings which are not mapped in any other page
304 * tables. This function must be called before runtime_service32().
305 *
306 * Also, disable interrupts because the IDT points to 64-bit handlers,
307 * which aren't going to function correctly when we switch to 32-bit.
308 */
309#define efi_thunk(f, ...) \
310({ \
311 efi_status_t __s; \
312 unsigned long flags; \
313 u32 func; \
314 \
315 efi_sync_low_kernel_mappings(); \
316 local_irq_save(flags); \
317 \
318 efi_scratch.prev_cr3 = read_cr3(); \
319 write_cr3((unsigned long)efi_scratch.efi_pgt); \
320 __flush_tlb_all(); \
321 \
322 func = runtime_service32(f); \
323 __s = efi64_thunk(func, __VA_ARGS__); \
324 \
325 write_cr3(efi_scratch.prev_cr3); \
326 __flush_tlb_all(); \
327 local_irq_restore(flags); \
328 \
329 __s; \
330})
331
332efi_status_t efi_thunk_set_virtual_address_map(
333 void *phys_set_virtual_address_map,
334 unsigned long memory_map_size,
335 unsigned long descriptor_size,
336 u32 descriptor_version,
337 efi_memory_desc_t *virtual_map)
338{
339 efi_status_t status;
340 unsigned long flags;
341 u32 func;
342
343 efi_sync_low_kernel_mappings();
344 local_irq_save(flags);
345
346 efi_scratch.prev_cr3 = read_cr3();
347 write_cr3((unsigned long)efi_scratch.efi_pgt);
348 __flush_tlb_all();
349
350 func = (u32)(unsigned long)phys_set_virtual_address_map;
351 status = efi64_thunk(func, memory_map_size, descriptor_size,
352 descriptor_version, virtual_map);
353
354 write_cr3(efi_scratch.prev_cr3);
355 __flush_tlb_all();
356 local_irq_restore(flags);
357
358 return status;
359}
360
361static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
362{
363 efi_status_t status;
364 u32 phys_tm, phys_tc;
365
366 spin_lock(&rtc_lock);
367
368 phys_tm = virt_to_phys(tm);
369 phys_tc = virt_to_phys(tc);
370
371 status = efi_thunk(get_time, phys_tm, phys_tc);
372
373 spin_unlock(&rtc_lock);
374
375 return status;
376}
377
378static efi_status_t efi_thunk_set_time(efi_time_t *tm)
379{
380 efi_status_t status;
381 u32 phys_tm;
382
383 spin_lock(&rtc_lock);
384
385 phys_tm = virt_to_phys(tm);
386
387 status = efi_thunk(set_time, phys_tm);
388
389 spin_unlock(&rtc_lock);
390
391 return status;
392}
393
394static efi_status_t
395efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
396 efi_time_t *tm)
397{
398 efi_status_t status;
399 u32 phys_enabled, phys_pending, phys_tm;
400
401 spin_lock(&rtc_lock);
402
403 phys_enabled = virt_to_phys(enabled);
404 phys_pending = virt_to_phys(pending);
405 phys_tm = virt_to_phys(tm);
406
407 status = efi_thunk(get_wakeup_time, phys_enabled,
408 phys_pending, phys_tm);
409
410 spin_unlock(&rtc_lock);
411
412 return status;
413}
414
415static efi_status_t
416efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
417{
418 efi_status_t status;
419 u32 phys_tm;
420
421 spin_lock(&rtc_lock);
422
423 phys_tm = virt_to_phys(tm);
424
425 status = efi_thunk(set_wakeup_time, enabled, phys_tm);
426
427 spin_unlock(&rtc_lock);
428
429 return status;
430}
431
432
433static efi_status_t
434efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
435 u32 *attr, unsigned long *data_size, void *data)
436{
437 efi_status_t status;
438 u32 phys_name, phys_vendor, phys_attr;
439 u32 phys_data_size, phys_data;
440
441 phys_data_size = virt_to_phys(data_size);
442 phys_vendor = virt_to_phys(vendor);
443 phys_name = virt_to_phys(name);
444 phys_attr = virt_to_phys(attr);
445 phys_data = virt_to_phys(data);
446
447 status = efi_thunk(get_variable, phys_name, phys_vendor,
448 phys_attr, phys_data_size, phys_data);
449
450 return status;
451}
452
453static efi_status_t
454efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
455 u32 attr, unsigned long data_size, void *data)
456{
457 u32 phys_name, phys_vendor, phys_data;
458 efi_status_t status;
459
460 phys_name = virt_to_phys(name);
461 phys_vendor = virt_to_phys(vendor);
462 phys_data = virt_to_phys(data);
463
464 /* If data_size is > sizeof(u32) we've got problems */
465 status = efi_thunk(set_variable, phys_name, phys_vendor,
466 attr, data_size, phys_data);
467
468 return status;
469}
470
471static efi_status_t
472efi_thunk_get_next_variable(unsigned long *name_size,
473 efi_char16_t *name,
474 efi_guid_t *vendor)
475{
476 efi_status_t status;
477 u32 phys_name_size, phys_name, phys_vendor;
478
479 phys_name_size = virt_to_phys(name_size);
480 phys_vendor = virt_to_phys(vendor);
481 phys_name = virt_to_phys(name);
482
483 status = efi_thunk(get_next_variable, phys_name_size,
484 phys_name, phys_vendor);
485
486 return status;
487}
488
489static efi_status_t
490efi_thunk_get_next_high_mono_count(u32 *count)
491{
492 efi_status_t status;
493 u32 phys_count;
494
495 phys_count = virt_to_phys(count);
496 status = efi_thunk(get_next_high_mono_count, phys_count);
497
498 return status;
499}
500
501static void
502efi_thunk_reset_system(int reset_type, efi_status_t status,
503 unsigned long data_size, efi_char16_t *data)
504{
505 u32 phys_data;
506
507 phys_data = virt_to_phys(data);
508
509 efi_thunk(reset_system, reset_type, status, data_size, phys_data);
510}
511
512static efi_status_t
513efi_thunk_update_capsule(efi_capsule_header_t **capsules,
514 unsigned long count, unsigned long sg_list)
515{
516 /*
517 * To properly support this function we would need to repackage
518 * 'capsules' because the firmware doesn't understand 64-bit
519 * pointers.
520 */
521 return EFI_UNSUPPORTED;
522}
523
524static efi_status_t
525efi_thunk_query_variable_info(u32 attr, u64 *storage_space,
526 u64 *remaining_space,
527 u64 *max_variable_size)
528{
529 efi_status_t status;
530 u32 phys_storage, phys_remaining, phys_max;
531
532 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
533 return EFI_UNSUPPORTED;
534
535 phys_storage = virt_to_phys(storage_space);
536 phys_remaining = virt_to_phys(remaining_space);
537 phys_max = virt_to_phys(max_variable_size);
538
539 status = efi_thunk(query_variable_info, phys_storage,
540 phys_remaining, phys_max);
541
542 return status;
543}
544
545static efi_status_t
546efi_thunk_query_capsule_caps(efi_capsule_header_t **capsules,
547 unsigned long count, u64 *max_size,
548 int *reset_type)
549{
550 /*
551 * To properly support this function we would need to repackage
552 * 'capsules' because the firmware doesn't understand 64-bit
553 * pointers.
554 */
555 return EFI_UNSUPPORTED;
556}
557
558void efi_thunk_runtime_setup(void)
559{
560 efi.get_time = efi_thunk_get_time;
561 efi.set_time = efi_thunk_set_time;
562 efi.get_wakeup_time = efi_thunk_get_wakeup_time;
563 efi.set_wakeup_time = efi_thunk_set_wakeup_time;
564 efi.get_variable = efi_thunk_get_variable;
565 efi.get_next_variable = efi_thunk_get_next_variable;
566 efi.set_variable = efi_thunk_set_variable;
567 efi.get_next_high_mono_count = efi_thunk_get_next_high_mono_count;
568 efi.reset_system = efi_thunk_reset_system;
569 efi.query_variable_info = efi_thunk_query_variable_info;
570 efi.update_capsule = efi_thunk_update_capsule;
571 efi.query_capsule_caps = efi_thunk_query_capsule_caps;
572}
573#endif /* CONFIG_EFI_MIXED */
diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S
index a790d69cc85e..e811514beeac 100644
--- a/arch/x86/platform/efi/efi_stub_64.S
+++ b/arch/x86/platform/efi/efi_stub_64.S
@@ -318,3 +318,4 @@ efi_gdt64_end:
318ENTRY(efi_scratch) 318ENTRY(efi_scratch)
319 .fill 3,8,0 319 .fill 3,8,0
320 .byte 0 320 .byte 0
321 .quad 0
diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S
new file mode 100644
index 000000000000..8806fa73e6e6
--- /dev/null
+++ b/arch/x86/platform/efi/efi_thunk_64.S
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2014 Intel Corporation; author Matt Fleming
3 */
4
5#include <linux/linkage.h>
6#include <asm/page_types.h>
7
8 .text
9 .code64
10ENTRY(efi64_thunk)
11 push %rbp
12 push %rbx
13
14 /*
15 * Switch to 1:1 mapped 32-bit stack pointer.
16 */
17 movq %rsp, efi_saved_sp(%rip)
18 movq efi_scratch+25(%rip), %rsp
19
20 /*
21 * Calculate the physical address of the kernel text.
22 */
23 movq $__START_KERNEL_map, %rax
24 subq phys_base(%rip), %rax
25
26 /*
27 * Push some physical addresses onto the stack. This is easier
28 * to do now in a code64 section while the assembler can address
29 * 64-bit values. Note that all the addresses on the stack are
30 * 32-bit.
31 */
32 subq $16, %rsp
33 leaq efi_exit32(%rip), %rbx
34 subq %rax, %rbx
35 movl %ebx, 8(%rsp)
36 leaq efi_gdt64(%rip), %rbx
37 subq %rax, %rbx
38 movl %ebx, 2(%ebx)
39 movl %ebx, 4(%rsp)
40 leaq efi_gdt32(%rip), %rbx
41 subq %rax, %rbx
42 movl %ebx, 2(%ebx)
43 movl %ebx, (%rsp)
44
45 leaq __efi64_thunk(%rip), %rbx
46 subq %rax, %rbx
47 call *%rbx
48
49 movq efi_saved_sp(%rip), %rsp
50 pop %rbx
51 pop %rbp
52 retq
53ENDPROC(efi64_thunk)
54
55 .data
56efi_gdt32:
57 .word efi_gdt32_end - efi_gdt32
58 .long 0 /* Filled out above */
59 .word 0
60 .quad 0x0000000000000000 /* NULL descriptor */
61 .quad 0x00cf9a000000ffff /* __KERNEL_CS */
62 .quad 0x00cf93000000ffff /* __KERNEL_DS */
63efi_gdt32_end:
64
65efi_saved_sp: .quad 0