All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] efi_loader: implement non-blocking file services
@ 2021-01-01 18:29 Heinrich Schuchardt
  2021-04-30 10:09 ` Michal Simek
  0 siblings, 1 reply; 4+ messages in thread
From: Heinrich Schuchardt @ 2021-01-01 18:29 UTC (permalink / raw)
  To: u-boot

Implement services OpenEx(), ReadEx(), WriteEx(), FlushEx() of the
EFI_FILE_PROTOCOL.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 include/efi_api.h         |  28 ++--
 lib/efi_loader/efi_file.c | 317 ++++++++++++++++++++++++++++++++------
 2 files changed, 280 insertions(+), 65 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index ecb43a0607..2b54ee02a2 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1589,35 +1589,35 @@ struct efi_file_io_token {

 struct efi_file_handle {
 	u64 rev;
-	efi_status_t (EFIAPI *open)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *open)(struct efi_file_handle *this,
 			struct efi_file_handle **new_handle,
 			u16 *file_name, u64 open_mode, u64 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,
+	efi_status_t (EFIAPI *close)(struct efi_file_handle *this);
+	efi_status_t (EFIAPI *delete)(struct efi_file_handle *this);
+	efi_status_t (EFIAPI *read)(struct efi_file_handle *this,
 			efi_uintn_t *buffer_size, void *buffer);
-	efi_status_t (EFIAPI *write)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *write)(struct efi_file_handle *this,
 			efi_uintn_t *buffer_size, void *buffer);
-	efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *getpos)(struct efi_file_handle *this,
 				      u64 *pos);
-	efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *setpos)(struct efi_file_handle *this,
 				      u64 pos);
-	efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *this,
 			const efi_guid_t *info_type, efi_uintn_t *buffer_size,
 			void *buffer);
-	efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *this,
 			const efi_guid_t *info_type, efi_uintn_t buffer_size,
 			void *buffer);
-	efi_status_t (EFIAPI *flush)(struct efi_file_handle *file);
-	efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *flush)(struct efi_file_handle *this);
+	efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *this,
 			struct efi_file_handle **new_handle,
 			u16 *file_name, u64 open_mode, u64 attributes,
 			struct efi_file_io_token *token);
-	efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *this,
 			struct efi_file_io_token *token);
-	efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *this,
 			struct efi_file_io_token *token);
-	efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *file,
+	efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *this,
 			struct efi_file_io_token *token);
 };

diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 72b7ec1e63..8ece8e71ee 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -246,18 +246,16 @@ error:
 	return NULL;
 }

-static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
-		struct efi_file_handle **new_handle,
-		u16 *file_name, u64 open_mode, u64 attributes)
+static efi_status_t efi_file_open_int(struct efi_file_handle *this,
+				      struct efi_file_handle **new_handle,
+				      u16 *file_name, u64 open_mode,
+				      u64 attributes)
 {
-	struct file_handle *fh = to_fh(file);
+	struct file_handle *fh = to_fh(this);
 	efi_status_t ret;

-	EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
-		  file_name, open_mode, attributes);
-
 	/* Check parameters */
-	if (!file || !new_handle || !file_name) {
+	if (!this || !new_handle || !file_name) {
 		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
@@ -291,6 +289,75 @@ static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
 	} else {
 		ret = EFI_NOT_FOUND;
 	}
+out:
+	return ret;
+}
+
+/**
+ * efi_file_open_()
+ *
+ * This function implements the Open service of the File Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this:	EFI_FILE_PROTOCOL instance
+ * @new_handle:	on return pointer to file handle
+ * @file_name:	file name
+ * @open_mode:	mode to open the file (read, read/write, create/read/write)
+ * @attributes:	attributes for newly created file
+ */
+static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *this,
+					 struct efi_file_handle **new_handle,
+					 u16 *file_name, u64 open_mode,
+					 u64 attributes)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", this, new_handle,
+		  file_name, open_mode, attributes);
+
+	ret = efi_file_open_int(this, new_handle, file_name, open_mode,
+				attributes);
+
+	return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_open_ex() - open file asynchronously
+ *
+ * This function implements the OpenEx service of the File Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this:	EFI_FILE_PROTOCOL instance
+ * @new_handle:	on return pointer to file handle
+ * @file_name:	file name
+ * @open_mode:	mode to open the file (read, read/write, create/read/write)
+ * @attributes:	attributes for newly created file
+ * @token:	transaction token
+ */
+static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *this,
+					    struct efi_file_handle **new_handle,
+					    u16 *file_name, u64 open_mode,
+					    u64 attributes,
+					    struct efi_file_io_token *token)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu, %p", this, new_handle,
+		  file_name, open_mode, attributes, token);
+
+	if (!token) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	ret = efi_file_open_int(this, new_handle, file_name, open_mode,
+				attributes);
+
+	if (ret == EFI_SUCCESS && token->event) {
+		token->status = EFI_SUCCESS;
+		efi_signal_event(token->event);
+	}
+
 out:
 	return EFI_EXIT(ret);
 }
@@ -441,19 +508,15 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
 	return EFI_SUCCESS;
 }

-static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
-					 efi_uintn_t *buffer_size, void *buffer)
+static efi_status_t efi_file_read_int(struct efi_file_handle *this,
+				      efi_uintn_t *buffer_size, void *buffer)
 {
-	struct file_handle *fh = to_fh(file);
+	struct file_handle *fh = to_fh(this);
 	efi_status_t ret = EFI_SUCCESS;
 	u64 bs;

-	EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
-
-	if (!buffer_size) {
-		ret = EFI_INVALID_PARAMETER;
-		goto error;
-	}
+	if (!this || !buffer_size || !buffer)
+		return EFI_INVALID_PARAMETER;

 	bs = *buffer_size;
 	if (fh->isdir)
@@ -465,34 +528,77 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
 	else
 		*buffer_size = SIZE_MAX;

-error:
+	return ret;
+}
+
+/**
+ * efi_file_read() - read file
+ *
+ * This function implements the Read() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:		file protocol instance
+ * @buffer_size:	number of bytes to read
+ * @buffer:		read buffer
+ * Return:		status code
+ */
+static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *this,
+					 efi_uintn_t *buffer_size, void *buffer)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
+
+	ret = efi_file_read_int(this, buffer_size, buffer);
+
 	return EFI_EXIT(ret);
 }

 /**
- * efi_file_write() - write to file
+ * efi_file_read_ex() - read file asynchonously
  *
- * This function implements the Write() service of the EFI_FILE_PROTOCOL.
+ * This function implements the ReadEx() service of the EFI_FILE_PROTOCOL.
  *
  * See the Unified Extensible Firmware Interface (UEFI) specification for
  * details.
  *
- * @file:		file handle
- * @buffer_size:	number of bytes to write
- * @buffer:		buffer with the bytes to write
+ * @this:		file protocol instance
+ * @token:		transaction token
  * Return:		status code
  */
-static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
-					  efi_uintn_t *buffer_size,
-					  void *buffer)
+static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *this,
+					    struct efi_file_io_token *token)
 {
-	struct file_handle *fh = to_fh(file);
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %p", this, token);
+
+	if (!token) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	ret = efi_file_read_int(this, &token->buffer_size, token->buffer);
+
+	if (ret == EFI_SUCCESS && token->event) {
+		token->status = EFI_SUCCESS;
+		efi_signal_event(token->event);
+	}
+
+out:
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t efi_file_write_int(struct efi_file_handle *this,
+				       efi_uintn_t *buffer_size, void *buffer)
+{
+	struct file_handle *fh = to_fh(this);
 	efi_status_t ret = EFI_SUCCESS;
 	loff_t actwrite;

-	EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
-
-	if (!file || !buffer_size || !buffer) {
+	if (!this || !buffer_size || !buffer) {
 		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
@@ -520,6 +626,67 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
 	*buffer_size = actwrite;
 	fh->offset += actwrite;

+out:
+	return ret;
+}
+
+/**
+ * efi_file_write() - write to file
+ *
+ * This function implements the Write() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:		file protocol instance
+ * @buffer_size:	number of bytes to write
+ * @buffer:		buffer with the bytes to write
+ * Return:		status code
+ */
+static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *this,
+					  efi_uintn_t *buffer_size,
+					  void *buffer)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
+
+	ret = efi_file_write_int(this, buffer_size, buffer);
+
+	return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_write_ex() - write to file
+ *
+ * This function implements the WriteEx() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:		file protocol instance
+ * @token:		transaction token
+ * Return:		status code
+ */
+static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *this,
+					     struct efi_file_io_token *token)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %p", this, token);
+
+	if (!token) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	ret = efi_file_write_int(this, &token->buffer_size, token->buffer);
+
+	if (ret == EFI_SUCCESS && token->event) {
+		token->status = EFI_SUCCESS;
+		efi_signal_event(token->event);
+	}
+
 out:
 	return EFI_EXIT(ret);
 }
@@ -761,36 +928,84 @@ out:
 	return EFI_EXIT(ret);
 }

-static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
+/**
+ * efi_file_flush_int() - flush file
+ *
+ * This is the internal implementation of the Flush() and FlushEx() services of
+ * the EFI_FILE_PROTOCOL.
+ *
+ * @this:	file protocol instance
+ * Return:	status code
+ */
+static efi_status_t efi_file_flush_int(struct efi_file_handle *this)
 {
-	EFI_ENTRY("%p", file);
-	return EFI_EXIT(EFI_SUCCESS);
-}
+	struct file_handle *fh = to_fh(this);

-static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
-			struct efi_file_handle **new_handle,
-			u16 *file_name, u64 open_mode, u64 attributes,
-			struct efi_file_io_token *token)
-{
-	return EFI_UNSUPPORTED;
-}
+	if (!this)
+		return EFI_INVALID_PARAMETER;

-static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
-			struct efi_file_io_token *token)
-{
-	return EFI_UNSUPPORTED;
+	if (!(fh->open_mode & EFI_FILE_MODE_WRITE))
+		return EFI_ACCESS_DENIED;
+
+	/* TODO: flush for file position after end of file */
+	return EFI_SUCCESS;
 }

-static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
-			struct efi_file_io_token *token)
+/**
+ * efi_file_flush() - flush file
+ *
+ * This function implements the Flush() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:	file protocol instance
+ * Return:	status code
+ */
+static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *this)
 {
-	return EFI_UNSUPPORTED;
+	efi_status_t ret;
+
+	EFI_ENTRY("%p", this);
+
+	ret = efi_file_flush_int(this);
+
+	return EFI_EXIT(ret);
 }

-static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
-			struct efi_file_io_token *token)
+/**
+ * efi_file_flush_ex() - flush file
+ *
+ * This function implements the FlushEx() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:	file protocol instance
+ * @token:	transaction token
+ * Return:	status code
+ */
+static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *this,
+					     struct efi_file_io_token *token)
 {
-	return EFI_UNSUPPORTED;
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %p", this, token);
+
+	if (!token) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	ret = efi_file_flush_int(this);
+
+	if (ret == EFI_SUCCESS && token->event) {
+		token->status = EFI_SUCCESS;
+		efi_signal_event(token->event);
+	}
+
+out:
+	return EFI_EXIT(ret);
 }

 static const struct efi_file_handle efi_file_handle_protocol = {
--
2.29.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 1/1] efi_loader: implement non-blocking file services
  2021-01-01 18:29 [PATCH 1/1] efi_loader: implement non-blocking file services Heinrich Schuchardt
@ 2021-04-30 10:09 ` Michal Simek
  2021-04-30 10:42   ` Heinrich Schuchardt
  0 siblings, 1 reply; 4+ messages in thread
From: Michal Simek @ 2021-04-30 10:09 UTC (permalink / raw)
  To: u-boot

Hi Heinrich,

p? 1. 1. 2021 v 19:29 odes?latel Heinrich Schuchardt
<xypron.glpk@gmx.de> napsal:
>
> Implement services OpenEx(), ReadEx(), WriteEx(), FlushEx() of the
> EFI_FILE_PROTOCOL.
>
> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
> ---
>  include/efi_api.h         |  28 ++--
>  lib/efi_loader/efi_file.c | 317 ++++++++++++++++++++++++++++++++------
>  2 files changed, 280 insertions(+), 65 deletions(-)
>
> diff --git a/include/efi_api.h b/include/efi_api.h
> index ecb43a0607..2b54ee02a2 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -1589,35 +1589,35 @@ struct efi_file_io_token {
>
>  struct efi_file_handle {
>         u64 rev;
> -       efi_status_t (EFIAPI *open)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *open)(struct efi_file_handle *this,
>                         struct efi_file_handle **new_handle,
>                         u16 *file_name, u64 open_mode, u64 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,
> +       efi_status_t (EFIAPI *close)(struct efi_file_handle *this);
> +       efi_status_t (EFIAPI *delete)(struct efi_file_handle *this);
> +       efi_status_t (EFIAPI *read)(struct efi_file_handle *this,
>                         efi_uintn_t *buffer_size, void *buffer);
> -       efi_status_t (EFIAPI *write)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *write)(struct efi_file_handle *this,
>                         efi_uintn_t *buffer_size, void *buffer);
> -       efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *getpos)(struct efi_file_handle *this,
>                                       u64 *pos);
> -       efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *setpos)(struct efi_file_handle *this,
>                                       u64 pos);
> -       efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *this,
>                         const efi_guid_t *info_type, efi_uintn_t *buffer_size,
>                         void *buffer);
> -       efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *this,
>                         const efi_guid_t *info_type, efi_uintn_t buffer_size,
>                         void *buffer);
> -       efi_status_t (EFIAPI *flush)(struct efi_file_handle *file);
> -       efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *flush)(struct efi_file_handle *this);
> +       efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *this,
>                         struct efi_file_handle **new_handle,
>                         u16 *file_name, u64 open_mode, u64 attributes,
>                         struct efi_file_io_token *token);
> -       efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *this,
>                         struct efi_file_io_token *token);
> -       efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *this,
>                         struct efi_file_io_token *token);
> -       efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *file,
> +       efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *this,
>                         struct efi_file_io_token *token);
>  };
>
> diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
> index 72b7ec1e63..8ece8e71ee 100644
> --- a/lib/efi_loader/efi_file.c
> +++ b/lib/efi_loader/efi_file.c
> @@ -246,18 +246,16 @@ error:
>         return NULL;
>  }
>
> -static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
> -               struct efi_file_handle **new_handle,
> -               u16 *file_name, u64 open_mode, u64 attributes)
> +static efi_status_t efi_file_open_int(struct efi_file_handle *this,
> +                                     struct efi_file_handle **new_handle,
> +                                     u16 *file_name, u64 open_mode,
> +                                     u64 attributes)
>  {
> -       struct file_handle *fh = to_fh(file);
> +       struct file_handle *fh = to_fh(this);
>         efi_status_t ret;
>
> -       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
> -                 file_name, open_mode, attributes);
> -
>         /* Check parameters */
> -       if (!file || !new_handle || !file_name) {
> +       if (!this || !new_handle || !file_name) {
>                 ret = EFI_INVALID_PARAMETER;
>                 goto out;
>         }
> @@ -291,6 +289,75 @@ static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
>         } else {
>                 ret = EFI_NOT_FOUND;
>         }
> +out:
> +       return ret;
> +}
> +
> +/**
> + * efi_file_open_()
> + *
> + * This function implements the Open service of the File Protocol.
> + * See the UEFI spec for details.
> + *
> + * @this:      EFI_FILE_PROTOCOL instance
> + * @new_handle:        on return pointer to file handle
> + * @file_name: file name
> + * @open_mode: mode to open the file (read, read/write, create/read/write)
> + * @attributes:        attributes for newly created file
> + */
> +static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *this,
> +                                        struct efi_file_handle **new_handle,
> +                                        u16 *file_name, u64 open_mode,
> +                                        u64 attributes)
> +{
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", this, new_handle,
> +                 file_name, open_mode, attributes);
> +
> +       ret = efi_file_open_int(this, new_handle, file_name, open_mode,
> +                               attributes);
> +
> +       return EFI_EXIT(ret);
> +}
> +
> +/**
> + * efi_file_open_ex() - open file asynchronously
> + *
> + * This function implements the OpenEx service of the File Protocol.
> + * See the UEFI spec for details.
> + *
> + * @this:      EFI_FILE_PROTOCOL instance
> + * @new_handle:        on return pointer to file handle
> + * @file_name: file name
> + * @open_mode: mode to open the file (read, read/write, create/read/write)
> + * @attributes:        attributes for newly created file
> + * @token:     transaction token
> + */
> +static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *this,
> +                                           struct efi_file_handle **new_handle,
> +                                           u16 *file_name, u64 open_mode,
> +                                           u64 attributes,
> +                                           struct efi_file_io_token *token)
> +{
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu, %p", this, new_handle,
> +                 file_name, open_mode, attributes, token);
> +
> +       if (!token) {
> +               ret = EFI_INVALID_PARAMETER;
> +               goto out;
> +       }
> +
> +       ret = efi_file_open_int(this, new_handle, file_name, open_mode,
> +                               attributes);
> +
> +       if (ret == EFI_SUCCESS && token->event) {
> +               token->status = EFI_SUCCESS;
> +               efi_signal_event(token->event);
> +       }
> +
>  out:
>         return EFI_EXIT(ret);
>  }
> @@ -441,19 +508,15 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
>         return EFI_SUCCESS;
>  }
>
> -static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
> -                                        efi_uintn_t *buffer_size, void *buffer)
> +static efi_status_t efi_file_read_int(struct efi_file_handle *this,
> +                                     efi_uintn_t *buffer_size, void *buffer)
>  {
> -       struct file_handle *fh = to_fh(file);
> +       struct file_handle *fh = to_fh(this);
>         efi_status_t ret = EFI_SUCCESS;
>         u64 bs;
>
> -       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
> -
> -       if (!buffer_size) {
> -               ret = EFI_INVALID_PARAMETER;
> -               goto error;
> -       }
> +       if (!this || !buffer_size || !buffer)
> +               return EFI_INVALID_PARAMETER;
>
>         bs = *buffer_size;
>         if (fh->isdir)
> @@ -465,34 +528,77 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
>         else
>                 *buffer_size = SIZE_MAX;
>
> -error:
> +       return ret;
> +}
> +
> +/**
> + * efi_file_read() - read file
> + *
> + * This function implements the Read() service of the EFI_FILE_PROTOCOL.
> + *
> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> + * details.
> + *
> + * @this:              file protocol instance
> + * @buffer_size:       number of bytes to read
> + * @buffer:            read buffer
> + * Return:             status code
> + */
> +static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *this,
> +                                        efi_uintn_t *buffer_size, void *buffer)
> +{
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
> +
> +       ret = efi_file_read_int(this, buffer_size, buffer);
> +
>         return EFI_EXIT(ret);
>  }
>
>  /**
> - * efi_file_write() - write to file
> + * efi_file_read_ex() - read file asynchonously
>   *
> - * This function implements the Write() service of the EFI_FILE_PROTOCOL.
> + * This function implements the ReadEx() service of the EFI_FILE_PROTOCOL.
>   *
>   * See the Unified Extensible Firmware Interface (UEFI) specification for
>   * details.
>   *
> - * @file:              file handle
> - * @buffer_size:       number of bytes to write
> - * @buffer:            buffer with the bytes to write
> + * @this:              file protocol instance
> + * @token:             transaction token
>   * Return:             status code
>   */
> -static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
> -                                         efi_uintn_t *buffer_size,
> -                                         void *buffer)
> +static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *this,
> +                                           struct efi_file_io_token *token)
>  {
> -       struct file_handle *fh = to_fh(file);
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p, %p", this, token);
> +
> +       if (!token) {
> +               ret = EFI_INVALID_PARAMETER;
> +               goto out;
> +       }
> +
> +       ret = efi_file_read_int(this, &token->buffer_size, token->buffer);
> +
> +       if (ret == EFI_SUCCESS && token->event) {
> +               token->status = EFI_SUCCESS;
> +               efi_signal_event(token->event);
> +       }
> +
> +out:
> +       return EFI_EXIT(ret);
> +}
> +
> +static efi_status_t efi_file_write_int(struct efi_file_handle *this,
> +                                      efi_uintn_t *buffer_size, void *buffer)
> +{
> +       struct file_handle *fh = to_fh(this);
>         efi_status_t ret = EFI_SUCCESS;
>         loff_t actwrite;
>
> -       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
> -
> -       if (!file || !buffer_size || !buffer) {
> +       if (!this || !buffer_size || !buffer) {
>                 ret = EFI_INVALID_PARAMETER;
>                 goto out;
>         }
> @@ -520,6 +626,67 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
>         *buffer_size = actwrite;
>         fh->offset += actwrite;
>
> +out:
> +       return ret;
> +}
> +
> +/**
> + * efi_file_write() - write to file
> + *
> + * This function implements the Write() service of the EFI_FILE_PROTOCOL.
> + *
> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> + * details.
> + *
> + * @this:              file protocol instance
> + * @buffer_size:       number of bytes to write
> + * @buffer:            buffer with the bytes to write
> + * Return:             status code
> + */
> +static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *this,
> +                                         efi_uintn_t *buffer_size,
> +                                         void *buffer)
> +{
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
> +
> +       ret = efi_file_write_int(this, buffer_size, buffer);
> +
> +       return EFI_EXIT(ret);
> +}
> +
> +/**
> + * efi_file_write_ex() - write to file
> + *
> + * This function implements the WriteEx() service of the EFI_FILE_PROTOCOL.
> + *
> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> + * details.
> + *
> + * @this:              file protocol instance
> + * @token:             transaction token
> + * Return:             status code
> + */
> +static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *this,
> +                                            struct efi_file_io_token *token)
> +{
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p, %p", this, token);
> +
> +       if (!token) {
> +               ret = EFI_INVALID_PARAMETER;
> +               goto out;
> +       }
> +
> +       ret = efi_file_write_int(this, &token->buffer_size, token->buffer);
> +
> +       if (ret == EFI_SUCCESS && token->event) {
> +               token->status = EFI_SUCCESS;
> +               efi_signal_event(token->event);
> +       }
> +
>  out:
>         return EFI_EXIT(ret);
>  }
> @@ -761,36 +928,84 @@ out:
>         return EFI_EXIT(ret);
>  }
>
> -static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
> +/**
> + * efi_file_flush_int() - flush file
> + *
> + * This is the internal implementation of the Flush() and FlushEx() services of
> + * the EFI_FILE_PROTOCOL.
> + *
> + * @this:      file protocol instance
> + * Return:     status code
> + */
> +static efi_status_t efi_file_flush_int(struct efi_file_handle *this)
>  {
> -       EFI_ENTRY("%p", file);
> -       return EFI_EXIT(EFI_SUCCESS);
> -}
> +       struct file_handle *fh = to_fh(this);
>
> -static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
> -                       struct efi_file_handle **new_handle,
> -                       u16 *file_name, u64 open_mode, u64 attributes,
> -                       struct efi_file_io_token *token)
> -{
> -       return EFI_UNSUPPORTED;
> -}
> +       if (!this)
> +               return EFI_INVALID_PARAMETER;
>
> -static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
> -                       struct efi_file_io_token *token)
> -{
> -       return EFI_UNSUPPORTED;
> +       if (!(fh->open_mode & EFI_FILE_MODE_WRITE))
> +               return EFI_ACCESS_DENIED;
> +
> +       /* TODO: flush for file position after end of file */
> +       return EFI_SUCCESS;
>  }
>
> -static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
> -                       struct efi_file_io_token *token)
> +/**
> + * efi_file_flush() - flush file
> + *
> + * This function implements the Flush() service of the EFI_FILE_PROTOCOL.
> + *
> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> + * details.
> + *
> + * @this:      file protocol instance
> + * Return:     status code
> + */
> +static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *this)
>  {
> -       return EFI_UNSUPPORTED;
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p", this);
> +
> +       ret = efi_file_flush_int(this);
> +
> +       return EFI_EXIT(ret);
>  }
>
> -static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
> -                       struct efi_file_io_token *token)
> +/**
> + * efi_file_flush_ex() - flush file
> + *
> + * This function implements the FlushEx() service of the EFI_FILE_PROTOCOL.
> + *
> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> + * details.
> + *
> + * @this:      file protocol instance
> + * @token:     transaction token
> + * Return:     status code
> + */
> +static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *this,
> +                                            struct efi_file_io_token *token)
>  {
> -       return EFI_UNSUPPORTED;
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%p, %p", this, token);
> +
> +       if (!token) {
> +               ret = EFI_INVALID_PARAMETER;
> +               goto out;
> +       }
> +
> +       ret = efi_file_flush_int(this);
> +
> +       if (ret == EFI_SUCCESS && token->event) {
> +               token->status = EFI_SUCCESS;
> +               efi_signal_event(token->event);
> +       }
> +
> +out:
> +       return EFI_EXIT(ret);
>  }
>
>  static const struct efi_file_handle efi_file_handle_protocol = {
> --
> 2.29.2
>

I have been trying to boot Fedora 35 Rawhide which booted fine with
2021.01 version but not with 2021.04 version.
I have bisect it and this patch is causing that grub doesn't start
automatically for this image.
(I haven't checked others yet).


U-Boot 2021.01-00398-gdb12f518edb0 (Apr 30 2021 - 12:00:13 +0200)

Model: ZynqMP ZCU104 RevC
Board: Xilinx ZynqMP
DRAM:  2 GiB
PMUFW:  v1.1
EL Level:       EL2
Chip ID:        zu7e
WDT:   Started with servicing (60s timeout)
NAND:  0 MiB
MMC:   mmc at ff170000: 0
Loading Environment from FAT... *** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Bootmode: LVL_SHFT_SD_MODE1
Reset reason:   EXTERNAL
Net:
ZYNQ GEM: ff0e0000, mdio bus ff0e0000, phyaddr 12, interface rgmii-id
eth0: ethernet at ff0e0000
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Scanning disk mmc at ff170000.blk...
Found 4 disks
Loading Boot0000 'Fedora' failed
EFI boot manager: Cannot load any image
Found EFI removable media binary efi/boot/bootaa64.efi
858216 bytes read in 79 ms (10.4 MiB/s)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Booting /efi\boot\bootaa64.efi
System BootOrder not found.  Initializing defaults.
Could not read \EFI\: Invalid Parameter
Error: could not find boot options: Invalid Parameter
start_image() returned Invalid Parameter
## Application failed, r = 2
EFI LOAD FAILED: continuing...
JTAG: Trying to boot script at 0x20000000
## Executing script at 20000000
Wrong image format for "source" command
JTAG: SCRIPT FAILED: continuing...
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Loading Boot0000 'Fedora' failed
EFI boot manager: Cannot load any image
Found EFI removable media binary efi/boot/bootaa64.efi
858216 bytes read in 78 ms (10.5 MiB/s)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Booting /efi\boot\bootaa64.efi
System BootOrder not found.  Initializing defaults.
Could not read \EFI\: Invalid Parameter
Error: could not find boot options: Invalid Parameter
start_image() returned Invalid Parameter
## Application failed, r = 2
EFI LOAD FAILED: continuing...

when this patch is reverted I am getting

eth0: ethernet at ff0e0000
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Scanning disk mmc at ff170000.blk...
Found 4 disks
Loading Boot0000 'Fedora' failed
EFI boot manager: Cannot load any image
Found EFI removable media binary efi/boot/bootaa64.efi
858216 bytes read in 80 ms (10.2 MiB/s)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Booting /efi\boot\bootaa64.efi
System BootOrder not found.  Initializing defaults.

ethernet at ff0e0000 Waiting for PHY auto negotiation to complete. done



      Fedora (5.12.0-0.rc6.20210407git2d743660786e.185.fc35.aarch64)
35 (Rawhide Prerelease)
      UEFI Firmware Settings

...

Do you know what's the problem here?
Peter: Have you ever seen this behavior?

Thanks,
Michal



-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/1] efi_loader: implement non-blocking file services
  2021-04-30 10:09 ` Michal Simek
@ 2021-04-30 10:42   ` Heinrich Schuchardt
  2021-04-30 11:28     ` Michal Simek
  0 siblings, 1 reply; 4+ messages in thread
From: Heinrich Schuchardt @ 2021-04-30 10:42 UTC (permalink / raw)
  To: u-boot

On 30.04.21 12:09, Michal Simek wrote:
> Hi Heinrich,
>
> p? 1. 1. 2021 v 19:29 odes?latel Heinrich Schuchardt
> <xypron.glpk@gmx.de> napsal:
>>
>> Implement services OpenEx(), ReadEx(), WriteEx(), FlushEx() of the
>> EFI_FILE_PROTOCOL.
>>
>> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
>> ---
>>  include/efi_api.h         |  28 ++--
>>  lib/efi_loader/efi_file.c | 317 ++++++++++++++++++++++++++++++++------
>>  2 files changed, 280 insertions(+), 65 deletions(-)
>>
>> diff --git a/include/efi_api.h b/include/efi_api.h
>> index ecb43a0607..2b54ee02a2 100644
>> --- a/include/efi_api.h
>> +++ b/include/efi_api.h
>> @@ -1589,35 +1589,35 @@ struct efi_file_io_token {
>>
>>  struct efi_file_handle {
>>         u64 rev;
>> -       efi_status_t (EFIAPI *open)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *open)(struct efi_file_handle *this,
>>                         struct efi_file_handle **new_handle,
>>                         u16 *file_name, u64 open_mode, u64 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,
>> +       efi_status_t (EFIAPI *close)(struct efi_file_handle *this);
>> +       efi_status_t (EFIAPI *delete)(struct efi_file_handle *this);
>> +       efi_status_t (EFIAPI *read)(struct efi_file_handle *this,
>>                         efi_uintn_t *buffer_size, void *buffer);
>> -       efi_status_t (EFIAPI *write)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *write)(struct efi_file_handle *this,
>>                         efi_uintn_t *buffer_size, void *buffer);
>> -       efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *getpos)(struct efi_file_handle *this,
>>                                       u64 *pos);
>> -       efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *setpos)(struct efi_file_handle *this,
>>                                       u64 pos);
>> -       efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *this,
>>                         const efi_guid_t *info_type, efi_uintn_t *buffer_size,
>>                         void *buffer);
>> -       efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *this,
>>                         const efi_guid_t *info_type, efi_uintn_t buffer_size,
>>                         void *buffer);
>> -       efi_status_t (EFIAPI *flush)(struct efi_file_handle *file);
>> -       efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *flush)(struct efi_file_handle *this);
>> +       efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *this,
>>                         struct efi_file_handle **new_handle,
>>                         u16 *file_name, u64 open_mode, u64 attributes,
>>                         struct efi_file_io_token *token);
>> -       efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *this,
>>                         struct efi_file_io_token *token);
>> -       efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *this,
>>                         struct efi_file_io_token *token);
>> -       efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *file,
>> +       efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *this,
>>                         struct efi_file_io_token *token);
>>  };
>>
>> diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
>> index 72b7ec1e63..8ece8e71ee 100644
>> --- a/lib/efi_loader/efi_file.c
>> +++ b/lib/efi_loader/efi_file.c
>> @@ -246,18 +246,16 @@ error:
>>         return NULL;
>>  }
>>
>> -static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
>> -               struct efi_file_handle **new_handle,
>> -               u16 *file_name, u64 open_mode, u64 attributes)
>> +static efi_status_t efi_file_open_int(struct efi_file_handle *this,
>> +                                     struct efi_file_handle **new_handle,
>> +                                     u16 *file_name, u64 open_mode,
>> +                                     u64 attributes)
>>  {
>> -       struct file_handle *fh = to_fh(file);
>> +       struct file_handle *fh = to_fh(this);
>>         efi_status_t ret;
>>
>> -       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
>> -                 file_name, open_mode, attributes);
>> -
>>         /* Check parameters */
>> -       if (!file || !new_handle || !file_name) {
>> +       if (!this || !new_handle || !file_name) {
>>                 ret = EFI_INVALID_PARAMETER;
>>                 goto out;
>>         }
>> @@ -291,6 +289,75 @@ static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
>>         } else {
>>                 ret = EFI_NOT_FOUND;
>>         }
>> +out:
>> +       return ret;
>> +}
>> +
>> +/**
>> + * efi_file_open_()
>> + *
>> + * This function implements the Open service of the File Protocol.
>> + * See the UEFI spec for details.
>> + *
>> + * @this:      EFI_FILE_PROTOCOL instance
>> + * @new_handle:        on return pointer to file handle
>> + * @file_name: file name
>> + * @open_mode: mode to open the file (read, read/write, create/read/write)
>> + * @attributes:        attributes for newly created file
>> + */
>> +static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *this,
>> +                                        struct efi_file_handle **new_handle,
>> +                                        u16 *file_name, u64 open_mode,
>> +                                        u64 attributes)
>> +{
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", this, new_handle,
>> +                 file_name, open_mode, attributes);
>> +
>> +       ret = efi_file_open_int(this, new_handle, file_name, open_mode,
>> +                               attributes);
>> +
>> +       return EFI_EXIT(ret);
>> +}
>> +
>> +/**
>> + * efi_file_open_ex() - open file asynchronously
>> + *
>> + * This function implements the OpenEx service of the File Protocol.
>> + * See the UEFI spec for details.
>> + *
>> + * @this:      EFI_FILE_PROTOCOL instance
>> + * @new_handle:        on return pointer to file handle
>> + * @file_name: file name
>> + * @open_mode: mode to open the file (read, read/write, create/read/write)
>> + * @attributes:        attributes for newly created file
>> + * @token:     transaction token
>> + */
>> +static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *this,
>> +                                           struct efi_file_handle **new_handle,
>> +                                           u16 *file_name, u64 open_mode,
>> +                                           u64 attributes,
>> +                                           struct efi_file_io_token *token)
>> +{
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu, %p", this, new_handle,
>> +                 file_name, open_mode, attributes, token);
>> +
>> +       if (!token) {
>> +               ret = EFI_INVALID_PARAMETER;
>> +               goto out;
>> +       }
>> +
>> +       ret = efi_file_open_int(this, new_handle, file_name, open_mode,
>> +                               attributes);
>> +
>> +       if (ret == EFI_SUCCESS && token->event) {
>> +               token->status = EFI_SUCCESS;
>> +               efi_signal_event(token->event);
>> +       }
>> +
>>  out:
>>         return EFI_EXIT(ret);
>>  }
>> @@ -441,19 +508,15 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
>>         return EFI_SUCCESS;
>>  }
>>
>> -static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
>> -                                        efi_uintn_t *buffer_size, void *buffer)
>> +static efi_status_t efi_file_read_int(struct efi_file_handle *this,
>> +                                     efi_uintn_t *buffer_size, void *buffer)
>>  {
>> -       struct file_handle *fh = to_fh(file);
>> +       struct file_handle *fh = to_fh(this);
>>         efi_status_t ret = EFI_SUCCESS;
>>         u64 bs;
>>
>> -       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
>> -
>> -       if (!buffer_size) {
>> -               ret = EFI_INVALID_PARAMETER;
>> -               goto error;
>> -       }
>> +       if (!this || !buffer_size || !buffer)
>> +               return EFI_INVALID_PARAMETER;
>>
>>         bs = *buffer_size;
>>         if (fh->isdir)
>> @@ -465,34 +528,77 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
>>         else
>>                 *buffer_size = SIZE_MAX;
>>
>> -error:
>> +       return ret;
>> +}
>> +
>> +/**
>> + * efi_file_read() - read file
>> + *
>> + * This function implements the Read() service of the EFI_FILE_PROTOCOL.
>> + *
>> + * See the Unified Extensible Firmware Interface (UEFI) specification for
>> + * details.
>> + *
>> + * @this:              file protocol instance
>> + * @buffer_size:       number of bytes to read
>> + * @buffer:            read buffer
>> + * Return:             status code
>> + */
>> +static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *this,
>> +                                        efi_uintn_t *buffer_size, void *buffer)
>> +{
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
>> +
>> +       ret = efi_file_read_int(this, buffer_size, buffer);
>> +
>>         return EFI_EXIT(ret);
>>  }
>>
>>  /**
>> - * efi_file_write() - write to file
>> + * efi_file_read_ex() - read file asynchonously
>>   *
>> - * This function implements the Write() service of the EFI_FILE_PROTOCOL.
>> + * This function implements the ReadEx() service of the EFI_FILE_PROTOCOL.
>>   *
>>   * See the Unified Extensible Firmware Interface (UEFI) specification for
>>   * details.
>>   *
>> - * @file:              file handle
>> - * @buffer_size:       number of bytes to write
>> - * @buffer:            buffer with the bytes to write
>> + * @this:              file protocol instance
>> + * @token:             transaction token
>>   * Return:             status code
>>   */
>> -static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
>> -                                         efi_uintn_t *buffer_size,
>> -                                         void *buffer)
>> +static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *this,
>> +                                           struct efi_file_io_token *token)
>>  {
>> -       struct file_handle *fh = to_fh(file);
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p, %p", this, token);
>> +
>> +       if (!token) {
>> +               ret = EFI_INVALID_PARAMETER;
>> +               goto out;
>> +       }
>> +
>> +       ret = efi_file_read_int(this, &token->buffer_size, token->buffer);
>> +
>> +       if (ret == EFI_SUCCESS && token->event) {
>> +               token->status = EFI_SUCCESS;
>> +               efi_signal_event(token->event);
>> +       }
>> +
>> +out:
>> +       return EFI_EXIT(ret);
>> +}
>> +
>> +static efi_status_t efi_file_write_int(struct efi_file_handle *this,
>> +                                      efi_uintn_t *buffer_size, void *buffer)
>> +{
>> +       struct file_handle *fh = to_fh(this);
>>         efi_status_t ret = EFI_SUCCESS;
>>         loff_t actwrite;
>>
>> -       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
>> -
>> -       if (!file || !buffer_size || !buffer) {
>> +       if (!this || !buffer_size || !buffer) {
>>                 ret = EFI_INVALID_PARAMETER;
>>                 goto out;
>>         }
>> @@ -520,6 +626,67 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
>>         *buffer_size = actwrite;
>>         fh->offset += actwrite;
>>
>> +out:
>> +       return ret;
>> +}
>> +
>> +/**
>> + * efi_file_write() - write to file
>> + *
>> + * This function implements the Write() service of the EFI_FILE_PROTOCOL.
>> + *
>> + * See the Unified Extensible Firmware Interface (UEFI) specification for
>> + * details.
>> + *
>> + * @this:              file protocol instance
>> + * @buffer_size:       number of bytes to write
>> + * @buffer:            buffer with the bytes to write
>> + * Return:             status code
>> + */
>> +static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *this,
>> +                                         efi_uintn_t *buffer_size,
>> +                                         void *buffer)
>> +{
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
>> +
>> +       ret = efi_file_write_int(this, buffer_size, buffer);
>> +
>> +       return EFI_EXIT(ret);
>> +}
>> +
>> +/**
>> + * efi_file_write_ex() - write to file
>> + *
>> + * This function implements the WriteEx() service of the EFI_FILE_PROTOCOL.
>> + *
>> + * See the Unified Extensible Firmware Interface (UEFI) specification for
>> + * details.
>> + *
>> + * @this:              file protocol instance
>> + * @token:             transaction token
>> + * Return:             status code
>> + */
>> +static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *this,
>> +                                            struct efi_file_io_token *token)
>> +{
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p, %p", this, token);
>> +
>> +       if (!token) {
>> +               ret = EFI_INVALID_PARAMETER;
>> +               goto out;
>> +       }
>> +
>> +       ret = efi_file_write_int(this, &token->buffer_size, token->buffer);
>> +
>> +       if (ret == EFI_SUCCESS && token->event) {
>> +               token->status = EFI_SUCCESS;
>> +               efi_signal_event(token->event);
>> +       }
>> +
>>  out:
>>         return EFI_EXIT(ret);
>>  }
>> @@ -761,36 +928,84 @@ out:
>>         return EFI_EXIT(ret);
>>  }
>>
>> -static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
>> +/**
>> + * efi_file_flush_int() - flush file
>> + *
>> + * This is the internal implementation of the Flush() and FlushEx() services of
>> + * the EFI_FILE_PROTOCOL.
>> + *
>> + * @this:      file protocol instance
>> + * Return:     status code
>> + */
>> +static efi_status_t efi_file_flush_int(struct efi_file_handle *this)
>>  {
>> -       EFI_ENTRY("%p", file);
>> -       return EFI_EXIT(EFI_SUCCESS);
>> -}
>> +       struct file_handle *fh = to_fh(this);
>>
>> -static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
>> -                       struct efi_file_handle **new_handle,
>> -                       u16 *file_name, u64 open_mode, u64 attributes,
>> -                       struct efi_file_io_token *token)
>> -{
>> -       return EFI_UNSUPPORTED;
>> -}
>> +       if (!this)
>> +               return EFI_INVALID_PARAMETER;
>>
>> -static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
>> -                       struct efi_file_io_token *token)
>> -{
>> -       return EFI_UNSUPPORTED;
>> +       if (!(fh->open_mode & EFI_FILE_MODE_WRITE))
>> +               return EFI_ACCESS_DENIED;
>> +
>> +       /* TODO: flush for file position after end of file */
>> +       return EFI_SUCCESS;
>>  }
>>
>> -static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
>> -                       struct efi_file_io_token *token)
>> +/**
>> + * efi_file_flush() - flush file
>> + *
>> + * This function implements the Flush() service of the EFI_FILE_PROTOCOL.
>> + *
>> + * See the Unified Extensible Firmware Interface (UEFI) specification for
>> + * details.
>> + *
>> + * @this:      file protocol instance
>> + * Return:     status code
>> + */
>> +static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *this)
>>  {
>> -       return EFI_UNSUPPORTED;
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p", this);
>> +
>> +       ret = efi_file_flush_int(this);
>> +
>> +       return EFI_EXIT(ret);
>>  }
>>
>> -static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
>> -                       struct efi_file_io_token *token)
>> +/**
>> + * efi_file_flush_ex() - flush file
>> + *
>> + * This function implements the FlushEx() service of the EFI_FILE_PROTOCOL.
>> + *
>> + * See the Unified Extensible Firmware Interface (UEFI) specification for
>> + * details.
>> + *
>> + * @this:      file protocol instance
>> + * @token:     transaction token
>> + * Return:     status code
>> + */
>> +static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *this,
>> +                                            struct efi_file_io_token *token)
>>  {
>> -       return EFI_UNSUPPORTED;
>> +       efi_status_t ret;
>> +
>> +       EFI_ENTRY("%p, %p", this, token);
>> +
>> +       if (!token) {
>> +               ret = EFI_INVALID_PARAMETER;
>> +               goto out;
>> +       }
>> +
>> +       ret = efi_file_flush_int(this);
>> +
>> +       if (ret == EFI_SUCCESS && token->event) {
>> +               token->status = EFI_SUCCESS;
>> +               efi_signal_event(token->event);
>> +       }
>> +
>> +out:
>> +       return EFI_EXIT(ret);
>>  }
>>
>>  static const struct efi_file_handle efi_file_handle_protocol = {
>> --
>> 2.29.2
>>
>
> I have been trying to boot Fedora 35 Rawhide which booted fine with
> 2021.01 version but not with 2021.04 version.
> I have bisect it and this patch is causing that grub doesn't start
> automatically for this image.
> (I haven't checked others yet).
>
>
> U-Boot 2021.01-00398-gdb12f518edb0 (Apr 30 2021 - 12:00:13 +0200)
>
> Model: ZynqMP ZCU104 RevC
> Board: Xilinx ZynqMP
> DRAM:  2 GiB
> PMUFW:  v1.1
> EL Level:       EL2
> Chip ID:        zu7e
> WDT:   Started with servicing (60s timeout)
> NAND:  0 MiB
> MMC:   mmc at ff170000: 0
> Loading Environment from FAT... *** Warning - bad CRC, using default environment
>
> In:    serial
> Out:   serial
> Err:   serial
> Bootmode: LVL_SHFT_SD_MODE1
> Reset reason:   EXTERNAL
> Net:
> ZYNQ GEM: ff0e0000, mdio bus ff0e0000, phyaddr 12, interface rgmii-id
> eth0: ethernet at ff0e0000
> Hit any key to stop autoboot:  0
> switch to partitions #0, OK
> mmc0 is current device
> Scanning mmc 0:1...
> libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> Scanning disk mmc at ff170000.blk...
> Found 4 disks
> Loading Boot0000 'Fedora' failed
> EFI boot manager: Cannot load any image
> Found EFI removable media binary efi/boot/bootaa64.efi
> 858216 bytes read in 79 ms (10.4 MiB/s)
> libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> Booting /efi\boot\bootaa64.efi
> System BootOrder not found.  Initializing defaults.
> Could not read \EFI\: Invalid Parameter
> Error: could not find boot options: Invalid Parameter
> start_image() returned Invalid Parameter
> ## Application failed, r = 2
> EFI LOAD FAILED: continuing...
> JTAG: Trying to boot script at 0x20000000
> ## Executing script at 20000000
> Wrong image format for "source" command
> JTAG: SCRIPT FAILED: continuing...
> switch to partitions #0, OK
> mmc0 is current device
> Scanning mmc 0:1...
> libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> Loading Boot0000 'Fedora' failed
> EFI boot manager: Cannot load any image
> Found EFI removable media binary efi/boot/bootaa64.efi
> 858216 bytes read in 78 ms (10.5 MiB/s)
> libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> Booting /efi\boot\bootaa64.efi
> System BootOrder not found.  Initializing defaults.
> Could not read \EFI\: Invalid Parameter
> Error: could not find boot options: Invalid Parameter
> start_image() returned Invalid Parameter
> ## Application failed, r = 2
> EFI LOAD FAILED: continuing...
>
> when this patch is reverted I am getting
>
> eth0: ethernet at ff0e0000
> Hit any key to stop autoboot:  0
> switch to partitions #0, OK
> mmc0 is current device
> Scanning mmc 0:1...
> libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> Scanning disk mmc at ff170000.blk...
> Found 4 disks
> Loading Boot0000 'Fedora' failed
> EFI boot manager: Cannot load any image
> Found EFI removable media binary efi/boot/bootaa64.efi
> 858216 bytes read in 80 ms (10.2 MiB/s)
> libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> Booting /efi\boot\bootaa64.efi
> System BootOrder not found.  Initializing defaults.
>
> ethernet at ff0e0000 Waiting for PHY auto negotiation to complete. done
>
>
>
>       Fedora (5.12.0-0.rc6.20210407git2d743660786e.185.fc35.aarch64)
> 35 (Rawhide Prerelease)
>       UEFI Firmware Settings
>
> ...
>
> Do you know what's the problem here?
> Peter: Have you ever seen this behavior?

The following patch is already queued for my next pull request:

[Patch V2] efi_loader: loosen buffer parameter check in efi_file_read_int
https://patchwork.ozlabs.org/project/uboot/patch/20210428135401.22365-1-peng.fan at oss.nxp.com/

Does it solve you problem?

Best regards

Heinrich


>
> Thanks,
> Michal
>
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/1] efi_loader: implement non-blocking file services
  2021-04-30 10:42   ` Heinrich Schuchardt
@ 2021-04-30 11:28     ` Michal Simek
  0 siblings, 0 replies; 4+ messages in thread
From: Michal Simek @ 2021-04-30 11:28 UTC (permalink / raw)
  To: u-boot

p? 30. 4. 2021 v 12:42 odes?latel Heinrich Schuchardt
<xypron.glpk@gmx.de> napsal:
>
> On 30.04.21 12:09, Michal Simek wrote:
> > Hi Heinrich,
> >
> > p? 1. 1. 2021 v 19:29 odes?latel Heinrich Schuchardt
> > <xypron.glpk@gmx.de> napsal:
> >>
> >> Implement services OpenEx(), ReadEx(), WriteEx(), FlushEx() of the
> >> EFI_FILE_PROTOCOL.
> >>
> >> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >> ---
> >>  include/efi_api.h         |  28 ++--
> >>  lib/efi_loader/efi_file.c | 317 ++++++++++++++++++++++++++++++++------
> >>  2 files changed, 280 insertions(+), 65 deletions(-)
> >>
> >> diff --git a/include/efi_api.h b/include/efi_api.h
> >> index ecb43a0607..2b54ee02a2 100644
> >> --- a/include/efi_api.h
> >> +++ b/include/efi_api.h
> >> @@ -1589,35 +1589,35 @@ struct efi_file_io_token {
> >>
> >>  struct efi_file_handle {
> >>         u64 rev;
> >> -       efi_status_t (EFIAPI *open)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *open)(struct efi_file_handle *this,
> >>                         struct efi_file_handle **new_handle,
> >>                         u16 *file_name, u64 open_mode, u64 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,
> >> +       efi_status_t (EFIAPI *close)(struct efi_file_handle *this);
> >> +       efi_status_t (EFIAPI *delete)(struct efi_file_handle *this);
> >> +       efi_status_t (EFIAPI *read)(struct efi_file_handle *this,
> >>                         efi_uintn_t *buffer_size, void *buffer);
> >> -       efi_status_t (EFIAPI *write)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *write)(struct efi_file_handle *this,
> >>                         efi_uintn_t *buffer_size, void *buffer);
> >> -       efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *getpos)(struct efi_file_handle *this,
> >>                                       u64 *pos);
> >> -       efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *setpos)(struct efi_file_handle *this,
> >>                                       u64 pos);
> >> -       efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *this,
> >>                         const efi_guid_t *info_type, efi_uintn_t *buffer_size,
> >>                         void *buffer);
> >> -       efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *this,
> >>                         const efi_guid_t *info_type, efi_uintn_t buffer_size,
> >>                         void *buffer);
> >> -       efi_status_t (EFIAPI *flush)(struct efi_file_handle *file);
> >> -       efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *flush)(struct efi_file_handle *this);
> >> +       efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *this,
> >>                         struct efi_file_handle **new_handle,
> >>                         u16 *file_name, u64 open_mode, u64 attributes,
> >>                         struct efi_file_io_token *token);
> >> -       efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *this,
> >>                         struct efi_file_io_token *token);
> >> -       efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *this,
> >>                         struct efi_file_io_token *token);
> >> -       efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *file,
> >> +       efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *this,
> >>                         struct efi_file_io_token *token);
> >>  };
> >>
> >> diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
> >> index 72b7ec1e63..8ece8e71ee 100644
> >> --- a/lib/efi_loader/efi_file.c
> >> +++ b/lib/efi_loader/efi_file.c
> >> @@ -246,18 +246,16 @@ error:
> >>         return NULL;
> >>  }
> >>
> >> -static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
> >> -               struct efi_file_handle **new_handle,
> >> -               u16 *file_name, u64 open_mode, u64 attributes)
> >> +static efi_status_t efi_file_open_int(struct efi_file_handle *this,
> >> +                                     struct efi_file_handle **new_handle,
> >> +                                     u16 *file_name, u64 open_mode,
> >> +                                     u64 attributes)
> >>  {
> >> -       struct file_handle *fh = to_fh(file);
> >> +       struct file_handle *fh = to_fh(this);
> >>         efi_status_t ret;
> >>
> >> -       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
> >> -                 file_name, open_mode, attributes);
> >> -
> >>         /* Check parameters */
> >> -       if (!file || !new_handle || !file_name) {
> >> +       if (!this || !new_handle || !file_name) {
> >>                 ret = EFI_INVALID_PARAMETER;
> >>                 goto out;
> >>         }
> >> @@ -291,6 +289,75 @@ static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
> >>         } else {
> >>                 ret = EFI_NOT_FOUND;
> >>         }
> >> +out:
> >> +       return ret;
> >> +}
> >> +
> >> +/**
> >> + * efi_file_open_()
> >> + *
> >> + * This function implements the Open service of the File Protocol.
> >> + * See the UEFI spec for details.
> >> + *
> >> + * @this:      EFI_FILE_PROTOCOL instance
> >> + * @new_handle:        on return pointer to file handle
> >> + * @file_name: file name
> >> + * @open_mode: mode to open the file (read, read/write, create/read/write)
> >> + * @attributes:        attributes for newly created file
> >> + */
> >> +static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *this,
> >> +                                        struct efi_file_handle **new_handle,
> >> +                                        u16 *file_name, u64 open_mode,
> >> +                                        u64 attributes)
> >> +{
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", this, new_handle,
> >> +                 file_name, open_mode, attributes);
> >> +
> >> +       ret = efi_file_open_int(this, new_handle, file_name, open_mode,
> >> +                               attributes);
> >> +
> >> +       return EFI_EXIT(ret);
> >> +}
> >> +
> >> +/**
> >> + * efi_file_open_ex() - open file asynchronously
> >> + *
> >> + * This function implements the OpenEx service of the File Protocol.
> >> + * See the UEFI spec for details.
> >> + *
> >> + * @this:      EFI_FILE_PROTOCOL instance
> >> + * @new_handle:        on return pointer to file handle
> >> + * @file_name: file name
> >> + * @open_mode: mode to open the file (read, read/write, create/read/write)
> >> + * @attributes:        attributes for newly created file
> >> + * @token:     transaction token
> >> + */
> >> +static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *this,
> >> +                                           struct efi_file_handle **new_handle,
> >> +                                           u16 *file_name, u64 open_mode,
> >> +                                           u64 attributes,
> >> +                                           struct efi_file_io_token *token)
> >> +{
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu, %p", this, new_handle,
> >> +                 file_name, open_mode, attributes, token);
> >> +
> >> +       if (!token) {
> >> +               ret = EFI_INVALID_PARAMETER;
> >> +               goto out;
> >> +       }
> >> +
> >> +       ret = efi_file_open_int(this, new_handle, file_name, open_mode,
> >> +                               attributes);
> >> +
> >> +       if (ret == EFI_SUCCESS && token->event) {
> >> +               token->status = EFI_SUCCESS;
> >> +               efi_signal_event(token->event);
> >> +       }
> >> +
> >>  out:
> >>         return EFI_EXIT(ret);
> >>  }
> >> @@ -441,19 +508,15 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
> >>         return EFI_SUCCESS;
> >>  }
> >>
> >> -static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
> >> -                                        efi_uintn_t *buffer_size, void *buffer)
> >> +static efi_status_t efi_file_read_int(struct efi_file_handle *this,
> >> +                                     efi_uintn_t *buffer_size, void *buffer)
> >>  {
> >> -       struct file_handle *fh = to_fh(file);
> >> +       struct file_handle *fh = to_fh(this);
> >>         efi_status_t ret = EFI_SUCCESS;
> >>         u64 bs;
> >>
> >> -       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
> >> -
> >> -       if (!buffer_size) {
> >> -               ret = EFI_INVALID_PARAMETER;
> >> -               goto error;
> >> -       }
> >> +       if (!this || !buffer_size || !buffer)
> >> +               return EFI_INVALID_PARAMETER;
> >>
> >>         bs = *buffer_size;
> >>         if (fh->isdir)
> >> @@ -465,34 +528,77 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
> >>         else
> >>                 *buffer_size = SIZE_MAX;
> >>
> >> -error:
> >> +       return ret;
> >> +}
> >> +
> >> +/**
> >> + * efi_file_read() - read file
> >> + *
> >> + * This function implements the Read() service of the EFI_FILE_PROTOCOL.
> >> + *
> >> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> >> + * details.
> >> + *
> >> + * @this:              file protocol instance
> >> + * @buffer_size:       number of bytes to read
> >> + * @buffer:            read buffer
> >> + * Return:             status code
> >> + */
> >> +static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *this,
> >> +                                        efi_uintn_t *buffer_size, void *buffer)
> >> +{
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
> >> +
> >> +       ret = efi_file_read_int(this, buffer_size, buffer);
> >> +
> >>         return EFI_EXIT(ret);
> >>  }
> >>
> >>  /**
> >> - * efi_file_write() - write to file
> >> + * efi_file_read_ex() - read file asynchonously
> >>   *
> >> - * This function implements the Write() service of the EFI_FILE_PROTOCOL.
> >> + * This function implements the ReadEx() service of the EFI_FILE_PROTOCOL.
> >>   *
> >>   * See the Unified Extensible Firmware Interface (UEFI) specification for
> >>   * details.
> >>   *
> >> - * @file:              file handle
> >> - * @buffer_size:       number of bytes to write
> >> - * @buffer:            buffer with the bytes to write
> >> + * @this:              file protocol instance
> >> + * @token:             transaction token
> >>   * Return:             status code
> >>   */
> >> -static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
> >> -                                         efi_uintn_t *buffer_size,
> >> -                                         void *buffer)
> >> +static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *this,
> >> +                                           struct efi_file_io_token *token)
> >>  {
> >> -       struct file_handle *fh = to_fh(file);
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p, %p", this, token);
> >> +
> >> +       if (!token) {
> >> +               ret = EFI_INVALID_PARAMETER;
> >> +               goto out;
> >> +       }
> >> +
> >> +       ret = efi_file_read_int(this, &token->buffer_size, token->buffer);
> >> +
> >> +       if (ret == EFI_SUCCESS && token->event) {
> >> +               token->status = EFI_SUCCESS;
> >> +               efi_signal_event(token->event);
> >> +       }
> >> +
> >> +out:
> >> +       return EFI_EXIT(ret);
> >> +}
> >> +
> >> +static efi_status_t efi_file_write_int(struct efi_file_handle *this,
> >> +                                      efi_uintn_t *buffer_size, void *buffer)
> >> +{
> >> +       struct file_handle *fh = to_fh(this);
> >>         efi_status_t ret = EFI_SUCCESS;
> >>         loff_t actwrite;
> >>
> >> -       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
> >> -
> >> -       if (!file || !buffer_size || !buffer) {
> >> +       if (!this || !buffer_size || !buffer) {
> >>                 ret = EFI_INVALID_PARAMETER;
> >>                 goto out;
> >>         }
> >> @@ -520,6 +626,67 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
> >>         *buffer_size = actwrite;
> >>         fh->offset += actwrite;
> >>
> >> +out:
> >> +       return ret;
> >> +}
> >> +
> >> +/**
> >> + * efi_file_write() - write to file
> >> + *
> >> + * This function implements the Write() service of the EFI_FILE_PROTOCOL.
> >> + *
> >> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> >> + * details.
> >> + *
> >> + * @this:              file protocol instance
> >> + * @buffer_size:       number of bytes to write
> >> + * @buffer:            buffer with the bytes to write
> >> + * Return:             status code
> >> + */
> >> +static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *this,
> >> +                                         efi_uintn_t *buffer_size,
> >> +                                         void *buffer)
> >> +{
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
> >> +
> >> +       ret = efi_file_write_int(this, buffer_size, buffer);
> >> +
> >> +       return EFI_EXIT(ret);
> >> +}
> >> +
> >> +/**
> >> + * efi_file_write_ex() - write to file
> >> + *
> >> + * This function implements the WriteEx() service of the EFI_FILE_PROTOCOL.
> >> + *
> >> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> >> + * details.
> >> + *
> >> + * @this:              file protocol instance
> >> + * @token:             transaction token
> >> + * Return:             status code
> >> + */
> >> +static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *this,
> >> +                                            struct efi_file_io_token *token)
> >> +{
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p, %p", this, token);
> >> +
> >> +       if (!token) {
> >> +               ret = EFI_INVALID_PARAMETER;
> >> +               goto out;
> >> +       }
> >> +
> >> +       ret = efi_file_write_int(this, &token->buffer_size, token->buffer);
> >> +
> >> +       if (ret == EFI_SUCCESS && token->event) {
> >> +               token->status = EFI_SUCCESS;
> >> +               efi_signal_event(token->event);
> >> +       }
> >> +
> >>  out:
> >>         return EFI_EXIT(ret);
> >>  }
> >> @@ -761,36 +928,84 @@ out:
> >>         return EFI_EXIT(ret);
> >>  }
> >>
> >> -static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
> >> +/**
> >> + * efi_file_flush_int() - flush file
> >> + *
> >> + * This is the internal implementation of the Flush() and FlushEx() services of
> >> + * the EFI_FILE_PROTOCOL.
> >> + *
> >> + * @this:      file protocol instance
> >> + * Return:     status code
> >> + */
> >> +static efi_status_t efi_file_flush_int(struct efi_file_handle *this)
> >>  {
> >> -       EFI_ENTRY("%p", file);
> >> -       return EFI_EXIT(EFI_SUCCESS);
> >> -}
> >> +       struct file_handle *fh = to_fh(this);
> >>
> >> -static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
> >> -                       struct efi_file_handle **new_handle,
> >> -                       u16 *file_name, u64 open_mode, u64 attributes,
> >> -                       struct efi_file_io_token *token)
> >> -{
> >> -       return EFI_UNSUPPORTED;
> >> -}
> >> +       if (!this)
> >> +               return EFI_INVALID_PARAMETER;
> >>
> >> -static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
> >> -                       struct efi_file_io_token *token)
> >> -{
> >> -       return EFI_UNSUPPORTED;
> >> +       if (!(fh->open_mode & EFI_FILE_MODE_WRITE))
> >> +               return EFI_ACCESS_DENIED;
> >> +
> >> +       /* TODO: flush for file position after end of file */
> >> +       return EFI_SUCCESS;
> >>  }
> >>
> >> -static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
> >> -                       struct efi_file_io_token *token)
> >> +/**
> >> + * efi_file_flush() - flush file
> >> + *
> >> + * This function implements the Flush() service of the EFI_FILE_PROTOCOL.
> >> + *
> >> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> >> + * details.
> >> + *
> >> + * @this:      file protocol instance
> >> + * Return:     status code
> >> + */
> >> +static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *this)
> >>  {
> >> -       return EFI_UNSUPPORTED;
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p", this);
> >> +
> >> +       ret = efi_file_flush_int(this);
> >> +
> >> +       return EFI_EXIT(ret);
> >>  }
> >>
> >> -static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
> >> -                       struct efi_file_io_token *token)
> >> +/**
> >> + * efi_file_flush_ex() - flush file
> >> + *
> >> + * This function implements the FlushEx() service of the EFI_FILE_PROTOCOL.
> >> + *
> >> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> >> + * details.
> >> + *
> >> + * @this:      file protocol instance
> >> + * @token:     transaction token
> >> + * Return:     status code
> >> + */
> >> +static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *this,
> >> +                                            struct efi_file_io_token *token)
> >>  {
> >> -       return EFI_UNSUPPORTED;
> >> +       efi_status_t ret;
> >> +
> >> +       EFI_ENTRY("%p, %p", this, token);
> >> +
> >> +       if (!token) {
> >> +               ret = EFI_INVALID_PARAMETER;
> >> +               goto out;
> >> +       }
> >> +
> >> +       ret = efi_file_flush_int(this);
> >> +
> >> +       if (ret == EFI_SUCCESS && token->event) {
> >> +               token->status = EFI_SUCCESS;
> >> +               efi_signal_event(token->event);
> >> +       }
> >> +
> >> +out:
> >> +       return EFI_EXIT(ret);
> >>  }
> >>
> >>  static const struct efi_file_handle efi_file_handle_protocol = {
> >> --
> >> 2.29.2
> >>
> >
> > I have been trying to boot Fedora 35 Rawhide which booted fine with
> > 2021.01 version but not with 2021.04 version.
> > I have bisect it and this patch is causing that grub doesn't start
> > automatically for this image.
> > (I haven't checked others yet).
> >
> >
> > U-Boot 2021.01-00398-gdb12f518edb0 (Apr 30 2021 - 12:00:13 +0200)
> >
> > Model: ZynqMP ZCU104 RevC
> > Board: Xilinx ZynqMP
> > DRAM:  2 GiB
> > PMUFW:  v1.1
> > EL Level:       EL2
> > Chip ID:        zu7e
> > WDT:   Started with servicing (60s timeout)
> > NAND:  0 MiB
> > MMC:   mmc at ff170000: 0
> > Loading Environment from FAT... *** Warning - bad CRC, using default environment
> >
> > In:    serial
> > Out:   serial
> > Err:   serial
> > Bootmode: LVL_SHFT_SD_MODE1
> > Reset reason:   EXTERNAL
> > Net:
> > ZYNQ GEM: ff0e0000, mdio bus ff0e0000, phyaddr 12, interface rgmii-id
> > eth0: ethernet at ff0e0000
> > Hit any key to stop autoboot:  0
> > switch to partitions #0, OK
> > mmc0 is current device
> > Scanning mmc 0:1...
> > libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> > Scanning disk mmc at ff170000.blk...
> > Found 4 disks
> > Loading Boot0000 'Fedora' failed
> > EFI boot manager: Cannot load any image
> > Found EFI removable media binary efi/boot/bootaa64.efi
> > 858216 bytes read in 79 ms (10.4 MiB/s)
> > libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> > Booting /efi\boot\bootaa64.efi
> > System BootOrder not found.  Initializing defaults.
> > Could not read \EFI\: Invalid Parameter
> > Error: could not find boot options: Invalid Parameter
> > start_image() returned Invalid Parameter
> > ## Application failed, r = 2
> > EFI LOAD FAILED: continuing...
> > JTAG: Trying to boot script at 0x20000000
> > ## Executing script at 20000000
> > Wrong image format for "source" command
> > JTAG: SCRIPT FAILED: continuing...
> > switch to partitions #0, OK
> > mmc0 is current device
> > Scanning mmc 0:1...
> > libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> > Loading Boot0000 'Fedora' failed
> > EFI boot manager: Cannot load any image
> > Found EFI removable media binary efi/boot/bootaa64.efi
> > 858216 bytes read in 78 ms (10.5 MiB/s)
> > libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> > Booting /efi\boot\bootaa64.efi
> > System BootOrder not found.  Initializing defaults.
> > Could not read \EFI\: Invalid Parameter
> > Error: could not find boot options: Invalid Parameter
> > start_image() returned Invalid Parameter
> > ## Application failed, r = 2
> > EFI LOAD FAILED: continuing...
> >
> > when this patch is reverted I am getting
> >
> > eth0: ethernet at ff0e0000
> > Hit any key to stop autoboot:  0
> > switch to partitions #0, OK
> > mmc0 is current device
> > Scanning mmc 0:1...
> > libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> > Scanning disk mmc at ff170000.blk...
> > Found 4 disks
> > Loading Boot0000 'Fedora' failed
> > EFI boot manager: Cannot load any image
> > Found EFI removable media binary efi/boot/bootaa64.efi
> > 858216 bytes read in 80 ms (10.2 MiB/s)
> > libfdt fdt_check_header(): FDT_ERR_BADMAGIC
> > Booting /efi\boot\bootaa64.efi
> > System BootOrder not found.  Initializing defaults.
> >
> > ethernet at ff0e0000 Waiting for PHY auto negotiation to complete. done
> >
> >
> >
> >       Fedora (5.12.0-0.rc6.20210407git2d743660786e.185.fc35.aarch64)
> > 35 (Rawhide Prerelease)
> >       UEFI Firmware Settings
> >
> > ...
> >
> > Do you know what's the problem here?
> > Peter: Have you ever seen this behavior?
>
> The following patch is already queued for my next pull request:
>
> [Patch V2] efi_loader: loosen buffer parameter check in efi_file_read_int
> https://patchwork.ozlabs.org/project/uboot/patch/20210428135401.22365-1-peng.fan at oss.nxp.com/
>
> Does it solve you problem?

yes it does. Will reply to that thread.
Another thing that I found (and talked to Peter about) is that
standard fedora rawhide image use the first
FAT partitions with type 0xc but for saving efi variables you need to
have 0xef type.
For Xilinx bootrom there is no issue to use 0xef type but it is just
hassle to do so.
Can u-boot be a little bit more flexible on this and also accept 0xc
partition type for saving it?

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-04-30 11:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-01 18:29 [PATCH 1/1] efi_loader: implement non-blocking file services Heinrich Schuchardt
2021-04-30 10:09 ` Michal Simek
2021-04-30 10:42   ` Heinrich Schuchardt
2021-04-30 11:28     ` Michal Simek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.