9
0
Fork 0

Add initial EFI architecture support

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

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Sascha Hauer 2014-07-07 18:02:53 +02:00
parent 3475ba2a1d
commit 1dff7e414d
44 changed files with 3791 additions and 270 deletions

1
.gitignore vendored
View File

@ -46,6 +46,7 @@ barebox.uimage
barebox.map
barebox.kwb
barebox.kwbuart
barebox.efi
barebox-flash-image
System.map
Module.symvers

View File

@ -997,7 +997,8 @@ CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \
.tmp_kallsyms* common/barebox_default_env* barebox.ldr \
scripts/bareboxenv-target barebox-flash-image \
Doxyfile.version barebox.srec barebox.s5p barebox.ubl \
barebox.uimage barebox.spi barebox.kwb barebox.kwbuart
barebox.uimage barebox.spi barebox.kwb barebox.kwbuart \
barebox.efi
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS += include/config include2 usr/include

51
arch/efi/Kconfig Normal file
View File

@ -0,0 +1,51 @@
config ARCH_EFI
bool
default y
select HAS_DEBUG_LL
select HAS_KALLSYMS
select HAVE_DEFAULT_ENVIRONMENT_NEW
select EFI_GUID
select EFI_DEVICEPATH
select PRINTF_UUID
config ARCH_TEXT_BASE
hex
default 0x0
menu "EFI specific settings"
config 64BIT
def_bool y
help
Say yes to build a 64-bit binary - formerly known as x86_64
Say no to build a 32-bit binary - formerly known as i386.
32-bit support currently does not compile and is not tested
due to the lack of hardware.
config X86_32
def_bool y
depends on !64BIT
config X86_64
def_bool y
depends on 64BIT
config ARCH_EFI_REGISTER_COM1
bool "Register first serial port"
help
Say yes here to register the first serial port on ioport 0x3f8.
This is useful to control barebox over a serial port if the board
has one. Enabling this option may not work on boards which do not
have a serial port. Also enable DRIVER_SERIAL_NS16550 to enable
the NS16550 driver.
endmenu
source common/Kconfig
source commands/Kconfig
source net/Kconfig
source drivers/Kconfig
source fs/Kconfig
source lib/Kconfig
source crypto/Kconfig

41
arch/efi/Makefile Normal file
View File

@ -0,0 +1,41 @@
CFLAGS += -fpic -fshort-wchar -mno-sse -mno-mmx
ifeq ($(CONFIG_X86_32),y)
UTS_MACHINE := i386
biarch := $(call cc-option,-m32)
AFLAGS += $(biarch)
CFLAGS += $(biarch)
TARGET = efi-app-ia32
else
UTS_MACHINE := x86_64
AFLAGS += -m64
CFLAGS += -m64 -mno-red-zone
TARGET = efi-app-x86_64
endif
lds-$(CONFIG_X86_32) := arch/efi/lib/elf_ia32_efi.lds
lds-$(CONFIG_X86_64) := arch/efi/lib/elf_x86_64_efi.lds
cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \
-T $(lds-y) \
-shared -Bsymbolic -nostdlib -znocombreloc \
--start-group $(barebox-common) \
--end-group \
$(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^)
quiet_cmd_efi_image = EFI-IMG $@
cmd_efi_image = objcopy -j .text -j .sdata -j .data -j .dynamic \
-j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \
-j __barebox_cmd -j .barebox_magicvar -j .bbenv.* \
--target=$(TARGET) $< $@
KBUILD_BINARY := barebox
LDFLAGS := -m elf_$(UTS_MACHINE) --no-undefined
barebox.efi: $(KBUILD_BINARY) FORCE
$(call if_changed,efi_image)
KBUILD_IMAGE := barebox.efi
common-y += arch/efi/efi/ arch/efi/lib/

View File

@ -0,0 +1,78 @@
CONFIG_MMU=y
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_PROMPT="barebox> "
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
# CONFIG_TIMESTAMP is not set
CONFIG_CONSOLE_ACTIVATE_ALL=y
CONFIG_PARTITION_DISK_EFI=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_POLLER=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_LL=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
CONFIG_CMD_MEMINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
CONFIG_CMD_GO=y
CONFIG_CMD_LOADB=y
CONFIG_CMD_RESET=y
CONFIG_CMD_UIMAGE=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_LOADENV=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_SAVEENV=y
CONFIG_CMD_FILETYPE=y
CONFIG_CMD_LN=y
CONFIG_CMD_MD5SUM=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_CMD_LET=y
CONFIG_CMD_MSLEEP=y
CONFIG_CMD_READF=y
CONFIG_CMD_SLEEP=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_HOST=y
CONFIG_CMD_PING=y
CONFIG_CMD_TFTP=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_EDIT=y
CONFIG_CMD_MENU=y
CONFIG_CMD_MENUTREE=y
CONFIG_CMD_READLINE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_CRC=y
CONFIG_CMD_CRC_CMP=y
CONFIG_CMD_MM=y
CONFIG_CMD_DETECT=y
CONFIG_CMD_FLASH=y
CONFIG_CMD_2048=y
CONFIG_CMD_BAREBOX_UPDATE=y
CONFIG_CMD_OF_NODE=y
CONFIG_CMD_OF_PROPERTY=y
CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIME=y
CONFIG_NET=y
CONFIG_NET_NFS=y
CONFIG_NET_NETCONSOLE=y
CONFIG_DRIVER_SERIAL_EFI_STDIO=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_NET_EFI_SNP=y
# CONFIG_SPI is not set
CONFIG_DISK=y
CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
CONFIG_FS_EFI=y
CONFIG_FS_EFIVARFS=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y

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

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

View File

@ -0,0 +1,60 @@
#include <common.h>
#include <efi.h>
#include <mach/efi.h>
#include <clock.h>
#ifdef __x86_64__
uint64_t ticks_read(void)
{
uint64_t a, d;
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
return (d << 32) | a;
}
#else
uint64_t ticks_read(void)
{
uint64_t val;
__asm__ volatile ("rdtsc" : "=A" (val));
return val;
}
#endif
static uint64_t freq;
/* count TSC ticks during a millisecond delay */
static uint64_t ticks_freq(void)
{
uint64_t ticks_start, ticks_end;
ticks_start = ticks_read();
BS->stall(1000);
ticks_end = ticks_read();
return (ticks_end - ticks_start) * 1000;
}
static uint64_t efi_clocksource_read(void)
{
return 1000 * 1000 * ticks_read() / freq;
}
static struct clocksource cs = {
.read = efi_clocksource_read,
.mask = CLOCKSOURCE_MASK(64),
.shift = 0,
};
int efi_clocksource_init(void)
{
cs.mult = clocksource_hz2mult(1000 * 1000, cs.shift);
freq = ticks_freq();
init_clock(&cs);
return 0;
}

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

@ -0,0 +1,174 @@
#include <common.h>
#include <driver.h>
#include <init.h>
#include <malloc.h>
#include <fs.h>
#include <string.h>
#include <command.h>
#include <errno.h>
#include <linux/stat.h>
#include <xfuncs.h>
#include <fcntl.h>
#include <efi.h>
#include <block.h>
#include <disks.h>
#include <mach/efi.h>
#include <mach/efi-device.h>
#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31))
struct efi_block_io_media{
u32 media_id;
bool removable_media;
bool media_present;
bool logical_partition;
bool read_only;
bool write_caching;
u32 block_size;
u32 io_align;
u64 last_block;
u64 lowest_aligned_lba; /* added in Revision 2 */
u32 logical_blocks_per_physical_block; /* added in Revision 2 */
u32 optimal_transfer_length_granularity; /* added in Revision 3 */
};
struct efi_block_io_protocol {
u64 revision;
struct efi_block_io_media *media;
efi_status_t(EFIAPI *reset)(struct efi_block_io_protocol *this,
bool ExtendedVerification);
efi_status_t(EFIAPI *read)(struct efi_block_io_protocol *this, u32 media_id,
u64 lba, unsigned long buffer_size, void *buf);
efi_status_t(EFIAPI *write)(struct efi_block_io_protocol *this, u32 media_id,
u64 lba, unsigned long buffer_size, void *buf);
efi_status_t(EFIAPI *flush)(struct efi_block_io_protocol *this);
};
struct efi_bio_priv {
struct efi_block_io_protocol *protocol;
struct device_d *dev;
struct block_device blk;
u32 media_id;
};
static int efi_bio_read(struct block_device *blk, void *buffer, int block,
int num_blocks)
{
struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
efi_status_t efiret;
efiret = priv->protocol->read(priv->protocol, priv->media_id,
block, num_blocks * 512, buffer);
if (EFI_ERROR(efiret))
return -efi_errno(efiret);
return 0;
}
static int efi_bio_write(struct block_device *blk,
const void *buffer, int block, int num_blocks)
{
struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
efi_status_t efiret;
efiret = priv->protocol->write(priv->protocol, priv->media_id,
block, num_blocks * 512, (void *)buffer);
if (EFI_ERROR(efiret))
return -efi_errno(efiret);
return 0;
}
static int efi_bio_flush(struct block_device *blk)
{
struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
efi_status_t efiret;
efiret = priv->protocol->flush(priv->protocol);
if (EFI_ERROR(efiret))
return -efi_errno(efiret);
return 0;
}
static struct block_device_ops efi_bio_ops = {
.read = efi_bio_read,
.write = efi_bio_write,
.flush = efi_bio_flush,
};
static void efi_bio_print_info(struct efi_bio_priv *priv)
{
struct efi_block_io_media *media = priv->protocol->media;
u64 revision = priv->protocol->revision;
dev_dbg(priv->dev, "revision: 0x%016llx\n", revision);
dev_dbg(priv->dev, "media_id: 0x%08x\n", media->media_id);
dev_dbg(priv->dev, "removable_media: %d\n", media->removable_media);
dev_dbg(priv->dev, "media_present: %d\n", media->media_present);
dev_dbg(priv->dev, "logical_partition: %d\n", media->logical_partition);
dev_dbg(priv->dev, "read_only: %d\n", media->read_only);
dev_dbg(priv->dev, "write_caching: %d\n", media->write_caching);
dev_dbg(priv->dev, "block_size: 0x%08x\n", media->block_size);
dev_dbg(priv->dev, "io_align: 0x%08x\n", media->io_align);
dev_dbg(priv->dev, "last_block: 0x%016llx\n", media->last_block);
if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION2)
return;
dev_dbg(priv->dev, "u64 lowest_aligned_lba: 0x%08llx\n",
media->lowest_aligned_lba);
dev_dbg(priv->dev, "logical_blocks_per_physical_block: 0x%08x\n",
media->logical_blocks_per_physical_block);
if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION3)
return;
dev_dbg(priv->dev, "optimal_transfer_length_granularity: 0x%08x\n",
media->optimal_transfer_length_granularity);
}
int efi_bio_probe(struct efi_device *efidev)
{
int ret;
struct efi_bio_priv *priv;
struct efi_block_io_media *media;
priv = xzalloc(sizeof(*priv));
BS->handle_protocol(efidev->handle, &efi_block_io_protocol_guid,
(void **)&priv->protocol);
if (!priv->protocol)
return -ENODEV;
media = priv->protocol->media;
efi_bio_print_info(priv);
priv->dev = &efidev->dev;
priv->blk.cdev.name = asprintf("disk%d", cdev_find_free_index("disk"));
priv->blk.blockbits = ffs(media->block_size) - 1;
priv->blk.num_blocks = media->last_block;
priv->blk.ops = &efi_bio_ops;
priv->blk.dev = &efidev->dev;
priv->media_id = media->media_id;
ret = blockdevice_register(&priv->blk);
if (ret)
return ret;
parse_partition_table(&priv->blk);
return 0;
}
static struct efi_driver efi_fs_driver = {
.driver = {
.name = "efi-block-io",
},
.probe = efi_bio_probe,
.guid = EFI_BLOCK_IO_PROTOCOL_GUID,
};
device_efi_driver(efi_fs_driver);

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

@ -0,0 +1,348 @@
/*
* efi-device.c - barebox EFI payload support
*
* Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <command.h>
#include <common.h>
#include <driver.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <sizes.h>
#include <wchar.h>
#include <init.h>
#include <efi.h>
#include <mach/efi.h>
#include <mach/efi-device.h>
#include <linux/err.h>
int efi_locate_handle(enum efi_locate_search_type search_type,
efi_guid_t *protocol,
void *search_key,
unsigned long *no_handles,
efi_handle_t **buffer)
{
efi_status_t efiret;
unsigned long buffer_size = 0;
efi_handle_t *buf;
efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size,
NULL);
if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL)
return -efi_errno(efiret);
buf = malloc(buffer_size);
if (!buf)
return -ENOMEM;
efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size,
buf);
if (EFI_ERROR(efiret)) {
free(buf);
return -efi_errno(efiret);
}
*no_handles = buffer_size / sizeof(efi_handle_t);
*buffer = buf;
return 0;
}
static struct efi_device *efi_find_device(efi_handle_t *handle)
{
struct device_d *dev;
struct efi_device *efidev;
bus_for_each_device(&efi_bus, dev) {
efidev = container_of(dev, struct efi_device, dev);
if (efidev->handle == handle)
return efidev;
}
return NULL;
}
static void efi_devinfo(struct device_d *dev)
{
struct efi_device *efidev = to_efi_device(dev);
int i;
printf("Protocols:\n");
for (i = 0; i < efidev->num_guids; i++)
printf(" %d: %pUl\n", i, &efidev->guids[i]);
}
static efi_handle_t *efi_find_parent(efi_handle_t *handle)
{
unsigned long handle_count = 0;
efi_handle_t *handles = NULL, *parent;
unsigned long num_guids;
efi_guid_t **guids;
int ret, i, j, k;
efi_status_t efiret;
struct efi_open_protocol_information_entry *entry_buffer;
unsigned long entry_count;
ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles);
if (ret)
return NULL;
/*
* Normally one would expect a function/pointer to retrieve the parent.
* With EFI we have to:
* - get all handles
* - for each handle get the registered protocols
* - for each protocol get the users
* - the user which matches the input handle is the parent
*/
for (i = 0; i < handle_count; i++) {
efiret = BS->open_protocol(handles[i], &efi_device_path_protocol_guid,
NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
if (EFI_ERROR(efiret))
continue;
BS->protocols_per_handle(handles[i], &guids, &num_guids);
for (j = 0; j < num_guids; j++) {
efiret = BS->open_protocol_information(handles[i], guids[j],
&entry_buffer, &entry_count);
for (k = 0; k < entry_count; k++) {
if (entry_buffer[k].controller_handle == NULL)
continue;
if (entry_buffer[k].controller_handle == handles[i])
continue;
if (entry_buffer[k].controller_handle == handle) {
parent = handles[i];
goto out;
}
}
}
}
parent = NULL;
free(handles);
out:
return parent;
}
static struct efi_device *efi_add_device(efi_handle_t *handle, efi_guid_t **guids,
int num_guids)
{
struct efi_device *efidev;
int i;
efi_guid_t *guidarr;
efi_status_t efiret;
void *devpath;
efidev = efi_find_device(handle);
if (efidev)
return ERR_PTR(-EEXIST);
efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid,
NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
if (EFI_ERROR(efiret))
return ERR_PTR(-EINVAL);
guidarr = malloc(sizeof(efi_guid_t) * num_guids);
for (i = 0; i < num_guids; i++)
memcpy(&guidarr[i], guids[i], sizeof(efi_guid_t));
efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid,
&devpath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(efiret))
return ERR_PTR(-EINVAL);
efidev = xzalloc(sizeof(*efidev));
efidev->guids = guidarr;
efidev->num_guids = num_guids;
efidev->handle = handle;
efidev->dev.bus = &efi_bus;
efidev->dev.id = DEVICE_ID_SINGLE;
efidev->dev.info = efi_devinfo;
efidev->devpath = devpath;
BS->handle_protocol(handle, &guidarr[0], &efidev->protocol);
sprintf(efidev->dev.name, "handle-%p", handle);
efidev->parent_handle = efi_find_parent(efidev->handle);
return efidev;
}
static int efi_register_device(struct efi_device *efidev)
{
char *dev_path_str;
struct efi_device *parent;
int ret;
if (efi_find_device(efidev->handle))
return -EEXIST;
if (efidev->parent_handle) {
parent = efi_find_device(efidev->parent_handle);
if (!parent)
return -EINVAL;
efidev->dev.parent = &parent->dev;
}
ret = register_device(&efidev->dev);
if (ret)
return ret;
dev_path_str = device_path_to_str(efidev->devpath);
if (dev_path_str) {
dev_add_param_fixed(&efidev->dev, "devpath", dev_path_str);
free(dev_path_str);
}
debug("registered efi device %s\n", dev_name(&efidev->dev));
return 0;
}
/**
* efi_register_devices - iterate over all EFI handles and register
* the devices found
*
* in barebox we treat all EFI handles which support the device_path
* protocol as devices. This function iterates over all handles and
* registers the corresponding devices. efi_register_devices is safe
* to call multiple times. Already registered devices will be ignored.
*
*/
void efi_register_devices(void)
{
unsigned long handle_count = 0;
efi_handle_t *handles = NULL;
unsigned long num_guids;
efi_guid_t **guids;
int ret, i;
struct efi_device **efidevs;
int registered;
ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles);
if (ret)
return;
efidevs = xzalloc(handle_count * sizeof(struct efi_device *));
for (i = 0; i < handle_count; i++) {
BS->protocols_per_handle(handles[i], &guids, &num_guids);
efidevs[i] = efi_add_device(handles[i], guids, num_guids);
}
/*
* We have a list of devices we want to register, but can only
* register a device when all parents are registered already.
* Do this by continiously iterating over the list until no
* further devices are registered.
*/
do {
registered = 0;
for (i = 0; i < handle_count; i++) {
if (IS_ERR(efidevs[i]))
continue;
ret = efi_register_device(efidevs[i]);
if (!ret) {
efidevs[i] = ERR_PTR(-EEXIST);
registered = 1;
}
}
} while (registered);
free(efidevs);
free(handles);
}
int efi_connect_all(void)
{
efi_status_t efiret;
unsigned long handle_count;
efi_handle_t *handle_buffer;
int i;
efiret = BS->locate_handle_buffer(all_handles, NULL, NULL, &handle_count,
&handle_buffer);
if (EFI_ERROR(efiret))
return -efi_errno(efiret);
for (i = 0; i < handle_count; i++)
efiret = BS->connect_controller(handle_buffer[i], NULL, NULL, true);
if (handle_buffer)
BS->free_pool(handle_buffer);
return 0;
}
static int efi_bus_match(struct device_d *dev, struct driver_d *drv)
{
struct efi_driver *efidrv = to_efi_driver(drv);
struct efi_device *efidev = to_efi_device(dev);
int i;
for (i = 0; i < efidev->num_guids; i++) {
if (!memcmp(&efidrv->guid, &efidev->guids[i], sizeof(efi_guid_t)))
return 0;
}
return 1;
}
static int efi_bus_probe(struct device_d *dev)
{
struct efi_driver *efidrv = to_efi_driver(dev->driver);
struct efi_device *efidev = to_efi_device(dev);
return efidrv->probe(efidev);
}
static void efi_bus_remove(struct device_d *dev)
{
struct efi_driver *efidrv = to_efi_driver(dev->driver);
struct efi_device *efidev = to_efi_device(dev);
return efidrv->remove(efidev);
}
struct bus_type efi_bus = {
.name = "efi",
.match = efi_bus_match,
.probe = efi_bus_probe,
.remove = efi_bus_remove,
};
static int efi_init_devices(void)
{
bus_register(&efi_bus);
efi_register_devices();
return 0;
}
core_initcall(efi_init_devices);

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

@ -0,0 +1,105 @@
/*
* efi-image.c - barebox EFI payload support
*
* Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <sizes.h>
#include <memory.h>
#include <command.h>
#include <magicvar.h>
#include <init.h>
#include <driver.h>
#include <io.h>
#include <efi.h>
#include <malloc.h>
#include <string.h>
#include <linux/err.h>
#include <boot.h>
#include <fs.h>
#include <binfmt.h>
#include <wchar.h>
#include <mach/efi.h>
#include <mach/efi-device.h>
static int efi_execute_image(const char *file)
{
void *exe;
size_t size;
efi_handle_t handle;
efi_status_t efiret;
const char *options;
efi_loaded_image_t *loaded_image;
exe = read_file(file, &size);
if (!exe)
return -EINVAL;
efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe, size,
&handle);
if (EFI_ERROR(efiret)) {
pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
return -efi_errno(efiret);;
};
efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid,
(void **)&loaded_image,
efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(efiret))
return -efi_errno(efiret);
options = linux_bootargs_get();
loaded_image->load_options = strdup_char_to_wchar(options);
loaded_image->load_options_size = (strlen(options) + 1) * sizeof(wchar_t);
efiret = BS->start_image(handle, NULL, NULL);
efi_connect_all();
efi_register_devices();
return 0;
}
static int do_bootm_efi(struct image_data *data)
{
return efi_execute_image(data->os_file);
}
static struct image_handler efi_handle_tr = {
.name = "EFI Application",
.bootm = do_bootm_efi,
.filetype = filetype_exe,
};
static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv)
{
return efi_execute_image(file);
}
static struct binfmt_hook binfmt_efi_hook = {
.type = filetype_exe,
.hook = efi_execute,
};
static int efi_register_image_handler(void)
{
register_image_handler(&efi_handle_tr);
binfmt_register(&binfmt_efi_hook);
return 0;
}
late_initcall(efi_register_image_handler);

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

@ -0,0 +1,342 @@
/*
* efi.c - barebox EFI payload support
*
* Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <sizes.h>
#include <memory.h>
#include <clock.h>
#include <command.h>
#include <magicvar.h>
#include <init.h>
#include <driver.h>
#include <ns16550.h>
#include <io.h>
#include <efi.h>
#include <malloc.h>
#include <string.h>
#include <linux/err.h>
#include <boot.h>
#include <fs.h>
#include <binfmt.h>
#include <wchar.h>
#include <envfs.h>
#include <mach/efi.h>
#include <mach/efi-device.h>
efi_runtime_services_t *RT;
efi_boot_services_t *BS;
efi_system_table_t *efi_sys_table;
efi_handle_t efi_parent_image;
struct efi_device_path *efi_device_path;
efi_loaded_image_t *efi_loaded_image;
void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size)
{
efi_status_t efiret;
void *buf;
unsigned long size = 0;
s16 *name16 = strdup_char_to_wchar(name);
efiret = RT->get_variable(name16, vendor, NULL, &size, NULL);
if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) {
buf = ERR_PTR(-efi_errno(efiret));
goto out;
}
buf = malloc(size);
if (!buf) {
buf = ERR_PTR(-ENOMEM);
goto out;
}
efiret = RT->get_variable(name16, vendor, NULL, &size, buf);
if (EFI_ERROR(efiret)) {
free(buf);
buf = ERR_PTR(-efi_errno(efiret));
goto out;
}
if (var_size)
*var_size = size;
out:
free(name16);
return buf;
}
struct efi_boot {
u32 attributes;
u16 file_path_len;
char *description;
struct efi_device_path *path;
void *binary;
};
struct efi_boot *efi_get_boot(int num)
{
struct efi_boot *boot = xzalloc(sizeof(*boot));
void *buf, *ptr;
int size;
char *name;
name = asprintf("Boot%04X", num);
buf = efi_get_global_var(name, &size);
free(name);
if (!buf) {
free(boot);
return NULL;
}
ptr = buf;
boot->attributes = *(u32 *)ptr;
ptr += sizeof(u32);
boot->file_path_len = *(u16 *)ptr;
ptr += sizeof(u16);
boot->description = strdup_wchar_to_char(ptr);
ptr += (strlen(boot->description) + 1) * 2;
printf("description: %s\n", boot->description);
boot->path = memdup(ptr, boot->file_path_len);
printf("path: %s\n", device_path_to_str(boot->path));
return boot;
}
static int misc_init(void)
{
efi_get_boot(1);
efi_get_boot(2);
efi_get_boot(3);
return 0;
}
late_initcall(misc_init);
const char *efi_strerror(efi_status_t err)
{
const char *str;
switch (err) {
case EFI_SUCCESS: str = "Success"; break;
case EFI_LOAD_ERROR: str = "Load Error"; break;
case EFI_INVALID_PARAMETER: str = "Invalid Parameter"; break;
case EFI_UNSUPPORTED: str = "Unsupported"; break;
case EFI_BAD_BUFFER_SIZE: str = "Bad Buffer Size"; break;
case EFI_BUFFER_TOO_SMALL: str = "Buffer Too Small"; break;
case EFI_NOT_READY: str = "Not Ready"; break;
case EFI_DEVICE_ERROR: str = "Device Error"; break;
case EFI_WRITE_PROTECTED: str = "Write Protected"; break;
case EFI_OUT_OF_RESOURCES: str = "Out of Resources"; break;
case EFI_VOLUME_CORRUPTED: str = "Volume Corrupt"; break;
case EFI_VOLUME_FULL: str = "Volume Full"; break;
case EFI_NO_MEDIA: str = "No Media"; break;
case EFI_MEDIA_CHANGED: str = "Media changed"; break;
case EFI_NOT_FOUND: str = "Not Found"; break;
case EFI_ACCESS_DENIED: str = "Access Denied"; break;
case EFI_NO_RESPONSE: str = "No Response"; break;
case EFI_NO_MAPPING: str = "No mapping"; break;
case EFI_TIMEOUT: str = "Time out"; break;
case EFI_NOT_STARTED: str = "Not started"; break;
case EFI_ALREADY_STARTED: str = "Already started"; break;
case EFI_ABORTED: str = "Aborted"; break;
case EFI_ICMP_ERROR: str = "ICMP Error"; break;
case EFI_TFTP_ERROR: str = "TFTP Error"; break;
case EFI_PROTOCOL_ERROR: str = "Protocol Error"; break;
case EFI_INCOMPATIBLE_VERSION: str = "Incompatible Version"; break;
case EFI_SECURITY_VIOLATION: str = "Security Violation"; break;
case EFI_CRC_ERROR: str = "CRC Error"; break;
case EFI_END_OF_MEDIA: str = "End of Media"; break;
case EFI_END_OF_FILE: str = "End of File"; break;
case EFI_INVALID_LANGUAGE: str = "Invalid Language"; break;
case EFI_COMPROMISED_DATA: str = "Compromised Data"; break;
default: str = "unknown error";
}
return str;
}
int efi_errno(efi_status_t err)
{
int ret;
switch (err) {
case EFI_SUCCESS: ret = 0; break;
case EFI_LOAD_ERROR: ret = EIO; break;
case EFI_INVALID_PARAMETER: ret = EINVAL; break;
case EFI_UNSUPPORTED: ret = ENOTSUPP; break;
case EFI_BAD_BUFFER_SIZE: ret = EINVAL; break;
case EFI_BUFFER_TOO_SMALL: ret = EINVAL; break;
case EFI_NOT_READY: ret = EAGAIN; break;
case EFI_DEVICE_ERROR: ret = EIO; break;
case EFI_WRITE_PROTECTED: ret = EROFS; break;
case EFI_OUT_OF_RESOURCES: ret = ENOMEM; break;
case EFI_VOLUME_CORRUPTED: ret = EIO; break;
case EFI_VOLUME_FULL: ret = ENOSPC; break;
case EFI_NO_MEDIA: ret = ENOMEDIUM; break;
case EFI_MEDIA_CHANGED: ret = ENOMEDIUM; break;
case EFI_NOT_FOUND: ret = ENODEV; break;
case EFI_ACCESS_DENIED: ret = EACCES; break;
case EFI_NO_RESPONSE: ret = ETIMEDOUT; break;
case EFI_NO_MAPPING: ret = EINVAL; break;
case EFI_TIMEOUT: ret = ETIMEDOUT; break;
case EFI_NOT_STARTED: ret = EINVAL; break;
case EFI_ALREADY_STARTED: ret = EINVAL; break;
case EFI_ABORTED: ret = EINTR; break;
case EFI_ICMP_ERROR: ret = EINVAL; break;
case EFI_TFTP_ERROR: ret = EINVAL; break;
case EFI_PROTOCOL_ERROR: ret = EPROTO; break;
case EFI_INCOMPATIBLE_VERSION: ret = EINVAL; break;
case EFI_SECURITY_VIOLATION: ret = EINVAL; break;
case EFI_CRC_ERROR: ret = EINVAL; break;
case EFI_END_OF_MEDIA: ret = EINVAL; break;
case EFI_END_OF_FILE: ret = EINVAL; break;
case EFI_INVALID_LANGUAGE: ret = EINVAL; break;
case EFI_COMPROMISED_DATA: ret = EINVAL; break;
default: ret = EINVAL;
}
return ret;
}
static struct NS16550_plat ns16550_plat = {
.clock = 115200 * 16,
};
static int efi_console_init(void)
{
add_generic_device("efi-stdio", DEVICE_ID_SINGLE, NULL, 0 , 0, 0, NULL);
if (IS_ENABLED(CONFIG_ARCH_EFI_REGISTER_COM1))
add_ns16550_device(0, 0x3f8, 0x10, IORESOURCE_IO | IORESOURCE_MEM_8BIT,
&ns16550_plat);
return 0;
}
console_initcall(efi_console_init);
void reset_cpu(unsigned long addr)
{
BS->exit(efi_parent_image, EFI_SUCCESS, 0, NULL);
while(1);
}
extern char image_base[];
extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
__barebox_initcalls_end[];
/*
* We have a position independent binary generated with -fpic. This function
* fixes the linker generated tables.
*/
static void fixup_tables(void)
{
initcall_t *initcall;
unsigned long offset = (unsigned long)image_base;
struct command *cmdtp;
struct magicvar *m;
for (initcall = __barebox_initcalls_start;
initcall < __barebox_initcalls_end; initcall++)
*initcall += offset;
for (cmdtp = &__barebox_cmd_start;
cmdtp != &__barebox_cmd_end;
cmdtp++) {
cmdtp->name += offset;
cmdtp->cmd += offset;
if (cmdtp->complete)
cmdtp->complete += offset;
if (cmdtp->desc)
cmdtp->desc += offset;
if (cmdtp->help)
cmdtp->help += offset;
if (cmdtp->opts)
cmdtp->opts += offset;
if (cmdtp->aliases)
cmdtp->aliases = (void *)cmdtp->aliases + offset;
}
for (m = &__barebox_magicvar_start;
m != &__barebox_magicvar_end;
m++) {
m->name += offset;
m->description += offset;
}
}
static int efi_init(void)
{
barebox_set_model("barebox EFI payload");
defaultenv_append_directory(env_efi);
return 0;
}
device_initcall(efi_init);
/**
* efi-main - Entry point for EFI images
*/
efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table)
{
void *mem;
efi_status_t efiret;
#ifdef DEBUG
sys_table->con_out->output_string(sys_table->con_out, L"barebox\n");
#endif
BS = sys_table->boottime;
efi_parent_image = image;
efi_sys_table = sys_table;
RT = sys_table->runtime;
efiret = BS->open_protocol(efi_parent_image, &efi_loaded_image_protocol_guid,
(void **)&efi_loaded_image,
efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (!EFI_ERROR(efiret))
BS->handle_protocol(efi_loaded_image->device_handle,
&efi_device_path_protocol_guid, (void **)&efi_device_path);
fixup_tables();
BS->allocate_pool(efi_loaded_image->image_data_type, SZ_16M, &mem);
mem_malloc_init(mem, mem + SZ_16M);
efi_clocksource_init();
start_barebox();
return EFI_SUCCESS;
}

View File

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

View File

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

View File

@ -0,0 +1,15 @@
#ifndef _SANDBOX_BITOPS_H
#define _SANDBOX_BITOPS_H
/* nothing but the defaults.. */
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/ops.h>
#endif

View File

@ -0,0 +1,8 @@
#ifndef _I386_BYTEORDER_H
#define _I386_BYTEORDER_H
#include <asm/types.h>
#include <linux/byteorder/little_endian.h>
#endif /* _I386_BYTEORDER_H */

View File

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

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de>
*
* This file is released under the GPLv2
*
*/
#ifndef __ASM_DMA_H
#define __ASM_DMA_H
/* empty*/
#endif /* __ASM_DMA_H */

View File

@ -0,0 +1,60 @@
#ifndef __ASM_SANDBOX_ELF_H__
#define __ASM_SANDBOX_ELF_H__
#ifdef __i386__
typedef struct user_fxsr_struct elf_fpxregset_t;
#define R_386_NONE 0
#define R_386_32 1
#define R_386_PC32 2
#define R_386_GOT32 3
#define R_386_PLT32 4
#define R_386_COPY 5
#define R_386_GLOB_DAT 6
#define R_386_JMP_SLOT 7
#define R_386_RELATIVE 8
#define R_386_GOTOFF 9
#define R_386_GOTPC 10
#define R_386_NUM 11
/*
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_386
#else
/* x86-64 relocation types */
#define R_X86_64_NONE 0 /* No reloc */
#define R_X86_64_64 1 /* Direct 64 bit */
#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
#define R_X86_64_PLT32 4 /* 32 bit PLT address */
#define R_X86_64_COPY 5 /* Copy symbol at runtime */
#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
#define R_X86_64_RELATIVE 8 /* Adjust by program base */
#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative
offset to GOT */
#define R_X86_64_32 10 /* Direct 32 bit zero extended */
#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
#define R_X86_64_16 12 /* Direct 16 bit zero extended */
#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
#define R_X86_64_8 14 /* Direct 8 bit sign extended */
#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
#define R_X86_64_NUM 16
/*
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS64
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_X86_64
#endif
#endif /* __ASM_SANDBOX_ELF_H__ */

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

@ -0,0 +1,55 @@
#ifndef __ASM_SANDBOX_IO_H
#define __ASM_SANDBOX_IO_H
#define build_mmio_read(name, size, type, reg, barrier) \
static inline type name(const volatile void *addr) \
{ type ret; asm volatile("mov" size " %1,%0":reg (ret) \
:"m" (*(volatile type*)addr) barrier); return ret; }
build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
#define build_mmio_write(name, size, type, reg, barrier) \
static inline void name(type val, volatile void *addr) \
{ asm volatile("mov" size " %0,%1": :reg (val), \
"m" (*(volatile type*)addr) barrier); }
build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
build_mmio_write(writew, "w", unsigned short, "r", :"memory")
build_mmio_write(writel, "l", unsigned int, "r", :"memory")
#define BUILDIO(bwl, bw, type) \
static inline void out##bwl(unsigned type value, int port) \
{ \
asm volatile("out" #bwl " %" #bw "0, %w1" \
: : "a"(value), "Nd"(port)); \
} \
\
static inline unsigned type in##bwl(int port) \
{ \
unsigned type value; \
asm volatile("in" #bwl " %w1, %" #bw "0" \
: "=a"(value) : "Nd"(port)); \
return value; \
} \
\
static inline void outs##bwl(int port, const void *addr, unsigned long count) \
{ \
asm volatile("rep; outs" #bwl \
: "+S"(addr), "+c"(count) : "d"(port)); \
} \
\
static inline void ins##bwl(int port, void *addr, unsigned long count) \
{ \
asm volatile("rep; ins" #bwl \
: "+D"(addr), "+c"(count) : "d"(port)); \
}
BUILDIO(b, b, char)
BUILDIO(w, w, short)
BUILDIO(l, , int)
#define IO_SPACE_LIMIT 0xffff
#endif /* __ASM_SANDBOX_IO_H */

View File

@ -0,0 +1,93 @@
#ifndef __ARCH_I386_POSIX_TYPES_H
#define __ARCH_I386_POSIX_TYPES_H
/*
* This file is generally used by user-level software, so you need to
* be a little careful about namespace pollution etc. Also, we cannot
* assume GCC is being used.
*/
typedef unsigned long __kernel_ino_t;
typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_nlink_t;
typedef long __kernel_off_t;
typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
/*
* Most 32 bit architectures use "unsigned int" size_t,
* and all 64 bit architectures use "unsigned long" size_t.
*
* TODO: It's not clean to use __x86_64__ here. It's better
* to check on __BITS_PER_LONG here. But this is wrong set in
* arch/sandbox/include/asm/types.h.
*/
#ifdef __x86_64__
typedef unsigned long __kernel_size_t;
typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
#else
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
#endif
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t;
typedef int __kernel_daddr_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
#ifdef __GNUC__
typedef long long __kernel_loff_t;
#endif
typedef struct {
#if defined(__KERNEL__) || defined(__USE_ALL)
int val[2];
#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
int __val[2];
#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
} __kernel_fsid_t;
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#undef __FD_SET
#define __FD_SET(fd,fdsetp) \
__asm__ __volatile__("btsl %1,%0": \
"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
#undef __FD_CLR
#define __FD_CLR(fd,fdsetp) \
__asm__ __volatile__("btrl %1,%0": \
"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
#undef __FD_ISSET
#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
unsigned char __result; \
__asm__ __volatile__("btl %1,%2 ; setb %0" \
:"=q" (__result) :"r" ((int) (fd)), \
"m" (*(__kernel_fd_set *) (fdsetp))); \
__result; }))
#undef __FD_ZERO
#define __FD_ZERO(fdsetp) \
do { \
int __d0, __d1; \
__asm__ __volatile__("cld ; rep ; stosl" \
:"=m" (*(__kernel_fd_set *) (fdsetp)), \
"=&c" (__d0), "=&D" (__d1) \
:"a" (0), "1" (__FDSET_LONGS), \
"2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
} while (0)
#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
#endif

View File

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

View File

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

View File

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

View File

@ -0,0 +1,73 @@
#ifndef __ASM_I386_TYPES_H
#define __ASM_I386_TYPES_H
#ifndef __ASSEMBLY__
#ifdef __x86_64__
/*
* This is used in dlmalloc. On X86_64 we need it to be
* 64 bit
*/
#define INTERNAL_SIZE_T unsigned long
/*
* This is a Kconfig variable in the Kernel, but we want to detect
* this during compile time, so we set it here.
*/
#define CONFIG_PHYS_ADDR_T_64BIT
#endif
typedef unsigned short umode_t;
/*
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
* header files exported to user space
*/
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/*
* These aren't exported outside the kernel to avoid name space clashes
*/
#ifdef __KERNEL__
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
#ifdef __x86_64__
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
#endif /* __KERNEL__ */
#endif
#endif

View File

@ -0,0 +1,19 @@
#ifndef _ASM_SANDBOX_UNALIGNED_H
#define _ASM_SANDBOX_UNALIGNED_H
/*
* The architecture sandbox is compiled on can do unaligned accesses itself.
*/
#include <linux/unaligned/access_ok.h>
#include <linux/unaligned/generic.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define get_unaligned __get_unaligned_le
#define put_unaligned __put_unaligned_le
#else
#define get_unaligned __get_unaligned_be
#define put_unaligned __put_unaligned_be
#endif
#endif /* _ASM_SANDBOX_UNALIGNED_H */

View File

@ -0,0 +1,20 @@
#ifndef __MACH_DEBUG_LL_H__
#define __MACH_DEBUG_LL_H__
#define EFI_DEBUG 0
#define EFI_DEBUG_CLEAR_MEMORY 0
#include <efi.h>
#include <mach/efi.h>
static inline void PUTC_LL(char c)
{
uint16_t str[2] = {};
struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out;
str[0] = c;
con_out->output_string(con_out, str);
}
#endif

View File

@ -0,0 +1,45 @@
#ifndef __MACH_EFI_DEVICE_H
#define __MACH_EFI_DEVICE_H
struct efi_device {
struct device_d dev;
efi_guid_t *guids;
int num_guids;
efi_handle_t handle;
efi_handle_t parent_handle;
void *protocol;
struct efi_device_path *devpath;
};
struct efi_driver {
struct driver_d driver;
int (*probe)(struct efi_device *efidev);
void (*remove)(struct efi_device *efidev);
efi_guid_t guid;
};
extern struct bus_type efi_bus;
static inline struct efi_device *to_efi_device(struct device_d *dev)
{
return container_of(dev, struct efi_device, dev);
}
static inline struct efi_driver *to_efi_driver(struct driver_d *drv)
{
return container_of(drv, struct efi_driver, driver);
}
#define device_efi_driver(drv) \
register_driver_macro(device, efi, drv)
static inline int efi_driver_register(struct efi_driver *efidrv)
{
efidrv->driver.bus = &efi_bus;
return register_driver(&efidrv->driver);
}
int efi_connect_all(void);
void efi_register_devices(void);
#endif /* __MACH_EFI_DEVICE_H */

View File

@ -0,0 +1,24 @@
#ifndef __MACH_EFI_H
#define __MACH_EFI_H
#include <efi.h>
const char *efi_strerror(efi_status_t err);
extern efi_system_table_t *efi_sys_table;
extern efi_handle_t efi_parent_image;
extern struct efi_device_path *efi_device_path;
extern efi_loaded_image_t *efi_loaded_image;
int efi_errno(efi_status_t err);
int efi_clocksource_init(void);
void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size);
static inline void *efi_get_global_var(char *name, int *var_size)
{
return efi_get_variable(name, &efi_global_variable_guid, var_size);
}
#endif /* __MACH_EFI_H */

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

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

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

@ -0,0 +1,4 @@
obj-$(CONFIG_X86_64) += reloc_x86_64.o crt0-efi-x86_64.o
obj-$(CONFIG_X86_32) += reloc_ia32.o crt0-efi-ia32.o
extra-$(CONFIG_X86_32) += elf_ia32_efi.lds
extra-$(CONFIG_X86_64) += elf_x86_64_efi.lds

View File

@ -0,0 +1,76 @@
/* crt0-efi-ia32.S - x86 EFI startup code.
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
.text
.align 4
.globl _start
_start:
pushl %ebp
movl %esp,%ebp
pushl 12(%ebp) # copy "image" argument
pushl 8(%ebp) # copy "systab" argument
call 0f
0: popl %eax
movl %eax,%ebx
addl $image_base-0b,%eax # %eax = ldbase
addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC
pushl %ebx # pass _DYNAMIC as second argument
pushl %eax # pass ldbase as first argument
call _relocate
popl %ebx
popl %ebx
testl %eax,%eax
jne .exit
call efi_main # call app with "image" and "systab" argument
.exit: leave
ret
/* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */
.data
dummy: .long 0
#define IMAGE_REL_ABSOLUTE 0
.section .reloc
.long dummy /* Page RVA */
.long 10 /* Block Size (2*4+2) */
.word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */

View File

@ -0,0 +1,75 @@
/* crt0-efi-x86_64.S - x86_64 EFI startup code.
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
Copyright (C) 2005 Intel Co.
Contributed by Fenghua Yu <fenghua.yu@intel.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
.text
.align 4
.globl _start
_start:
subq $8, %rsp
pushq %rcx
pushq %rdx
0:
lea image_base(%rip), %rdi
lea _DYNAMIC(%rip), %rsi
popq %rcx
popq %rdx
pushq %rcx
pushq %rdx
call _relocate
popq %rdi
popq %rsi
call efi_main
addq $8, %rsp
.exit:
ret
/* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */
.data
dummy: .long 0
#define IMAGE_REL_ABSOLUTE 0
.section .reloc, "a"
label1:
.long dummy-label1 /* Page RVA */
.long 10 /* Block Size (2*4+2) */
.word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */

View File

@ -0,0 +1,102 @@
#include <asm-generic/barebox.lds.h>
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0;
image_base = .;
.hash : { *(.hash) } /* this MUST come first! */
. = ALIGN(4096);
.text :
{
_stext = .;
_text = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
}
_etext = .;
. = ALIGN(4096);
.sdata : {
*(.got.plt)
*(.got)
*(.srodata)
*(.sdata)
*(.sbss)
*(.scommon)
}
. = ALIGN(4096);
_sdata = .;
.data : {
*(.rodata*)
*(.data)
*(.data1)
*(.data.*)
*(.sdata)
*(.got.plt)
*(.got)
/* the EFI loader doesn't seem to like a .bss section, so we stick
* it all into .data: */
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
}
. = ALIGN(64);
__barebox_initcalls_start = .;
__barebox_initcalls : { INITCALLS }
__barebox_initcalls_end = .;
. = ALIGN(64);
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
__barebox_magicvar_end = .;
. = ALIGN(64);
__barebox_cmd_start = .;
__barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rel : {
*(.rel.data)
*(.rel.data.*)
*(.rel.got)
*(.rel.stab)
*(.data.rel.ro.local)
*(.data.rel.local)
*(.data.rel.ro)
*(.data.rel*)
}
. = ALIGN(4096);
.reloc : /* This is the PECOFF .reloc section! */
{
*(.reloc)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
/DISCARD/ :
{
*(.rel.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

View File

@ -0,0 +1,93 @@
#include <asm-generic/barebox.lds.h>
/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
. = 0;
image_base = .;
.hash : { *(.hash) } /* this MUST come first! */
. = ALIGN(4096);
.eh_frame : {
*(.eh_frame)
}
. = ALIGN(4096);
.text : {
_stext = .;
_text = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
}
_etext = .;
. = ALIGN(4096);
.reloc : {
*(.reloc)
}
. = ALIGN(4096);
_sdata = .;
.data : {
*(.rodata*)
*(.got.plt)
*(.got)
*(.data*)
*(.sdata)
/* the EFI loader doesn't seem to like a .bss section, so we stick
* it all into .data: */
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
*(.rel.local)
}
. = ALIGN(64);
__barebox_initcalls_start = .;
__barebox_initcalls : { INITCALLS }
__barebox_initcalls_end = .;
. = ALIGN(64);
__barebox_magicvar_start = .;
.barebox_magicvar : { BAREBOX_MAGICVARS }
__barebox_magicvar_end = .;
. = ALIGN(64);
__barebox_cmd_start = .;
__barebox_cmd : { BAREBOX_CMDS }
__barebox_cmd_end = .;
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela : {
*(.rela.data*)
*(.rela.got)
*(.rela.stab)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.ignored.reloc : {
*(.rela.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

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

@ -0,0 +1,97 @@
/* reloc_ia32.c - position independent x86 ELF shared object relocator
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#include <common.h>
#include <efi.h>
#include <elf.h>
efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
{
long relsz = 0, relent = 0;
Elf32_Rel *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_REL:
rel = (Elf32_Rel*)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_RELSZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELENT:
relent = dyn[i].d_un.d_val;
break;
case DT_RELA:
break;
default:
break;
}
}
if (!rel && relent == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF32_R_TYPE (rel->r_info)) {
case R_386_NONE:
break;
case R_386_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf32_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,96 @@
/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
Copyright (C) 2005 Intel Co.
Contributed by Fenghua Yu <fenghua.yu@intel.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#include <common.h>
#include <efi.h>
#include <elf.h>
efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
{
long relsz = 0, relent = 0;
Elf64_Rel *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_RELA:
rel = (Elf64_Rel*)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_RELASZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELAENT:
relent = dyn[i].d_un.d_val;
break;
default:
break;
}
}
if (!rel && relent == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF64_R_TYPE (rel->r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf64_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

View File

@ -64,6 +64,14 @@ config MENUTREE
select GLOB
select GLOB_SORT
config EFI_GUID
bool
help
With this option a table of EFI guids is compiled in.
config EFI_DEVICEPATH
bool
menu "General Settings"
config LOCALVERSION

View File

@ -43,7 +43,9 @@ obj-$(CONFIG_RESET_SOURCE) += reset_source.o
obj-$(CONFIG_SHELL_HUSH) += hush.o
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
obj-$(CONFIG_UIMAGE) += image.o uimage.o
obj-$(CONFIG_MENUTREE) += menutree.o
obj-$(CONFIG_MENUTREE) += menutree.o
obj-$(CONFIG_EFI_GUID) += efi-guid.o
obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD

1370
common/efi-devicepath.c Normal file

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,11 @@
#include <common.h>
#include <efi.h>
efi_guid_t efi_file_info_id = EFI_FILE_INFO_GUID;
efi_guid_t efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_GUID;
efi_guid_t efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
efi_guid_t efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
efi_guid_t efi_unknown_device_guid = EFI_UNKNOWN_DEVICE_GUID;
efi_guid_t efi_null_guid = EFI_NULL_GUID;
efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
efi_guid_t efi_block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID;

View File

@ -58,7 +58,7 @@ void mem_malloc_init(void *start, void *end)
#endif
}
#ifndef __SANDBOX__
#if !defined __SANDBOX__ && !defined CONFIG_ARCH_EFI
static int mem_malloc_resource(void)
{
/*

View File

@ -232,7 +232,7 @@ static int is_gpt_valid(struct block_device *blk, u64 lba,
static inline int
is_pte_valid(const gpt_entry *pte, const u64 lastlba)
{
if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
if ((!efi_guidcmp(pte->partition_type_guid, EFI_NULL_GUID)) ||
le64_to_cpu(pte->starting_lba) > lastlba ||
le64_to_cpu(pte->ending_lba) > lastlba)
return 0;

View File

@ -4,7 +4,7 @@ config OFTREE
config OFTREE_MEM_GENERIC
depends on OFTREE
depends on PPC || ARM
depends on PPC || ARM || ARCH_EFI
def_bool y
config DTC

View File

@ -14,6 +14,14 @@
#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)))
@ -52,13 +60,15 @@
typedef unsigned long efi_status_t;
typedef u8 efi_bool_t;
typedef u16 efi_char16_t; /* UNICODE character */
typedef u64 efi_physical_addr_t;
typedef void *efi_handle_t;
typedef struct {
u8 b[16];
} efi_guid_t;
#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
((efi_guid_t) \
{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
(b) & 0xff, ((b) >> 8) & 0xff, \
@ -109,22 +119,7 @@ typedef struct {
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
#define EFI_PAGE_SHIFT 12
typedef struct {
u32 type;
u32 pad;
u64 phys_addr;
u64 virt_addr;
u64 num_pages;
u64 attribute;
} efi_memory_desc_t;
typedef struct {
efi_guid_t guid;
u32 headersize;
u32 flags;
u32 imagesize;
} efi_capsule_header_t;
#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
/*
* Allocation types for calls to boottime->allocate_pages.
@ -163,6 +158,19 @@ typedef struct {
u8 sets_to_zero;
} efi_time_cap_t;
enum efi_locate_search_type {
all_handles,
by_register_notify,
by_protocol
};
struct efi_open_protocol_information_entry {
efi_handle_t agent_handle;
efi_handle_t controller_handle;
u32 attributes;
u32 open_count;
};
/*
* EFI Boot Services table
*/
@ -170,41 +178,69 @@ typedef struct {
efi_table_hdr_t hdr;
void *raise_tpl;
void *restore_tpl;
void *allocate_pages;
void *free_pages;
void *get_memory_map;
void *allocate_pool;
void *free_pool;
efi_status_t (EFIAPI *allocate_pages)(int, int, unsigned long,
efi_physical_addr_t *);
efi_status_t (EFIAPI *free_pages)(efi_physical_addr_t, unsigned long);
efi_status_t (EFIAPI *get_memory_map)(unsigned long *, void *, unsigned long *,
unsigned long *, u32 *);
efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **);
efi_status_t (EFIAPI *free_pool)(void *);
void *create_event;
void *set_timer;
void *wait_for_event;
efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events, void *event,
unsigned long *index);
void *signal_event;
void *close_event;
void *check_event;
void *install_protocol_interface;
void *reinstall_protocol_interface;
void *uninstall_protocol_interface;
void *handle_protocol;
efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, efi_guid_t *, void **);
void *__reserved;
void *register_protocol_notify;
void *locate_handle;
void *locate_device_path;
efi_status_t (EFIAPI *locate_handle) (enum efi_locate_search_type search_type,
efi_guid_t *protocol, void *search_key,
unsigned long *buffer_size, efi_handle_t *buffer);
efi_status_t (EFIAPI *locate_device_path)(efi_guid_t *protocol,
struct efi_device_path **device_path, efi_handle_t *device);
void *install_configuration_table;
void *load_image;
void *start_image;
void *exit;
efi_status_t (EFIAPI *load_image)(bool boot_policiy, efi_handle_t parent_image,
struct efi_device_path *file_path, void *source_buffer,
unsigned long source_size, efi_handle_t *image);
efi_status_t (EFIAPI *start_image)(efi_handle_t handle,
unsigned long *exitdata_size, s16 **exitdata);
efi_status_t(EFIAPI *exit)(efi_handle_t handle, efi_status_t exit_status,
unsigned long exitdata_size, s16 *exitdata);
void *unload_image;
void *exit_boot_services;
efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
void *get_next_monotonic_count;
void *stall;
efi_status_t (EFIAPI *stall)(unsigned long usecs);
void *set_watchdog_timer;
void *connect_controller;
efi_status_t(EFIAPI *connect_controller)(efi_handle_t controller_handle,
efi_handle_t *driver_image_handle,
struct efi_device_path *remaining_device_path,
bool Recursive);
void *disconnect_controller;
void *open_protocol;
#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
efi_status_t (EFIAPI *open_protocol)(efi_handle_t handle, efi_guid_t *protocol,
void ** interface, efi_handle_t agent_handle,
efi_handle_t controller_handle, u32 attributes);
void *close_protocol;
void *open_protocol_information;
void *protocols_per_handle;
void *locate_handle_buffer;
efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle, efi_guid_t *Protocol,
struct efi_open_protocol_information_entry **entry_buffer,
unsigned long *entry_count);
efi_status_t (EFIAPI *protocols_per_handle)(efi_handle_t handle,
efi_guid_t ***protocol_buffer,
unsigned long *protocols_buffer_count);
efi_status_t (EFIAPI *locate_handle_buffer) (
enum efi_locate_search_type search_type,
efi_guid_t *protocol, void *search_key,
unsigned long *no_handles, efi_handle_t **buffer);
void *locate_protocol;
void *install_multiple_protocol_interfaces;
void *uninstall_multiple_protocol_interfaces;
@ -214,6 +250,8 @@ typedef struct {
void *create_event_ex;
} efi_boot_services_t;
extern efi_boot_services_t *BS;
/*
* Types and defines for EFI ResetSystem
*/
@ -229,90 +267,63 @@ typedef struct {
typedef struct {
efi_table_hdr_t hdr;
unsigned long get_time;
unsigned long set_time;
unsigned long get_wakeup_time;
unsigned long set_wakeup_time;
unsigned long set_virtual_address_map;
unsigned long convert_pointer;
unsigned long get_variable;
unsigned long get_next_variable;
unsigned long set_variable;
unsigned long get_next_high_mono_count;
unsigned long reset_system;
unsigned long update_capsule;
unsigned long query_capsule_caps;
unsigned long query_variable_info;
void *get_time;
void *set_time;
void *get_wakeup_time;
void *set_wakeup_time;
void *set_virtual_address_map;
void *convert_pointer;
efi_status_t (EFIAPI *get_variable)(s16 *variable_name, efi_guid_t *vendor,
u32 *Attributes, unsigned long *data_size, void *data);
efi_status_t (EFIAPI *get_next_variable)(unsigned long *variable_name_size,
s16 *variable_name, efi_guid_t *vendor);
void *set_variable;
void *get_next_high_mono_count;
void *reset_system;
void *update_capsule;
void *query_capsule_caps;
void *query_variable_info;
} efi_runtime_services_t;
typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
typedef efi_status_t efi_set_time_t (efi_time_t *tm);
typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
efi_time_t *tm);
typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
unsigned long *data_size, void *data);
typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
efi_guid_t *vendor);
typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor,
u32 attr, unsigned long data_size,
void *data);
typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
typedef void efi_reset_system_t (int reset_type, efi_status_t status,
unsigned long data_size, efi_char16_t *data);
typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
unsigned long descriptor_size,
u32 descriptor_version,
efi_memory_desc_t *virtual_map);
typedef efi_status_t efi_query_variable_info_t(u32 attr,
u64 *storage_space,
u64 *remaining_space,
u64 *max_variable_size);
typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules,
unsigned long count,
unsigned long sg_list);
typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
unsigned long count,
u64 *max_size,
int *reset_type);
extern efi_runtime_services_t *RT;
/*
* EFI Configuration Table and GUID definitions
*/
#define NULL_GUID \
#define EFI_NULL_GUID \
EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
#define MPS_TABLE_GUID \
#define EFI_MPS_TABLE_GUID \
EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define ACPI_TABLE_GUID \
#define EFI_ACPI_TABLE_GUID \
EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define ACPI_20_TABLE_GUID \
#define EFI_ACPI_20_TABLE_GUID \
EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
#define SMBIOS_TABLE_GUID \
#define EFI_SMBIOS_TABLE_GUID \
EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define SAL_SYSTEM_TABLE_GUID \
#define EFI_SAL_SYSTEM_TABLE_GUID \
EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define HCDP_TABLE_GUID \
#define EFI_HCDP_TABLE_GUID \
EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
#define UGA_IO_PROTOCOL_GUID \
#define EFI_UGA_IO_PROTOCOL_GUID \
EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 )
#define EFI_GLOBAL_VARIABLE_GUID \
EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c )
#define UV_SYSTEM_TABLE_GUID \
#define EFI_UV_SYSTEM_TABLE_GUID \
EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
#define LINUX_EFI_CRASH_GUID \
#define EFI_LINUX_EFI_CRASH_GUID \
EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
#define LOADED_IMAGE_PROTOCOL_GUID \
#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
@ -324,26 +335,38 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
#define EFI_PCI_IO_PROTOCOL_GUID \
EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a )
#define EFI_FILE_INFO_ID \
#define EFI_FILE_INFO_GUID \
EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
#define EFI_FILE_SYSTEM_GUID \
#define EFI_SIMPLE_FILE_SYSTEM_GUID \
EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
typedef struct {
efi_guid_t guid;
u64 table;
} efi_config_table_64_t;
#define EFI_DEVICE_TREE_GUID \
EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
typedef struct {
efi_guid_t guid;
u32 table;
} efi_config_table_32_t;
#define EFI_DEVICE_PATH_PROTOCOL_GUID \
EFI_GUID( 0x9576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
typedef struct {
efi_guid_t guid;
unsigned long table;
} efi_config_table_t;
#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \
EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D )
#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
EFI_GUID(0x0964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
#define EFI_UNKNOWN_DEVICE_GUID \
EFI_GUID(0xcf31fac5, 0xc24e, 0x11d2, 0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b)
#define EFI_BLOCK_IO_PROTOCOL_GUID \
EFI_GUID(0x964e5b21, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
extern efi_guid_t efi_file_info_id;
extern efi_guid_t efi_simple_file_system_protocol_guid;
extern efi_guid_t efi_device_path_protocol_guid;
extern efi_guid_t efi_loaded_image_protocol_guid;
extern efi_guid_t efi_unknown_device_guid;
extern efi_guid_t efi_null_guid;
extern efi_guid_t efi_global_variable_guid;
extern efi_guid_t efi_block_io_protocol_guid;
#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
@ -354,65 +377,22 @@ typedef struct {
#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;
struct efi_simple_input_interface *con_in;
unsigned long con_out_handle;
unsigned long con_out;
struct efi_simple_text_output_protocol *con_out;
unsigned long stderr_handle;
unsigned long _stderr;
unsigned long std_err;
efi_runtime_services_t *runtime;
efi_boot_services_t *boottime;
unsigned long nr_tables;
unsigned long tables;
} efi_system_table_t;
struct efi_memory_map {
void *phys_map;
void *map;
void *map_end;
int nr_map;
unsigned long desc_version;
unsigned long desc_size;
};
typedef struct {
u32 revision;
void *parent_handle;
@ -429,85 +409,12 @@ typedef struct {
unsigned long unload;
} efi_loaded_image_t;
typedef struct {
u64 revision;
void *open_volume;
} efi_file_io_interface_t;
typedef struct {
u64 size;
u64 file_size;
u64 phys_size;
efi_time_t create_time;
efi_time_t last_access_time;
efi_time_t modification_time;
__aligned_u64 attribute;
efi_char16_t filename[1];
} efi_file_info_t;
typedef struct {
u64 revision;
void *open;
void *close;
void *delete;
void *read;
void *write;
void *get_position;
void *set_position;
void *get_info;
void *set_info;
void *flush;
} efi_file_handle_t;
#define EFI_FILE_MODE_READ 0x0000000000000001
#define EFI_FILE_MODE_WRITE 0x0000000000000002
#define EFI_FILE_MODE_CREATE 0x8000000000000000
#define EFI_INVALID_TABLE_ADDR (~0UL)
/*
* All runtime access to EFI goes through this structure:
*/
extern struct efi {
efi_system_table_t *systab; /* EFI system table */
unsigned int runtime_version; /* Runtime services version */
unsigned long mps; /* MPS table */
unsigned long acpi; /* ACPI table (IA64 ext 0.71) */
unsigned long acpi20; /* ACPI table (ACPI 2.0) */
unsigned long smbios; /* SM BIOS table */
unsigned long sal_systab; /* SAL system table */
unsigned long boot_info; /* boot info table */
unsigned long hcdp; /* HCDP table */
unsigned long uga; /* UGA table */
unsigned long uv_systab; /* UV system table */
efi_get_time_t *get_time;
efi_set_time_t *set_time;
efi_get_wakeup_time_t *get_wakeup_time;
efi_set_wakeup_time_t *set_wakeup_time;
efi_get_variable_t *get_variable;
efi_get_next_variable_t *get_next_variable;
efi_set_variable_t *set_variable;
efi_query_variable_info_t *query_variable_info;
efi_update_capsule_t *update_capsule;
efi_query_capsule_caps_t *query_capsule_caps;
efi_get_next_high_mono_count_t *get_next_high_mono_count;
efi_reset_system_t *reset_system;
efi_set_virtual_address_map_t *set_virtual_address_map;
} efi;
static inline int
efi_guidcmp (efi_guid_t left, efi_guid_t right)
{
return memcmp(&left, &right, sizeof (efi_guid_t));
}
static inline char *
efi_guid_unparse(efi_guid_t *guid, char *out)
{
sprintf(out, "%pUl", guid->b);
return out;
}
/*
* Variable Attributes
*/
@ -527,48 +434,80 @@ efi_guid_unparse(efi_guid_t *guid, char *out)
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
EFI_VARIABLE_APPEND_WRITE)
/*
* The type of search to perform when calling boottime->locate_handle
* Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
* not including trailing NUL
*/
#define EFI_LOCATE_ALL_HANDLES 0
#define EFI_LOCATE_BY_REGISTER_NOTIFY 1
#define EFI_LOCATE_BY_PROTOCOL 2
#define EFI_VARIABLE_GUID_LEN 36
/*
* EFI Device Path information
*/
#define EFI_DEV_HW 0x01
#define EFI_DEV_PCI 1
#define EFI_DEV_PCCARD 2
#define EFI_DEV_MEM_MAPPED 3
#define EFI_DEV_VENDOR 4
#define EFI_DEV_CONTROLLER 5
#define EFI_DEV_ACPI 0x02
#define EFI_DEV_BASIC_ACPI 1
#define EFI_DEV_EXPANDED_ACPI 2
#define EFI_DEV_MSG 0x03
#define EFI_DEV_MSG_ATAPI 1
#define EFI_DEV_MSG_SCSI 2
#define EFI_DEV_MSG_FC 3
#define EFI_DEV_MSG_1394 4
#define EFI_DEV_MSG_USB 5
#define EFI_DEV_MSG_USB_CLASS 15
#define EFI_DEV_MSG_I20 6
#define EFI_DEV_MSG_MAC 11
#define EFI_DEV_MSG_IPV4 12
#define EFI_DEV_MSG_IPV6 13
#define EFI_DEV_MSG_INFINIBAND 9
#define EFI_DEV_MSG_UART 14
#define EFI_DEV_MSG_VENDOR 10
#define EFI_DEV_MEDIA 0x04
#define EFI_DEV_MEDIA_HARD_DRIVE 1
#define EFI_DEV_MEDIA_CDROM 2
#define EFI_DEV_MEDIA_VENDOR 3
#define EFI_DEV_MEDIA_FILE 4
#define EFI_DEV_MEDIA_PROTOCOL 5
#define EFI_DEV_BIOS_BOOT 0x05
#define EFI_DEV_END_PATH 0x7F
#define EFI_DEV_END_PATH2 0xFF
#define EFI_DEV_END_INSTANCE 0x01
#define EFI_DEV_END_ENTIRE 0xFF
struct efi_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);
#endif /* _LINUX_EFI_H */