From 2fb3ed2cbc5012718c9cfbfae7fcf87daa000e9b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 23 Oct 2020 12:46:04 +0200 Subject: [PATCH 1/5] cmd: conitrace: replace getc() by getchar() This command was missed when renaming getc() to getchar(). Fixes: c670aeee3df9 ("common: rename getc() to getchar()") Signed-off-by: Heinrich Schuchardt --- cmd/conitrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/conitrace.c b/cmd/conitrace.c index 88850db541..811f5c68a9 100644 --- a/cmd/conitrace.c +++ b/cmd/conitrace.c @@ -19,10 +19,10 @@ static int do_conitrace(struct cmd_tbl *cmdtp, int flag, int argc, /* Empty input buffer */ while (tstc()) - getc(); + getchar(); for (;;) { - int c = getc(); + int c = getchar(); if (first && (c == 'x' || c == 'X')) break; From b055a05b989cb67484d2cef62b784896914ceb58 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 23 Oct 2020 20:52:26 +0200 Subject: [PATCH 2/5] input: add support for FN1 - FN10 on crosswire kbd Chromebooks and the sandbox use a crosswire keyboard with function keys FN1 - FN10. These keys are needed when running UEFI applications like GRUB or the UEFI SCT. Add support for these keys when translating from key codes to ECMA-48 (or withdrawn ANSI 3.64) escape sequences. All escape sequences start with 0x1b. So we should not repeat this byte in the kbd_to_ansi364 table. For testing use: sandbox_defconfig + CONFIG_EFI_SELFTEST=y $ ./u-boot -D -l => setenv efi_selftest extended text input => bootefi selftest Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- drivers/input/input.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index da264f4166..c1c5e428dc 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -170,21 +170,35 @@ static struct kbd_entry { }; /* - * Scan key code to ANSI 3.64 escape sequence table. This table is - * incomplete in that it does not include all possible extra keys. + * The table contains conversions from scan key codes to ECMA-48 escape + * sequences. The same sequences exist in the withdrawn ANSI 3.64 standard. + * + * As all escape sequences start with 0x1b this byte has been removed. + * + * This table is incomplete in that it does not include all possible extra keys. */ static struct { int kbd_scan_code; char *escape; } kbd_to_ansi364[] = { - { KEY_UP, "\033[A"}, - { KEY_DOWN, "\033[B"}, - { KEY_RIGHT, "\033[C"}, - { KEY_LEFT, "\033[D"}, + { KEY_UP, "[A"}, + { KEY_LEFT, "[D"}, + { KEY_RIGHT, "[C"}, + { KEY_DOWN, "[B"}, + { KEY_F1, "OP"}, + { KEY_F2, "OQ"}, + { KEY_F3, "OR"}, + { KEY_F4, "OS"}, + { KEY_F5, "[15~"}, + { KEY_F6, "[17~"}, + { KEY_F7, "[18~"}, + { KEY_F8, "[19~"}, + { KEY_F9, "[20~"}, + { KEY_F10, "[21~"}, }; /* Maximum number of output characters that an ANSI sequence expands to */ -#define ANSI_CHAR_MAX 3 +#define ANSI_CHAR_MAX 5 static int input_queue_ascii(struct input_config *config, int ch) { @@ -417,6 +431,7 @@ static int input_keycode_to_ansi364(struct input_config *config, for (i = ch_count = 0; i < ARRAY_SIZE(kbd_to_ansi364); i++) { if (keycode != kbd_to_ansi364[i].kbd_scan_code) continue; + output_ch[ch_count++] = 0x1b; for (escape = kbd_to_ansi364[i].escape; *escape; escape++) { if (ch_count < max_chars) output_ch[ch_count] = *escape; @@ -473,7 +488,7 @@ static int input_keycodes_to_ascii(struct input_config *config, /* Start conversion by looking for the first new keycode (by same). */ for (i = same; i < num_keycodes; i++) { int key = keycode[i]; - int ch; + int ch = 0xff; /* * For a normal key (with an ASCII value), add it; otherwise @@ -492,10 +507,10 @@ static int input_keycodes_to_ascii(struct input_config *config, } if (ch_count < max_chars && ch != 0xff) output_ch[ch_count++] = (uchar)ch; - } else { + } + if (ch == 0xff) ch_count += input_keycode_to_ansi364(config, key, output_ch, max_chars); - } } if (ch_count > max_chars) { From ab02c3fec499e89e09b0f024ef263821e4b5d918 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 2 Nov 2020 19:32:24 +0100 Subject: [PATCH 3/5] efi_loader: non-volatile variable not deleted from file When deleting a non-volatile variable it was deleted from memory but the deletion was not persisted to the file system. SetVariable() may be called with attributes == 0 to delete a variable. To determine if the deletion shall be persisted we have to consider the non-volatile flag in the attributes of the deleted variable and not the value passed in the call parameter. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_variable.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index a10b9caa8b..0c689cfb47 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -393,6 +393,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor, if (delete) { /* EFI_NOT_FOUND has been handled before */ + attributes = var->attr; ret = EFI_SUCCESS; } else if (append) { u16 *old_data = var->name; From b1aa6fcf274cb655ffb56eadcb9518fbb57e47b5 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 4 Nov 2020 22:00:48 +0100 Subject: [PATCH 4/5] efi_selftest: add tool to download dtb For validating the fixed up device tree we need a tool to need to save it to a file. dtbdump.efi copies the configuration table with the device tree to a file on the same partition from which dtbdump.efi was invoked. The file name can be entered on the console. Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/Makefile | 5 + lib/efi_selftest/dtbdump.c | 215 +++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 lib/efi_selftest/dtbdump.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 06d66cfdd1..aabb743ecb 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -8,6 +8,8 @@ asflags-y += -DHOST_ARCH="$(HOST_ARCH)" ccflags-y += -DHOST_ARCH="$(HOST_ARCH)" +CFLAGS_dtbdump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding +CFLAGS_REMOVE_dtbdump.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding @@ -76,6 +78,9 @@ efi_selftest_miniapp_exception.efi \ efi_selftest_miniapp_exit.efi \ efi_selftest_miniapp_return.efi +always += \ +dtbdump.efi + $(obj)/efi_miniapp_file_image_exception.h: $(obj)/efi_selftest_miniapp_exception.efi $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exception.efi > \ $(obj)/efi_miniapp_file_image_exception.h diff --git a/lib/efi_selftest/dtbdump.c b/lib/efi_selftest/dtbdump.c new file mode 100644 index 0000000000..d90e3eb768 --- /dev/null +++ b/lib/efi_selftest/dtbdump.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020, Heinrich Schuchardt + * + * dtbdump.efi saves the device tree provided as a configuration table + * to a file. + */ + +#include +#include + +#define BUFFER_SIZE 64 +#define ESC 0x17 +#define DEFAULT_FILENAME L"dtb.dtb" + +static struct efi_simple_text_output_protocol *cerr; +static struct efi_simple_text_output_protocol *cout; +static struct efi_simple_text_input_protocol *cin; +static struct efi_boot_services *bs; +static const efi_guid_t fdt_guid = EFI_FDT_GUID; +static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; +static const efi_guid_t guid_simple_file_system_protocol = + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + +/** + * input() - read string from console + * + * @buffer: input buffer + * @buffer_size: buffer size + * Return: status code + */ +static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size) +{ + struct efi_input_key key = {0}; + efi_uintn_t index; + efi_uintn_t pos = 0; + u16 outbuf[2] = L" "; + efi_status_t ret; + + /* Drain the console input */ + ret = cin->reset(cin, true); + for (;;) { + ret = bs->wait_for_event(1, &cin->wait_for_key, &index); + if (ret != EFI_SUCCESS) + continue; + ret = cin->read_key_stroke(cin, &key); + if (ret != EFI_SUCCESS) + continue; + switch (key.scan_code) { + case 0x17: /* Escape */ + cout->output_string(cout, L"\nAborted\n"); + return EFI_ABORTED; + default: + break; + } + switch (key.unicode_char) { + case 0x08: /* Backspace */ + if (pos) { + buffer[pos--] = 0; + cout->output_string(cout, L"\b \b"); + } + break; + case 0x0a: /* Linefeed */ + case 0x0d: /* Carriage return */ + return EFI_SUCCESS; + default: + break; + } + /* Ignore surrogate codes */ + if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF) + continue; + if (key.unicode_char >= 0x20 && + pos < buffer_size - 1) { + *outbuf = key.unicode_char; + buffer[pos++] = key.unicode_char; + cout->output_string(cout, outbuf); + } + } +} + +/* + * Convert FDT value to host endianness. + * + * @val FDT value + * @return converted value + */ +static u32 f2h(fdt32_t val) +{ + char *buf = (char *)&val; + char i; + + /* Swap the bytes */ + i = buf[0]; buf[0] = buf[3]; buf[3] = i; + i = buf[1]; buf[1] = buf[2]; buf[2] = i; + return *(u32 *)buf; +} + +/** + * get_dtb() - get device tree + * + * @systable: system table + * Return: device tree or NULL + */ +void *get_dtb(struct efi_system_table *systable) +{ + void *dtb = NULL; + efi_uintn_t i; + + for (i = 0; i < systable->nr_tables; ++i) { + if (!memcmp(&systable->tables[i].guid, &fdt_guid, + sizeof(efi_guid_t))) { + dtb = systable->tables[i].table; + break; + } + } + return dtb; +} + +/** + * efi_main() - entry point of the EFI application. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: status code + */ +efi_status_t EFIAPI efi_main(efi_handle_t handle, + struct efi_system_table *systable) +{ + efi_uintn_t ret; + u16 filename[BUFFER_SIZE] = {0}; + efi_uintn_t dtb_size; + struct efi_loaded_image *loaded_image; + struct efi_simple_file_system_protocol *file_system; + struct efi_file_handle *root, *file; + struct fdt_header *dtb; + + cerr = systable->std_err; + cout = systable->con_out; + cin = systable->con_in; + bs = systable->boottime; + + cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK); + cout->clear_screen(cout); + cout->set_attribute(cout, EFI_YELLOW | EFI_BACKGROUND_BLACK); + cout->output_string(cout, L"DTB Dump\n\n"); + cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK); + + dtb = get_dtb(systable); + if (!dtb) { + cerr->output_string(cout, L"DTB not found\n"); + return EFI_NOT_FOUND; + } + if (f2h(dtb->magic) != FDT_MAGIC) { + cerr->output_string(cout, L"Wrong device tree magic\n"); + return EFI_NOT_FOUND; + } + dtb_size = f2h(dtb->totalsize); + + cout->output_string(cout, L"Filename (" DEFAULT_FILENAME ")?\n"); + ret = efi_input(filename, sizeof(filename)); + if (ret != EFI_SUCCESS) + return ret; + if (!*filename) + memcpy(filename, DEFAULT_FILENAME, sizeof(DEFAULT_FILENAME)); + + cout->output_string(cout, L"\n"); + + ret = bs->open_protocol(handle, &loaded_image_guid, + (void **)&loaded_image, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + cerr->output_string(cout, + L"Loaded image protocol not found\n"); + return ret; + } + + /* Open the simple file system protocol */ + ret = bs->open_protocol(loaded_image->device_handle, + &guid_simple_file_system_protocol, + (void **)&file_system, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + cerr->output_string( + cout, L"Failed to open simple file system protocol\n"); + return ret; + } + + /* Open volume */ + ret = file_system->open_volume(file_system, &root); + if (ret != EFI_SUCCESS) { + cerr->output_string(cerr, L"Failed to open volume\n"); + return ret; + } + /* Create file */ + ret = root->open(root, &file, filename, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | + EFI_FILE_MODE_CREATE, EFI_FILE_ARCHIVE); + if (ret == EFI_SUCCESS) { + /* Write file */ + ret = file->write(file, &dtb_size, dtb); + if (ret != EFI_SUCCESS) + cerr->output_string(cerr, L"Failed to write file\n"); + file->close(file); + } else { + cerr->output_string(cerr, L"Failed to open file\n"); + } + root->close(root); + + if (ret == EFI_SUCCESS) { + cout->output_string(cout, filename); + cout->output_string(cout, L" written\n"); + } + + return ret; +} From a322f54f50cfb2e8e7a68968c060b2fd3dbd934d Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Thu, 5 Nov 2020 23:58:43 +0200 Subject: [PATCH 5/5] tpm: Change response length of tpm2_get_capability() For implementing the EFI_TCG2_PROTOCOL we need the count field returned by the TPM when reading capabilities via tpm2_get_capability(). Adjust the implementation of the 'tpm2 get_capability' command accordingly. Suggested-by: Heinrich Schuchardt Signed-off-by: Ilias Apalodimas Reviewed-by: Heinrich Schuchardt --- cmd/tpm-v2.c | 4 ++-- lib/tpm-v2.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c index e6742656f5..5fa4788a72 100644 --- a/cmd/tpm-v2.c +++ b/cmd/tpm-v2.c @@ -191,10 +191,10 @@ static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc, for (i = 0; i < count; i++) { printf("Property 0x"); for (j = 0; j < 4; j++) - printf("%02x", data[(i * 8) + j]); + printf("%02x", data[(i * 8) + j + sizeof(u32)]); printf(": 0x"); for (j = 4; j < 8; j++) - printf("%02x", data[(i * 8) + j]); + printf("%02x", data[(i * 8) + j + sizeof(u32)]); printf("\n"); } diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index a4c352e3ef..91759068cf 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -184,10 +184,10 @@ u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property, /* * In the response buffer, the properties are located after the: * tag (u16), response size (u32), response code (u32), - * YES/NO flag (u8), TPM_CAP (u32) and TPMU_CAPABILITIES (u32). + * YES/NO flag (u8), TPM_CAP (u32). */ properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) + - sizeof(u8) + sizeof(u32) + sizeof(u32); + sizeof(u8) + sizeof(u32); memcpy(buf, &response[properties_off], response_len - properties_off); return 0;