9
0
Fork 0

Merge branch 'for-next/efi'

Conflicts:
	.gitignore
	Makefile
	drivers/serial/Makefile
This commit is contained in:
Sascha Hauer 2014-08-07 06:14:56 +02:00
commit 8a11a59b37
78 changed files with 6544 additions and 678 deletions

1
.gitignore vendored
View File

@ -46,6 +46,7 @@ barebox.uimage
barebox.map
barebox.kwb
barebox.kwbuart
barebox.efi
barebox.canon-a1100.bin
barebox-flash-image
System.map

View File

@ -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

View File

@ -16,3 +16,6 @@ Glossary
PBL
Pre BootLoader image
ESP
EFI System Partition

View File

@ -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

51
arch/efi/Kconfig Normal file
View File

@ -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

41
arch/efi/Makefile Normal file
View File

@ -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/

View File

@ -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

2
arch/efi/efi/Makefile Normal file
View File

@ -0,0 +1,2 @@
obj-y += efi.o clocksource.o efi-block-io.o efi-device.o efi-image.o
bbenv-y += env-efi

View File

@ -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;
}

174
arch/efi/efi/efi-block-io.c Normal file
View File

@ -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);

349
arch/efi/efi/efi-device.c Normal file
View File

@ -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);

105
arch/efi/efi/efi-image.c Normal file
View File

@ -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);

343
arch/efi/efi/efi.c Normal file
View File

@ -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;
}

View File

@ -0,0 +1,5 @@
#!/bin/sh
for i in /boot/network-drivers/*; do
$i;
done

View File

@ -0,0 +1 @@
/* dummy */

View File

@ -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

View File

@ -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 */

View File

@ -0,0 +1,4 @@
#ifndef ASM_COMMON_H
#define ASM_COMMON_H
#endif /* ASM_COMMON_H */

View File

@ -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 */

View File

@ -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__ */

55
arch/efi/include/asm/io.h Normal file
View File

@ -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 */

View File

@ -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

View File

@ -0,0 +1 @@
#include <asm-generic/sections.h>

View File

@ -0,0 +1 @@
/* dummy */

View File

@ -0,0 +1,6 @@
#ifndef _ASM_SWAB_H
#define _ASM_SWAB_H
/* nothing. use generic functions */
#endif /* _ASM_SWAB_H */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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 */

2
arch/efi/lib/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
elf_x86_64_efi.lds
elf_ia32_efi.lds

4
arch/efi/lib/Makefile Normal file
View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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) }
}

View File

@ -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) }
}

97
arch/efi/lib/reloc_ia32.c Normal file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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') {

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -55,6 +55,9 @@ static int writebuffer_flush(struct block_device *blk)
}
}
if (blk->ops->flush)
return blk->ops->flush(blk);
return 0;
}

View File

@ -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');

1370
common/efi-devicepath.c Normal file

File diff suppressed because it is too large Load Diff

84
common/efi-guid.c Normal file
View File

@ -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";
}

View File

@ -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)

View File

@ -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)
{
/*

View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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

296
drivers/net/efi-snp.c Normal file
View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

367
drivers/serial/efi-stdio.c Normal file
View File

@ -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);

View File

@ -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;
};
/**
* @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 uint8_t ns16550_read_reg_mmio_8(struct ns16550_priv *priv, unsigned offset)
{
if (mmio)
return readb(addr);
else
return (uint8_t) inb((int) addr);
return readb(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 void ns16550_write_reg_mmio_8(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
if (mmio)
return readw(addr);
else
return (uint16_t) inw((int) addr);
writeb(val, 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 uint8_t ns16550_read_reg_mmio_16(struct ns16550_priv *priv, unsigned offset)
{
if (mmio)
return readl(addr);
else
return (uint32_t) inl((int) addr);
return readw(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 void ns16550_write_reg_mmio_16(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
if (mmio)
writeb(val, addr);
else
outb(val, (int) addr);
writew(val, 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 uint8_t ns16550_read_reg_mmio_32(struct ns16550_priv *priv, unsigned offset)
{
if (mmio)
writew(val, addr);
else
outw(val, (int) addr);
return readl(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 void ns16550_write_reg_mmio_32(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
if (mmio)
writel(val, addr);
else
outl(val, (int) addr);
writel(val, priv->mmiobase + offset);
}
static uint8_t ns16550_read_reg_ioport_8(struct ns16550_priv *priv, unsigned offset)
{
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;

View File

@ -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

View File

@ -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

563
fs/efi.c Normal file
View File

@ -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);

340
fs/efivarfs.c Normal file
View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

621
include/efi.h Normal file
View File

@ -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 */

View File

@ -32,6 +32,7 @@ enum filetype {
filetype_barebox_env,
filetype_ch_image,
filetype_ch_image_be,
filetype_exe,
filetype_max,
};

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

18
include/wchar.h Normal file
View File

@ -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 */

View File

@ -54,4 +54,7 @@ source lib/gui/Kconfig
source lib/bootstrap/Kconfig
config PRINTF_UUID
bool
endmenu

View File

@ -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

View File

@ -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";

View File

@ -25,7 +25,7 @@
struct esc_cmds {
const char *seq;
char val;
unsigned char val;
};
static const struct esc_cmds esccmds[] = {

View File

@ -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) {

80
lib/wchar.c Normal file
View File

@ -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;
}