mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2] Initial EFI support
@ 2014-07-11  7:36 Sascha Hauer
  2014-07-11  7:36 ` [PATCH 1/7] Documentation: Add EFI documentation Sascha Hauer
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Sascha Hauer @ 2014-07-11  7:36 UTC (permalink / raw)
  To: barebox

Second round of barebox on EFI patches. I merged the preparatory patches
already to -next, so here are only the EFI patches again.

Changes since v1:

- Add documentation how to run this on qemu
- The root directory on EFI filesystems now works on Tianocore (tested with qemu)
- Made 64-bit mandatory since 32-bit doesn't compile and cannot be tested
- Updated defconfig. For some reason the original defconfig had all relevant drivers
  disabled
- Add patch from Jean-Christophe to print GUIDs as strings

Sascha

The following changes since commit b6a37cf0c3eb5dddf69a5067c1b1d629d48a2fa0:

  efi: Add more error codes (2014-07-11 09:27:18 +0200)

are available in the git repository at:

  git://git.pengutronix.de/git/barebox.git efi

for you to fetch changes up to 873c978375a9a0b689c5bc73ac2281d748e0b809:

  EFI: introduce efi_strguid to convert GUID to human readable names (2014-07-11 09:29:13 +0200)

----------------------------------------------------------------
Jean-Christophe PLAGNIOL-VILLARD (1):
      EFI: introduce efi_strguid to convert GUID to human readable names

Sascha Hauer (6):
      Documentation: Add EFI documentation
      Add initial EFI architecture support
      net: Add EFI Simple Network Protocol Driver
      serial: Add EFI stdio driver
      fs: implement EFI filesystem driver
      fs: implement EFI variable filesystem driver

 .gitignore                                 |    1 +
 Documentation/boards/efi.rst               |  298 ++++++
 Documentation/glossary.rst                 |    3 +
 Makefile                                   |    3 +-
 arch/efi/Kconfig                           |   51 ++
 arch/efi/Makefile                          |   41 +
 arch/efi/configs/efi_defconfig             |   78 ++
 arch/efi/efi/Makefile                      |    2 +
 arch/efi/efi/clocksource.c                 |   60 ++
 arch/efi/efi/efi-block-io.c                |  174 ++++
 arch/efi/efi/efi-device.c                  |  349 +++++++
 arch/efi/efi/efi-image.c                   |  105 +++
 arch/efi/efi/efi.c                         |  343 +++++++
 arch/efi/efi/env-efi/network/eth0-discover |    5 +
 arch/efi/include/asm/barebox.h             |    1 +
 arch/efi/include/asm/bitops.h              |   15 +
 arch/efi/include/asm/byteorder.h           |    8 +
 arch/efi/include/asm/common.h              |    4 +
 arch/efi/include/asm/dma.h                 |   13 +
 arch/efi/include/asm/elf.h                 |   60 ++
 arch/efi/include/asm/io.h                  |   55 ++
 arch/efi/include/asm/posix_types.h         |   93 ++
 arch/efi/include/asm/sections.h            |    1 +
 arch/efi/include/asm/string.h              |    1 +
 arch/efi/include/asm/swab.h                |    6 +
 arch/efi/include/asm/types.h               |   73 ++
 arch/efi/include/asm/unaligned.h           |   19 +
 arch/efi/include/mach/debug_ll.h           |   20 +
 arch/efi/include/mach/efi-device.h         |   45 +
 arch/efi/include/mach/efi.h                |   24 +
 arch/efi/lib/.gitignore                    |    2 +
 arch/efi/lib/Makefile                      |    4 +
 arch/efi/lib/crt0-efi-ia32.S               |   76 ++
 arch/efi/lib/crt0-efi-x86_64.S             |   75 ++
 arch/efi/lib/elf_ia32_efi.lds.S            |  102 +++
 arch/efi/lib/elf_x86_64_efi.lds.S          |   93 ++
 arch/efi/lib/reloc_ia32.c                  |   97 ++
 arch/efi/lib/reloc_x86_64.c                |   96 ++
 commands/edit.c                            |   11 +-
 common/Kconfig                             |    8 +
 common/Makefile                            |    4 +-
 common/efi-devicepath.c                    | 1370 ++++++++++++++++++++++++++++
 common/efi-guid.c                          |   84 ++
 common/memory.c                            |    2 +-
 common/partitions/efi.c                    |    2 +-
 drivers/net/Kconfig                        |    4 +
 drivers/net/Makefile                       |    1 +
 drivers/net/efi-snp.c                      |  296 ++++++
 drivers/of/Kconfig                         |    2 +-
 drivers/serial/Kconfig                     |    4 +
 drivers/serial/Makefile                    |    1 +
 drivers/serial/efi-stdio.c                 |  367 ++++++++
 fs/Kconfig                                 |   15 +
 fs/Makefile                                |    2 +
 fs/efi.c                                   |  563 ++++++++++++
 fs/efivarfs.c                              |  340 +++++++
 include/efi.h                              |  572 ++++++------
 57 files changed, 5873 insertions(+), 271 deletions(-)
 create mode 100644 Documentation/boards/efi.rst
 create mode 100644 arch/efi/Kconfig
 create mode 100644 arch/efi/Makefile
 create mode 100644 arch/efi/configs/efi_defconfig
 create mode 100644 arch/efi/efi/Makefile
 create mode 100644 arch/efi/efi/clocksource.c
 create mode 100644 arch/efi/efi/efi-block-io.c
 create mode 100644 arch/efi/efi/efi-device.c
 create mode 100644 arch/efi/efi/efi-image.c
 create mode 100644 arch/efi/efi/efi.c
 create mode 100644 arch/efi/efi/env-efi/network/eth0-discover
 create mode 100644 arch/efi/include/asm/barebox.h
 create mode 100644 arch/efi/include/asm/bitops.h
 create mode 100644 arch/efi/include/asm/byteorder.h
 create mode 100644 arch/efi/include/asm/common.h
 create mode 100644 arch/efi/include/asm/dma.h
 create mode 100644 arch/efi/include/asm/elf.h
 create mode 100644 arch/efi/include/asm/io.h
 create mode 100644 arch/efi/include/asm/posix_types.h
 create mode 100644 arch/efi/include/asm/sections.h
 create mode 100644 arch/efi/include/asm/string.h
 create mode 100644 arch/efi/include/asm/swab.h
 create mode 100644 arch/efi/include/asm/types.h
 create mode 100644 arch/efi/include/asm/unaligned.h
 create mode 100644 arch/efi/include/mach/debug_ll.h
 create mode 100644 arch/efi/include/mach/efi-device.h
 create mode 100644 arch/efi/include/mach/efi.h
 create mode 100644 arch/efi/lib/.gitignore
 create mode 100644 arch/efi/lib/Makefile
 create mode 100644 arch/efi/lib/crt0-efi-ia32.S
 create mode 100644 arch/efi/lib/crt0-efi-x86_64.S
 create mode 100644 arch/efi/lib/elf_ia32_efi.lds.S
 create mode 100644 arch/efi/lib/elf_x86_64_efi.lds.S
 create mode 100644 arch/efi/lib/reloc_ia32.c
 create mode 100644 arch/efi/lib/reloc_x86_64.c
 create mode 100644 common/efi-devicepath.c
 create mode 100644 common/efi-guid.c
 create mode 100644 drivers/net/efi-snp.c
 create mode 100644 drivers/serial/efi-stdio.c
 create mode 100644 fs/efi.c
 create mode 100644 fs/efivarfs.c

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/7] Documentation: Add EFI documentation
  2014-07-11  7:36 [PATCH v2] Initial EFI support Sascha Hauer
@ 2014-07-11  7:36 ` Sascha Hauer
  2014-07-11  7:36 ` [PATCH 3/7] net: Add EFI Simple Network Protocol Driver Sascha Hauer
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2014-07-11  7:36 UTC (permalink / raw)
  To: barebox

This adds documentation for the upcoming barebox on EFI support.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 Documentation/boards/efi.rst | 298 +++++++++++++++++++++++++++++++++++++++++++
 Documentation/glossary.rst   |   3 +
 2 files changed, 301 insertions(+)
 create mode 100644 Documentation/boards/efi.rst

diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst
new file mode 100644
index 0000000..2147cb6
--- /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 8bad7dc..106dce9 100644
--- a/Documentation/glossary.rst
+++ b/Documentation/glossary.rst
@@ -16,3 +16,6 @@ Glossary
 
    PBL
       Pre BootLoader image
+
+   ESP
+      EFI System Partition
-- 
2.0.0


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/7] net: Add EFI Simple Network Protocol Driver
  2014-07-11  7:36 [PATCH v2] Initial EFI support Sascha Hauer
  2014-07-11  7:36 ` [PATCH 1/7] Documentation: Add EFI documentation Sascha Hauer
@ 2014-07-11  7:36 ` Sascha Hauer
  2014-07-11  7:36 ` [PATCH 4/7] serial: Add EFI stdio driver Sascha Hauer
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2014-07-11  7:36 UTC (permalink / raw)
  To: barebox

This adds a network driver which uses the EFI Simple Network
Protocol to implement networking for barebox.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/net/Kconfig   |   4 +
 drivers/net/Makefile  |   1 +
 drivers/net/efi-snp.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 301 insertions(+)
 create mode 100644 drivers/net/efi-snp.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f0c41b..43409a8 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 33bb5c8..1b85778 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 0000000..5b96fbf
--- /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);
-- 
2.0.0


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/7] serial: Add EFI stdio driver
  2014-07-11  7:36 [PATCH v2] Initial EFI support Sascha Hauer
  2014-07-11  7:36 ` [PATCH 1/7] Documentation: Add EFI documentation Sascha Hauer
  2014-07-11  7:36 ` [PATCH 3/7] net: Add EFI Simple Network Protocol Driver Sascha Hauer
@ 2014-07-11  7:36 ` Sascha Hauer
  2014-07-11  7:36 ` [PATCH 5/7] fs: implement EFI filesystem driver Sascha Hauer
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2014-07-11  7:36 UTC (permalink / raw)
  To: barebox

This adds a driver which uses the EFI stdin/stdout interfaces to
implement a barebox console. Keyboard input should be fairly complete,
but not all vt100 needed by barebox work properly. The clear-to-eol
escape is missing causing garbled output in the editor.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/edit.c            |  11 +-
 drivers/serial/Kconfig     |   4 +
 drivers/serial/Makefile    |   1 +
 drivers/serial/efi-stdio.c | 367 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 382 insertions(+), 1 deletion(-)
 create mode 100644 drivers/serial/efi-stdio.c

diff --git a/commands/edit.c b/commands/edit.c
index 5a2da7d..98af583 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/drivers/serial/Kconfig b/drivers/serial/Kconfig
index f51c6e6..5698c2f 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 e1865f7..2c0176d 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -18,3 +18,4 @@ 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
diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c
new file mode 100644
index 0000000..bf14c5e
--- /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);
-- 
2.0.0


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 5/7] fs: implement EFI filesystem driver
  2014-07-11  7:36 [PATCH v2] Initial EFI support Sascha Hauer
                   ` (2 preceding siblings ...)
  2014-07-11  7:36 ` [PATCH 4/7] serial: Add EFI stdio driver Sascha Hauer
@ 2014-07-11  7:36 ` Sascha Hauer
  2014-07-11  7:36 ` [PATCH 6/7] fs: implement EFI variable " Sascha Hauer
  2014-07-11  7:36 ` [PATCH 7/7] EFI: introduce efi_strguid to convert GUID to human readable names Sascha Hauer
  5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2014-07-11  7:36 UTC (permalink / raw)
  To: barebox

This implements a filesystem driver which uses the EFI Simple File
System Protocol to provide files from EFI to barebox.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/Kconfig  |   8 +
 fs/Makefile |   1 +
 fs/efi.c    | 563 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 572 insertions(+)
 create mode 100644 fs/efi.c

diff --git a/fs/Kconfig b/fs/Kconfig
index 3724b34..21690de 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -41,6 +41,14 @@ 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.
+
 source fs/fat/Kconfig
 source fs/ubifs/Kconfig
 
diff --git a/fs/Makefile b/fs/Makefile
index d3465ed..f027851 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -11,3 +11,4 @@ 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
diff --git a/fs/efi.c b/fs/efi.c
new file mode 100644
index 0000000..f096f91
--- /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);
-- 
2.0.0


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 6/7] fs: implement EFI variable filesystem driver
  2014-07-11  7:36 [PATCH v2] Initial EFI support Sascha Hauer
                   ` (3 preceding siblings ...)
  2014-07-11  7:36 ` [PATCH 5/7] fs: implement EFI filesystem driver Sascha Hauer
@ 2014-07-11  7:36 ` Sascha Hauer
  2014-07-11  7:36 ` [PATCH 7/7] EFI: introduce efi_strguid to convert GUID to human readable names Sascha Hauer
  5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2014-07-11  7:36 UTC (permalink / raw)
  To: barebox

This implements a filesystem for accessing EFI variables.
It is compatible to the Linux Kernel efivarfs filesystem.
Currently the variables can only be accessed readonly.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/Kconfig    |   7 ++
 fs/Makefile   |   1 +
 fs/efivarfs.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 348 insertions(+)
 create mode 100644 fs/efivarfs.c

diff --git a/fs/Kconfig b/fs/Kconfig
index 21690de..64fc117 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -49,6 +49,13 @@ config FS_EFI
 	  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 f027851..f5aae91 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -12,3 +12,4 @@ 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/efivarfs.c b/fs/efivarfs.c
new file mode 100644
index 0000000..58c637e
--- /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);
-- 
2.0.0


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 7/7] EFI: introduce efi_strguid to convert GUID to human readable names
  2014-07-11  7:36 [PATCH v2] Initial EFI support Sascha Hauer
                   ` (4 preceding siblings ...)
  2014-07-11  7:36 ` [PATCH 6/7] fs: implement EFI variable " Sascha Hauer
@ 2014-07-11  7:36 ` Sascha Hauer
  5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2014-07-11  7:36 UTC (permalink / raw)
  To: barebox

From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

use in devinfo Protocols

Tested today on qemu with all the GUID translated

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/efi/efi/efi-device.c |   3 +-
 arch/efi/efi/efi.c        |   5 ++-
 common/efi-guid.c         |  73 +++++++++++++++++++++++++++++++
 include/efi.h             | 108 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 186 insertions(+), 3 deletions(-)

diff --git a/arch/efi/efi/efi-device.c b/arch/efi/efi/efi-device.c
index 71526b9..1c9553d 100644
--- a/arch/efi/efi/efi-device.c
+++ b/arch/efi/efi/efi-device.c
@@ -86,7 +86,8 @@ static void efi_devinfo(struct device_d *dev)
 	printf("Protocols:\n");
 
 	for (i = 0; i < efidev->num_guids; i++)
-		printf("  %d: %pUl\n", i, &efidev->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)
diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c
index 48b7d9a..ff97783 100644
--- a/arch/efi/efi/efi.c
+++ b/arch/efi/efi/efi.c
@@ -36,6 +36,7 @@
 #include <binfmt.h>
 #include <wchar.h>
 #include <envfs.h>
+#include <efi.h>
 #include <mach/efi.h>
 #include <mach/efi-device.h>
 
@@ -233,6 +234,8 @@ static struct NS16550_plat ns16550_plat = {
 
 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))
@@ -296,8 +299,6 @@ static void fixup_tables(void)
 
 static int efi_init(void)
 {
-	barebox_set_model("barebox EFI payload");
-
 	defaultenv_append_directory(env_efi);
 
 	return 0;
diff --git a/common/efi-guid.c b/common/efi-guid.c
index 5109b5d..f6b0404 100644
--- a/common/efi-guid.c
+++ b/common/efi-guid.c
@@ -9,3 +9,76 @@ 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/include/efi.h b/include/efi.h
index c624eb3..597dc74 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -354,6 +354,112 @@ extern efi_runtime_services_t *RT;
 #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;
@@ -505,4 +611,6 @@ static inline int efi_compare_guid(efi_guid_t *a, efi_guid_t *b)
 
 char *device_path_to_str(struct efi_device_path *dev_path);
 
+const char *efi_guid_string(efi_guid_t *g);
+
 #endif /* _LINUX_EFI_H */
-- 
2.0.0


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-07-11  7:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-11  7:36 [PATCH v2] Initial EFI support Sascha Hauer
2014-07-11  7:36 ` [PATCH 1/7] Documentation: Add EFI documentation Sascha Hauer
2014-07-11  7:36 ` [PATCH 3/7] net: Add EFI Simple Network Protocol Driver Sascha Hauer
2014-07-11  7:36 ` [PATCH 4/7] serial: Add EFI stdio driver Sascha Hauer
2014-07-11  7:36 ` [PATCH 5/7] fs: implement EFI filesystem driver Sascha Hauer
2014-07-11  7:36 ` [PATCH 6/7] fs: implement EFI variable " Sascha Hauer
2014-07-11  7:36 ` [PATCH 7/7] EFI: introduce efi_strguid to convert GUID to human readable names Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox