[fastboot] erase cmd writes zeroes to unaligned partition chunks

Bug: b/315500301

Change-Id: I9f4cd0d1d6b990f3fcbd90e83e77181a3b174320
Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/802850
Reviewed-by: Yecheng Zhao <zyecheng@google.com>
GitOrigin-RevId: c7e8c723f6d48dd118cb9166c6a072d442a25787
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index 34692ad..4536a64 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -339,10 +339,15 @@
 			fastboot_okay("");
 		} else
 			write_raw_image(dev_desc, &info, cmd, download_buffer,
-				download_bytes);
+					download_bytes);
 	}
 }
 
+inline lbaint_t lba_max(lbaint_t a, lbaint_t b)
+{
+	return a > b ? a : b;
+}
+
 void fb_mmc_erase_write(const char *cmd, void *download_buffer)
 {
 	int ret = 0;
@@ -388,14 +393,58 @@
 		blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
 		if (info.size >= grp_size)
 			blks_size = (info.size - (blks_start - info.start)) &
-					(~(grp_size - 1));
+				    (~(grp_size - 1));
 		else
 			blks_size = 0;
 
-		printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
-		       blks_start, blks_start + blks_size);
+		lbaint_t unaligned_header_blks =
+			(info.start + info.size >= blks_start) ?
+				blks_start - info.start :
+				info.size;
+		lbaint_t unaligned_footer_blks =
+			info.size - blks_size - unaligned_header_blks;
+		lbaint_t unaligned_buffer_blks =
+			lba_max(unaligned_header_blks, unaligned_footer_blks);
+		if (unaligned_buffer_blks) {
+			size_t unaligned_buffer_size_bytes =
+				unaligned_buffer_blks * info.blksz;
+			void *unaligned_write_buffer =
+				calloc(1, unaligned_buffer_size_bytes);
+			if (unaligned_header_blks) {
+				printf("%s: writing zeroes to unaligned header starting at %lu for %lu blocks\n",
+				       __func__, info.start,
+				       unaligned_header_blks);
+				blks = dev_desc->block_write(
+					dev_desc->dev, info.start,
+					unaligned_header_blks,
+					unaligned_write_buffer);
+				if (blks != unaligned_header_blks) {
+					printf("%s: unaligned header write failed\n",
+					       __func__);
+				}
+			}
+			if (unaligned_footer_blks) {
+				lbaint_t footer_start = blks_start + blks_size;
+				printf("%s: writing zeroes to unaligned footer starting at %lu for %lu blocks\n",
+				       __func__, footer_start,
+				       unaligned_footer_blks);
+				blks = dev_desc->block_write(
+					dev_desc->dev, footer_start,
+					unaligned_footer_blks,
+					unaligned_write_buffer);
+				if (blks != unaligned_footer_blks) {
+					printf("%s: unaligned footer write failed\n",
+					       __func__);
+				}
+			}
+			free(unaligned_write_buffer);
+		}
 
-		blks = dev_desc->block_erase(dev_desc->dev, blks_start, blks_size);
+		printf("Erasing blocks " LBAFU " to " LBAFU
+		       " due to alignment\n",
+		       blks_start, blks_start + blks_size);
+		blks = dev_desc->block_erase(dev_desc->dev, blks_start,
+					     blks_size);
 		if (blks != 0) {
 			error("failed erasing from device %d", dev_desc->dev);
 			fastboot_fail("failed erasing from device");