From 76c0935726672e5d87608eddfe79f127c9a3bc45 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:09:15 +0200 Subject: Make IPaddr_t a 32bit type unsigned long is 64bit wide on some architectures. Make IPaddr_t a typedef to uint32_t to make sure it's 32bit wide. Signed-off-by: Sascha Hauer --- include/param.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/param.h b/include/param.h index 24827c5e78..8f200df847 100644 --- a/include/param.h +++ b/include/param.h @@ -7,7 +7,7 @@ #define PARAM_FLAG_RO (1 << 0) struct device_d; -typedef unsigned long IPaddr_t; +typedef uint32_t IPaddr_t; struct param_d { const char* (*get)(struct device_d *, struct param_d *param); -- cgit v1.2.3 From a0962885af0a32bd841819a7c3f1c11310bfc074 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:28:01 +0200 Subject: oftree command: Use size_t for size read_file takes a size_t argument as size, so use this type for the size variable. Signed-off-by: Sascha Hauer --- commands/oftree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/oftree.c b/commands/oftree.c index 983a0a59ea..49976bc02a 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -42,7 +42,7 @@ static int do_oftree(int argc, char *argv[]) { struct fdt_header *fdt = NULL; - int size; + size_t size; int opt; int probe = 0; char *load = NULL; -- cgit v1.2.3 From b5b926750fc26642825ab277b65a4cff521af406 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:16:34 +0200 Subject: fat: Use correct format specifier Use %zd to print size_t arguments. Signed-off-by: Sascha Hauer --- fs/fat/fat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index e65ef585a2..f8094d0608 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -167,7 +167,7 @@ static int fat_write(struct device_d *_dev, FILE *f, const void *buf, size_t ins ret = f_write(f_file, buf, insize, &outsize); - debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file); + debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file); if (ret) return ret; @@ -260,7 +260,7 @@ static int fat_read(struct device_d *_dev, FILE *f, void *buf, size_t insize) ret = f_read(f_file, buf, insize, &outsize); - debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file); + debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file); if (ret) return ret; -- cgit v1.2.3 From 084a102af3e3f54a8f8930190fc8dac7244a4157 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 8 Jul 2014 10:31:55 +0200 Subject: readkey: keys are unsigned char We have keys with values > 127, so it must be an unsigned char. Signed-off-by: Sascha Hauer --- lib/readkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/readkey.c b/lib/readkey.c index 7b38110113..2073a732f4 100644 --- a/lib/readkey.c +++ b/lib/readkey.c @@ -25,7 +25,7 @@ struct esc_cmds { const char *seq; - char val; + unsigned char val; }; static const struct esc_cmds esccmds[] = { -- cgit v1.2.3 From d9087662082965af1b2a0057724550f5b1c119ad Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 10:40:24 +0200 Subject: of: platform: Use PRINTF_CONVERSION_RESOURCE for printing resources Avoids compiler warnings about wrong format specifiers Signed-off-by: Sascha Hauer --- drivers/of/platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 72e75cc079..c417cfdcd9 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -183,7 +183,8 @@ static struct device_d *of_platform_device_create(struct device_node *np, dev->num_resources = num_reg; of_device_make_bus_id(dev); - debug("%s: register device %s, io=0x%08x\n", __func__, dev_name(dev), + debug("%s: register device %s, io=" PRINTF_CONVERSION_RESOURCE "\n", + __func__, dev_name(dev), (num_reg) ? dev->resource[0].start : (-1)); ret = platform_device_register(dev); -- cgit v1.2.3 From 241c6a017b65a88b1c23c701b32618e3ff5e8e07 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 4 Jun 2014 09:17:31 +0200 Subject: console: Add puts callback to console devices Some devices may have a much more efficient way to output strings rather than single characters. Let console devices implement a callback for this. Signed-off-by: Sascha Hauer --- common/console.c | 29 +++++++++++++++++++++++++++++ include/console.h | 1 + 2 files changed, 30 insertions(+) diff --git a/common/console.c b/common/console.c index aa9e3ce0f5..b3198356a2 100644 --- a/common/console.c +++ b/common/console.c @@ -162,6 +162,22 @@ static void console_set_stdoutpath(struct console_device *cdev) free(str); } +static int __console_puts(struct console_device *cdev, const char *s) +{ + int n = 0; + + while (*s) { + if (*s == '\n') { + cdev->putc(cdev, '\r'); + n++; + } + cdev->putc(cdev, *s); + n++; + s++; + } + return n; +} + int console_register(struct console_device *newcdev) { struct device_d *dev = &newcdev->class_dev; @@ -182,6 +198,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)) { @@ -342,9 +361,19 @@ EXPORT_SYMBOL(console_putc); int console_puts(unsigned int ch, const char *str) { + struct console_device *cdev; const char *s = str; int n = 0; + if (initialized == CONSOLE_INIT_FULL) { + for_each_console(cdev) { + if (cdev->f_active & ch) { + n = cdev->puts(cdev, str); + } + } + return n; + } + while (*s) { if (*s == '\n') { console_putc(ch, '\r'); diff --git a/include/console.h b/include/console.h index 6da0199aba..6372cfe68f 100644 --- a/include/console.h +++ b/include/console.h @@ -39,6 +39,7 @@ struct console_device { int (*tstc)(struct console_device *cdev); void (*putc)(struct console_device *cdev, char c); + int (*puts)(struct console_device *cdev, const char *s); int (*getc)(struct console_device *cdev); int (*setbrg)(struct console_device *cdev, int baudrate); void (*flush)(struct console_device *cdev); -- cgit v1.2.3 From 36d3cc49fb556cfbb15d7cf65569b14796f20246 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:14:07 +0200 Subject: Add hex_byte_pack and hex_byte_pack_upper from kernel Utility functions needed by the UUID/GUID printf support. Signed-off-by: Sascha Hauer --- include/linux/kernel.h | 23 ++++++++++++++++++++++- lib/misc.c | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 4322f01580..c5ba99fe0a 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -117,5 +117,26 @@ } \ ) -#endif /* _LINUX_KERNEL_H */ +extern const char hex_asc[]; +#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] +#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] + +static inline char *hex_byte_pack(char *buf, u8 byte) +{ + *buf++ = hex_asc_hi(byte); + *buf++ = hex_asc_lo(byte); + return buf; +} + +extern const char hex_asc_upper[]; +#define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0f)] +#define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xf0) >> 4] +static inline char *hex_byte_pack_upper(char *buf, u8 byte) +{ + *buf++ = hex_asc_upper_hi(byte); + *buf++ = hex_asc_upper_lo(byte); + return buf; +} + +#endif /* _LINUX_KERNEL_H */ diff --git a/lib/misc.c b/lib/misc.c index 0f3eb9aabb..9f2067cf36 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -113,3 +113,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"; -- cgit v1.2.3 From 9b09369a0a118282eff1b953f82de66e220ee22a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 08:57:56 +0200 Subject: vsprintf: Support pU for printing UUIDs With EFI 16byte UUIDs/GUIDs are common. Add support for printing them. This needs to be selected via Kconfig since most architectures have no use for this functionality. Signed-off-by: Sascha Hauer --- lib/Kconfig | 3 +++ lib/vsprintf.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/lib/Kconfig b/lib/Kconfig index d9ad4aa949..09a1674820 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -54,4 +54,7 @@ source lib/gui/Kconfig source lib/bootstrap/Kconfig +config PRINTF_UUID + bool + endmenu diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 066338b4e8..512c88247f 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -253,6 +253,53 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int #endif } +static noinline_for_stack +char *uuid_string(char *buf, char *end, const u8 *addr, int field_width, + int precision, int flags, const char *fmt) +{ + char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; + char *p = uuid; + int i; + static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15}; + const u8 *index = be; + bool uc = false; + + switch (*(++fmt)) { + case 'L': + uc = true; /* fall-through */ + case 'l': + index = le; + break; + case 'B': + uc = true; + break; + } + + for (i = 0; i < 16; i++) { + p = hex_byte_pack(p, addr[index[i]]); + switch (i) { + case 3: + case 5: + case 7: + case 9: + *p++ = '-'; + break; + } + } + + *p = 0; + + if (uc) { + p = uuid; + do { + *p = toupper(*p); + } while (*(++p)); + } + + return string(buf, end, uuid, field_width, precision, flags); +} + /* * Show a '%p' thing. A kernel extension is that the '%p' is followed * by an extra set of alphanumeric characters that are extended format @@ -261,6 +308,17 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int * Right now we handle: * * - 'S' For symbolic direct pointers + * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form + * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + * Options for %pU are: + * b big endian lower case hex (default) + * B big endian UPPER case hex + * l little endian lower case hex + * L little endian UPPER case hex + * big endian output byte order is: + * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] + * little endian output byte order is: + * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] * * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 * function pointers are really function descriptors, which contain a @@ -271,6 +329,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field switch (*fmt) { case 'S': return symbol_string(buf, end, ptr, field_width, precision, flags); + case 'U': + if (IS_ENABLED(CONFIG_PRINTF_UUID)) + return uuid_string(buf, end, ptr, field_width, precision, flags, fmt); + break; } flags |= SMALL; if (field_width == -1) { -- cgit v1.2.3 From 2e82822d080950d9f2cc2bfadafd31ec9809b871 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:04:50 +0200 Subject: Add beginning wchar support EFI uses 16 bit character strings. Add beginning support for this. Since barebox uses 8 bit strings internally we need conversion functions to convert between 16 bit and 8 bit strings. Signed-off-by: Sascha Hauer --- include/wchar.h | 18 +++++++++++++ lib/Makefile | 1 + lib/misc.c | 1 + lib/wchar.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 include/wchar.h create mode 100644 lib/wchar.c diff --git a/include/wchar.h b/include/wchar.h new file mode 100644 index 0000000000..80dcd81bf4 --- /dev/null +++ b/include/wchar.h @@ -0,0 +1,18 @@ +#ifndef __WCHAR_H +#define __WCHAR_H + +#include + +typedef u16 wchar_t; + +char *strcpy_wchar_to_char(char *dst, const wchar_t *src); + +wchar_t *strcpy_char_to_wchar(wchar_t *dst, const char *src); + +wchar_t *strdup_char_to_wchar(const char *src); + +char *strdup_wchar_to_char(const wchar_t *src); + +size_t wcslen(const wchar_t *s); + +#endif /* __WCHAR_H */ diff --git a/lib/Makefile b/lib/Makefile index e8769a9be2..48c953d679 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -44,3 +44,4 @@ obj-y += gui/ obj-$(CONFIG_XYMODEM) += xymodem.o obj-y += unlink-recursive.o obj-$(CONFIG_STMP_DEVICE) += stmp-device.o +obj-y += wchar.o diff --git a/lib/misc.c b/lib/misc.c index 9f2067cf36..87626c1e8b 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include /* diff --git a/lib/wchar.c b/lib/wchar.c new file mode 100644 index 0000000000..6368a01994 --- /dev/null +++ b/lib/wchar.c @@ -0,0 +1,80 @@ +/* + * wchar.c - wide character support + * + * Copyright (c) 2014 Sascha Hauer , 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 +#include +#include + +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; +} -- cgit v1.2.3 From 2d9d230089d0a5088bb3b37b01dfddc6527740a6 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:07:24 +0200 Subject: block: Add flush callback Some block devices need an explicit callback for flushing written blocks. Add this callback. Signed-off-by: Sascha Hauer --- common/block.c | 3 +++ include/block.h | 1 + 2 files changed, 4 insertions(+) diff --git a/common/block.c b/common/block.c index e522ee425a..0edc8619ef 100644 --- a/common/block.c +++ b/common/block.c @@ -55,6 +55,9 @@ static int writebuffer_flush(struct block_device *blk) } } + if (blk->ops->flush) + return blk->ops->flush(blk); + return 0; } diff --git a/include/block.h b/include/block.h index 872a4c1bba..91377679b0 100644 --- a/include/block.h +++ b/include/block.h @@ -9,6 +9,7 @@ struct block_device; struct block_device_ops { int (*read)(struct block_device *, void *buf, int block, int num_blocks); int (*write)(struct block_device *, const void *buf, int block, int num_blocks); + int (*flush)(struct block_device *); }; struct chunk; -- cgit v1.2.3 From 17d1f9288cb6cc1804414c427dac97897fb19b80 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:19:24 +0200 Subject: Move efi.h to include/ With upcoming EFI payload support the efi.h file will diverge from the kernel, so move it from include/linux/ to include/ Signed-off-by: Sascha Hauer --- common/partitions/efi.h | 2 +- include/efi.h | 547 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 547 ------------------------------------------------ 3 files changed, 548 insertions(+), 548 deletions(-) create mode 100644 include/efi.h delete mode 100644 include/linux/efi.h diff --git a/common/partitions/efi.h b/common/partitions/efi.h index 703ecca2f2..a9b10c1266 100644 --- a/common/partitions/efi.h +++ b/common/partitions/efi.h @@ -21,7 +21,7 @@ #ifndef FS_PART_EFI_H_INCLUDED #define FS_PART_EFI_H_INCLUDED -#include +#include #define MSDOS_MBR_SIGNATURE 0xaa55 #define EFI_PMBR_OSTYPE_EFI 0xEF diff --git a/include/efi.h b/include/efi.h new file mode 100644 index 0000000000..570eff75de --- /dev/null +++ b/include/efi.h @@ -0,0 +1,547 @@ +#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 + * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. + * David Mosberger-Tang + * Stephane Eranian + */ +#include +#include + +#define EFI_SUCCESS 0 +#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1))) +#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1))) +#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) +#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) +#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) + +typedef unsigned long efi_status_t; +typedef u8 efi_bool_t; +typedef u16 efi_char16_t; /* UNICODE character */ + + +typedef struct { + u8 b[16]; +} efi_guid_t; + +#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ +((efi_guid_t) \ +{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + +/* + * Generic EFI table header + */ +typedef struct { + u64 signature; + u32 revision; + u32 headersize; + u32 crc32; + u32 reserved; +} efi_table_hdr_t; + +/* + * Memory map descriptor: + */ + +/* Memory types: */ +#define EFI_RESERVED_TYPE 0 +#define EFI_LOADER_CODE 1 +#define EFI_LOADER_DATA 2 +#define EFI_BOOT_SERVICES_CODE 3 +#define EFI_BOOT_SERVICES_DATA 4 +#define EFI_RUNTIME_SERVICES_CODE 5 +#define EFI_RUNTIME_SERVICES_DATA 6 +#define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNUSABLE_MEMORY 8 +#define EFI_ACPI_RECLAIM_MEMORY 9 +#define EFI_ACPI_MEMORY_NVS 10 +#define EFI_MEMORY_MAPPED_IO 11 +#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 +#define EFI_PAL_CODE 13 +#define EFI_MAX_MEMORY_TYPE 14 + +/* Attribute values: */ +#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ +#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ +#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ +#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ +#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ +#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ +#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 + +#define EFI_PAGE_SHIFT 12 + +typedef struct { + u32 type; + u32 pad; + u64 phys_addr; + u64 virt_addr; + u64 num_pages; + u64 attribute; +} efi_memory_desc_t; + +typedef struct { + efi_guid_t guid; + u32 headersize; + u32 flags; + u32 imagesize; +} efi_capsule_header_t; + +/* + * Allocation types for calls to boottime->allocate_pages. + */ +#define EFI_ALLOCATE_ANY_PAGES 0 +#define EFI_ALLOCATE_MAX_ADDRESS 1 +#define EFI_ALLOCATE_ADDRESS 2 +#define EFI_MAX_ALLOCATE_TYPE 3 + +typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); + +/* + * Types and defines for Time Services + */ +#define EFI_TIME_ADJUST_DAYLIGHT 0x1 +#define EFI_TIME_IN_DAYLIGHT 0x2 +#define EFI_UNSPECIFIED_TIMEZONE 0x07ff + +typedef struct { + u16 year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; + u8 pad1; + u32 nanosecond; + s16 timezone; + u8 daylight; + u8 pad2; +} efi_time_t; + +typedef struct { + u32 resolution; + u32 accuracy; + u8 sets_to_zero; +} efi_time_cap_t; + +/* + * EFI Boot Services table + */ +typedef struct { + efi_table_hdr_t hdr; + void *raise_tpl; + void *restore_tpl; + void *allocate_pages; + void *free_pages; + void *get_memory_map; + void *allocate_pool; + void *free_pool; + void *create_event; + void *set_timer; + void *wait_for_event; + void *signal_event; + void *close_event; + void *check_event; + void *install_protocol_interface; + void *reinstall_protocol_interface; + void *uninstall_protocol_interface; + void *handle_protocol; + void *__reserved; + void *register_protocol_notify; + void *locate_handle; + void *locate_device_path; + void *install_configuration_table; + void *load_image; + void *start_image; + void *exit; + void *unload_image; + void *exit_boot_services; + void *get_next_monotonic_count; + void *stall; + void *set_watchdog_timer; + void *connect_controller; + void *disconnect_controller; + void *open_protocol; + void *close_protocol; + void *open_protocol_information; + void *protocols_per_handle; + void *locate_handle_buffer; + void *locate_protocol; + void *install_multiple_protocol_interfaces; + void *uninstall_multiple_protocol_interfaces; + void *calculate_crc32; + void *copy_mem; + void *set_mem; + void *create_event_ex; +} efi_boot_services_t; + +/* + * Types and defines for EFI ResetSystem + */ +#define EFI_RESET_COLD 0 +#define EFI_RESET_WARM 1 +#define EFI_RESET_SHUTDOWN 2 + +/* + * EFI Runtime Services table + */ +#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL) +#define EFI_RUNTIME_SERVICES_REVISION 0x00010000 + +typedef struct { + efi_table_hdr_t hdr; + unsigned long get_time; + unsigned long set_time; + unsigned long get_wakeup_time; + unsigned long set_wakeup_time; + unsigned long set_virtual_address_map; + unsigned long convert_pointer; + unsigned long get_variable; + unsigned long get_next_variable; + unsigned long set_variable; + unsigned long get_next_high_mono_count; + unsigned long reset_system; + unsigned long update_capsule; + unsigned long query_capsule_caps; + unsigned long query_variable_info; +} efi_runtime_services_t; + +typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); +typedef efi_status_t efi_set_time_t (efi_time_t *tm); +typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending, + efi_time_t *tm); +typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm); +typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, + unsigned long *data_size, void *data); +typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name, + efi_guid_t *vendor); +typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, + u32 attr, unsigned long data_size, + void *data); +typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count); +typedef void efi_reset_system_t (int reset_type, efi_status_t status, + unsigned long data_size, efi_char16_t *data); +typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size, + unsigned long descriptor_size, + u32 descriptor_version, + efi_memory_desc_t *virtual_map); +typedef efi_status_t efi_query_variable_info_t(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size); +typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules, + unsigned long count, + unsigned long sg_list); +typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + unsigned long count, + u64 *max_size, + int *reset_type); + +/* + * EFI Configuration Table and GUID definitions + */ +#define NULL_GUID \ + EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) + +#define MPS_TABLE_GUID \ + EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define ACPI_TABLE_GUID \ + EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define ACPI_20_TABLE_GUID \ + EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 ) + +#define SMBIOS_TABLE_GUID \ + EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define SAL_SYSTEM_TABLE_GUID \ + EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define HCDP_TABLE_GUID \ + EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 ) + +#define UGA_IO_PROTOCOL_GUID \ + EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 ) + +#define EFI_GLOBAL_VARIABLE_GUID \ + EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c ) + +#define UV_SYSTEM_TABLE_GUID \ + EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 ) + +#define LINUX_EFI_CRASH_GUID \ + EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 ) + +#define LOADED_IMAGE_PROTOCOL_GUID \ + EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a ) + +#define EFI_UGA_PROTOCOL_GUID \ + EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 ) + +#define EFI_PCI_IO_PROTOCOL_GUID \ + EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a ) + +#define EFI_FILE_INFO_ID \ + EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + +#define EFI_FILE_SYSTEM_GUID \ + EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + +typedef struct { + efi_guid_t guid; + u64 table; +} efi_config_table_64_t; + +typedef struct { + efi_guid_t guid; + u32 table; +} efi_config_table_32_t; + +typedef struct { + efi_guid_t guid; + unsigned long table; +} efi_config_table_t; + +#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) + +#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) +#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) +#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) +#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00)) +#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10)) +#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02)) + +typedef struct { + efi_table_hdr_t hdr; + u64 fw_vendor; /* physical addr of CHAR16 vendor string */ + u32 fw_revision; + u32 __pad1; + u64 con_in_handle; + u64 con_in; + u64 con_out_handle; + u64 con_out; + u64 stderr_handle; + u64 _stderr; + u64 runtime; + u64 boottime; + u32 nr_tables; + u32 __pad2; + u64 tables; +} efi_system_table_64_t; + +typedef struct { + efi_table_hdr_t hdr; + u32 fw_vendor; /* physical addr of CHAR16 vendor string */ + u32 fw_revision; + u32 con_in_handle; + u32 con_in; + u32 con_out_handle; + u32 con_out; + u32 stderr_handle; + u32 _stderr; + u32 runtime; + u32 boottime; + u32 nr_tables; + u32 tables; +} efi_system_table_32_t; + +typedef struct { + efi_table_hdr_t hdr; + unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ + u32 fw_revision; + unsigned long con_in_handle; + unsigned long con_in; + unsigned long con_out_handle; + unsigned long con_out; + unsigned long stderr_handle; + unsigned long _stderr; + efi_runtime_services_t *runtime; + efi_boot_services_t *boottime; + unsigned long nr_tables; + unsigned long tables; +} efi_system_table_t; + +struct efi_memory_map { + void *phys_map; + void *map; + void *map_end; + int nr_map; + unsigned long desc_version; + unsigned long desc_size; +}; + +typedef struct { + u32 revision; + void *parent_handle; + efi_system_table_t *system_table; + void *device_handle; + void *file_path; + void *reserved; + u32 load_options_size; + void *load_options; + void *image_base; + __aligned_u64 image_size; + unsigned int image_code_type; + unsigned int image_data_type; + unsigned long unload; +} efi_loaded_image_t; + +typedef struct { + u64 revision; + void *open_volume; +} efi_file_io_interface_t; + +typedef struct { + u64 size; + u64 file_size; + u64 phys_size; + efi_time_t create_time; + efi_time_t last_access_time; + efi_time_t modification_time; + __aligned_u64 attribute; + efi_char16_t filename[1]; +} efi_file_info_t; + +typedef struct { + u64 revision; + void *open; + void *close; + void *delete; + void *read; + void *write; + void *get_position; + void *set_position; + void *get_info; + void *set_info; + void *flush; +} efi_file_handle_t; + +#define EFI_FILE_MODE_READ 0x0000000000000001 +#define EFI_FILE_MODE_WRITE 0x0000000000000002 +#define EFI_FILE_MODE_CREATE 0x8000000000000000 + +#define EFI_INVALID_TABLE_ADDR (~0UL) + +/* + * All runtime access to EFI goes through this structure: + */ +extern struct efi { + efi_system_table_t *systab; /* EFI system table */ + unsigned int runtime_version; /* Runtime services version */ + unsigned long mps; /* MPS table */ + unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ + unsigned long acpi20; /* ACPI table (ACPI 2.0) */ + unsigned long smbios; /* SM BIOS table */ + unsigned long sal_systab; /* SAL system table */ + unsigned long boot_info; /* boot info table */ + unsigned long hcdp; /* HCDP table */ + unsigned long uga; /* UGA table */ + unsigned long uv_systab; /* UV system table */ + efi_get_time_t *get_time; + efi_set_time_t *set_time; + efi_get_wakeup_time_t *get_wakeup_time; + efi_set_wakeup_time_t *set_wakeup_time; + efi_get_variable_t *get_variable; + efi_get_next_variable_t *get_next_variable; + efi_set_variable_t *set_variable; + efi_query_variable_info_t *query_variable_info; + efi_update_capsule_t *update_capsule; + efi_query_capsule_caps_t *query_capsule_caps; + efi_get_next_high_mono_count_t *get_next_high_mono_count; + efi_reset_system_t *reset_system; + efi_set_virtual_address_map_t *set_virtual_address_map; +} efi; + +static inline int +efi_guidcmp (efi_guid_t left, efi_guid_t right) +{ + return memcmp(&left, &right, sizeof (efi_guid_t)); +} + +static inline char * +efi_guid_unparse(efi_guid_t *guid, char *out) +{ + sprintf(out, "%pUl", guid->b); + return out; +} + +/* + * Variable Attributes + */ +#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008 +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020 +#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040 + +#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS | \ + EFI_VARIABLE_HARDWARE_ERROR_RECORD | \ + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_APPEND_WRITE) +/* + * The type of search to perform when calling boottime->locate_handle + */ +#define EFI_LOCATE_ALL_HANDLES 0 +#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 +#define EFI_LOCATE_BY_PROTOCOL 2 + +/* + * EFI Device Path information + */ +#define EFI_DEV_HW 0x01 +#define EFI_DEV_PCI 1 +#define EFI_DEV_PCCARD 2 +#define EFI_DEV_MEM_MAPPED 3 +#define EFI_DEV_VENDOR 4 +#define EFI_DEV_CONTROLLER 5 +#define EFI_DEV_ACPI 0x02 +#define EFI_DEV_BASIC_ACPI 1 +#define EFI_DEV_EXPANDED_ACPI 2 +#define EFI_DEV_MSG 0x03 +#define EFI_DEV_MSG_ATAPI 1 +#define EFI_DEV_MSG_SCSI 2 +#define EFI_DEV_MSG_FC 3 +#define EFI_DEV_MSG_1394 4 +#define EFI_DEV_MSG_USB 5 +#define EFI_DEV_MSG_USB_CLASS 15 +#define EFI_DEV_MSG_I20 6 +#define EFI_DEV_MSG_MAC 11 +#define EFI_DEV_MSG_IPV4 12 +#define EFI_DEV_MSG_IPV6 13 +#define EFI_DEV_MSG_INFINIBAND 9 +#define EFI_DEV_MSG_UART 14 +#define EFI_DEV_MSG_VENDOR 10 +#define EFI_DEV_MEDIA 0x04 +#define EFI_DEV_MEDIA_HARD_DRIVE 1 +#define EFI_DEV_MEDIA_CDROM 2 +#define EFI_DEV_MEDIA_VENDOR 3 +#define EFI_DEV_MEDIA_FILE 4 +#define EFI_DEV_MEDIA_PROTOCOL 5 +#define EFI_DEV_BIOS_BOOT 0x05 +#define EFI_DEV_END_PATH 0x7F +#define EFI_DEV_END_PATH2 0xFF +#define EFI_DEV_END_INSTANCE 0x01 +#define EFI_DEV_END_ENTIRE 0xFF + +#endif /* _LINUX_EFI_H */ diff --git a/include/linux/efi.h b/include/linux/efi.h deleted file mode 100644 index 570eff75de..0000000000 --- a/include/linux/efi.h +++ /dev/null @@ -1,547 +0,0 @@ -#ifndef _LINUX_EFI_H -#define _LINUX_EFI_H - -/* - * Extensible Firmware Interface - * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999 - * - * Copyright (C) 1999 VA Linux Systems - * Copyright (C) 1999 Walt Drummond - * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. - * David Mosberger-Tang - * Stephane Eranian - */ -#include -#include - -#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 */ -- cgit v1.2.3 From ccf2963541be1ef291c13e6c0667058dd6c165ed Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:39:45 +0200 Subject: serial: ns16550: Add mmiobase to private data We have a private data struct, so use it for storing the base address instead of abusing the dev->priv field. Signed-off-by: Sascha Hauer --- drivers/serial/serial_ns16550.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index 709f704cb4..27fae9b46e 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -50,6 +50,7 @@ struct ns16550_priv { int mmio; struct clk *clk; uint32_t fcrval; + void __iomem *mmiobase; }; static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev) @@ -157,7 +158,6 @@ 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; @@ -165,11 +165,11 @@ static uint32_t ns16550_read(struct console_device *cdev, uint32_t off) switch (width) { case IORESOURCE_MEM_8BIT: - return ns16550_sys_readb(dev->priv + off, priv->mmio); + return ns16550_sys_readb(priv->mmiobase + off, priv->mmio); case IORESOURCE_MEM_16BIT: - return ns16550_sys_readw(dev->priv + off, priv->mmio); + return ns16550_sys_readw(priv->mmiobase + off, priv->mmio); case IORESOURCE_MEM_32BIT: - return ns16550_sys_readl(dev->priv + off, priv->mmio); + return ns16550_sys_readl(priv->mmiobase + off, priv->mmio); } return -1; } @@ -185,7 +185,6 @@ 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; @@ -193,13 +192,13 @@ static void ns16550_write(struct console_device *cdev, uint32_t val, switch (width) { case IORESOURCE_MEM_8BIT: - ns16550_sys_writeb(val & 0xff, dev->priv + off, priv->mmio); + ns16550_sys_writeb(val & 0xff, priv->mmiobase + off, priv->mmio); break; case IORESOURCE_MEM_16BIT: - ns16550_sys_writew(val & 0xffff, dev->priv + off, priv->mmio); + ns16550_sys_writew(val & 0xffff, priv->mmiobase + off, priv->mmio); break; case IORESOURCE_MEM_32BIT: - ns16550_sys_writel(val, dev->priv + off, priv->mmio); + ns16550_sys_writel(val, priv->mmiobase + off, priv->mmio); break; } } @@ -395,7 +394,7 @@ static int ns16550_probe(struct device_d *dev) } if (!res) goto err; - dev->priv = (void __force __iomem *) res->start; + priv->mmiobase = (void __force __iomem *) res->start; if (plat) -- cgit v1.2.3 From 0ed7bda1bc9f71e53c4385fdea89cbae4a0eaae6 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 10:17:03 +0200 Subject: serial: ns16550: Add register read/write function pointers to private data Makes the code a bit cleaner. This also avoids casting from a pointer to a 32bit integer which may produce compiler warnings. Signed-off-by: Sascha Hauer --- drivers/serial/serial_ns16550.c | 234 ++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 114 deletions(-) diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index 27fae9b46e..09e6a6aba8 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -46,11 +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) @@ -58,93 +64,64 @@ static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev) return container_of(cdev, struct ns16550_priv, cdev); } -struct ns16550_drvdata { - void (*init_port)(struct console_device *cdev); - const char *linux_console_name; -}; +static uint8_t ns16550_read_reg_mmio_8(struct ns16550_priv *priv, unsigned offset) +{ + return readb(priv->mmiobase + offset); +} -/** - * @brief read system i/o (byte) - * @param[in] addr address to read - * @param[in] mmio memory i/o space or i/o port space - */ -static inline uint8_t ns16550_sys_readb(void __iomem *addr, int mmio) +static void ns16550_write_reg_mmio_8(struct ns16550_priv *priv, uint8_t val, unsigned offset) { - if (mmio) - return readb(addr); - else - return (uint8_t) inb((int) addr); + writeb(val, priv->mmiobase + offset); } -/** - * @brief read system i/o (word) - * @param[in] addr address to read - * @param[in] mmio memory i/o space or i/o port space - */ -static inline uint16_t ns16550_sys_readw(void __iomem *addr, int mmio) +static uint8_t ns16550_read_reg_mmio_16(struct ns16550_priv *priv, unsigned offset) { - if (mmio) - return readw(addr); - else - return (uint16_t) inw((int) addr); + return readw(priv->mmiobase + offset); } -/** - * @brief read system i/o (dword) - * @param[in] addr address to read - * @param[in] mmio memory i/o space or i/o port space - */ -static inline uint32_t ns16550_sys_readl(void __iomem *addr, int mmio) +static void ns16550_write_reg_mmio_16(struct ns16550_priv *priv, uint8_t val, unsigned offset) { - if (mmio) - return readl(addr); - else - return (uint32_t) inl((int) addr); + writew(val, priv->mmiobase + offset); } -/** - * @brief write system i/o (byte) - * @param[in] val data to write - * @param[in] addr address to write to - * @param[in] mmio memory i/o space or i/o port space - */ -static inline void ns16550_sys_writeb(uint8_t val, void __iomem *addr, - int mmio) +static uint8_t ns16550_read_reg_mmio_32(struct ns16550_priv *priv, unsigned offset) { - if (mmio) - writeb(val, addr); - else - outb(val, (int) addr); + return readl(priv->mmiobase + offset); } -/** - * @brief read system i/o (word) - * @param[in] val data to write - * @param[in] addr address to write to - * @param[in] mmio memory i/o space or i/o port space - */ -static inline void ns16550_sys_writew(uint16_t val, void __iomem *addr, - int mmio) +static void ns16550_write_reg_mmio_32(struct ns16550_priv *priv, uint8_t val, unsigned offset) { - if (mmio) - writew(val, addr); - else - outw(val, (int) addr); + writel(val, priv->mmiobase + offset); } -/** - * @brief read system i/o (dword) - * @param[in] val data to write - * @param[in] addr address to write to - * @param[in] mmio memory i/o space or i/o port space - */ -static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr, - int mmio) +static uint8_t ns16550_read_reg_ioport_8(struct ns16550_priv *priv, unsigned offset) { - if (mmio) - writel(val, addr); - else - outl(val, (int) addr); + return inb(priv->iobase + offset); +} + +static void ns16550_write_reg_ioport_8(struct ns16550_priv *priv, uint8_t val, unsigned offset) +{ + outb(val, priv->iobase + offset); +} + +static uint8_t ns16550_read_reg_ioport_16(struct ns16550_priv *priv, unsigned offset) +{ + return inw(priv->iobase + offset); +} + +static void ns16550_write_reg_ioport_16(struct ns16550_priv *priv, uint8_t val, unsigned offset) +{ + outw(val, priv->iobase + offset); +} + +static uint8_t ns16550_read_reg_ioport_32(struct ns16550_priv *priv, unsigned offset) +{ + return inl(priv->iobase + offset); +} + +static void ns16550_write_reg_ioport_32(struct ns16550_priv *priv, uint8_t val, unsigned offset) +{ + outl(val, priv->iobase + offset); } /** @@ -159,19 +136,8 @@ static uint32_t ns16550_read(struct console_device *cdev, uint32_t off) { struct ns16550_priv *priv = to_ns16550_priv(cdev); struct NS16550_plat *plat = &priv->plat; - int width = priv->access_width; - - off <<= plat->shift; - switch (width) { - case IORESOURCE_MEM_8BIT: - return ns16550_sys_readb(priv->mmiobase + off, priv->mmio); - case IORESOURCE_MEM_16BIT: - return ns16550_sys_readw(priv->mmiobase + off, priv->mmio); - case IORESOURCE_MEM_32BIT: - return ns16550_sys_readl(priv->mmiobase + off, priv->mmio); - } - return -1; + return priv->read_reg(priv, off << plat->shift); } /** @@ -186,21 +152,8 @@ static void ns16550_write(struct console_device *cdev, uint32_t val, { struct ns16550_priv *priv = to_ns16550_priv(cdev); 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, priv->mmiobase + off, priv->mmio); - break; - case IORESOURCE_MEM_16BIT: - ns16550_sys_writew(val & 0xffff, priv->mmiobase + off, priv->mmio); - break; - case IORESOURCE_MEM_32BIT: - ns16550_sys_writel(val, priv->mmiobase + off, priv->mmio); - break; - } + priv->write_reg(priv, val, off << plat->shift); } /** @@ -358,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 * @@ -373,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); @@ -382,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; - priv->mmiobase = (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; @@ -423,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; -- cgit v1.2.3 From 66f1030e11970c5e201c9ef95ad9a5228f255bb7 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:26:17 +0200 Subject: filetype: Add DOS EXE file detection support Signed-off-by: Sascha Hauer --- common/filetype.c | 4 ++++ include/filetype.h | 1 + 2 files changed, 5 insertions(+) diff --git a/common/filetype.c b/common/filetype.c index a04fbdd541..5d6a5443f0 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -56,6 +56,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) @@ -236,6 +237,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize) if (bufsize < 64) return filetype_unknown; + if (buf8[0] == 'M' && buf8[1] == 'Z') + return filetype_exe; + if (is_barebox_arm_head(_buf)) return filetype_arm_barebox; if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01) diff --git a/include/filetype.h b/include/filetype.h index fc3140c929..eedf4b4afe 100644 --- a/include/filetype.h +++ b/include/filetype.h @@ -32,6 +32,7 @@ enum filetype { filetype_barebox_env, filetype_ch_image, filetype_ch_image_be, + filetype_exe, filetype_max, }; -- cgit v1.2.3 From 7e2de7dc67e170955061950993559c2486b7210a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Jul 2014 09:30:23 +0200 Subject: efi: Add more error codes Signed-off-by: Sascha Hauer --- include/efi.h | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/include/efi.h b/include/efi.h index 570eff75de..9911fa1e8c 100644 --- a/include/efi.h +++ b/include/efi.h @@ -14,13 +14,40 @@ #include #include -#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))) +#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; -- cgit v1.2.3 From 3475ba2a1da1358697297a3cf9337eed10b69695 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 7 Jul 2014 17:59:04 +0200 Subject: Documentation: Add EFI documentation This adds documentation for the upcoming barebox on EFI support. Signed-off-by: Sascha Hauer --- Documentation/boards/efi.rst | 298 +++++++++++++++++++++++++++++++++++++++++++ Documentation/glossary.rst | 3 + 2 files changed, 301 insertions(+) create mode 100644 Documentation/boards/efi.rst diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst new file mode 100644 index 0000000000..2147cb63db --- /dev/null +++ b/Documentation/boards/efi.rst @@ -0,0 +1,298 @@ +barebox on (U)EFI +================= + +barebox can be built as an EFI application for X86 PCs. This makes +barebox a bootloader running on PC type hardware. In EFI jargon barebox +would be a EFI shell. Due to the barebox :ref:`bootloader_spec` support +it can act as a replacement for gummiboot. + +For accessing hardware the EFI drivers and abstractions are used. barebox +has several drivers which merely map to the underlying EFI layers. A plain +barebox binary provides access to the screen and keyboard. The EFI System +partition (:term:`ESP`) is available under ``/boot``, additional partitions may +be available as ``/efi*``. Networking may be available if the BIOS provides +the necessary drivers, but most likely you'll have to download/compile +network drivers yourself, see below. + +Depending on the ``CONFIG_64BIT`` option either a ia32 binary or a x86_64 +binary is built. Due to the lack of 32bit UEFI testing hardware only the +x86_64 binary currently is tested. + +Building barebox for EFI +------------------------ + +Use the following to build barebox for EFI: + +.. code-block:: sh + + export ARCH=efi + make efi_defconfig + make + +The resulting EFI image is ``barebox.efi`` (or the barebox-flash-image link). + +Running barebox on EFI systems +------------------------------ + +The simplest way to run barebox on a USB memory stick. (U)EFI only supports +FAT filesystems, so make sure you either have a FAT16 or FAT32 filesystem on +the memory stick. Put ``barebox.efi`` into the ``EFI/BOOT/`` directory and +name it ``BOOTx64.EFI`` on 64bit architectures and ``BOOTIA32.EFI`` on 32bit +architectures. Switching to USB boot in the BIOS should then be enough to +start barebox via USB. Some BIOSes allow to specify a path to a binary to +be executed, others have a "start UEFI shell" entry which executes +EFI/Shellx64.efi on the :term:`ESP`. This can be a barebox binary aswell. + +Running EFI barebox on qemu +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +barebox can be started in qemu with OVMF http://www.linux-kvm.org/page/OVMF. + +OVMF is part of several distributions and can be installed with the package +management system. qemu needs the OVMF.fd from the OVMF package file as +argument to the -pflash option. As qemu needs write access to that file it's +necessary to make a copy first. + +To start it create a USB memory stick like above and execute: + +.. code-block:: sh + + qemu-system-x86_64 -pflash OVMF.fd -nographic /dev/sdx + +A plain VFAT image will work aswell, but in this case the UEFI BIOS won't +recognize it as ESP and ``/boot`` won't be mounted. + +Loading EFI applications +------------------------ + +EFI supports loading applications aswell as drivers. barebox does not differentiate +between both. Both types can be simply executed by typing the path on the command +line. When an application/driver returns barebox iterates over the handle database +and will initialize all new devices. + +Applications +^^^^^^^^^^^^ + +barebox itself and also the Linux Kernel are EFI applications. This means both +can be directly executed. On other architectures when barebox is executed from +another barebox it means the barebox binary will be replaced. EFI behaves +differently, here different barebox instances will be nested, so exiting barebox +means passing control to the calling instance. Note that currently the :ref:`command_reset` +command will pass the control to the calling instance rather than resetting +the CPU. This may change in the future. + +Although the Linux Kernel can be directly executed one should use the :ref:`command_bootm` +command. Only the bootm command passes the Kernel commandline to the Kernel. + +Drivers +^^^^^^^ + +EFI is modular and drivers can be loaded during runtime. Many drivers are +included in the BIOS already, but some have to be loaded during runtime, +for example it's common that network drivers are not included in the BIOS. + +Drivers can be loaded under barebox simply by executing them: + +.. code-block:: sh + + barebox:/ /boot/network-drivers/0001-SnpDxe.efi + +Should the drivers instanciate new devices these are automatically registered +after the driver has been loaded. + +Simple Network Protocol (SNP) +----------------------------- + +The Simple Network Protocol provides a raw packet interface to the EFI +network drivers. Each device which supports SNP shows up as a regular +network device under barebox. To use SNP the BIOS must have the SNP +protocol and the network driver installed. For getting the SNP protocol +follow the instruction in :ref:`efi_building_edk2`. Network drivers for +the common Intel Network devices can be found here: + +https://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=19186 + +Once instantiated the EFI drivers take some time to bring up the link, so +it's best to only load the network drivers when needed. This can be +archieved with the following script to put under ``/env/network/eth0-discover``: + +.. code-block:: sh + + #!/bin/sh + + for i in /boot/network-drivers/*; do + $i; + done + +This script will load the drivers in ``/boot/network-drivers/`` in alphabetical +order. + +**NOTE** Loading the network drivers only works when loaded in the +correct order. First the SNP driver must be loaded and then the network device +driver. Otherwise the drivers will load without errors, but no devices will be +instantiated. For making the order sure the driver names can be prepended with +a number: + +.. code-block:: sh + + /boot/network-drivers/0001-SnpDxe.efi + /boot/network-drivers/0002-E6208X3.EFI + +It is currently not known whether this is a limitation in EFI or a bug in +barebox. + +EFI File IO Interface +--------------------- + +EFI itself has filesystem support. At least the :term:`ESP` will be mounted by the +EFI core already. The :term:`ESP` is mounted to ``/boot`` under barebox, other devices +are mounted to ``/efi`` 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.`` +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 -. Access to EFI variables +is currently readonly. Since the variables have binary content using :ref:`command_md` is often +more suitable than :ref:`command_cat`. + +EFI driver model and barebox +---------------------------- + +The EFI driver model is based around handles and protocols. A handle is an opaque +cookie that represents a hardware device or a software object. Each handle can have +multiple protocols attached to it. A protocol is a callable interface and is defined +by a C struct containing function pointers. A protocol is identified by a 64bit GUID. +Common examples for protocols are DEVICE_PATH, DEVICE_IO, BLOCK_IO, DISK_IO, +FILE_SYSTEM, SIMPLE_INPUT or SIMPLE_TEXT_OUTPUT. Every handle that implements the +DEVICE_PATH protocol is registered as device in barebox. The structure can be best +seen in the ``devinfo`` output of such a device: + +.. code-block:: sh + + barebox:/ devinfo handle-00000000cfaed198 + Driver: efi-snp + Bus: efi + Protocols: + 0: a19832b9-ac25-11d3-9a2d-0090273fc14d + 1: 330d4706-f2a0-4e4f-a369-b66fa8d54385 + 2: e5dd1403-d622-c24e-8488-c71b17f5e802 + 3: 34d59603-1428-4429-a414-e6b3b5fd7dc1 + 4: 0e1ad94a-dcf4-11db-9705-00e08161165f + 5: 1aced566-76ed-4218-bc81-767f1f977a89 + 6: e3161450-ad0f-11d9-9669-0800200c9a66 + 7: 09576e91-6d3f-11d2-8e39-00a0c969723b + 8: 51dd8b21-ad8d-48e9-bc3f-24f46722c748 + Parameters: + devpath: pci_root(0)/Pci(0x1c,0x3)/Pci(0x0,0x0)/Mac(e03f4914f157) + +The protocols section in the output shows the different protocols this +handle implements. One of this Protocols (here the first) is the Simple +Network Protocol GUID: + +.. code-block:: c + + #define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ + EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D ) + +Matching between EFI devices and drivers is done based on the Protocol GUIDs, so +whenever a driver GUID matches one of the GUIDs a device imeplements the drivers +probe function is called. + +.. _efi_building_edk2: + +Building EDK2 +------------- + +Additional drivers may be needed from the EDK2 package. For example to +use Networking in barebox not only the network device drivers are needed, +but also the Simple Network Protocol driver, SnpDxe.efi. This is often +not included in the BIOS, but can be compiled from the EDK2 package. + +Here is only a quick walkthrough for building edk2, there are more elaborated +HOWTOs in the net, for example on http://tianocore.sourceforge.net/wiki/Using_EDK_II_with_Native_GCC. + +.. code-block:: sh + + git clone git://github.com/tianocore/edk2.git + cd edk2 + make -C BaseTools + . edksetup.sh + +At least the following lines in ``Conf/target.txt`` should be edited:: + + ACTIVE_PLATFORM = MdeModulePkg/MdeModulePkg.dsc + TARGET_ARCH = X64 + TOOL_CHAIN_TAG = GCC48 + MAX_CONCURRENT_THREAD_NUMBER = 4 + +The actual build is started with invoking ``build``. After building +``Build/MdeModule/DEBUG_GCC48/X64/SnpDxe.efi`` should exist. + +**NOTE** As of this writing (July 2014) the following patch was needed to +compile EDK2. + +.. code-block:: diff + + diff --git a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S + index 9783ec6..13fc06c 100644 + --- a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S + +++ b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S + @@ -280,7 +280,7 @@ ExtraPushDone: + + mov %ds, %rax + pushq %rax + - movw %es, %rax + + mov %es, %rax^M + pushq %rax + mov %fs, %rax + pushq %rax + diff --git a/Documentation/glossary.rst b/Documentation/glossary.rst index 8bad7dc6e8..106dce98a9 100644 --- a/Documentation/glossary.rst +++ b/Documentation/glossary.rst @@ -16,3 +16,6 @@ Glossary PBL Pre BootLoader image + + ESP + EFI System Partition -- cgit v1.2.3 From 1dff7e414d78d5fd8ff62a57b67617aa1f73e532 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 7 Jul 2014 18:02:53 +0200 Subject: Add initial EFI architecture support This adds support for running barebox in an EFI environment on X86 PC hardware. Signed-off-by: Sascha Hauer --- .gitignore | 1 + Makefile | 3 +- arch/efi/Kconfig | 51 ++ arch/efi/Makefile | 41 + arch/efi/configs/efi_defconfig | 78 ++ arch/efi/efi/Makefile | 2 + arch/efi/efi/clocksource.c | 60 ++ arch/efi/efi/efi-block-io.c | 174 ++++ arch/efi/efi/efi-device.c | 348 +++++++ arch/efi/efi/efi-image.c | 105 +++ arch/efi/efi/efi.c | 342 +++++++ arch/efi/efi/env-efi/network/eth0-discover | 5 + arch/efi/include/asm/barebox.h | 1 + arch/efi/include/asm/bitops.h | 15 + arch/efi/include/asm/byteorder.h | 8 + arch/efi/include/asm/common.h | 4 + arch/efi/include/asm/dma.h | 13 + arch/efi/include/asm/elf.h | 60 ++ arch/efi/include/asm/io.h | 55 ++ arch/efi/include/asm/posix_types.h | 93 ++ arch/efi/include/asm/sections.h | 1 + arch/efi/include/asm/string.h | 1 + arch/efi/include/asm/swab.h | 6 + arch/efi/include/asm/types.h | 73 ++ arch/efi/include/asm/unaligned.h | 19 + arch/efi/include/mach/debug_ll.h | 20 + arch/efi/include/mach/efi-device.h | 45 + arch/efi/include/mach/efi.h | 24 + arch/efi/lib/.gitignore | 2 + arch/efi/lib/Makefile | 4 + arch/efi/lib/crt0-efi-ia32.S | 76 ++ arch/efi/lib/crt0-efi-x86_64.S | 75 ++ arch/efi/lib/elf_ia32_efi.lds.S | 102 +++ arch/efi/lib/elf_x86_64_efi.lds.S | 93 ++ arch/efi/lib/reloc_ia32.c | 97 ++ arch/efi/lib/reloc_x86_64.c | 96 ++ common/Kconfig | 8 + common/Makefile | 4 +- common/efi-devicepath.c | 1370 ++++++++++++++++++++++++++++ common/efi-guid.c | 11 + common/memory.c | 2 +- common/partitions/efi.c | 2 +- drivers/of/Kconfig | 2 +- include/efi.h | 469 +++++----- 44 files changed, 3791 insertions(+), 270 deletions(-) create mode 100644 arch/efi/Kconfig create mode 100644 arch/efi/Makefile create mode 100644 arch/efi/configs/efi_defconfig create mode 100644 arch/efi/efi/Makefile create mode 100644 arch/efi/efi/clocksource.c create mode 100644 arch/efi/efi/efi-block-io.c create mode 100644 arch/efi/efi/efi-device.c create mode 100644 arch/efi/efi/efi-image.c create mode 100644 arch/efi/efi/efi.c create mode 100644 arch/efi/efi/env-efi/network/eth0-discover create mode 100644 arch/efi/include/asm/barebox.h create mode 100644 arch/efi/include/asm/bitops.h create mode 100644 arch/efi/include/asm/byteorder.h create mode 100644 arch/efi/include/asm/common.h create mode 100644 arch/efi/include/asm/dma.h create mode 100644 arch/efi/include/asm/elf.h create mode 100644 arch/efi/include/asm/io.h create mode 100644 arch/efi/include/asm/posix_types.h create mode 100644 arch/efi/include/asm/sections.h create mode 100644 arch/efi/include/asm/string.h create mode 100644 arch/efi/include/asm/swab.h create mode 100644 arch/efi/include/asm/types.h create mode 100644 arch/efi/include/asm/unaligned.h create mode 100644 arch/efi/include/mach/debug_ll.h create mode 100644 arch/efi/include/mach/efi-device.h create mode 100644 arch/efi/include/mach/efi.h create mode 100644 arch/efi/lib/.gitignore create mode 100644 arch/efi/lib/Makefile create mode 100644 arch/efi/lib/crt0-efi-ia32.S create mode 100644 arch/efi/lib/crt0-efi-x86_64.S create mode 100644 arch/efi/lib/elf_ia32_efi.lds.S create mode 100644 arch/efi/lib/elf_x86_64_efi.lds.S create mode 100644 arch/efi/lib/reloc_ia32.c create mode 100644 arch/efi/lib/reloc_x86_64.c create mode 100644 common/efi-devicepath.c create mode 100644 common/efi-guid.c diff --git a/.gitignore b/.gitignore index 135fdeb630..19534c9a73 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ barebox.uimage barebox.map barebox.kwb barebox.kwbuart +barebox.efi barebox-flash-image System.map Module.symvers diff --git a/Makefile b/Makefile index 63139c2512..69320d8100 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/arch/efi/Kconfig b/arch/efi/Kconfig new file mode 100644 index 0000000000..71ac1c74e8 --- /dev/null +++ b/arch/efi/Kconfig @@ -0,0 +1,51 @@ +config ARCH_EFI + bool + default y + select HAS_DEBUG_LL + select HAS_KALLSYMS + select HAVE_DEFAULT_ENVIRONMENT_NEW + select EFI_GUID + select EFI_DEVICEPATH + select PRINTF_UUID + +config ARCH_TEXT_BASE + hex + default 0x0 + +menu "EFI specific settings" + +config 64BIT + def_bool y + help + Say yes to build a 64-bit binary - formerly known as x86_64 + Say no to build a 32-bit binary - formerly known as i386. + + 32-bit support currently does not compile and is not tested + due to the lack of hardware. + +config X86_32 + def_bool y + depends on !64BIT + +config X86_64 + def_bool y + depends on 64BIT + +config ARCH_EFI_REGISTER_COM1 + bool "Register first serial port" + help + Say yes here to register the first serial port on ioport 0x3f8. + This is useful to control barebox over a serial port if the board + has one. Enabling this option may not work on boards which do not + have a serial port. Also enable DRIVER_SERIAL_NS16550 to enable + the NS16550 driver. + +endmenu + +source common/Kconfig +source commands/Kconfig +source net/Kconfig +source drivers/Kconfig +source fs/Kconfig +source lib/Kconfig +source crypto/Kconfig diff --git a/arch/efi/Makefile b/arch/efi/Makefile new file mode 100644 index 0000000000..af280859f0 --- /dev/null +++ b/arch/efi/Makefile @@ -0,0 +1,41 @@ +CFLAGS += -fpic -fshort-wchar -mno-sse -mno-mmx + +ifeq ($(CONFIG_X86_32),y) + UTS_MACHINE := i386 + biarch := $(call cc-option,-m32) + AFLAGS += $(biarch) + CFLAGS += $(biarch) + TARGET = efi-app-ia32 +else + UTS_MACHINE := x86_64 + AFLAGS += -m64 + CFLAGS += -m64 -mno-red-zone + TARGET = efi-app-x86_64 +endif + +lds-$(CONFIG_X86_32) := arch/efi/lib/elf_ia32_efi.lds +lds-$(CONFIG_X86_64) := arch/efi/lib/elf_x86_64_efi.lds + +cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \ + -T $(lds-y) \ + -shared -Bsymbolic -nostdlib -znocombreloc \ + --start-group $(barebox-common) \ + --end-group \ + $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^) + +quiet_cmd_efi_image = EFI-IMG $@ + cmd_efi_image = objcopy -j .text -j .sdata -j .data -j .dynamic \ + -j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \ + -j __barebox_cmd -j .barebox_magicvar -j .bbenv.* \ + --target=$(TARGET) $< $@ + +KBUILD_BINARY := barebox + +LDFLAGS := -m elf_$(UTS_MACHINE) --no-undefined + +barebox.efi: $(KBUILD_BINARY) FORCE + $(call if_changed,efi_image) + +KBUILD_IMAGE := barebox.efi + +common-y += arch/efi/efi/ arch/efi/lib/ diff --git a/arch/efi/configs/efi_defconfig b/arch/efi/configs/efi_defconfig new file mode 100644 index 0000000000..456f70d32b --- /dev/null +++ b/arch/efi/configs/efi_defconfig @@ -0,0 +1,78 @@ +CONFIG_MMU=y +CONFIG_MALLOC_SIZE=0x0 +CONFIG_MALLOC_TLSF=y +CONFIG_PROMPT="barebox> " +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +# CONFIG_TIMESTAMP is not set +CONFIG_CONSOLE_ACTIVATE_ALL=y +CONFIG_PARTITION_DISK_EFI=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_POLLER=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +CONFIG_CMD_GO=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_RESET=y +CONFIG_CMD_UIMAGE=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_MAGICVAR=y +CONFIG_CMD_MAGICVAR_HELP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_FILETYPE=y +CONFIG_CMD_LN=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_LET=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_READF=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_HOST=y +CONFIG_CMD_PING=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENUTREE=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MM=y +CONFIG_CMD_DETECT=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_2048=y +CONFIG_CMD_BAREBOX_UPDATE=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_TIME=y +CONFIG_NET=y +CONFIG_NET_NFS=y +CONFIG_NET_NETCONSOLE=y +CONFIG_DRIVER_SERIAL_EFI_STDIO=y +CONFIG_DRIVER_SERIAL_NS16550=y +CONFIG_DRIVER_NET_EFI_SNP=y +# CONFIG_SPI is not set +CONFIG_DISK=y +CONFIG_FS_EXT4=y +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y +CONFIG_FS_EFI=y +CONFIG_FS_EFIVARFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y diff --git a/arch/efi/efi/Makefile b/arch/efi/efi/Makefile new file mode 100644 index 0000000000..a856e5907c --- /dev/null +++ b/arch/efi/efi/Makefile @@ -0,0 +1,2 @@ +obj-y += efi.o clocksource.o efi-block-io.o efi-device.o efi-image.o +bbenv-y += env-efi diff --git a/arch/efi/efi/clocksource.c b/arch/efi/efi/clocksource.c new file mode 100644 index 0000000000..2f33b43cce --- /dev/null +++ b/arch/efi/efi/clocksource.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#ifdef __x86_64__ +uint64_t ticks_read(void) +{ + uint64_t a, d; + + __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); + + return (d << 32) | a; +} +#else +uint64_t ticks_read(void) +{ + uint64_t val; + + __asm__ volatile ("rdtsc" : "=A" (val)); + + return val; +} +#endif + +static uint64_t freq; + +/* count TSC ticks during a millisecond delay */ +static uint64_t ticks_freq(void) +{ + uint64_t ticks_start, ticks_end; + + ticks_start = ticks_read(); + BS->stall(1000); + ticks_end = ticks_read(); + + return (ticks_end - ticks_start) * 1000; +} + +static uint64_t efi_clocksource_read(void) +{ + return 1000 * 1000 * ticks_read() / freq; +} + +static struct clocksource cs = { + .read = efi_clocksource_read, + .mask = CLOCKSOURCE_MASK(64), + .shift = 0, +}; + +int efi_clocksource_init(void) +{ + cs.mult = clocksource_hz2mult(1000 * 1000, cs.shift); + + freq = ticks_freq(); + + init_clock(&cs); + + return 0; +} diff --git a/arch/efi/efi/efi-block-io.c b/arch/efi/efi/efi-block-io.c new file mode 100644 index 0000000000..00115317fc --- /dev/null +++ b/arch/efi/efi/efi-block-io.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 +#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31)) + +struct efi_block_io_media{ + u32 media_id; + bool removable_media; + bool media_present; + bool logical_partition; + bool read_only; + bool write_caching; + u32 block_size; + u32 io_align; + u64 last_block; + u64 lowest_aligned_lba; /* added in Revision 2 */ + u32 logical_blocks_per_physical_block; /* added in Revision 2 */ + u32 optimal_transfer_length_granularity; /* added in Revision 3 */ +}; + +struct efi_block_io_protocol { + u64 revision; + struct efi_block_io_media *media; + efi_status_t(EFIAPI *reset)(struct efi_block_io_protocol *this, + bool ExtendedVerification); + efi_status_t(EFIAPI *read)(struct efi_block_io_protocol *this, u32 media_id, + u64 lba, unsigned long buffer_size, void *buf); + efi_status_t(EFIAPI *write)(struct efi_block_io_protocol *this, u32 media_id, + u64 lba, unsigned long buffer_size, void *buf); + efi_status_t(EFIAPI *flush)(struct efi_block_io_protocol *this); +}; + +struct efi_bio_priv { + struct efi_block_io_protocol *protocol; + struct device_d *dev; + struct block_device blk; + u32 media_id; +}; + +static int efi_bio_read(struct block_device *blk, void *buffer, int block, + int num_blocks) +{ + struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk); + efi_status_t efiret; + + efiret = priv->protocol->read(priv->protocol, priv->media_id, + block, num_blocks * 512, buffer); + + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static int efi_bio_write(struct block_device *blk, + const void *buffer, int block, int num_blocks) +{ + struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk); + efi_status_t efiret; + + efiret = priv->protocol->write(priv->protocol, priv->media_id, + block, num_blocks * 512, (void *)buffer); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static int efi_bio_flush(struct block_device *blk) +{ + struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk); + efi_status_t efiret; + + efiret = priv->protocol->flush(priv->protocol); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static struct block_device_ops efi_bio_ops = { + .read = efi_bio_read, + .write = efi_bio_write, + .flush = efi_bio_flush, +}; + +static void efi_bio_print_info(struct efi_bio_priv *priv) +{ + struct efi_block_io_media *media = priv->protocol->media; + u64 revision = priv->protocol->revision; + + dev_dbg(priv->dev, "revision: 0x%016llx\n", revision); + dev_dbg(priv->dev, "media_id: 0x%08x\n", media->media_id); + dev_dbg(priv->dev, "removable_media: %d\n", media->removable_media); + dev_dbg(priv->dev, "media_present: %d\n", media->media_present); + dev_dbg(priv->dev, "logical_partition: %d\n", media->logical_partition); + dev_dbg(priv->dev, "read_only: %d\n", media->read_only); + dev_dbg(priv->dev, "write_caching: %d\n", media->write_caching); + dev_dbg(priv->dev, "block_size: 0x%08x\n", media->block_size); + dev_dbg(priv->dev, "io_align: 0x%08x\n", media->io_align); + dev_dbg(priv->dev, "last_block: 0x%016llx\n", media->last_block); + + if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION2) + return; + + dev_dbg(priv->dev, "u64 lowest_aligned_lba: 0x%08llx\n", + media->lowest_aligned_lba); + dev_dbg(priv->dev, "logical_blocks_per_physical_block: 0x%08x\n", + media->logical_blocks_per_physical_block); + + if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION3) + return; + + dev_dbg(priv->dev, "optimal_transfer_length_granularity: 0x%08x\n", + media->optimal_transfer_length_granularity); +} + +int efi_bio_probe(struct efi_device *efidev) +{ + int ret; + struct efi_bio_priv *priv; + struct efi_block_io_media *media; + + priv = xzalloc(sizeof(*priv)); + + BS->handle_protocol(efidev->handle, &efi_block_io_protocol_guid, + (void **)&priv->protocol); + if (!priv->protocol) + return -ENODEV; + + media = priv->protocol->media; + efi_bio_print_info(priv); + priv->dev = &efidev->dev; + + priv->blk.cdev.name = asprintf("disk%d", cdev_find_free_index("disk")); + priv->blk.blockbits = ffs(media->block_size) - 1; + priv->blk.num_blocks = media->last_block; + priv->blk.ops = &efi_bio_ops; + priv->blk.dev = &efidev->dev; + + priv->media_id = media->media_id; + + ret = blockdevice_register(&priv->blk); + if (ret) + return ret; + + parse_partition_table(&priv->blk); + + return 0; +} + +static struct efi_driver efi_fs_driver = { + .driver = { + .name = "efi-block-io", + }, + .probe = efi_bio_probe, + .guid = EFI_BLOCK_IO_PROTOCOL_GUID, +}; +device_efi_driver(efi_fs_driver); diff --git a/arch/efi/efi/efi-device.c b/arch/efi/efi/efi-device.c new file mode 100644 index 0000000000..71526b999f --- /dev/null +++ b/arch/efi/efi/efi-device.c @@ -0,0 +1,348 @@ +/* + * efi-device.c - barebox EFI payload support + * + * Copyright (c) 2014 Sascha Hauer , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c new file mode 100644 index 0000000000..18757d2697 --- /dev/null +++ b/arch/efi/efi/efi-image.c @@ -0,0 +1,105 @@ +/* + * efi-image.c - barebox EFI payload support + * + * Copyright (c) 2014 Sascha Hauer , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int efi_execute_image(const char *file) +{ + void *exe; + size_t size; + efi_handle_t handle; + efi_status_t efiret; + const char *options; + efi_loaded_image_t *loaded_image; + + exe = read_file(file, &size); + if (!exe) + return -EINVAL; + + efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe, size, + &handle); + if (EFI_ERROR(efiret)) { + pr_err("failed to LoadImage: %s\n", efi_strerror(efiret)); + return -efi_errno(efiret);; + }; + + efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid, + (void **)&loaded_image, + efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + options = linux_bootargs_get(); + loaded_image->load_options = strdup_char_to_wchar(options); + loaded_image->load_options_size = (strlen(options) + 1) * sizeof(wchar_t); + + efiret = BS->start_image(handle, NULL, NULL); + + efi_connect_all(); + efi_register_devices(); + + return 0; +} + +static int do_bootm_efi(struct image_data *data) +{ + return efi_execute_image(data->os_file); +} + +static struct image_handler efi_handle_tr = { + .name = "EFI Application", + .bootm = do_bootm_efi, + .filetype = filetype_exe, +}; + +static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv) +{ + return efi_execute_image(file); +} + +static struct binfmt_hook binfmt_efi_hook = { + .type = filetype_exe, + .hook = efi_execute, +}; + +static int efi_register_image_handler(void) +{ + register_image_handler(&efi_handle_tr); + binfmt_register(&binfmt_efi_hook); + + return 0; +} +late_initcall(efi_register_image_handler); diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c new file mode 100644 index 0000000000..48b7d9a438 --- /dev/null +++ b/arch/efi/efi/efi.c @@ -0,0 +1,342 @@ +/* + * efi.c - barebox EFI payload support + * + * Copyright (c) 2014 Sascha Hauer , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/arch/efi/efi/env-efi/network/eth0-discover b/arch/efi/efi/env-efi/network/eth0-discover new file mode 100644 index 0000000000..62c31a553c --- /dev/null +++ b/arch/efi/efi/env-efi/network/eth0-discover @@ -0,0 +1,5 @@ +#!/bin/sh + +for i in /boot/network-drivers/*; do + $i; +done diff --git a/arch/efi/include/asm/barebox.h b/arch/efi/include/asm/barebox.h new file mode 100644 index 0000000000..2997587d82 --- /dev/null +++ b/arch/efi/include/asm/barebox.h @@ -0,0 +1 @@ +/* dummy */ diff --git a/arch/efi/include/asm/bitops.h b/arch/efi/include/asm/bitops.h new file mode 100644 index 0000000000..94646d4d0d --- /dev/null +++ b/arch/efi/include/asm/bitops.h @@ -0,0 +1,15 @@ +#ifndef _SANDBOX_BITOPS_H +#define _SANDBOX_BITOPS_H + +/* nothing but the defaults.. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/arch/efi/include/asm/byteorder.h b/arch/efi/include/asm/byteorder.h new file mode 100644 index 0000000000..37316f2371 --- /dev/null +++ b/arch/efi/include/asm/byteorder.h @@ -0,0 +1,8 @@ +#ifndef _I386_BYTEORDER_H +#define _I386_BYTEORDER_H + +#include + +#include + +#endif /* _I386_BYTEORDER_H */ diff --git a/arch/efi/include/asm/common.h b/arch/efi/include/asm/common.h new file mode 100644 index 0000000000..b0e6b7fb18 --- /dev/null +++ b/arch/efi/include/asm/common.h @@ -0,0 +1,4 @@ +#ifndef ASM_COMMON_H +#define ASM_COMMON_H + +#endif /* ASM_COMMON_H */ diff --git a/arch/efi/include/asm/dma.h b/arch/efi/include/asm/dma.h new file mode 100644 index 0000000000..459536779e --- /dev/null +++ b/arch/efi/include/asm/dma.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2012 by Marc Kleine-Budde + * + * This file is released under the GPLv2 + * + */ + +#ifndef __ASM_DMA_H +#define __ASM_DMA_H + +/* empty*/ + +#endif /* __ASM_DMA_H */ diff --git a/arch/efi/include/asm/elf.h b/arch/efi/include/asm/elf.h new file mode 100644 index 0000000000..ddde035188 --- /dev/null +++ b/arch/efi/include/asm/elf.h @@ -0,0 +1,60 @@ +#ifndef __ASM_SANDBOX_ELF_H__ +#define __ASM_SANDBOX_ELF_H__ + +#ifdef __i386__ + +typedef struct user_fxsr_struct elf_fpxregset_t; + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_386 + +#else + +/* x86-64 relocation types */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ + +#define R_X86_64_NUM 16 + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_X86_64 + +#endif + +#endif /* __ASM_SANDBOX_ELF_H__ */ diff --git a/arch/efi/include/asm/io.h b/arch/efi/include/asm/io.h new file mode 100644 index 0000000000..ac8a9c1b35 --- /dev/null +++ b/arch/efi/include/asm/io.h @@ -0,0 +1,55 @@ +#ifndef __ASM_SANDBOX_IO_H +#define __ASM_SANDBOX_IO_H + +#define build_mmio_read(name, size, type, reg, barrier) \ + static inline type name(const volatile void *addr) \ + { type ret; asm volatile("mov" size " %1,%0":reg (ret) \ + :"m" (*(volatile type*)addr) barrier); return ret; } + +build_mmio_read(readb, "b", unsigned char, "=q", :"memory") +build_mmio_read(readw, "w", unsigned short, "=r", :"memory") +build_mmio_read(readl, "l", unsigned int, "=r", :"memory") + +#define build_mmio_write(name, size, type, reg, barrier) \ + static inline void name(type val, volatile void *addr) \ + { asm volatile("mov" size " %0,%1": :reg (val), \ + "m" (*(volatile type*)addr) barrier); } + +build_mmio_write(writeb, "b", unsigned char, "q", :"memory") +build_mmio_write(writew, "w", unsigned short, "r", :"memory") +build_mmio_write(writel, "l", unsigned int, "r", :"memory") + +#define BUILDIO(bwl, bw, type) \ +static inline void out##bwl(unsigned type value, int port) \ +{ \ + asm volatile("out" #bwl " %" #bw "0, %w1" \ + : : "a"(value), "Nd"(port)); \ +} \ + \ +static inline unsigned type in##bwl(int port) \ +{ \ + unsigned type value; \ + asm volatile("in" #bwl " %w1, %" #bw "0" \ + : "=a"(value) : "Nd"(port)); \ + return value; \ +} \ + \ +static inline void outs##bwl(int port, const void *addr, unsigned long count) \ +{ \ + asm volatile("rep; outs" #bwl \ + : "+S"(addr), "+c"(count) : "d"(port)); \ +} \ + \ +static inline void ins##bwl(int port, void *addr, unsigned long count) \ +{ \ + asm volatile("rep; ins" #bwl \ + : "+D"(addr), "+c"(count) : "d"(port)); \ +} + +BUILDIO(b, b, char) +BUILDIO(w, w, short) +BUILDIO(l, , int) + +#define IO_SPACE_LIMIT 0xffff + +#endif /* __ASM_SANDBOX_IO_H */ diff --git a/arch/efi/include/asm/posix_types.h b/arch/efi/include/asm/posix_types.h new file mode 100644 index 0000000000..6985b8eb4a --- /dev/null +++ b/arch/efi/include/asm/posix_types.h @@ -0,0 +1,93 @@ +#ifndef __ARCH_I386_POSIX_TYPES_H +#define __ARCH_I386_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +/* + * Most 32 bit architectures use "unsigned int" size_t, + * and all 64 bit architectures use "unsigned long" size_t. + * + * TODO: It's not clean to use __x86_64__ here. It's better + * to check on __BITS_PER_LONG here. But this is wrong set in + * arch/sandbox/include/asm/types.h. + */ +#ifdef __x86_64__ +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +#else +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +#endif +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + int __val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +#define __FD_SET(fd,fdsetp) \ + __asm__ __volatile__("btsl %1,%0": \ + "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd))) + +#undef __FD_CLR +#define __FD_CLR(fd,fdsetp) \ + __asm__ __volatile__("btrl %1,%0": \ + "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd))) + +#undef __FD_ISSET +#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \ + unsigned char __result; \ + __asm__ __volatile__("btl %1,%2 ; setb %0" \ + :"=q" (__result) :"r" ((int) (fd)), \ + "m" (*(__kernel_fd_set *) (fdsetp))); \ + __result; })) + +#undef __FD_ZERO +#define __FD_ZERO(fdsetp) \ +do { \ + int __d0, __d1; \ + __asm__ __volatile__("cld ; rep ; stosl" \ + :"=m" (*(__kernel_fd_set *) (fdsetp)), \ + "=&c" (__d0), "=&D" (__d1) \ + :"a" (0), "1" (__FDSET_LONGS), \ + "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \ +} while (0) + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif diff --git a/arch/efi/include/asm/sections.h b/arch/efi/include/asm/sections.h new file mode 100644 index 0000000000..2b8c516038 --- /dev/null +++ b/arch/efi/include/asm/sections.h @@ -0,0 +1 @@ +#include diff --git a/arch/efi/include/asm/string.h b/arch/efi/include/asm/string.h new file mode 100644 index 0000000000..2997587d82 --- /dev/null +++ b/arch/efi/include/asm/string.h @@ -0,0 +1 @@ +/* dummy */ diff --git a/arch/efi/include/asm/swab.h b/arch/efi/include/asm/swab.h new file mode 100644 index 0000000000..60a90120b6 --- /dev/null +++ b/arch/efi/include/asm/swab.h @@ -0,0 +1,6 @@ +#ifndef _ASM_SWAB_H +#define _ASM_SWAB_H + +/* nothing. use generic functions */ + +#endif /* _ASM_SWAB_H */ diff --git a/arch/efi/include/asm/types.h b/arch/efi/include/asm/types.h new file mode 100644 index 0000000000..3204448dce --- /dev/null +++ b/arch/efi/include/asm/types.h @@ -0,0 +1,73 @@ +#ifndef __ASM_I386_TYPES_H +#define __ASM_I386_TYPES_H + +#ifndef __ASSEMBLY__ + +#ifdef __x86_64__ +/* + * This is used in dlmalloc. On X86_64 we need it to be + * 64 bit + */ +#define INTERNAL_SIZE_T unsigned long + +/* + * This is a Kconfig variable in the Kernel, but we want to detect + * this during compile time, so we set it here. + */ +#define CONFIG_PHYS_ADDR_T_64BIT + +#endif + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#ifdef __x86_64__ +#define BITS_PER_LONG 64 +#else +#define BITS_PER_LONG 32 +#endif + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +#endif /* __KERNEL__ */ + +#endif + +#endif diff --git a/arch/efi/include/asm/unaligned.h b/arch/efi/include/asm/unaligned.h new file mode 100644 index 0000000000..d02da6e60d --- /dev/null +++ b/arch/efi/include/asm/unaligned.h @@ -0,0 +1,19 @@ +#ifndef _ASM_SANDBOX_UNALIGNED_H +#define _ASM_SANDBOX_UNALIGNED_H + +/* + * The architecture sandbox is compiled on can do unaligned accesses itself. + */ + +#include +#include + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define get_unaligned __get_unaligned_le +#define put_unaligned __put_unaligned_le +#else +#define get_unaligned __get_unaligned_be +#define put_unaligned __put_unaligned_be +#endif + +#endif /* _ASM_SANDBOX_UNALIGNED_H */ diff --git a/arch/efi/include/mach/debug_ll.h b/arch/efi/include/mach/debug_ll.h new file mode 100644 index 0000000000..0fb2cb8c2a --- /dev/null +++ b/arch/efi/include/mach/debug_ll.h @@ -0,0 +1,20 @@ +#ifndef __MACH_DEBUG_LL_H__ +#define __MACH_DEBUG_LL_H__ + +#define EFI_DEBUG 0 +#define EFI_DEBUG_CLEAR_MEMORY 0 + +#include +#include + +static inline void PUTC_LL(char c) +{ + uint16_t str[2] = {}; + struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out; + + str[0] = c; + + con_out->output_string(con_out, str); +} + +#endif diff --git a/arch/efi/include/mach/efi-device.h b/arch/efi/include/mach/efi-device.h new file mode 100644 index 0000000000..fe074a44bb --- /dev/null +++ b/arch/efi/include/mach/efi-device.h @@ -0,0 +1,45 @@ +#ifndef __MACH_EFI_DEVICE_H +#define __MACH_EFI_DEVICE_H + +struct efi_device { + struct device_d dev; + efi_guid_t *guids; + int num_guids; + efi_handle_t handle; + efi_handle_t parent_handle; + void *protocol; + struct efi_device_path *devpath; +}; + +struct efi_driver { + struct driver_d driver; + int (*probe)(struct efi_device *efidev); + void (*remove)(struct efi_device *efidev); + efi_guid_t guid; +}; + +extern struct bus_type efi_bus; + +static inline struct efi_device *to_efi_device(struct device_d *dev) +{ + return container_of(dev, struct efi_device, dev); +} + +static inline struct efi_driver *to_efi_driver(struct driver_d *drv) +{ + return container_of(drv, struct efi_driver, driver); +} + +#define device_efi_driver(drv) \ + register_driver_macro(device, efi, drv) + +static inline int efi_driver_register(struct efi_driver *efidrv) +{ + efidrv->driver.bus = &efi_bus; + return register_driver(&efidrv->driver); +} + +int efi_connect_all(void); +void efi_register_devices(void); + +#endif /* __MACH_EFI_DEVICE_H */ diff --git a/arch/efi/include/mach/efi.h b/arch/efi/include/mach/efi.h new file mode 100644 index 0000000000..1e9782a136 --- /dev/null +++ b/arch/efi/include/mach/efi.h @@ -0,0 +1,24 @@ +#ifndef __MACH_EFI_H +#define __MACH_EFI_H + +#include + +const char *efi_strerror(efi_status_t err); + +extern efi_system_table_t *efi_sys_table; +extern efi_handle_t efi_parent_image; +extern struct efi_device_path *efi_device_path; +extern efi_loaded_image_t *efi_loaded_image; + +int efi_errno(efi_status_t err); + +int efi_clocksource_init(void); + +void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size); + +static inline void *efi_get_global_var(char *name, int *var_size) +{ + return efi_get_variable(name, &efi_global_variable_guid, var_size); +} + +#endif /* __MACH_EFI_H */ diff --git a/arch/efi/lib/.gitignore b/arch/efi/lib/.gitignore new file mode 100644 index 0000000000..847e317701 --- /dev/null +++ b/arch/efi/lib/.gitignore @@ -0,0 +1,2 @@ +elf_x86_64_efi.lds +elf_ia32_efi.lds diff --git a/arch/efi/lib/Makefile b/arch/efi/lib/Makefile new file mode 100644 index 0000000000..c8a97bae07 --- /dev/null +++ b/arch/efi/lib/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_X86_64) += reloc_x86_64.o crt0-efi-x86_64.o +obj-$(CONFIG_X86_32) += reloc_ia32.o crt0-efi-ia32.o +extra-$(CONFIG_X86_32) += elf_ia32_efi.lds +extra-$(CONFIG_X86_64) += elf_x86_64_efi.lds diff --git a/arch/efi/lib/crt0-efi-ia32.S b/arch/efi/lib/crt0-efi-ia32.S new file mode 100644 index 0000000000..6f0f2e872e --- /dev/null +++ b/arch/efi/lib/crt0-efi-ia32.S @@ -0,0 +1,76 @@ +/* crt0-efi-ia32.S - x86 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + + .text + .align 4 + + .globl _start +_start: + pushl %ebp + movl %esp,%ebp + + pushl 12(%ebp) # copy "image" argument + pushl 8(%ebp) # copy "systab" argument + + call 0f +0: popl %eax + movl %eax,%ebx + + addl $image_base-0b,%eax # %eax = ldbase + addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC + + pushl %ebx # pass _DYNAMIC as second argument + pushl %eax # pass ldbase as first argument + call _relocate + popl %ebx + popl %ebx + testl %eax,%eax + jne .exit + + call efi_main # call app with "image" and "systab" argument + +.exit: leave + ret + + /* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */ + + .data +dummy: .long 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc + .long dummy /* Page RVA */ + .long 10 /* Block Size (2*4+2) */ + .word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */ diff --git a/arch/efi/lib/crt0-efi-x86_64.S b/arch/efi/lib/crt0-efi-x86_64.S new file mode 100644 index 0000000000..aa03106e9c --- /dev/null +++ b/arch/efi/lib/crt0-efi-x86_64.S @@ -0,0 +1,75 @@ +/* crt0-efi-x86_64.S - x86_64 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + .text + .align 4 + + .globl _start +_start: + subq $8, %rsp + pushq %rcx + pushq %rdx + +0: + lea image_base(%rip), %rdi + lea _DYNAMIC(%rip), %rsi + + popq %rcx + popq %rdx + pushq %rcx + pushq %rdx + call _relocate + + popq %rdi + popq %rsi + + call efi_main + addq $8, %rsp + +.exit: + ret + + /* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */ + + .data +dummy: .long 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc, "a" +label1: + .long dummy-label1 /* Page RVA */ + .long 10 /* Block Size (2*4+2) */ + .word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */ diff --git a/arch/efi/lib/elf_ia32_efi.lds.S b/arch/efi/lib/elf_ia32_efi.lds.S new file mode 100644 index 0000000000..a5f6287500 --- /dev/null +++ b/arch/efi/lib/elf_ia32_efi.lds.S @@ -0,0 +1,102 @@ +#include + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + . = 0; + image_base = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .text : + { + _stext = .; + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + _etext = .; + + . = ALIGN(4096); + .sdata : { + *(.got.plt) + *(.got) + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + } + + . = ALIGN(4096); + _sdata = .; + + .data : { + *(.rodata*) + *(.data) + *(.data1) + *(.data.*) + *(.sdata) + *(.got.plt) + *(.got) + /* the EFI loader doesn't seem to like a .bss section, so we stick + * it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + + . = ALIGN(64); + + __barebox_initcalls_start = .; + __barebox_initcalls : { INITCALLS } + __barebox_initcalls_end = .; + + . = ALIGN(64); + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + + . = ALIGN(64); + __barebox_cmd_start = .; + __barebox_cmd : { BAREBOX_CMDS } + __barebox_cmd_end = .; + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rel : { + *(.rel.data) + *(.rel.data.*) + *(.rel.got) + *(.rel.stab) + *(.data.rel.ro.local) + *(.data.rel.local) + *(.data.rel.ro) + *(.data.rel*) + } + + . = ALIGN(4096); + .reloc : /* This is the PECOFF .reloc section! */ + { + *(.reloc) + } + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + + .comment 0 : { *(.comment) } +} diff --git a/arch/efi/lib/elf_x86_64_efi.lds.S b/arch/efi/lib/elf_x86_64_efi.lds.S new file mode 100644 index 0000000000..d48432d21b --- /dev/null +++ b/arch/efi/lib/elf_x86_64_efi.lds.S @@ -0,0 +1,93 @@ +#include + +/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ + +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + . = 0; + image_base = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .eh_frame : { + *(.eh_frame) + } + + . = ALIGN(4096); + + .text : { + _stext = .; + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + _etext = .; + + . = ALIGN(4096); + + .reloc : { + *(.reloc) + } + + . = ALIGN(4096); + _sdata = .; + + .data : { + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + * it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + } + + . = ALIGN(64); + + __barebox_initcalls_start = .; + __barebox_initcalls : { INITCALLS } + __barebox_initcalls_end = .; + + . = ALIGN(64); + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + + . = ALIGN(64); + __barebox_cmd_start = .; + __barebox_cmd : { BAREBOX_CMDS } + __barebox_cmd_end = .; + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + + .rela : { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + + .comment 0 : { *(.comment) } +} diff --git a/arch/efi/lib/reloc_ia32.c b/arch/efi/lib/reloc_ia32.c new file mode 100644 index 0000000000..46929631ec --- /dev/null +++ b/arch/efi/lib/reloc_ia32.c @@ -0,0 +1,97 @@ +/* reloc_ia32.c - position independent x86 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + 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 +#include + +#include + +efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab) +{ + long relsz = 0, relent = 0; + Elf32_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf32_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + + case DT_RELA: + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF32_R_TYPE (rel->r_info)) { + case R_386_NONE: + break; + + case R_386_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf32_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/arch/efi/lib/reloc_x86_64.c b/arch/efi/lib/reloc_x86_64.c new file mode 100644 index 0000000000..1db72f5dbc --- /dev/null +++ b/arch/efi/lib/reloc_x86_64.c @@ -0,0 +1,96 @@ +/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu . + + 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 +#include + +#include + +efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab) +{ + long relsz = 0, relent = 0; + Elf64_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE (rel->r_info)) { + case R_X86_64_NONE: + break; + + case R_X86_64_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf64_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/common/Kconfig b/common/Kconfig index bba7f159c1..8b361260c0 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -64,6 +64,14 @@ config MENUTREE select GLOB select GLOB_SORT +config EFI_GUID + bool + help + With this option a table of EFI guids is compiled in. + +config EFI_DEVICEPATH + bool + menu "General Settings" config LOCALVERSION diff --git a/common/Makefile b/common/Makefile index 204241c919..4220e15127 100644 --- a/common/Makefile +++ b/common/Makefile @@ -43,7 +43,9 @@ obj-$(CONFIG_RESET_SOURCE) += reset_source.o obj-$(CONFIG_SHELL_HUSH) += hush.o obj-$(CONFIG_SHELL_SIMPLE) += parser.o obj-$(CONFIG_UIMAGE) += image.o uimage.o -obj-$(CONFIG_MENUTREE) += menutree.o +obj-$(CONFIG_MENUTREE) += menutree.o +obj-$(CONFIG_EFI_GUID) += efi-guid.o +obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o quiet_cmd_pwd_h = PWDH $@ ifdef CONFIG_PASSWORD diff --git a/common/efi-devicepath.c b/common/efi-devicepath.c new file mode 100644 index 0000000000..2b1d916768 --- /dev/null +++ b/common/efi-devicepath.c @@ -0,0 +1,1370 @@ +#include +#include +#include +#include +#include + +struct string { + char *str; + int len; +}; + +char *cprintf(struct string *str, const char *fmt, ...) + __attribute__ ((format(__printf__, 2, 3))); + +char *cprintf(struct string *str, const char *fmt, ...) +{ + va_list args; + int len; + + va_start(args, fmt); + if (str->str) + len = vsprintf(str->str + str->len, fmt, args); + else + len = vsnprintf(NULL, 0, fmt, args); + va_end(args); + + str->len += len; + + return NULL; +} + +#define MIN_ALIGNMENT_SIZE 8 /* FIXME: X86_64 specific */ +#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) + +#define EFI_DP_TYPE_MASK 0x7f +#define EFI_DP_TYPE_UNPACKED 0x80 + +#define END_DEVICE_PATH_TYPE 0x7f + +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 +#define END_DEVICE_PATH_LENGTH (sizeof(struct efi_device_path)) + +#define DP_IS_END_TYPE(a) +#define DP_IS_END_SUBTYPE(a) ( ((a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE ) + +#define device_path_type(a) ( ((a)->type) & EFI_DP_TYPE_MASK ) +#define next_device_path_node(a) ( (struct efi_device_path *) ( ((u8 *) (a)) + (a)->length)) +#define is_device_path_end_type(a) ( device_path_type(a) == END_DEVICE_PATH_TYPE ) +#define is_device_path_end_sub_type(a) ( (a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE ) +#define is_device_path_end(a) ( is_device_path_end_type(a) && is_device_path_end_sub_type(a) ) +#define is_device_path_unpacked(a) ( (a)->type & EFI_DP_TYPE_UNPACKED ) + +#define set_device_path_end_node(a) { \ + (a)->type = END_DEVICE_PATH_TYPE; \ + (a)->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE; \ + (a)->length = sizeof(struct efi_device_path); \ + } + +/* + * Hardware Device Path (UEFI 2.4 specification, version 2.4 § 9.3.2.) + */ + +#define HARDWARE_DEVICE_PATH 0x01 + +#define HW_PCI_DP 0x01 +struct pci_device_path { + struct efi_device_path header; + u8 Function; + u8 Device; +}; + +#define HW_PCCARD_DP 0x02 +struct pccard_device_path { + struct efi_device_path header; + u8 function_number; +}; + +#define HW_MEMMAP_DP 0x03 +struct memmap_device_path { + struct efi_device_path header; + u32 memory_type; + efi_physical_addr_t starting_address; + efi_physical_addr_t ending_address; +}; + +#define HW_VENDOR_DP 0x04 +struct vendor_device_path { + struct efi_device_path header; + efi_guid_t Guid; +}; + +struct unknown_device_vendor_device_path { + struct vendor_device_path device_path; + u8 legacy_drive_letter; +}; + +#define HW_CONTROLLER_DP 0x05 +struct controller_device_path { + struct efi_device_path header; + u32 Controller; +}; + +/* + * ACPI Device Path (UEFI 2.4 specification, version 2.4 § 9.3.3 and 9.3.4.) + */ +#define ACPI_DEVICE_PATH 0x02 + +#define ACPI_DP 0x01 +struct acpi_hid_device_path { + struct efi_device_path header; + u32 HID; + u32 UID; +}; + +#define EXPANDED_ACPI_DP 0x02 +struct expanded_acpi_hid_device_path { + struct efi_device_path header; + u32 HID; + u32 UID; + u32 CID; + u8 hid_str[1]; +}; + +#define ACPI_ADR_DP 3 +struct acpi_adr_device_path { + struct efi_device_path header; + u32 ADR; +}; + +/* + * EISA ID Macro + * EISA ID Definition 32-bits + * bits[15:0] - three character compressed ASCII EISA ID. + * bits[31:16] - binary number + * Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' + */ +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((u32) ((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + +/* + * Messaging Device Path (UEFI 2.4 specification, version 2.4 § 9.3.5.) + */ +#define MESSAGING_DEVICE_PATH 0x03 + +#define MSG_ATAPI_DP 0x01 +struct atapi_device_path { + struct efi_device_path header; + u8 primary_secondary; + u8 slave_master; + u16 Lun; +}; + +#define MSG_SCSI_DP 0x02 +struct scsi_device_path { + struct efi_device_path header; + u16 Pun; + u16 Lun; +}; + +#define MSG_FIBRECHANNEL_DP 0x03 +struct fibrechannel_device_path { + struct efi_device_path header; + u32 Reserved; + u64 WWN; + u64 Lun; +}; + +/** + * Fibre Channel Ex sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_FIBRECHANNELEX_DP 21 +struct fibrechannelex_device_path { + struct efi_device_path header; + u32 Reserved; + u8 WWN[8]; /* World Wide Name */ + u8 Lun[8]; /* Logical unit, T-10 SCSI Architecture Model 4 specification */ +}; + +#define MSG_1394_DP 0x04 +struct f1394_device_path { + struct efi_device_path header; + u32 Reserved; + u64 Guid; +}; + +#define MSG_USB_DP 0x05 +struct usb_device_path { + struct efi_device_path header; + u8 Port; + u8 Endpoint; +}; + +/** + * SATA Device Path sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_SATA_DP 18 +struct sata_device_path { + struct efi_device_path header; + u16 HBAPort_number; + u16 port_multiplier_port_number; + u16 Lun; /* Logical Unit Number */ +}; + +/** + * USB WWID Device Path sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.7. + */ +#define MSG_USB_WWID_DP 16 +struct usb_wwid_device_path { + struct efi_device_path header; + u16 interface_number; + u16 vendor_id; + u16 product_id; + s16 serial_number[1]; /* UTF-16 characters of the USB serial number */ +}; + +/** + * Device Logical Unit sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_DEVICE_LOGICAL_UNIT_DP 17 +struct device_logical_unit_device_path { + struct efi_device_path header; + u8 Lun; /* Logical Unit Number */ +}; + +#define MSG_USB_CLASS_DP 0x0_f +struct usb_class_device_path { + struct efi_device_path header; + u16 vendor_id; + u16 product_id; + u8 device_class; + u8 device_subclass; + u8 device_protocol; +}; + +#define MSG_I2_o_DP 0x06 +struct i2_o_device_path { + struct efi_device_path header; + u32 Tid; +}; + +#define MSG_MAC_ADDR_DP 0x0b +struct mac_addr_device_path { + struct efi_device_path header; + efi_mac_address mac_address; + u8 if_type; +}; + +#define MSG_IPv4_DP 0x0c +struct ipv4_device_path { + struct efi_device_path header; + efi_ipv4_address local_ip_address; + efi_ipv4_address remote_ip_address; + u16 local_port; + u16 remote_port; + u16 Protocol; + bool static_ip_address; + /* new from UEFI version 2, code must check length field in header */ + efi_ipv4_address gateway_ip_address; + efi_ipv4_address subnet_mask; +}; + +#define MSG_IPv6_DP 0x0d +struct ipv6_device_path { + struct efi_device_path header; + efi_ipv6_address local_ip_address; + efi_ipv6_address remote_ip_address; + u16 local_port; + u16 remote_port; + u16 Protocol; + bool IPAddress_origin; + /* new from UEFI version 2, code must check length field in header */ + u8 prefix_length; + efi_ipv6_address gateway_ip_address; +}; + +/** + * Device Logical Unit sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_VLAN_DP 20 +struct vlan_device_path { + struct efi_device_path header; + u16 vlan_id; +}; + +#define MSG_INFINIBAND_DP 0x09 +struct infiniband_device_path { + struct efi_device_path header; + u32 resource_flags; + efi_guid_t port_gid; + u64 service_id; + u64 target_port_id; + u64 device_id; +}; + +#define MSG_UART_DP 0x0e +struct uart_device_path { + struct efi_device_path header; + u32 Reserved; + u64 baud_rate; + u8 data_bits; + u8 Parity; + u8 stop_bits; +}; + +#define MSG_VENDOR_DP 0x0a +/* Use VENDOR_DEVICE_PATH struct */ + +#define DEVICE_PATH_MESSAGING_PC_ANSI \ + { 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define DEVICE_PATH_MESSAGING_VT_100 \ + { 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define DEVICE_PATH_MESSAGING_VT_100_PLUS \ + { 0x7baec70b , 0x57e0 , 0x4c76 , { 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 } } + +#define DEVICE_PATH_MESSAGING_VT_UTF8 \ + { 0xad15a0d6 , 0x8bec , 0x4acf , { 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 } } + +#define EFI_PC_ANSI_GUID \ + { 0xe0c14753 , 0xf9be , 0x11d2 , 0x9a , 0x0c , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d } + +#define EFI_VT_100_GUID \ + { 0xdfa66065 , 0xb419 , 0x11d3 , 0x9a , 0x2d , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d } + +#define EFI_VT_100_PLUS_GUID \ + { 0x7baec70b , 0x57e0 , 0x4c76 , 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 } + +#define EFI_VT_UTF8_GUID \ + { 0xad15a0d6 , 0x8bec , 0x4acf , 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 } + +/* + * Media Device Path (UEFI 2.4 specification, version 2.4 § 9.3.6.) + */ +#define MEDIA_DEVICE_PATH 0x04 + +#define MEDIA_HARDDRIVE_DP 0x01 +struct harddrive_device_path { + struct efi_device_path header; + u32 partition_number; + u64 partition_start; + u64 partition_size; + u8 signature[16]; + u8 mbr_type; + u8 signature_type; +}; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +#define MEDIA_CDROM_DP 0x02 +struct cdrom_device_path { + struct efi_device_path header; + u32 boot_entry; + u64 partition_start; + u64 partition_size; +}; + +#define MEDIA_VENDOR_DP 0x03 +/* Use VENDOR_DEVICE_PATH struct */ + +#define MEDIA_FILEPATH_DP 0x04 +struct filepath_device_path { + struct efi_device_path header; + s16 path_name[1]; +}; + +#define SIZE_OF_FILEPATH_DEVICE_PATH offsetof(FILEPATH_DEVICE_PATH,path_name) + +#define MEDIA_PROTOCOL_DP 0x05 +struct media_protocol_device_path { + struct efi_device_path header; + efi_guid_t Protocol; +}; + +/** + * PIWG Firmware File sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.6.6. + */ +#define MEDIA_PIWG_FW_FILE_DP 6 +struct media_fw_vol_filepath_device_path { + struct efi_device_path header; + efi_guid_t fv_file_name; +}; + +/** + * PIWG Firmware Volume Device Path sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.6.7. + */ +#define MEDIA_PIWG_FW_VOL_DP 7 +struct media_fw_vol_device_path { + struct efi_device_path header; + efi_guid_t fv_name; +}; + +/** + * Media relative offset range device path. + * UEFI 2.0 specification version 2.4 § 9.3.6.8. + */ +#define MEDIA_RELATIVE_OFFSET_RANGE_DP 8 +struct media_relative_offset_range_device_path { + struct efi_device_path header; + u32 Reserved; + u64 starting_offset; + u64 ending_offset; +}; + +/* + * BIOS Boot Specification Device Path (UEFI 2.4 specification, version 2.4 § 9.3.7.) + */ +#define BBS_DEVICE_PATH 0x05 + +#define BBS_BBS_DP 0x01 +struct bbs_bbs_device_path { + struct efi_device_path header; + u16 device_type; + u16 status_flag; + s8 String[1]; +}; + +/* device_type definitions - from BBS specification */ +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_DEV 0x80 +#define BBS_TYPE_UNKNOWN 0x_fF + +struct efi_device_path end_device_path = { + .type = END_DEVICE_PATH_TYPE, + .sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE, + .length = END_DEVICE_PATH_LENGTH, +}; + +struct efi_device_path end_instance_device_path = { + .type = END_DEVICE_PATH_TYPE, + .sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE, + .length = END_DEVICE_PATH_LENGTH, +}; + +unsigned long +device_path_size(struct efi_device_path *dev_path) +{ + struct efi_device_path *Start; + + Start = dev_path; + while (!is_device_path_end(dev_path)) + dev_path = next_device_path_node(dev_path); + + return ((unsigned long) dev_path - (unsigned long) Start) + + sizeof (struct efi_device_path); +} + +struct efi_device_path * +duplicate_device_path(struct efi_device_path *dev_path) +{ + struct efi_device_path *new_dev_path; + unsigned long Size; + + Size = device_path_size(dev_path); + + new_dev_path = malloc(Size); + if (new_dev_path) + memcpy(new_dev_path, dev_path, Size); + + return new_dev_path; +} + +struct efi_device_path * +device_path_from_handle(efi_handle_t Handle) +{ + efi_status_t Status; + struct efi_device_path *device_path; + + Status = BS->handle_protocol(Handle, &efi_device_path_protocol_guid, + (void *) &device_path); + if (EFI_ERROR(Status)) + device_path = NULL; + + return device_path; +} + +struct efi_device_path * +device_path_instance(struct efi_device_path **device_path, unsigned long *Size) +{ + struct efi_device_path *Start, *Next, *dev_path; + unsigned long Count; + + dev_path = *device_path; + Start = dev_path; + + if (!dev_path) + return NULL; + + for (Count = 0;; Count++) { + Next = next_device_path_node(dev_path); + + if (is_device_path_end_type(dev_path)) + break; + + dev_path = Next; + } + + if (dev_path->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE) + Next = NULL; + + *device_path = Next; + + *Size = ((u8 *) dev_path) - ((u8 *) Start); + + return Start; +} + +unsigned long +device_path_instance_count(struct efi_device_path *device_path) +{ + unsigned long Count, Size; + + Count = 0; + while (device_path_instance(&device_path, &Size)) { + Count += 1; + } + + return Count; +} + +struct efi_device_path * +append_device_path(struct efi_device_path *Src1, struct efi_device_path *Src2) +/* + * Src1 may have multiple "instances" and each instance is appended + * Src2 is appended to each instance is Src1. (E.g., it's possible + * to append a new instance to the complete device path by passing + * it in Src2) + */ +{ + unsigned long src1_size, src1_inst, src2_size, Size; + struct efi_device_path *Dst, *Inst; + u8 *dst_pos; + + if (!Src1) + return duplicate_device_path(Src2); + + if (!Src2) { + return duplicate_device_path(Src1); + } + + src1_size = device_path_size(Src1); + src1_inst = device_path_instance_count(Src1); + src2_size = device_path_size(Src2); + Size = src1_size * src1_inst + src2_size; + + Dst = malloc(Size); + if (Dst) { + dst_pos = (u8 *) Dst; + + /* Copy all device path instances */ + + while ((Inst = device_path_instance(&Src1, &Size))) { + + memcpy(dst_pos, Inst, Size); + dst_pos += Size; + + memcpy(dst_pos, Src2, src2_size); + dst_pos += src2_size; + + memcpy(dst_pos, &end_instance_device_path, + sizeof (struct efi_device_path)); + dst_pos += sizeof (struct efi_device_path); + } + + /* Change last end marker */ + dst_pos -= sizeof (struct efi_device_path); + memcpy(dst_pos, &end_device_path, + sizeof (struct efi_device_path)); + } + + return Dst; +} + +struct efi_device_path * +append_device_path_node(struct efi_device_path *Src1, + struct efi_device_path *Src2) +/* + * Src1 may have multiple "instances" and each instance is appended + * Src2 is a signal device path node (without a terminator) that is + * appended to each instance is Src1. + */ +{ + struct efi_device_path *Temp, *Eop; + unsigned long length; + + /* Build a Src2 that has a terminator on it */ + + length = Src2->length; + Temp = malloc(length + sizeof (struct efi_device_path)); + if (!Temp) + return NULL; + + memcpy(Temp, Src2, length); + Eop = next_device_path_node(Temp); + set_device_path_end_node(Eop); + + /* Append device paths */ + + Src1 = append_device_path(Src1, Temp); + free(Temp); + return Src1; +} + +struct efi_device_path * +unpack_device_path(struct efi_device_path *dev_path) +{ + struct efi_device_path *Src, *Dest, *new_path; + unsigned long Size; + + /* Walk device path and round sizes to valid boundries */ + + Src = dev_path; + Size = 0; + for (;;) { + Size += Src->length; + Size += ALIGN_SIZE(Size); + + if (is_device_path_end(Src)) { + break; + } + + Src = next_device_path_node(Src); + } + + new_path = xzalloc(Size); + + Src = dev_path; + Dest = new_path; + for (;;) { + Size = Src->length; + memcpy(Dest, Src, Size); + Size += ALIGN_SIZE(Size); + Dest->length = Size; + Dest->type |= EFI_DP_TYPE_UNPACKED; + Dest = + (struct efi_device_path *) (((u8 *) Dest) + Size); + + if (is_device_path_end(Src)) + break; + + Src = next_device_path_node(Src); + } + + return new_path; +} + +struct efi_device_path * +append_device_path_instance(struct efi_device_path *Src, + struct efi_device_path *Instance) +{ + u8 *Ptr; + struct efi_device_path *dev_path; + unsigned long src_size; + unsigned long instance_size; + + if (Src == NULL) + return duplicate_device_path(Instance); + + src_size = device_path_size(Src); + instance_size = device_path_size(Instance); + Ptr = malloc(src_size + instance_size); + dev_path = (struct efi_device_path *) Ptr; + + memcpy(Ptr, Src, src_size); + + while (!is_device_path_end(dev_path)) + dev_path = next_device_path_node(dev_path); + + /* + * Convert the End to an End Instance, since we are + * appending another instacne after this one its a good + * idea. + */ + dev_path->sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE; + + dev_path = next_device_path_node(dev_path); + memcpy(dev_path, Instance, instance_size); + + return (struct efi_device_path *) Ptr; +} + +efi_status_t +lib_device_path_to_interface(efi_guid_t * Protocol, + struct efi_device_path *file_path, + void **Interface) +{ + efi_status_t Status; + efi_handle_t Device; + + Status = BS->locate_device_path(Protocol, &file_path, &Device); + + if (!EFI_ERROR(Status)) { + + /* If we didn't get a direct match return not found */ + Status = EFI_NOT_FOUND; + + if (is_device_path_end(file_path)) { + + /* It was a direct match, lookup the protocol interface */ + + Status = + BS->handle_protocol(Device, Protocol, Interface); + } + } + + if (EFI_ERROR(Status)) + *Interface = NULL; + + return Status; +} + +static void +dev_path_pci(struct string *str, void *dev_path) +{ + struct pci_device_path *Pci; + + Pci = dev_path; + cprintf(str, "Pci(0x%x,0x%x)", Pci->Device, Pci->Function); +} + +static void +dev_path_pccard(struct string *str, void *dev_path) +{ + struct pccard_device_path *Pccard; + + Pccard = dev_path; + cprintf(str, "Pccard(0x%x)", Pccard->function_number); +} + +static void +dev_path_mem_map(struct string *str, void *dev_path) +{ + struct memmap_device_path *mem_map; + + mem_map = dev_path; + cprintf(str, "mem_map(%d,0x%llx,0x%llx)", + mem_map->memory_type, + mem_map->starting_address, mem_map->ending_address); +} + +static void +dev_path_controller(struct string *str, void *dev_path) +{ + struct controller_device_path *Controller; + + Controller = dev_path; + cprintf(str, "Ctrl(%d)", Controller->Controller); +} + +static void +dev_path_vendor(struct string *str, void *dev_path) +{ + struct vendor_device_path *Vendor; + char *type; + struct unknown_device_vendor_device_path *unknown_dev_path; + + Vendor = dev_path; + switch (device_path_type(&Vendor->header)) { + case HARDWARE_DEVICE_PATH: + type = "Hw"; + break; + case MESSAGING_DEVICE_PATH: + type = "Msg"; + break; + case MEDIA_DEVICE_PATH: + type = "Media"; + break; + default: + type = "?"; + break; + } + + cprintf(str, "Ven%s(%pU", type, &Vendor->Guid); + if (efi_compare_guid(&Vendor->Guid, &efi_unknown_device_guid) == 0) { + /* GUID used by EFI to enumerate an EDD 1.1 device */ + unknown_dev_path = + (struct unknown_device_vendor_device_path *) Vendor; + cprintf(str, ":%02x)", unknown_dev_path->legacy_drive_letter); + } else { + cprintf(str, ")"); + } +} + +/* + type: 2 (ACPI Device Path) sub_type: 1 (ACPI Device Path) + */ +static void +dev_path_acpi(struct string *str, void *dev_path) +{ + struct acpi_hid_device_path *Acpi; + + Acpi = dev_path; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + switch (EISA_ID_TO_NUM(Acpi->HID)) { + case 0x301: + cprintf(str, "Keyboard(%d)", Acpi->UID); + break; + + case 0x401: + cprintf(str, "parallel_port(%d)", Acpi->UID); + break; + case 0x501: + cprintf(str, "Serial(%d)", Acpi->UID); + break; + case 0x604: + cprintf(str, "Floppy(%d)", Acpi->UID); + break; + case 0xa03: + cprintf(str, "pci_root(%d)", Acpi->UID); + break; + case 0xa08: + cprintf(str, "pcie_root(%d)", Acpi->UID); + break; + default: + cprintf(str, "Acpi(PNP%04x", + EISA_ID_TO_NUM(Acpi->HID)); + if (Acpi->UID) + cprintf(str, ",%d", Acpi->UID); + cprintf(str, ")"); + break; + } + } else { + cprintf(str, "Acpi(0x%X", Acpi->HID); + if (Acpi->UID) + cprintf(str, ",%d", Acpi->UID); + cprintf(str, ")"); + } +} + +static void +dev_path_atapi(struct string *str, void *dev_path) +{ + struct atapi_device_path *Atapi; + + Atapi = dev_path; + cprintf(str, "Ata(%s,%s)", + Atapi->primary_secondary ? "Secondary" : "Primary", + Atapi->slave_master ? "Slave" : "Master"); +} + +static void +dev_path_scsi(struct string *str, void *dev_path) +{ + struct scsi_device_path *Scsi; + + Scsi = dev_path; + cprintf(str, "Scsi(%d,%d)", Scsi->Pun, Scsi->Lun); +} + +static void +dev_path_fibre(struct string *str, void *dev_path) +{ + struct fibrechannel_device_path *Fibre; + + Fibre = dev_path; + cprintf(str, "Fibre%s(0x%016llx,0x%016llx)", + device_path_type(&Fibre->header) == + MSG_FIBRECHANNEL_DP ? "" : "Ex", Fibre->WWN, Fibre->Lun); +} + +static void +dev_path1394(struct string *str, void *dev_path) +{ + struct f1394_device_path *F1394; + + F1394 = dev_path; + cprintf(str, "1394(%pU)", &F1394->Guid); +} + +static void +dev_path_usb(struct string *str, void *dev_path) +{ + struct usb_device_path *Usb; + + Usb = dev_path; + cprintf(str, "Usb(0x%x,0x%x)", Usb->Port, Usb->Endpoint); +} + +static void +dev_path_i2_o(struct string *str, void *dev_path) +{ + struct i2_o_device_path *i2_o; + + i2_o = dev_path; + cprintf(str, "i2_o(0x%X)", i2_o->Tid); +} + +static void +dev_path_mac_addr(struct string *str, void *dev_path) +{ + struct mac_addr_device_path *MAC; + unsigned long hw_address_size; + unsigned long Index; + + MAC = dev_path; + + /* hw_address_size = sizeof(EFI_MAC_ADDRESS); */ + hw_address_size = MAC->header.length; + hw_address_size -= sizeof (MAC->header); + hw_address_size -= sizeof (MAC->if_type); + if (MAC->if_type == 0x01 || MAC->if_type == 0x00) + hw_address_size = 6; + + cprintf(str, "Mac("); + + for (Index = 0; Index < hw_address_size; Index++) + cprintf(str, "%02x", MAC->mac_address.Addr[Index]); + + if (MAC->if_type != 0) + cprintf(str, ",%d", MAC->if_type); + + cprintf(str, ")"); +} + +static void +cat_print_iPv4(struct string *str, efi_ipv4_address * address) +{ + cprintf(str, "%d.%d.%d.%d", address->Addr[0], address->Addr[1], + address->Addr[2], address->Addr[3]); +} + +static bool +is_not_null_iPv4(efi_ipv4_address * address) +{ + u8 val; + + val = address->Addr[0] | address->Addr[1]; + val |= address->Addr[2] | address->Addr[3]; + + return val != 0; +} + +static void +cat_print_network_protocol(struct string *str, u16 Proto) +{ + if (Proto == 6) + cprintf(str, "TCP"); + else if (Proto == 17) + cprintf(str, "UDP"); + else + cprintf(str, "%d", Proto); +} + +static void +dev_path_iPv4(struct string *str, void *dev_path) +{ + struct ipv4_device_path *ip; + bool show; + + ip = dev_path; + cprintf(str, "IPv4("); + cat_print_iPv4(str, &ip->remote_ip_address); + cprintf(str, ","); + cat_print_network_protocol(str, ip->Protocol); + cprintf(str, ",%s", ip->static_ip_address ? "Static" : "DHCP"); + show = is_not_null_iPv4(&ip->local_ip_address); + if (!show + && ip->header.length == + sizeof (struct ipv4_device_path)) { + /* only version 2 includes gateway and netmask */ + show |= is_not_null_iPv4(&ip->gateway_ip_address); + show |= is_not_null_iPv4(&ip->subnet_mask); + } + if (show) { + cprintf(str, ","); + cat_print_iPv4(str, &ip->local_ip_address); + if (ip->header.length == + sizeof (struct ipv4_device_path)) { + /* only version 2 includes gateway and netmask */ + show = is_not_null_iPv4(&ip->gateway_ip_address); + show |= is_not_null_iPv4(&ip->subnet_mask); + if (show) { + cprintf(str, ","); + cat_print_iPv4(str, &ip->gateway_ip_address); + if (is_not_null_iPv4(&ip->subnet_mask)) { + cprintf(str, ","); + cat_print_iPv4(str, &ip->subnet_mask); + } + } + } + } + cprintf(str, ")"); +} + +#define cat_print_iPv6_ADD( x , y ) ( ( (u16) ( x ) ) << 8 | ( y ) ) +static void +cat_print_ipv6(struct string *str, efi_ipv6_address * address) +{ + cprintf(str, "%x:%x:%x:%x:%x:%x:%x:%x", + cat_print_iPv6_ADD(address->Addr[0], address->Addr[1]), + cat_print_iPv6_ADD(address->Addr[2], address->Addr[3]), + cat_print_iPv6_ADD(address->Addr[4], address->Addr[5]), + cat_print_iPv6_ADD(address->Addr[6], address->Addr[7]), + cat_print_iPv6_ADD(address->Addr[8], address->Addr[9]), + cat_print_iPv6_ADD(address->Addr[10], address->Addr[11]), + cat_print_iPv6_ADD(address->Addr[12], address->Addr[13]), + cat_print_iPv6_ADD(address->Addr[14], address->Addr[15])); +} + +static void +dev_path_iPv6(struct string *str, void *dev_path) +{ + struct ipv6_device_path *ip; + + ip = dev_path; + cprintf(str, "IPv6("); + cat_print_ipv6(str, &ip->remote_ip_address); + cprintf(str, ","); + cat_print_network_protocol(str, ip->Protocol); + cprintf(str, ",%s,", ip->IPAddress_origin ? + (ip->IPAddress_origin == 1 ? "stateless_auto_configure" : + "stateful_auto_configure") : "Static"); + cat_print_ipv6(str, &ip->local_ip_address); + if (ip->header.length == + sizeof (struct ipv6_device_path)) { + cprintf(str, ","); + cat_print_ipv6(str, &ip->gateway_ip_address); + cprintf(str, ","); + cprintf(str, "%d", ip->prefix_length); + } + cprintf(str, ")"); +} + +static void +dev_path_infini_band(struct string *str, void *dev_path) +{ + struct infiniband_device_path *infini_band; + + infini_band = dev_path; + cprintf(str, "Infiniband(0x%x,%pU,0x%llx,0x%llx,0x%llx)", + infini_band->resource_flags, &infini_band->port_gid, + infini_band->service_id, infini_band->target_port_id, + infini_band->device_id); +} + +static void +dev_path_uart(struct string *str, void *dev_path) +{ + struct uart_device_path *Uart; + s8 Parity; + + Uart = dev_path; + switch (Uart->Parity) { + case 0: + Parity = 'D'; + break; + case 1: + Parity = 'N'; + break; + case 2: + Parity = 'E'; + break; + case 3: + Parity = 'O'; + break; + case 4: + Parity = 'M'; + break; + case 5: + Parity = 'S'; + break; + default: + Parity = 'x'; + break; + } + + if (Uart->baud_rate == 0) + cprintf(str, "Uart(DEFAULT %c", Parity); + else + cprintf(str, "Uart(%lld %c", Uart->baud_rate, Parity); + + if (Uart->data_bits == 0) + cprintf(str, "D"); + else + cprintf(str, "%d", Uart->data_bits); + + switch (Uart->stop_bits) { + case 0: + cprintf(str, "D)"); + break; + case 1: + cprintf(str, "1)"); + break; + case 2: + cprintf(str, "1.5)"); + break; + case 3: + cprintf(str, "2)"); + break; + default: + cprintf(str, "x)"); + break; + } +} + +static void +dev_path_sata(struct string *str, void *dev_path) +{ + struct sata_device_path *sata; + + sata = dev_path; + cprintf(str, "Sata(0x%x,0x%x,0x%x)", sata->HBAPort_number, + sata->port_multiplier_port_number, sata->Lun); +} + +static void +dev_path_hard_drive(struct string *str, void *dev_path) +{ + struct harddrive_device_path *hd; + + hd = dev_path; + switch (hd->signature_type) { + case SIGNATURE_TYPE_MBR: + cprintf(str, "HD(Part%d,Sig%08x)", + hd->partition_number, *((u32 *) (&(hd->signature[0]))) + ); + break; + case SIGNATURE_TYPE_GUID: + cprintf(str, "HD(Part%d,Sig%pU)", + hd->partition_number, + (efi_guid_t *) & (hd->signature[0]) + ); + break; + default: + cprintf(str, "HD(Part%d,mbr_type=%02x,sig_type=%02x)", + hd->partition_number, hd->mbr_type, hd->signature_type); + break; + } +} + +static void +dev_path_cdrom(struct string *str, void *dev_path) +{ + struct cdrom_device_path *cd; + + cd = dev_path; + cprintf(str, "CDROM(0x%x)", cd->boot_entry); +} + +static void +dev_path_file_path(struct string *str, void *dev_path) +{ + struct filepath_device_path *Fp; + char *dst; + + Fp = dev_path; + + dst = strdup_wchar_to_char(Fp->path_name); + + cprintf(str, "%s", dst); + + free(dst); +} + +static void +dev_path_media_protocol(struct string *str, void *dev_path) +{ + struct media_protocol_device_path *media_prot; + + media_prot = dev_path; + cprintf(str, "%pU", &media_prot->Protocol); +} + +static void +dev_path_bss_bss(struct string *str, void *dev_path) +{ + struct bbs_bbs_device_path *Bss; + char *type; + + Bss = dev_path; + switch (Bss->device_type) { + case BBS_TYPE_FLOPPY: + type = "Floppy"; + break; + case BBS_TYPE_HARDDRIVE: + type = "Harddrive"; + break; + case BBS_TYPE_CDROM: + type = "CDROM"; + break; + case BBS_TYPE_PCMCIA: + type = "PCMCIA"; + break; + case BBS_TYPE_USB: + type = "Usb"; + break; + case BBS_TYPE_EMBEDDED_NETWORK: + type = "Net"; + break; + default: + type = "?"; + break; + } + + cprintf(str, "Bss-%s(%s)", type, Bss->String); +} + +static void +dev_path_end_instance(struct string *str, void *dev_path) +{ + cprintf(str, ","); +} + +/** + * Print unknown device node. + * UEFI 2.4 § 9.6.1.6 table 89. + */ + +static void +dev_path_node_unknown(struct string *str, void *dev_path) +{ + struct efi_device_path *Path; + u8 *value; + int length, index; + Path = dev_path; + value = dev_path; + value += 4; + switch (Path->type) { + case HARDWARE_DEVICE_PATH:{ + /* Unknown Hardware Device Path */ + cprintf(str, "hardware_path(%d", Path->sub_type); + break; + } + case ACPI_DEVICE_PATH:{/* Unknown ACPI Device Path */ + cprintf(str, "acpi_path(%d", Path->sub_type); + break; + } + case MESSAGING_DEVICE_PATH:{ + /* Unknown Messaging Device Path */ + cprintf(str, "Msg(%d", Path->sub_type); + break; + } + case MEDIA_DEVICE_PATH:{ + /* Unknown Media Device Path */ + cprintf(str, "media_path(%d", Path->sub_type); + break; + } + case BBS_DEVICE_PATH:{ /* Unknown BIOS Boot Specification Device Path */ + cprintf(str, "bbs_path(%d", Path->sub_type); + break; + } + default:{ /* Unknown Device Path */ + cprintf(str, "Path(%d,%d", Path->type, Path->sub_type); + break; + } + } + length = Path->length; + for (index = 0; index < length; index++) { + if (index == 0) + cprintf(str, ",0x"); + cprintf(str, "%02x", *value); + value++; + } + cprintf(str, ")"); +} + +/* + * Table to convert "type" and "sub_type" to a "convert to text" function/ + * Entries hold "type" and "sub_type" for know values. + * Special "sub_type" 0 is used as default for known type with unknown subtype. + */ +struct { + u8 type; + u8 sub_type; + void (*Function) (struct string *, void *); +} dev_path_table[] = { + { + HARDWARE_DEVICE_PATH, HW_PCI_DP, dev_path_pci}, { + HARDWARE_DEVICE_PATH, HW_PCCARD_DP, dev_path_pccard}, { + HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, dev_path_mem_map}, { + HARDWARE_DEVICE_PATH, HW_VENDOR_DP, dev_path_vendor}, { + HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, dev_path_controller}, { + ACPI_DEVICE_PATH, ACPI_DP, dev_path_acpi}, { + MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, dev_path_atapi}, { + MESSAGING_DEVICE_PATH, MSG_SCSI_DP, dev_path_scsi}, { + MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, dev_path_fibre}, { + MESSAGING_DEVICE_PATH, MSG_1394_DP, dev_path1394}, { + MESSAGING_DEVICE_PATH, MSG_USB_DP, dev_path_usb}, { + MESSAGING_DEVICE_PATH, MSG_I2_o_DP, dev_path_i2_o}, { + MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, dev_path_mac_addr}, { + MESSAGING_DEVICE_PATH, MSG_IPv4_DP, dev_path_iPv4}, { + MESSAGING_DEVICE_PATH, MSG_IPv6_DP, dev_path_iPv6}, { + MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, dev_path_infini_band}, { + MESSAGING_DEVICE_PATH, MSG_UART_DP, dev_path_uart}, { + MESSAGING_DEVICE_PATH, MSG_SATA_DP, dev_path_sata}, { + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, dev_path_vendor}, { + MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, dev_path_hard_drive}, { + MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, dev_path_cdrom}, { + MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, dev_path_vendor}, { + MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, dev_path_file_path}, { + MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, dev_path_media_protocol}, { + BBS_DEVICE_PATH, BBS_BBS_DP, dev_path_bss_bss}, { + END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, + dev_path_end_instance}, { + 0, 0, NULL} +}; + +static int __device_path_to_str(struct string *str, struct efi_device_path *dev_path) +{ + struct efi_device_path *dev_path_node; + void (*dump_node) (struct string *, void *); + int i; + + dev_path = unpack_device_path(dev_path); + + dev_path_node = dev_path; + while (!is_device_path_end(dev_path_node)) { + dump_node = NULL; + for (i = 0; dev_path_table[i].Function; i += 1) { + + if (device_path_type(dev_path_node) == + dev_path_table[i].type + && dev_path_node->sub_type == + dev_path_table[i].sub_type) { + dump_node = dev_path_table[i].Function; + break; + } + } + + if (!dump_node) + dump_node = dev_path_node_unknown; + + if (str->len && dump_node != dev_path_end_instance) + cprintf(str, "/"); + + dump_node(str, dev_path_node); + + dev_path_node = next_device_path_node(dev_path_node); + } + + return 0; +} + +char *device_path_to_str(struct efi_device_path *dev_path) +{ + struct string str = {}; + + __device_path_to_str(&str, dev_path); + + str.str = malloc(str.len + 1); + if (!str.str) + return NULL; + + str.len = 0; + + __device_path_to_str(&str, dev_path); + + return str.str; +} diff --git a/common/efi-guid.c b/common/efi-guid.c new file mode 100644 index 0000000000..5109b5da04 --- /dev/null +++ b/common/efi-guid.c @@ -0,0 +1,11 @@ +#include +#include + +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; diff --git a/common/memory.c b/common/memory.c index 7dbd7f4399..4a8fe283f2 100644 --- a/common/memory.c +++ b/common/memory.c @@ -58,7 +58,7 @@ void mem_malloc_init(void *start, void *end) #endif } -#ifndef __SANDBOX__ +#if !defined __SANDBOX__ && !defined CONFIG_ARCH_EFI static int mem_malloc_resource(void) { /* diff --git a/common/partitions/efi.c b/common/partitions/efi.c index ee1326e622..dcb95414f6 100644 --- a/common/partitions/efi.c +++ b/common/partitions/efi.c @@ -232,7 +232,7 @@ static int is_gpt_valid(struct block_device *blk, u64 lba, static inline int is_pte_valid(const gpt_entry *pte, const u64 lastlba) { - if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) || + if ((!efi_guidcmp(pte->partition_type_guid, EFI_NULL_GUID)) || le64_to_cpu(pte->starting_lba) > lastlba || le64_to_cpu(pte->ending_lba) > lastlba) return 0; diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 45f77a759f..2b28cf3fb4 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -4,7 +4,7 @@ config OFTREE config OFTREE_MEM_GENERIC depends on OFTREE - depends on PPC || ARM + depends on PPC || ARM || ARCH_EFI def_bool y config DTC diff --git a/include/efi.h b/include/efi.h index 9911fa1e8c..f027712cd3 100644 --- a/include/efi.h +++ b/include/efi.h @@ -14,6 +14,14 @@ #include #include +#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 + +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; +}; -/* - * 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_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 */ -- cgit v1.2.3 From 62a123fb589178a41dff91db709696f04269ad76 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 7 Jul 2014 18:04:47 +0200 Subject: net: Add EFI Simple Network Protocol Driver This adds a network driver which uses the EFI Simple Network Protocol to implement networking for barebox. Signed-off-by: Sascha Hauer --- drivers/net/Kconfig | 4 + drivers/net/Makefile | 1 + drivers/net/efi-snp.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 301 insertions(+) create mode 100644 drivers/net/efi-snp.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5f0c41b151..43409a8f8c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -170,6 +170,10 @@ config DRIVER_NET_TAP bool "tap Ethernet driver" depends on LINUX +config DRIVER_NET_EFI_SNP + bool "EFI SNP ethernet driver" + depends on ARCH_EFI + config DRIVER_NET_TSE depends on NIOS2 bool "Altera TSE ethernet driver" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 33bb5c8fa0..1b85778f9f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o obj-$(CONFIG_DRIVER_NET_TAP) += tap.o obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o +obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o diff --git a/drivers/net/efi-snp.c b/drivers/net/efi-snp.c new file mode 100644 index 0000000000..5b96fbf462 --- /dev/null +++ b/drivers/net/efi-snp.c @@ -0,0 +1,296 @@ +/* + * efi-snp.c - Simple Network Protocol driver for EFI + * + * Copyright (c) 2014 Sascha Hauer , 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 +#include +#include +#include +#include +#include +#include +#include + +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); -- cgit v1.2.3 From e4caa90188430e1d527a40edb0e613b05900b243 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 7 Jul 2014 18:07:11 +0200 Subject: serial: Add EFI stdio driver This adds a driver which uses the EFI stdin/stdout interfaces to implement a barebox console. Keyboard input should be fairly complete, but not all vt100 needed by barebox work properly. The clear-to-eol escape is missing causing garbled output in the editor. Signed-off-by: Sascha Hauer --- commands/edit.c | 11 +- drivers/serial/Kconfig | 4 + drivers/serial/Makefile | 1 + drivers/serial/efi-stdio.c | 367 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 drivers/serial/efi-stdio.c diff --git a/commands/edit.c b/commands/edit.c index 5a2da7d034..98af583574 100644 --- a/commands/edit.c +++ b/commands/edit.c @@ -379,7 +379,16 @@ static int do_edit(int argc, char *argv[]) return COMMAND_ERROR_USAGE; screenwidth = 80; - screenheight = 25; + + /* + * The EFI simple text output protocol wraps to the next line and scrolls + * down when we write to the right bottom screen position. Reduce the number + * of rows by one to work around this. + */ + if (IS_ENABLED(CONFIG_ARCH_EFI)) + screenheight = 24; + else + screenheight = 25; /* check if we are called as "sedit" instead of "edit" */ if (*argv[0] == 's') { diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index f51c6e6b02..5698c2fe78 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -45,6 +45,10 @@ config DRIVER_SERIAL_LINUX_CONSOLE default y bool "linux console driver" +config DRIVER_SERIAL_EFI_STDIO + depends on ARCH_EFI + bool "EFI stdio driver" + config DRIVER_SERIAL_MPC5XXX depends on MPC5200 default y diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index e1865f725a..2c0176dd9c 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o obj-$(CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT) += serial_omap4_usbboot.o obj-$(CONFIG_DRIVER_SERIAL_AUART) += serial_auart.o obj-$(CONFIG_DRIVER_SERIAL_CADENCE) += serial_cadence.o +obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO) += efi-stdio.o diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c new file mode 100644 index 0000000000..bf14c5e24a --- /dev/null +++ b/drivers/serial/efi-stdio.c @@ -0,0 +1,367 @@ +/* + * efi_console.c - EFI console support + * + * Copyright (c) 2014 Sascha Hauer , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); -- cgit v1.2.3 From d6e62b225b89c4dcc715b839eefbde1254f67be7 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 7 Jul 2014 18:12:42 +0200 Subject: fs: implement EFI filesystem driver This implements a filesystem driver which uses the EFI Simple File System Protocol to provide files from EFI to barebox. Signed-off-by: Sascha Hauer --- fs/Kconfig | 8 + fs/Makefile | 1 + fs/efi.c | 563 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 572 insertions(+) create mode 100644 fs/efi.c diff --git a/fs/Kconfig b/fs/Kconfig index 3724b34f9a..21690de196 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -41,6 +41,14 @@ config FS_NFS bool prompt "nfs support" +config FS_EFI + depends on ARCH_EFI + bool + prompt "EFI filesystem support" + help + This filesystem driver provides access to the filesystems provided + by the EFI Firmware via the EFI Simple File System Protocol. + source fs/fat/Kconfig source fs/ubifs/Kconfig diff --git a/fs/Makefile b/fs/Makefile index d3465edfa5..f02785176c 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_FS_OMAP4_USBBOOT) += omap4_usbbootfs.o obj-$(CONFIG_FS_NFS) += nfs.o parseopt.o obj-$(CONFIG_FS_BPKFS) += bpkfs.o obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o +obj-$(CONFIG_FS_EFI) += efi.o diff --git a/fs/efi.c b/fs/efi.c new file mode 100644 index 0000000000..f096f91f58 --- /dev/null +++ b/fs/efi.c @@ -0,0 +1,563 @@ +/* + * efi.c - EFI filesystem mirror driver + * + * Copyright (c) 2014 Sascha Hauer , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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); -- cgit v1.2.3 From ef4f9d77b72c2349e7dfcdb2de9f60ed758e1888 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 7 Jul 2014 18:15:17 +0200 Subject: fs: implement EFI variable filesystem driver This implements a filesystem for accessing EFI variables. It is compatible to the Linux Kernel efivarfs filesystem. Currently the variables can only be accessed readonly. Signed-off-by: Sascha Hauer --- fs/Kconfig | 7 ++ fs/Makefile | 1 + fs/efivarfs.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 348 insertions(+) create mode 100644 fs/efivarfs.c diff --git a/fs/Kconfig b/fs/Kconfig index 21690de196..64fc1176a6 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -49,6 +49,13 @@ config FS_EFI This filesystem driver provides access to the filesystems provided by the EFI Firmware via the EFI Simple File System Protocol. +config FS_EFIVARFS + depends on ARCH_EFI + bool + prompt "EFI variable filesystem support (efivarfs)" + help + This filesystem driver provides access to EFI variables. + source fs/fat/Kconfig source fs/ubifs/Kconfig diff --git a/fs/Makefile b/fs/Makefile index f02785176c..f5aae91a60 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_FS_NFS) += nfs.o parseopt.o obj-$(CONFIG_FS_BPKFS) += bpkfs.o obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o obj-$(CONFIG_FS_EFI) += efi.o +obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o diff --git a/fs/efivarfs.c b/fs/efivarfs.c new file mode 100644 index 0000000000..58c637ef19 --- /dev/null +++ b/fs/efivarfs.c @@ -0,0 +1,340 @@ +/* + * ramfs.c - a malloc based filesystem + * + * Copyright (c) 2007 Sascha Hauer , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); -- cgit v1.2.3 From 9183a8c683014f7f6dae004009556c9c0d4d2a15 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 8 Jul 2014 18:38:34 +0200 Subject: EFI: introduce efi_strguid to convert GUID to human readable names use in devinfo Protocols Tested today on qemu with all the GUID translated Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/efi/efi/efi-device.c | 3 +- arch/efi/efi/efi.c | 5 ++- common/efi-guid.c | 73 +++++++++++++++++++++++++++++++ include/efi.h | 108 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 3 deletions(-) diff --git a/arch/efi/efi/efi-device.c b/arch/efi/efi/efi-device.c index 71526b999f..1c9553d906 100644 --- a/arch/efi/efi/efi-device.c +++ b/arch/efi/efi/efi-device.c @@ -86,7 +86,8 @@ static void efi_devinfo(struct device_d *dev) printf("Protocols:\n"); for (i = 0; i < efidev->num_guids; i++) - printf(" %d: %pUl\n", i, &efidev->guids[i]); + printf(" %d: %pUl: %s\n", i, &efidev->guids[i], + efi_guid_string(&efidev->guids[i])); } static efi_handle_t *efi_find_parent(efi_handle_t *handle) diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c index 48b7d9a438..ff97783b13 100644 --- a/arch/efi/efi/efi.c +++ b/arch/efi/efi/efi.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -233,6 +234,8 @@ static struct NS16550_plat ns16550_plat = { static int efi_console_init(void) { + barebox_set_model("barebox EFI payload"); + add_generic_device("efi-stdio", DEVICE_ID_SINGLE, NULL, 0 , 0, 0, NULL); if (IS_ENABLED(CONFIG_ARCH_EFI_REGISTER_COM1)) @@ -296,8 +299,6 @@ static void fixup_tables(void) static int efi_init(void) { - barebox_set_model("barebox EFI payload"); - defaultenv_append_directory(env_efi); return 0; diff --git a/common/efi-guid.c b/common/efi-guid.c index 5109b5da04..f6b0404105 100644 --- a/common/efi-guid.c +++ b/common/efi-guid.c @@ -9,3 +9,76 @@ efi_guid_t efi_unknown_device_guid = EFI_UNKNOWN_DEVICE_GUID; efi_guid_t efi_null_guid = EFI_NULL_GUID; efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; efi_guid_t efi_block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID; + +#define EFI_GUID_STRING(guid, short, long) do { \ + if (!efi_guidcmp(guid, *g)) \ + return long; \ + } while(0) + +const char *efi_guid_string(efi_guid_t *g) +{ + EFI_GUID_STRING(EFI_NULL_GUID, "NULL", "NULL GUID"); + EFI_GUID_STRING(EFI_MPS_TABLE_GUID, "MPS Table", "MPS Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_ACPI_TABLE_GUID, "ACPI Table", "ACPI 1.0 Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_ACPI_20_TABLE_GUID, "ACPI 2.0 Table", "ACPI 2.0 Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_SMBIOS_TABLE_GUID, "SMBIOS Table", "SMBIOS Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_SAL_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_HCDP_TABLE_GUID, "HDCP Table", "HDCP Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol"); + EFI_GUID_STRING(EFI_GLOBAL_VARIABLE_GUID, "Efi", "Efi Variable GUID"); + EFI_GUID_STRING(EFI_UV_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_LINUX_EFI_CRASH_GUID, "Linux EFI Crash", "Linux EFI Crash GUID"); + EFI_GUID_STRING(EFI_LOADED_IMAGE_PROTOCOL_GUID, "LoadedImage Protocol", "EFI 1.0 Loaded Image Protocol"); + EFI_GUID_STRING(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, "EFI Graphics Output Protocol", "UEFI Graphics Output Protocol"); + EFI_GUID_STRING(EFI_UGA_PROTOCOL_GUID, "UGA Draw Protocol", "EFI 1.1 UGA Draw Protocol"); + EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol"); + EFI_GUID_STRING(EFI_PCI_IO_PROTOCOL_GUID, "PCI IO Protocol", "EFI 1.1 PCI IO Protocol"); + EFI_GUID_STRING(EFI_FILE_INFO_GUID, "File Info", "EFI File Infom"); + EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_GUID, "Filesystem", "EFI 1.0 Simple FileSystem"); + EFI_GUID_STRING(EFI_DEVICE_TREE_GUID, "Device Tree", "EFI Device Tree GUID"); + EFI_GUID_STRING(EFI_DEVICE_PATH_PROTOCOL_GUID, "Device Path Protocol", "EFI 1.0 Device Path protocol"); + EFI_GUID_STRING(EFI_SIMPLE_NETWORK_PROTOCOL_GUID, "Simple Network Protocol", "EFI 1.0 Simple Network Protocol"); + EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "Filesystem Protocol", "EFI 1.0 Simple FileSystem Protocol"); + EFI_GUID_STRING(EFI_UNKNOWN_DEVICE_GUID, "Efi Unknown Device", "Efi Unknown Device GUID"); + EFI_GUID_STRING(EFI_BLOCK_IO_PROTOCOL_GUID, "BlockIo Protocol", "EFI 1.0 Block IO protocol"); + + EFI_GUID_STRING(EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID, "FirmwareVolume2Protocol", "Efi FirmwareVolume2Protocol"); + EFI_GUID_STRING(EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID, "FirmwareVolumeBlock Protocol", "Firmware Volume Block protocol"); + EFI_GUID_STRING(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID, "PciRootBridgeIo Protocol", "EFI 1.1 Pci Root Bridge IO Protocol"); + EFI_GUID_STRING(EFI_ISA_ACPI_PROTOCOL_GUID, "ISA Acpi Protocol", "ISA Acpi Protocol"); + EFI_GUID_STRING(EFI_ISA_IO_PROTOCOL_GUID, "ISA IO Protocol", "ISA IO Protocol"); + EFI_GUID_STRING(EFI_STANDARD_ERROR_DEVICE_GUID, "Standard Error Device Guid", "EFI Standard Error Device Guid"); + EFI_GUID_STRING(EFI_CONSOLE_OUT_DEVICE_GUID, "Console Out Device Guid", "EFI Console Out Device Guid"); + EFI_GUID_STRING(EFI_CONSOLE_IN_DEVICE_GUID, "Console In Device Guid", "EFI Conosle In Device Guid"); + EFI_GUID_STRING(EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID, "Simple Text Out Protocol", "EFI 1.0 Simple Text Out Protocol"); + EFI_GUID_STRING(EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, "Simple Text Input Ex Protocol", "UEFI 2.1 Simple Text Input Ex Protocol"); + EFI_GUID_STRING(EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID, "Simple Text In Protocol", "EFI 1.0 Simple Text In Protocol"); + EFI_GUID_STRING(EFI_DISK_IO_PROTOCOL_GUID, "DiskIo Protocol", "EFI 1.0 Disk IO Protocol"); + EFI_GUID_STRING(EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID, "IDE Controller Init Protocol", "Platform IDE Init Protocol"); + EFI_GUID_STRING(EFI_DISK_INFO_PROTOCOL_GUID, "Disk Info Protocol", "Disk Info Protocol"); + EFI_GUID_STRING(EFI_SERIAL_IO_PROTOCOL_GUID, "SerialIo Protocol", "EFI 1.0 Serial IO Protocol"); + EFI_GUID_STRING(EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID, "Bus Specific Driver Override Protocol", "EFI 1.1 Bus Specific Driver Override Protocol"); + EFI_GUID_STRING(EFI_LOAD_FILE2_PROTOCOL_GUID, "LoadFile2 Protocol", "EFI Load File 2 Protocol"); + EFI_GUID_STRING(EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP4 Service Binding Protocol", "MTFTP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_DHCP4_PROTOCOL_GUID, "DHCP4 Protocol", "DHCP4 Protocol"); + EFI_GUID_STRING(EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID, "UDP4 Service Binding Protocol", "UDP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID, "TCP4 Service Binding Protocol", "TCP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID, "IP4 Service Binding Protocol", "IP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_IP4_CONFIG_PROTOCOL_GUID, "Ip4Config Protocol", "Ip4Config Protocol"); + EFI_GUID_STRING(EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID, "ARP Service Binding Protocol", "ARP Service Binding Protocol"); + EFI_GUID_STRING(EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID, "Managed Network Service Binding Protocol", "Managed Network Service Binding Protocol"); + EFI_GUID_STRING(EFI_VLAN_CONFIG_PROTOCOL_GUID, "VlanConfig Protocol", "VlanConfig Protocol"); + EFI_GUID_STRING(EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID, "HII Config Access Protocol", "HII Config Access 2.1 protocol"); + EFI_GUID_STRING(LOAD_FILE_PROTOCOL_GUID, "LoadFile Protocol", "EFI 1.0 Load File Protocol"); + EFI_GUID_STRING(EFI_COMPONENT_NAME2_PROTOCOL_GUID, "Component Name2 Protocol", "UEFI 2.0 Component Name2 Protocol"); + EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31, "Network Interface Identifier Protocol_31", "EFI1.1 Network Interface Identifier Protocol"); + EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID, "Network Interface Identifier Protocol", "EFI Network Interface Identifier Protocol"); + + /* File */ + EFI_GUID_STRING(EFI_IDEBUSDXE_INF_GUID, "IdeBusDxe.inf", "EFI IdeBusDxe.inf File GUID"); + EFI_GUID_STRING(EFI_TERMINALDXE_INF_GUID, "TerminalDxe.inf", "EFI TerminalDxe.inf File GUID"); + EFI_GUID_STRING(EFI_ISCSIDXE_INF_GUID, "IScsiDxe.inf", "EFI IScsiDxe.inf File GUID"); + EFI_GUID_STRING(EFI_VLANCONFIGDXE_INF_GUID, "VlanConfigDxe.inf", "EFI VlanConfigDxe.inf File GUID"); + + return "unknown"; +} diff --git a/include/efi.h b/include/efi.h index f027712cd3..4ad9f69237 100644 --- a/include/efi.h +++ b/include/efi.h @@ -359,6 +359,112 @@ extern efi_runtime_services_t *RT; #define EFI_BLOCK_IO_PROTOCOL_GUID \ EFI_GUID(0x964e5b21, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) +/* additional GUID from EDK2 */ +#define EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID \ + EFI_GUID(0x220e73b6, 0x6bdb, 0x4413, 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a) + +#define EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID \ + EFI_GUID(0x8f644fa9, 0xe850, 0x4db1, 0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4) + +#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + EFI_GUID(0x2f707ebb, 0x4a1a, 0x11d4, 0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_ISA_ACPI_PROTOCOL_GUID \ + EFI_GUID(0x64a892dc, 0x5561, 0x4536, 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55) + +#define EFI_ISA_IO_PROTOCOL_GUID \ + EFI_GUID(0x7ee2bd44, 0x3da0, 0x11d4, 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_STANDARD_ERROR_DEVICE_GUID \ + EFI_GUID(0xd3b36f2d, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_CONSOLE_OUT_DEVICE_GUID \ + EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_CONSOLE_IN_DEVICE_GUID \ + EFI_GUID(0xd3b36f2b, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID \ + EFI_GUID(0x387477c2, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + EFI_GUID(0xdd9e7534, 0x7762, 0x4698, 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa) + +#define EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID \ + EFI_GUID(0x387477c1, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_DISK_IO_PROTOCOL_GUID \ + EFI_GUID(0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID \ + EFI_GUID(0xa1e37052, 0x80d9, 0x4e65, 0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9) + +#define EFI_DISK_INFO_PROTOCOL_GUID \ + EFI_GUID(0xd432a67f, 0x14dc, 0x484b, 0xb3, 0xbb, 0x3f, 0x2, 0x91, 0x84, 0x93, 0x27) + +#define EFI_SERIAL_IO_PROTOCOL_GUID \ + EFI_GUID(0xbb25cf6f, 0xf1d4, 0x11d2, 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0xfd) + +#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \ + EFI_GUID(0x3bc1b285, 0x8a15, 0x4a82, 0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65) + +#define EFI_LOAD_FILE2_PROTOCOL_GUID \ + EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d) + +#define EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0x2fe800be, 0x8f01, 0x4aa6, 0x94, 0x6b, 0xd7, 0x13, 0x88, 0xe1, 0x83, 0x3f) + +#define EFI_DHCP4_PROTOCOL_GUID \ + EFI_GUID(0x9d9a39d8, 0xbd42, 0x4a73, 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80) + +#define EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0x83f01464, 0x99bd, 0x45e5, 0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6) + +#define EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0x00720665, 0x67EB, 0x4a99, 0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9) + +#define EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0xc51711e7, 0xb4bf, 0x404a, 0xbf, 0xb8, 0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4) + +#define EFI_IP4_CONFIG_PROTOCOL_GUID \ + EFI_GUID(0x3b95aa31, 0x3793, 0x434b, 0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e) + +#define EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID\ + EFI_GUID(0xf44c00ee, 0x1f2c, 0x4a00, 0xaa, 0x9, 0x1c, 0x9f, 0x3e, 0x8, 0x0, 0xa3) + +#define EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0xf36ff770, 0xa7e1, 0x42cf, 0x9e, 0xd2, 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c) + +#define EFI_VLAN_CONFIG_PROTOCOL_GUID \ + EFI_GUID(0x9e23d768, 0xd2f3, 0x4366, 0x9f, 0xc3, 0x3a, 0x7a, 0xba, 0x86, 0x43, 0x74) + +#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \ + EFI_GUID(0x330d4706, 0xf2a0, 0x4e4f, 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85) + +#define LOAD_FILE_PROTOCOL_GUID \ + EFI_GUID(0x56ec3091, 0x954c, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \ + EFI_GUID(0x6a7a5cff, 0xe8d9, 0x4f70, 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14) + +#define EFI_IDEBUSDXE_INF_GUID \ + EFI_GUID(0x69fd8e47, 0xa161, 0x4550, 0xb0, 0x1a, 0x55, 0x94, 0xce, 0xb2, 0xb2, 0xb2) + +#define EFI_TERMINALDXE_INF_GUID \ + EFI_GUID(0x9e863906, 0xa40f, 0x4875, 0x97, 0x7f, 0x5b, 0x93, 0xff, 0x23, 0x7f, 0xc6) + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31 \ + EFI_GUID(0x1aced566, 0x76ed, 0x4218, 0xbc, 0x81, 0x76, 0x7f, 0x1f, 0x97, 0x7a, 0x89) + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \ + EFI_GUID(0xe18541cd, 0xf755, 0x4f73, 0x92, 0x8d, 0x64, 0x3c, 0x8a, 0x79, 0xb2, 0x29) + +#define EFI_ISCSIDXE_INF_GUID \ + EFI_GUID(0x4579b72d, 0x7ec4, 0x4dd4, 0x84, 0x86, 0x08, 0x3c, 0x86, 0xb1, 0x82, 0xa7) + +#define EFI_VLANCONFIGDXE_INF_GUID \ + EFI_GUID(0xe4f61863, 0xfe2c, 0x4b56, 0xa8, 0xf4, 0x08, 0x51, 0x9b, 0xc4, 0x39, 0xdf) + extern efi_guid_t efi_file_info_id; extern efi_guid_t efi_simple_file_system_protocol_guid; extern efi_guid_t efi_device_path_protocol_guid; @@ -510,4 +616,6 @@ static inline int efi_compare_guid(efi_guid_t *a, efi_guid_t *b) char *device_path_to_str(struct efi_device_path *dev_path); +const char *efi_guid_string(efi_guid_t *g); + #endif /* _LINUX_EFI_H */ -- cgit v1.2.3