diff --git a/xen/arch/x86/efi/boot.c b/xen/arch/x86/efi/boot.c index 50ea3c8ee3..9a959e306d 100644 --- a/xen/arch/x86/efi/boot.c +++ b/xen/arch/x86/efi/boot.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -1149,6 +1150,53 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) for( ; ; ); /* not reached */ } +static __init void copy_mapping(unsigned long mfn, unsigned long end, + bool_t (*is_valid)(unsigned long smfn, + unsigned long emfn)) +{ + unsigned long next; + + for ( ; mfn < end; mfn = next ) + { + l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)]; + l3_pgentry_t *l3src, *l3dst; + unsigned long va = (unsigned long)mfn_to_virt(mfn); + + next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)); + if ( !is_valid(mfn, min(next, end)) ) + continue; + if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) + { + l3dst = alloc_xen_pagetable(); + BUG_ON(!l3dst); + clear_page(l3dst); + efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] = + l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR); + } + else + l3dst = l4e_to_l3e(l4e); + l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]); + l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)]; + } +} + +static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn) +{ + unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1; + + return !(smfn & pfn_hole_mask) && + find_next_bit(pdx_group_valid, sz, + pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz; +} + +static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn) +{ + return 1; +} + +#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \ + (EFI_PAGE_SHIFT + BITS_PER_LONG - 32)) + void __init efi_init_memory(void) { unsigned int i; @@ -1169,11 +1217,11 @@ void __init efi_init_memory(void) if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) ) continue; + desc->VirtualStart = INVALID_VIRTUAL_ADDRESS; + smfn = PFN_DOWN(desc->PhysicalStart); emfn = PFN_UP(desc->PhysicalStart + len); - desc->VirtualStart = 0xBAAADUL << (EFI_PAGE_SHIFT + BITS_PER_LONG - 32); - if ( desc->Attribute & EFI_MEMORY_WB ) /* nothing */; else if ( desc->Attribute & EFI_MEMORY_WT ) @@ -1217,5 +1265,34 @@ void __init efi_init_memory(void) #if 0 /* Incompatible with kexec. */ efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size, mdesc_ver, efi_memmap); +#else + /* Set up 1:1 page tables to do runtime calls in "physical" mode. */ + efi_l4_pgtable = alloc_xen_pagetable(); + BUG_ON(!efi_l4_pgtable); + clear_page(efi_l4_pgtable); + + copy_mapping(0, max_page, ram_range_valid); + + /* Insert non-RAM runtime mappings. */ + for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) + { + const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; + + if ( desc->Attribute & EFI_MEMORY_RUNTIME ) + { + if ( desc->VirtualStart != INVALID_VIRTUAL_ADDRESS ) + copy_mapping(PFN_DOWN(desc->PhysicalStart), + PFN_UP(desc->PhysicalStart + + (desc->NumberOfPages << EFI_PAGE_SHIFT)), + rt_range_valid); + else + /* XXX */; + } + } + + /* Insert Xen mappings. */ + for ( i = l4_table_offset(HYPERVISOR_VIRT_START); + i < l4_table_offset(HYPERVISOR_VIRT_END); ++i ) + efi_l4_pgtable[i] = idle_pg_table[i]; #endif } diff --git a/xen/arch/x86/efi/compat.c b/xen/arch/x86/efi/compat.c index 4277f51f9f..7cc6279b8f 100644 --- a/xen/arch/x86/efi/compat.c +++ b/xen/arch/x86/efi/compat.c @@ -4,13 +4,27 @@ #define efi_get_info efi_compat_get_info #define xenpf_efi_info compat_pf_efi_info +#define efi_runtime_call efi_compat_runtime_call +#define xenpf_efi_runtime_call compat_pf_efi_runtime_call + +#define xenpf_efi_guid compat_pf_efi_guid +#define xenpf_efi_time compat_pf_efi_time + #define COMPAT #undef DEFINE_XEN_GUEST_HANDLE #define DEFINE_XEN_GUEST_HANDLE DEFINE_COMPAT_HANDLE +#undef XEN_GUEST_HANDLE +#define XEN_GUEST_HANDLE COMPAT_HANDLE #undef guest_handle_okay #define guest_handle_okay compat_handle_okay #undef guest_handle_cast #define guest_handle_cast compat_handle_cast +#undef __copy_from_guest +#define __copy_from_guest __copy_from_compat +#undef copy_from_guest_offset +#define copy_from_guest_offset copy_from_compat_offset +#undef copy_to_guest +#define copy_to_guest copy_to_compat #undef __copy_to_guest_offset #define __copy_to_guest_offset __copy_to_compat_offset #include "runtime.c" diff --git a/xen/arch/x86/efi/efi.h b/xen/arch/x86/efi/efi.h index e7673ee910..0a42a463a9 100644 --- a/xen/arch/x86/efi/efi.h +++ b/xen/arch/x86/efi/efi.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include extern unsigned int efi_num_ct; extern EFI_CONFIGURATION_TABLE *efi_ct; @@ -16,3 +18,8 @@ extern EFI_RUNTIME_SERVICES *efi_rs; extern UINTN efi_memmap_size, efi_mdesc_size; extern void *efi_memmap; + +extern l4_pgentry_t *efi_l4_pgtable; + +unsigned long efi_rs_enter(void); +void efi_rs_leave(unsigned long); diff --git a/xen/arch/x86/efi/runtime.c b/xen/arch/x86/efi/runtime.c index 5b98d0c9df..6f4e4de77b 100644 --- a/xen/arch/x86/efi/runtime.c +++ b/xen/arch/x86/efi/runtime.c @@ -2,6 +2,7 @@ #include #include #include +#include DEFINE_XEN_GUEST_HANDLE(CHAR16); @@ -19,6 +20,7 @@ unsigned int __read_mostly efi_fw_revision; const CHAR16 *__read_mostly efi_fw_vendor; EFI_RUNTIME_SERVICES *__read_mostly efi_rs; +static DEFINE_SPINLOCK(efi_rs_lock); UINTN __read_mostly efi_memmap_size; UINTN __read_mostly efi_mdesc_size; @@ -30,6 +32,68 @@ struct efi __read_mostly efi = { .smbios = EFI_INVALID_TABLE_ADDR, }; +l4_pgentry_t *__read_mostly efi_l4_pgtable; + +unsigned long efi_rs_enter(void) +{ + unsigned long cr3 = read_cr3(); + + spin_lock(&efi_rs_lock); + + /* prevent fixup_page_fault() from doing anything */ + irq_enter(); + + write_cr3(virt_to_maddr(efi_l4_pgtable)); + + return cr3; +} + +void efi_rs_leave(unsigned long cr3) +{ + write_cr3(cr3); + irq_exit(); + spin_unlock(&efi_rs_lock); +} + +unsigned long efi_get_time(void) +{ + EFI_TIME time; + EFI_STATUS status; + unsigned long cr3 = efi_rs_enter(); + + status = efi_rs->GetTime(&time, NULL); + efi_rs_leave(cr3); + + if ( EFI_ERROR(status) ) + return 0; + + return mktime(time.Year, time.Month, time.Day, + time.Hour, time.Minute, time.Second); +} + +void efi_halt_system(void) +{ + EFI_STATUS status; + unsigned long cr3 = efi_rs_enter(); + + status = efi_rs->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + efi_rs_leave(cr3); + + printk(XENLOG_WARNING "EFI: could not halt system (%#lx)\n", status); +} + +void efi_reset_system(bool_t warm) +{ + EFI_STATUS status; + unsigned long cr3 = efi_rs_enter(); + + status = efi_rs->ResetSystem(warm ? EfiResetWarm : EfiResetCold, + EFI_SUCCESS, 0, NULL); + efi_rs_leave(cr3); + + printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status); +} + #endif int efi_get_info(uint32_t idx, union xenpf_efi_info *info) @@ -86,3 +150,267 @@ int efi_get_info(uint32_t idx, union xenpf_efi_info *info) return 0; } + +static long gwstrlen(XEN_GUEST_HANDLE(CHAR16) str) +{ + unsigned long len; + + for ( len = 0; ; ++len ) + { + CHAR16 c; + + if ( copy_from_guest_offset(&c, str, len, 1) ) + return -EFAULT; + if ( !c ) + break; + } + + return len; +} + +static inline EFI_TIME *cast_time(struct xenpf_efi_time *time) +{ +#define chk_fld(F, f) \ + BUILD_BUG_ON(sizeof(cast_time(NULL)->F) != sizeof(time->f) || \ + offsetof(EFI_TIME, F) != offsetof(struct xenpf_efi_time, f)) + chk_fld(Year, year); + chk_fld(Month, month); + chk_fld(Day, day); + chk_fld(Hour, hour); + chk_fld(Minute, min); + chk_fld(Second, sec); + chk_fld(Nanosecond, ns); + chk_fld(TimeZone, tz); + chk_fld(Daylight, daylight); +#undef chk_fld + return (void *)time; +} + +static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid) +{ +#define chk_fld(n) \ + BUILD_BUG_ON(sizeof(cast_guid(NULL)->Data##n) != sizeof(guid->data##n) || \ + offsetof(EFI_GUID, Data##n) != \ + offsetof(struct xenpf_efi_guid, data##n)) + chk_fld(1); + chk_fld(2); + chk_fld(3); + chk_fld(4); +#undef chk_fld + return (void *)guid; +} + +int efi_runtime_call(struct xenpf_efi_runtime_call *op) +{ + unsigned long cr3; + EFI_STATUS status = EFI_NOT_STARTED; + int rc = 0; + + switch ( op->function ) + { + case XEN_EFI_get_time: + { + EFI_TIME_CAPABILITIES caps; + + if ( op->misc ) + return -EINVAL; + + cr3 = efi_rs_enter(); + status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps); + efi_rs_leave(cr3); + + if ( !EFI_ERROR(status) ) + { + op->u.get_time.resolution = caps.Resolution; + op->u.get_time.accuracy = caps.Accuracy; + if ( caps.SetsToZero ) + op->misc = XEN_EFI_GET_TIME_SET_CLEARS_NS; + } + } + break; + + case XEN_EFI_set_time: + if ( op->misc ) + return -EINVAL; + + cr3 = efi_rs_enter(); + status = efi_rs->SetTime(cast_time(&op->u.set_time)); + efi_rs_leave(cr3); + break; + + case XEN_EFI_get_wakeup_time: + { + BOOLEAN enabled, pending; + + if ( op->misc ) + return -EINVAL; + + cr3 = efi_rs_enter(); + status = efi_rs->GetWakeupTime(&enabled, &pending, + cast_time(&op->u.get_wakeup_time)); + efi_rs_leave(cr3); + + if ( !EFI_ERROR(status) ) + { + if ( enabled ) + op->misc |= XEN_EFI_GET_WAKEUP_TIME_ENABLED; + if ( pending ) + op->misc |= XEN_EFI_GET_WAKEUP_TIME_PENDING; + } + } + break; + + case XEN_EFI_set_wakeup_time: + if ( op->misc & ~(XEN_EFI_SET_WAKEUP_TIME_ENABLE | + XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ) + return -EINVAL; + + cr3 = efi_rs_enter(); + status = efi_rs->SetWakeupTime(!!(op->misc & + XEN_EFI_SET_WAKEUP_TIME_ENABLE), + (op->misc & + XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ? + NULL : + cast_time(&op->u.set_wakeup_time)); + efi_rs_leave(cr3); + + op->misc = 0; + break; + + case XEN_EFI_get_next_high_monotonic_count: + if ( op->misc ) + return -EINVAL; + + cr3 = efi_rs_enter(); + status = efi_rs->GetNextHighMonotonicCount(&op->misc); + efi_rs_leave(cr3); + break; + + case XEN_EFI_get_variable: + { + CHAR16 *name; + long len; + unsigned char *data; + UINTN size; + + if ( op->misc ) + return -EINVAL; + + len = gwstrlen(guest_handle_cast(op->u.get_variable.name, CHAR16)); + if ( len < 0 ) + return len; + name = xmalloc_array(CHAR16, ++len); + if ( !name ) + return -ENOMEM; + __copy_from_guest(name, op->u.get_variable.name, len); + + size = op->u.get_variable.size; + if ( size ) + { + data = xmalloc_bytes(size); + if ( !data ) + { + xfree(name); + return -ENOMEM; + } + } + else + data = NULL; + + cr3 = efi_rs_enter(); + status = efi_rs->GetVariable( + name, cast_guid(&op->u.get_variable.vendor_guid), + &op->misc, &size, data); + efi_rs_leave(cr3); + + if ( !EFI_ERROR(status) && + copy_to_guest(op->u.get_variable.data, data, size) ) + rc = -EFAULT; + op->u.get_variable.size = size; + + xfree(data); + xfree(name); + } + break; + + case XEN_EFI_set_variable: + { + CHAR16 *name; + long len; + unsigned char *data; + + if ( op->misc ) + return -EINVAL; + + len = gwstrlen(guest_handle_cast(op->u.set_variable.name, CHAR16)); + if ( len < 0 ) + return len; + name = xmalloc_array(CHAR16, ++len); + if ( !name ) + return -ENOMEM; + __copy_from_guest(name, op->u.set_variable.name, len); + + data = xmalloc_bytes(op->u.set_variable.size); + if ( !data ) + rc = -ENOMEM; + else if ( copy_from_guest(data, op->u.set_variable.data, + op->u.set_variable.size) ) + rc = -EFAULT; + else + { + cr3 = efi_rs_enter(); + status = efi_rs->SetVariable( + name, cast_guid(&op->u.set_variable.vendor_guid), + op->misc, op->u.set_variable.size, data); + efi_rs_leave(cr3); + } + + xfree(data); + xfree(name); + } + break; + + case XEN_EFI_get_next_variable_name: + { + union { + CHAR16 *str; + unsigned char *raw; + } name; + UINTN size; + + if ( op->misc ) + return -EINVAL; + + size = op->u.get_next_variable_name.size; + name.raw = xmalloc_bytes(size); + if ( !name.raw ) + return -ENOMEM; + copy_from_guest(name.raw, op->u.get_next_variable_name.name, size); + + cr3 = efi_rs_enter(); + status = efi_rs->GetNextVariableName( + &size, name.str, + cast_guid(&op->u.get_next_variable_name.vendor_guid)); + efi_rs_leave(cr3); + + if ( !EFI_ERROR(status) && + copy_to_guest(op->u.get_next_variable_name.name, name.raw, size) ) + rc = -EFAULT; + op->u.get_next_variable_name.size = size; + + xfree(name.raw); + } + break; + + default: + return -ENOSYS; + } + +#ifndef COMPAT + op->status = status; +#else + op->status = (status & 0x3fffffff) | (status >> 62); +#endif + + return rc; +} diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c index 12289938d1..1520bae6e3 100644 --- a/xen/arch/x86/efi/stub.c +++ b/xen/arch/x86/efi/stub.c @@ -1,6 +1,7 @@ #include #include #include +#include #ifndef efi_enabled const bool_t efi_enabled = 0; @@ -8,6 +9,15 @@ const bool_t efi_enabled = 0; void __init efi_init_memory(void) { } +unsigned long efi_get_time(void) +{ + BUG(); + return 0; +} + +void efi_halt_system(void) { } +void efi_reset_system(bool_t warm) { } + int efi_get_info(uint32_t idx, union xenpf_efi_info *info) { return -ENOSYS; @@ -15,3 +25,11 @@ int efi_get_info(uint32_t idx, union xenpf_efi_info *info) int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *) __attribute__((__alias__("efi_get_info"))); + +int efi_runtime_call(struct xenpf_efi_runtime_call *op) +{ + return -ENOSYS; +} + +int efi_compat_runtime_call(struct compat_pf_efi_runtime_call *) + __attribute__((__alias__("efi_runtime_call"))); diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index aede176cbd..f6bcb59bec 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -305,6 +305,17 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) } break; + case XENPF_efi_runtime_call: + ret = xsm_efi_runtime_call(); + if ( ret ) + break; + + ret = efi_runtime_call(&op->u.efi_runtime_call); + if ( ret == 0 && + copy_field_to_guest(u_xenpf_op, op, u.efi_runtime_call) ) + ret = -EFAULT; + break; + case XENPF_enter_acpi_sleep: ret = xsm_acpi_sleep(); if ( ret ) diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c index 74ef63dfc8..5b9ed97c3d 100644 --- a/xen/arch/x86/shutdown.c +++ b/xen/arch/x86/shutdown.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,7 @@ void machine_halt(void) watchdog_disable(); console_start_sync(); local_irq_enable(); + efi_halt_system(); smp_call_function(__machine_halt, NULL, 0); __machine_halt(NULL); } @@ -337,6 +339,8 @@ void machine_restart(unsigned int delay_millisecs) if ( tboot_in_measured_env() ) tboot_shutdown(TB_SHUTDOWN_REBOOT); + efi_reset_system(reboot_mode != 0); + /* Rebooting needs to touch the page at absolute address 0. */ *((unsigned short *)__va(0x472)) = reboot_mode; diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 282d3b7b59..26388205d4 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -759,6 +760,13 @@ static unsigned long get_cmos_time(void) unsigned long res, flags; int i; + if ( efi_enabled ) + { + res = efi_get_time(); + if ( res ) + return res; + } + spin_lock_irqsave(&rtc_lock, flags); /* read RTC exactly on falling edge of update flag */ diff --git a/xen/arch/x86/x86_64/platform_hypercall.c b/xen/arch/x86/x86_64/platform_hypercall.c index f20fb99dc6..a1d41c2be2 100644 --- a/xen/arch/x86/x86_64/platform_hypercall.c +++ b/xen/arch/x86/x86_64/platform_hypercall.c @@ -12,6 +12,7 @@ DEFINE_XEN_GUEST_HANDLE(compat_platform_op_t); #define do_platform_op(x) compat_platform_op(_##x) #define efi_get_info efi_compat_get_info +#define efi_runtime_call(x) efi_compat_runtime_call(x) #define xen_processor_px compat_processor_px #define xen_processor_px_t compat_processor_px_t diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h index deb2f57bb3..04dbaef64d 100644 --- a/xen/include/public/platform.h +++ b/xen/include/public/platform.h @@ -114,6 +114,77 @@ struct xenpf_platform_quirk { typedef struct xenpf_platform_quirk xenpf_platform_quirk_t; DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t); +#define XENPF_efi_runtime_call 49 +#define XEN_EFI_get_time 1 +#define XEN_EFI_set_time 2 +#define XEN_EFI_get_wakeup_time 3 +#define XEN_EFI_set_wakeup_time 4 +#define XEN_EFI_get_next_high_monotonic_count 5 +#define XEN_EFI_get_variable 6 +#define XEN_EFI_set_variable 7 +#define XEN_EFI_get_next_variable_name 8 +struct xenpf_efi_runtime_call { + uint32_t function; + /* + * This field is generally used for per sub-function flags (defined + * below), except for the XEN_EFI_get_next_high_monotonic_count case, + * where it holds the single returned value. + */ + uint32_t misc; + unsigned long status; + union { +#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001 + struct { + struct xenpf_efi_time { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + uint32_t ns; + int16_t tz; + uint8_t daylight; + } time; + uint32_t resolution; + uint32_t accuracy; + } get_time; + + struct xenpf_efi_time set_time; + +#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001 +#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002 + struct xenpf_efi_time get_wakeup_time; + +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE 0x00000001 +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002 + struct xenpf_efi_time set_wakeup_time; + +#define XEN_EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 + struct { + XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */ + unsigned long size; + XEN_GUEST_HANDLE(void) data; + struct xenpf_efi_guid { + uint32_t data1; + uint16_t data2; + uint16_t data3; + uint8_t data4[8]; + } vendor_guid; + } get_variable, set_variable; + + struct { + unsigned long size; + XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */ + struct xenpf_efi_guid vendor_guid; + } get_next_variable_name; + } u; +}; +typedef struct xenpf_efi_runtime_call xenpf_efi_runtime_call_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_efi_runtime_call_t); + #define XENPF_firmware_info 50 #define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */ #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */ @@ -388,6 +459,7 @@ struct xen_platform_op { struct xenpf_read_memtype read_memtype; struct xenpf_microcode_update microcode; struct xenpf_platform_quirk platform_quirk; + struct xenpf_efi_runtime_call efi_runtime_call; struct xenpf_firmware_info firmware_info; struct xenpf_enter_acpi_sleep enter_acpi_sleep; struct xenpf_change_freq change_freq; diff --git a/xen/include/xen/efi.h b/xen/include/xen/efi.h index d32d4f2bc1..390316439c 100644 --- a/xen/include/xen/efi.h +++ b/xen/include/xen/efi.h @@ -29,10 +29,18 @@ extern struct efi efi; union xenpf_efi_info; union compat_pf_efi_info; +struct xenpf_efi_runtime_call; +struct compat_pf_efi_runtime_call; + void efi_init_memory(void); +unsigned long efi_get_time(void); +void efi_halt_system(void); +void efi_reset_system(bool_t warm); #ifndef COMPAT int efi_get_info(uint32_t idx, union xenpf_efi_info *); +int efi_runtime_call(struct xenpf_efi_runtime_call *); #endif int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *); +int efi_compat_runtime_call(struct compat_pf_efi_runtime_call *); #endif /* __XEN_EFI_H__ */ diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index b0b798f388..ffc84a53a8 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -132,6 +132,7 @@ struct xsm_operations { int (*physinfo) (void); int (*platform_quirk) (uint32_t); int (*firmware_info) (void); + int (*efi_runtime_call) (void); int (*acpi_sleep) (void); int (*change_freq) (void); int (*getidletime) (void); @@ -553,6 +554,11 @@ static inline int xsm_firmware_info (void) return xsm_call(firmware_info()); } +static inline int xsm_efi_runtime_call (void) +{ + return xsm_call(efi_runtime_call()); +} + static inline int xsm_acpi_sleep (void) { return xsm_call(acpi_sleep());