diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h new file mode 100644 index 0000000..a8d1bdb --- /dev/null +++ b/arch/x86/include/asm/linkage.h @@ -0,0 +1,6 @@ +#ifndef __ASM_LINKAGE_H +#define __ASM_LINKAGE_H + +/* referenced by */ + +#endif diff --git a/arch/x86/mach-efi/reloc_x86_64.c b/arch/x86/mach-efi/reloc_x86_64.c index 1db72f5..e83bacb 100644 --- a/arch/x86/mach-efi/reloc_x86_64.c +++ b/arch/x86/mach-efi/reloc_x86_64.c @@ -35,11 +35,14 @@ SUCH DAMAGE. */ +#include #include #include #include +asmlinkage efi_status_t _relocate (long, Elf64_Dyn *, efi_handle_t, efi_system_table_t *); + efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab) { long relsz = 0, relent = 0; diff --git a/common/efi-devicepath.c b/common/efi-devicepath.c index 2472228..3db2cea 100644 --- a/common/efi-devicepath.c +++ b/common/efi-devicepath.c @@ -572,7 +572,7 @@ } cprintf(str, "Ven%s(%pU", type, &Vendor->Guid); - if (efi_compare_guid(&Vendor->Guid, &efi_unknown_device_guid) == 0) { + if (efi_guidcmp(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; diff --git a/common/efi-guid.c b/common/efi-guid.c index 1e45ccf..2bf2395 100644 --- a/common/efi-guid.c +++ b/common/efi-guid.c @@ -52,7 +52,7 @@ 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_CONSOLE_IN_DEVICE_GUID, "Console In Device Guid", "EFI Console 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"); diff --git a/common/efi/efi.c b/common/efi/efi.c index a7b25cb..73cea37 100644 --- a/common/efi/efi.c +++ b/common/efi/efi.c @@ -17,6 +17,7 @@ * */ +#include #include #include #include @@ -318,6 +319,8 @@ } device_initcall(efi_init); +asmlinkage efi_status_t efi_main(efi_handle_t, efi_system_table_t *); + /** * efi-main - Entry point for EFI images */ diff --git a/drivers/block/efi-block-io.c b/drivers/block/efi-block-io.c index d167d81..39dbfb0 100644 --- a/drivers/block/efi-block-io.c +++ b/drivers/block/efi-block-io.c @@ -14,6 +14,7 @@ #include #include #include +#include #define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 #define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31)) @@ -145,6 +146,7 @@ static int efi_bio_probe(struct efi_device *efidev) { int ret; + int instance; struct efi_bio_priv *priv; struct efi_block_io_media *media; @@ -159,10 +161,14 @@ efi_bio_print_info(priv); priv->dev = &efidev->dev; - if (is_bio_usbdev(efidev)) - priv->blk.cdev.name = xasprintf("usbdisk%d", cdev_find_free_index("usbdisk")); - else - priv->blk.cdev.name = xasprintf("disk%d", cdev_find_free_index("disk")); + if (is_bio_usbdev(efidev)) { + instance = cdev_find_free_index("usbdisk"); + priv->blk.cdev.name = xasprintf("usbdisk%d", instance); + } else { + instance = cdev_find_free_index("disk"); + priv->blk.cdev.name = xasprintf("disk%d", instance); + } + priv->blk.blockbits = ffs(media->block_size) - 1; priv->blk.num_blocks = media->last_block + 1; priv->blk.ops = &efi_bio_ops; @@ -174,6 +180,9 @@ if (ret) return ret; + if (efi_get_bootsource() == efidev) + bootsource_set_instance(instance); + parse_partition_table(&priv->blk); return 0; diff --git a/drivers/efi/efi-device.c b/drivers/efi/efi-device.c index 305d337..a1aac2d 100644 --- a/drivers/efi/efi-device.c +++ b/drivers/efi/efi-device.c @@ -311,7 +311,7 @@ int i; for (i = 0; i < efidev->num_guids; i++) { - if (!memcmp(&efidrv->guid, &efidev->guids[i], sizeof(efi_guid_t))) { + if (!efi_guidcmp(efidrv->guid, efidev->guids[i])) { BS->handle_protocol(efidev->handle, &efidev->guids[i], &efidev->protocol); return 0; @@ -398,13 +398,19 @@ return 0; } +static struct efi_device *bootdev; + +struct efi_device *efi_get_bootsource(void) +{ + return bootdev; +} + static void efi_set_bootsource(void) { enum bootsource src = BOOTSOURCE_UNKNOWN; int instance = BOOTSOURCE_INSTANCE_UNKNOWN; efi_handle_t *efi_parent; - struct efi_device *bootdev; if (!efi_loaded_image->parent_handle) goto out; diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c index 2ca89fa..9e82518 100644 --- a/drivers/serial/efi-stdio.c +++ b/drivers/serial/efi-stdio.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include "efi-stdio.h" #define EFI_SHIFT_STATE_VALID 0x80000000 #define EFI_RIGHT_CONTROL_PRESSED 0x00000004 @@ -71,6 +73,7 @@ struct efi_console_priv { struct efi_simple_text_output_protocol *out; struct efi_simple_input_interface *in; + struct efi_simple_text_input_ex_protocol *inex; struct console_device cdev; int lastkey; u16 efi_console_buffer[CONFIG_CBSIZE]; @@ -105,35 +108,72 @@ { 0x17, 27 /* escape key */ }, }; +static int xlate_keypress(struct efi_input_key *k) +{ + int i; + + /* 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 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; + struct efi_key_data kd; /* 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); + if (priv->inex) { + efiret = priv->inex->read_key_stroke_ex(priv->inex, &kd); - /* 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; + if (efiret == EFI_NOT_READY) + return -EAGAIN; + if (!EFI_ERROR(efiret)) { + if ((kd.state.shift_state & EFI_SHIFT_STATE_VALID) && + (kd.state.shift_state & EFI_CONTROL_PRESSED)) { + int ch = tolower(kd.key.unicode_char & 0xff); + + if (isalpha(ch)) + return CHAR_CTRL(ch); + if (ch == '\0') /* ctrl is pressed on its own */ + return -EAGAIN; + } + + if (kd.key.unicode_char || kd.key.scan_code) + return xlate_keypress(&kd.key); + + /* Some broken firmwares offer simple_text_input_ex_protocol, + * but never handle any key. Treat those as if + * read_key_stroke_ex failed and fall through + * to the basic simple_text_input_protocol. + */ + dev_dbg(priv->cdev.dev, "Falling back to simple_text_input_protocol\n"); + } } - return k.unicode_char & 0xff; + efiret = priv->in->read_key_stroke(priv->in, &kd.key); + + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return xlate_keypress(&kd.key); } 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; + struct efi_console_priv *priv = to_efi(cdev); + struct efi_simple_text_output_protocol *con_out = priv->out; str[0] = c; @@ -331,8 +371,12 @@ static int efi_console_probe(struct device_d *dev) { + efi_guid_t inex_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; + struct efi_simple_text_input_ex_protocol *inex; struct console_device *cdev; struct efi_console_priv *priv; + efi_status_t efiret; + int i; priv = xzalloc(sizeof(*priv)); @@ -340,6 +384,18 @@ priv->out = efi_sys_table->con_out; priv->in = efi_sys_table->con_in; + efiret = BS->open_protocol((void *)efi_sys_table->con_in_handle, + &inex_guid, + (void **)&inex, + efi_parent_image, + 0, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!EFI_ERROR(efiret)) { + priv->inex = inex; + dev_dbg(dev, "Using simple_text_input_ex_protocol\n"); + } + priv->current_color = EFI_WHITE; efi_set_mode(priv); diff --git a/drivers/serial/efi-stdio.h b/drivers/serial/efi-stdio.h new file mode 100644 index 0000000..1fa417c --- /dev/null +++ b/drivers/serial/efi-stdio.h @@ -0,0 +1,58 @@ +#ifndef EFI_STDIO_H_ +#define EFI_STDIO_H_ + +#include + +struct efi_simple_text_input_ex_protocol; + +typedef efi_status_t (EFIAPI *efi_input_reset_ex)( + struct efi_simple_text_input_ex_protocol *this, + efi_bool_t extended_verification +); + +struct efi_key_state { + u32 shift_state; + u8 toggle_state; +}; + +struct efi_key_data { + struct efi_input_key key; + struct efi_key_state state; +}; + +typedef efi_status_t (EFIAPI *efi_input_read_key_ex)( + struct efi_simple_text_input_ex_protocol *this, + struct efi_key_data *keydata +); + +typedef efi_status_t (EFIAPI *efi_set_state)( + struct efi_simple_text_input_ex_protocol *this, + u8 *key_toggle_state +); + +typedef efi_status_t (EFIAPI *efi_key_notify_function)( + struct efi_key_data *keydata +); + +typedef efi_status_t (EFIAPI *efi_register_keystroke_notify)( + struct efi_simple_text_input_ex_protocol *this, + struct efi_key_data keydata, + efi_key_notify_function key_notification_function, + void **notify_handle +); + +typedef efi_status_t (EFIAPI *efi_unregister_keystroke_notify)( + struct efi_simple_text_input_ex_protocol *this, + void *notification_handle +); + +struct efi_simple_text_input_ex_protocol { + efi_input_reset_ex reset; + efi_input_read_key_ex read_key_stroke_ex; + void *wait_for_key_ex; + efi_set_state set_state; + efi_register_keystroke_notify register_key_notify; + efi_unregister_keystroke_notify unregister_key_notify; +}; + +#endif diff --git a/fs/efivarfs.c b/fs/efivarfs.c index 1e80493..9eadda4 100644 --- a/fs/efivarfs.c +++ b/fs/efivarfs.c @@ -145,7 +145,7 @@ if (ret) return -ENOENT; - if (memcmp(&vendor, &EFI_BAREBOX_VENDOR_GUID, sizeof(efi_guid_t))) + if (efi_guidcmp(vendor, EFI_BAREBOX_VENDOR_GUID)) return -EPERM; inode = xzalloc(sizeof(*inode)); diff --git a/include/efi.h b/include/efi.h index 218333f..166803a 100644 --- a/include/efi.h +++ b/include/efi.h @@ -664,11 +664,6 @@ 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)); -} - struct efi_device_path *device_path_from_handle(efi_handle_t Handle); char *device_path_to_str(struct efi_device_path *dev_path); u8 device_path_to_type(struct efi_device_path *dev_path); diff --git a/include/efi/efi-device.h b/include/efi/efi-device.h index 15c293b..5eaf1f2 100644 --- a/include/efi/efi-device.h +++ b/include/efi/efi-device.h @@ -43,5 +43,6 @@ int efi_connect_all(void); void efi_register_devices(void); +struct efi_device *efi_get_bootsource(void); #endif /* __EFI_EFI_DEVICE_H */