diff options
| author | Tom Rini <trini@konsulko.com> | 2019-09-21 07:31:23 -0400 | 
|---|---|---|
| committer | Tom Rini <trini@konsulko.com> | 2019-09-21 07:31:23 -0400 | 
| commit | 390183b58179ddaf986422f4d9446c596660f7e0 (patch) | |
| tree | d2401285ea91806eeac338eeaf721d855c896f4b /lib | |
| parent | d6c7309f561ac832c080e5ec07b0af9c8da319a8 (diff) | |
| parent | 79907a4f8429aef161add59b3d026cf2c734c1aa (diff) | |
Merge tag 'efi-2019-10-rc4-5' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
Pull request for UEFI sub-system for v2019.10-rc4 (5)
This patch set fixes errors in the UEFI sub-system and adds a function to
compare u16 strings which is prerequisite for further patches.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/charset.c | 25 | ||||
| -rw-r--r-- | lib/efi_loader/efi_boottime.c | 26 | ||||
| -rw-r--r-- | lib/efi_loader/efi_device_path.c | 33 | ||||
| -rw-r--r-- | lib/efi_loader/efi_variable.c | 70 | ||||
| -rw-r--r-- | lib/efi_selftest/efi_selftest_variables.c | 20 | 
5 files changed, 135 insertions, 39 deletions
| diff --git a/lib/charset.c b/lib/charset.c index 72d745da4f4..1c6a7f693de 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -335,6 +335,31 @@ s32 utf_to_upper(const s32 code)  	return ret;  } +/* + * u16_strncmp() - compare two u16 string + * + * @s1:		first string to compare + * @s2:		second string to compare + * @n:		maximum number of u16 to compare + * Return:	0  if the first n u16 are the same in s1 and s2 + *		< 0 if the first different u16 in s1 is less than the + *		corresponding u16 in s2 + *		> 0 if the first different u16 in s1 is greater than the + *		corresponding u16 in s2 + */ +int u16_strncmp(const u16 *s1, const u16 *s2, size_t n) +{ +	int ret = 0; + +	for (; n; --n, ++s1, ++s2) { +		ret = *s1 - *s2; +		if (ret || !*s1) +			break; +	} + +	return ret; +} +  size_t u16_strlen(const void *in)  {  	const char *pos = in; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b9bff894cbb..493d906c641 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -3499,7 +3499,6 @@ static efi_status_t EFIAPI efi_disconnect_controller(  	efi_handle_t *child_handle_buffer = NULL;  	size_t number_of_children = 0;  	efi_status_t r; -	size_t stop_count = 0;  	struct efi_object *efiobj;  	EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle, @@ -3539,32 +3538,35 @@ static efi_status_t EFIAPI efi_disconnect_controller(  				       (void **)&binding_protocol,  				       driver_image_handle, NULL,  				       EFI_OPEN_PROTOCOL_GET_PROTOCOL)); -	if (r != EFI_SUCCESS) +	if (r != EFI_SUCCESS) { +		r = EFI_INVALID_PARAMETER;  		goto out; +	}  	/* Remove the children */  	if (number_of_children) {  		r = EFI_CALL(binding_protocol->stop(binding_protocol,  						    controller_handle,  						    number_of_children,  						    child_handle_buffer)); -		if (r == EFI_SUCCESS) -			++stop_count; +		if (r != EFI_SUCCESS) { +			r = EFI_DEVICE_ERROR; +			goto out; +		}  	}  	/* Remove the driver */ -	if (!child_handle) +	if (!child_handle) {  		r = EFI_CALL(binding_protocol->stop(binding_protocol,  						    controller_handle,  						    0, NULL)); -	if (r == EFI_SUCCESS) -		++stop_count; +		if (r != EFI_SUCCESS) { +			r = EFI_DEVICE_ERROR; +			goto out; +		} +	}  	EFI_CALL(efi_close_protocol(driver_image_handle,  				    &efi_guid_driver_binding_protocol,  				    driver_image_handle, NULL)); - -	if (stop_count) -		r = EFI_SUCCESS; -	else -		r = EFI_NOT_FOUND; +	r = EFI_SUCCESS;  out:  	if (!child_handle)  		free(child_handle_buffer); diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index ea39f13b735..86297bb7c11 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -12,8 +12,13 @@  #include <mmc.h>  #include <efi_loader.h>  #include <part.h> +#include <sandboxblockdev.h>  #include <asm-generic/unaligned.h> +#ifdef CONFIG_SANDBOX +const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID; +#endif +  /* template END node: */  static const struct efi_device_path END = {  	.type     = DEVICE_PATH_TYPE_END, @@ -446,6 +451,16 @@ static unsigned dp_size(struct udevice *dev)  			return dp_size(dev->parent) +  				sizeof(struct efi_device_path_sd_mmc_path);  #endif +#ifdef CONFIG_SANDBOX +		case UCLASS_ROOT: +			 /* +			  * Sandbox's host device will be represented +			  * as vendor device with extra one byte for +			  * device number +			  */ +			return dp_size(dev->parent) +				+ sizeof(struct efi_device_path_vendor) + 1; +#endif  		default:  			return dp_size(dev->parent);  		} @@ -505,6 +520,24 @@ static void *dp_fill(void *buf, struct udevice *dev)  #ifdef CONFIG_BLK  	case UCLASS_BLK:  		switch (dev->parent->uclass->uc_drv->id) { +#ifdef CONFIG_SANDBOX +		case UCLASS_ROOT: { +			/* stop traversing parents at this point: */ +			struct efi_device_path_vendor *dp = buf; +			struct blk_desc *desc = dev_get_uclass_platdata(dev); + +			dp_fill(buf, dev->parent); +			dp = buf; +			++dp; +			dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; +			dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; +			dp->dp.length = sizeof(*dp) + 1; +			memcpy(&dp->guid, &efi_guid_host_dev, +			       sizeof(efi_guid_t)); +			dp->vendor_data[0] = desc->devnum; +			return &dp->vendor_data[1]; +			} +#endif  #ifdef CONFIG_IDE  		case UCLASS_IDE: {  			struct efi_device_path_atapi *dp = diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 6687b69a400..48ee255f879 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -424,17 +424,17 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,  				     efi_uintn_t data_size, const void *data)  {  	char *native_name = NULL, *val = NULL, *s; +	const char *old_val; +	size_t old_size;  	efi_status_t ret = EFI_SUCCESS;  	u32 attr;  	EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,  		  data_size, data); -	/* TODO: implement APPEND_WRITE */  	if (!variable_name || !*variable_name || !vendor ||  	    ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) && -	     !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) || -	    (attributes & EFI_VARIABLE_APPEND_WRITE)) { +	     !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {  		ret = EFI_INVALID_PARAMETER;  		goto out;  	} @@ -445,35 +445,51 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,  #define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS) -	if ((data_size == 0) || !(attributes & ACCESS_ATTR)) { -		/* delete the variable: */ -		env_set(native_name, NULL); -		ret = EFI_SUCCESS; -		goto out; -	} +	old_val = env_get(native_name); +	if (old_val) { +		old_val = parse_attr(old_val, &attr); -	val = env_get(native_name); -	if (val) { -		parse_attr(val, &attr); - -		/* We should not free val */ -		val = NULL; +		/* check read-only first */  		if (attr & READ_ONLY) {  			ret = EFI_WRITE_PROTECTED;  			goto out;  		} -		/* -		 * attributes won't be changed -		 * TODO: take care of APPEND_WRITE once supported -		 */ -		if (attr != attributes) { +		if ((data_size == 0) || !(attributes & ACCESS_ATTR)) { +			/* delete the variable: */ +			env_set(native_name, NULL); +			ret = EFI_SUCCESS; +			goto out; +		} + +		/* attributes won't be changed */ +		if (attr != (attributes & ~EFI_VARIABLE_APPEND_WRITE)) {  			ret = EFI_INVALID_PARAMETER;  			goto out;  		} + +		if (attributes & EFI_VARIABLE_APPEND_WRITE) { +			if (!prefix(old_val, "(blob)")) { +				return EFI_DEVICE_ERROR; +				goto out; +			} +			old_size = strlen(old_val); +		} else { +			old_size = 0; +		} +	} else { +		if ((data_size == 0) || !(attributes & ACCESS_ATTR) || +		    (attributes & EFI_VARIABLE_APPEND_WRITE)) { +			/* delete, but nothing to do */ +			ret = EFI_NOT_FOUND; +			goto out; +		} + +		old_size = 0;  	} -	val = malloc(2 * data_size + strlen("{ro,run,boot,nv}(blob)") + 1); +	val = malloc(old_size + 2 * data_size +		     + strlen("{ro,run,boot,nv}(blob)") + 1);  	if (!val) {  		ret = EFI_OUT_OF_RESOURCES;  		goto out; @@ -481,10 +497,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,  	s = val; -	/* -	 * store attributes -	 * TODO: several attributes are not supported -	 */ +	/* store attributes */  	attributes &= (EFI_VARIABLE_NON_VOLATILE |  		       EFI_VARIABLE_BOOTSERVICE_ACCESS |  		       EFI_VARIABLE_RUNTIME_ACCESS); @@ -505,8 +518,13 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,  	}  	s += sprintf(s, "}"); +	if (old_size) +		/* APPEND_WRITE */ +		s += sprintf(s, old_val); +	else +		s += sprintf(s, "(blob)"); +  	/* store payload: */ -	s += sprintf(s, "(blob)");  	s = bin2hex(s, data, data_size);  	*s = '\0'; diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c index 06c1a032dd0..a6b41d1f008 100644 --- a/lib/efi_selftest/efi_selftest_variables.c +++ b/lib/efi_selftest/efi_selftest_variables.c @@ -21,6 +21,9 @@ static const efi_guid_t guid_vendor0 =  static const efi_guid_t guid_vendor1 =  	EFI_GUID(0xff629290, 0x1fc1, 0xd73f,  		 0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea); +static const efi_guid_t guid_global = +	EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, +		 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c);  /*   * Setup unit test. @@ -116,7 +119,7 @@ static int execute(void)  				    EFI_VARIABLE_APPEND_WRITE,  				    7, v + 8);  	if (ret != EFI_SUCCESS) { -		efi_st_todo("SetVariable(APPEND_WRITE) failed\n"); +		efi_st_error("SetVariable(APPEND_WRITE) failed\n");  	} else {  		len = EFI_ST_MAX_DATA_SIZE;  		ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, @@ -131,6 +134,21 @@ static int execute(void)  		if (memcmp(data, v, len))  			efi_st_todo("GetVariable returned wrong value\n");  	} +	/* Append variable 2 */ +	ret = runtime->set_variable(L"efi_none", &guid_vendor1, +				    EFI_VARIABLE_BOOTSERVICE_ACCESS | +				    EFI_VARIABLE_APPEND_WRITE, +				    15, v); +	if (ret != EFI_NOT_FOUND) +		efi_st_error("SetVariable(APPEND_WRITE) with size 0 to non-existent variable returns wrong code\n"); +	/* Append variable 3 */ +	ret = runtime->set_variable(L"PlatformLangCodes", &guid_global, +				    EFI_VARIABLE_BOOTSERVICE_ACCESS | +				    EFI_VARIABLE_RUNTIME_ACCESS | +				    EFI_VARIABLE_APPEND_WRITE, +				    15, v); +	if (ret != EFI_WRITE_PROTECTED) +		efi_st_todo("SetVariable(APPEND_WRITE) to read-only variable returns wrong code\n");  	/* Enumerate variables */  	boottime->set_mem(&guid, 16, 0);  	*varname = 0; | 
