mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 17/21] Add initial EFI architecture support
Date: Tue,  8 Jul 2014 10:50:13 +0200	[thread overview]
Message-ID: <1404809417-21477-18-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1404809417-21477-1-git-send-email-s.hauer@pengutronix.de>

This adds support for running barebox in an EFI environment
on X86 PC hardware.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/efi/Kconfig                           |   47 +
 arch/efi/Makefile                          |   41 +
 arch/efi/configs/efi_defconfig             |   73 ++
 arch/efi/efi/Makefile                      |    2 +
 arch/efi/efi/clocksource.c                 |   60 ++
 arch/efi/efi/efi-block-io.c                |  174 ++++
 arch/efi/efi/efi-device.c                  |  348 +++++++
 arch/efi/efi/efi-image.c                   |  105 +++
 arch/efi/efi/efi.c                         |  342 +++++++
 arch/efi/efi/env-efi/network/eth0-discover |    5 +
 arch/efi/include/asm/barebox.h             |    1 +
 arch/efi/include/asm/bitops.h              |   15 +
 arch/efi/include/asm/byteorder.h           |    8 +
 arch/efi/include/asm/common.h              |    4 +
 arch/efi/include/asm/dma.h                 |   13 +
 arch/efi/include/asm/elf.h                 |   60 ++
 arch/efi/include/asm/io.h                  |   55 ++
 arch/efi/include/asm/posix_types.h         |   93 ++
 arch/efi/include/asm/sections.h            |    1 +
 arch/efi/include/asm/string.h              |    1 +
 arch/efi/include/asm/swab.h                |    6 +
 arch/efi/include/asm/types.h               |   73 ++
 arch/efi/include/asm/unaligned.h           |   19 +
 arch/efi/include/mach/debug_ll.h           |   20 +
 arch/efi/include/mach/efi-device.h         |   45 +
 arch/efi/include/mach/efi.h                |   24 +
 arch/efi/lib/.gitignore                    |    2 +
 arch/efi/lib/Makefile                      |    4 +
 arch/efi/lib/crt0-efi-ia32.S               |   76 ++
 arch/efi/lib/crt0-efi-x86_64.S             |   75 ++
 arch/efi/lib/elf_ia32_efi.lds.S            |  102 +++
 arch/efi/lib/elf_x86_64_efi.lds.S          |   93 ++
 arch/efi/lib/reloc_ia32.c                  |   97 ++
 arch/efi/lib/reloc_x86_64.c                |   96 ++
 common/Kconfig                             |    8 +
 common/Makefile                            |    4 +-
 common/efi-devicepath.c                    | 1370 ++++++++++++++++++++++++++++
 common/efi-guid.c                          |   11 +
 common/memory.c                            |    2 +-
 common/partitions/efi.c                    |    2 +-
 drivers/of/Kconfig                         |    2 +-
 include/efi.h                              |  464 ++++------
 42 files changed, 3774 insertions(+), 269 deletions(-)
 create mode 100644 arch/efi/Kconfig
 create mode 100644 arch/efi/Makefile
 create mode 100644 arch/efi/configs/efi_defconfig
 create mode 100644 arch/efi/efi/Makefile
 create mode 100644 arch/efi/efi/clocksource.c
 create mode 100644 arch/efi/efi/efi-block-io.c
 create mode 100644 arch/efi/efi/efi-device.c
 create mode 100644 arch/efi/efi/efi-image.c
 create mode 100644 arch/efi/efi/efi.c
 create mode 100644 arch/efi/efi/env-efi/network/eth0-discover
 create mode 100644 arch/efi/include/asm/barebox.h
 create mode 100644 arch/efi/include/asm/bitops.h
 create mode 100644 arch/efi/include/asm/byteorder.h
 create mode 100644 arch/efi/include/asm/common.h
 create mode 100644 arch/efi/include/asm/dma.h
 create mode 100644 arch/efi/include/asm/elf.h
 create mode 100644 arch/efi/include/asm/io.h
 create mode 100644 arch/efi/include/asm/posix_types.h
 create mode 100644 arch/efi/include/asm/sections.h
 create mode 100644 arch/efi/include/asm/string.h
 create mode 100644 arch/efi/include/asm/swab.h
 create mode 100644 arch/efi/include/asm/types.h
 create mode 100644 arch/efi/include/asm/unaligned.h
 create mode 100644 arch/efi/include/mach/debug_ll.h
 create mode 100644 arch/efi/include/mach/efi-device.h
 create mode 100644 arch/efi/include/mach/efi.h
 create mode 100644 arch/efi/lib/.gitignore
 create mode 100644 arch/efi/lib/Makefile
 create mode 100644 arch/efi/lib/crt0-efi-ia32.S
 create mode 100644 arch/efi/lib/crt0-efi-x86_64.S
 create mode 100644 arch/efi/lib/elf_ia32_efi.lds.S
 create mode 100644 arch/efi/lib/elf_x86_64_efi.lds.S
 create mode 100644 arch/efi/lib/reloc_ia32.c
 create mode 100644 arch/efi/lib/reloc_x86_64.c
 create mode 100644 common/efi-devicepath.c
 create mode 100644 common/efi-guid.c

diff --git a/arch/efi/Kconfig b/arch/efi/Kconfig
new file mode 100644
index 0000000..f67ed9d
--- /dev/null
+++ b/arch/efi/Kconfig
@@ -0,0 +1,47 @@
+config ARCH_EFI
+	bool
+	default y
+	select HAS_DEBUG_LL
+	select HAS_KALLSYMS
+	select HAVE_DEFAULT_ENVIRONMENT_NEW
+	select EFI_GUID
+	select EFI_DEVICEPATH
+
+config ARCH_TEXT_BASE
+	hex
+	default 0x0
+
+menu "EFI specific settings"
+
+config 64BIT
+	bool "64-bit binary"
+	help
+	  Say yes to build a 64-bit kernel - formerly known as x86_64
+	  Say no to build a 32-bit kernel - formerly known as i386
+
+config X86_32
+	def_bool y
+	depends on !64BIT
+
+config X86_64
+	def_bool y
+	depends on 64BIT
+
+config ARCH_EFI_REGISTER_COM1
+	bool "Register first serial port"
+	help
+	  Say yes here to register the first serial port on ioport 0x3f8.
+	  This is useful to control barebox over a serial port if the board
+	  has one. Enabling this option may not work on boards which do not
+	  have a serial port. Also enable DRIVER_SERIAL_NS16550 to enable
+	  the NS16550 driver.
+
+endmenu
+
+source common/Kconfig
+source commands/Kconfig
+source net/Kconfig
+source drivers/Kconfig
+source fs/Kconfig
+source lib/Kconfig
+source crypto/Kconfig
diff --git a/arch/efi/Makefile b/arch/efi/Makefile
new file mode 100644
index 0000000..af28085
--- /dev/null
+++ b/arch/efi/Makefile
@@ -0,0 +1,41 @@
+CFLAGS += -fpic -fshort-wchar -mno-sse -mno-mmx
+
+ifeq ($(CONFIG_X86_32),y)
+	UTS_MACHINE := i386
+	biarch := $(call cc-option,-m32)
+	AFLAGS += $(biarch)
+	CFLAGS += $(biarch)
+	TARGET = efi-app-ia32
+else
+	UTS_MACHINE := x86_64
+	AFLAGS += -m64
+	CFLAGS += -m64 -mno-red-zone
+	TARGET = efi-app-x86_64
+endif
+
+lds-$(CONFIG_X86_32)   := arch/efi/lib/elf_ia32_efi.lds
+lds-$(CONFIG_X86_64)   := arch/efi/lib/elf_x86_64_efi.lds
+
+cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@	\
+		-T $(lds-y)					\
+		-shared -Bsymbolic -nostdlib -znocombreloc	\
+		--start-group $(barebox-common)			\
+		--end-group					\
+		$(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^)
+
+quiet_cmd_efi_image = EFI-IMG $@
+      cmd_efi_image = objcopy -j .text -j .sdata -j .data -j .dynamic \
+		      -j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \
+		      -j __barebox_cmd -j .barebox_magicvar -j .bbenv.* \
+		      --target=$(TARGET) $< $@
+
+KBUILD_BINARY := barebox
+
+LDFLAGS := -m elf_$(UTS_MACHINE) --no-undefined
+
+barebox.efi: $(KBUILD_BINARY) FORCE
+	$(call if_changed,efi_image)
+
+KBUILD_IMAGE := barebox.efi
+
+common-y += arch/efi/efi/ arch/efi/lib/
diff --git a/arch/efi/configs/efi_defconfig b/arch/efi/configs/efi_defconfig
new file mode 100644
index 0000000..253d7e8
--- /dev/null
+++ b/arch/efi/configs/efi_defconfig
@@ -0,0 +1,73 @@
+CONFIG_MMU=y
+CONFIG_MALLOC_SIZE=0x0
+CONFIG_MALLOC_TLSF=y
+CONFIG_PROMPT="barebox> "
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+# CONFIG_TIMESTAMP is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
+CONFIG_PARTITION_DISK_EFI=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_POLLER=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_UIMAGE=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_HOST=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_2048=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_NET=y
+CONFIG_NET_NFS=y
+CONFIG_NET_NETCONSOLE=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+# CONFIG_SPI is not set
+CONFIG_DISK=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
diff --git a/arch/efi/efi/Makefile b/arch/efi/efi/Makefile
new file mode 100644
index 0000000..a856e59
--- /dev/null
+++ b/arch/efi/efi/Makefile
@@ -0,0 +1,2 @@
+obj-y += efi.o clocksource.o efi-block-io.o efi-device.o efi-image.o
+bbenv-y += env-efi
diff --git a/arch/efi/efi/clocksource.c b/arch/efi/efi/clocksource.c
new file mode 100644
index 0000000..2f33b43
--- /dev/null
+++ b/arch/efi/efi/clocksource.c
@@ -0,0 +1,60 @@
+#include <common.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <clock.h>
+
+#ifdef __x86_64__
+uint64_t ticks_read(void)
+{
+	uint64_t a, d;
+
+	__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
+
+	return (d << 32) | a;
+}
+#else
+uint64_t ticks_read(void)
+{
+	uint64_t val;
+
+	__asm__ volatile ("rdtsc" : "=A" (val));
+
+	return val;
+}
+#endif
+
+static uint64_t freq;
+
+/* count TSC ticks during a millisecond delay */
+static uint64_t ticks_freq(void)
+{
+	uint64_t ticks_start, ticks_end;
+
+	ticks_start = ticks_read();
+	BS->stall(1000);
+	ticks_end = ticks_read();
+
+	return (ticks_end - ticks_start) * 1000;
+}
+
+static uint64_t efi_clocksource_read(void)
+{
+	return 1000 * 1000 * ticks_read() / freq;
+}
+
+static struct clocksource cs = {
+	.read   = efi_clocksource_read,
+	.mask   = CLOCKSOURCE_MASK(64),
+	.shift  = 0,
+};
+
+int efi_clocksource_init(void)
+{
+	cs.mult = clocksource_hz2mult(1000 * 1000, cs.shift);
+
+	freq = ticks_freq();
+
+	init_clock(&cs);
+
+	return 0;
+}
diff --git a/arch/efi/efi/efi-block-io.c b/arch/efi/efi/efi-block-io.c
new file mode 100644
index 0000000..0011531
--- /dev/null
+++ b/arch/efi/efi/efi-block-io.c
@@ -0,0 +1,174 @@
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <fs.h>
+#include <string.h>
+#include <command.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <xfuncs.h>
+#include <fcntl.h>
+#include <efi.h>
+#include <block.h>
+#include <disks.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
+#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31))
+
+struct efi_block_io_media{
+	u32 media_id;
+	bool removable_media;
+	bool media_present;
+	bool logical_partition;
+	bool read_only;
+	bool write_caching;
+	u32 block_size;
+	u32 io_align;
+	u64 last_block;
+	u64 lowest_aligned_lba; /* added in Revision 2 */
+	u32 logical_blocks_per_physical_block; /* added in Revision 2 */
+	u32 optimal_transfer_length_granularity; /* added in Revision 3 */
+};
+
+struct efi_block_io_protocol {
+	u64 revision;
+	struct efi_block_io_media *media;
+	efi_status_t(EFIAPI *reset)(struct efi_block_io_protocol *this,
+			bool ExtendedVerification);
+	efi_status_t(EFIAPI *read)(struct efi_block_io_protocol *this, u32 media_id,
+			u64 lba, unsigned long buffer_size, void *buf);
+	efi_status_t(EFIAPI *write)(struct efi_block_io_protocol *this, u32 media_id,
+			u64 lba, unsigned long buffer_size, void *buf);
+	efi_status_t(EFIAPI *flush)(struct efi_block_io_protocol *this);
+};
+
+struct efi_bio_priv {
+	struct efi_block_io_protocol *protocol;
+	struct device_d *dev;
+	struct block_device blk;
+	u32 media_id;
+};
+
+static int efi_bio_read(struct block_device *blk, void *buffer, int block,
+		int num_blocks)
+{
+	struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
+	efi_status_t efiret;
+
+	efiret = priv->protocol->read(priv->protocol, priv->media_id,
+			block, num_blocks * 512, buffer);
+
+	if (EFI_ERROR(efiret))
+		return -efi_errno(efiret);
+
+	return 0;
+}
+
+static int efi_bio_write(struct block_device *blk,
+		const void *buffer, int block, int num_blocks)
+{
+	struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
+	efi_status_t efiret;
+
+	efiret = priv->protocol->write(priv->protocol, priv->media_id,
+			block, num_blocks * 512, (void *)buffer);
+	if (EFI_ERROR(efiret))
+		return -efi_errno(efiret);
+
+	return 0;
+}
+
+static int efi_bio_flush(struct block_device *blk)
+{
+	struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
+	efi_status_t efiret;
+
+	efiret = priv->protocol->flush(priv->protocol);
+	if (EFI_ERROR(efiret))
+		return -efi_errno(efiret);
+
+	return 0;
+}
+
+static struct block_device_ops efi_bio_ops = {
+	.read = efi_bio_read,
+	.write = efi_bio_write,
+	.flush = efi_bio_flush,
+};
+
+static void efi_bio_print_info(struct efi_bio_priv *priv)
+{
+	struct efi_block_io_media *media = priv->protocol->media;
+	u64 revision = priv->protocol->revision;
+
+	dev_dbg(priv->dev, "revision: 0x%016llx\n", revision);
+	dev_dbg(priv->dev, "media_id: 0x%08x\n", media->media_id);
+	dev_dbg(priv->dev, "removable_media: %d\n", media->removable_media);
+	dev_dbg(priv->dev, "media_present: %d\n", media->media_present);
+	dev_dbg(priv->dev, "logical_partition: %d\n", media->logical_partition);
+	dev_dbg(priv->dev, "read_only: %d\n", media->read_only);
+	dev_dbg(priv->dev, "write_caching: %d\n", media->write_caching);
+	dev_dbg(priv->dev, "block_size: 0x%08x\n", media->block_size);
+	dev_dbg(priv->dev, "io_align: 0x%08x\n", media->io_align);
+	dev_dbg(priv->dev, "last_block: 0x%016llx\n", media->last_block);
+
+	if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION2)
+		return;
+
+	dev_dbg(priv->dev, "u64 lowest_aligned_lba: 0x%08llx\n",
+			media->lowest_aligned_lba);
+	dev_dbg(priv->dev, "logical_blocks_per_physical_block: 0x%08x\n",
+			media->logical_blocks_per_physical_block);
+
+	if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION3)
+		return;
+
+	dev_dbg(priv->dev, "optimal_transfer_length_granularity: 0x%08x\n",
+			media->optimal_transfer_length_granularity);
+}
+
+int efi_bio_probe(struct efi_device *efidev)
+{
+	int ret;
+	struct efi_bio_priv *priv;
+	struct efi_block_io_media *media;
+
+	priv = xzalloc(sizeof(*priv));
+
+	BS->handle_protocol(efidev->handle, &efi_block_io_protocol_guid,
+			(void **)&priv->protocol);
+	if (!priv->protocol)
+		return -ENODEV;
+
+	media = priv->protocol->media;
+	efi_bio_print_info(priv);
+	priv->dev = &efidev->dev;
+
+	priv->blk.cdev.name = asprintf("disk%d", cdev_find_free_index("disk"));
+	priv->blk.blockbits = ffs(media->block_size) - 1;
+	priv->blk.num_blocks = media->last_block;
+	priv->blk.ops = &efi_bio_ops;
+	priv->blk.dev = &efidev->dev;
+
+	priv->media_id = media->media_id;
+
+	ret = blockdevice_register(&priv->blk);
+	if (ret)
+		return ret;
+
+	parse_partition_table(&priv->blk);
+
+	return 0;
+}
+
+static struct efi_driver efi_fs_driver = {
+        .driver = {
+		.name  = "efi-block-io",
+	},
+        .probe = efi_bio_probe,
+	.guid = EFI_BLOCK_IO_PROTOCOL_GUID,
+};
+device_efi_driver(efi_fs_driver);
diff --git a/arch/efi/efi/efi-device.c b/arch/efi/efi/efi-device.c
new file mode 100644
index 0000000..71526b9
--- /dev/null
+++ b/arch/efi/efi/efi-device.c
@@ -0,0 +1,348 @@
+/*
+ * efi-device.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <command.h>
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <memory.h>
+#include <string.h>
+#include <sizes.h>
+#include <wchar.h>
+#include <init.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+#include <linux/err.h>
+
+int efi_locate_handle(enum efi_locate_search_type search_type,
+		efi_guid_t *protocol,
+		void *search_key,
+		unsigned long *no_handles,
+		efi_handle_t **buffer)
+{
+	efi_status_t efiret;
+	unsigned long buffer_size = 0;
+	efi_handle_t *buf;
+
+	efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size,
+			NULL);
+	if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL)
+		return -efi_errno(efiret);
+
+	buf = malloc(buffer_size);
+	if (!buf)
+		return -ENOMEM;
+
+	efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size,
+			buf);
+	if (EFI_ERROR(efiret)) {
+		free(buf);
+		return -efi_errno(efiret);
+	}
+
+	*no_handles = buffer_size / sizeof(efi_handle_t);
+	*buffer = buf;
+
+	return 0;
+}
+
+static struct efi_device *efi_find_device(efi_handle_t *handle)
+{
+	struct device_d *dev;
+	struct efi_device *efidev;
+
+	bus_for_each_device(&efi_bus, dev) {
+		efidev = container_of(dev, struct efi_device, dev);
+
+		if (efidev->handle == handle)
+			return efidev;
+	}
+
+	return NULL;
+}
+
+static void efi_devinfo(struct device_d *dev)
+{
+	struct efi_device *efidev = to_efi_device(dev);
+	int i;
+
+	printf("Protocols:\n");
+
+	for (i = 0; i < efidev->num_guids; i++)
+		printf("  %d: %pUl\n", i, &efidev->guids[i]);
+}
+
+static efi_handle_t *efi_find_parent(efi_handle_t *handle)
+{
+	unsigned long handle_count = 0;
+        efi_handle_t *handles = NULL, *parent;
+	unsigned long num_guids;
+	efi_guid_t **guids;
+	int ret, i, j, k;
+	efi_status_t efiret;
+	struct efi_open_protocol_information_entry *entry_buffer;
+	unsigned long entry_count;
+
+	ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles);
+	if (ret)
+		return NULL;
+
+	/*
+	 * Normally one would expect a function/pointer to retrieve the parent.
+	 * With EFI we have to:
+	 * - get all handles
+	 * - for each handle get the registered protocols
+	 * - for each protocol get the users
+	 * - the user which matches the input handle is the parent
+	 */
+	for (i = 0; i < handle_count; i++) {
+		efiret = BS->open_protocol(handles[i], &efi_device_path_protocol_guid,
+				NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+		if (EFI_ERROR(efiret))
+			continue;
+
+		BS->protocols_per_handle(handles[i], &guids, &num_guids);
+		for (j = 0; j < num_guids; j++) {
+			efiret = BS->open_protocol_information(handles[i], guids[j],
+				&entry_buffer, &entry_count);
+			for (k = 0; k < entry_count; k++) {
+				if (entry_buffer[k].controller_handle == NULL)
+					continue;
+				if (entry_buffer[k].controller_handle == handles[i])
+					continue;
+				if (entry_buffer[k].controller_handle == handle) {
+					parent = handles[i];
+					goto out;
+				}
+			}
+		}
+	}
+
+	parent = NULL;
+
+	free(handles);
+out:
+	return parent;
+}
+
+static struct efi_device *efi_add_device(efi_handle_t *handle, efi_guid_t **guids,
+		int num_guids)
+{
+	struct efi_device *efidev;
+	int i;
+	efi_guid_t *guidarr;
+	efi_status_t efiret;
+	void *devpath;
+
+	efidev = efi_find_device(handle);
+	if (efidev)
+		return ERR_PTR(-EEXIST);
+
+	efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid,
+			NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+	if (EFI_ERROR(efiret))
+		return ERR_PTR(-EINVAL);
+
+	guidarr = malloc(sizeof(efi_guid_t) * num_guids);
+
+	for (i = 0; i < num_guids; i++)
+		memcpy(&guidarr[i], guids[i], sizeof(efi_guid_t));
+
+	efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid,
+			&devpath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (EFI_ERROR(efiret))
+		return ERR_PTR(-EINVAL);
+
+	efidev = xzalloc(sizeof(*efidev));
+
+	efidev->guids = guidarr;
+	efidev->num_guids = num_guids;
+	efidev->handle = handle;
+	efidev->dev.bus = &efi_bus;
+	efidev->dev.id = DEVICE_ID_SINGLE;
+	efidev->dev.info = efi_devinfo;
+	efidev->devpath = devpath;
+
+	BS->handle_protocol(handle, &guidarr[0], &efidev->protocol);
+
+	sprintf(efidev->dev.name, "handle-%p", handle);
+
+	efidev->parent_handle = efi_find_parent(efidev->handle);
+
+	return efidev;
+}
+
+
+static int efi_register_device(struct efi_device *efidev)
+{
+	char *dev_path_str;
+	struct efi_device *parent;
+	int ret;
+
+	if (efi_find_device(efidev->handle))
+		return -EEXIST;
+
+	if (efidev->parent_handle) {
+		parent = efi_find_device(efidev->parent_handle);
+		if (!parent)
+			return -EINVAL;
+
+		efidev->dev.parent = &parent->dev;
+	}
+
+	ret = register_device(&efidev->dev);
+	if (ret)
+		return ret;
+
+	dev_path_str = device_path_to_str(efidev->devpath);
+	if (dev_path_str) {
+		dev_add_param_fixed(&efidev->dev, "devpath", dev_path_str);
+		free(dev_path_str);
+	}
+
+	debug("registered efi device %s\n", dev_name(&efidev->dev));
+
+	return 0;
+}
+
+/**
+ * efi_register_devices - iterate over all EFI handles and register
+ *                        the devices found
+ *
+ * in barebox we treat all EFI handles which support the device_path
+ * protocol as devices. This function iterates over all handles and
+ * registers the corresponding devices. efi_register_devices is safe
+ * to call multiple times. Already registered devices will be ignored.
+ *
+ */
+void efi_register_devices(void)
+{
+	unsigned long handle_count = 0;
+        efi_handle_t *handles = NULL;
+	unsigned long num_guids;
+	efi_guid_t **guids;
+	int ret, i;
+	struct efi_device **efidevs;
+	int registered;
+
+	ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles);
+	if (ret)
+		return;
+
+	efidevs = xzalloc(handle_count * sizeof(struct efi_device *));
+
+	for (i = 0; i < handle_count; i++) {
+		BS->protocols_per_handle(handles[i], &guids, &num_guids);
+
+		efidevs[i] = efi_add_device(handles[i], guids, num_guids);
+	}
+
+	/*
+	 * We have a list of devices we want to register, but can only
+	 * register a device when all parents are registered already.
+	 * Do this by continiously iterating over the list until no
+	 * further devices are registered.
+	 */
+	do {
+		registered = 0;
+
+		for (i = 0; i < handle_count; i++) {
+			if (IS_ERR(efidevs[i]))
+				continue;
+
+			ret = efi_register_device(efidevs[i]);
+			if (!ret) {
+				efidevs[i] = ERR_PTR(-EEXIST);
+				registered = 1;
+			}
+		}
+	} while (registered);
+
+	free(efidevs);
+	free(handles);
+}
+
+int efi_connect_all(void)
+{
+	efi_status_t  efiret;
+	unsigned long handle_count;
+	efi_handle_t *handle_buffer;
+	int i;
+
+	efiret = BS->locate_handle_buffer(all_handles, NULL, NULL, &handle_count,
+			&handle_buffer);
+	if (EFI_ERROR(efiret))
+		return -efi_errno(efiret);
+
+	for (i = 0; i < handle_count; i++)
+		efiret = BS->connect_controller(handle_buffer[i], NULL, NULL, true);
+
+	if (handle_buffer)
+		BS->free_pool(handle_buffer);
+
+	return 0;
+}
+
+static int efi_bus_match(struct device_d *dev, struct driver_d *drv)
+{
+	struct efi_driver *efidrv = to_efi_driver(drv);
+	struct efi_device *efidev = to_efi_device(dev);
+	int i;
+
+	for (i = 0; i < efidev->num_guids; i++) {
+		if (!memcmp(&efidrv->guid, &efidev->guids[i], sizeof(efi_guid_t)))
+			return 0;
+	}
+
+	return 1;
+}
+
+static int efi_bus_probe(struct device_d *dev)
+{
+	struct efi_driver *efidrv = to_efi_driver(dev->driver);
+	struct efi_device *efidev = to_efi_device(dev);
+
+	return efidrv->probe(efidev);
+}
+
+static void efi_bus_remove(struct device_d *dev)
+{
+	struct efi_driver *efidrv = to_efi_driver(dev->driver);
+	struct efi_device *efidev = to_efi_device(dev);
+
+	return efidrv->remove(efidev);
+}
+
+struct bus_type efi_bus = {
+	.name = "efi",
+	.match = efi_bus_match,
+	.probe = efi_bus_probe,
+	.remove = efi_bus_remove,
+};
+
+static int efi_init_devices(void)
+{
+	bus_register(&efi_bus);
+
+	efi_register_devices();
+
+	return 0;
+}
+core_initcall(efi_init_devices);
diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c
new file mode 100644
index 0000000..5cbc5df
--- /dev/null
+++ b/arch/efi/efi/efi-image.c
@@ -0,0 +1,105 @@
+/*
+ * efi-image.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <sizes.h>
+#include <memory.h>
+#include <command.h>
+#include <magicvar.h>
+#include <init.h>
+#include <driver.h>
+#include <io.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/err.h>
+#include <boot.h>
+#include <fs.h>
+#include <binfmt.h>
+#include <wchar.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+static int efi_execute_image(const char *file)
+{
+	void *exe;
+	size_t size;
+	efi_handle_t handle;
+	efi_status_t efiret;
+	const char *options;
+	efi_loaded_image_t *loaded_image;
+
+	exe = read_file(file, &size);
+	if (!exe)
+		return -EINVAL;
+
+	efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe, size,
+			&handle);
+	if (EFI_ERROR(efiret)) {
+		pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
+		return -efi_errno(efiret);;
+	};
+
+	efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid,
+			(void **)&loaded_image,
+			efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (EFI_ERROR(efiret))
+		return -efi_errno(efiret);
+
+	options = linux_bootargs_get();
+	loaded_image->load_options = strdup_char_to_wchar(options);
+	loaded_image->load_options_size = (strlen(options) + 1) * sizeof(wchar_t);
+
+	efiret = BS->start_image(handle, NULL, NULL);
+
+	efi_connect_all();
+	efi_register_devices();
+
+	return 0;
+}
+
+static int do_bootm_efi(struct image_data *data)
+{
+	return efi_execute_image(data->os_file);
+}
+
+static struct image_handler efi_handle_tr = {
+	.name = "EFI Application",
+	.bootm = do_bootm_efi,
+	.filetype = filetype_dos,
+};
+
+static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv)
+{
+	return efi_execute_image(file);
+}
+
+static struct binfmt_hook binfmt_efi_hook = {
+	.type = filetype_dos,
+	.hook = efi_execute,
+};
+
+static int efi_register_image_handler(void)
+{
+	register_image_handler(&efi_handle_tr);
+	binfmt_register(&binfmt_efi_hook);
+
+	return 0;
+}
+late_initcall(efi_register_image_handler);
diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c
new file mode 100644
index 0000000..48b7d9a
--- /dev/null
+++ b/arch/efi/efi/efi.c
@@ -0,0 +1,342 @@
+/*
+ * efi.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <sizes.h>
+#include <memory.h>
+#include <clock.h>
+#include <command.h>
+#include <magicvar.h>
+#include <init.h>
+#include <driver.h>
+#include <ns16550.h>
+#include <io.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/err.h>
+#include <boot.h>
+#include <fs.h>
+#include <binfmt.h>
+#include <wchar.h>
+#include <envfs.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+efi_runtime_services_t *RT;
+efi_boot_services_t *BS;
+efi_system_table_t *efi_sys_table;
+efi_handle_t efi_parent_image;
+struct efi_device_path *efi_device_path;
+efi_loaded_image_t *efi_loaded_image;
+
+void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size)
+{
+	efi_status_t efiret;
+	void *buf;
+	unsigned long size = 0;
+	s16 *name16 = strdup_char_to_wchar(name);
+
+	efiret = RT->get_variable(name16, vendor, NULL, &size, NULL);
+
+	if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) {
+		buf = ERR_PTR(-efi_errno(efiret));
+		goto out;
+	}
+
+	buf = malloc(size);
+	if (!buf) {
+		buf = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	efiret = RT->get_variable(name16, vendor, NULL, &size, buf);
+	if (EFI_ERROR(efiret)) {
+		free(buf);
+		buf = ERR_PTR(-efi_errno(efiret));
+		goto out;
+	}
+
+	if (var_size)
+		*var_size = size;
+
+out:
+	free(name16);
+
+	return buf;
+}
+
+struct efi_boot {
+	u32 attributes;
+	u16 file_path_len;
+	char *description;
+	struct efi_device_path *path;
+	void *binary;
+};
+
+struct efi_boot *efi_get_boot(int num)
+{
+	struct efi_boot *boot = xzalloc(sizeof(*boot));
+	void *buf, *ptr;
+	int size;
+	char *name;
+
+	name = asprintf("Boot%04X", num);
+
+	buf = efi_get_global_var(name, &size);
+
+	free(name);
+
+	if (!buf) {
+		free(boot);
+		return NULL;
+	}
+
+	ptr = buf;
+
+	boot->attributes = *(u32 *)ptr;
+
+	ptr += sizeof(u32);
+
+	boot->file_path_len = *(u16 *)ptr;
+
+	ptr += sizeof(u16);
+
+	boot->description = strdup_wchar_to_char(ptr);
+
+	ptr += (strlen(boot->description) + 1) * 2;
+
+	printf("description: %s\n", boot->description);
+
+	boot->path = memdup(ptr, boot->file_path_len);
+
+	printf("path: %s\n", device_path_to_str(boot->path));
+
+	return boot;
+}
+
+static int misc_init(void)
+{
+	efi_get_boot(1);
+	efi_get_boot(2);
+	efi_get_boot(3);
+
+	return 0;
+}
+late_initcall(misc_init);
+
+const char *efi_strerror(efi_status_t err)
+{
+	const char *str;
+
+	switch (err) {
+	case EFI_SUCCESS: str = "Success"; break;
+	case EFI_LOAD_ERROR: str = "Load Error"; break;
+	case EFI_INVALID_PARAMETER: str = "Invalid Parameter"; break;
+	case EFI_UNSUPPORTED: str = "Unsupported"; break;
+	case EFI_BAD_BUFFER_SIZE: str = "Bad Buffer Size"; break;
+	case EFI_BUFFER_TOO_SMALL: str = "Buffer Too Small"; break;
+	case EFI_NOT_READY: str = "Not Ready"; break;
+	case EFI_DEVICE_ERROR: str = "Device Error"; break;
+	case EFI_WRITE_PROTECTED: str = "Write Protected"; break;
+	case EFI_OUT_OF_RESOURCES: str = "Out of Resources"; break;
+	case EFI_VOLUME_CORRUPTED: str = "Volume Corrupt"; break;
+	case EFI_VOLUME_FULL: str = "Volume Full"; break;
+	case EFI_NO_MEDIA: str = "No Media"; break;
+	case EFI_MEDIA_CHANGED: str = "Media changed"; break;
+	case EFI_NOT_FOUND: str = "Not Found"; break;
+	case EFI_ACCESS_DENIED: str = "Access Denied"; break;
+	case EFI_NO_RESPONSE: str = "No Response"; break;
+	case EFI_NO_MAPPING: str = "No mapping"; break;
+	case EFI_TIMEOUT: str = "Time out"; break;
+	case EFI_NOT_STARTED: str = "Not started"; break;
+	case EFI_ALREADY_STARTED: str = "Already started"; break;
+	case EFI_ABORTED: str = "Aborted"; break;
+	case EFI_ICMP_ERROR: str = "ICMP Error"; break;
+	case EFI_TFTP_ERROR: str = "TFTP Error"; break;
+	case EFI_PROTOCOL_ERROR: str = "Protocol Error"; break;
+	case EFI_INCOMPATIBLE_VERSION: str = "Incompatible Version"; break;
+	case EFI_SECURITY_VIOLATION: str = "Security Violation"; break;
+	case EFI_CRC_ERROR: str = "CRC Error"; break;
+	case EFI_END_OF_MEDIA: str = "End of Media"; break;
+	case EFI_END_OF_FILE: str = "End of File"; break;
+	case EFI_INVALID_LANGUAGE: str = "Invalid Language"; break;
+	case EFI_COMPROMISED_DATA: str = "Compromised Data"; break;
+	default: str = "unknown error";
+	}
+
+	return str;
+}
+
+int efi_errno(efi_status_t err)
+{
+	int ret;
+
+	switch (err) {
+	case EFI_SUCCESS: ret = 0; break;
+	case EFI_LOAD_ERROR: ret = EIO; break;
+	case EFI_INVALID_PARAMETER: ret = EINVAL; break;
+	case EFI_UNSUPPORTED: ret = ENOTSUPP; break;
+	case EFI_BAD_BUFFER_SIZE: ret = EINVAL; break;
+	case EFI_BUFFER_TOO_SMALL: ret = EINVAL; break;
+	case EFI_NOT_READY: ret = EAGAIN; break;
+	case EFI_DEVICE_ERROR: ret = EIO; break;
+	case EFI_WRITE_PROTECTED: ret = EROFS; break;
+	case EFI_OUT_OF_RESOURCES: ret = ENOMEM; break;
+	case EFI_VOLUME_CORRUPTED: ret = EIO; break;
+	case EFI_VOLUME_FULL: ret = ENOSPC; break;
+	case EFI_NO_MEDIA: ret = ENOMEDIUM; break;
+	case EFI_MEDIA_CHANGED: ret = ENOMEDIUM; break;
+	case EFI_NOT_FOUND: ret = ENODEV; break;
+	case EFI_ACCESS_DENIED: ret = EACCES; break;
+	case EFI_NO_RESPONSE: ret = ETIMEDOUT; break;
+	case EFI_NO_MAPPING: ret = EINVAL; break;
+	case EFI_TIMEOUT: ret = ETIMEDOUT; break;
+	case EFI_NOT_STARTED: ret = EINVAL; break;
+	case EFI_ALREADY_STARTED: ret = EINVAL; break;
+	case EFI_ABORTED: ret = EINTR; break;
+	case EFI_ICMP_ERROR: ret = EINVAL; break;
+	case EFI_TFTP_ERROR: ret = EINVAL; break;
+	case EFI_PROTOCOL_ERROR: ret = EPROTO; break;
+	case EFI_INCOMPATIBLE_VERSION: ret = EINVAL; break;
+	case EFI_SECURITY_VIOLATION: ret = EINVAL; break;
+	case EFI_CRC_ERROR: ret = EINVAL; break;
+	case EFI_END_OF_MEDIA: ret = EINVAL; break;
+	case EFI_END_OF_FILE: ret = EINVAL; break;
+	case EFI_INVALID_LANGUAGE: ret = EINVAL; break;
+	case EFI_COMPROMISED_DATA: ret = EINVAL; break;
+	default: ret = EINVAL;
+	}
+
+	return ret;
+}
+
+static struct NS16550_plat ns16550_plat = {
+	.clock = 115200 * 16,
+};
+
+static int efi_console_init(void)
+{
+	add_generic_device("efi-stdio", DEVICE_ID_SINGLE, NULL, 0 , 0, 0, NULL);
+
+	if (IS_ENABLED(CONFIG_ARCH_EFI_REGISTER_COM1))
+		add_ns16550_device(0, 0x3f8, 0x10, IORESOURCE_IO | IORESOURCE_MEM_8BIT,
+				&ns16550_plat);
+
+	return 0;
+}
+console_initcall(efi_console_init);
+
+void reset_cpu(unsigned long addr)
+{
+	BS->exit(efi_parent_image, EFI_SUCCESS, 0, NULL);
+
+	while(1);
+}
+
+extern char image_base[];
+extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
+		  __barebox_initcalls_end[];
+
+/*
+ * We have a position independent binary generated with -fpic. This function
+ * fixes the linker generated tables.
+ */
+static void fixup_tables(void)
+{
+	initcall_t *initcall;
+	unsigned long offset = (unsigned long)image_base;
+	struct command *cmdtp;
+	struct magicvar *m;
+
+	for (initcall = __barebox_initcalls_start;
+			initcall < __barebox_initcalls_end; initcall++)
+		*initcall += offset;
+
+	for (cmdtp = &__barebox_cmd_start;
+			cmdtp != &__barebox_cmd_end;
+			cmdtp++) {
+		cmdtp->name += offset;
+		cmdtp->cmd += offset;
+		if (cmdtp->complete)
+			cmdtp->complete += offset;
+		if (cmdtp->desc)
+			cmdtp->desc += offset;
+		if (cmdtp->help)
+			cmdtp->help += offset;
+		if (cmdtp->opts)
+			cmdtp->opts += offset;
+		if (cmdtp->aliases)
+			cmdtp->aliases = (void *)cmdtp->aliases + offset;
+	}
+
+	for (m = &__barebox_magicvar_start;
+			m != &__barebox_magicvar_end;
+			m++) {
+		m->name += offset;
+		m->description += offset;
+	}
+}
+
+static int efi_init(void)
+{
+	barebox_set_model("barebox EFI payload");
+
+	defaultenv_append_directory(env_efi);
+
+	return 0;
+}
+device_initcall(efi_init);
+
+/**
+ * efi-main - Entry point for EFI images
+ */
+efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table)
+{
+	void *mem;
+	efi_status_t efiret;
+
+#ifdef DEBUG
+	sys_table->con_out->output_string(sys_table->con_out, L"barebox\n");
+#endif
+
+	BS = sys_table->boottime;
+
+	efi_parent_image = image;
+	efi_sys_table = sys_table;
+	RT = sys_table->runtime;
+
+	efiret = BS->open_protocol(efi_parent_image, &efi_loaded_image_protocol_guid,
+			(void **)&efi_loaded_image,
+			efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (!EFI_ERROR(efiret))
+		BS->handle_protocol(efi_loaded_image->device_handle,
+				&efi_device_path_protocol_guid, (void **)&efi_device_path);
+
+	fixup_tables();
+
+	BS->allocate_pool(efi_loaded_image->image_data_type, SZ_16M, &mem);
+	mem_malloc_init(mem, mem + SZ_16M);
+
+	efi_clocksource_init();
+
+	start_barebox();
+
+	return EFI_SUCCESS;
+}
diff --git a/arch/efi/efi/env-efi/network/eth0-discover b/arch/efi/efi/env-efi/network/eth0-discover
new file mode 100644
index 0000000..62c31a5
--- /dev/null
+++ b/arch/efi/efi/env-efi/network/eth0-discover
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+for i in /boot/network-drivers/*; do
+	$i;
+done
diff --git a/arch/efi/include/asm/barebox.h b/arch/efi/include/asm/barebox.h
new file mode 100644
index 0000000..2997587
--- /dev/null
+++ b/arch/efi/include/asm/barebox.h
@@ -0,0 +1 @@
+/* dummy */
diff --git a/arch/efi/include/asm/bitops.h b/arch/efi/include/asm/bitops.h
new file mode 100644
index 0000000..94646d4
--- /dev/null
+++ b/arch/efi/include/asm/bitops.h
@@ -0,0 +1,15 @@
+#ifndef _SANDBOX_BITOPS_H
+#define _SANDBOX_BITOPS_H
+
+/* nothing but the defaults.. */
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/ops.h>
+
+#endif
diff --git a/arch/efi/include/asm/byteorder.h b/arch/efi/include/asm/byteorder.h
new file mode 100644
index 0000000..37316f2
--- /dev/null
+++ b/arch/efi/include/asm/byteorder.h
@@ -0,0 +1,8 @@
+#ifndef _I386_BYTEORDER_H
+#define _I386_BYTEORDER_H
+
+#include <asm/types.h>
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _I386_BYTEORDER_H */
diff --git a/arch/efi/include/asm/common.h b/arch/efi/include/asm/common.h
new file mode 100644
index 0000000..b0e6b7f
--- /dev/null
+++ b/arch/efi/include/asm/common.h
@@ -0,0 +1,4 @@
+#ifndef ASM_COMMON_H
+#define ASM_COMMON_H
+
+#endif /* ASM_COMMON_H */
diff --git a/arch/efi/include/asm/dma.h b/arch/efi/include/asm/dma.h
new file mode 100644
index 0000000..4595367
--- /dev/null
+++ b/arch/efi/include/asm/dma.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#ifndef __ASM_DMA_H
+#define __ASM_DMA_H
+
+/* empty*/
+
+#endif /* __ASM_DMA_H */
diff --git a/arch/efi/include/asm/elf.h b/arch/efi/include/asm/elf.h
new file mode 100644
index 0000000..ddde035
--- /dev/null
+++ b/arch/efi/include/asm/elf.h
@@ -0,0 +1,60 @@
+#ifndef __ASM_SANDBOX_ELF_H__
+#define __ASM_SANDBOX_ELF_H__
+
+#ifdef __i386__
+
+typedef struct user_fxsr_struct elf_fpxregset_t;
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_386
+
+#else
+
+/* x86-64 relocation types */
+#define R_X86_64_NONE		0	/* No reloc */
+#define R_X86_64_64		1	/* Direct 64 bit  */
+#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
+#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
+#define R_X86_64_PLT32		4	/* 32 bit PLT address */
+#define R_X86_64_COPY		5	/* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
+#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
+#define R_X86_64_RELATIVE	8	/* Adjust by program base */
+#define R_X86_64_GOTPCREL	9	/* 32 bit signed pc relative
+					   offset to GOT */
+#define R_X86_64_32		10	/* Direct 32 bit zero extended */
+#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
+#define R_X86_64_16		12	/* Direct 16 bit zero extended */
+#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
+#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
+#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM		16
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_X86_64
+
+#endif
+
+#endif /* __ASM_SANDBOX_ELF_H__ */
diff --git a/arch/efi/include/asm/io.h b/arch/efi/include/asm/io.h
new file mode 100644
index 0000000..ac8a9c1
--- /dev/null
+++ b/arch/efi/include/asm/io.h
@@ -0,0 +1,55 @@
+#ifndef __ASM_SANDBOX_IO_H
+#define __ASM_SANDBOX_IO_H
+
+#define build_mmio_read(name, size, type, reg, barrier) \
+ static inline type name(const volatile void *addr) \
+ { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
+ :"m" (*(volatile type*)addr) barrier); return ret; }
+
+build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
+build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
+build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
+
+#define build_mmio_write(name, size, type, reg, barrier) \
+ static inline void name(type val, volatile void *addr) \
+ { asm volatile("mov" size " %0,%1": :reg (val), \
+ "m" (*(volatile type*)addr) barrier); }
+
+build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
+build_mmio_write(writew, "w", unsigned short, "r", :"memory")
+build_mmio_write(writel, "l", unsigned int, "r", :"memory")
+
+#define BUILDIO(bwl, bw, type)						\
+static inline void out##bwl(unsigned type value, int port)		\
+{									\
+	asm volatile("out" #bwl " %" #bw "0, %w1"			\
+		     : : "a"(value), "Nd"(port));			\
+}									\
+									\
+static inline unsigned type in##bwl(int port)				\
+{									\
+	unsigned type value;						\
+	asm volatile("in" #bwl " %w1, %" #bw "0"			\
+		     : "=a"(value) : "Nd"(port));			\
+	return value;							\
+}									\
+									\
+static inline void outs##bwl(int port, const void *addr, unsigned long count) \
+{									\
+	asm volatile("rep; outs" #bwl					\
+		     : "+S"(addr), "+c"(count) : "d"(port));		\
+}									\
+									\
+static inline void ins##bwl(int port, void *addr, unsigned long count)	\
+{									\
+	asm volatile("rep; ins" #bwl					\
+		     : "+D"(addr), "+c"(count) : "d"(port));		\
+}
+
+BUILDIO(b, b, char)
+BUILDIO(w, w, short)
+BUILDIO(l, , int)
+
+#define  IO_SPACE_LIMIT  0xffff
+
+#endif /* __ASM_SANDBOX_IO_H */
diff --git a/arch/efi/include/asm/posix_types.h b/arch/efi/include/asm/posix_types.h
new file mode 100644
index 0000000..6985b8e
--- /dev/null
+++ b/arch/efi/include/asm/posix_types.h
@@ -0,0 +1,93 @@
+#ifndef __ARCH_I386_POSIX_TYPES_H
+#define __ARCH_I386_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+/*
+ * Most 32 bit architectures use "unsigned int" size_t,
+ * and all 64 bit architectures use "unsigned long" size_t.
+ *
+ * TODO: It's not clean to use __x86_64__ here. It's better
+ * to check on __BITS_PER_LONG here. But this is wrong set in
+ * arch/sandbox/include/asm/types.h.
+ */
+#ifdef __x86_64__
+typedef unsigned long	__kernel_size_t;
+typedef long		__kernel_ssize_t;
+typedef long		__kernel_ptrdiff_t;
+#else
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+#endif
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+
+typedef unsigned short	__kernel_old_uid_t;
+typedef unsigned short	__kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+	int	val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+	int	__val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef	__FD_SET
+#define __FD_SET(fd,fdsetp) \
+		__asm__ __volatile__("btsl %1,%0": \
+			"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef	__FD_CLR
+#define __FD_CLR(fd,fdsetp) \
+		__asm__ __volatile__("btrl %1,%0": \
+			"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef	__FD_ISSET
+#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
+		unsigned char __result; \
+		__asm__ __volatile__("btl %1,%2 ; setb %0" \
+			:"=q" (__result) :"r" ((int) (fd)), \
+			"m" (*(__kernel_fd_set *) (fdsetp))); \
+		__result; }))
+
+#undef	__FD_ZERO
+#define __FD_ZERO(fdsetp) \
+do { \
+	int __d0, __d1; \
+	__asm__ __volatile__("cld ; rep ; stosl" \
+			:"=m" (*(__kernel_fd_set *) (fdsetp)), \
+			  "=&c" (__d0), "=&D" (__d1) \
+			:"a" (0), "1" (__FDSET_LONGS), \
+			"2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
+} while (0)
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif
diff --git a/arch/efi/include/asm/sections.h b/arch/efi/include/asm/sections.h
new file mode 100644
index 0000000..2b8c516
--- /dev/null
+++ b/arch/efi/include/asm/sections.h
@@ -0,0 +1 @@
+#include <asm-generic/sections.h>
diff --git a/arch/efi/include/asm/string.h b/arch/efi/include/asm/string.h
new file mode 100644
index 0000000..2997587
--- /dev/null
+++ b/arch/efi/include/asm/string.h
@@ -0,0 +1 @@
+/* dummy */
diff --git a/arch/efi/include/asm/swab.h b/arch/efi/include/asm/swab.h
new file mode 100644
index 0000000..60a9012
--- /dev/null
+++ b/arch/efi/include/asm/swab.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+/* nothing. use generic functions */
+
+#endif /* _ASM_SWAB_H */
diff --git a/arch/efi/include/asm/types.h b/arch/efi/include/asm/types.h
new file mode 100644
index 0000000..3204448
--- /dev/null
+++ b/arch/efi/include/asm/types.h
@@ -0,0 +1,73 @@
+#ifndef __ASM_I386_TYPES_H
+#define __ASM_I386_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+#ifdef __x86_64__
+/*
+ * This is used in dlmalloc. On X86_64 we need it to be
+ * 64 bit
+ */
+#define INTERNAL_SIZE_T unsigned long
+
+/*
+ * This is a Kconfig variable in the Kernel, but we want to detect
+ * this during compile time, so we set it here.
+ */
+#define CONFIG_PHYS_ADDR_T_64BIT
+
+#endif
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#ifdef __x86_64__
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif
+
+/* Dma addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+
+#endif /* __KERNEL__ */
+
+#endif
+
+#endif
diff --git a/arch/efi/include/asm/unaligned.h b/arch/efi/include/asm/unaligned.h
new file mode 100644
index 0000000..d02da6e
--- /dev/null
+++ b/arch/efi/include/asm/unaligned.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_SANDBOX_UNALIGNED_H
+#define _ASM_SANDBOX_UNALIGNED_H
+
+/*
+ * The architecture sandbox is compiled on can do unaligned accesses itself.
+ */
+
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define get_unaligned __get_unaligned_le
+#define put_unaligned __put_unaligned_le
+#else
+#define get_unaligned __get_unaligned_be
+#define put_unaligned __put_unaligned_be
+#endif
+
+#endif /* _ASM_SANDBOX_UNALIGNED_H */
diff --git a/arch/efi/include/mach/debug_ll.h b/arch/efi/include/mach/debug_ll.h
new file mode 100644
index 0000000..0fb2cb8
--- /dev/null
+++ b/arch/efi/include/mach/debug_ll.h
@@ -0,0 +1,20 @@
+#ifndef __MACH_DEBUG_LL_H__
+#define __MACH_DEBUG_LL_H__
+
+#define EFI_DEBUG 0
+#define EFI_DEBUG_CLEAR_MEMORY 0
+
+#include <efi.h>
+#include <mach/efi.h>
+
+static inline void PUTC_LL(char c)
+{
+	uint16_t str[2] = {};
+	struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out;
+
+	str[0] = c;
+
+	con_out->output_string(con_out, str);
+}
+
+#endif
diff --git a/arch/efi/include/mach/efi-device.h b/arch/efi/include/mach/efi-device.h
new file mode 100644
index 0000000..fe074a4
--- /dev/null
+++ b/arch/efi/include/mach/efi-device.h
@@ -0,0 +1,45 @@
+#ifndef __MACH_EFI_DEVICE_H
+#define __MACH_EFI_DEVICE_H
+
+struct efi_device {
+	struct device_d dev;
+	efi_guid_t *guids;
+	int num_guids;
+	efi_handle_t handle;
+	efi_handle_t parent_handle;
+	void *protocol;
+	struct efi_device_path *devpath;
+};
+
+struct efi_driver {
+	struct driver_d driver;
+	int (*probe)(struct efi_device *efidev);
+	void (*remove)(struct efi_device *efidev);
+	efi_guid_t guid;
+};
+
+extern struct bus_type efi_bus;
+
+static inline struct efi_device *to_efi_device(struct device_d *dev)
+{
+	return container_of(dev, struct efi_device, dev);
+}
+
+static inline struct efi_driver *to_efi_driver(struct driver_d *drv)
+{
+	return container_of(drv, struct efi_driver, driver);
+}
+
+#define device_efi_driver(drv)	\
+	register_driver_macro(device, efi, drv)
+
+static inline int efi_driver_register(struct efi_driver *efidrv)
+{
+	efidrv->driver.bus = &efi_bus;
+	return register_driver(&efidrv->driver);
+}
+
+int efi_connect_all(void);
+void efi_register_devices(void);
+
+#endif /* __MACH_EFI_DEVICE_H */
diff --git a/arch/efi/include/mach/efi.h b/arch/efi/include/mach/efi.h
new file mode 100644
index 0000000..1e9782a
--- /dev/null
+++ b/arch/efi/include/mach/efi.h
@@ -0,0 +1,24 @@
+#ifndef __MACH_EFI_H
+#define __MACH_EFI_H
+
+#include <efi.h>
+
+const char *efi_strerror(efi_status_t err);
+
+extern efi_system_table_t *efi_sys_table;
+extern efi_handle_t efi_parent_image;
+extern struct efi_device_path *efi_device_path;
+extern efi_loaded_image_t *efi_loaded_image;
+
+int efi_errno(efi_status_t err);
+
+int efi_clocksource_init(void);
+
+void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size);
+
+static inline void *efi_get_global_var(char *name, int *var_size)
+{
+	return efi_get_variable(name, &efi_global_variable_guid, var_size);
+}
+
+#endif /* __MACH_EFI_H */
diff --git a/arch/efi/lib/.gitignore b/arch/efi/lib/.gitignore
new file mode 100644
index 0000000..847e317
--- /dev/null
+++ b/arch/efi/lib/.gitignore
@@ -0,0 +1,2 @@
+elf_x86_64_efi.lds
+elf_ia32_efi.lds
diff --git a/arch/efi/lib/Makefile b/arch/efi/lib/Makefile
new file mode 100644
index 0000000..c8a97ba
--- /dev/null
+++ b/arch/efi/lib/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_X86_64) += reloc_x86_64.o crt0-efi-x86_64.o
+obj-$(CONFIG_X86_32) += reloc_ia32.o crt0-efi-ia32.o
+extra-$(CONFIG_X86_32) += elf_ia32_efi.lds
+extra-$(CONFIG_X86_64) += elf_x86_64_efi.lds
diff --git a/arch/efi/lib/crt0-efi-ia32.S b/arch/efi/lib/crt0-efi-ia32.S
new file mode 100644
index 0000000..6f0f2e8
--- /dev/null
+++ b/arch/efi/lib/crt0-efi-ia32.S
@@ -0,0 +1,76 @@
+/* crt0-efi-ia32.S - x86 EFI startup code.
+   Copyright (C) 1999 Hewlett-Packard Co.
+	Contributed by David Mosberger <davidm@hpl.hp.com>.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+    * Neither the name of Hewlett-Packard Co. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+
+	.text
+	.align 4
+
+	.globl _start
+_start:
+	pushl %ebp
+	movl %esp,%ebp
+
+	pushl 12(%ebp)			# copy "image" argument
+	pushl  8(%ebp)			# copy "systab" argument
+
+	call 0f
+0:	popl %eax
+	movl %eax,%ebx
+
+	addl $image_base-0b,%eax		# %eax = ldbase
+	addl $_DYNAMIC-0b,%ebx		# %ebx = _DYNAMIC
+
+	pushl %ebx			# pass _DYNAMIC as second argument
+	pushl %eax			# pass ldbase as first argument
+	call _relocate
+	popl %ebx
+	popl %ebx
+	testl %eax,%eax
+	jne .exit
+
+	call efi_main			# call app with "image" and "systab" argument
+
+.exit:	leave
+	ret
+
+	/* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */
+
+	.data
+dummy:	.long	0
+
+#define IMAGE_REL_ABSOLUTE	0
+	.section .reloc
+	.long	dummy					/* Page RVA */
+	.long	10					/* Block Size (2*4+2) */
+	.word	(IMAGE_REL_ABSOLUTE<<12) +  0		/* reloc for dummy */
diff --git a/arch/efi/lib/crt0-efi-x86_64.S b/arch/efi/lib/crt0-efi-x86_64.S
new file mode 100644
index 0000000..aa03106
--- /dev/null
+++ b/arch/efi/lib/crt0-efi-x86_64.S
@@ -0,0 +1,75 @@
+/* crt0-efi-x86_64.S - x86_64 EFI startup code.
+   Copyright (C) 1999 Hewlett-Packard Co.
+	Contributed by David Mosberger <davidm@hpl.hp.com>.
+   Copyright (C) 2005 Intel Co.
+	Contributed by Fenghua Yu <fenghua.yu@intel.com>.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+    * Neither the name of Hewlett-Packard Co. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+	.text
+	.align 4
+
+	.globl _start
+_start:
+	subq $8, %rsp
+	pushq %rcx
+	pushq %rdx
+
+0:
+	lea image_base(%rip), %rdi
+	lea _DYNAMIC(%rip), %rsi
+
+	popq %rcx
+	popq %rdx
+	pushq %rcx
+	pushq %rdx
+	call _relocate
+
+	popq %rdi
+	popq %rsi
+
+	call efi_main
+	addq $8, %rsp
+
+.exit:
+	ret
+
+	/* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */
+
+	.data
+dummy:	.long	0
+
+#define IMAGE_REL_ABSOLUTE	0
+	.section .reloc, "a"
+label1:
+	.long	dummy-label1				/* Page RVA */
+	.long	10					/* Block Size (2*4+2) */
+	.word	(IMAGE_REL_ABSOLUTE<<12) +  0		/* reloc for dummy */
diff --git a/arch/efi/lib/elf_ia32_efi.lds.S b/arch/efi/lib/elf_ia32_efi.lds.S
new file mode 100644
index 0000000..a5f6287
--- /dev/null
+++ b/arch/efi/lib/elf_ia32_efi.lds.S
@@ -0,0 +1,102 @@
+#include <asm-generic/barebox.lds.h>
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0;
+	image_base = .;
+	.hash : { *(.hash) }	/* this MUST come first! */
+	. = ALIGN(4096);
+	.text :
+	{
+		_stext = .;
+		_text = .;
+		*(.text)
+		*(.text.*)
+		*(.gnu.linkonce.t.*)
+	}
+
+	_etext = .;
+
+	. = ALIGN(4096);
+	.sdata : {
+		*(.got.plt)
+		*(.got)
+		*(.srodata)
+		*(.sdata)
+		*(.sbss)
+		*(.scommon)
+	}
+
+	. = ALIGN(4096);
+	_sdata = .;
+
+	.data : {
+		*(.rodata*)
+		*(.data)
+		*(.data1)
+		*(.data.*)
+		*(.sdata)
+		*(.got.plt)
+		*(.got)
+		/* the EFI loader doesn't seem to like a .bss section, so we stick
+		 * it all into .data: */
+		*(.sbss)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss)
+		*(COMMON)
+	}
+
+	. = ALIGN(64);
+
+	__barebox_initcalls_start = .;
+	__barebox_initcalls : { INITCALLS }
+	__barebox_initcalls_end = .;
+
+	. = ALIGN(64);
+	__barebox_magicvar_start = .;
+	.barebox_magicvar : { BAREBOX_MAGICVARS }
+	__barebox_magicvar_end = .;
+
+	. = ALIGN(64);
+	__barebox_cmd_start = .;
+	__barebox_cmd : { BAREBOX_CMDS }
+	__barebox_cmd_end = .;
+
+	. = ALIGN(4096);
+	.dynamic : { *(.dynamic) }
+	. = ALIGN(4096);
+	.rel : {
+		*(.rel.data)
+		*(.rel.data.*)
+		*(.rel.got)
+		*(.rel.stab)
+		*(.data.rel.ro.local)
+		*(.data.rel.local)
+		*(.data.rel.ro)
+		*(.data.rel*)
+	}
+
+	. = ALIGN(4096);
+	.reloc :		/* This is the PECOFF .reloc section! */
+	{
+		*(.reloc)
+	}
+
+	. = ALIGN(4096);
+	.dynsym : { *(.dynsym) }
+	. = ALIGN(4096);
+	.dynstr : { *(.dynstr) }
+	. = ALIGN(4096);
+	/DISCARD/ :
+	{
+		*(.rel.reloc)
+		*(.eh_frame)
+		*(.note.GNU-stack)
+	}
+
+	.comment 0 : { *(.comment) }
+}
diff --git a/arch/efi/lib/elf_x86_64_efi.lds.S b/arch/efi/lib/elf_x86_64_efi.lds.S
new file mode 100644
index 0000000..d48432d
--- /dev/null
+++ b/arch/efi/lib/elf_x86_64_efi.lds.S
@@ -0,0 +1,93 @@
+#include <asm-generic/barebox.lds.h>
+
+/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0;
+	image_base = .;
+	.hash : { *(.hash) }	/* this MUST come first! */
+	. = ALIGN(4096);
+	.eh_frame : {
+		*(.eh_frame)
+	}
+
+	. = ALIGN(4096);
+
+	.text : {
+		_stext = .;
+		_text = .;
+		*(.text)
+		*(.text.*)
+		*(.gnu.linkonce.t.*)
+	}
+
+	_etext = .;
+
+	. = ALIGN(4096);
+
+	.reloc : {
+		*(.reloc)
+	}
+
+	. = ALIGN(4096);
+	_sdata = .;
+
+	.data : {
+		*(.rodata*)
+		*(.got.plt)
+		*(.got)
+		*(.data*)
+		*(.sdata)
+		/* the EFI loader doesn't seem to like a .bss section, so we stick
+		 * it all into .data: */
+		*(.sbss)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss)
+		*(COMMON)
+		*(.rel.local)
+	}
+
+	. = ALIGN(64);
+
+	__barebox_initcalls_start = .;
+	__barebox_initcalls : { INITCALLS }
+	__barebox_initcalls_end = .;
+
+	. = ALIGN(64);
+	__barebox_magicvar_start = .;
+	.barebox_magicvar : { BAREBOX_MAGICVARS }
+	__barebox_magicvar_end = .;
+
+	. = ALIGN(64);
+	__barebox_cmd_start = .;
+	__barebox_cmd : { BAREBOX_CMDS }
+	__barebox_cmd_end = .;
+
+	. = ALIGN(4096);
+	.dynamic : { *(.dynamic) }
+	. = ALIGN(4096);
+
+	.rela : {
+		*(.rela.data*)
+		*(.rela.got)
+		*(.rela.stab)
+	}
+
+	. = ALIGN(4096);
+	.dynsym : { *(.dynsym) }
+	. = ALIGN(4096);
+	.dynstr : { *(.dynstr) }
+	. = ALIGN(4096);
+	.ignored.reloc : {
+		*(.rela.reloc)
+		*(.eh_frame)
+		*(.note.GNU-stack)
+	}
+
+	.comment 0 : { *(.comment) }
+}
diff --git a/arch/efi/lib/reloc_ia32.c b/arch/efi/lib/reloc_ia32.c
new file mode 100644
index 0000000..4692963
--- /dev/null
+++ b/arch/efi/lib/reloc_ia32.c
@@ -0,0 +1,97 @@
+/* reloc_ia32.c - position independent x86 ELF shared object relocator
+   Copyright (C) 1999 Hewlett-Packard Co.
+	Contributed by David Mosberger <davidm@hpl.hp.com>.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+    * Neither the name of Hewlett-Packard Co. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+
+#include <common.h>
+#include <efi.h>
+
+#include <elf.h>
+
+efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
+{
+	long relsz = 0, relent = 0;
+	Elf32_Rel *rel = 0;
+	unsigned long *addr;
+	int i;
+
+	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+		switch (dyn[i].d_tag) {
+			case DT_REL:
+				rel = (Elf32_Rel*)
+					((unsigned long)dyn[i].d_un.d_ptr
+					 + ldbase);
+				break;
+
+			case DT_RELSZ:
+				relsz = dyn[i].d_un.d_val;
+				break;
+
+			case DT_RELENT:
+				relent = dyn[i].d_un.d_val;
+				break;
+
+			case DT_RELA:
+				break;
+
+			default:
+				break;
+		}
+	}
+
+        if (!rel && relent == 0)
+                return EFI_SUCCESS;
+
+	if (!rel || relent == 0)
+		return EFI_LOAD_ERROR;
+
+	while (relsz > 0) {
+		/* apply the relocs */
+		switch (ELF32_R_TYPE (rel->r_info)) {
+			case R_386_NONE:
+				break;
+
+			case R_386_RELATIVE:
+				addr = (unsigned long *)
+					(ldbase + rel->r_offset);
+				*addr += ldbase;
+				break;
+
+			default:
+				break;
+		}
+		rel = (Elf32_Rel*) ((char *) rel + relent);
+		relsz -= relent;
+	}
+	return EFI_SUCCESS;
+}
diff --git a/arch/efi/lib/reloc_x86_64.c b/arch/efi/lib/reloc_x86_64.c
new file mode 100644
index 0000000..1db72f5
--- /dev/null
+++ b/arch/efi/lib/reloc_x86_64.c
@@ -0,0 +1,96 @@
+/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator
+   Copyright (C) 1999 Hewlett-Packard Co.
+	Contributed by David Mosberger <davidm@hpl.hp.com>.
+   Copyright (C) 2005 Intel Co.
+	Contributed by Fenghua Yu <fenghua.yu@intel.com>.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+    * Neither the name of Hewlett-Packard Co. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+
+#include <common.h>
+#include <efi.h>
+
+#include <elf.h>
+
+efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
+{
+	long relsz = 0, relent = 0;
+	Elf64_Rel *rel = 0;
+	unsigned long *addr;
+	int i;
+
+	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+		switch (dyn[i].d_tag) {
+			case DT_RELA:
+				rel = (Elf64_Rel*)
+					((unsigned long)dyn[i].d_un.d_ptr
+					 + ldbase);
+				break;
+
+			case DT_RELASZ:
+				relsz = dyn[i].d_un.d_val;
+				break;
+
+			case DT_RELAENT:
+				relent = dyn[i].d_un.d_val;
+				break;
+
+			default:
+				break;
+		}
+	}
+
+        if (!rel && relent == 0)
+                return EFI_SUCCESS;
+
+	if (!rel || relent == 0)
+		return EFI_LOAD_ERROR;
+
+	while (relsz > 0) {
+		/* apply the relocs */
+		switch (ELF64_R_TYPE (rel->r_info)) {
+			case R_X86_64_NONE:
+				break;
+
+			case R_X86_64_RELATIVE:
+				addr = (unsigned long *)
+					(ldbase + rel->r_offset);
+				*addr += ldbase;
+				break;
+
+			default:
+				break;
+		}
+		rel = (Elf64_Rel*) ((char *) rel + relent);
+		relsz -= relent;
+	}
+	return EFI_SUCCESS;
+}
diff --git a/common/Kconfig b/common/Kconfig
index bba7f15..8b36126 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -64,6 +64,14 @@ config MENUTREE
 	select GLOB
 	select GLOB_SORT
 
+config EFI_GUID
+	bool
+	help
+	  With this option a table of EFI guids is compiled in.
+
+config EFI_DEVICEPATH
+	bool
+
 menu "General Settings"
 
 config LOCALVERSION
diff --git a/common/Makefile b/common/Makefile
index 204241c..4220e15 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -43,7 +43,9 @@ obj-$(CONFIG_RESET_SOURCE)	+= reset_source.o
 obj-$(CONFIG_SHELL_HUSH)	+= hush.o
 obj-$(CONFIG_SHELL_SIMPLE)	+= parser.o
 obj-$(CONFIG_UIMAGE)		+= image.o uimage.o
-obj-$(CONFIG_MENUTREE) += menutree.o
+obj-$(CONFIG_MENUTREE)		+= menutree.o
+obj-$(CONFIG_EFI_GUID)		+= efi-guid.o
+obj-$(CONFIG_EFI_DEVICEPATH)	+= efi-devicepath.o
 
 quiet_cmd_pwd_h = PWDH    $@
 ifdef CONFIG_PASSWORD
diff --git a/common/efi-devicepath.c b/common/efi-devicepath.c
new file mode 100644
index 0000000..2b1d916
--- /dev/null
+++ b/common/efi-devicepath.c
@@ -0,0 +1,1370 @@
+#include <common.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <wchar.h>
+
+struct string {
+	char *str;
+	int len;
+};
+
+char *cprintf(struct string *str, const char *fmt, ...)
+    __attribute__ ((format(__printf__, 2, 3)));
+
+char *cprintf(struct string *str, const char *fmt, ...)
+{
+	va_list args;
+	int len;
+
+	va_start(args, fmt);
+	if (str->str)
+		len = vsprintf(str->str + str->len, fmt, args);
+	else
+		len = vsnprintf(NULL, 0, fmt, args);
+	va_end(args);
+
+	str->len += len;
+
+	return NULL;
+}
+
+#define MIN_ALIGNMENT_SIZE  8	/* FIXME: X86_64 specific */
+#define ALIGN_SIZE(a)   ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
+
+#define EFI_DP_TYPE_MASK			0x7f
+#define EFI_DP_TYPE_UNPACKED			0x80
+
+#define END_DEVICE_PATH_TYPE			0x7f
+
+#define END_ENTIRE_DEVICE_PATH_SUBTYPE		0xff
+#define END_INSTANCE_DEVICE_PATH_SUBTYPE	0x01
+#define END_DEVICE_PATH_LENGTH			(sizeof(struct efi_device_path))
+
+#define DP_IS_END_TYPE(a)
+#define DP_IS_END_SUBTYPE(a)        ( ((a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE )
+
+#define device_path_type(a)           ( ((a)->type) & EFI_DP_TYPE_MASK )
+#define next_device_path_node(a)       ( (struct efi_device_path *) ( ((u8 *) (a)) + (a)->length))
+#define is_device_path_end_type(a)      ( device_path_type(a) == END_DEVICE_PATH_TYPE )
+#define is_device_path_end_sub_type(a)   ( (a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE )
+#define is_device_path_end(a)          ( is_device_path_end_type(a) && is_device_path_end_sub_type(a) )
+#define is_device_path_unpacked(a)     ( (a)->type & EFI_DP_TYPE_UNPACKED )
+
+#define set_device_path_end_node(a)  {                      \
+            (a)->type = END_DEVICE_PATH_TYPE;           \
+            (a)->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE;     \
+            (a)->length = sizeof(struct efi_device_path);   \
+            }
+
+/*
+ * Hardware Device Path (UEFI 2.4 specification, version 2.4 § 9.3.2.)
+ */
+
+#define HARDWARE_DEVICE_PATH            0x01
+
+#define HW_PCI_DP                       0x01
+struct pci_device_path {
+	struct efi_device_path header;
+	u8 Function;
+	u8 Device;
+};
+
+#define HW_PCCARD_DP                    0x02
+struct pccard_device_path {
+	struct efi_device_path header;
+	u8 function_number;
+};
+
+#define HW_MEMMAP_DP                    0x03
+struct memmap_device_path {
+	struct efi_device_path header;
+	u32 memory_type;
+	efi_physical_addr_t starting_address;
+	efi_physical_addr_t ending_address;
+};
+
+#define HW_VENDOR_DP                    0x04
+struct vendor_device_path {
+	struct efi_device_path header;
+	efi_guid_t Guid;
+};
+
+struct unknown_device_vendor_device_path {
+	struct vendor_device_path device_path;
+	u8 legacy_drive_letter;
+};
+
+#define HW_CONTROLLER_DP            0x05
+struct controller_device_path {
+	struct efi_device_path header;
+	u32 Controller;
+};
+
+/*
+ * ACPI Device Path (UEFI 2.4 specification, version 2.4 § 9.3.3 and 9.3.4.)
+ */
+#define ACPI_DEVICE_PATH                 0x02
+
+#define ACPI_DP                         0x01
+struct acpi_hid_device_path {
+	struct efi_device_path header;
+	u32 HID;
+	u32 UID;
+};
+
+#define EXPANDED_ACPI_DP		0x02
+struct expanded_acpi_hid_device_path {
+	struct efi_device_path header;
+	u32 HID;
+	u32 UID;
+	u32 CID;
+	u8 hid_str[1];
+};
+
+#define ACPI_ADR_DP 3
+struct acpi_adr_device_path {
+	struct efi_device_path header;
+	u32 ADR;
+};
+
+/*
+ * EISA ID Macro
+ * EISA ID Definition 32-bits
+ *  bits[15:0] - three character compressed ASCII EISA ID.
+ *  bits[31:16] - binary number
+ *   Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z'
+ */
+#define PNP_EISA_ID_CONST       0x41d0
+#define EISA_ID(_Name, _Num)    ((u32) ((_Name) | (_Num) << 16))
+#define EISA_PNP_ID(_PNPId)     (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
+
+#define PNP_EISA_ID_MASK        0xffff
+#define EISA_ID_TO_NUM(_Id)     ((_Id) >> 16)
+
+/*
+ * Messaging Device Path (UEFI 2.4 specification, version 2.4 § 9.3.5.)
+ */
+#define MESSAGING_DEVICE_PATH           0x03
+
+#define MSG_ATAPI_DP                    0x01
+struct atapi_device_path {
+	struct efi_device_path header;
+	u8 primary_secondary;
+	u8 slave_master;
+	u16 Lun;
+};
+
+#define MSG_SCSI_DP                     0x02
+struct scsi_device_path {
+	struct efi_device_path header;
+	u16 Pun;
+	u16 Lun;
+};
+
+#define MSG_FIBRECHANNEL_DP             0x03
+struct fibrechannel_device_path {
+	struct efi_device_path header;
+	u32 Reserved;
+	u64 WWN;
+	u64 Lun;
+};
+
+/**
+ * Fibre Channel Ex sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.6.
+ */
+#define MSG_FIBRECHANNELEX_DP 21
+struct fibrechannelex_device_path {
+	struct efi_device_path header;
+	u32 Reserved;
+	u8 WWN[8];		/* World Wide Name */
+	u8 Lun[8];		/* Logical unit, T-10 SCSI Architecture Model 4 specification */
+};
+
+#define MSG_1394_DP                     0x04
+struct f1394_device_path {
+	struct efi_device_path header;
+	u32 Reserved;
+	u64 Guid;
+};
+
+#define MSG_USB_DP                      0x05
+struct usb_device_path {
+	struct efi_device_path header;
+	u8 Port;
+	u8 Endpoint;
+};
+
+/**
+ * SATA Device Path sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.6.
+ */
+#define MSG_SATA_DP 18
+struct sata_device_path {
+	struct efi_device_path header;
+	u16 HBAPort_number;
+	u16 port_multiplier_port_number;
+	u16 Lun;		/* Logical Unit Number */
+};
+
+/**
+ * USB WWID Device Path sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.7.
+ */
+#define MSG_USB_WWID_DP 16
+struct usb_wwid_device_path {
+	struct efi_device_path header;
+	u16 interface_number;
+	u16 vendor_id;
+	u16 product_id;
+	s16 serial_number[1];	/* UTF-16 characters of the USB serial number */
+};
+
+/**
+ * Device Logical Unit sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.8.
+ */
+#define MSG_DEVICE_LOGICAL_UNIT_DP 17
+struct device_logical_unit_device_path {
+	struct efi_device_path header;
+	u8 Lun;			/* Logical Unit Number */
+};
+
+#define MSG_USB_CLASS_DP                0x0_f
+struct usb_class_device_path {
+	struct efi_device_path header;
+	u16 vendor_id;
+	u16 product_id;
+	u8 device_class;
+	u8 device_subclass;
+	u8 device_protocol;
+};
+
+#define MSG_I2_o_DP                      0x06
+struct i2_o_device_path {
+	struct efi_device_path header;
+	u32 Tid;
+};
+
+#define MSG_MAC_ADDR_DP                 0x0b
+struct mac_addr_device_path {
+	struct efi_device_path header;
+	efi_mac_address mac_address;
+	u8 if_type;
+};
+
+#define MSG_IPv4_DP                     0x0c
+struct ipv4_device_path {
+	struct efi_device_path header;
+	efi_ipv4_address local_ip_address;
+	efi_ipv4_address remote_ip_address;
+	u16 local_port;
+	u16 remote_port;
+	u16 Protocol;
+	bool static_ip_address;
+	/* new from UEFI version 2, code must check length field in header */
+	efi_ipv4_address gateway_ip_address;
+	efi_ipv4_address subnet_mask;
+};
+
+#define MSG_IPv6_DP                     0x0d
+struct ipv6_device_path {
+	struct efi_device_path header;
+	efi_ipv6_address local_ip_address;
+	efi_ipv6_address remote_ip_address;
+	u16 local_port;
+	u16 remote_port;
+	u16 Protocol;
+	bool IPAddress_origin;
+	/* new from UEFI version 2, code must check length field in header */
+	u8 prefix_length;
+	efi_ipv6_address gateway_ip_address;
+};
+
+/**
+ * Device Logical Unit sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.8.
+ */
+#define MSG_VLAN_DP 20
+struct vlan_device_path {
+	struct efi_device_path header;
+	u16 vlan_id;
+};
+
+#define MSG_INFINIBAND_DP               0x09
+struct infiniband_device_path {
+	struct efi_device_path header;
+	u32 resource_flags;
+	efi_guid_t port_gid;
+	u64 service_id;
+	u64 target_port_id;
+	u64 device_id;
+};
+
+#define MSG_UART_DP                     0x0e
+struct uart_device_path {
+	struct efi_device_path header;
+	u32 Reserved;
+	u64 baud_rate;
+	u8 data_bits;
+	u8 Parity;
+	u8 stop_bits;
+};
+
+#define MSG_VENDOR_DP                   0x0a
+/* Use VENDOR_DEVICE_PATH struct */
+
+#define DEVICE_PATH_MESSAGING_PC_ANSI \
+    { 0xe0c14753, 0xf9be, 0x11d2,  {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d}  }
+
+#define DEVICE_PATH_MESSAGING_VT_100 \
+    { 0xdfa66065, 0xb419, 0x11d3,  {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d}  }
+
+#define DEVICE_PATH_MESSAGING_VT_100_PLUS \
+    { 0x7baec70b , 0x57e0 , 0x4c76 , { 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 } }
+
+#define DEVICE_PATH_MESSAGING_VT_UTF8 \
+    { 0xad15a0d6 , 0x8bec , 0x4acf , { 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 } }
+
+#define EFI_PC_ANSI_GUID \
+    { 0xe0c14753 , 0xf9be , 0x11d2 , 0x9a , 0x0c , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d }
+
+#define EFI_VT_100_GUID \
+    { 0xdfa66065 , 0xb419 , 0x11d3 , 0x9a , 0x2d , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d }
+
+#define EFI_VT_100_PLUS_GUID \
+    { 0x7baec70b , 0x57e0 , 0x4c76 , 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 }
+
+#define EFI_VT_UTF8_GUID \
+    { 0xad15a0d6 , 0x8bec , 0x4acf , 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 }
+
+/*
+ * Media Device Path (UEFI 2.4 specification, version 2.4 § 9.3.6.)
+ */
+#define MEDIA_DEVICE_PATH               0x04
+
+#define MEDIA_HARDDRIVE_DP              0x01
+struct harddrive_device_path {
+	struct efi_device_path header;
+	u32 partition_number;
+	u64 partition_start;
+	u64 partition_size;
+	u8 signature[16];
+	u8 mbr_type;
+	u8 signature_type;
+};
+
+#define MBR_TYPE_PCAT                       0x01
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
+
+#define SIGNATURE_TYPE_MBR                  0x01
+#define SIGNATURE_TYPE_GUID                 0x02
+
+#define MEDIA_CDROM_DP                  0x02
+struct cdrom_device_path {
+	struct efi_device_path header;
+	u32 boot_entry;
+	u64 partition_start;
+	u64 partition_size;
+};
+
+#define MEDIA_VENDOR_DP                 0x03
+/* Use VENDOR_DEVICE_PATH struct */
+
+#define MEDIA_FILEPATH_DP               0x04
+struct filepath_device_path {
+	struct efi_device_path header;
+	s16 path_name[1];
+};
+
+#define SIZE_OF_FILEPATH_DEVICE_PATH offsetof(FILEPATH_DEVICE_PATH,path_name)
+
+#define MEDIA_PROTOCOL_DP               0x05
+struct media_protocol_device_path {
+	struct efi_device_path header;
+	efi_guid_t Protocol;
+};
+
+/**
+ * PIWG Firmware File sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.6.6.
+ */
+#define MEDIA_PIWG_FW_FILE_DP 6
+struct media_fw_vol_filepath_device_path {
+	struct efi_device_path header;
+	efi_guid_t fv_file_name;
+};
+
+/**
+ * PIWG Firmware Volume Device Path sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.6.7.
+ */
+#define MEDIA_PIWG_FW_VOL_DP 7
+struct media_fw_vol_device_path {
+	struct efi_device_path header;
+	efi_guid_t fv_name;
+};
+
+/**
+ * Media relative offset range device path.
+ * UEFI 2.0 specification version 2.4 § 9.3.6.8.
+ */
+#define MEDIA_RELATIVE_OFFSET_RANGE_DP 8
+struct media_relative_offset_range_device_path {
+	struct efi_device_path header;
+	u32 Reserved;
+	u64 starting_offset;
+	u64 ending_offset;
+};
+
+/*
+ * BIOS Boot Specification Device Path (UEFI 2.4 specification, version 2.4 § 9.3.7.)
+ */
+#define BBS_DEVICE_PATH                 0x05
+
+#define BBS_BBS_DP                      0x01
+struct bbs_bbs_device_path {
+	struct efi_device_path header;
+	u16 device_type;
+	u16 status_flag;
+	s8 String[1];
+};
+
+/* device_type definitions - from BBS specification */
+#define BBS_TYPE_FLOPPY                 0x01
+#define BBS_TYPE_HARDDRIVE              0x02
+#define BBS_TYPE_CDROM                  0x03
+#define BBS_TYPE_PCMCIA                 0x04
+#define BBS_TYPE_USB                    0x05
+#define BBS_TYPE_EMBEDDED_NETWORK       0x06
+#define BBS_TYPE_DEV                    0x80
+#define BBS_TYPE_UNKNOWN                0x_fF
+
+struct efi_device_path end_device_path = {
+	.type = END_DEVICE_PATH_TYPE,
+	.sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE,
+	.length = END_DEVICE_PATH_LENGTH,
+};
+
+struct efi_device_path end_instance_device_path = {
+	.type = END_DEVICE_PATH_TYPE,
+	.sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE,
+	.length = END_DEVICE_PATH_LENGTH,
+};
+
+unsigned long
+device_path_size(struct efi_device_path *dev_path)
+{
+	struct efi_device_path *Start;
+
+	Start = dev_path;
+	while (!is_device_path_end(dev_path))
+		dev_path = next_device_path_node(dev_path);
+
+	return ((unsigned long) dev_path - (unsigned long) Start) +
+	    sizeof (struct efi_device_path);
+}
+
+struct efi_device_path *
+duplicate_device_path(struct efi_device_path *dev_path)
+{
+	struct efi_device_path *new_dev_path;
+	unsigned long Size;
+
+	Size = device_path_size(dev_path);
+
+	new_dev_path = malloc(Size);
+	if (new_dev_path)
+		memcpy(new_dev_path, dev_path, Size);
+
+	return new_dev_path;
+}
+
+struct efi_device_path *
+device_path_from_handle(efi_handle_t Handle)
+{
+	efi_status_t Status;
+	struct efi_device_path *device_path;
+
+	Status = BS->handle_protocol(Handle, &efi_device_path_protocol_guid,
+				(void *) &device_path);
+	if (EFI_ERROR(Status))
+		device_path = NULL;
+
+	return device_path;
+}
+
+struct efi_device_path *
+device_path_instance(struct efi_device_path **device_path, unsigned long *Size)
+{
+	struct efi_device_path *Start, *Next, *dev_path;
+	unsigned long Count;
+
+	dev_path = *device_path;
+	Start = dev_path;
+
+	if (!dev_path)
+		return NULL;
+
+	for (Count = 0;; Count++) {
+		Next = next_device_path_node(dev_path);
+
+		if (is_device_path_end_type(dev_path))
+			break;
+
+		dev_path = Next;
+	}
+
+	if (dev_path->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE)
+		Next = NULL;
+
+	*device_path = Next;
+
+	*Size = ((u8 *) dev_path) - ((u8 *) Start);
+
+	return Start;
+}
+
+unsigned long
+device_path_instance_count(struct efi_device_path *device_path)
+{
+	unsigned long Count, Size;
+
+	Count = 0;
+	while (device_path_instance(&device_path, &Size)) {
+		Count += 1;
+	}
+
+	return Count;
+}
+
+struct efi_device_path *
+append_device_path(struct efi_device_path *Src1, struct efi_device_path *Src2)
+/*
+ * Src1 may have multiple "instances" and each instance is appended
+ * Src2 is appended to each instance is Src1.  (E.g., it's possible
+ * to append a new instance to the complete device path by passing
+ * it in Src2)
+ */
+{
+	unsigned long src1_size, src1_inst, src2_size, Size;
+	struct efi_device_path *Dst, *Inst;
+	u8 *dst_pos;
+
+	if (!Src1)
+		return duplicate_device_path(Src2);
+
+	if (!Src2) {
+		return duplicate_device_path(Src1);
+	}
+
+	src1_size = device_path_size(Src1);
+	src1_inst = device_path_instance_count(Src1);
+	src2_size = device_path_size(Src2);
+	Size = src1_size * src1_inst + src2_size;
+
+	Dst = malloc(Size);
+	if (Dst) {
+		dst_pos = (u8 *) Dst;
+
+		/* Copy all device path instances */
+
+		while ((Inst = device_path_instance(&Src1, &Size))) {
+
+			memcpy(dst_pos, Inst, Size);
+			dst_pos += Size;
+
+			memcpy(dst_pos, Src2, src2_size);
+			dst_pos += src2_size;
+
+			memcpy(dst_pos, &end_instance_device_path,
+			       sizeof (struct efi_device_path));
+			dst_pos += sizeof (struct efi_device_path);
+		}
+
+		/* Change last end marker */
+		dst_pos -= sizeof (struct efi_device_path);
+		memcpy(dst_pos, &end_device_path,
+		       sizeof (struct efi_device_path));
+	}
+
+	return Dst;
+}
+
+struct efi_device_path *
+append_device_path_node(struct efi_device_path *Src1,
+			struct efi_device_path *Src2)
+/*
+ * Src1 may have multiple "instances" and each instance is appended
+ * Src2 is a signal device path node (without a terminator) that is
+ * appended to each instance is Src1.
+ */
+{
+	struct efi_device_path *Temp, *Eop;
+	unsigned long length;
+
+	/* Build a Src2 that has a terminator on it */
+
+	length = Src2->length;
+	Temp = malloc(length + sizeof (struct efi_device_path));
+	if (!Temp)
+		return NULL;
+
+	memcpy(Temp, Src2, length);
+	Eop = next_device_path_node(Temp);
+	set_device_path_end_node(Eop);
+
+	/* Append device paths */
+
+	Src1 = append_device_path(Src1, Temp);
+	free(Temp);
+	return Src1;
+}
+
+struct efi_device_path *
+unpack_device_path(struct efi_device_path *dev_path)
+{
+	struct efi_device_path *Src, *Dest, *new_path;
+	unsigned long Size;
+
+	/* Walk device path and round sizes to valid boundries */
+
+	Src = dev_path;
+	Size = 0;
+	for (;;) {
+		Size += Src->length;
+		Size += ALIGN_SIZE(Size);
+
+		if (is_device_path_end(Src)) {
+			break;
+		}
+
+		Src = next_device_path_node(Src);
+	}
+
+	new_path = xzalloc(Size);
+
+	Src = dev_path;
+	Dest = new_path;
+	for (;;) {
+		Size = Src->length;
+		memcpy(Dest, Src, Size);
+		Size += ALIGN_SIZE(Size);
+		Dest->length = Size;
+		Dest->type |= EFI_DP_TYPE_UNPACKED;
+		Dest =
+		    (struct efi_device_path *) (((u8 *) Dest) + Size);
+
+		if (is_device_path_end(Src))
+			break;
+
+		Src = next_device_path_node(Src);
+	}
+
+	return new_path;
+}
+
+struct efi_device_path *
+append_device_path_instance(struct efi_device_path *Src,
+			    struct efi_device_path *Instance)
+{
+	u8 *Ptr;
+	struct efi_device_path *dev_path;
+	unsigned long src_size;
+	unsigned long instance_size;
+
+	if (Src == NULL)
+		return duplicate_device_path(Instance);
+
+	src_size = device_path_size(Src);
+	instance_size = device_path_size(Instance);
+	Ptr = malloc(src_size + instance_size);
+	dev_path = (struct efi_device_path *) Ptr;
+
+	memcpy(Ptr, Src, src_size);
+
+	while (!is_device_path_end(dev_path))
+		dev_path = next_device_path_node(dev_path);
+
+	/*
+	 * Convert the End to an End Instance, since we are
+	 *  appending another instacne after this one its a good
+	 *  idea.
+	 */
+	dev_path->sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE;
+
+	dev_path = next_device_path_node(dev_path);
+	memcpy(dev_path, Instance, instance_size);
+
+	return (struct efi_device_path *) Ptr;
+}
+
+efi_status_t
+lib_device_path_to_interface(efi_guid_t * Protocol,
+			     struct efi_device_path *file_path,
+			     void **Interface)
+{
+	efi_status_t Status;
+	efi_handle_t Device;
+
+	Status = BS->locate_device_path(Protocol, &file_path, &Device);
+
+	if (!EFI_ERROR(Status)) {
+
+		/* If we didn't get a direct match return not found */
+		Status = EFI_NOT_FOUND;
+
+		if (is_device_path_end(file_path)) {
+
+			/* It was a direct match, lookup the protocol interface */
+
+			Status =
+			    BS->handle_protocol(Device, Protocol, Interface);
+		}
+	}
+
+	if (EFI_ERROR(Status))
+		*Interface = NULL;
+
+	return Status;
+}
+
+static void
+dev_path_pci(struct string *str, void *dev_path)
+{
+	struct pci_device_path *Pci;
+
+	Pci = dev_path;
+	cprintf(str, "Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
+}
+
+static void
+dev_path_pccard(struct string *str, void *dev_path)
+{
+	struct pccard_device_path *Pccard;
+
+	Pccard = dev_path;
+	cprintf(str, "Pccard(0x%x)", Pccard->function_number);
+}
+
+static void
+dev_path_mem_map(struct string *str, void *dev_path)
+{
+	struct memmap_device_path *mem_map;
+
+	mem_map = dev_path;
+	cprintf(str, "mem_map(%d,0x%llx,0x%llx)",
+		mem_map->memory_type,
+		mem_map->starting_address, mem_map->ending_address);
+}
+
+static void
+dev_path_controller(struct string *str, void *dev_path)
+{
+	struct controller_device_path *Controller;
+
+	Controller = dev_path;
+	cprintf(str, "Ctrl(%d)", Controller->Controller);
+}
+
+static void
+dev_path_vendor(struct string *str, void *dev_path)
+{
+	struct vendor_device_path *Vendor;
+	char *type;
+	struct unknown_device_vendor_device_path *unknown_dev_path;
+
+	Vendor = dev_path;
+	switch (device_path_type(&Vendor->header)) {
+	case HARDWARE_DEVICE_PATH:
+		type = "Hw";
+		break;
+	case MESSAGING_DEVICE_PATH:
+		type = "Msg";
+		break;
+	case MEDIA_DEVICE_PATH:
+		type = "Media";
+		break;
+	default:
+		type = "?";
+		break;
+	}
+
+	cprintf(str, "Ven%s(%pU", type, &Vendor->Guid);
+	if (efi_compare_guid(&Vendor->Guid, &efi_unknown_device_guid) == 0) {
+		/* GUID used by EFI to enumerate an EDD 1.1 device */
+		unknown_dev_path =
+		    (struct unknown_device_vendor_device_path *) Vendor;
+		cprintf(str, ":%02x)", unknown_dev_path->legacy_drive_letter);
+	} else {
+		cprintf(str, ")");
+	}
+}
+
+/*
+  type: 2 (ACPI Device Path) sub_type: 1 (ACPI Device Path)
+ */
+static void
+dev_path_acpi(struct string *str, void *dev_path)
+{
+	struct acpi_hid_device_path *Acpi;
+
+	Acpi = dev_path;
+	if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+		switch (EISA_ID_TO_NUM(Acpi->HID)) {
+		case 0x301:
+			cprintf(str, "Keyboard(%d)", Acpi->UID);
+			break;
+
+		case 0x401:
+			cprintf(str, "parallel_port(%d)", Acpi->UID);
+			break;
+		case 0x501:
+			cprintf(str, "Serial(%d)", Acpi->UID);
+			break;
+		case 0x604:
+			cprintf(str, "Floppy(%d)", Acpi->UID);
+			break;
+		case 0xa03:
+			cprintf(str, "pci_root(%d)", Acpi->UID);
+			break;
+		case 0xa08:
+			cprintf(str, "pcie_root(%d)", Acpi->UID);
+			break;
+		default:
+			cprintf(str, "Acpi(PNP%04x",
+				EISA_ID_TO_NUM(Acpi->HID));
+			if (Acpi->UID)
+				cprintf(str, ",%d", Acpi->UID);
+			cprintf(str, ")");
+			break;
+		}
+	} else {
+		cprintf(str, "Acpi(0x%X", Acpi->HID);
+		if (Acpi->UID)
+			cprintf(str, ",%d", Acpi->UID);
+		cprintf(str, ")");
+	}
+}
+
+static void
+dev_path_atapi(struct string *str, void *dev_path)
+{
+	struct atapi_device_path *Atapi;
+
+	Atapi = dev_path;
+	cprintf(str, "Ata(%s,%s)",
+		Atapi->primary_secondary ? "Secondary" : "Primary",
+		Atapi->slave_master ? "Slave" : "Master");
+}
+
+static void
+dev_path_scsi(struct string *str, void *dev_path)
+{
+	struct scsi_device_path *Scsi;
+
+	Scsi = dev_path;
+	cprintf(str, "Scsi(%d,%d)", Scsi->Pun, Scsi->Lun);
+}
+
+static void
+dev_path_fibre(struct string *str, void *dev_path)
+{
+	struct fibrechannel_device_path *Fibre;
+
+	Fibre = dev_path;
+	cprintf(str, "Fibre%s(0x%016llx,0x%016llx)",
+		device_path_type(&Fibre->header) ==
+		MSG_FIBRECHANNEL_DP ? "" : "Ex", Fibre->WWN, Fibre->Lun);
+}
+
+static void
+dev_path1394(struct string *str, void *dev_path)
+{
+	struct f1394_device_path *F1394;
+
+	F1394 = dev_path;
+	cprintf(str, "1394(%pU)", &F1394->Guid);
+}
+
+static void
+dev_path_usb(struct string *str, void *dev_path)
+{
+	struct usb_device_path *Usb;
+
+	Usb = dev_path;
+	cprintf(str, "Usb(0x%x,0x%x)", Usb->Port, Usb->Endpoint);
+}
+
+static void
+dev_path_i2_o(struct string *str, void *dev_path)
+{
+	struct i2_o_device_path *i2_o;
+
+	i2_o = dev_path;
+	cprintf(str, "i2_o(0x%X)", i2_o->Tid);
+}
+
+static void
+dev_path_mac_addr(struct string *str, void *dev_path)
+{
+	struct mac_addr_device_path *MAC;
+	unsigned long hw_address_size;
+	unsigned long Index;
+
+	MAC = dev_path;
+
+	/* hw_address_size = sizeof(EFI_MAC_ADDRESS); */
+	hw_address_size = MAC->header.length;
+	hw_address_size -= sizeof (MAC->header);
+	hw_address_size -= sizeof (MAC->if_type);
+	if (MAC->if_type == 0x01 || MAC->if_type == 0x00)
+		hw_address_size = 6;
+
+	cprintf(str, "Mac(");
+
+	for (Index = 0; Index < hw_address_size; Index++)
+		cprintf(str, "%02x", MAC->mac_address.Addr[Index]);
+
+	if (MAC->if_type != 0)
+		cprintf(str, ",%d", MAC->if_type);
+
+	cprintf(str, ")");
+}
+
+static void
+cat_print_iPv4(struct string *str, efi_ipv4_address * address)
+{
+	cprintf(str, "%d.%d.%d.%d", address->Addr[0], address->Addr[1],
+		address->Addr[2], address->Addr[3]);
+}
+
+static bool
+is_not_null_iPv4(efi_ipv4_address * address)
+{
+	u8 val;
+
+	val = address->Addr[0] | address->Addr[1];
+	val |= address->Addr[2] | address->Addr[3];
+
+	return val != 0;
+}
+
+static void
+cat_print_network_protocol(struct string *str, u16 Proto)
+{
+	if (Proto == 6)
+		cprintf(str, "TCP");
+	else if (Proto == 17)
+		cprintf(str, "UDP");
+	else
+		cprintf(str, "%d", Proto);
+}
+
+static void
+dev_path_iPv4(struct string *str, void *dev_path)
+{
+	struct ipv4_device_path *ip;
+	bool show;
+
+	ip = dev_path;
+	cprintf(str, "IPv4(");
+	cat_print_iPv4(str, &ip->remote_ip_address);
+	cprintf(str, ",");
+	cat_print_network_protocol(str, ip->Protocol);
+	cprintf(str, ",%s", ip->static_ip_address ? "Static" : "DHCP");
+	show = is_not_null_iPv4(&ip->local_ip_address);
+	if (!show
+	    && ip->header.length ==
+	    sizeof (struct ipv4_device_path)) {
+		/* only version 2 includes gateway and netmask */
+		show |= is_not_null_iPv4(&ip->gateway_ip_address);
+		show |= is_not_null_iPv4(&ip->subnet_mask);
+	}
+	if (show) {
+		cprintf(str, ",");
+		cat_print_iPv4(str, &ip->local_ip_address);
+		if (ip->header.length ==
+		    sizeof (struct ipv4_device_path)) {
+			/* only version 2 includes gateway and netmask */
+			show = is_not_null_iPv4(&ip->gateway_ip_address);
+			show |= is_not_null_iPv4(&ip->subnet_mask);
+			if (show) {
+				cprintf(str, ",");
+				cat_print_iPv4(str, &ip->gateway_ip_address);
+				if (is_not_null_iPv4(&ip->subnet_mask)) {
+					cprintf(str, ",");
+					cat_print_iPv4(str, &ip->subnet_mask);
+				}
+			}
+		}
+	}
+	cprintf(str, ")");
+}
+
+#define cat_print_iPv6_ADD( x , y ) ( ( (u16) ( x ) ) << 8 | ( y ) )
+static void
+cat_print_ipv6(struct string *str, efi_ipv6_address * address)
+{
+	cprintf(str, "%x:%x:%x:%x:%x:%x:%x:%x",
+		cat_print_iPv6_ADD(address->Addr[0], address->Addr[1]),
+		cat_print_iPv6_ADD(address->Addr[2], address->Addr[3]),
+		cat_print_iPv6_ADD(address->Addr[4], address->Addr[5]),
+		cat_print_iPv6_ADD(address->Addr[6], address->Addr[7]),
+		cat_print_iPv6_ADD(address->Addr[8], address->Addr[9]),
+		cat_print_iPv6_ADD(address->Addr[10], address->Addr[11]),
+		cat_print_iPv6_ADD(address->Addr[12], address->Addr[13]),
+		cat_print_iPv6_ADD(address->Addr[14], address->Addr[15]));
+}
+
+static void
+dev_path_iPv6(struct string *str, void *dev_path)
+{
+	struct ipv6_device_path *ip;
+
+	ip = dev_path;
+	cprintf(str, "IPv6(");
+	cat_print_ipv6(str, &ip->remote_ip_address);
+	cprintf(str, ",");
+	cat_print_network_protocol(str, ip->Protocol);
+	cprintf(str, ",%s,", ip->IPAddress_origin ?
+		(ip->IPAddress_origin == 1 ? "stateless_auto_configure" :
+		 "stateful_auto_configure") : "Static");
+	cat_print_ipv6(str, &ip->local_ip_address);
+	if (ip->header.length ==
+	    sizeof (struct ipv6_device_path)) {
+		cprintf(str, ",");
+		cat_print_ipv6(str, &ip->gateway_ip_address);
+		cprintf(str, ",");
+		cprintf(str, "%d", ip->prefix_length);
+	}
+	cprintf(str, ")");
+}
+
+static void
+dev_path_infini_band(struct string *str, void *dev_path)
+{
+	struct infiniband_device_path *infini_band;
+
+	infini_band = dev_path;
+	cprintf(str, "Infiniband(0x%x,%pU,0x%llx,0x%llx,0x%llx)",
+		infini_band->resource_flags, &infini_band->port_gid,
+		infini_band->service_id, infini_band->target_port_id,
+		infini_band->device_id);
+}
+
+static void
+dev_path_uart(struct string *str, void *dev_path)
+{
+	struct uart_device_path *Uart;
+	s8 Parity;
+
+	Uart = dev_path;
+	switch (Uart->Parity) {
+	case 0:
+		Parity = 'D';
+		break;
+	case 1:
+		Parity = 'N';
+		break;
+	case 2:
+		Parity = 'E';
+		break;
+	case 3:
+		Parity = 'O';
+		break;
+	case 4:
+		Parity = 'M';
+		break;
+	case 5:
+		Parity = 'S';
+		break;
+	default:
+		Parity = 'x';
+		break;
+	}
+
+	if (Uart->baud_rate == 0)
+		cprintf(str, "Uart(DEFAULT %c", Parity);
+	else
+		cprintf(str, "Uart(%lld %c", Uart->baud_rate, Parity);
+
+	if (Uart->data_bits == 0)
+		cprintf(str, "D");
+	else
+		cprintf(str, "%d", Uart->data_bits);
+
+	switch (Uart->stop_bits) {
+	case 0:
+		cprintf(str, "D)");
+		break;
+	case 1:
+		cprintf(str, "1)");
+		break;
+	case 2:
+		cprintf(str, "1.5)");
+		break;
+	case 3:
+		cprintf(str, "2)");
+		break;
+	default:
+		cprintf(str, "x)");
+		break;
+	}
+}
+
+static void
+dev_path_sata(struct string *str, void *dev_path)
+{
+	struct sata_device_path *sata;
+
+	sata = dev_path;
+	cprintf(str, "Sata(0x%x,0x%x,0x%x)", sata->HBAPort_number,
+		sata->port_multiplier_port_number, sata->Lun);
+}
+
+static void
+dev_path_hard_drive(struct string *str, void *dev_path)
+{
+	struct harddrive_device_path *hd;
+
+	hd = dev_path;
+	switch (hd->signature_type) {
+	case SIGNATURE_TYPE_MBR:
+		cprintf(str, "HD(Part%d,Sig%08x)",
+			hd->partition_number, *((u32 *) (&(hd->signature[0])))
+		    );
+		break;
+	case SIGNATURE_TYPE_GUID:
+		cprintf(str, "HD(Part%d,Sig%pU)",
+			hd->partition_number,
+			(efi_guid_t *) & (hd->signature[0])
+		    );
+		break;
+	default:
+		cprintf(str, "HD(Part%d,mbr_type=%02x,sig_type=%02x)",
+			hd->partition_number, hd->mbr_type, hd->signature_type);
+		break;
+	}
+}
+
+static void
+dev_path_cdrom(struct string *str, void *dev_path)
+{
+	struct cdrom_device_path *cd;
+
+	cd = dev_path;
+	cprintf(str, "CDROM(0x%x)", cd->boot_entry);
+}
+
+static void
+dev_path_file_path(struct string *str, void *dev_path)
+{
+	struct filepath_device_path *Fp;
+	char *dst;
+
+	Fp = dev_path;
+
+	dst = strdup_wchar_to_char(Fp->path_name);
+
+	cprintf(str, "%s", dst);
+
+	free(dst);
+}
+
+static void
+dev_path_media_protocol(struct string *str, void *dev_path)
+{
+	struct media_protocol_device_path *media_prot;
+
+	media_prot = dev_path;
+	cprintf(str, "%pU", &media_prot->Protocol);
+}
+
+static void
+dev_path_bss_bss(struct string *str, void *dev_path)
+{
+	struct bbs_bbs_device_path *Bss;
+	char *type;
+
+	Bss = dev_path;
+	switch (Bss->device_type) {
+	case BBS_TYPE_FLOPPY:
+		type = "Floppy";
+		break;
+	case BBS_TYPE_HARDDRIVE:
+		type = "Harddrive";
+		break;
+	case BBS_TYPE_CDROM:
+		type = "CDROM";
+		break;
+	case BBS_TYPE_PCMCIA:
+		type = "PCMCIA";
+		break;
+	case BBS_TYPE_USB:
+		type = "Usb";
+		break;
+	case BBS_TYPE_EMBEDDED_NETWORK:
+		type = "Net";
+		break;
+	default:
+		type = "?";
+		break;
+	}
+
+	cprintf(str, "Bss-%s(%s)", type, Bss->String);
+}
+
+static void
+dev_path_end_instance(struct string *str, void *dev_path)
+{
+	cprintf(str, ",");
+}
+
+/**
+ * Print unknown device node.
+ * UEFI 2.4 § 9.6.1.6 table 89.
+ */
+
+static void
+dev_path_node_unknown(struct string *str, void *dev_path)
+{
+	struct efi_device_path *Path;
+	u8 *value;
+	int length, index;
+	Path = dev_path;
+	value = dev_path;
+	value += 4;
+	switch (Path->type) {
+	case HARDWARE_DEVICE_PATH:{
+			/* Unknown Hardware Device Path */
+			cprintf(str, "hardware_path(%d", Path->sub_type);
+			break;
+		}
+	case ACPI_DEVICE_PATH:{/* Unknown ACPI Device Path */
+			cprintf(str, "acpi_path(%d", Path->sub_type);
+			break;
+		}
+	case MESSAGING_DEVICE_PATH:{
+			/* Unknown Messaging Device Path */
+			cprintf(str, "Msg(%d", Path->sub_type);
+			break;
+		}
+	case MEDIA_DEVICE_PATH:{
+			/* Unknown Media Device Path */
+			cprintf(str, "media_path(%d", Path->sub_type);
+			break;
+		}
+	case BBS_DEVICE_PATH:{	/* Unknown BIOS Boot Specification Device Path */
+			cprintf(str, "bbs_path(%d", Path->sub_type);
+			break;
+		}
+	default:{		/* Unknown Device Path */
+			cprintf(str, "Path(%d,%d", Path->type, Path->sub_type);
+			break;
+		}
+	}
+	length = Path->length;
+	for (index = 0; index < length; index++) {
+		if (index == 0)
+			cprintf(str, ",0x");
+		cprintf(str, "%02x", *value);
+		value++;
+	}
+	cprintf(str, ")");
+}
+
+/*
+ * Table to convert "type" and "sub_type" to a "convert to text" function/
+ * Entries hold "type" and "sub_type" for know values.
+ * Special "sub_type" 0 is used as default for known type with unknown subtype.
+ */
+struct {
+	u8 type;
+	u8 sub_type;
+	void (*Function) (struct string *, void *);
+} dev_path_table[] = {
+	{
+	HARDWARE_DEVICE_PATH, HW_PCI_DP, dev_path_pci}, {
+	HARDWARE_DEVICE_PATH, HW_PCCARD_DP, dev_path_pccard}, {
+	HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, dev_path_mem_map}, {
+	HARDWARE_DEVICE_PATH, HW_VENDOR_DP, dev_path_vendor}, {
+	HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, dev_path_controller}, {
+	ACPI_DEVICE_PATH, ACPI_DP, dev_path_acpi}, {
+	MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, dev_path_atapi}, {
+	MESSAGING_DEVICE_PATH, MSG_SCSI_DP, dev_path_scsi}, {
+	MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, dev_path_fibre}, {
+	MESSAGING_DEVICE_PATH, MSG_1394_DP, dev_path1394}, {
+	MESSAGING_DEVICE_PATH, MSG_USB_DP, dev_path_usb}, {
+	MESSAGING_DEVICE_PATH, MSG_I2_o_DP, dev_path_i2_o}, {
+	MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, dev_path_mac_addr}, {
+	MESSAGING_DEVICE_PATH, MSG_IPv4_DP, dev_path_iPv4}, {
+	MESSAGING_DEVICE_PATH, MSG_IPv6_DP, dev_path_iPv6}, {
+	MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, dev_path_infini_band}, {
+	MESSAGING_DEVICE_PATH, MSG_UART_DP, dev_path_uart}, {
+	MESSAGING_DEVICE_PATH, MSG_SATA_DP, dev_path_sata}, {
+	MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, dev_path_vendor}, {
+	MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, dev_path_hard_drive}, {
+	MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, dev_path_cdrom}, {
+	MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, dev_path_vendor}, {
+	MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, dev_path_file_path}, {
+	MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, dev_path_media_protocol}, {
+	BBS_DEVICE_PATH, BBS_BBS_DP, dev_path_bss_bss}, {
+	END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE,
+		    dev_path_end_instance}, {
+	0, 0, NULL}
+};
+
+static int __device_path_to_str(struct string *str, struct efi_device_path *dev_path)
+{
+	struct efi_device_path *dev_path_node;
+	void (*dump_node) (struct string *, void *);
+	int i;
+
+	dev_path = unpack_device_path(dev_path);
+
+	dev_path_node = dev_path;
+	while (!is_device_path_end(dev_path_node)) {
+		dump_node = NULL;
+		for (i = 0; dev_path_table[i].Function; i += 1) {
+
+			if (device_path_type(dev_path_node) ==
+			    dev_path_table[i].type
+			    && dev_path_node->sub_type ==
+			    dev_path_table[i].sub_type) {
+				dump_node = dev_path_table[i].Function;
+				break;
+			}
+		}
+
+		if (!dump_node)
+			dump_node = dev_path_node_unknown;
+
+		if (str->len && dump_node != dev_path_end_instance)
+			cprintf(str, "/");
+
+		dump_node(str, dev_path_node);
+
+		dev_path_node = next_device_path_node(dev_path_node);
+	}
+
+	return 0;
+}
+
+char *device_path_to_str(struct efi_device_path *dev_path)
+{
+	struct string str = {};
+
+	__device_path_to_str(&str, dev_path);
+
+	str.str = malloc(str.len + 1);
+	if (!str.str)
+		return NULL;
+
+	str.len = 0;
+
+	__device_path_to_str(&str, dev_path);
+
+	return str.str;
+}
diff --git a/common/efi-guid.c b/common/efi-guid.c
new file mode 100644
index 0000000..5109b5d
--- /dev/null
+++ b/common/efi-guid.c
@@ -0,0 +1,11 @@
+#include <common.h>
+#include <efi.h>
+
+efi_guid_t efi_file_info_id = EFI_FILE_INFO_GUID;
+efi_guid_t efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_GUID;
+efi_guid_t efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+efi_guid_t efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+efi_guid_t efi_unknown_device_guid = EFI_UNKNOWN_DEVICE_GUID;
+efi_guid_t efi_null_guid = EFI_NULL_GUID;
+efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
+efi_guid_t efi_block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
diff --git a/common/memory.c b/common/memory.c
index 7dbd7f4..4a8fe28 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -58,7 +58,7 @@ void mem_malloc_init(void *start, void *end)
 #endif
 }
 
-#ifndef __SANDBOX__
+#if !defined __SANDBOX__ && !defined CONFIG_ARCH_EFI
 static int mem_malloc_resource(void)
 {
 	/*
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index ee1326e..dcb9541 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -232,7 +232,7 @@ static int is_gpt_valid(struct block_device *blk, u64 lba,
 static inline int
 is_pte_valid(const gpt_entry *pte, const u64 lastlba)
 {
-	if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
+	if ((!efi_guidcmp(pte->partition_type_guid, EFI_NULL_GUID)) ||
 	    le64_to_cpu(pte->starting_lba) > lastlba	 ||
 	    le64_to_cpu(pte->ending_lba)   > lastlba)
 		return 0;
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 45f77a7..2b28cf3 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -4,7 +4,7 @@ config OFTREE
 
 config OFTREE_MEM_GENERIC
 	depends on OFTREE
-	depends on PPC || ARM
+	depends on PPC || ARM || ARCH_EFI
 	def_bool y
 
 config DTC
diff --git a/include/efi.h b/include/efi.h
index 9911fa1..c624eb3 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -14,6 +14,9 @@
 #include <linux/string.h>
 #include <linux/types.h>
 
+#define EFIAPI __attribute__((ms_abi))
+struct efi_device_path;
+
 #define EFI_SUCCESS                             0
 #define EFI_LOAD_ERROR                  ( 1 | (1UL << (BITS_PER_LONG-1)))
 #define EFI_INVALID_PARAMETER           ( 2 | (1UL << (BITS_PER_LONG-1)))
@@ -52,13 +55,15 @@
 typedef unsigned long efi_status_t;
 typedef u8 efi_bool_t;
 typedef u16 efi_char16_t;		/* UNICODE character */
+typedef u64 efi_physical_addr_t;
+typedef void *efi_handle_t;
 
 
 typedef struct {
 	u8 b[16];
 } efi_guid_t;
 
-#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
+#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
 ((efi_guid_t) \
 {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
   (b) & 0xff, ((b) >> 8) & 0xff, \
@@ -109,22 +114,7 @@ typedef	struct {
 #define EFI_MEMORY_DESCRIPTOR_VERSION	1
 
 #define EFI_PAGE_SHIFT		12
-
-typedef struct {
-	u32 type;
-	u32 pad;
-	u64 phys_addr;
-	u64 virt_addr;
-	u64 num_pages;
-	u64 attribute;
-} efi_memory_desc_t;
-
-typedef struct {
-	efi_guid_t guid;
-	u32 headersize;
-	u32 flags;
-	u32 imagesize;
-} efi_capsule_header_t;
+#define EFI_PAGE_SIZE		(1UL << EFI_PAGE_SHIFT)
 
 /*
  * Allocation types for calls to boottime->allocate_pages.
@@ -163,6 +153,19 @@ typedef struct {
 	u8 sets_to_zero;
 } efi_time_cap_t;
 
+enum efi_locate_search_type {
+	all_handles,
+	by_register_notify,
+	by_protocol
+};
+
+struct efi_open_protocol_information_entry {
+	efi_handle_t agent_handle;
+	efi_handle_t controller_handle;
+	u32 attributes;
+	u32 open_count;
+};
+
 /*
  * EFI Boot Services table
  */
@@ -170,41 +173,69 @@ typedef struct {
 	efi_table_hdr_t hdr;
 	void *raise_tpl;
 	void *restore_tpl;
-	void *allocate_pages;
-	void *free_pages;
-	void *get_memory_map;
-	void *allocate_pool;
-	void *free_pool;
+	efi_status_t (EFIAPI *allocate_pages)(int, int, unsigned long,
+				       efi_physical_addr_t *);
+	efi_status_t (EFIAPI *free_pages)(efi_physical_addr_t, unsigned long);
+	efi_status_t (EFIAPI *get_memory_map)(unsigned long *, void *, unsigned long *,
+				       unsigned long *, u32 *);
+	efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **);
+	efi_status_t (EFIAPI *free_pool)(void *);
 	void *create_event;
 	void *set_timer;
-	void *wait_for_event;
+	efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events, void *event,
+			unsigned long *index);
 	void *signal_event;
 	void *close_event;
 	void *check_event;
 	void *install_protocol_interface;
 	void *reinstall_protocol_interface;
 	void *uninstall_protocol_interface;
-	void *handle_protocol;
+	efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, efi_guid_t *, void **);
 	void *__reserved;
 	void *register_protocol_notify;
-	void *locate_handle;
-	void *locate_device_path;
+	efi_status_t (EFIAPI *locate_handle) (enum efi_locate_search_type search_type,
+			efi_guid_t *protocol, void *search_key,
+			unsigned long *buffer_size, efi_handle_t *buffer);
+	efi_status_t (EFIAPI *locate_device_path)(efi_guid_t *protocol,
+			struct efi_device_path **device_path, efi_handle_t *device);
 	void *install_configuration_table;
-	void *load_image;
-	void *start_image;
-	void *exit;
+	efi_status_t (EFIAPI *load_image)(bool boot_policiy, efi_handle_t parent_image,
+			struct efi_device_path *file_path, void *source_buffer,
+			unsigned long source_size, efi_handle_t *image);
+	efi_status_t (EFIAPI *start_image)(efi_handle_t handle,
+			unsigned long *exitdata_size, s16 **exitdata);
+	efi_status_t(EFIAPI *exit)(efi_handle_t handle,  efi_status_t exit_status,
+			unsigned long exitdata_size, s16 *exitdata);
 	void *unload_image;
-	void *exit_boot_services;
+	efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
 	void *get_next_monotonic_count;
-	void *stall;
+	efi_status_t (EFIAPI *stall)(unsigned long usecs);
 	void *set_watchdog_timer;
-	void *connect_controller;
+	efi_status_t(EFIAPI *connect_controller)(efi_handle_t controller_handle,
+			efi_handle_t *driver_image_handle,
+			struct efi_device_path *remaining_device_path,
+			bool Recursive);
 	void *disconnect_controller;
-	void *open_protocol;
+#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL  0x00000001
+#define EFI_OPEN_PROTOCOL_GET_PROTOCOL        0x00000002
+#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL       0x00000004
+#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
+#define EFI_OPEN_PROTOCOL_BY_DRIVER           0x00000010
+#define EFI_OPEN_PROTOCOL_EXCLUSIVE           0x00000020
+	efi_status_t (EFIAPI *open_protocol)(efi_handle_t handle, efi_guid_t *protocol,
+			void ** interface, efi_handle_t agent_handle,
+			efi_handle_t controller_handle, u32 attributes);
 	void *close_protocol;
-	void *open_protocol_information;
-	void *protocols_per_handle;
-	void *locate_handle_buffer;
+	efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle, efi_guid_t *Protocol,
+			struct efi_open_protocol_information_entry **entry_buffer,
+			unsigned long *entry_count);
+	efi_status_t (EFIAPI *protocols_per_handle)(efi_handle_t handle,
+			efi_guid_t ***protocol_buffer,
+			unsigned long *protocols_buffer_count);
+	efi_status_t (EFIAPI *locate_handle_buffer) (
+			enum efi_locate_search_type search_type,
+			efi_guid_t *protocol, void *search_key,
+			unsigned long *no_handles, efi_handle_t **buffer);
 	void *locate_protocol;
 	void *install_multiple_protocol_interfaces;
 	void *uninstall_multiple_protocol_interfaces;
@@ -214,6 +245,8 @@ typedef struct {
 	void *create_event_ex;
 } efi_boot_services_t;
 
+extern efi_boot_services_t *BS;
+
 /*
  * Types and defines for EFI ResetSystem
  */
@@ -229,90 +262,63 @@ typedef struct {
 
 typedef struct {
 	efi_table_hdr_t hdr;
-	unsigned long get_time;
-	unsigned long set_time;
-	unsigned long get_wakeup_time;
-	unsigned long set_wakeup_time;
-	unsigned long set_virtual_address_map;
-	unsigned long convert_pointer;
-	unsigned long get_variable;
-	unsigned long get_next_variable;
-	unsigned long set_variable;
-	unsigned long get_next_high_mono_count;
-	unsigned long reset_system;
-	unsigned long update_capsule;
-	unsigned long query_capsule_caps;
-	unsigned long query_variable_info;
+	void *get_time;
+	void *set_time;
+	void *get_wakeup_time;
+	void *set_wakeup_time;
+	void *set_virtual_address_map;
+	void *convert_pointer;
+	efi_status_t (EFIAPI *get_variable)(s16 *variable_name, efi_guid_t *vendor,
+			u32 *Attributes, unsigned long *data_size, void *data);
+	efi_status_t (EFIAPI *get_next_variable)(unsigned long *variable_name_size,
+			s16 *variable_name, efi_guid_t *vendor);
+	void *set_variable;
+	void *get_next_high_mono_count;
+	void *reset_system;
+	void *update_capsule;
+	void *query_capsule_caps;
+	void *query_variable_info;
 } efi_runtime_services_t;
 
-typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
-typedef efi_status_t efi_set_time_t (efi_time_t *tm);
-typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
-					    efi_time_t *tm);
-typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
-typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
-					 unsigned long *data_size, void *data);
-typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
-					      efi_guid_t *vendor);
-typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor,
-					 u32 attr, unsigned long data_size,
-					 void *data);
-typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
-typedef void efi_reset_system_t (int reset_type, efi_status_t status,
-				 unsigned long data_size, efi_char16_t *data);
-typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
-						unsigned long descriptor_size,
-						u32 descriptor_version,
-						efi_memory_desc_t *virtual_map);
-typedef efi_status_t efi_query_variable_info_t(u32 attr,
-					       u64 *storage_space,
-					       u64 *remaining_space,
-					       u64 *max_variable_size);
-typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules,
-					  unsigned long count,
-					  unsigned long sg_list);
-typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
-					      unsigned long count,
-					      u64 *max_size,
-					      int *reset_type);
+extern efi_runtime_services_t *RT;
 
 /*
  *  EFI Configuration Table and GUID definitions
  */
-#define NULL_GUID \
+#define EFI_NULL_GUID \
     EFI_GUID(  0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
 
-#define MPS_TABLE_GUID    \
+#define EFI_MPS_TABLE_GUID    \
     EFI_GUID(  0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
-#define ACPI_TABLE_GUID    \
+#define EFI_ACPI_TABLE_GUID    \
     EFI_GUID(  0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
-#define ACPI_20_TABLE_GUID    \
+#define EFI_ACPI_20_TABLE_GUID    \
     EFI_GUID(  0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
 
-#define SMBIOS_TABLE_GUID    \
+#define EFI_SMBIOS_TABLE_GUID    \
     EFI_GUID(  0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
-#define SAL_SYSTEM_TABLE_GUID    \
+#define EFI_SAL_SYSTEM_TABLE_GUID    \
     EFI_GUID(  0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
-#define HCDP_TABLE_GUID	\
+#define EFI_HCDP_TABLE_GUID	\
     EFI_GUID(  0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
 
-#define UGA_IO_PROTOCOL_GUID \
+#define EFI_UGA_IO_PROTOCOL_GUID \
     EFI_GUID(  0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 )
 
 #define EFI_GLOBAL_VARIABLE_GUID \
     EFI_GUID(  0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c )
 
-#define UV_SYSTEM_TABLE_GUID \
+#define EFI_UV_SYSTEM_TABLE_GUID \
     EFI_GUID(  0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
 
-#define LINUX_EFI_CRASH_GUID \
+#define EFI_LINUX_EFI_CRASH_GUID \
     EFI_GUID(  0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
 
-#define LOADED_IMAGE_PROTOCOL_GUID \
+#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
     EFI_GUID(  0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 
 #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
@@ -324,26 +330,38 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
 #define EFI_PCI_IO_PROTOCOL_GUID \
     EFI_GUID(  0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a )
 
-#define EFI_FILE_INFO_ID \
+#define EFI_FILE_INFO_GUID \
     EFI_GUID(  0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 
-#define EFI_FILE_SYSTEM_GUID \
+#define EFI_SIMPLE_FILE_SYSTEM_GUID \
     EFI_GUID(  0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 
-typedef struct {
-	efi_guid_t guid;
-	u64 table;
-} efi_config_table_64_t;
+#define EFI_DEVICE_TREE_GUID \
+    EFI_GUID(  0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
 
-typedef struct {
-	efi_guid_t guid;
-	u32 table;
-} efi_config_table_32_t;
+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
+    EFI_GUID(  0x9576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 
-typedef struct {
-	efi_guid_t guid;
-	unsigned long table;
-} efi_config_table_t;
+#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \
+    EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D )
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+	EFI_GUID(0x0964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_UNKNOWN_DEVICE_GUID \
+	EFI_GUID(0xcf31fac5, 0xc24e, 0x11d2, 0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b)
+
+#define EFI_BLOCK_IO_PROTOCOL_GUID \
+	EFI_GUID(0x964e5b21, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+extern efi_guid_t efi_file_info_id;
+extern efi_guid_t efi_simple_file_system_protocol_guid;
+extern efi_guid_t efi_device_path_protocol_guid;
+extern efi_guid_t efi_loaded_image_protocol_guid;
+extern efi_guid_t efi_unknown_device_guid;
+extern efi_guid_t efi_null_guid;
+extern efi_guid_t efi_global_variable_guid;
+extern efi_guid_t efi_block_io_protocol_guid;
 
 #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
 
@@ -356,63 +374,20 @@ typedef struct {
 
 typedef struct {
 	efi_table_hdr_t hdr;
-	u64 fw_vendor;	/* physical addr of CHAR16 vendor string */
-	u32 fw_revision;
-	u32 __pad1;
-	u64 con_in_handle;
-	u64 con_in;
-	u64 con_out_handle;
-	u64 con_out;
-	u64 stderr_handle;
-	u64 _stderr;
-	u64 runtime;
-	u64 boottime;
-	u32 nr_tables;
-	u32 __pad2;
-	u64 tables;
-} efi_system_table_64_t;
-
-typedef struct {
-	efi_table_hdr_t hdr;
-	u32 fw_vendor;	/* physical addr of CHAR16 vendor string */
-	u32 fw_revision;
-	u32 con_in_handle;
-	u32 con_in;
-	u32 con_out_handle;
-	u32 con_out;
-	u32 stderr_handle;
-	u32 _stderr;
-	u32 runtime;
-	u32 boottime;
-	u32 nr_tables;
-	u32 tables;
-} efi_system_table_32_t;
-
-typedef struct {
-	efi_table_hdr_t hdr;
 	unsigned long fw_vendor;	/* physical addr of CHAR16 vendor string */
 	u32 fw_revision;
 	unsigned long con_in_handle;
-	unsigned long con_in;
+	struct efi_simple_input_interface *con_in;
 	unsigned long con_out_handle;
-	unsigned long con_out;
+	struct efi_simple_text_output_protocol *con_out;
 	unsigned long stderr_handle;
-	unsigned long _stderr;
+	unsigned long std_err;
 	efi_runtime_services_t *runtime;
 	efi_boot_services_t *boottime;
 	unsigned long nr_tables;
 	unsigned long tables;
 } efi_system_table_t;
 
-struct efi_memory_map {
-	void *phys_map;
-	void *map;
-	void *map_end;
-	int nr_map;
-	unsigned long desc_version;
-	unsigned long desc_size;
-};
-
 typedef struct {
 	u32 revision;
 	void *parent_handle;
@@ -429,85 +404,12 @@ typedef struct {
 	unsigned long unload;
 } efi_loaded_image_t;
 
-typedef struct {
-	u64 revision;
-	void *open_volume;
-} efi_file_io_interface_t;
-
-typedef struct {
-	u64 size;
-	u64 file_size;
-	u64 phys_size;
-	efi_time_t create_time;
-	efi_time_t last_access_time;
-	efi_time_t modification_time;
-	__aligned_u64 attribute;
-	efi_char16_t filename[1];
-} efi_file_info_t;
-
-typedef struct {
-	u64 revision;
-	void *open;
-	void *close;
-	void *delete;
-	void *read;
-	void *write;
-	void *get_position;
-	void *set_position;
-	void *get_info;
-	void *set_info;
-	void *flush;
-} efi_file_handle_t;
-
-#define EFI_FILE_MODE_READ	0x0000000000000001
-#define EFI_FILE_MODE_WRITE	0x0000000000000002
-#define EFI_FILE_MODE_CREATE	0x8000000000000000
-
-#define EFI_INVALID_TABLE_ADDR		(~0UL)
-
-/*
- * All runtime access to EFI goes through this structure:
- */
-extern struct efi {
-	efi_system_table_t *systab;	/* EFI system table */
-	unsigned int runtime_version;	/* Runtime services version */
-	unsigned long mps;		/* MPS table */
-	unsigned long acpi;		/* ACPI table  (IA64 ext 0.71) */
-	unsigned long acpi20;		/* ACPI table  (ACPI 2.0) */
-	unsigned long smbios;		/* SM BIOS table */
-	unsigned long sal_systab;	/* SAL system table */
-	unsigned long boot_info;	/* boot info table */
-	unsigned long hcdp;		/* HCDP table */
-	unsigned long uga;		/* UGA table */
-	unsigned long uv_systab;	/* UV system table */
-	efi_get_time_t *get_time;
-	efi_set_time_t *set_time;
-	efi_get_wakeup_time_t *get_wakeup_time;
-	efi_set_wakeup_time_t *set_wakeup_time;
-	efi_get_variable_t *get_variable;
-	efi_get_next_variable_t *get_next_variable;
-	efi_set_variable_t *set_variable;
-	efi_query_variable_info_t *query_variable_info;
-	efi_update_capsule_t *update_capsule;
-	efi_query_capsule_caps_t *query_capsule_caps;
-	efi_get_next_high_mono_count_t *get_next_high_mono_count;
-	efi_reset_system_t *reset_system;
-	efi_set_virtual_address_map_t *set_virtual_address_map;
-} efi;
-
 static inline int
 efi_guidcmp (efi_guid_t left, efi_guid_t right)
 {
 	return memcmp(&left, &right, sizeof (efi_guid_t));
 }
 
-static inline char *
-efi_guid_unparse(efi_guid_t *guid, char *out)
-{
-	sprintf(out, "%pUl", guid->b);
-        return out;
-}
-
 /*
  * Variable Attributes
  */
@@ -527,48 +429,80 @@ efi_guid_unparse(efi_guid_t *guid, char *out)
 				EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
 				EFI_VARIABLE_APPEND_WRITE)
 /*
- * The type of search to perform when calling boottime->locate_handle
+ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
+ * not including trailing NUL
  */
-#define EFI_LOCATE_ALL_HANDLES			0
-#define EFI_LOCATE_BY_REGISTER_NOTIFY		1
-#define EFI_LOCATE_BY_PROTOCOL			2
+#define EFI_VARIABLE_GUID_LEN 36
+
+struct efi_device_path {
+	u8 type;
+	u8 sub_type;
+	u16 length;
+} __attribute ((packed));
+
+struct simple_text_output_mode {
+	s32 max_mode;
+	s32 mode;
+	s32 attribute;
+	s32 cursor_column;
+	s32 cursor_row;
+	bool cursor_visible;
+};
 
-/*
- * EFI Device Path information
- */
-#define EFI_DEV_HW			0x01
-#define  EFI_DEV_PCI				 1
-#define  EFI_DEV_PCCARD				 2
-#define  EFI_DEV_MEM_MAPPED			 3
-#define  EFI_DEV_VENDOR				 4
-#define  EFI_DEV_CONTROLLER			 5
-#define EFI_DEV_ACPI			0x02
-#define   EFI_DEV_BASIC_ACPI			 1
-#define   EFI_DEV_EXPANDED_ACPI			 2
-#define EFI_DEV_MSG			0x03
-#define   EFI_DEV_MSG_ATAPI			 1
-#define   EFI_DEV_MSG_SCSI			 2
-#define   EFI_DEV_MSG_FC			 3
-#define   EFI_DEV_MSG_1394			 4
-#define   EFI_DEV_MSG_USB			 5
-#define   EFI_DEV_MSG_USB_CLASS			15
-#define   EFI_DEV_MSG_I20			 6
-#define   EFI_DEV_MSG_MAC			11
-#define   EFI_DEV_MSG_IPV4			12
-#define   EFI_DEV_MSG_IPV6			13
-#define   EFI_DEV_MSG_INFINIBAND		 9
-#define   EFI_DEV_MSG_UART			14
-#define   EFI_DEV_MSG_VENDOR			10
-#define EFI_DEV_MEDIA			0x04
-#define   EFI_DEV_MEDIA_HARD_DRIVE		 1
-#define   EFI_DEV_MEDIA_CDROM			 2
-#define   EFI_DEV_MEDIA_VENDOR			 3
-#define   EFI_DEV_MEDIA_FILE			 4
-#define   EFI_DEV_MEDIA_PROTOCOL		 5
-#define EFI_DEV_BIOS_BOOT		0x05
-#define EFI_DEV_END_PATH		0x7F
-#define EFI_DEV_END_PATH2		0xFF
-#define   EFI_DEV_END_INSTANCE			0x01
-#define   EFI_DEV_END_ENTIRE			0xFF
+struct efi_simple_text_output_protocol {
+	void *reset;
+	efi_status_t (EFIAPI *output_string)(void *, void *);
+	void *test_string;
+
+	efi_status_t(EFIAPI *query_mode)(struct efi_simple_text_output_protocol *this,
+			unsigned long mode_number, unsigned long *columns, unsigned long *rows);
+	efi_status_t(EFIAPI *set_mode)(struct efi_simple_text_output_protocol *this,
+			unsigned long mode_number);
+	efi_status_t(EFIAPI *set_attribute)(struct efi_simple_text_output_protocol *this,
+			unsigned long attribute);
+	efi_status_t(EFIAPI *clear_screen) (struct efi_simple_text_output_protocol *this);
+	efi_status_t(EFIAPI *set_cursor_position) (struct efi_simple_text_output_protocol *this,
+			unsigned long column, unsigned long row);
+	efi_status_t(EFIAPI *enable_cursor)(void *, bool enable);
+	struct simple_text_output_mode *mode;
+};
+
+struct efi_input_key {
+	u16 scan_code;
+	s16 unicode_char;
+};
+
+struct efi_simple_input_interface {
+	efi_status_t(EFIAPI *reset)(struct efi_simple_input_interface *this,
+			bool ExtendedVerification);
+	efi_status_t(EFIAPI *read_key_stroke)(struct efi_simple_input_interface *this,
+			struct efi_input_key *key);
+	void *wait_for_key;
+};
+
+typedef struct {
+	uint8_t Addr[32];
+} efi_mac_address;
+
+typedef struct {
+	uint8_t Addr[4];
+} efi_ipv4_address;
+
+typedef struct {
+	uint8_t Addr[16];
+} efi_ipv6_address;
+
+typedef union {
+	uint32_t Addr[4];
+	efi_ipv4_address v4;
+	efi_ipv6_address v6;
+} efi_ip_address;
+
+static inline int efi_compare_guid(efi_guid_t *a, efi_guid_t *b)
+{
+	return memcmp(a, b, sizeof(efi_guid_t));
+}
+
+char *device_path_to_str(struct efi_device_path *dev_path);
 
 #endif /* _LINUX_EFI_H */
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2014-07-08  8:50 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-08  8:49 Initial EFI Support Sascha Hauer
2014-07-08  8:49 ` [PATCH 01/21] Make IPaddr_t a 32bit type Sascha Hauer
2014-07-08  8:49 ` [PATCH 02/21] oftree command: Use size_t for size Sascha Hauer
2014-07-08  8:49 ` [PATCH 03/21] fat: Use correct format specifier Sascha Hauer
2014-07-08  8:50 ` [PATCH 04/21] readkey: keys are unsugned char Sascha Hauer
2014-07-08  8:50 ` [PATCH 05/21] of: platform: Use PRINTF_CONVERSION_RESOURCE for printing resources Sascha Hauer
2014-07-08  8:50 ` [PATCH 06/21] console: Add puts callback to console devices Sascha Hauer
2014-07-08  8:50 ` [PATCH 07/21] Add hex_byte_pack and hex_byte_pack_upper from kernel Sascha Hauer
2014-07-08  8:50 ` [PATCH 08/21] vsprintf: Support pU for printing UUIDs Sascha Hauer
2014-07-08  8:50 ` [PATCH 09/21] Add beginning wchar support Sascha Hauer
2014-07-11 12:35   ` Antony Pavlov
2014-07-14  6:05     ` Sascha Hauer
2014-07-08  8:50 ` [PATCH 10/21] block: Add flush callback Sascha Hauer
2014-07-08  8:50 ` [PATCH 11/21] Move efi.h to include/ Sascha Hauer
2014-07-08  8:50 ` [PATCH 12/21] filetype: Add DOS EXE file detection support Sascha Hauer
2014-07-08  8:50 ` [PATCH 13/21] efi: Add more error codes Sascha Hauer
2014-07-08  8:50 ` [PATCH 14/21] serial: ns16550: Add mmiobase to private data Sascha Hauer
2014-07-08  8:50 ` [PATCH 15/21] serial: ns16550: Add register read/write function pointers " Sascha Hauer
2014-07-08  8:50 ` [PATCH 16/21] Documentation: Add EFI documentation Sascha Hauer
2014-07-08  9:04   ` Jean-Christophe PLAGNIOL-VILLARD
2014-07-08  8:50 ` Sascha Hauer [this message]
2014-07-08  8:50 ` [PATCH 18/21] net: Add EFI Simple Network Protocol Driver Sascha Hauer
2014-07-08  8:50 ` [PATCH 19/21] serial: Add EFI stdio driver Sascha Hauer
2014-07-08  8:50 ` [PATCH 20/21] fs: implement EFI filesystem driver Sascha Hauer
2014-07-08  8:50 ` [PATCH 21/21] fs: implement EFI variable " Sascha Hauer
2014-07-08  8:53 ` Initial EFI Support Jean-Christophe PLAGNIOL-VILLARD
2014-07-08  8:59   ` Sascha Hauer
2014-07-08  9:52     ` Sascha Hauer
2014-07-08 10:04 ` Jean-Christophe PLAGNIOL-VILLARD
2014-07-08 16:38 ` [PATCH 1/2] EFI: enable printf UUID support Jean-Christophe PLAGNIOL-VILLARD
2014-07-08 16:38   ` [PATCH 2/2] EFI: introduce efi_strguid to convert GUID to human readable names Jean-Christophe PLAGNIOL-VILLARD
2014-07-11  7:23     ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1404809417-21477-18-git-send-email-s.hauer@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox