diff options
author | Frédéric Riss <frederic.riss@gmail.com> | 2007-01-30 15:41:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-04 13:27:10 -0500 |
commit | 40c373cc3af9720d1cec0e32c3da26b1d220a95b (patch) | |
tree | adec525ed9e80a3b923302a273b7524c231d614d /arch | |
parent | 886ae1fa1380309d91cdb7e67bd4bf71e053c1d5 (diff) |
[PATCH] EFI x86: pass firmware call parameters on the stack
When calling into the EFI firmware, the parameters need to be passed on
the stack. The recent change to use -mregparm=3 breaks x86 EFI support.
This patch is needed to allow the new Intel-based Macs to suspend to ram
(efi.get_time is called during the suspend phase).
Signed-off-by: Frederic Riss <frederic.riss@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/efi.c | 89 |
1 files changed, 73 insertions, 16 deletions
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index b92c7f0a358a..8f9c624ace6f 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c | |||
@@ -473,6 +473,70 @@ static inline void __init check_range_for_systab(efi_memory_desc_t *md) | |||
473 | } | 473 | } |
474 | 474 | ||
475 | /* | 475 | /* |
476 | * Wrap all the virtual calls in a way that forces the parameters on the stack. | ||
477 | */ | ||
478 | |||
479 | #define efi_call_virt(f, args...) \ | ||
480 | ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args) | ||
481 | |||
482 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | ||
483 | { | ||
484 | return efi_call_virt(get_time, tm, tc); | ||
485 | } | ||
486 | |||
487 | static efi_status_t virt_efi_set_time (efi_time_t *tm) | ||
488 | { | ||
489 | return efi_call_virt(set_time, tm); | ||
490 | } | ||
491 | |||
492 | static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled, | ||
493 | efi_bool_t *pending, | ||
494 | efi_time_t *tm) | ||
495 | { | ||
496 | return efi_call_virt(get_wakeup_time, enabled, pending, tm); | ||
497 | } | ||
498 | |||
499 | static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled, | ||
500 | efi_time_t *tm) | ||
501 | { | ||
502 | return efi_call_virt(set_wakeup_time, enabled, tm); | ||
503 | } | ||
504 | |||
505 | static efi_status_t virt_efi_get_variable (efi_char16_t *name, | ||
506 | efi_guid_t *vendor, u32 *attr, | ||
507 | unsigned long *data_size, void *data) | ||
508 | { | ||
509 | return efi_call_virt(get_variable, name, vendor, attr, data_size, data); | ||
510 | } | ||
511 | |||
512 | static efi_status_t virt_efi_get_next_variable (unsigned long *name_size, | ||
513 | efi_char16_t *name, | ||
514 | efi_guid_t *vendor) | ||
515 | { | ||
516 | return efi_call_virt(get_next_variable, name_size, name, vendor); | ||
517 | } | ||
518 | |||
519 | static efi_status_t virt_efi_set_variable (efi_char16_t *name, | ||
520 | efi_guid_t *vendor, | ||
521 | unsigned long attr, | ||
522 | unsigned long data_size, void *data) | ||
523 | { | ||
524 | return efi_call_virt(set_variable, name, vendor, attr, data_size, data); | ||
525 | } | ||
526 | |||
527 | static efi_status_t virt_efi_get_next_high_mono_count (u32 *count) | ||
528 | { | ||
529 | return efi_call_virt(get_next_high_mono_count, count); | ||
530 | } | ||
531 | |||
532 | static void virt_efi_reset_system (int reset_type, efi_status_t status, | ||
533 | unsigned long data_size, | ||
534 | efi_char16_t *data) | ||
535 | { | ||
536 | efi_call_virt(reset_system, reset_type, status, data_size, data); | ||
537 | } | ||
538 | |||
539 | /* | ||
476 | * This function will switch the EFI runtime services to virtual mode. | 540 | * This function will switch the EFI runtime services to virtual mode. |
477 | * Essentially, look through the EFI memmap and map every region that | 541 | * Essentially, look through the EFI memmap and map every region that |
478 | * has the runtime attribute bit set in its memory descriptor and update | 542 | * has the runtime attribute bit set in its memory descriptor and update |
@@ -525,22 +589,15 @@ void __init efi_enter_virtual_mode(void) | |||
525 | * pointers in the runtime service table to the new virtual addresses. | 589 | * pointers in the runtime service table to the new virtual addresses. |
526 | */ | 590 | */ |
527 | 591 | ||
528 | efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time; | 592 | efi.get_time = virt_efi_get_time; |
529 | efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time; | 593 | efi.set_time = virt_efi_set_time; |
530 | efi.get_wakeup_time = (efi_get_wakeup_time_t *) | 594 | efi.get_wakeup_time = virt_efi_get_wakeup_time; |
531 | efi.systab->runtime->get_wakeup_time; | 595 | efi.set_wakeup_time = virt_efi_set_wakeup_time; |
532 | efi.set_wakeup_time = (efi_set_wakeup_time_t *) | 596 | efi.get_variable = virt_efi_get_variable; |
533 | efi.systab->runtime->set_wakeup_time; | 597 | efi.get_next_variable = virt_efi_get_next_variable; |
534 | efi.get_variable = (efi_get_variable_t *) | 598 | efi.set_variable = virt_efi_set_variable; |
535 | efi.systab->runtime->get_variable; | 599 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; |
536 | efi.get_next_variable = (efi_get_next_variable_t *) | 600 | efi.reset_system = virt_efi_reset_system; |
537 | efi.systab->runtime->get_next_variable; | ||
538 | efi.set_variable = (efi_set_variable_t *) | ||
539 | efi.systab->runtime->set_variable; | ||
540 | efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *) | ||
541 | efi.systab->runtime->get_next_high_mono_count; | ||
542 | efi.reset_system = (efi_reset_system_t *) | ||
543 | efi.systab->runtime->reset_system; | ||
544 | } | 601 | } |
545 | 602 | ||
546 | void __init | 603 | void __init |