summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-08-07 06:14:56 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-08-07 06:14:56 +0200
commit8a11a59b379b641423a6ed655aae36ec00404403 (patch)
treea10f059d0bdcf9ba043cef744d605f9260991b18
parente3ff4dfa41b4e8afc26b69e5c3d8c127f0f37c39 (diff)
parent9183a8c683014f7f6dae004009556c9c0d4d2a15 (diff)
downloadbarebox-8a11a59b379b641423a6ed655aae36ec00404403.tar.gz
barebox-8a11a59b379b641423a6ed655aae36ec00404403.tar.xz
Merge branch 'for-next/efi'
Conflicts: .gitignore Makefile drivers/serial/Makefile
-rw-r--r--.gitignore1
-rw-r--r--Documentation/boards/efi.rst298
-rw-r--r--Documentation/glossary.rst3
-rw-r--r--Makefile2
-rw-r--r--arch/efi/Kconfig51
-rw-r--r--arch/efi/Makefile41
-rw-r--r--arch/efi/configs/efi_defconfig78
-rw-r--r--arch/efi/efi/Makefile2
-rw-r--r--arch/efi/efi/clocksource.c60
-rw-r--r--arch/efi/efi/efi-block-io.c174
-rw-r--r--arch/efi/efi/efi-device.c349
-rw-r--r--arch/efi/efi/efi-image.c105
-rw-r--r--arch/efi/efi/efi.c343
-rw-r--r--arch/efi/efi/env-efi/network/eth0-discover5
-rw-r--r--arch/efi/include/asm/barebox.h1
-rw-r--r--arch/efi/include/asm/bitops.h15
-rw-r--r--arch/efi/include/asm/byteorder.h8
-rw-r--r--arch/efi/include/asm/common.h4
-rw-r--r--arch/efi/include/asm/dma.h13
-rw-r--r--arch/efi/include/asm/elf.h60
-rw-r--r--arch/efi/include/asm/io.h55
-rw-r--r--arch/efi/include/asm/posix_types.h93
-rw-r--r--arch/efi/include/asm/sections.h1
-rw-r--r--arch/efi/include/asm/string.h1
-rw-r--r--arch/efi/include/asm/swab.h6
-rw-r--r--arch/efi/include/asm/types.h73
-rw-r--r--arch/efi/include/asm/unaligned.h19
-rw-r--r--arch/efi/include/mach/debug_ll.h20
-rw-r--r--arch/efi/include/mach/efi-device.h45
-rw-r--r--arch/efi/include/mach/efi.h24
-rw-r--r--arch/efi/lib/.gitignore2
-rw-r--r--arch/efi/lib/Makefile4
-rw-r--r--arch/efi/lib/crt0-efi-ia32.S76
-rw-r--r--arch/efi/lib/crt0-efi-x86_64.S75
-rw-r--r--arch/efi/lib/elf_ia32_efi.lds.S102
-rw-r--r--arch/efi/lib/elf_x86_64_efi.lds.S93
-rw-r--r--arch/efi/lib/reloc_ia32.c97
-rw-r--r--arch/efi/lib/reloc_x86_64.c96
-rw-r--r--commands/edit.c11
-rw-r--r--commands/oftree.c2
-rw-r--r--common/Kconfig8
-rw-r--r--common/Makefile4
-rw-r--r--common/block.c3
-rw-r--r--common/console.c29
-rw-r--r--common/efi-devicepath.c1370
-rw-r--r--common/efi-guid.c84
-rw-r--r--common/filetype.c4
-rw-r--r--common/memory.c2
-rw-r--r--common/partitions/efi.c2
-rw-r--r--common/partitions/efi.h2
-rw-r--r--drivers/net/Kconfig4
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/efi-snp.c296
-rw-r--r--drivers/of/Kconfig2
-rw-r--r--drivers/of/platform.c3
-rw-r--r--drivers/serial/Kconfig4
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/efi-stdio.c367
-rw-r--r--drivers/serial/serial_ns16550.c237
-rw-r--r--fs/Kconfig15
-rw-r--r--fs/Makefile2
-rw-r--r--fs/efi.c563
-rw-r--r--fs/efivarfs.c340
-rw-r--r--fs/fat/fat.c4
-rw-r--r--include/block.h1
-rw-r--r--include/console.h1
-rw-r--r--include/efi.h621
-rw-r--r--include/filetype.h1
-rw-r--r--include/linux/efi.h547
-rw-r--r--include/linux/kernel.h23
-rw-r--r--include/param.h2
-rw-r--r--include/wchar.h18
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile1
-rw-r--r--lib/misc.c3
-rw-r--r--lib/readkey.c2
-rw-r--r--lib/vsprintf.c62
-rw-r--r--lib/wchar.c80
78 files changed, 6543 insertions, 677 deletions
diff --git a/.gitignore b/.gitignore
index a74b6d5f4e..a62e08c730 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,7 @@ barebox.uimage
barebox.map
barebox.kwb
barebox.kwbuart
+barebox.efi
barebox.canon-a1100.bin
barebox-flash-image
System.map
diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst
new file mode 100644
index 0000000000..2147cb63db
--- /dev/null
+++ b/Documentation/boards/efi.rst
@@ -0,0 +1,298 @@
+barebox on (U)EFI
+=================
+
+barebox can be built as an EFI application for X86 PCs. This makes
+barebox a bootloader running on PC type hardware. In EFI jargon barebox
+would be a EFI shell. Due to the barebox :ref:`bootloader_spec` support
+it can act as a replacement for gummiboot.
+
+For accessing hardware the EFI drivers and abstractions are used. barebox
+has several drivers which merely map to the underlying EFI layers. A plain
+barebox binary provides access to the screen and keyboard. The EFI System
+partition (:term:`ESP`) is available under ``/boot``, additional partitions may
+be available as ``/efi*``. Networking may be available if the BIOS provides
+the necessary drivers, but most likely you'll have to download/compile
+network drivers yourself, see below.
+
+Depending on the ``CONFIG_64BIT`` option either a ia32 binary or a x86_64
+binary is built. Due to the lack of 32bit UEFI testing hardware only the
+x86_64 binary currently is tested.
+
+Building barebox for EFI
+------------------------
+
+Use the following to build barebox for EFI:
+
+.. code-block:: sh
+
+ export ARCH=efi
+ make efi_defconfig
+ make
+
+The resulting EFI image is ``barebox.efi`` (or the barebox-flash-image link).
+
+Running barebox on EFI systems
+------------------------------
+
+The simplest way to run barebox on a USB memory stick. (U)EFI only supports
+FAT filesystems, so make sure you either have a FAT16 or FAT32 filesystem on
+the memory stick. Put ``barebox.efi`` into the ``EFI/BOOT/`` directory and
+name it ``BOOTx64.EFI`` on 64bit architectures and ``BOOTIA32.EFI`` on 32bit
+architectures. Switching to USB boot in the BIOS should then be enough to
+start barebox via USB. Some BIOSes allow to specify a path to a binary to
+be executed, others have a "start UEFI shell" entry which executes
+EFI/Shellx64.efi on the :term:`ESP`. This can be a barebox binary aswell.
+
+Running EFI barebox on qemu
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+barebox can be started in qemu with OVMF http://www.linux-kvm.org/page/OVMF.
+
+OVMF is part of several distributions and can be installed with the package
+management system. qemu needs the OVMF.fd from the OVMF package file as
+argument to the -pflash option. As qemu needs write access to that file it's
+necessary to make a copy first.
+
+To start it create a USB memory stick like above and execute:
+
+.. code-block:: sh
+
+ qemu-system-x86_64 -pflash OVMF.fd -nographic /dev/sdx
+
+A plain VFAT image will work aswell, but in this case the UEFI BIOS won't
+recognize it as ESP and ``/boot`` won't be mounted.
+
+Loading EFI applications
+------------------------
+
+EFI supports loading applications aswell as drivers. barebox does not differentiate
+between both. Both types can be simply executed by typing the path on the command
+line. When an application/driver returns barebox iterates over the handle database
+and will initialize all new devices.
+
+Applications
+^^^^^^^^^^^^
+
+barebox itself and also the Linux Kernel are EFI applications. This means both
+can be directly executed. On other architectures when barebox is executed from
+another barebox it means the barebox binary will be replaced. EFI behaves
+differently, here different barebox instances will be nested, so exiting barebox
+means passing control to the calling instance. Note that currently the :ref:`command_reset`
+command will pass the control to the calling instance rather than resetting
+the CPU. This may change in the future.
+
+Although the Linux Kernel can be directly executed one should use the :ref:`command_bootm`
+command. Only the bootm command passes the Kernel commandline to the Kernel.
+
+Drivers
+^^^^^^^
+
+EFI is modular and drivers can be loaded during runtime. Many drivers are
+included in the BIOS already, but some have to be loaded during runtime,
+for example it's common that network drivers are not included in the BIOS.
+
+Drivers can be loaded under barebox simply by executing them:
+
+.. code-block:: sh
+
+ barebox:/ /boot/network-drivers/0001-SnpDxe.efi
+
+Should the drivers instanciate new devices these are automatically registered
+after the driver has been loaded.
+
+Simple Network Protocol (SNP)
+-----------------------------
+
+The Simple Network Protocol provides a raw packet interface to the EFI
+network drivers. Each device which supports SNP shows up as a regular
+network device under barebox. To use SNP the BIOS must have the SNP
+protocol and the network driver installed. For getting the SNP protocol
+follow the instruction in :ref:`efi_building_edk2`. Network drivers for
+the common Intel Network devices can be found here:
+
+https://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=19186
+
+Once instantiated the EFI drivers take some time to bring up the link, so
+it's best to only load the network drivers when needed. This can be
+archieved with the following script to put under ``/env/network/eth0-discover``:
+
+.. code-block:: sh
+
+ #!/bin/sh
+
+ for i in /boot/network-drivers/*; do
+ $i;
+ done
+
+This script will load the drivers in ``/boot/network-drivers/`` in alphabetical
+order.
+
+**NOTE** Loading the network drivers only works when loaded in the
+correct order. First the SNP driver must be loaded and then the network device
+driver. Otherwise the drivers will load without errors, but no devices will be
+instantiated. For making the order sure the driver names can be prepended with
+a number:
+
+.. code-block:: sh
+
+ /boot/network-drivers/0001-SnpDxe.efi
+ /boot/network-drivers/0002-E6208X3.EFI
+
+It is currently not known whether this is a limitation in EFI or a bug in
+barebox.
+
+EFI File IO Interface
+---------------------
+
+EFI itself has filesystem support. At least the :term:`ESP` will be mounted by the
+EFI core already. The :term:`ESP` is mounted to ``/boot`` under barebox, other devices
+are mounted to ``/efi<no>`` in no particular order.
+
+Block IO Protocol
+-----------------
+
+EFI provides access to block devices with the Block IO Protocol. This can
+be used to access raw block devices under barebox and also to access filesystems
+not supported by EFI. The block devices will show up as ``/dev/disk<diskno>.<partno>``
+under barebox and can be accessed like any other device:
+
+.. code-block:: sh
+
+ mount /dev/disk0.1 -text4 /mnt
+
+Care must be taken that a partition is only accessed either via the Block IO Protocol *or*
+the File IO Interface. Doing both at the same time will most likely result in data
+corruption on the partition
+
+EFI device pathes
+-----------------
+
+In EFI each device can be pointed to using a device path. Device pathes have multiple
+components. The toplevel component on X86 systems will be the PCI root complex, on
+other systems this can be the physical memory space. Each component will now descrive
+how to find the child component on the parent bus. Additional device path nodes can
+describe network addresses or filenames on partitions. Device pathes have a binary
+representation and a clearly defined string representation. These characteristics make
+device pathes suitable for describing boot entries. barebox could use device pathes
+to store the reference to kernels on boot media. Also device pathes could be used to
+pass a root filesystem to the Kernel.
+
+Currently device pathes are only integrated into barebox in a way that each EFI device
+has a device parameter ``devpath`` which contains its device path:
+
+.. code-block:: sh
+
+ barebox:/ echo ${handle-00000000d0012198.devpath}
+ pci_root(0)/Pci(0x1d,0x0)/Usb(0x1,0x0)/Usb(0x2,0x0)
+
+
+EFI variables
+-------------
+
+EFI has support for variables which are exported via the EFI Variable Services. EFI variables
+are identified by a 64bit GUID and a name. EFI variables can have arbitrary binary values, so
+they are not compatible with barebox shell variables which can only have printable content.
+Support for these variables is not yet complete in barebox. barebox contains the efivarfs which
+has the same format as the Linux Kernels efivarfs. It can be mounted with:
+
+.. code-block:: sh
+
+ mkdir efivarfs
+ mount -tefivarfs none /efivarfs
+
+In efivarfs each variable is represented by a file named <varname>-<guid>. Access to EFI variables
+is currently readonly. Since the variables have binary content using :ref:`command_md` is often
+more suitable than :ref:`command_cat`.
+
+EFI driver model and barebox
+----------------------------
+
+The EFI driver model is based around handles and protocols. A handle is an opaque
+cookie that represents a hardware device or a software object. Each handle can have
+multiple protocols attached to it. A protocol is a callable interface and is defined
+by a C struct containing function pointers. A protocol is identified by a 64bit GUID.
+Common examples for protocols are DEVICE_PATH, DEVICE_IO, BLOCK_IO, DISK_IO,
+FILE_SYSTEM, SIMPLE_INPUT or SIMPLE_TEXT_OUTPUT. Every handle that implements the
+DEVICE_PATH protocol is registered as device in barebox. The structure can be best
+seen in the ``devinfo`` output of such a device:
+
+.. code-block:: sh
+
+ barebox:/ devinfo handle-00000000cfaed198
+ Driver: efi-snp
+ Bus: efi
+ Protocols:
+ 0: a19832b9-ac25-11d3-9a2d-0090273fc14d
+ 1: 330d4706-f2a0-4e4f-a369-b66fa8d54385
+ 2: e5dd1403-d622-c24e-8488-c71b17f5e802
+ 3: 34d59603-1428-4429-a414-e6b3b5fd7dc1
+ 4: 0e1ad94a-dcf4-11db-9705-00e08161165f
+ 5: 1aced566-76ed-4218-bc81-767f1f977a89
+ 6: e3161450-ad0f-11d9-9669-0800200c9a66
+ 7: 09576e91-6d3f-11d2-8e39-00a0c969723b
+ 8: 51dd8b21-ad8d-48e9-bc3f-24f46722c748
+ Parameters:
+ devpath: pci_root(0)/Pci(0x1c,0x3)/Pci(0x0,0x0)/Mac(e03f4914f157)
+
+The protocols section in the output shows the different protocols this
+handle implements. One of this Protocols (here the first) is the Simple
+Network Protocol GUID:
+
+.. code-block:: c
+
+ #define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \
+ EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D )
+
+Matching between EFI devices and drivers is done based on the Protocol GUIDs, so
+whenever a driver GUID matches one of the GUIDs a device imeplements the drivers
+probe function is called.
+
+.. _efi_building_edk2:
+
+Building EDK2
+-------------
+
+Additional drivers may be needed from the EDK2 package. For example to
+use Networking in barebox not only the network device drivers are needed,
+but also the Simple Network Protocol driver, SnpDxe.efi. This is often
+not included in the BIOS, but can be compiled from the EDK2 package.
+
+Here is only a quick walkthrough for building edk2, there are more elaborated
+HOWTOs in the net, for example on http://tianocore.sourceforge.net/wiki/Using_EDK_II_with_Native_GCC.
+
+.. code-block:: sh
+
+ git clone git://github.com/tianocore/edk2.git
+ cd edk2
+ make -C BaseTools
+ . edksetup.sh
+
+At least the following lines in ``Conf/target.txt`` should be edited::
+
+ ACTIVE_PLATFORM = MdeModulePkg/MdeModulePkg.dsc
+ TARGET_ARCH = X64
+ TOOL_CHAIN_TAG = GCC48
+ MAX_CONCURRENT_THREAD_NUMBER = 4
+
+The actual build is started with invoking ``build``. After building
+``Build/MdeModule/DEBUG_GCC48/X64/SnpDxe.efi`` should exist.
+
+**NOTE** As of this writing (July 2014) the following patch was needed to
+compile EDK2.
+
+.. code-block:: diff
+
+ diff --git a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S
+ index 9783ec6..13fc06c 100644
+ --- a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S
+ +++ b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S
+ @@ -280,7 +280,7 @@ ExtraPushDone:
+
+ mov %ds, %rax
+ pushq %rax
+ - movw %es, %rax
+ + mov %es, %rax^M
+ pushq %rax
+ mov %fs, %rax
+ pushq %rax
+
diff --git a/Documentation/glossary.rst b/Documentation/glossary.rst
index 8bad7dc6e8..106dce98a9 100644
--- a/Documentation/glossary.rst
+++ b/Documentation/glossary.rst
@@ -16,3 +16,6 @@ Glossary
PBL
Pre BootLoader image
+
+ ESP
+ EFI System Partition
diff --git a/Makefile b/Makefile
index c60f83e765..4c40929343 100644
--- a/Makefile
+++ b/Makefile
@@ -994,7 +994,7 @@ CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \
scripts/bareboxenv-target barebox-flash-image \
barebox.srec barebox.s5p barebox.ubl barebox.zynq \
barebox.uimage barebox.spi barebox.kwb barebox.kwbuart \
- barebox.canon-a1100.bin
+ barebox.efi barebox.canon-a1100.bin
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS += include/config include2 usr/include
diff --git a/arch/efi/Kconfig b/arch/efi/Kconfig
new file mode 100644
index 0000000000..71ac1c74e8
--- /dev/null
+++ b/arch/efi/Kconfig
@@ -0,0 +1,51 @@
+config ARCH_EFI
+ bool
+ default y
+ select HAS_DEBUG_LL
+ select HAS_KALLSYMS
+ select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select EFI_GUID
+ select EFI_DEVICEPATH
+ select PRINTF_UUID
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x0
+
+menu "EFI specific settings"
+
+config 64BIT
+ def_bool y
+ help
+ Say yes to build a 64-bit binary - formerly known as x86_64
+ Say no to build a 32-bit binary - formerly known as i386.
+
+ 32-bit support currently does not compile and is not tested
+ due to the lack of hardware.
+
+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 0000000000..af280859f0
--- /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 0000000000..456f70d32b
--- /dev/null
+++ b/arch/efi/configs/efi_defconfig
@@ -0,0 +1,78 @@
+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_EFI_STDIO=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_EFI_SNP=y
+# CONFIG_SPI is not set
+CONFIG_DISK=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_FS_EFI=y
+CONFIG_FS_EFIVARFS=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 0000000000..a856e5907c
--- /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 0000000000..2f33b43cce
--- /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 0000000000..00115317fc
--- /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 0000000000..1c9553d906
--- /dev/null
+++ b/arch/efi/efi/efi-device.c
@@ -0,0 +1,349 @@
+/*
+ * 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: %s\n", i, &efidev->guids[i],
+ efi_guid_string(&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 0000000000..18757d2697
--- /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_exe,
+};
+
+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_exe,
+ .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 0000000000..ff97783b13
--- /dev/null
+++ b/arch/efi/efi/efi.c
@@ -0,0 +1,343 @@
+/*
+ * 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 <efi.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)
+{
+ barebox_set_model("barebox EFI payload");
+
+ 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)
+{
+ 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 0000000000..62c31a553c
--- /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 0000000000..2997587d82
--- /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 0000000000..94646d4d0d
--- /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 0000000000..37316f2371
--- /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 0000000000..b0e6b7fb18
--- /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 0000000000..459536779e
--- /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 0000000000..ddde035188
--- /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 0000000000..ac8a9c1b35
--- /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 0000000000..6985b8eb4a
--- /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 0000000000..2b8c516038
--- /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 0000000000..2997587d82
--- /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 0000000000..60a90120b6
--- /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 0000000000..3204448dce
--- /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 0000000000..d02da6e60d
--- /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 0000000000..0fb2cb8c2a
--- /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 0000000000..fe074a44bb
--- /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 0000000000..1e9782a136
--- /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 0000000000..847e317701
--- /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 0000000000..c8a97bae07
--- /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 0000000000..6f0f2e872e
--- /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 0000000000..aa03106e9c
--- /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 0000000000..a5f6287500
--- /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 0000000000..d48432d21b
--- /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 0000000000..46929631ec
--- /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 0000000000..1db72f5dbc
--- /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/commands/edit.c b/commands/edit.c
index 5a2da7d034..98af583574 100644
--- a/commands/edit.c
+++ b/commands/edit.c
@@ -379,7 +379,16 @@ static int do_edit(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
screenwidth = 80;
- screenheight = 25;
+
+ /*
+ * The EFI simple text output protocol wraps to the next line and scrolls
+ * down when we write to the right bottom screen position. Reduce the number
+ * of rows by one to work around this.
+ */
+ if (IS_ENABLED(CONFIG_ARCH_EFI))
+ screenheight = 24;
+ else
+ screenheight = 25;
/* check if we are called as "sedit" instead of "edit" */
if (*argv[0] == 's') {
diff --git a/commands/oftree.c b/commands/oftree.c
index 983a0a59ea..49976bc02a 100644
--- a/commands/oftree.c
+++ b/commands/oftree.c
@@ -42,7 +42,7 @@
static int do_oftree(int argc, char *argv[])
{
struct fdt_header *fdt = NULL;
- int size;
+ size_t size;
int opt;
int probe = 0;
char *load = NULL;
diff --git a/common/Kconfig b/common/Kconfig
index bba7f159c1..8b361260c0 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 204241c919..4220e15127 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/block.c b/common/block.c
index e522ee425a..0edc8619ef 100644
--- a/common/block.c
+++ b/common/block.c
@@ -55,6 +55,9 @@ static int writebuffer_flush(struct block_device *blk)
}
}
+ if (blk->ops->flush)
+ return blk->ops->flush(blk);
+
return 0;
}
diff --git a/common/console.c b/common/console.c
index f9823661f0..e5f4267cbd 100644
--- a/common/console.c
+++ b/common/console.c
@@ -162,6 +162,22 @@ static void console_set_stdoutpath(struct console_device *cdev)
free(str);
}
+static int __console_puts(struct console_device *cdev, const char *s)
+{
+ int n = 0;
+
+ while (*s) {
+ if (*s == '\n') {
+ cdev->putc(cdev, '\r');
+ n++;
+ }
+ cdev->putc(cdev, *s);
+ n++;
+ s++;
+ }
+ return n;
+}
+
int console_register(struct console_device *newcdev)
{
struct device_d *dev = &newcdev->class_dev;
@@ -188,6 +204,9 @@ int console_register(struct console_device *newcdev)
NULL, &newcdev->baudrate, "%u", newcdev);
}
+ if (newcdev->putc && !newcdev->puts)
+ newcdev->puts = __console_puts;
+
dev_add_param(dev, "active", console_std_set, NULL, 0);
if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_FIRST)) {
@@ -348,9 +367,19 @@ EXPORT_SYMBOL(console_putc);
int console_puts(unsigned int ch, const char *str)
{
+ struct console_device *cdev;
const char *s = str;
int n = 0;
+ if (initialized == CONSOLE_INIT_FULL) {
+ for_each_console(cdev) {
+ if (cdev->f_active & ch) {
+ n = cdev->puts(cdev, str);
+ }
+ }
+ return n;
+ }
+
while (*s) {
if (*s == '\n') {
console_putc(ch, '\r');
diff --git a/common/efi-devicepath.c b/common/efi-devicepath.c
new file mode 100644
index 0000000000..2b1d916768
--- /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 0000000000..f6b0404105
--- /dev/null
+++ b/common/efi-guid.c
@@ -0,0 +1,84 @@
+#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;
+
+#define EFI_GUID_STRING(guid, short, long) do { \
+ if (!efi_guidcmp(guid, *g)) \
+ return long; \
+ } while(0)
+
+const char *efi_guid_string(efi_guid_t *g)
+{
+ EFI_GUID_STRING(EFI_NULL_GUID, "NULL", "NULL GUID");
+ EFI_GUID_STRING(EFI_MPS_TABLE_GUID, "MPS Table", "MPS Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_ACPI_TABLE_GUID, "ACPI Table", "ACPI 1.0 Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_ACPI_20_TABLE_GUID, "ACPI 2.0 Table", "ACPI 2.0 Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_SMBIOS_TABLE_GUID, "SMBIOS Table", "SMBIOS Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_SAL_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_HCDP_TABLE_GUID, "HDCP Table", "HDCP Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol");
+ EFI_GUID_STRING(EFI_GLOBAL_VARIABLE_GUID, "Efi", "Efi Variable GUID");
+ EFI_GUID_STRING(EFI_UV_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_LINUX_EFI_CRASH_GUID, "Linux EFI Crash", "Linux EFI Crash GUID");
+ EFI_GUID_STRING(EFI_LOADED_IMAGE_PROTOCOL_GUID, "LoadedImage Protocol", "EFI 1.0 Loaded Image Protocol");
+ EFI_GUID_STRING(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, "EFI Graphics Output Protocol", "UEFI Graphics Output Protocol");
+ EFI_GUID_STRING(EFI_UGA_PROTOCOL_GUID, "UGA Draw Protocol", "EFI 1.1 UGA Draw Protocol");
+ EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol");
+ EFI_GUID_STRING(EFI_PCI_IO_PROTOCOL_GUID, "PCI IO Protocol", "EFI 1.1 PCI IO Protocol");
+ EFI_GUID_STRING(EFI_FILE_INFO_GUID, "File Info", "EFI File Infom");
+ EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_GUID, "Filesystem", "EFI 1.0 Simple FileSystem");
+ EFI_GUID_STRING(EFI_DEVICE_TREE_GUID, "Device Tree", "EFI Device Tree GUID");
+ EFI_GUID_STRING(EFI_DEVICE_PATH_PROTOCOL_GUID, "Device Path Protocol", "EFI 1.0 Device Path protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_NETWORK_PROTOCOL_GUID, "Simple Network Protocol", "EFI 1.0 Simple Network Protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "Filesystem Protocol", "EFI 1.0 Simple FileSystem Protocol");
+ EFI_GUID_STRING(EFI_UNKNOWN_DEVICE_GUID, "Efi Unknown Device", "Efi Unknown Device GUID");
+ EFI_GUID_STRING(EFI_BLOCK_IO_PROTOCOL_GUID, "BlockIo Protocol", "EFI 1.0 Block IO protocol");
+
+ EFI_GUID_STRING(EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID, "FirmwareVolume2Protocol", "Efi FirmwareVolume2Protocol");
+ EFI_GUID_STRING(EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID, "FirmwareVolumeBlock Protocol", "Firmware Volume Block protocol");
+ EFI_GUID_STRING(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID, "PciRootBridgeIo Protocol", "EFI 1.1 Pci Root Bridge IO Protocol");
+ EFI_GUID_STRING(EFI_ISA_ACPI_PROTOCOL_GUID, "ISA Acpi Protocol", "ISA Acpi Protocol");
+ EFI_GUID_STRING(EFI_ISA_IO_PROTOCOL_GUID, "ISA IO Protocol", "ISA IO Protocol");
+ EFI_GUID_STRING(EFI_STANDARD_ERROR_DEVICE_GUID, "Standard Error Device Guid", "EFI Standard Error Device Guid");
+ EFI_GUID_STRING(EFI_CONSOLE_OUT_DEVICE_GUID, "Console Out Device Guid", "EFI Console Out Device Guid");
+ EFI_GUID_STRING(EFI_CONSOLE_IN_DEVICE_GUID, "Console In Device Guid", "EFI Conosle In Device Guid");
+ EFI_GUID_STRING(EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID, "Simple Text Out Protocol", "EFI 1.0 Simple Text Out Protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, "Simple Text Input Ex Protocol", "UEFI 2.1 Simple Text Input Ex Protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID, "Simple Text In Protocol", "EFI 1.0 Simple Text In Protocol");
+ EFI_GUID_STRING(EFI_DISK_IO_PROTOCOL_GUID, "DiskIo Protocol", "EFI 1.0 Disk IO Protocol");
+ EFI_GUID_STRING(EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID, "IDE Controller Init Protocol", "Platform IDE Init Protocol");
+ EFI_GUID_STRING(EFI_DISK_INFO_PROTOCOL_GUID, "Disk Info Protocol", "Disk Info Protocol");
+ EFI_GUID_STRING(EFI_SERIAL_IO_PROTOCOL_GUID, "SerialIo Protocol", "EFI 1.0 Serial IO Protocol");
+ EFI_GUID_STRING(EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID, "Bus Specific Driver Override Protocol", "EFI 1.1 Bus Specific Driver Override Protocol");
+ EFI_GUID_STRING(EFI_LOAD_FILE2_PROTOCOL_GUID, "LoadFile2 Protocol", "EFI Load File 2 Protocol");
+ EFI_GUID_STRING(EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP4 Service Binding Protocol", "MTFTP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_DHCP4_PROTOCOL_GUID, "DHCP4 Protocol", "DHCP4 Protocol");
+ EFI_GUID_STRING(EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID, "UDP4 Service Binding Protocol", "UDP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID, "TCP4 Service Binding Protocol", "TCP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID, "IP4 Service Binding Protocol", "IP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_IP4_CONFIG_PROTOCOL_GUID, "Ip4Config Protocol", "Ip4Config Protocol");
+ EFI_GUID_STRING(EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID, "ARP Service Binding Protocol", "ARP Service Binding Protocol");
+ EFI_GUID_STRING(EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID, "Managed Network Service Binding Protocol", "Managed Network Service Binding Protocol");
+ EFI_GUID_STRING(EFI_VLAN_CONFIG_PROTOCOL_GUID, "VlanConfig Protocol", "VlanConfig Protocol");
+ EFI_GUID_STRING(EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID, "HII Config Access Protocol", "HII Config Access 2.1 protocol");
+ EFI_GUID_STRING(LOAD_FILE_PROTOCOL_GUID, "LoadFile Protocol", "EFI 1.0 Load File Protocol");
+ EFI_GUID_STRING(EFI_COMPONENT_NAME2_PROTOCOL_GUID, "Component Name2 Protocol", "UEFI 2.0 Component Name2 Protocol");
+ EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31, "Network Interface Identifier Protocol_31", "EFI1.1 Network Interface Identifier Protocol");
+ EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID, "Network Interface Identifier Protocol", "EFI Network Interface Identifier Protocol");
+
+ /* File */
+ EFI_GUID_STRING(EFI_IDEBUSDXE_INF_GUID, "IdeBusDxe.inf", "EFI IdeBusDxe.inf File GUID");
+ EFI_GUID_STRING(EFI_TERMINALDXE_INF_GUID, "TerminalDxe.inf", "EFI TerminalDxe.inf File GUID");
+ EFI_GUID_STRING(EFI_ISCSIDXE_INF_GUID, "IScsiDxe.inf", "EFI IScsiDxe.inf File GUID");
+ EFI_GUID_STRING(EFI_VLANCONFIGDXE_INF_GUID, "VlanConfigDxe.inf", "EFI VlanConfigDxe.inf File GUID");
+
+ return "unknown";
+}
diff --git a/common/filetype.c b/common/filetype.c
index 86e544ae58..c8f3582cd1 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -57,6 +57,7 @@ static const struct filetype_str filetype_str[] = {
[filetype_ch_image] = { "TI OMAP CH boot image", "ch-image" },
[filetype_ch_image_be] = {
"TI OMAP CH boot image (big endian)", "ch-image-be" },
+ [filetype_exe] = { "MS-DOS executable", "exe" },
};
const char *file_type_to_string(enum filetype f)
@@ -237,6 +238,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
if (bufsize < 64)
return filetype_unknown;
+ if (buf8[0] == 'M' && buf8[1] == 'Z')
+ return filetype_exe;
+
if (is_barebox_arm_head(_buf))
return filetype_arm_barebox;
if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01)
diff --git a/common/memory.c b/common/memory.c
index 7dbd7f4399..4a8fe283f2 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 ee1326e622..dcb95414f6 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/common/partitions/efi.h b/common/partitions/efi.h
index 703ecca2f2..a9b10c1266 100644
--- a/common/partitions/efi.h
+++ b/common/partitions/efi.h
@@ -21,7 +21,7 @@
#ifndef FS_PART_EFI_H_INCLUDED
#define FS_PART_EFI_H_INCLUDED
-#include <linux/efi.h>
+#include <efi.h>
#define MSDOS_MBR_SIGNATURE 0xaa55
#define EFI_PMBR_OSTYPE_EFI 0xEF
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f0c41b151..43409a8f8c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -170,6 +170,10 @@ config DRIVER_NET_TAP
bool "tap Ethernet driver"
depends on LINUX
+config DRIVER_NET_EFI_SNP
+ bool "EFI SNP ethernet driver"
+ depends on ARCH_EFI
+
config DRIVER_NET_TSE
depends on NIOS2
bool "Altera TSE ethernet driver"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 33bb5c8fa0..1b85778f9f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o
obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o
obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o
+obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o
diff --git a/drivers/net/efi-snp.c b/drivers/net/efi-snp.c
new file mode 100644
index 0000000000..5b96fbf462
--- /dev/null
+++ b/drivers/net/efi-snp.c
@@ -0,0 +1,296 @@
+/*
+ * efi-snp.c - Simple Network Protocol driver for EFI
+ *
+ * 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 <driver.h>
+#include <malloc.h>
+#include <net.h>
+#include <init.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+struct efi_network_statistics {
+ uint64_t RxTotalFrames;
+ uint64_t RxGoodFrames;
+ uint64_t RxUndersizeFrames;
+ uint64_t RxOversizeFrames;
+ uint64_t RxDroppedFrames;
+ uint64_t RxUnicastFrames;
+ uint64_t RxBroadcastFrames;
+ uint64_t RxMulticastFrames;
+ uint64_t RxCrcErrorFrames;
+ uint64_t RxTotalBytes;
+ uint64_t TxTotalFrames;
+ uint64_t TxGoodFrames;
+ uint64_t TxUndersizeFrames;
+ uint64_t TxOversizeFrames;
+ uint64_t TxDroppedFrames;
+ uint64_t TxUnicastFrames;
+ uint64_t TxBroadcastFrames;
+ uint64_t TxMulticastFrames;
+ uint64_t TxCrcErrorFrames;
+ uint64_t TxTotalBytes;
+ uint64_t Collisions;
+ uint64_t UnsupportedProtocol;
+};
+
+enum efi_simple_network_state {
+ EfiSimpleNetworkStopped,
+ EfiSimpleNetworkStarted,
+ EfiSimpleNetworkInitialized,
+ EfiSimpleNetworkMaxState
+};
+
+#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01
+#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02
+#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10
+
+#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01
+#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02
+#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04
+#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08
+
+#define MAX_MCAST_FILTER_CNT 16
+struct efi_simple_network_mode {
+ uint32_t State;
+ uint32_t HwAddressSize;
+ uint32_t MediaHeaderSize;
+ uint32_t MaxPacketSize;
+ uint32_t NvRamSize;
+ uint32_t NvRamAccessSize;
+ uint32_t ReceiveFilterMask;
+ uint32_t ReceiveFilterSetting;
+ uint32_t MaxMCastFilterCount;
+ uint32_t MCastFilterCount;
+ efi_mac_address MCastFilter[MAX_MCAST_FILTER_CNT];
+ efi_mac_address CurrentAddress;
+ efi_mac_address BroadcastAddress;
+ efi_mac_address PermanentAddress;
+ uint8_t IfType;
+ bool MacAddressChangeable;
+ bool MultipleTxSupported;
+ bool MediaPresentSupported;
+ bool MediaPresent;
+};
+
+#define EFI_SIMPLE_NETWORK_INTERFACE_REVISION 0x00010000
+
+struct efi_simple_network {
+ uint64_t Revision;
+ efi_status_t (EFIAPI *start) (struct efi_simple_network *This);
+ efi_status_t (EFIAPI *stop) (struct efi_simple_network *This);
+ efi_status_t (EFIAPI *initialize) (struct efi_simple_network *This,
+ unsigned long ExtraRxBufferSize, unsigned long ExtraTxBufferSize);
+ efi_status_t (EFIAPI *reset) (struct efi_simple_network *This, bool ExtendedVerification);
+ efi_status_t (EFIAPI *shutdown) (struct efi_simple_network *This);
+ efi_status_t (EFIAPI *receive_filters) (struct efi_simple_network *This,
+ uint32_t Enable, uint32_t Disable, bool ResetMCastFilter,
+ unsigned long MCastFilterCnt, efi_mac_address *MCastFilter);
+ efi_status_t (EFIAPI *station_address) (struct efi_simple_network *This,
+ bool Reset, efi_mac_address *New);
+ efi_status_t (EFIAPI *statistics) (struct efi_simple_network *This,
+ bool Reset, unsigned long *StatisticsSize,
+ struct efi_network_statistics *StatisticsTable);
+ efi_status_t (EFIAPI *mcast_ip_to_mac) (struct efi_simple_network *This,
+ bool IPv6, efi_ip_address *IP, efi_mac_address *MAC);
+ efi_status_t (EFIAPI *nvdata) (struct efi_simple_network *This,
+ bool ReadWrite, unsigned long Offset, unsigned long BufferSize,
+ void *Buffer);
+ efi_status_t (EFIAPI *get_status) (struct efi_simple_network *This,
+ uint32_t *InterruptStatus, void **TxBuf);
+ efi_status_t (EFIAPI *transmit) (struct efi_simple_network *This,
+ unsigned long HeaderSize, unsigned long BufferSize, void *Buffer,
+ efi_mac_address *SrcAddr, efi_mac_address *DestAddr,
+ uint16_t *Protocol);
+ efi_status_t (EFIAPI *receive) (struct efi_simple_network *This,
+ unsigned long *HeaderSize, unsigned long *BufferSize, void *Buffer,
+ efi_mac_address *SrcAddr, efi_mac_address *DestAddr, uint16_t *Protocol);
+ void *WaitForPacket;
+ struct efi_simple_network_mode *Mode;
+};
+
+struct efi_snp_priv {
+ struct device_d *dev;
+ struct eth_device edev;
+ struct efi_simple_network *snp;
+};
+
+static inline struct efi_snp_priv *to_priv(struct eth_device *edev)
+{
+ return container_of(edev, struct efi_snp_priv, edev);
+}
+
+static int efi_snp_eth_send(struct eth_device *edev, void *packet, int length)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+ efi_status_t efiret;
+ void *txbuf;
+ uint64_t start;
+
+ efiret = priv->snp->transmit(priv->snp, 0, length, packet, NULL, NULL, NULL);
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to send: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ start = get_time_ns();
+
+ while (!is_timeout(start, SECOND)) {
+ uint32_t irq;
+ priv->snp->get_status(priv->snp, &irq, &txbuf);
+ if (txbuf)
+ return 0;
+ }
+
+ dev_err(priv->dev, "tx time out\n");
+
+ return -ETIMEDOUT;
+}
+
+static int efi_snp_eth_rx(struct eth_device *edev)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+ long bufsize = PKTSIZE;
+ efi_status_t efiret;
+
+ efiret = priv->snp->receive(priv->snp, NULL, &bufsize, NetRxPackets[0], NULL, NULL, NULL);
+ if (efiret == EFI_NOT_READY)
+ return 0;
+
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to receive: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ net_receive(edev, NetRxPackets[0], bufsize);
+
+ return 0;
+}
+
+static int efi_snp_eth_open(struct eth_device *edev)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+ uint32_t mask;
+ efi_status_t efiret;
+
+ priv->snp->shutdown(priv->snp);
+ priv->snp->stop(priv->snp);
+ priv->snp->start(priv->snp);
+ efiret = priv->snp->initialize(priv->snp, 0, 0);
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "Initialize failed with: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ efiret = priv->snp->station_address(priv->snp, false,
+ (efi_mac_address *)priv->snp->Mode->PermanentAddress.Addr );
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to set MAC address: %s\n",
+ efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
+ efiret = priv->snp->receive_filters(priv->snp, mask, 0, 0, 0, 0);
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to set receive filters: %s\n",
+ efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ return 0;
+}
+
+static void efi_snp_eth_halt(struct eth_device *edev)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+
+ priv->snp->stop(priv->snp);
+}
+
+static int efi_snp_get_ethaddr(struct eth_device *edev, unsigned char *adr)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+
+ memcpy(adr, priv->snp->Mode->PermanentAddress.Addr, 6);
+
+ return 0;
+}
+
+static int efi_snp_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+{
+ return 0;
+}
+
+int efi_snp_probe(struct efi_device *efidev)
+{
+ struct eth_device *edev;
+ struct efi_snp_priv *priv;
+ int ret;
+
+ dev_dbg(&efidev->dev, "efi_snp_probe\n");
+
+ priv = xzalloc(sizeof(struct efi_snp_priv));
+ priv->snp = efidev->protocol;
+ priv->dev = &efidev->dev;
+
+ dev_dbg(&efidev->dev, "perm: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ priv->snp->Mode->PermanentAddress.Addr[0],
+ priv->snp->Mode->PermanentAddress.Addr[1],
+ priv->snp->Mode->PermanentAddress.Addr[2],
+ priv->snp->Mode->PermanentAddress.Addr[3],
+ priv->snp->Mode->PermanentAddress.Addr[4],
+ priv->snp->Mode->PermanentAddress.Addr[5]);
+ dev_dbg(&efidev->dev, "curr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ priv->snp->Mode->CurrentAddress.Addr[0],
+ priv->snp->Mode->CurrentAddress.Addr[1],
+ priv->snp->Mode->CurrentAddress.Addr[2],
+ priv->snp->Mode->CurrentAddress.Addr[3],
+ priv->snp->Mode->CurrentAddress.Addr[4],
+ priv->snp->Mode->CurrentAddress.Addr[5]);
+
+ edev = &priv->edev;
+ edev->priv = priv;
+ edev->parent = &efidev->dev;
+
+ edev->open = efi_snp_eth_open;
+ edev->send = efi_snp_eth_send;
+ edev->recv = efi_snp_eth_rx;
+ edev->halt = efi_snp_eth_halt;
+ edev->get_ethaddr = efi_snp_get_ethaddr;
+ edev->set_ethaddr = efi_snp_set_ethaddr;
+
+ ret = eth_register(edev);
+
+ return ret;
+}
+
+static struct efi_driver efi_snp_driver = {
+ .driver = {
+ .name = "efi-snp",
+ },
+ .probe = efi_snp_probe,
+ .guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
+};
+device_efi_driver(efi_snp_driver);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 45f77a759f..2b28cf3fb4 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/drivers/of/platform.c b/drivers/of/platform.c
index 72e75cc079..c417cfdcd9 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -183,7 +183,8 @@ static struct device_d *of_platform_device_create(struct device_node *np,
dev->num_resources = num_reg;
of_device_make_bus_id(dev);
- debug("%s: register device %s, io=0x%08x\n", __func__, dev_name(dev),
+ debug("%s: register device %s, io=" PRINTF_CONVERSION_RESOURCE "\n",
+ __func__, dev_name(dev),
(num_reg) ? dev->resource[0].start : (-1));
ret = platform_device_register(dev);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index aa8833126c..146bf1ec3c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -45,6 +45,10 @@ config DRIVER_SERIAL_LINUX_CONSOLE
default y
bool "linux console driver"
+config DRIVER_SERIAL_EFI_STDIO
+ depends on ARCH_EFI
+ bool "EFI stdio driver"
+
config DRIVER_SERIAL_MPC5XXX
depends on MPC5200
default y
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 2d0e98eed3..189e777777 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -18,4 +18,5 @@ obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o
obj-$(CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT) += serial_omap4_usbboot.o
obj-$(CONFIG_DRIVER_SERIAL_AUART) += serial_auart.o
obj-$(CONFIG_DRIVER_SERIAL_CADENCE) += serial_cadence.o
+obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO) += efi-stdio.o
obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o
diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c
new file mode 100644
index 0000000000..bf14c5e24a
--- /dev/null
+++ b/drivers/serial/efi-stdio.c
@@ -0,0 +1,367 @@
+/*
+ * efi_console.c - EFI console 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 WITHOUT ANY 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 <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <console.h>
+#include <xfuncs.h>
+#include <efi.h>
+#include <readkey.h>
+#include <linux/ctype.h>
+#include <mach/efi.h>
+
+#define EFI_SHIFT_STATE_VALID 0x80000000
+#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
+#define EFI_LEFT_CONTROL_PRESSED 0x00000008
+#define EFI_RIGHT_ALT_PRESSED 0x00000010
+#define EFI_LEFT_ALT_PRESSED 0x00000020
+
+#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)
+#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED)
+#define KEYPRESS(keys, scan, uni) ((((uint64_t)keys) << 32) | ((scan) << 16) | (uni))
+#define KEYCHAR(k) ((k) & 0xffff)
+#define CHAR_CTRL(c) ((c) - 'a' + 1)
+
+#define EFI_BLACK 0x00
+#define EFI_BLUE 0x01
+#define EFI_GREEN 0x02
+#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
+#define EFI_RED 0x04
+#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
+#define EFI_BROWN (EFI_GREEN | EFI_RED)
+#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
+#define EFI_BRIGHT 0x08
+#define EFI_DARKGRAY (EFI_BRIGHT)
+#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
+#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
+#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
+#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
+#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
+#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
+#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
+
+#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4))
+
+#define EFI_BACKGROUND_BLACK 0x00
+#define EFI_BACKGROUND_BLUE 0x10
+#define EFI_BACKGROUND_GREEN 0x20
+#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
+#define EFI_BACKGROUND_RED 0x40
+#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+
+struct efi_console_priv {
+ struct efi_simple_text_output_protocol *out;
+ struct efi_simple_input_interface *in;
+ struct console_device cdev;
+ int lastkey;
+ u16 efi_console_buffer[CONFIG_CBSIZE];
+
+ unsigned long columns, rows;
+
+ int current_color;
+ s16 *blank_line;
+};
+
+static inline struct efi_console_priv *to_efi(struct console_device *cdev)
+{
+ return container_of(cdev, struct efi_console_priv, cdev);
+}
+
+struct efi_ctrlkey {
+ u8 scan_code;
+ u8 bb_key;
+};
+
+static struct efi_ctrlkey ctrlkeys[] = {
+ { 0x01, BB_KEY_UP },
+ { 0x02, BB_KEY_DOWN },
+ { 0x03, BB_KEY_RIGHT },
+ { 0x04, BB_KEY_LEFT },
+ { 0x05, BB_KEY_HOME },
+ { 0x06, BB_KEY_END },
+ { 0x07, BB_KEY_INSERT },
+ { 0x08, BB_KEY_DEL },
+ { 0x09, BB_KEY_PAGEUP },
+ { 0x0a, BB_KEY_PAGEDOWN },
+};
+
+static int efi_read_key(struct efi_console_priv *priv, bool wait)
+{
+ unsigned long index;
+ efi_status_t efiret;
+ struct efi_input_key k;
+ int i;
+
+ /* wait until key is pressed */
+ if (wait)
+ BS->wait_for_event(1, priv->in->wait_for_key, &index);
+
+ efiret = priv->in->read_key_stroke(efi_sys_table->con_in, &k);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
+ for (i = 0; i < ARRAY_SIZE(ctrlkeys); i++) {
+ if (ctrlkeys[i].scan_code == k.scan_code)
+ return ctrlkeys[i].bb_key;
+
+ }
+
+ return k.unicode_char & 0xff;
+}
+
+static void efi_console_putc(struct console_device *cdev, 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);
+}
+
+static void clear_to_eol(struct efi_console_priv *priv)
+{
+ int pos = priv->out->mode->cursor_column;
+
+ priv->out->output_string(priv->out, priv->blank_line + pos);
+}
+
+static int efi_process_square_bracket(struct efi_console_priv *priv, const char *inp)
+{
+ int x, y;
+ char *endp;
+
+ inp++;
+
+ switch (*inp) {
+ case 'A':
+ /* Cursor up */
+ case 'B':
+ /* Cursor down */
+ case 'C':
+ /* Cursor right */
+ case 'D':
+ /* Cursor left */
+ case 'H':
+ /* home */
+ case 'F':
+ /* end */
+ return 3;
+ case 'K':
+ clear_to_eol(priv);
+ return 3;
+ }
+
+ if (*inp == '2' && *(inp + 1) == 'J') {
+ priv->out->clear_screen(priv->out);
+ return 4;
+ }
+
+ if (*inp == '0' && *(inp + 1) == 'm') {
+ priv->out->set_attribute(priv->out,
+ EFI_TEXT_ATTR(EFI_WHITE, EFI_BLACK));
+ return 4;
+ }
+
+ if (*inp == '7' && *(inp + 1) == 'm') {
+ priv->out->set_attribute(priv->out,
+ EFI_TEXT_ATTR(EFI_BLACK, priv->current_color));
+ return 4;
+ }
+
+ if (*inp == '1' &&
+ *(inp + 1) == ';' &&
+ *(inp + 2) == '3' &&
+ *(inp + 3) &&
+ *(inp + 4) == 'm') {
+ int color;
+ switch (*(inp + 3)) {
+ case '1': color = EFI_RED; break;
+ case '4': color = EFI_BLUE; break;
+ case '2': color = EFI_GREEN; break;
+ case '6': color = EFI_CYAN; break;
+ case '3': color = EFI_YELLOW; break;
+ case '5': color = EFI_MAGENTA; break;
+ case '7': color = EFI_WHITE; break;
+ default: color = EFI_WHITE; break;
+ }
+
+ priv->current_color = color;
+
+ priv->out->set_attribute(priv->out,
+ EFI_TEXT_ATTR(color, EFI_BLACK));
+ return 7;
+ }
+
+ y = simple_strtoul(inp, &endp, 10);
+ if (*endp == ';') {
+ x = simple_strtoul(endp + 1, &endp, 10);
+ if (*endp == 'H') {
+ priv->out->set_cursor_position(priv->out, x - 1, y - 1);
+ return endp - inp + 3;
+ }
+ }
+
+ return 8;
+}
+
+static int efi_process_key(struct efi_console_priv *priv, const char *inp)
+{
+ char c;
+
+ c = *inp;
+
+ if (c != 27)
+ return 0;
+
+ inp++;
+
+ if (*inp == '[')
+ return efi_process_square_bracket(priv, inp);
+
+ return 1;
+}
+
+static int efi_console_puts(struct console_device *cdev, const char *s)
+{
+ struct efi_console_priv *priv = to_efi(cdev);
+ int n = 0;
+
+ while (*s) {
+ if (*s == 27) {
+ priv->efi_console_buffer[n] = 0;
+ priv->out->output_string(priv->out,
+ priv->efi_console_buffer);
+ n = 0;
+ s += efi_process_key(priv, s);
+ continue;
+ }
+
+ if (*s == '\n')
+ priv->efi_console_buffer[n++] = '\r';
+ priv->efi_console_buffer[n] = *s;
+ s++;
+ n++;
+ }
+
+ priv->efi_console_buffer[n] = 0;
+
+ priv->out->output_string(priv->out, priv->efi_console_buffer);
+
+ return n;
+}
+
+static int efi_console_tstc(struct console_device *cdev)
+{
+ struct efi_console_priv *priv = to_efi(cdev);
+ int key;
+
+ if (priv->lastkey > 0)
+ return 1;
+
+ key = efi_read_key(priv, 0);
+ if (key < 0)
+ return 0;
+
+ priv->lastkey = key;
+
+ return 1;
+}
+
+static int efi_console_getc(struct console_device *cdev)
+{
+ struct efi_console_priv *priv = to_efi(cdev);
+ int key;
+
+ if (priv->lastkey > 0) {
+ key = priv->lastkey;
+ priv->lastkey = -1;
+ return key;
+ }
+
+ return efi_read_key(priv, 1);
+}
+
+static void efi_set_mode(struct efi_console_priv *priv)
+{
+#if 0
+ int i;
+ unsigned long rows, columns, best = 0, mode = 0;
+ efi_status_t efiret;
+
+ for (i = 0; i < priv->out->mode->max_mode; i++) {
+ priv->out->query_mode(priv->out, i, &columns, &rows);
+ printf("%d: %ld %ld\n", i, columns, rows);
+ if (rows * columns > best) {
+ best = rows * columns;
+ mode = i;
+ }
+ }
+
+ /*
+ * Setting the mode doesn't work as expected. set_mode succeeds, but
+ * the graphics resolution is not changed.
+ */
+ priv->out->set_mode(priv->out, mode);
+#endif
+ priv->out->query_mode(priv->out, priv->out->mode->mode, &priv->columns, &priv->rows);
+}
+
+static int efi_console_probe(struct device_d *dev)
+{
+ struct console_device *cdev;
+ struct efi_console_priv *priv;
+ int i;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->out = efi_sys_table->con_out;
+ priv->in = efi_sys_table->con_in;
+
+ priv->current_color = EFI_WHITE;
+
+ efi_set_mode(priv);
+
+ priv->out->enable_cursor(priv->out, 1);
+
+ priv->blank_line = xzalloc((priv->columns + 1) * sizeof(s16));
+ for (i = 0; i < priv->columns; i++)
+ priv->blank_line[i] = ' ';
+
+ cdev = &priv->cdev;
+ cdev->dev = dev;
+ cdev->tstc = efi_console_tstc;
+ cdev->getc = efi_console_getc;
+ cdev->putc = efi_console_putc;
+ cdev->puts = efi_console_puts;
+
+ priv->lastkey = -1;
+
+ return console_register(cdev);
+}
+
+static struct driver_d efi_console_driver = {
+ .name = "efi-stdio",
+ .probe = efi_console_probe,
+};
+console_platform_driver(efi_console_driver);
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 709f704cb4..09e6a6aba8 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -46,10 +46,17 @@
struct ns16550_priv {
struct console_device cdev;
struct NS16550_plat plat;
- int access_width;
- int mmio;
struct clk *clk;
uint32_t fcrval;
+ void __iomem *mmiobase;
+ unsigned iobase;
+ void (*write_reg)(struct ns16550_priv *, uint8_t val, unsigned offset);
+ uint8_t (*read_reg)(struct ns16550_priv *, unsigned offset);
+};
+
+struct ns16550_drvdata {
+ void (*init_port)(struct console_device *cdev);
+ const char *linux_console_name;
};
static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev)
@@ -57,93 +64,64 @@ static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev)
return container_of(cdev, struct ns16550_priv, cdev);
}
-struct ns16550_drvdata {
- void (*init_port)(struct console_device *cdev);
- const char *linux_console_name;
-};
+static uint8_t ns16550_read_reg_mmio_8(struct ns16550_priv *priv, unsigned offset)
+{
+ return readb(priv->mmiobase + offset);
+}
-/**
- * @brief read system i/o (byte)
- * @param[in] addr address to read
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline uint8_t ns16550_sys_readb(void __iomem *addr, int mmio)
+static void ns16550_write_reg_mmio_8(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
- if (mmio)
- return readb(addr);
- else
- return (uint8_t) inb((int) addr);
+ writeb(val, priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (word)
- * @param[in] addr address to read
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline uint16_t ns16550_sys_readw(void __iomem *addr, int mmio)
+static uint8_t ns16550_read_reg_mmio_16(struct ns16550_priv *priv, unsigned offset)
{
- if (mmio)
- return readw(addr);
- else
- return (uint16_t) inw((int) addr);
+ return readw(priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (dword)
- * @param[in] addr address to read
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline uint32_t ns16550_sys_readl(void __iomem *addr, int mmio)
+static void ns16550_write_reg_mmio_16(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
- if (mmio)
- return readl(addr);
- else
- return (uint32_t) inl((int) addr);
+ writew(val, priv->mmiobase + offset);
}
-/**
- * @brief write system i/o (byte)
- * @param[in] val data to write
- * @param[in] addr address to write to
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline void ns16550_sys_writeb(uint8_t val, void __iomem *addr,
- int mmio)
+static uint8_t ns16550_read_reg_mmio_32(struct ns16550_priv *priv, unsigned offset)
{
- if (mmio)
- writeb(val, addr);
- else
- outb(val, (int) addr);
+ return readl(priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (word)
- * @param[in] val data to write
- * @param[in] addr address to write to
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline void ns16550_sys_writew(uint16_t val, void __iomem *addr,
- int mmio)
+static void ns16550_write_reg_mmio_32(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
- if (mmio)
- writew(val, addr);
- else
- outw(val, (int) addr);
+ writel(val, priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (dword)
- * @param[in] val data to write
- * @param[in] addr address to write to
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr,
- int mmio)
+static uint8_t ns16550_read_reg_ioport_8(struct ns16550_priv *priv, unsigned offset)
{
- if (mmio)
- writel(val, addr);
- else
- outl(val, (int) addr);
+ return inb(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_8(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+ outb(val, priv->iobase + offset);
+}
+
+static uint8_t ns16550_read_reg_ioport_16(struct ns16550_priv *priv, unsigned offset)
+{
+ return inw(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_16(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+ outw(val, priv->iobase + offset);
+}
+
+static uint8_t ns16550_read_reg_ioport_32(struct ns16550_priv *priv, unsigned offset)
+{
+ return inl(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_32(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+ outl(val, priv->iobase + offset);
}
/**
@@ -157,21 +135,9 @@ static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr,
static uint32_t ns16550_read(struct console_device *cdev, uint32_t off)
{
struct ns16550_priv *priv = to_ns16550_priv(cdev);
- struct device_d *dev = cdev->dev;
struct NS16550_plat *plat = &priv->plat;
- int width = priv->access_width;
-
- off <<= plat->shift;
- switch (width) {
- case IORESOURCE_MEM_8BIT:
- return ns16550_sys_readb(dev->priv + off, priv->mmio);
- case IORESOURCE_MEM_16BIT:
- return ns16550_sys_readw(dev->priv + off, priv->mmio);
- case IORESOURCE_MEM_32BIT:
- return ns16550_sys_readl(dev->priv + off, priv->mmio);
- }
- return -1;
+ return priv->read_reg(priv, off << plat->shift);
}
/**
@@ -185,23 +151,9 @@ static void ns16550_write(struct console_device *cdev, uint32_t val,
uint32_t off)
{
struct ns16550_priv *priv = to_ns16550_priv(cdev);
- struct device_d *dev = cdev->dev;
struct NS16550_plat *plat = &priv->plat;
- int width = priv->access_width;
-
- off <<= plat->shift;
- switch (width) {
- case IORESOURCE_MEM_8BIT:
- ns16550_sys_writeb(val & 0xff, dev->priv + off, priv->mmio);
- break;
- case IORESOURCE_MEM_16BIT:
- ns16550_sys_writew(val & 0xffff, dev->priv + off, priv->mmio);
- break;
- case IORESOURCE_MEM_32BIT:
- ns16550_sys_writel(val, dev->priv + off, priv->mmio);
- break;
- }
+ priv->write_reg(priv, val, off << plat->shift);
}
/**
@@ -359,6 +311,70 @@ static __maybe_unused struct ns16550_drvdata jz_drvdata = {
.init_port = ns16550_jz_init_port,
};
+static int ns16550_init_iomem(struct device_d *dev, struct ns16550_priv *priv)
+{
+ struct resource *res;
+ int width;
+
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ priv->mmiobase = dev_request_mem_region(dev, 0);
+
+ width = res->flags & IORESOURCE_MEM_TYPE_MASK;
+ switch (width) {
+ case IORESOURCE_MEM_8BIT:
+ priv->read_reg = ns16550_read_reg_mmio_8;
+ priv->write_reg = ns16550_write_reg_mmio_8;
+ break;
+ case IORESOURCE_MEM_16BIT:
+ priv->read_reg = ns16550_read_reg_mmio_16;
+ priv->write_reg = ns16550_write_reg_mmio_16;
+ break;
+ case IORESOURCE_MEM_32BIT:
+ priv->read_reg = ns16550_read_reg_mmio_32;
+ priv->write_reg = ns16550_write_reg_mmio_32;
+ break;
+ }
+
+ return 0;
+}
+
+static int ns16550_init_ioport(struct device_d *dev, struct ns16550_priv *priv)
+{
+ struct resource *res;
+ int width;
+
+ res = dev_get_resource(dev, IORESOURCE_IO, 0);
+ if (!res)
+ return -ENODEV;
+
+ res = request_ioport_region(dev_name(dev), res->start, res->end);
+ if (!res)
+ return -ENODEV;
+
+ priv->iobase = res->start;
+
+ width = res->flags & IORESOURCE_MEM_TYPE_MASK;
+ switch (width) {
+ case IORESOURCE_MEM_8BIT:
+ priv->read_reg = ns16550_read_reg_ioport_8;
+ priv->write_reg = ns16550_write_reg_ioport_8;
+ break;
+ case IORESOURCE_MEM_16BIT:
+ priv->read_reg = ns16550_read_reg_ioport_16;
+ priv->write_reg = ns16550_write_reg_ioport_16;
+ break;
+ case IORESOURCE_MEM_32BIT:
+ priv->read_reg = ns16550_read_reg_ioport_32;
+ priv->write_reg = ns16550_write_reg_ioport_32;
+ break;
+ }
+
+ return 0;
+}
+
/**
* @brief Probe entry point -called on the first match for device
*
@@ -374,7 +390,6 @@ static int ns16550_probe(struct device_d *dev)
struct console_device *cdev;
struct NS16550_plat *plat = (struct NS16550_plat *)dev->platform_data;
struct ns16550_drvdata *devtype;
- struct resource *res;
int ret;
ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
@@ -383,20 +398,12 @@ static int ns16550_probe(struct device_d *dev)
priv = xzalloc(sizeof(*priv));
- res = dev_get_resource(dev, IORESOURCE_MEM, 0);
- priv->mmio = (res != NULL);
- if (res) {
- res = request_iomem_region(dev_name(dev), res->start, res->end);
- } else {
- res = dev_get_resource(dev, IORESOURCE_IO, 0);
- if (res)
- res = request_ioport_region(dev_name(dev), res->start,
- res->end);
- }
- if (!res)
- goto err;
- dev->priv = (void __force __iomem *) res->start;
+ ret = ns16550_init_iomem(dev, priv);
+ if (ret)
+ ret = ns16550_init_ioport(dev, priv);
+ if (ret)
+ return ret;
if (plat)
priv->plat = *plat;
@@ -424,8 +431,6 @@ static int ns16550_probe(struct device_d *dev)
goto err;
}
- priv->access_width = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
-
cdev = &priv->cdev;
cdev->dev = dev;
cdev->tstc = ns16550_tstc;
diff --git a/fs/Kconfig b/fs/Kconfig
index 3724b34f9a..64fc1176a6 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -41,6 +41,21 @@ config FS_NFS
bool
prompt "nfs support"
+config FS_EFI
+ depends on ARCH_EFI
+ bool
+ prompt "EFI filesystem support"
+ help
+ This filesystem driver provides access to the filesystems provided
+ by the EFI Firmware via the EFI Simple File System Protocol.
+
+config FS_EFIVARFS
+ depends on ARCH_EFI
+ bool
+ prompt "EFI variable filesystem support (efivarfs)"
+ help
+ This filesystem driver provides access to EFI variables.
+
source fs/fat/Kconfig
source fs/ubifs/Kconfig
diff --git a/fs/Makefile b/fs/Makefile
index d3465edfa5..f5aae91a60 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -11,3 +11,5 @@ obj-$(CONFIG_FS_OMAP4_USBBOOT) += omap4_usbbootfs.o
obj-$(CONFIG_FS_NFS) += nfs.o parseopt.o
obj-$(CONFIG_FS_BPKFS) += bpkfs.o
obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o
+obj-$(CONFIG_FS_EFI) += efi.o
+obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o
diff --git a/fs/efi.c b/fs/efi.c
new file mode 100644
index 0000000000..f096f91f58
--- /dev/null
+++ b/fs/efi.c
@@ -0,0 +1,563 @@
+/*
+ * efi.c - EFI filesystem mirror driver
+ *
+ * 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 WITHOUT ANY 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 <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 <wchar.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+/* Open modes */
+#define EFI_FILE_MODE_READ 0x0000000000000001
+#define EFI_FILE_MODE_WRITE 0x0000000000000002
+#define EFI_FILE_MODE_CREATE 0x8000000000000000
+
+/* File attributes */
+#define EFI_FILE_READ_ONLY 0x0000000000000001
+#define EFI_FILE_HIDDEN 0x0000000000000002
+#define EFI_FILE_SYSTEM 0x0000000000000004
+#define EFI_FILE_RESERVIED 0x0000000000000008
+#define EFI_FILE_DIRECTORY 0x0000000000000010
+#define EFI_FILE_ARCHIVE 0x0000000000000020
+#define EFI_FILE_VALID_ATTR 0x0000000000000037
+
+#define EFI_FILE_HANDLE_REVISION 0x00010000
+struct efi_file_handle {
+ uint64_t Revision;
+ efi_status_t(EFIAPI *open)(struct efi_file_handle *File,
+ struct efi_file_handle **NewHandle, s16 *FileName,
+ uint64_t OpenMode, uint64_t Attributes);
+ efi_status_t(EFIAPI *close)(struct efi_file_handle *File);
+ efi_status_t(EFIAPI *delete)(struct efi_file_handle *File);
+ efi_status_t(EFIAPI *read)(struct efi_file_handle *File, unsigned long *BufferSize,
+ void *Buffer);
+ efi_status_t(EFIAPI *write)(struct efi_file_handle *File,
+ unsigned long *BufferSize, void *Buffer);
+ efi_status_t(EFIAPI *get_position)(struct efi_file_handle *File,
+ uint64_t *Position);
+ efi_status_t(EFIAPI *set_position)(struct efi_file_handle *File,
+ uint64_t Position);
+ efi_status_t(EFIAPI *get_info)(struct efi_file_handle *File,
+ efi_guid_t *InformationType, unsigned long *BufferSize,
+ void *Buffer);
+ efi_status_t(EFIAPI *set_info)(struct efi_file_handle *File,
+ efi_guid_t *InformationType, unsigned long BufferSize,
+ void *Buffer);
+ efi_status_t(EFIAPI *flush)(struct efi_file_handle *File);
+};
+
+#define EFI_FILE_IO_INTERFACE_REVISION 0x00010000
+
+struct efi_file_io_interface {
+ uint64_t Revision;
+ efi_status_t(EFIAPI *open_volume)(
+ struct efi_file_io_interface *This,
+ struct efi_file_handle **Root);
+};
+
+struct efi_file_info {
+ uint64_t Size;
+ uint64_t FileSize;
+ uint64_t PhysicalSize;
+ efi_time_t CreateTime;
+ efi_time_t LastAccessTime;
+ efi_time_t ModificationTime;
+ uint64_t Attribute;
+ s16 FileName[1];
+};
+
+typedef unsigned short wchar_t;
+
+struct efifs_priv {
+ struct efi_file_handle *root_dir;
+ struct efi_file_io_interface *protocol;
+};
+
+struct efifs_file {
+ struct efi_file_handle *entry;
+};
+
+struct efifs_dir {
+ DIR dir;
+ struct efi_file_handle *entries;
+};
+
+static wchar_t *path_to_efi(const char *path)
+{
+ wchar_t *dst;
+ wchar_t *ret;
+
+ if (!*path)
+ return strdup_char_to_wchar("\\");
+
+ dst = strdup_char_to_wchar(path);
+ if (!dst)
+ return NULL;
+
+ ret = dst;
+
+ while (*dst) {
+ if (*dst == '/')
+ *dst = '\\';
+ dst++;
+ }
+
+ return ret;
+}
+
+static int efifs_create(struct device_d *dev, const char *pathname, mode_t mode)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path = path_to_efi(pathname);
+ struct efi_file_handle *entry;
+ efi_status_t efiret;
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ 0ULL);
+
+ free(efi_path);
+
+ if (EFI_ERROR(efiret)) {
+ printf("%s %s: %s\n", __func__, pathname, efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ entry->close(entry);
+
+ return 0;
+}
+
+static int efifs_unlink(struct device_d *dev, const char *pathname)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path = path_to_efi(pathname);
+ struct efi_file_handle *entry;
+ efi_status_t efiret;
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0ULL);
+
+ free(efi_path);
+
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ efiret = entry->delete(entry);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ return 0;
+}
+
+static int efifs_mkdir(struct device_d *dev, const char *pathname)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path = path_to_efi(pathname);
+ struct efi_file_handle *entry;
+ efi_status_t efiret;
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ EFI_FILE_DIRECTORY);
+
+ free(efi_path);
+
+ if (EFI_ERROR(efiret)) {
+ printf("%s %s: %s\n", __func__, pathname, efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ entry->close(entry);
+
+ return 0;
+}
+
+static int efifs_rmdir(struct device_d *dev, const char *pathname)
+{
+ return efifs_unlink(dev, pathname);
+}
+
+static int efifs_open(struct device_d *dev, FILE *f, const char *filename)
+{
+ struct efifs_priv *priv = dev->priv;
+ efi_status_t efiret;
+ struct efifs_file *ufile;
+ wchar_t *efi_path = path_to_efi(filename);
+ struct efi_file_info *info;
+ unsigned long bufsize = 1024;
+ uint64_t efimode = EFI_FILE_MODE_READ;
+ int ret;
+
+ ufile = xzalloc(sizeof(*ufile));
+
+ if (f->flags & O_ACCMODE)
+ efimode |= EFI_FILE_MODE_WRITE;
+
+ efiret = priv->root_dir->open(priv->root_dir, &ufile->entry, efi_path,
+ efimode, 0ULL);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to Open %s: %s\n", __func__,
+ filename, efi_strerror(efiret));
+ free(ufile);
+ return -efi_errno(efiret);
+ }
+
+ free(efi_path);
+
+ info = xzalloc(1024);
+ efiret = ufile->entry->get_info(ufile->entry, &efi_file_info_id, &bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to GetInfo %s: %s\n", __func__,
+ filename, efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ f->size = info->FileSize;
+
+ free(info);
+ f->inode = ufile;
+
+ return 0;
+out:
+ free(info);
+ free(ufile);
+ return ret;
+}
+
+static int efifs_close(struct device_d *dev, FILE *f)
+{
+ struct efifs_file *ufile = f->inode;
+
+ ufile->entry->close(ufile->entry);
+
+ free(ufile);
+
+ return 0;
+}
+
+static int efifs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+ unsigned long bufsize = insize;
+
+ efiret = ufile->entry->read(ufile->entry, &bufsize, buf);
+ if (EFI_ERROR(efiret)) {
+ return -efi_errno(efiret);
+ }
+
+ return bufsize;
+}
+
+static int efifs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+ unsigned long bufsize = insize;
+
+ efiret = ufile->entry->write(ufile->entry, &bufsize, (void *)buf);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to write: %s\n", __func__, efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ return bufsize;
+}
+
+static loff_t efifs_lseek(struct device_d *dev, FILE *f, loff_t pos)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+
+ f->pos = pos;
+
+ efiret = ufile->entry->set_position(ufile->entry, pos);
+ if (EFI_ERROR(efiret)) {
+ return -efi_errno(efiret);
+ }
+
+ return f->pos;
+}
+
+static int efifs_truncate(struct device_d *dev, FILE *f, unsigned long size)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+ struct efi_file_info *info;
+ unsigned long bufsize = 1024;
+ int ret;
+
+ info = xzalloc(1024);
+
+ efiret = ufile->entry->get_info(ufile->entry, &efi_file_info_id, &bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to GetInfo: %s\n", __func__, efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ if (size > info->FileSize)
+ return 0;
+
+ info->FileSize = size;
+
+ efiret = ufile->entry->set_info(ufile->entry, &efi_file_info_id, bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to SetInfo: %s\n", __func__, efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ return 0;
+out:
+ return ret;
+}
+
+static DIR *efifs_opendir(struct device_d *dev, const char *pathname)
+{
+ struct efifs_priv *priv = dev->priv;
+ efi_status_t efiret;
+ struct efifs_dir *udir;
+ wchar_t *efi_path = path_to_efi(pathname);
+
+ udir = xzalloc(sizeof(*udir));
+
+ efiret = priv->root_dir->open(priv->root_dir, &udir->entries, efi_path, EFI_FILE_MODE_READ, 0ULL);
+ if (EFI_ERROR(efiret)) {
+ free(udir);
+ return NULL;
+ }
+
+ free(efi_path);
+
+ return &udir->dir;
+}
+
+static struct dirent *efifs_readdir(struct device_d *dev, DIR *dir)
+{
+ struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir);
+ efi_status_t efiret;
+ unsigned long bufsize = 256;
+ s16 buf[256];
+ struct efi_file_info *f;
+
+ efiret = udir->entries->read(udir->entries, &bufsize, buf);
+ if (EFI_ERROR(efiret) || bufsize == 0)
+ return NULL;
+
+ f = (struct efi_file_info *)buf;
+
+ strcpy_wchar_to_char(dir->d.d_name, f->FileName);
+
+ return &dir->d;
+}
+
+static int efifs_closedir(struct device_d *dev, DIR *dir)
+{
+ struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir);
+
+ udir->entries->close(udir->entries);
+
+ free(dir);
+
+ return 0;
+}
+
+static int efifs_stat(struct device_d *dev, const char *filename, struct stat *s)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path;
+ efi_status_t efiret;
+ struct efi_file_handle *entry;
+ struct efi_file_info *info;
+ unsigned long bufsize = 1024;
+ int ret;
+
+ info = xzalloc(1024);
+
+ efi_path = path_to_efi(filename);
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path, EFI_FILE_MODE_READ, 0ULL);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to Open %s: %s\n", __func__, filename,
+ efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out_free;
+ }
+
+ efiret = entry->get_info(entry, &efi_file_info_id, &bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to GetInfo %s: %s\n", __func__, filename,
+ efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ s->st_size = info->FileSize;
+ s->st_mode = 00555;
+
+ if (!info->Attribute & EFI_FILE_READ_ONLY)
+ s->st_mode |= 00222;
+
+ if (info->Attribute & EFI_FILE_DIRECTORY)
+ s->st_mode |= S_IFDIR;
+ else
+ s->st_mode |= S_IFREG;
+
+ ret = 0;
+out:
+ entry->close(entry);
+out_free:
+ free(efi_path);
+ free(info);
+
+ return ret;
+}
+
+static int efifs_symlink(struct device_d *dev, const char *pathname,
+ const char *newpath)
+{
+ return -EROFS;
+}
+
+static int efifs_readlink(struct device_d *dev, const char *pathname,
+ char *buf, size_t bufsiz)
+{
+ return -ENOENT;
+}
+
+static int efifs_probe(struct device_d *dev)
+{
+ struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct efifs_priv *priv;
+ efi_status_t efiret;
+ struct efi_file_handle *file;
+ struct device_d *efi = get_device_by_name(fsdev->backingstore);
+ struct efi_device *udev = container_of(efi, struct efi_device, dev);
+
+ priv = xzalloc(sizeof(struct efifs_priv));
+ priv->protocol = udev->protocol;
+ dev->priv = priv;
+ dev->parent = &udev->dev;
+
+ efiret = priv->protocol->open_volume(priv->protocol, &file);
+ if (EFI_ERROR(efiret)) {
+ dev_err(dev, "failed to open volume: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ priv->root_dir = file;
+
+ return 0;
+}
+
+static void efifs_remove(struct device_d *dev)
+{
+ free(dev->priv);
+}
+
+static struct fs_driver_d efifs_driver = {
+ .create = efifs_create,
+ .unlink = efifs_unlink,
+ .open = efifs_open,
+ .close = efifs_close,
+ .truncate = efifs_truncate,
+ .read = efifs_read,
+ .write = efifs_write,
+ .lseek = efifs_lseek,
+ .mkdir = efifs_mkdir,
+ .rmdir = efifs_rmdir,
+ .opendir = efifs_opendir,
+ .readdir = efifs_readdir,
+ .closedir = efifs_closedir,
+ .stat = efifs_stat,
+ .symlink = efifs_symlink,
+ .readlink = efifs_readlink,
+ .drv = {
+ .probe = efifs_probe,
+ .remove = efifs_remove,
+ .name = "efifs",
+ }
+};
+
+static int efifs_init(void)
+{
+ return register_fs_driver(&efifs_driver);
+}
+
+coredevice_initcall(efifs_init);
+
+static int index;
+
+int efi_fs_probe(struct efi_device *efidev)
+{
+ char *path, *device;
+ int ret;
+ struct efi_file_io_interface *volume;
+
+ if (efi_loaded_image)
+ BS->handle_protocol(efi_loaded_image->device_handle,
+ &efi_simple_file_system_protocol_guid, (void*)&volume);
+
+ if (efidev->protocol == volume)
+ path = xstrdup("/boot");
+ else
+ path = asprintf("/efi%d", index);
+ device = asprintf("%s", dev_name(&efidev->dev));
+
+ ret = make_directory(path);
+ if (ret)
+ goto out;
+
+ ret = mount(device, "efifs", path, NULL);
+ if (ret)
+ goto out;
+
+ index++;
+
+ dev_info(&efidev->dev, "mounted on %s\n", path);
+
+ ret = 0;
+out:
+ free(path);
+ free(device);
+
+ return ret;
+}
+
+static struct efi_driver efi_fs_driver = {
+ .driver = {
+ .name = "efi-fs",
+ },
+ .probe = efi_fs_probe,
+ .guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
+};
+device_efi_driver(efi_fs_driver);
diff --git a/fs/efivarfs.c b/fs/efivarfs.c
new file mode 100644
index 0000000000..58c637ef19
--- /dev/null
+++ b/fs/efivarfs.c
@@ -0,0 +1,340 @@
+/*
+ * ramfs.c - a malloc based filesystem
+ *
+ * Copyright (c) 2007 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 WITHOUT ANY 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 <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <fs.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <xfuncs.h>
+#include <fcntl.h>
+#include <efi.h>
+#include <wchar.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+struct efivarfs_priv {
+ struct efi_file_handle *root_dir;
+ struct efi_file_io_interface *protocol;
+};
+
+static int char_to_nibble(char c)
+{
+ int ret = tolower(c);
+
+ return ret <= '9' ? ret - '0' : ret - 'a' + 10;
+}
+
+static int read_byte_str(const char *str, u8 *out)
+{
+ if (!isxdigit(*str) || !isxdigit(*(str + 1)))
+ return -EINVAL;
+
+ *out = (char_to_nibble(*str) << 4) | char_to_nibble(*(str + 1));
+
+ return 0;
+}
+
+int efi_guid_parse(const char *str, efi_guid_t *guid)
+{
+ int i, ret;
+ u8 idx[] = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ for (i = 0; i < 16; i++) {
+ ret = read_byte_str(str, &guid->b[idx[i]]);
+ if (ret)
+ return ret;
+ str += 2;
+
+ switch (i) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ if (*str != '-')
+ return -EINVAL;
+ str++;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, s16 **name)
+{
+ int len, ret;
+ const char *guidstr;
+ s16 *varname;
+ int i;
+
+ if (*filename == '/')
+ filename++;
+
+ len = strlen(filename);
+
+ if (len < sizeof("-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"))
+ return -EINVAL;
+
+ guidstr = filename + len - sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
+ if (*guidstr != '-')
+ return -EINVAL;
+
+ guidstr++;
+
+ ret = efi_guid_parse(guidstr, vendor);
+
+ varname = xzalloc((guidstr - filename) * sizeof(s16));
+
+ for (i = 0; i < guidstr - filename - 1; i++)
+ varname[i] = filename[i];
+
+ *name = varname;
+
+ return 0;
+}
+
+struct efivars_file {
+ void *buf;
+ unsigned long size;
+ efi_guid_t vendor;
+ s16 *name;
+};
+
+static int efivarfs_open(struct device_d *dev, FILE *f, const char *filename)
+{
+ struct efivars_file *efile;
+ efi_status_t efiret;
+ int ret;
+ uint32_t attributes;
+
+ efile = xzalloc(sizeof(*efile));
+
+ ret = efivarfs_parse_filename(filename, &efile->vendor, &efile->name);
+ if (ret)
+ return -ENOENT;
+
+ efiret = RT->get_variable(efile->name, &efile->vendor, &attributes, &efile->size, NULL);
+ if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) {
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ efile->buf = malloc(efile->size + sizeof(uint32_t));
+ if (!efile->buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ efiret = RT->get_variable(efile->name, &efile->vendor, NULL, &efile->size,
+ efile->buf + sizeof(uint32_t));
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ *(uint32_t *)efile->buf = attributes;
+
+ f->size = efile->size + sizeof(uint32_t);
+ f->inode = efile;
+
+ return 0;
+
+out:
+ free(efile->buf);
+ free(efile);
+
+ return ret;
+}
+
+static int efivarfs_close(struct device_d *dev, FILE *f)
+{
+ struct efivars_file *efile = f->inode;
+
+ free(efile->buf);
+ free(efile);
+
+ return 0;
+}
+
+static int efivarfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+{
+ struct efivars_file *efile = f->inode;
+
+ memcpy(buf, efile->buf + f->pos, insize);
+
+ return insize;
+}
+
+static loff_t efivarfs_lseek(struct device_d *dev, FILE *f, loff_t pos)
+{
+ f->pos = pos;
+
+ return f->pos;
+}
+
+struct efivarfs_dir_entry {
+ char *name;
+ struct efivarfs_dir_entry *next;
+};
+
+struct efivarfs_dir {
+ struct efivarfs_dir_entry *first;
+ struct efivarfs_dir_entry *current;
+ DIR dir;
+};
+
+static DIR *efivarfs_opendir(struct device_d *dev, const char *pathname)
+{
+ efi_status_t efiret;
+ efi_guid_t vendor;
+ s16 name[1024];
+ struct efivarfs_dir *edir;
+ unsigned long size;
+ unsigned char *name8;
+
+ name[0] = 0;
+
+ edir = xzalloc(sizeof(*edir));
+
+ while (1) {
+ struct efivarfs_dir_entry *entry;
+
+ size = sizeof(name);
+ efiret = RT->get_next_variable(&size, name, &vendor);
+ if (EFI_ERROR(efiret))
+ break;
+
+ entry = xzalloc(sizeof(*entry));
+ name8 = strdup_wchar_to_char(name);
+
+ entry->name = asprintf("%s-%pUl", name8, &vendor);
+
+ free(name8);
+
+ if (!edir->first)
+ edir->first = entry;
+
+ if (edir->current)
+ edir->current->next = entry;
+
+ edir->current = entry;
+ }
+
+ edir->current = edir->first;
+
+ return &edir->dir;
+}
+
+static struct dirent *efivarfs_readdir(struct device_d *dev, DIR *dir)
+{
+ struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir);
+
+ if (!edir->current)
+ return NULL;
+
+ strcpy(dir->d.d_name, edir->current->name);
+
+ edir->current = edir->current->next;
+
+ return &dir->d;
+}
+
+static int efivarfs_closedir(struct device_d *dev, DIR *dir)
+{
+ struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir);
+ struct efivarfs_dir_entry *entry;
+
+ entry = edir->first;
+
+ while (entry) {
+ struct efivarfs_dir_entry *tmp;
+ free(entry->name);
+ tmp = entry->next;
+ free(entry);
+ entry = tmp;
+ }
+
+ free(edir);
+
+ return 0;
+}
+
+static int efivarfs_stat(struct device_d *dev, const char *filename, struct stat *s)
+{
+ efi_guid_t vendor;
+ s16 *name;
+ efi_status_t efiret;
+ unsigned long size = 0;
+ int ret;
+
+ ret = efivarfs_parse_filename(filename, &vendor, &name);
+ if (ret)
+ return -ENOENT;
+
+ efiret = RT->get_variable(name, &vendor, NULL, &size, NULL);
+
+ free(name);
+
+ if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL)
+ return -efi_errno(efiret);
+
+ s->st_mode = 00666 | S_IFREG;
+ s->st_size = size;
+
+ return 0;
+}
+
+static int efivarfs_probe(struct device_d *dev)
+{
+ return 0;
+}
+
+static void efivarfs_remove(struct device_d *dev)
+{
+ free(dev->priv);
+}
+
+static struct fs_driver_d efivarfs_driver = {
+ .open = efivarfs_open,
+ .close = efivarfs_close,
+ .read = efivarfs_read,
+ .lseek = efivarfs_lseek,
+ .opendir = efivarfs_opendir,
+ .readdir = efivarfs_readdir,
+ .closedir = efivarfs_closedir,
+ .stat = efivarfs_stat,
+ .drv = {
+ .probe = efivarfs_probe,
+ .remove = efivarfs_remove,
+ .name = "efivarfs",
+ }
+};
+
+static int efivarfs_init(void)
+{
+ return register_fs_driver(&efivarfs_driver);
+}
+
+coredevice_initcall(efivarfs_init);
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index e65ef585a2..f8094d0608 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -167,7 +167,7 @@ static int fat_write(struct device_d *_dev, FILE *f, const void *buf, size_t ins
ret = f_write(f_file, buf, insize, &outsize);
- debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file);
+ debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file);
if (ret)
return ret;
@@ -260,7 +260,7 @@ static int fat_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
ret = f_read(f_file, buf, insize, &outsize);
- debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file);
+ debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file);
if (ret)
return ret;
diff --git a/include/block.h b/include/block.h
index 872a4c1bba..91377679b0 100644
--- a/include/block.h
+++ b/include/block.h
@@ -9,6 +9,7 @@ struct block_device;
struct block_device_ops {
int (*read)(struct block_device *, void *buf, int block, int num_blocks);
int (*write)(struct block_device *, const void *buf, int block, int num_blocks);
+ int (*flush)(struct block_device *);
};
struct chunk;
diff --git a/include/console.h b/include/console.h
index 7535a56121..97a406d9c9 100644
--- a/include/console.h
+++ b/include/console.h
@@ -39,6 +39,7 @@ struct console_device {
int (*tstc)(struct console_device *cdev);
void (*putc)(struct console_device *cdev, char c);
+ int (*puts)(struct console_device *cdev, const char *s);
int (*getc)(struct console_device *cdev);
int (*setbrg)(struct console_device *cdev, int baudrate);
void (*flush)(struct console_device *cdev);
diff --git a/include/efi.h b/include/efi.h
new file mode 100644
index 0000000000..4ad9f69237
--- /dev/null
+++ b/include/efi.h
@@ -0,0 +1,621 @@
+#ifndef _LINUX_EFI_H
+#define _LINUX_EFI_H
+
+/*
+ * Extensible Firmware Interface
+ * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co.
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
+ */
+#include <linux/string.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_ARCH_EFI
+#define EFIAPI __attribute__((ms_abi))
+#else
+#define EFIAPI
+#endif
+
+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)))
+#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_VOLUME_CORRUPTED ( 10 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_VOLUME_FULL ( 11 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NO_MEDIA ( 12 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_MEDIA_CHANGED ( 13 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_FOUND ( 14 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ACCESS_DENIED ( 15 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NO_RESPONSE ( 16 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NO_MAPPING ( 17 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_TIMEOUT ( 18 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_STARTED ( 19 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ALREADY_STARTED ( 20 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ABORTED ( 21 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ICMP_ERROR ( 22 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_TFTP_ERROR ( 23 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_PROTOCOL_ERROR ( 24 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_INCOMPATIBLE_VERSION ( 25 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_SECURITY_VIOLATION ( 26 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_CRC_ERROR ( 27 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_END_OF_MEDIA ( 28 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_END_OF_FILE ( 31 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_INVALID_LANGUAGE ( 32 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_COMPROMISED_DATA ( 33 | (1UL << (BITS_PER_LONG-1)))
+
+#define EFI_ERROR(a) (((signed long) a) < 0)
+
+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) \
+((efi_guid_t) \
+{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
+ (b) & 0xff, ((b) >> 8) & 0xff, \
+ (c) & 0xff, ((c) >> 8) & 0xff, \
+ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
+
+/*
+ * Generic EFI table header
+ */
+typedef struct {
+ u64 signature;
+ u32 revision;
+ u32 headersize;
+ u32 crc32;
+ u32 reserved;
+} efi_table_hdr_t;
+
+/*
+ * Memory map descriptor:
+ */
+
+/* Memory types: */
+#define EFI_RESERVED_TYPE 0
+#define EFI_LOADER_CODE 1
+#define EFI_LOADER_DATA 2
+#define EFI_BOOT_SERVICES_CODE 3
+#define EFI_BOOT_SERVICES_DATA 4
+#define EFI_RUNTIME_SERVICES_CODE 5
+#define EFI_RUNTIME_SERVICES_DATA 6
+#define EFI_CONVENTIONAL_MEMORY 7
+#define EFI_UNUSABLE_MEMORY 8
+#define EFI_ACPI_RECLAIM_MEMORY 9
+#define EFI_ACPI_MEMORY_NVS 10
+#define EFI_MEMORY_MAPPED_IO 11
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
+#define EFI_PAL_CODE 13
+#define EFI_MAX_MEMORY_TYPE 14
+
+/* Attribute values: */
+#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
+#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
+#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
+#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
+#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
+#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
+#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
+#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
+#define EFI_MEMORY_DESCRIPTOR_VERSION 1
+
+#define EFI_PAGE_SHIFT 12
+#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
+
+/*
+ * Allocation types for calls to boottime->allocate_pages.
+ */
+#define EFI_ALLOCATE_ANY_PAGES 0
+#define EFI_ALLOCATE_MAX_ADDRESS 1
+#define EFI_ALLOCATE_ADDRESS 2
+#define EFI_MAX_ALLOCATE_TYPE 3
+
+typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg);
+
+/*
+ * Types and defines for Time Services
+ */
+#define EFI_TIME_ADJUST_DAYLIGHT 0x1
+#define EFI_TIME_IN_DAYLIGHT 0x2
+#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
+
+typedef struct {
+ u16 year;
+ u8 month;
+ u8 day;
+ u8 hour;
+ u8 minute;
+ u8 second;
+ u8 pad1;
+ u32 nanosecond;
+ s16 timezone;
+ u8 daylight;
+ u8 pad2;
+} efi_time_t;
+
+typedef struct {
+ u32 resolution;
+ u32 accuracy;
+ 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
+ */
+typedef struct {
+ efi_table_hdr_t hdr;
+ void *raise_tpl;
+ void *restore_tpl;
+ 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;
+ 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;
+ efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, efi_guid_t *, void **);
+ void *__reserved;
+ void *register_protocol_notify;
+ 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;
+ 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;
+ efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
+ void *get_next_monotonic_count;
+ efi_status_t (EFIAPI *stall)(unsigned long usecs);
+ void *set_watchdog_timer;
+ 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;
+#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;
+ 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;
+ void *calculate_crc32;
+ void *copy_mem;
+ void *set_mem;
+ void *create_event_ex;
+} efi_boot_services_t;
+
+extern efi_boot_services_t *BS;
+
+/*
+ * Types and defines for EFI ResetSystem
+ */
+#define EFI_RESET_COLD 0
+#define EFI_RESET_WARM 1
+#define EFI_RESET_SHUTDOWN 2
+
+/*
+ * EFI Runtime Services table
+ */
+#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
+#define EFI_RUNTIME_SERVICES_REVISION 0x00010000
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ 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;
+
+extern efi_runtime_services_t *RT;
+
+/*
+ * EFI Configuration Table and GUID definitions
+ */
+#define EFI_NULL_GUID \
+ EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
+
+#define EFI_MPS_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_ACPI_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_ACPI_20_TABLE_GUID \
+ EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
+
+#define EFI_SMBIOS_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_SAL_SYSTEM_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_HCDP_TABLE_GUID \
+ EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
+
+#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 EFI_UV_SYSTEM_TABLE_GUID \
+ EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
+
+#define EFI_LINUX_EFI_CRASH_GUID \
+ EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
+
+#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 \
+ EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a )
+
+#define EFI_UGA_PROTOCOL_GUID \
+ EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 )
+
+#define EFI_PCI_IO_PROTOCOL_GUID \
+ EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a )
+
+#define EFI_FILE_INFO_GUID \
+ EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#define EFI_SIMPLE_FILE_SYSTEM_GUID \
+ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#define EFI_DEVICE_TREE_GUID \
+ EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
+
+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
+ EFI_GUID( 0x9576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#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)
+
+/* additional GUID from EDK2 */
+#define EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID \
+ EFI_GUID(0x220e73b6, 0x6bdb, 0x4413, 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a)
+
+#define EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID \
+ EFI_GUID(0x8f644fa9, 0xe850, 0x4db1, 0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4)
+
+#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \
+ EFI_GUID(0x2f707ebb, 0x4a1a, 0x11d4, 0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_ISA_ACPI_PROTOCOL_GUID \
+ EFI_GUID(0x64a892dc, 0x5561, 0x4536, 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55)
+
+#define EFI_ISA_IO_PROTOCOL_GUID \
+ EFI_GUID(0x7ee2bd44, 0x3da0, 0x11d4, 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_STANDARD_ERROR_DEVICE_GUID \
+ EFI_GUID(0xd3b36f2d, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_CONSOLE_OUT_DEVICE_GUID \
+ EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_CONSOLE_IN_DEVICE_GUID \
+ EFI_GUID(0xd3b36f2b, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID \
+ EFI_GUID(0x387477c2, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
+ EFI_GUID(0xdd9e7534, 0x7762, 0x4698, 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa)
+
+#define EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID \
+ EFI_GUID(0x387477c1, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_DISK_IO_PROTOCOL_GUID \
+ EFI_GUID(0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID \
+ EFI_GUID(0xa1e37052, 0x80d9, 0x4e65, 0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9)
+
+#define EFI_DISK_INFO_PROTOCOL_GUID \
+ EFI_GUID(0xd432a67f, 0x14dc, 0x484b, 0xb3, 0xbb, 0x3f, 0x2, 0x91, 0x84, 0x93, 0x27)
+
+#define EFI_SERIAL_IO_PROTOCOL_GUID \
+ EFI_GUID(0xbb25cf6f, 0xf1d4, 0x11d2, 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0xfd)
+
+#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \
+ EFI_GUID(0x3bc1b285, 0x8a15, 0x4a82, 0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65)
+
+#define EFI_LOAD_FILE2_PROTOCOL_GUID \
+ EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
+
+#define EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0x2fe800be, 0x8f01, 0x4aa6, 0x94, 0x6b, 0xd7, 0x13, 0x88, 0xe1, 0x83, 0x3f)
+
+#define EFI_DHCP4_PROTOCOL_GUID \
+ EFI_GUID(0x9d9a39d8, 0xbd42, 0x4a73, 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80)
+
+#define EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0x83f01464, 0x99bd, 0x45e5, 0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6)
+
+#define EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0x00720665, 0x67EB, 0x4a99, 0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9)
+
+#define EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0xc51711e7, 0xb4bf, 0x404a, 0xbf, 0xb8, 0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4)
+
+#define EFI_IP4_CONFIG_PROTOCOL_GUID \
+ EFI_GUID(0x3b95aa31, 0x3793, 0x434b, 0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e)
+
+#define EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID\
+ EFI_GUID(0xf44c00ee, 0x1f2c, 0x4a00, 0xaa, 0x9, 0x1c, 0x9f, 0x3e, 0x8, 0x0, 0xa3)
+
+#define EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0xf36ff770, 0xa7e1, 0x42cf, 0x9e, 0xd2, 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c)
+
+#define EFI_VLAN_CONFIG_PROTOCOL_GUID \
+ EFI_GUID(0x9e23d768, 0xd2f3, 0x4366, 0x9f, 0xc3, 0x3a, 0x7a, 0xba, 0x86, 0x43, 0x74)
+
+#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \
+ EFI_GUID(0x330d4706, 0xf2a0, 0x4e4f, 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85)
+
+#define LOAD_FILE_PROTOCOL_GUID \
+ EFI_GUID(0x56ec3091, 0x954c, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \
+ EFI_GUID(0x6a7a5cff, 0xe8d9, 0x4f70, 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14)
+
+#define EFI_IDEBUSDXE_INF_GUID \
+ EFI_GUID(0x69fd8e47, 0xa161, 0x4550, 0xb0, 0x1a, 0x55, 0x94, 0xce, 0xb2, 0xb2, 0xb2)
+
+#define EFI_TERMINALDXE_INF_GUID \
+ EFI_GUID(0x9e863906, 0xa40f, 0x4875, 0x97, 0x7f, 0x5b, 0x93, 0xff, 0x23, 0x7f, 0xc6)
+
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31 \
+ EFI_GUID(0x1aced566, 0x76ed, 0x4218, 0xbc, 0x81, 0x76, 0x7f, 0x1f, 0x97, 0x7a, 0x89)
+
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \
+ EFI_GUID(0xe18541cd, 0xf755, 0x4f73, 0x92, 0x8d, 0x64, 0x3c, 0x8a, 0x79, 0xb2, 0x29)
+
+#define EFI_ISCSIDXE_INF_GUID \
+ EFI_GUID(0x4579b72d, 0x7ec4, 0x4dd4, 0x84, 0x86, 0x08, 0x3c, 0x86, 0xb1, 0x82, 0xa7)
+
+#define EFI_VLANCONFIGDXE_INF_GUID \
+ EFI_GUID(0xe4f61863, 0xfe2c, 0x4b56, 0xa8, 0xf4, 0x08, 0x51, 0x9b, 0xc4, 0x39, 0xdf)
+
+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)
+
+#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30))
+#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20))
+#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10))
+#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00))
+#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10))
+#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02))
+
+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;
+ struct efi_simple_input_interface *con_in;
+ unsigned long con_out_handle;
+ struct efi_simple_text_output_protocol *con_out;
+ unsigned long stderr_handle;
+ 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;
+
+typedef struct {
+ u32 revision;
+ void *parent_handle;
+ efi_system_table_t *system_table;
+ void *device_handle;
+ void *file_path;
+ void *reserved;
+ u32 load_options_size;
+ void *load_options;
+ void *image_base;
+ __aligned_u64 image_size;
+ unsigned int image_code_type;
+ unsigned int image_data_type;
+ unsigned long unload;
+} efi_loaded_image_t;
+
+static inline int
+efi_guidcmp (efi_guid_t left, efi_guid_t right)
+{
+ return memcmp(&left, &right, sizeof (efi_guid_t));
+}
+
+/*
+ * Variable Attributes
+ */
+#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
+#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040
+
+#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_RUNTIME_ACCESS | \
+ EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_APPEND_WRITE)
+/*
+ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
+ * not including trailing NUL
+ */
+#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;
+};
+
+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);
+
+const char *efi_guid_string(efi_guid_t *g);
+
+#endif /* _LINUX_EFI_H */
diff --git a/include/filetype.h b/include/filetype.h
index fc3140c929..eedf4b4afe 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -32,6 +32,7 @@ enum filetype {
filetype_barebox_env,
filetype_ch_image,
filetype_ch_image_be,
+ filetype_exe,
filetype_max,
};
diff --git a/include/linux/efi.h b/include/linux/efi.h
deleted file mode 100644
index 570eff75de..0000000000
--- a/include/linux/efi.h
+++ /dev/null
@@ -1,547 +0,0 @@
-#ifndef _LINUX_EFI_H
-#define _LINUX_EFI_H
-
-/*
- * Extensible Firmware Interface
- * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999
- *
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- */
-#include <linux/string.h>
-#include <linux/types.h>
-
-#define EFI_SUCCESS 0
-#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
-
-typedef unsigned long efi_status_t;
-typedef u8 efi_bool_t;
-typedef u16 efi_char16_t; /* UNICODE character */
-
-
-typedef struct {
- u8 b[16];
-} efi_guid_t;
-
-#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, \
- (c) & 0xff, ((c) >> 8) & 0xff, \
- (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
-
-/*
- * Generic EFI table header
- */
-typedef struct {
- u64 signature;
- u32 revision;
- u32 headersize;
- u32 crc32;
- u32 reserved;
-} efi_table_hdr_t;
-
-/*
- * Memory map descriptor:
- */
-
-/* Memory types: */
-#define EFI_RESERVED_TYPE 0
-#define EFI_LOADER_CODE 1
-#define EFI_LOADER_DATA 2
-#define EFI_BOOT_SERVICES_CODE 3
-#define EFI_BOOT_SERVICES_DATA 4
-#define EFI_RUNTIME_SERVICES_CODE 5
-#define EFI_RUNTIME_SERVICES_DATA 6
-#define EFI_CONVENTIONAL_MEMORY 7
-#define EFI_UNUSABLE_MEMORY 8
-#define EFI_ACPI_RECLAIM_MEMORY 9
-#define EFI_ACPI_MEMORY_NVS 10
-#define EFI_MEMORY_MAPPED_IO 11
-#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
-#define EFI_PAL_CODE 13
-#define EFI_MAX_MEMORY_TYPE 14
-
-/* Attribute values: */
-#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
-#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
-#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
-#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
-#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
-#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
-#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
-#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
-#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;
-
-/*
- * Allocation types for calls to boottime->allocate_pages.
- */
-#define EFI_ALLOCATE_ANY_PAGES 0
-#define EFI_ALLOCATE_MAX_ADDRESS 1
-#define EFI_ALLOCATE_ADDRESS 2
-#define EFI_MAX_ALLOCATE_TYPE 3
-
-typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg);
-
-/*
- * Types and defines for Time Services
- */
-#define EFI_TIME_ADJUST_DAYLIGHT 0x1
-#define EFI_TIME_IN_DAYLIGHT 0x2
-#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
-
-typedef struct {
- u16 year;
- u8 month;
- u8 day;
- u8 hour;
- u8 minute;
- u8 second;
- u8 pad1;
- u32 nanosecond;
- s16 timezone;
- u8 daylight;
- u8 pad2;
-} efi_time_t;
-
-typedef struct {
- u32 resolution;
- u32 accuracy;
- u8 sets_to_zero;
-} efi_time_cap_t;
-
-/*
- * EFI Boot Services table
- */
-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;
- void *create_event;
- void *set_timer;
- void *wait_for_event;
- void *signal_event;
- void *close_event;
- void *check_event;
- void *install_protocol_interface;
- void *reinstall_protocol_interface;
- void *uninstall_protocol_interface;
- void *handle_protocol;
- void *__reserved;
- void *register_protocol_notify;
- void *locate_handle;
- void *locate_device_path;
- void *install_configuration_table;
- void *load_image;
- void *start_image;
- void *exit;
- void *unload_image;
- void *exit_boot_services;
- void *get_next_monotonic_count;
- void *stall;
- void *set_watchdog_timer;
- void *connect_controller;
- void *disconnect_controller;
- void *open_protocol;
- void *close_protocol;
- void *open_protocol_information;
- void *protocols_per_handle;
- void *locate_handle_buffer;
- void *locate_protocol;
- void *install_multiple_protocol_interfaces;
- void *uninstall_multiple_protocol_interfaces;
- void *calculate_crc32;
- void *copy_mem;
- void *set_mem;
- void *create_event_ex;
-} efi_boot_services_t;
-
-/*
- * Types and defines for EFI ResetSystem
- */
-#define EFI_RESET_COLD 0
-#define EFI_RESET_WARM 1
-#define EFI_RESET_SHUTDOWN 2
-
-/*
- * EFI Runtime Services table
- */
-#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
-#define EFI_RUNTIME_SERVICES_REVISION 0x00010000
-
-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;
-} 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);
-
-/*
- * EFI Configuration Table and GUID definitions
- */
-#define NULL_GUID \
- EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
-
-#define MPS_TABLE_GUID \
- EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define ACPI_TABLE_GUID \
- EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define ACPI_20_TABLE_GUID \
- EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
-
-#define SMBIOS_TABLE_GUID \
- EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define SAL_SYSTEM_TABLE_GUID \
- EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define HCDP_TABLE_GUID \
- EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
-
-#define 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 \
- EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
-
-#define LINUX_EFI_CRASH_GUID \
- EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
-
-#define LOADED_IMAGE_PROTOCOL_GUID \
- EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
-
-#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
- EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a )
-
-#define EFI_UGA_PROTOCOL_GUID \
- EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 )
-
-#define EFI_PCI_IO_PROTOCOL_GUID \
- EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a )
-
-#define EFI_FILE_INFO_ID \
- EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
-
-#define EFI_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;
-
-typedef struct {
- efi_guid_t guid;
- u32 table;
-} efi_config_table_32_t;
-
-typedef struct {
- efi_guid_t guid;
- unsigned long table;
-} efi_config_table_t;
-
-#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
-
-#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30))
-#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20))
-#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10))
-#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00))
-#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10))
-#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02))
-
-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;
- unsigned long con_out_handle;
- unsigned long con_out;
- unsigned long stderr_handle;
- unsigned long _stderr;
- 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;
- efi_system_table_t *system_table;
- void *device_handle;
- void *file_path;
- void *reserved;
- u32 load_options_size;
- void *load_options;
- void *image_base;
- __aligned_u64 image_size;
- unsigned int image_code_type;
- unsigned int image_data_type;
- 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
- */
-#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
-#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
-#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
-#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
-#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
-#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
-#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040
-
-#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \
- EFI_VARIABLE_BOOTSERVICE_ACCESS | \
- EFI_VARIABLE_RUNTIME_ACCESS | \
- EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
- EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
- EFI_VARIABLE_APPEND_WRITE)
-/*
- * The type of search to perform when calling boottime->locate_handle
- */
-#define EFI_LOCATE_ALL_HANDLES 0
-#define EFI_LOCATE_BY_REGISTER_NOTIFY 1
-#define EFI_LOCATE_BY_PROTOCOL 2
-
-/*
- * 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
-
-#endif /* _LINUX_EFI_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 4322f01580..c5ba99fe0a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -117,5 +117,26 @@
} \
)
-#endif /* _LINUX_KERNEL_H */
+extern const char hex_asc[];
+#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
+#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
+
+static inline char *hex_byte_pack(char *buf, u8 byte)
+{
+ *buf++ = hex_asc_hi(byte);
+ *buf++ = hex_asc_lo(byte);
+ return buf;
+}
+
+extern const char hex_asc_upper[];
+#define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0f)]
+#define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xf0) >> 4]
+static inline char *hex_byte_pack_upper(char *buf, u8 byte)
+{
+ *buf++ = hex_asc_upper_hi(byte);
+ *buf++ = hex_asc_upper_lo(byte);
+ return buf;
+}
+
+#endif /* _LINUX_KERNEL_H */
diff --git a/include/param.h b/include/param.h
index 24827c5e78..8f200df847 100644
--- a/include/param.h
+++ b/include/param.h
@@ -7,7 +7,7 @@
#define PARAM_FLAG_RO (1 << 0)
struct device_d;
-typedef unsigned long IPaddr_t;
+typedef uint32_t IPaddr_t;
struct param_d {
const char* (*get)(struct device_d *, struct param_d *param);
diff --git a/include/wchar.h b/include/wchar.h
new file mode 100644
index 0000000000..80dcd81bf4
--- /dev/null
+++ b/include/wchar.h
@@ -0,0 +1,18 @@
+#ifndef __WCHAR_H
+#define __WCHAR_H
+
+#include <linux/types.h>
+
+typedef u16 wchar_t;
+
+char *strcpy_wchar_to_char(char *dst, const wchar_t *src);
+
+wchar_t *strcpy_char_to_wchar(wchar_t *dst, const char *src);
+
+wchar_t *strdup_char_to_wchar(const char *src);
+
+char *strdup_wchar_to_char(const wchar_t *src);
+
+size_t wcslen(const wchar_t *s);
+
+#endif /* __WCHAR_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index d9ad4aa949..09a1674820 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -54,4 +54,7 @@ source lib/gui/Kconfig
source lib/bootstrap/Kconfig
+config PRINTF_UUID
+ bool
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index e8769a9be2..48c953d679 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -44,3 +44,4 @@ obj-y += gui/
obj-$(CONFIG_XYMODEM) += xymodem.o
obj-y += unlink-recursive.o
obj-$(CONFIG_STMP_DEVICE) += stmp-device.o
+obj-y += wchar.o
diff --git a/lib/misc.c b/lib/misc.c
index 0f3eb9aabb..87626c1e8b 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -21,6 +21,7 @@
#include <malloc.h>
#include <errno.h>
#include <fs.h>
+#include <string.h>
#include <linux/ctype.h>
/*
@@ -113,3 +114,5 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size)
return -1;
}
EXPORT_SYMBOL(parse_area_spec);
+
+const char hex_asc[] = "0123456789abcdef";
diff --git a/lib/readkey.c b/lib/readkey.c
index 7b38110113..2073a732f4 100644
--- a/lib/readkey.c
+++ b/lib/readkey.c
@@ -25,7 +25,7 @@
struct esc_cmds {
const char *seq;
- char val;
+ unsigned char val;
};
static const struct esc_cmds esccmds[] = {
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 066338b4e8..512c88247f 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -253,6 +253,53 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int
#endif
}
+static noinline_for_stack
+char *uuid_string(char *buf, char *end, const u8 *addr, int field_width,
+ int precision, int flags, const char *fmt)
+{
+ char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+ char *p = uuid;
+ int i;
+ static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
+ const u8 *index = be;
+ bool uc = false;
+
+ switch (*(++fmt)) {
+ case 'L':
+ uc = true; /* fall-through */
+ case 'l':
+ index = le;
+ break;
+ case 'B':
+ uc = true;
+ break;
+ }
+
+ for (i = 0; i < 16; i++) {
+ p = hex_byte_pack(p, addr[index[i]]);
+ switch (i) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ *p++ = '-';
+ break;
+ }
+ }
+
+ *p = 0;
+
+ if (uc) {
+ p = uuid;
+ do {
+ *p = toupper(*p);
+ } while (*(++p));
+ }
+
+ return string(buf, end, uuid, field_width, precision, flags);
+}
+
/*
* Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format
@@ -261,6 +308,17 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int
* Right now we handle:
*
* - 'S' For symbolic direct pointers
+ * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
+ * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ * Options for %pU are:
+ * b big endian lower case hex (default)
+ * B big endian UPPER case hex
+ * l little endian lower case hex
+ * L little endian UPPER case hex
+ * big endian output byte order is:
+ * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
+ * little endian output byte order is:
+ * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
*
* Note: The difference between 'S' and 'F' is that on ia64 and ppc64
* function pointers are really function descriptors, which contain a
@@ -271,6 +329,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
switch (*fmt) {
case 'S':
return symbol_string(buf, end, ptr, field_width, precision, flags);
+ case 'U':
+ if (IS_ENABLED(CONFIG_PRINTF_UUID))
+ return uuid_string(buf, end, ptr, field_width, precision, flags, fmt);
+ break;
}
flags |= SMALL;
if (field_width == -1) {
diff --git a/lib/wchar.c b/lib/wchar.c
new file mode 100644
index 0000000000..6368a01994
--- /dev/null
+++ b/lib/wchar.c
@@ -0,0 +1,80 @@
+/*
+ * wchar.c - wide character 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 WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <wchar.h>
+#include <malloc.h>
+#include <string.h>
+
+size_t wcslen(const wchar_t *s)
+{
+ size_t len = 0;
+
+ while (*s++)
+ len++;
+
+ return len;
+}
+
+char *strcpy_wchar_to_char(char *dst, const wchar_t *src)
+{
+ char *ret = dst;
+
+ while (*src)
+ *dst++ = *src++ & 0xff;
+
+ *dst = 0;
+
+ return ret;
+}
+
+wchar_t *strcpy_char_to_wchar(wchar_t *dst, const char *src)
+{
+ wchar_t *ret = dst;
+
+ while (*src)
+ *dst++ = *src++;
+
+ *dst = 0;
+
+ return ret;
+}
+
+wchar_t *strdup_char_to_wchar(const char *src)
+{
+ wchar_t *dst = malloc((strlen(src) + 1) * sizeof(wchar_t));
+
+ if (!dst)
+ return NULL;
+
+ strcpy_char_to_wchar(dst, src);
+
+ return dst;
+}
+
+char *strdup_wchar_to_char(const wchar_t *src)
+{
+ char *dst = malloc((wcslen(src) + 1));
+
+ if (!dst)
+ return NULL;
+
+ strcpy_wchar_to_char(dst, src);
+
+ return dst;
+}