Merge tag 'efi-2019-07-rc5-3' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi

Pull request for UEFI sub-system for v2019.07-rc5 (3)

This pull request provides error fixes for the graphical output protocol,
the text output protocol, and the extended text input protocol.

Setting the boot device for the bootefi command is now not only supported
by the 'load' command but also for the file system specific commands like
'fatload'.
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index e657226..cb152b3 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -505,7 +505,8 @@
 	struct efi_load_option lo;
 	void *data = NULL;
 	efi_uintn_t size;
-	int ret;
+	efi_status_t ret;
+	int r = CMD_RET_SUCCESS;
 
 	if (argc < 6 || argc > 7)
 		return CMD_RET_USAGE;
@@ -538,7 +539,7 @@
 	if (ret != EFI_SUCCESS) {
 		printf("Cannot create device path for \"%s %s\"\n",
 		       argv[3], argv[4]);
-		ret = CMD_RET_FAILURE;
+		r = CMD_RET_FAILURE;
 		goto out;
 	}
 	lo.file_path = file_path;
@@ -553,7 +554,7 @@
 
 	size = efi_serialize_load_option(&lo, (u8 **)&data);
 	if (!size) {
-		ret = CMD_RET_FAILURE;
+		r = CMD_RET_FAILURE;
 		goto out;
 	}
 
@@ -562,14 +563,17 @@
 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
 					EFI_VARIABLE_RUNTIME_ACCESS,
 					size, data));
-	ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
+	if (ret != EFI_SUCCESS) {
+		printf("Cannot set %ls\n", var_name16);
+		r = CMD_RET_FAILURE;
+	}
 out:
 	free(data);
 	efi_free_pool(device_path);
 	efi_free_pool(file_path);
 	free(lo.label);
 
-	return ret;
+	return r;
 }
 
 /**
@@ -609,7 +613,7 @@
 
 		ret = EFI_CALL(RT->set_variable(var_name16, &guid, 0, 0, NULL));
 		if (ret) {
-			printf("cannot remove Boot%04X", id);
+			printf("Cannot remove Boot%04X", id);
 			return CMD_RET_FAILURE;
 		}
 	}
@@ -896,6 +900,7 @@
 	char *endp;
 	efi_guid_t guid;
 	efi_status_t ret;
+	int r = CMD_RET_SUCCESS;
 
 	if (argc != 2)
 		return CMD_RET_USAGE;
@@ -903,7 +908,7 @@
 	bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
 	if (*endp != '\0' || bootnext > 0xffff) {
 		printf("invalid value: %s\n", argv[1]);
-		ret = CMD_RET_FAILURE;
+		r = CMD_RET_FAILURE;
 		goto out;
 	}
 
@@ -914,9 +919,12 @@
 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
 					EFI_VARIABLE_RUNTIME_ACCESS,
 					size, &bootnext));
-	ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
+	if (ret != EFI_SUCCESS) {
+		printf("Cannot set BootNext\n");
+		r = CMD_RET_FAILURE;
+	}
 out:
-	return ret;
+	return r;
 }
 
 /**
@@ -941,6 +949,7 @@
 	char *endp;
 	efi_guid_t guid;
 	efi_status_t ret;
+	int r = CMD_RET_SUCCESS;
 
 	if (argc == 1)
 		return show_efi_boot_order();
@@ -957,7 +966,7 @@
 		id = (int)simple_strtoul(argv[i], &endp, 16);
 		if (*endp != '\0' || id > 0xffff) {
 			printf("invalid value: %s\n", argv[i]);
-			ret = CMD_RET_FAILURE;
+			r = CMD_RET_FAILURE;
 			goto out;
 		}
 
@@ -970,11 +979,14 @@
 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
 					EFI_VARIABLE_RUNTIME_ACCESS,
 					size, bootorder));
-	ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
+	if (ret != EFI_SUCCESS) {
+		printf("Cannot set BootOrder\n");
+		r = CMD_RET_FAILURE;
+	}
 out:
 	free(bootorder);
 
-	return ret;
+	return r;
 }
 
 static cmd_tbl_t cmd_efidebug_boot_sub[] = {
diff --git a/cmd/fs.c b/cmd/fs.c
index aaafbf9..db74767 100644
--- a/cmd/fs.c
+++ b/cmd/fs.c
@@ -8,7 +8,6 @@
 #include <common.h>
 #include <command.h>
 #include <fs.h>
-#include <efi_loader.h>
 
 static int do_size_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
@@ -26,10 +25,6 @@
 static int do_load_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
 				char * const argv[])
 {
-#ifdef CONFIG_CMD_BOOTEFI
-	efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "",
-			(argc > 4) ? argv[4] : "");
-#endif
 	return do_load(cmdtp, flag, argc, argv, FS_TYPE_ANY);
 }
 
diff --git a/fs/fs.c b/fs/fs.c
index 736ebef..48d8f1f 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -17,6 +17,7 @@
 #include <asm/io.h>
 #include <div64.h>
 #include <linux/math64.h>
+#include <efi_loader.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -700,6 +701,10 @@
 	else
 		pos = 0;
 
+#ifdef CONFIG_CMD_BOOTEFI
+	efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "",
+			(argc > 4) ? argv[4] : "");
+#endif
 	time = get_timer(0);
 	ret = _fs_read(filename, addr, pos, bytes, 1, &len_read);
 	time = get_timer(time);
diff --git a/include/efi_api.h b/include/efi_api.h
index d7d95ed..4de5d20 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -577,7 +577,9 @@
 #define EFI_ATTR_BG(attr)        (((attr) >> 4) & 0x7)
 
 struct efi_simple_text_output_protocol {
-	void *reset;
+	efi_status_t (EFIAPI *reset)(
+			struct efi_simple_text_output_protocol *this,
+			char extended_verification);
 	efi_status_t (EFIAPI *output_string)(
 			struct efi_simple_text_output_protocol *this,
 			const efi_string_t str);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index b26291b..d104cc6 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3620,11 +3620,11 @@
 	},
 	.fw_vendor = firmware_vendor,
 	.fw_revision = FW_VERSION << 16 | FW_PATCHLEVEL << 8,
-	.con_in = (void *)&efi_con_in,
-	.con_out = (void *)&efi_con_out,
-	.std_err = (void *)&efi_con_out,
-	.runtime = (void *)&efi_runtime_services,
-	.boottime = (void *)&efi_boot_services,
+	.con_in = &efi_con_in,
+	.con_out = &efi_con_out,
+	.std_err = &efi_con_out,
+	.runtime = &efi_runtime_services,
+	.boottime = &efi_boot_services,
 	.nr_tables = 0,
 	.tables = NULL,
 };
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 706e6ad..6c8229d 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -481,10 +481,8 @@
 			key_state->key_shift_state |= EFI_LEFT_ALT_PRESSED;
 		if (mod & 4)
 			key_state->key_shift_state |= EFI_LEFT_CONTROL_PRESSED;
-		if (mod & 8)
+		if (!mod || (mod & 8))
 			key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
-	} else {
-		key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
 	}
 }
 
@@ -563,10 +561,13 @@
 		case cESC: /* ESC */
 			pressed_key.scan_code = 23;
 			break;
-		case 'O': /* F1 - F4 */
+		case 'O': /* F1 - F4, End */
 			ch = getc();
 			/* consider modifiers */
-			if (ch < 'P') {
+			if (ch == 'F') { /* End */
+				pressed_key.scan_code = 6;
+				break;
+			} else if (ch < 'P') {
 				set_shift_mask(ch - '0', &key->key_state);
 				ch = getc();
 			}
@@ -590,17 +591,20 @@
 				case '1'...'5': /* F1 - F5 */
 					pressed_key.scan_code = ch - '1' + 11;
 					break;
-				case '7'...'9': /* F6 - F8 */
-					pressed_key.scan_code = ch - '7' + 16;
+				case '6'...'9': /* F5 - F8 */
+					pressed_key.scan_code = ch - '6' + 15;
 					break;
 				case 'A'...'D': /* up, down right, left */
 					pressed_key.scan_code = ch - 'A' + 1;
 					break;
-				case 'F':
-					pressed_key.scan_code = 6; /* End */
+				case 'F': /* End */
+					pressed_key.scan_code = 6;
+					break;
+				case 'H': /* Home */
+					pressed_key.scan_code = 5;
 					break;
-				case 'H':
-					pressed_key.scan_code = 5; /* Home */
+				case '~': /* Home */
+					pressed_key.scan_code = 5;
 					break;
 				}
 				break;
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 182d735..36ca719 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -307,16 +307,10 @@
 
 	EFI_ENTRY("%p", file);
 
-	if (set_blk_dev(fh)) {
-		ret = EFI_DEVICE_ERROR;
-		goto error;
-	}
+	if (set_blk_dev(fh) || fs_unlink(fh->path))
+		ret = EFI_WARN_DELETE_FAILURE;
 
-	if (fs_unlink(fh->path))
-		ret = EFI_DEVICE_ERROR;
 	file_close(fh);
-
-error:
 	return EFI_EXIT(ret);
 }
 
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index e003823..cad509b 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -41,24 +41,25 @@
 					  struct efi_gop_mode_info **info)
 {
 	struct efi_gop_obj *gopobj;
+	efi_status_t ret = EFI_SUCCESS;
 
 	EFI_ENTRY("%p, %x, %p, %p", this, mode_number, size_of_info, info);
 
+	if (!this || !size_of_info || !info || mode_number) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
 	gopobj = container_of(this, struct efi_gop_obj, ops);
+	ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, sizeof(gopobj->info),
+				(void **)info);
+	if (ret != EFI_SUCCESS)
+		goto out;
 	*size_of_info = sizeof(gopobj->info);
-	*info = &gopobj->info;
-
-	return EFI_EXIT(EFI_SUCCESS);
-}
-
-static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number)
-{
-	EFI_ENTRY("%p, %x", this, mode_number);
-
-	if (mode_number != 0)
-		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	memcpy(*info, &gopobj->info, sizeof(gopobj->info));
 
-	return EFI_EXIT(EFI_SUCCESS);
+out:
+	return EFI_EXIT(ret);
 }
 
 static __always_inline struct efi_gop_pixel efi_vid16_to_blt_col(u16 vid)
@@ -309,6 +310,44 @@
 			   dx, dy, width, height, delta, vid_bpp);
 }
 
+/**
+ * gop_set_mode() - set graphical output mode
+ *
+ * This function implements the SetMode() service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:		the graphical output protocol
+ * @model_number:	the mode to be set
+ * Return:		status code
+ */
+static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number)
+{
+	struct efi_gop_obj *gopobj;
+	struct efi_gop_pixel buffer = {0, 0, 0, 0};
+	efi_uintn_t vid_bpp;
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p, %x", this, mode_number);
+
+	if (!this) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	if (mode_number) {
+		ret = EFI_UNSUPPORTED;
+		goto out;
+	}
+	gopobj = container_of(this, struct efi_gop_obj, ops);
+	vid_bpp = gop_get_bpp(this);
+	ret = gop_blt_video_fill(this, &buffer, EFI_BLT_VIDEO_FILL, 0, 0, 0, 0,
+				 gopobj->info.width, gopobj->info.height, 0,
+				 vid_bpp);
+out:
+	return EFI_EXIT(ret);
+}
+
 /*
  * Copy rectangle.
  *
@@ -367,7 +406,7 @@
 					 dy, width, height, delta, vid_bpp);
 		break;
 	default:
-		ret = EFI_UNSUPPORTED;
+		ret = EFI_INVALID_PARAMETER;
 	}
 
 	if (ret != EFI_SUCCESS)
@@ -464,26 +503,26 @@
 	gopobj->mode.info = &gopobj->info;
 	gopobj->mode.info_size = sizeof(gopobj->info);
 
+	gopobj->mode.fb_base = fb_base;
+	gopobj->mode.fb_size = fb_size;
+
+	gopobj->info.version = 0;
+	gopobj->info.width = col;
+	gopobj->info.height = row;
 #ifdef CONFIG_DM_VIDEO
 	if (bpix == VIDEO_BPP32)
 #else
 	if (bpix == LCD_COLOR32)
 #endif
 	{
-		/*
-		 * With 32bit color space we can directly expose the frame
-		 * buffer
-		 */
-		gopobj->mode.fb_base = fb_base;
-		gopobj->mode.fb_size = fb_size;
+		gopobj->info.pixel_format = EFI_GOT_BGRA8;
+	} else {
+		gopobj->info.pixel_format = EFI_GOT_BITMASK;
+		gopobj->info.pixel_bitmask[0] = 0xf800; /* red */
+		gopobj->info.pixel_bitmask[1] = 0x07e0; /* green */
+		gopobj->info.pixel_bitmask[2] = 0x001f; /* blue */
 	}
-
-	gopobj->info.version = 0;
-	gopobj->info.width = col;
-	gopobj->info.height = row;
-	gopobj->info.pixel_format = EFI_GOT_BGRA8;
 	gopobj->info.pixels_per_scanline = col;
-
 	gopobj->bpix = bpix;
 	gopobj->fb = fb;
 
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 61b71de..77e3302 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -581,18 +581,22 @@
 	struct efi_hii_packagelist *hii =
 				(struct efi_hii_packagelist *)handle;
 	int package_cnt, package_max;
-	efi_status_t ret = EFI_SUCCESS;
+	efi_status_t ret = EFI_NOT_FOUND;
 
 	EFI_ENTRY("%p, %u, %pUl, %p, %p", this, package_type, package_guid,
 		  handle_buffer_length, handle);
 
 	if (!handle_buffer_length ||
-	    (*handle_buffer_length && !handle))
-		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	    (*handle_buffer_length && !handle)) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
 
 	if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) ||
-	    (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid))
-		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	    (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid)) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
 
 	EFI_PRINT("package type=%x, guid=%pUl, length=%zu\n", (int)package_type,
 		  package_guid, *handle_buffer_length);
@@ -607,53 +611,28 @@
 			if (!list_empty(&hii->guid_list))
 				break;
 			continue;
-		case EFI_HII_PACKAGE_FORMS:
-			EFI_PRINT("Form package not supported\n");
-			ret = EFI_INVALID_PARAMETER;
-			continue;
 		case EFI_HII_PACKAGE_STRINGS:
 			if (!list_empty(&hii->string_tables))
 				break;
 			continue;
-		case EFI_HII_PACKAGE_FONTS:
-			EFI_PRINT("Font package not supported\n");
-			ret = EFI_INVALID_PARAMETER;
-			continue;
-		case EFI_HII_PACKAGE_IMAGES:
-			EFI_PRINT("Image package not supported\n");
-			ret = EFI_INVALID_PARAMETER;
-			continue;
-		case EFI_HII_PACKAGE_SIMPLE_FONTS:
-			EFI_PRINT("Simple font package not supported\n");
-			ret = EFI_INVALID_PARAMETER;
-			continue;
-		case EFI_HII_PACKAGE_DEVICE_PATH:
-			EFI_PRINT("Device path package not supported\n");
-			ret = EFI_INVALID_PARAMETER;
-			continue;
 		case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
 			if (!list_empty(&hii->keyboard_packages))
 				break;
 			continue;
-		case EFI_HII_PACKAGE_ANIMATIONS:
-			EFI_PRINT("Animation package not supported\n");
-			ret = EFI_INVALID_PARAMETER;
-			continue;
-		case EFI_HII_PACKAGE_END:
-		case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
-		case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
 		default:
 			continue;
 		}
 
 		package_cnt++;
-		if (package_cnt <= package_max)
+		if (package_cnt <= package_max) {
 			*handle++ = hii;
-		else
+			ret = EFI_SUCCESS;
+		} else {
 			ret = EFI_BUFFER_TOO_SMALL;
+		}
 	}
 	*handle_buffer_length = package_cnt * sizeof(*handle);
-
+out:
 	return EFI_EXIT(ret);
 }
 
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index 1d1b23b..d6b75ca 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -148,7 +148,7 @@
 }
 
 /**
- * efi_efi_get_variable() - retrieve value of a UEFI variable
+ * efi_get_variable() - retrieve value of a UEFI variable
  *
  * This function implements the GetVariable runtime service.
  *
@@ -404,7 +404,7 @@
 }
 
 /**
- * efi_efi_set_variable() - set value of a UEFI variable
+ * efi_set_variable() - set value of a UEFI variable
  *
  * This function implements the SetVariable runtime service.
  *
diff --git a/lib/efi_selftest/efi_selftest_gop.c b/lib/efi_selftest/efi_selftest_gop.c
index 4ad043c..d64294a 100644
--- a/lib/efi_selftest/efi_selftest_gop.c
+++ b/lib/efi_selftest/efi_selftest_gop.c
@@ -80,6 +80,11 @@
 		}
 		efi_st_printf("Mode %u: %u x %u\n",
 			      i, info->width, info->height);
+		ret = boottime->free_pool(info);
+		if (ret != EFI_SUCCESS) {
+			efi_st_printf("FreePool failed");
+			return EFI_ST_FAILURE;
+		}
 	}
 
 	return EFI_ST_SUCCESS;