All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] bootstd: android: don't read whole partition sizes
@ 2024-11-21 10:59 Julien Masson
  2024-11-22 10:17 ` Mattijs Korpershoek
  2024-11-26  9:05 ` Mattijs Korpershoek
  0 siblings, 2 replies; 3+ messages in thread
From: Julien Masson @ 2024-11-21 10:59 UTC (permalink / raw)
  To: Simon Glass, Mattijs Korpershoek, Tom Rini; +Cc: u-boot, Julien Masson

The current implementation is reading the whole partition for boot and
vendor_boot image which can be long following the size of the
partition or the time to read blocks (driver/SoC specific).

For example with mediatek mt8365 EVK board, we have a 64MiB boot
partition and the boot image flashed in this partition is only 42MiB.
It takes ~8-9 secs to read the boot partition.

Instead we can retrieved the boot image and vendor boot image size
with these new functions:
- android_image_get_bootimg_size
- android_image_get_vendor_bootimg_size
Use these information and read only the necessary.

By doing this with mt8365 EVK board, we read boot image in ~5 secs.

Signed-off-by: Julien Masson <jmasson@baylibre.com>
---
Changes have been tested with:
$ ./test/py/test.py --bd sandbox --build -k ut_bootstd_bootflow_android_image_v4
$ ./test/py/test.py --bd sandbox --build -k ut_bootstd_bootflow_android_image_v2
---
 boot/bootmeth_android.c | 28 +++++++++++++++++++++++-----
 boot/image-android.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/image.h         | 24 ++++++++++++++++++++++++
 3 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
index 2aac32331d3c28853bc87d05a8c76ae868ea97c7..3a5144aaa3b0125cf13ff1805b05e87385263308 100644
--- a/boot/bootmeth_android.c
+++ b/boot/bootmeth_android.c
@@ -45,6 +45,8 @@ struct android_priv {
 	enum android_boot_mode boot_mode;
 	char *slot;
 	u32 header_version;
+	u32 boot_img_size;
+	u32 vendor_boot_img_size;
 };
 
 static int android_check(struct udevice *dev, struct bootflow_iter *iter)
@@ -98,7 +100,13 @@ static int scan_boot_part(struct udevice *blk, struct android_priv *priv)
 		return log_msg_ret("header", -ENOENT);
 	}
 
+	if (!android_image_get_bootimg_size(buf, &priv->boot_img_size)) {
+		free(buf);
+		return log_msg_ret("get bootimg size", -EINVAL);
+	}
+
 	priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version;
+
 	free(buf);
 
 	return 0;
@@ -138,6 +146,12 @@ static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv)
 		free(buf);
 		return log_msg_ret("header", -ENOENT);
 	}
+
+	if (!android_image_get_vendor_bootimg_size(buf, &priv->vendor_boot_img_size)) {
+		free(buf);
+		return log_msg_ret("get vendor bootimg size", -EINVAL);
+	}
+
 	free(buf);
 
 	return 0;
@@ -330,15 +344,17 @@ static int android_read_file(struct udevice *dev, struct bootflow *bflow,
  * @blk: Block device to read
  * @name: Partition name to read
  * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0")
+ * @image_size: Image size in bytes used when reading the partition
  * @addr: Address where the partition content is loaded into
  * Return: 0 if OK, negative errno on failure.
  */
 static int read_slotted_partition(struct blk_desc *desc, const char *const name,
-				  const char slot[2], ulong addr)
+				  const char slot[2], ulong image_size, ulong addr)
 {
 	struct disk_partition partition;
 	char partname[PART_NAME_LEN];
 	size_t partname_len;
+	ulong num_blks = DIV_ROUND_UP(image_size, desc->blksz);
 	int ret;
 	u32 n;
 
@@ -364,8 +380,8 @@ static int read_slotted_partition(struct blk_desc *desc, const char *const name,
 	if (ret < 0)
 		return log_msg_ret("part", ret);
 
-	n = blk_dread(desc, partition.start, partition.size, map_sysmem(addr, 0));
-	if (n < partition.size)
+	n = blk_dread(desc, partition.start, num_blks, map_sysmem(addr, 0));
+	if (n < num_blks)
 		return log_msg_ret("part read", -EIO);
 
 	return 0;
@@ -498,12 +514,14 @@ static int boot_android_normal(struct bootflow *bflow)
 	if (ret < 0)
 		return log_msg_ret("read slot", ret);
 
-	ret = read_slotted_partition(desc, "boot", priv->slot, loadaddr);
+	ret = read_slotted_partition(desc, "boot", priv->slot, priv->boot_img_size,
+				     loadaddr);
 	if (ret < 0)
 		return log_msg_ret("read boot", ret);
 
 	if (priv->header_version >= 3) {
-		ret = read_slotted_partition(desc, "vendor_boot", priv->slot, vloadaddr);
+		ret = read_slotted_partition(desc, "vendor_boot", priv->slot,
+					     priv->vendor_boot_img_size, vloadaddr);
 		if (ret < 0)
 			return log_msg_ret("read vendor_boot", ret);
 		set_avendor_bootimg_addr(vloadaddr);
diff --git a/boot/image-android.c b/boot/image-android.c
index cd01278f211d63262f2bdad7aa1176e2c1bbfedd..93b54bf8d7936862693d56d5b75343575f3e6293 100644
--- a/boot/image-android.c
+++ b/boot/image-android.c
@@ -178,6 +178,51 @@ static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr
 	data->boot_img_total_size = end - (ulong)hdr;
 }
 
+bool android_image_get_bootimg_size(const void *hdr, u32 *boot_img_size)
+{
+	struct andr_image_data data;
+
+	if (!hdr || !boot_img_size) {
+		printf("hdr or boot_img_size can't be NULL\n");
+		return false;
+	}
+
+	if (!is_android_boot_image_header(hdr)) {
+		printf("Incorrect boot image header\n");
+		return false;
+	}
+
+	if (((struct andr_boot_img_hdr_v0 *)hdr)->header_version <= 2)
+		android_boot_image_v0_v1_v2_parse_hdr(hdr, &data);
+	else
+		android_boot_image_v3_v4_parse_hdr(hdr, &data);
+
+	*boot_img_size = data.boot_img_total_size;
+
+	return true;
+}
+
+bool android_image_get_vendor_bootimg_size(const void *hdr, u32 *vendor_boot_img_size)
+{
+	struct andr_image_data data;
+
+	if (!hdr || !vendor_boot_img_size) {
+		printf("hdr or vendor_boot_img_size can't be NULL\n");
+		return false;
+	}
+
+	if (!is_android_vendor_boot_image_header(hdr)) {
+		printf("Incorrect vendor boot image header\n");
+		return false;
+	}
+
+	android_vendor_boot_image_v3_v4_parse_hdr(hdr, &data);
+
+	*vendor_boot_img_size = data.vendor_boot_img_total_size;
+
+	return true;
+}
+
 bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr,
 			    struct andr_image_data *data)
 {
diff --git a/include/image.h b/include/image.h
index c52fced9b409b1f963daa4ab6c266909ca035aff..9be5acd8158f00930ab1f3988b8f577817acd1fe 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1801,6 +1801,30 @@ int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo);
 struct cipher_algo *image_get_cipher_algo(const char *full_name);
 struct andr_image_data;
 
+/**
+ * android_image_get_bootimg_size() - Extract size of Android boot image
+ *
+ * This is used to extract the size of an Android boot image
+ * from boot image header.
+ *
+ * @hdr: Pointer to boot image header
+ * @boot_img_size: On exit returns the size in bytes of the boot image
+ * Return: true if succeeded, false otherwise
+ */
+bool android_image_get_bootimg_size(const void *hdr, u32 *boot_img_size);
+
+/**
+ * android_image_get_vendor_bootimg_size() - Extract size of Android vendor-boot image
+ *
+ * This is used to extract the size of an Android vendor-boot image
+ * from vendor-boot image header.
+ *
+ * @hdr: Pointer to vendor-boot image header
+ * @vendor_boot_img_size: On exit returns the size in bytes of the vendor-boot image
+ * Return: true if succeeded, false otherwise
+ */
+bool android_image_get_vendor_bootimg_size(const void *hdr, u32 *vendor_boot_img_size);
+
 /**
  * android_image_get_data() - Parse Android boot images
  *

---
base-commit: acaa7f35a33146f887948d34130229388280844a
change-id: 20241121-bootmeth-android-part-sizes-ff2866e0d079

Best regards,
-- 
Julien Masson <jmasson@baylibre.com>


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

* Re: [PATCH] bootstd: android: don't read whole partition sizes
  2024-11-21 10:59 [PATCH] bootstd: android: don't read whole partition sizes Julien Masson
@ 2024-11-22 10:17 ` Mattijs Korpershoek
  2024-11-26  9:05 ` Mattijs Korpershoek
  1 sibling, 0 replies; 3+ messages in thread
From: Mattijs Korpershoek @ 2024-11-22 10:17 UTC (permalink / raw)
  To: Julien Masson, Simon Glass, Tom Rini; +Cc: u-boot, Julien Masson

Hi Julien,

Thank you for the patch.

On jeu., nov. 21, 2024 at 11:59, Julien Masson <jmasson@baylibre.com> wrote:

> The current implementation is reading the whole partition for boot and
> vendor_boot image which can be long following the size of the
> partition or the time to read blocks (driver/SoC specific).
>
> For example with mediatek mt8365 EVK board, we have a 64MiB boot
> partition and the boot image flashed in this partition is only 42MiB.
> It takes ~8-9 secs to read the boot partition.
>
> Instead we can retrieved the boot image and vendor boot image size
> with these new functions:
> - android_image_get_bootimg_size
> - android_image_get_vendor_bootimg_size
> Use these information and read only the necessary.
>
> By doing this with mt8365 EVK board, we read boot image in ~5 secs.
>
> Signed-off-by: Julien Masson <jmasson@baylibre.com>

Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>

> ---
> Changes have been tested with:
> $ ./test/py/test.py --bd sandbox --build -k ut_bootstd_bootflow_android_image_v4
> $ ./test/py/test.py --bd sandbox --build -k ut_bootstd_bootflow_android_image_v2
> ---
>  boot/bootmeth_android.c | 28 +++++++++++++++++++++++-----
>  boot/image-android.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  include/image.h         | 24 ++++++++++++++++++++++++
>  3 files changed, 92 insertions(+), 5 deletions(-)
>
> diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
> index 2aac32331d3c28853bc87d05a8c76ae868ea97c7..3a5144aaa3b0125cf13ff1805b05e87385263308 100644
> --- a/boot/bootmeth_android.c
> +++ b/boot/bootmeth_android.c
> @@ -45,6 +45,8 @@ struct android_priv {
>  	enum android_boot_mode boot_mode;
>  	char *slot;
>  	u32 header_version;
> +	u32 boot_img_size;
> +	u32 vendor_boot_img_size;
>  };
>  
>  static int android_check(struct udevice *dev, struct bootflow_iter *iter)
> @@ -98,7 +100,13 @@ static int scan_boot_part(struct udevice *blk, struct android_priv *priv)
>  		return log_msg_ret("header", -ENOENT);
>  	}
>  
> +	if (!android_image_get_bootimg_size(buf, &priv->boot_img_size)) {
> +		free(buf);
> +		return log_msg_ret("get bootimg size", -EINVAL);
> +	}
> +
>  	priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version;
> +
>  	free(buf);
>  
>  	return 0;
> @@ -138,6 +146,12 @@ static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv)
>  		free(buf);
>  		return log_msg_ret("header", -ENOENT);
>  	}
> +
> +	if (!android_image_get_vendor_bootimg_size(buf, &priv->vendor_boot_img_size)) {
> +		free(buf);
> +		return log_msg_ret("get vendor bootimg size", -EINVAL);
> +	}
> +
>  	free(buf);
>  
>  	return 0;
> @@ -330,15 +344,17 @@ static int android_read_file(struct udevice *dev, struct bootflow *bflow,
>   * @blk: Block device to read
>   * @name: Partition name to read
>   * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0")
> + * @image_size: Image size in bytes used when reading the partition
>   * @addr: Address where the partition content is loaded into
>   * Return: 0 if OK, negative errno on failure.
>   */
>  static int read_slotted_partition(struct blk_desc *desc, const char *const name,
> -				  const char slot[2], ulong addr)
> +				  const char slot[2], ulong image_size, ulong addr)
>  {
>  	struct disk_partition partition;
>  	char partname[PART_NAME_LEN];
>  	size_t partname_len;
> +	ulong num_blks = DIV_ROUND_UP(image_size, desc->blksz);
>  	int ret;
>  	u32 n;
>  
> @@ -364,8 +380,8 @@ static int read_slotted_partition(struct blk_desc *desc, const char *const name,
>  	if (ret < 0)
>  		return log_msg_ret("part", ret);
>  
> -	n = blk_dread(desc, partition.start, partition.size, map_sysmem(addr, 0));
> -	if (n < partition.size)
> +	n = blk_dread(desc, partition.start, num_blks, map_sysmem(addr, 0));
> +	if (n < num_blks)
>  		return log_msg_ret("part read", -EIO);
>  
>  	return 0;
> @@ -498,12 +514,14 @@ static int boot_android_normal(struct bootflow *bflow)
>  	if (ret < 0)
>  		return log_msg_ret("read slot", ret);
>  
> -	ret = read_slotted_partition(desc, "boot", priv->slot, loadaddr);
> +	ret = read_slotted_partition(desc, "boot", priv->slot, priv->boot_img_size,
> +				     loadaddr);
>  	if (ret < 0)
>  		return log_msg_ret("read boot", ret);
>  
>  	if (priv->header_version >= 3) {
> -		ret = read_slotted_partition(desc, "vendor_boot", priv->slot, vloadaddr);
> +		ret = read_slotted_partition(desc, "vendor_boot", priv->slot,
> +					     priv->vendor_boot_img_size, vloadaddr);
>  		if (ret < 0)
>  			return log_msg_ret("read vendor_boot", ret);
>  		set_avendor_bootimg_addr(vloadaddr);
> diff --git a/boot/image-android.c b/boot/image-android.c
> index cd01278f211d63262f2bdad7aa1176e2c1bbfedd..93b54bf8d7936862693d56d5b75343575f3e6293 100644
> --- a/boot/image-android.c
> +++ b/boot/image-android.c
> @@ -178,6 +178,51 @@ static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr
>  	data->boot_img_total_size = end - (ulong)hdr;
>  }
>  
> +bool android_image_get_bootimg_size(const void *hdr, u32 *boot_img_size)
> +{
> +	struct andr_image_data data;
> +
> +	if (!hdr || !boot_img_size) {
> +		printf("hdr or boot_img_size can't be NULL\n");
> +		return false;
> +	}
> +
> +	if (!is_android_boot_image_header(hdr)) {
> +		printf("Incorrect boot image header\n");
> +		return false;
> +	}
> +
> +	if (((struct andr_boot_img_hdr_v0 *)hdr)->header_version <= 2)
> +		android_boot_image_v0_v1_v2_parse_hdr(hdr, &data);
> +	else
> +		android_boot_image_v3_v4_parse_hdr(hdr, &data);
> +
> +	*boot_img_size = data.boot_img_total_size;
> +
> +	return true;
> +}
> +
> +bool android_image_get_vendor_bootimg_size(const void *hdr, u32 *vendor_boot_img_size)
> +{
> +	struct andr_image_data data;
> +
> +	if (!hdr || !vendor_boot_img_size) {
> +		printf("hdr or vendor_boot_img_size can't be NULL\n");
> +		return false;
> +	}
> +
> +	if (!is_android_vendor_boot_image_header(hdr)) {
> +		printf("Incorrect vendor boot image header\n");
> +		return false;
> +	}
> +
> +	android_vendor_boot_image_v3_v4_parse_hdr(hdr, &data);
> +
> +	*vendor_boot_img_size = data.vendor_boot_img_total_size;
> +
> +	return true;
> +}
> +
>  bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr,
>  			    struct andr_image_data *data)
>  {
> diff --git a/include/image.h b/include/image.h
> index c52fced9b409b1f963daa4ab6c266909ca035aff..9be5acd8158f00930ab1f3988b8f577817acd1fe 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -1801,6 +1801,30 @@ int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo);
>  struct cipher_algo *image_get_cipher_algo(const char *full_name);
>  struct andr_image_data;
>  
> +/**
> + * android_image_get_bootimg_size() - Extract size of Android boot image
> + *
> + * This is used to extract the size of an Android boot image
> + * from boot image header.
> + *
> + * @hdr: Pointer to boot image header
> + * @boot_img_size: On exit returns the size in bytes of the boot image
> + * Return: true if succeeded, false otherwise
> + */
> +bool android_image_get_bootimg_size(const void *hdr, u32 *boot_img_size);
> +
> +/**
> + * android_image_get_vendor_bootimg_size() - Extract size of Android vendor-boot image
> + *
> + * This is used to extract the size of an Android vendor-boot image
> + * from vendor-boot image header.
> + *
> + * @hdr: Pointer to vendor-boot image header
> + * @vendor_boot_img_size: On exit returns the size in bytes of the vendor-boot image
> + * Return: true if succeeded, false otherwise
> + */
> +bool android_image_get_vendor_bootimg_size(const void *hdr, u32 *vendor_boot_img_size);
> +
>  /**
>   * android_image_get_data() - Parse Android boot images
>   *
>
> ---
> base-commit: acaa7f35a33146f887948d34130229388280844a
> change-id: 20241121-bootmeth-android-part-sizes-ff2866e0d079
>
> Best regards,
> -- 
> Julien Masson <jmasson@baylibre.com>

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

* Re: [PATCH] bootstd: android: don't read whole partition sizes
  2024-11-21 10:59 [PATCH] bootstd: android: don't read whole partition sizes Julien Masson
  2024-11-22 10:17 ` Mattijs Korpershoek
@ 2024-11-26  9:05 ` Mattijs Korpershoek
  1 sibling, 0 replies; 3+ messages in thread
From: Mattijs Korpershoek @ 2024-11-26  9:05 UTC (permalink / raw)
  To: Simon Glass, Tom Rini, Julien Masson; +Cc: u-boot

Hi,

On Thu, 21 Nov 2024 11:59:55 +0100, Julien Masson wrote:
> The current implementation is reading the whole partition for boot and
> vendor_boot image which can be long following the size of the
> partition or the time to read blocks (driver/SoC specific).
> 
> For example with mediatek mt8365 EVK board, we have a 64MiB boot
> partition and the boot image flashed in this partition is only 42MiB.
> It takes ~8-9 secs to read the boot partition.
> 
> [...]

Thanks, Applied to https://source.denx.de/u-boot/custodians/u-boot-dfu (u-boot-dfu-next)

[1/1] bootstd: android: don't read whole partition sizes
      https://source.denx.de/u-boot/custodians/u-boot-dfu/-/commit/abadcda24b100b8eb0f138085cca6595518cec85

--
Mattijs

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

end of thread, other threads:[~2024-11-26  9:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-21 10:59 [PATCH] bootstd: android: don't read whole partition sizes Julien Masson
2024-11-22 10:17 ` Mattijs Korpershoek
2024-11-26  9:05 ` Mattijs Korpershoek

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.