a time-of-day clock device based on the GetTime() and SetTime() services.
The virtual memory mappings for the runtime services calls are implemented
through a separate pmap that is only activated when we make a runtime services
call.
ok tom@, visa@
tested by naddy@
-/* $OpenBSD: machdep.c,v 1.23 2017/12/11 05:27:40 deraadt Exp $ */
+/* $OpenBSD: machdep.c,v 1.24 2018/01/04 14:30:08 kettenis Exp $ */
/*
* Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
*
paddr_t memstart, memend;
void *config = abp->arg2;
void *fdt = NULL;
+ EFI_PHYSICAL_ADDRESS system_table = 0;
int (*map_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_handle_t *);
int (*map_a4x_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int,
len = fdt_node_property(node, "openbsd,uefi-mmap-desc-ver", &prop);
if (len == sizeof(mmap_desc_ver))
mmap_desc_ver = bemtoh32((uint32_t *)prop);
+
+ len = fdt_node_property(node, "openbsd,uefi-system-table", &prop);
+ if (len == sizeof(system_table))
+ system_table = bemtoh64((uint64_t *)prop);
}
/* Set the pcpu data, this is needed by pmap_bootstrap */
for (va = vstart, csize = size; csize > 0;
csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE)
- pmap_kenter_cache(va, pa, PROT_READ, PMAP_CACHE_WB);
+ pmap_kenter_cache(va, pa, PROT_READ | PROT_WRITE, PMAP_CACHE_WB);
mmap = (void *)vstart;
vstart += size;
arm64_bs_tag._space_map = map_func_save;
arm64_a4x_bs_tag._space_map = map_a4x_func_save;
+ /* Remap EFI runtime. */
+ if (mmap_start != 0 && system_table != 0) {
+ EFI_SYSTEM_TABLE *st = (EFI_SYSTEM_TABLE *)system_table;
+ EFI_RUNTIME_SERVICES *rs;
+ EFI_STATUS status;
+ EFI_MEMORY_DESCRIPTOR *src;
+ EFI_MEMORY_DESCRIPTOR *dst;
+ EFI_PHYSICAL_ADDRESS phys_start = ~0ULL;
+ EFI_VIRTUAL_ADDRESS virt_start;
+ vsize_t space;
+ int i, count = 0;
+ paddr_t pa;
+
+ /*
+ * Pick a random address somewhere in the lower half
+ * of the usable virtual address space.
+ */
+ space = 3 * (VM_MAX_ADDRESS - VM_MIN_ADDRESS) / 4;
+ virt_start = VM_MIN_ADDRESS +
+ ((vsize_t)arc4random_uniform(space >> PAGE_SHIFT) << PAGE_SHIFT);
+
+ /* Make sure the EFI system table is mapped. */
+ pmap_map_early(system_table, sizeof(EFI_SYSTEM_TABLE));
+ rs = st->RuntimeServices;
+
+ /* Make sure memory for EFI runtime services is mapped. */
+ src = mmap;
+ for (i = 0; i < mmap_size / mmap_desc_size; i++) {
+ if (src->Attribute & EFI_MEMORY_RUNTIME) {
+ pmap_map_early(src->PhysicalStart,
+ src->NumberOfPages * PAGE_SIZE);
+ if (phys_start > src->PhysicalStart)
+ phys_start = src->PhysicalStart;
+ count++;
+ }
+ src = NextMemoryDescriptor(src, mmap_desc_size);
+ }
+
+ /* Allocate memory descriptors for new mappings. */
+ pa = pmap_steal_avail(count * mmap_desc_size,
+ mmap_desc_size, NULL);
+ memset((void *)pa, 0, count * mmap_desc_size);
+
+ src = mmap;
+ dst = (EFI_MEMORY_DESCRIPTOR *)pa;
+ for (i = 0; i < mmap_size / mmap_desc_size; i++) {
+ if (src->Attribute & EFI_MEMORY_RUNTIME) {
+ src->VirtualStart = virt_start +
+ (src->PhysicalStart - phys_start);
+ memcpy(dst, src, mmap_desc_size);
+ dst = NextMemoryDescriptor(dst, mmap_desc_size);
+ }
+ src = NextMemoryDescriptor(src, mmap_desc_size);
+ }
+
+ /* Install new mappings. */
+ dst = (EFI_MEMORY_DESCRIPTOR *)pa;
+ status = rs->SetVirtualAddressMap(count * mmap_desc_size,
+ mmap_desc_size, mmap_desc_ver, dst);
+ if (status != EFI_SUCCESS)
+ printf("SetVirtualAddressMap failed: %lu\n", status);
+ }
+
/* XXX */
pmap_avail_fixup();
/* Make all other physical memory available to UVM. */
if (mmap && mmap_desc_ver == EFI_MEMORY_DESCRIPTOR_VERSION) {
+ EFI_MEMORY_DESCRIPTOR *desc = mmap;
int i;
/*
*/
for (i = 0; i < mmap_size / mmap_desc_size; i++) {
printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr 0x%llx\n",
- mmap->Type, mmap->PhysicalStart,
- mmap->VirtualStart, mmap->NumberOfPages,
- mmap->Attribute);
- if (mmap->Type == EfiConventionalMemory &&
- mmap->NumberOfPages >= 16) {
- uvm_page_physload(atop(mmap->PhysicalStart),
- atop(mmap->PhysicalStart) +
- mmap->NumberOfPages,
- atop(mmap->PhysicalStart),
- atop(mmap->PhysicalStart) +
- mmap->NumberOfPages, 0);
- physmem += mmap->NumberOfPages;
+ desc->Type, desc->PhysicalStart,
+ desc->VirtualStart, desc->NumberOfPages,
+ desc->Attribute);
+ if (desc->Type == EfiConventionalMemory &&
+ desc->NumberOfPages >= 16) {
+ uvm_page_physload(atop(desc->PhysicalStart),
+ atop(desc->PhysicalStart) +
+ desc->NumberOfPages,
+ atop(desc->PhysicalStart),
+ atop(desc->PhysicalStart) +
+ desc->NumberOfPages, 0);
+ physmem += desc->NumberOfPages;
}
- mmap = NextMemoryDescriptor(mmap, mmap_desc_size);
+ desc = NextMemoryDescriptor(desc, mmap_desc_size);
}
} else {
paddr_t start, end;
-/* $OpenBSD: pmap.c,v 1.41 2017/12/31 08:42:04 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.42 2018/01/04 14:30:08 kettenis Exp $ */
/*
* Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com>
*
}
const uint64_t ap_bits_user[8] = {
- [PROT_NONE] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AP(2),
- [PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(3),
- [PROT_WRITE] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
- [PROT_WRITE|PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
- [PROT_EXEC] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(2),
- [PROT_EXEC|PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(3),
- [PROT_EXEC|PROT_WRITE] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1),
- [PROT_EXEC|PROT_WRITE|PROT_READ]= ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1),
+ [PROT_NONE] = ATTR_PXN|ATTR_UXN|ATTR_AP(2),
+ [PROT_READ] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(3),
+ [PROT_WRITE] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
+ [PROT_WRITE|PROT_READ] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
+ [PROT_EXEC] = ATTR_PXN|ATTR_AF|ATTR_AP(2),
+ [PROT_EXEC|PROT_READ] = ATTR_PXN|ATTR_AF|ATTR_AP(3),
+ [PROT_EXEC|PROT_WRITE] = ATTR_PXN|ATTR_AF|ATTR_AP(1),
+ [PROT_EXEC|PROT_WRITE|PROT_READ] = ATTR_PXN|ATTR_AF|ATTR_AP(1),
};
const uint64_t ap_bits_kern[8] = {
pt1pa = pmap_steal_avail(sizeof(struct pmapvp1), Lx_TABLE_ALIGN, &va);
vp1 = (struct pmapvp1 *)pt1pa;
pmap_kernel()->pm_vp.l1 = (struct pmapvp1 *)va;
+ pmap_kernel()->pm_privileged = 1;
pmap_kernel()->pm_asid = 0;
/* allocate Lx entries */
printf("all mapped\n");
+ curcpu()->ci_curpm = pmap_kernel();
+
memhook = (char *)vstart;
vstart += PAGE_SIZE;
panic("pmap_pte_insert: invalid cache mode");
}
- /* kernel mappings are global, so nG should not be set */
- if (pm == pmap_kernel())
+ if (pm->pm_privileged)
access_bits = ap_bits_kern[pted->pted_pte & PROT_MASK];
else
access_bits = ap_bits_user[pted->pted_pte & PROT_MASK];
+ if (pted->pted_va < VM_MIN_KERNEL_ADDRESS)
+ access_bits |= ATTR_nG;
+
pte = (pted->pted_pte & PTE_RPGN) | attr | access_bits | L3_P;
*pl3 = pte;
}
-# $OpenBSD: GENERIC,v 1.47 2018/01/02 22:47:45 kettenis Exp $
+# $OpenBSD: GENERIC,v 1.48 2018/01/04 14:30:08 kettenis Exp $
#
# GENERIC machine description file
#
# The main bus device
mainbus0 at root
cpu0 at mainbus?
+efi0 at mainbus?
simplebus* at fdt?
scsibus* at scsi?
-# $OpenBSD: RAMDISK,v 1.41 2018/01/02 22:47:45 kettenis Exp $
+# $OpenBSD: RAMDISK,v 1.42 2018/01/04 14:30:08 kettenis Exp $
#
# GENERIC machine description file
#
# The main bus device
mainbus0 at root
cpu0 at mainbus?
+efi0 at mainbus?
simplebus* at fdt?
scsibus* at scsi?
-# $OpenBSD: files.arm64,v 1.15 2017/06/04 14:10:42 patrick Exp $
+# $OpenBSD: files.arm64,v 1.16 2018/01/04 14:30:08 kettenis Exp $
maxpartitions 16
maxusers 2 8 64
attach simplebus at fdt
file arch/arm64/dev/simplebus.c simplebus
+device efi
+attach efi at fdt
+file arch/arm64/dev/efi.c efi
+
# FDT support
file dev/ofw/fdt.c
file dev/ofw/ofw_clock.c
--- /dev/null
+/* $OpenBSD: efi.c,v 1.1 2018/01/04 14:30:08 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpufunc.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#include <dev/acpi/efi.h>
+
+#include <dev/clock_subr.h>
+
+extern todr_chip_handle_t todr_handle;
+
+extern uint32_t mmap_size;
+extern uint32_t mmap_desc_size;
+extern uint32_t mmap_desc_ver;
+
+extern EFI_MEMORY_DESCRIPTOR *mmap;
+
+struct efi_softc {
+ struct device sc_dev;
+ struct pmap *sc_pm;
+ EFI_RUNTIME_SERVICES *sc_rs;
+ int sc_psw;
+
+ struct todr_chip_handle sc_todr;
+};
+
+int efi_match(struct device *, void *, void *);
+void efi_attach(struct device *, struct device *, void *);
+
+struct cfattach efi_ca = {
+ sizeof(struct efi_softc), efi_match, efi_attach
+};
+
+struct cfdriver efi_cd = {
+ NULL, "efi", DV_DULL
+};
+
+void efi_enter(struct efi_softc *);
+void efi_leave(struct efi_softc *);
+int efi_gettime(struct todr_chip_handle *, struct timeval *);
+int efi_settime(struct todr_chip_handle *, struct timeval *);
+
+int
+efi_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ return (strcmp(faa->fa_name, "efi") == 0);
+}
+
+void
+efi_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct efi_softc *sc = (struct efi_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ uint64_t system_table;
+ bus_space_handle_t ioh;
+ EFI_SYSTEM_TABLE *st;
+ EFI_RUNTIME_SERVICES *rs;
+ EFI_MEMORY_DESCRIPTOR *desc;
+ EFI_TIME time;
+ EFI_STATUS status;
+ uint16_t major, minor;
+ int node, i;
+
+ node = OF_finddevice("/chosen");
+ KASSERT(node);
+
+ system_table = OF_getpropint64(node, "openbsd,uefi-system-table", 0);
+ KASSERT(system_table);
+
+ if (bus_space_map(faa->fa_iot, system_table, sizeof(EFI_SYSTEM_TABLE),
+ BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &ioh)) {
+ printf(": can't map system table\n");
+ return;
+ }
+
+ st = bus_space_vaddr(faa->fa_iot, ioh);
+ rs = st->RuntimeServices;
+
+ major = st->Hdr.Revision >> 16;
+ minor = st->Hdr.Revision & 0xffff;
+ printf(": UEFI %d.%d", major, minor / 10);
+ if (minor % 10)
+ printf(".%d", minor % 10);
+ printf("\n");
+
+ /*
+ * We don't really want some random executable non-OpenBSD
+ * code lying around in kernel space. So create a separate
+ * pmap and only activate it when we call runtime services.
+ */
+ sc->sc_pm = pmap_create();
+ sc->sc_pm->pm_privileged = 1;
+
+ desc = mmap;
+ for (i = 0; i < mmap_size / mmap_desc_size; i++) {
+ if (desc->Attribute & EFI_MEMORY_RUNTIME) {
+ vaddr_t va = desc->VirtualStart;
+ paddr_t pa = desc->PhysicalStart;
+ int npages = desc->NumberOfPages;
+ vm_prot_t prot = PROT_READ;
+
+#ifdef EFI_DEBUG
+ printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr 0x%llx\n",
+ desc->Type, desc->PhysicalStart,
+ desc->VirtualStart, desc->NumberOfPages,
+ desc->Attribute);
+#endif
+
+ if (desc->Type == EfiRuntimeServicesCode)
+ prot |= PROT_EXEC;
+ else
+ prot |= PROT_WRITE;
+ while (npages--) {
+ pmap_enter(sc->sc_pm, va, pa, prot,
+ prot | PMAP_WIRED);
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ }
+ }
+ desc = NextMemoryDescriptor(desc, mmap_desc_size);
+ }
+
+ /*
+ * The FirmwareVendor field has been converted from a physical
+ * pointer to a virtual pointer, so we have to activate our
+ * pmap to access it.
+ */
+ if (st->FirmwareVendor) {
+ printf("%s: ", sc->sc_dev.dv_xname);
+ efi_enter(sc);
+ for (i = 0; st->FirmwareVendor[i]; i++)
+ printf("%c", st->FirmwareVendor[i]);
+ efi_leave(sc);
+ printf(" rev 0x%x\n", st->FirmwareRevision);
+ }
+
+ if (rs == NULL)
+ return;
+
+ efi_enter(sc);
+ status = rs->GetTime(&time, NULL);
+ efi_leave(sc);
+ if (status != EFI_SUCCESS)
+ return;
+
+ sc->sc_rs = rs;
+ sc->sc_todr.cookie = sc;
+ sc->sc_todr.todr_gettime = efi_gettime;
+ sc->sc_todr.todr_settime = efi_settime;
+ todr_handle = &sc->sc_todr;
+}
+
+void
+efi_enter(struct efi_softc *sc)
+{
+ struct pmap *pm = sc->sc_pm;
+
+ sc->sc_psw = disable_interrupts();
+ cpu_setttb(((uint64_t)pm->pm_asid << 48) | pm->pm_pt0pa);
+}
+
+void
+efi_leave(struct efi_softc *sc)
+{
+ struct pmap *pm = curcpu()->ci_curpm;
+
+ cpu_setttb(((uint64_t)pm->pm_asid << 48) | pm->pm_pt0pa);
+ restore_interrupts(sc->sc_psw);
+}
+
+int
+efi_gettime(struct todr_chip_handle *handle, struct timeval *tv)
+{
+ struct efi_softc *sc = handle->cookie;
+ struct clock_ymdhms dt;
+ EFI_TIME time;
+ EFI_STATUS status;
+
+ efi_enter(sc);
+ status = sc->sc_rs->GetTime(&time, NULL);
+ efi_leave(sc);
+ if (status != EFI_SUCCESS)
+ return EIO;
+
+ dt.dt_year = time.Year;
+ dt.dt_mon = time.Month;
+ dt.dt_day = time.Day;
+ dt.dt_hour = time.Hour;
+ dt.dt_min = time.Minute;
+ dt.dt_sec = time.Second;
+
+ if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
+ dt.dt_day > 31 || dt.dt_day == 0 ||
+ dt.dt_mon > 12 || dt.dt_mon == 0 ||
+ dt.dt_year < POSIX_BASE_YEAR)
+ return EINVAL;
+
+ tv->tv_sec = clock_ymdhms_to_secs(&dt);
+ tv->tv_usec = 0;
+ return 0;
+}
+
+int
+efi_settime(struct todr_chip_handle *handle, struct timeval *tv)
+{
+ struct efi_softc *sc = handle->cookie;
+ struct clock_ymdhms dt;
+ EFI_TIME time;
+ EFI_STATUS status;
+
+ clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+ time.Year = dt.dt_year;
+ time.Month = dt.dt_mon;
+ time.Day = dt.dt_day;
+ time.Hour = dt.dt_hour;
+ time.Minute = dt.dt_min;
+ time.Second = dt.dt_sec;
+ time.Nanosecond = 0;
+ time.TimeZone = 0;
+ time.Daylight = 0;
+
+ efi_enter(sc);
+ status = sc->sc_rs->SetTime(&time);
+ efi_leave(sc);
+ if (status != EFI_SUCCESS)
+ return EIO;
+ return 0;
+}
+
-/* $OpenBSD: mainbus.c,v 1.7 2017/08/23 12:58:00 kettenis Exp $ */
+/* $OpenBSD: mainbus.c,v 1.8 2018/01/04 14:30:08 kettenis Exp $ */
/*
* Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
void mainbus_attach_cpus(struct device *, cfmatch_t);
int mainbus_match_primary(struct device *, void *, void *);
int mainbus_match_secondary(struct device *, void *, void *);
+void mainbus_attach_efi(struct device *);
void mainbus_attach_framebuffer(struct device *);
struct mainbus_softc {
/* Attach primary CPU first. */
mainbus_attach_cpus(self, mainbus_match_primary);
+ mainbus_attach_efi(self);
+
sc->sc_rangeslen = OF_getproplen(OF_peer(0), "ranges");
if (sc->sc_rangeslen > 0 && !(sc->sc_rangeslen % sizeof(uint32_t))) {
sc->sc_ranges = malloc(sc->sc_rangeslen, M_TEMP, M_WAITOK);
struct cfdata *cf = match;
char buf[32];
+ if (fa->fa_node == 0)
+ return 0;
+
if (OF_getprop(fa->fa_node, "status", buf, sizeof(buf)) > 0 &&
strcmp(buf, "disabled") == 0)
return 0;
return (*cf->cf_attach->ca_match)(parent, match, aux);
}
+void
+mainbus_attach_efi(struct device *self)
+{
+ struct mainbus_softc *sc = (struct mainbus_softc *)self;
+ struct fdt_attach_args fa;
+ int node = OF_finddevice("/chosen");
+
+ if (node == 0 || OF_getproplen(node, "openbsd,uefi-system-table") <= 0)
+ return;
+
+ memset(&fa, 0, sizeof(fa));
+ fa.fa_name = "efi";
+ fa.fa_iot = sc->sc_iot;
+ fa.fa_dmat = sc->sc_dmat;
+ config_found(self, &fa, NULL);
+}
+
void
mainbus_attach_framebuffer(struct device *self)
{
-/* $OpenBSD: pmap.h,v 1.7 2017/12/31 08:42:04 kettenis Exp $ */
+/* $OpenBSD: pmap.h,v 1.8 2018/01/04 14:30:08 kettenis Exp $ */
/*
* Copyright (c) 2008,2009,2014 Dale Rahn <drahn@dalerahn.com>
*
} pm_vp;
uint64_t pm_pt0pa;
int have_4_level_pt;
+ int pm_privileged;
int pm_asid;
int pm_refs; /* ref count */
struct pmap_statistics pm_stats; /* pmap statistics */
-/* $OpenBSD: efi.h,v 1.1 2017/05/25 21:21:18 kettenis Exp $ */
+/* $OpenBSD: efi.h,v 1.2 2018/01/04 14:30:08 kettenis Exp $ */
/* Public Domain */
#define _MACHINE_EFI_H_
typedef uint8_t UINT8;
+typedef int16_t INT16;
+typedef uint16_t UINT16;
typedef uint32_t UINT32;
typedef uint64_t UINT64;
+typedef u_long UINTN;
+typedef uint16_t CHAR16;
+typedef void VOID;
+typedef uint32_t EFI_GUID[4];
typedef uint64_t EFI_PHYSICAL_ADDRESS;
typedef uint64_t EFI_VIRTUAL_ADDRESS;
+typedef UINTN EFI_STATUS;
+typedef VOID *EFI_HANDLE;
+
+typedef VOID *EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+typedef VOID *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+typedef VOID *EFI_BOOT_SERVICES;
typedef enum {
EfiReservedMemoryType,
#define NextMemoryDescriptor(Ptr, Size) \
((EFI_MEMORY_DESCRIPTOR *)(((UINT8 *)Ptr) + Size))
+typedef struct {
+ UINT64 Signature;
+ UINT32 Revision;
+ UINT32 HeaderSize;
+ UINT32 CRC32;
+ UINT32 Reserved;
+} EFI_TABLE_HEADER;
+
+typedef struct {
+ UINT16 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ UINT8 Pad1;
+ UINT32 Nanosecond;
+ INT16 TimeZone;
+ UINT8 Daylight;
+ UINT8 Pad2;
+} EFI_TIME;
+
+typedef VOID *EFI_TIME_CAPABILITIES;
+
+typedef EFI_STATUS (*EFI_GET_TIME)(EFI_TIME *, EFI_TIME_CAPABILITIES *);
+typedef EFI_STATUS (*EFI_SET_TIME)(EFI_TIME *);
+typedef EFI_STATUS (*EFI_SET_VIRTUAL_ADDRESS_MAP)(UINTN, UINTN, UINT32, EFI_MEMORY_DESCRIPTOR *);
+
+typedef struct {
+ EFI_TABLE_HEADER Hdr;
+ EFI_GET_TIME GetTime;
+ EFI_SET_TIME SetTime;
+ VOID *GetWakeupTime;
+ VOID *SetWakeupTime;
+
+ EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap;
+} EFI_RUNTIME_SERVICES;
+
+typedef struct {
+ EFI_GUID VendorGuid;
+ VOID *VendorTable;
+} EFI_CONFIGURATION_TABLE;
+
+typedef struct {
+ EFI_TABLE_HEADER Hdr;
+ CHAR16 *FirmwareVendor;
+ UINT32 FirmwareRevision;
+ EFI_HANDLE ConsoleInHandle;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
+ EFI_HANDLE ConsoleOutHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+ EFI_HANDLE StandardErrorHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
+ EFI_RUNTIME_SERVICES *RuntimeServices;
+ EFI_BOOT_SERVICES *BootServices;
+ UINTN NumberOfTableEntries;
+ EFI_CONFIGURATION_TABLE *ConfigurationTable;
+} EFI_SYSTEM_TABLE;
+
+#define EFI_SUCCESS 0
+
#endif /* _MACHINE_EFI_H_ */