Merge branch 'for-next/efi'
Conflicts: .gitignore Makefile drivers/serial/Makefile
This commit is contained in:
commit
8a11a59b37
|
@ -46,6 +46,7 @@ barebox.uimage
|
|||
barebox.map
|
||||
barebox.kwb
|
||||
barebox.kwbuart
|
||||
barebox.efi
|
||||
barebox.canon-a1100.bin
|
||||
barebox-flash-image
|
||||
System.map
|
||||
|
|
|
@ -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
|
||||
|
|
@ -16,3 +16,6 @@ Glossary
|
|||
|
||||
PBL
|
||||
Pre BootLoader image
|
||||
|
||||
ESP
|
||||
EFI System Partition
|
||||
|
|
2
Makefile
2
Makefile
|
@ -994,7 +994,7 @@ CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \
|
|||
scripts/bareboxenv-target barebox-flash-image \
|
||||
barebox.srec barebox.s5p barebox.ubl barebox.zynq \
|
||||
barebox.uimage barebox.spi barebox.kwb barebox.kwbuart \
|
||||
barebox.canon-a1100.bin
|
||||
barebox.efi barebox.canon-a1100.bin
|
||||
|
||||
# Directories & files removed with 'make mrproper'
|
||||
MRPROPER_DIRS += include/config include2 usr/include
|
||||
|
|
|
@ -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
|
|
@ -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/
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
obj-y += efi.o clocksource.o efi-block-io.o efi-device.o efi-image.o
|
||||
bbenv-y += env-efi
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
for i in /boot/network-drivers/*; do
|
||||
$i;
|
||||
done
|
|
@ -0,0 +1 @@
|
|||
/* dummy */
|
|
@ -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
|
|
@ -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 */
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef ASM_COMMON_H
|
||||
#define ASM_COMMON_H
|
||||
|
||||
#endif /* ASM_COMMON_H */
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
*
|
||||
* This file is released under the GPLv2
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_DMA_H
|
||||
#define __ASM_DMA_H
|
||||
|
||||
/* empty*/
|
||||
|
||||
#endif /* __ASM_DMA_H */
|
|
@ -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__ */
|
|
@ -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 */
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
#include <asm-generic/sections.h>
|
|
@ -0,0 +1 @@
|
|||
/* dummy */
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _ASM_SWAB_H
|
||||
#define _ASM_SWAB_H
|
||||
|
||||
/* nothing. use generic functions */
|
||||
|
||||
#endif /* _ASM_SWAB_H */
|
|
@ -0,0 +1,73 @@
|
|||
#ifndef __ASM_I386_TYPES_H
|
||||
#define __ASM_I386_TYPES_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef __x86_64__
|
||||
/*
|
||||
* This is used in dlmalloc. On X86_64 we need it to be
|
||||
* 64 bit
|
||||
*/
|
||||
#define INTERNAL_SIZE_T unsigned long
|
||||
|
||||
/*
|
||||
* This is a Kconfig variable in the Kernel, but we want to detect
|
||||
* this during compile time, so we set it here.
|
||||
*/
|
||||
#define CONFIG_PHYS_ADDR_T_64BIT
|
||||
|
||||
#endif
|
||||
|
||||
typedef unsigned short umode_t;
|
||||
|
||||
/*
|
||||
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
|
||||
* header files exported to user space
|
||||
*/
|
||||
|
||||
typedef __signed__ char __s8;
|
||||
typedef unsigned char __u8;
|
||||
|
||||
typedef __signed__ short __s16;
|
||||
typedef unsigned short __u16;
|
||||
|
||||
typedef __signed__ int __s32;
|
||||
typedef unsigned int __u32;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
typedef __signed__ long long __s64;
|
||||
typedef unsigned long long __u64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These aren't exported outside the kernel to avoid name space clashes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
|
||||
typedef signed char s8;
|
||||
typedef unsigned char u8;
|
||||
|
||||
typedef signed short s16;
|
||||
typedef unsigned short u16;
|
||||
|
||||
typedef signed int s32;
|
||||
typedef unsigned int u32;
|
||||
|
||||
typedef signed long long s64;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define BITS_PER_LONG 64
|
||||
#else
|
||||
#define BITS_PER_LONG 32
|
||||
#endif
|
||||
|
||||
/* Dma addresses are 32-bits wide. */
|
||||
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -0,0 +1,2 @@
|
|||
elf_x86_64_efi.lds
|
||||
elf_ia32_efi.lds
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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) }
|
||||
}
|
|
@ -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) }
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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') {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -55,6 +55,9 @@ static int writebuffer_flush(struct block_device *blk)
|
|||
}
|
||||
}
|
||||
|
||||
if (blk->ops->flush)
|
||||
return blk->ops->flush(blk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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";
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
15
fs/Kconfig
15
fs/Kconfig
|
@ -41,6 +41,21 @@ config FS_NFS
|
|||
bool
|
||||
prompt "nfs support"
|
||||
|
||||
config FS_EFI
|
||||
depends on ARCH_EFI
|
||||
bool
|
||||
prompt "EFI filesystem support"
|
||||
help
|
||||
This filesystem driver provides access to the filesystems provided
|
||||
by the EFI Firmware via the EFI Simple File System Protocol.
|
||||
|
||||
config FS_EFIVARFS
|
||||
depends on ARCH_EFI
|
||||
bool
|
||||
prompt "EFI variable filesystem support (efivarfs)"
|
||||
help
|
||||
This filesystem driver provides access to EFI variables.
|
||||
|
||||
source fs/fat/Kconfig
|
||||
source fs/ubifs/Kconfig
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
|
@ -32,6 +32,7 @@ enum filetype {
|
|||
filetype_barebox_env,
|
||||
filetype_ch_image,
|
||||
filetype_ch_image_be,
|
||||
filetype_exe,
|
||||
filetype_max,
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
|
@ -54,4 +54,7 @@ source lib/gui/Kconfig
|
|||
|
||||
source lib/bootstrap/Kconfig
|
||||
|
||||
config PRINTF_UUID
|
||||
bool
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
struct esc_cmds {
|
||||
const char *seq;
|
||||
char val;
|
||||
unsigned char val;
|
||||
};
|
||||
|
||||
static const struct esc_cmds esccmds[] = {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue