[U-Boot] [RFC PATCH 0/3] Implement "fastboot flash" for eMMC

Steve Rae srae at broadcom.com
Fri Jun 20 23:55:51 CEST 2014



On 14-06-19 11:32 PM, Marek Vasut wrote:
> On Friday, June 20, 2014 at 08:18:42 AM, Lukasz Majewski wrote:
>> Hi Steve,
>>
>>> This series implements the "fastboot flash" command for eMMC devices.
>>> It supports both raw and sparse images.
>>>
>>> NOTES:
>>> - the support for the "fastboot flash" command is enabled with
>>> CONFIG_FASTBOOT_FLASH
>>> - the support for eMMC is enabled with CONFIG_FASTBOOT_FLASH_MMC_DEV
>>> - (future) the support for NAND would be enabled with
>>> CONFIG_FASTBOOT_FLASH_NAND(???)
>>> - thus the proposal is to place the code in common/fb_mmc.c and
>>> (future) common/fb_nand.c(???), however, this may not be the
>>> appropriate location....
>>
>> Would you consider another approach for providing flashing backend for
>> fastboot?
>>
>> I'd like to propose reusing of the dfu flashing code for this purpose.
>> Such approach has been used successfully with USB "thor" downloading
>> function.
>>
>> Since the "fastboot" is using gadget infrastructure (thanks to the
>> effort of Rob Herring) I think that it would be feasible to reuse the
>> same approach as "thor" does. In this way the low level code would be
>> kept in one place and we could refine and test it more thoroughly.
>
> I'm all for this approach as well if possible.
>
> Best regards,
> Marek Vasut
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>

I have briefly investigated this suggestion....
And have 'hacked' some code as follows:

--- common/fb_mmc.c_000	2014-06-20 14:13:43.271158073 -0700
+++ common/fb_mmc.c_001	2014-06-20 14:17:48.688072764 -0700
  		while (remaining_chunks) {
  			switch (le16_to_cpu(c_header->chunk_type)) {
  			case CHUNK_TYPE_RAW:
+#if 0
  				blkcnt =
  				    (le32_to_cpu(c_header->chunk_sz) * blk_sz) /
  				    info.blksz;
  				buffer =
  				    (void *)c_header +
  				    le16_to_cpu(s_header->chunk_hdr_sz);

  				blks = mmc_dev->block_write(mmc_dev->dev, blk,
  							    blkcnt, buffer);
  				if (blks != blkcnt) {
  					printf("Write failed %lu\n", blks);
  					strcpy(response,
  					       "FAILmmc write failure");
  					return;
  				}

  				bytes_written += blkcnt * info.blksz;
+#else
+				buffer =
+				    (void *)c_header +
+				    le16_to_cpu(s_header->chunk_hdr_sz);
+
+				len = le32_to_cpu(c_header->chunk_sz) * blk_sz;
+				ret_dfu = dfu_write_medium_mmc(dfu, offset,
+							       buffer, &len);
+				if (ret_dfu) {
+					printf("Write failed %lu\n", len);
+					strcpy(response,
+					       "FAILmmc write failure");
+					return;
+				}
+
+
+				bytes_written += len;
+#endif
  				break;

  			case CHUNK_TYPE_FILL:
  			case CHUNK_TYPE_DONT_CARE:
  			case CHUNK_TYPE_CRC32:
  				/* do nothing */
  				break;

  			default:
  				/* error */
  				printf("Unknown chunk type\n");
  				strcpy(response,
  				       "FAILunknown chunk type in sparse image");
  				return;
  			}

+#if 0
  			blk += (le32_to_cpu(c_header->chunk_sz) * blk_sz) /
  			    info.blksz;
+#else
+			offset += le32_to_cpu(c_header->chunk_sz) * blk_sz;
+#endif
  			c_header = (chunk_header_t *)((void *)c_header +
  			    le32_to_cpu(c_header->total_sz));
  			remaining_chunks--;
  		}


--- common/fb_mmc.c_000	2014-06-20 14:13:43.271158073 -0700
+++ common/fb_mmc.c_001	2014-06-20 14:17:48.688072764 -0700
  		/* raw image */

+#if 0
  		/* determine number of blocks to write */
  		blkcnt =
  		    ((download_bytes + (info.blksz - 1)) & ~(info.blksz - 1));
  		blkcnt = blkcnt / info.blksz;

  		if (blkcnt > info.size) {
  			printf("%s: too large for partition: '%s'\n",
  			       __func__, cmd);
  			strcpy(response, "FAILtoo large for partition");
  			return;
  		}

  		printf("Flashing Raw Image\n");

  		blks = mmc_dev->block_write(mmc_dev->dev, info.start, blkcnt,
  					    download_buffer);
  		if (blks != blkcnt) {
  			printf("%s: failed writing to mmc device %d\n",
  			       __func__, mmc_dev->dev);
  			strcpy(response, "FAILfailed writing to mmc device");
  			return;
  		}

  		printf("........ wrote %lu bytes to '%s'\n",
  		       blkcnt * info.blksz, cmd);
+#else
+		printf("Flashing Raw Image\n");
+
+		ret_dfu = dfu_write_medium_mmc(dfu, offset, download_buffer, &len);
+		if (ret_dfu) {
+			printf("%s: failed writing to mmc device %d\n",
+			       __func__, mmc_dev->dev);
+			strcpy(response, "FAILfailed writing to mmc device");
+			return;
+		}
+
+		printf("........ wrote %lu bytes to '%s'\n", len, cmd);
+#endif
  	}

NOTE:
- I know that I cannot call "dfu_write_medium_mmc()" directly -- but I 
just wanted to test this functionality

My initial reaction is that using the DFU backend to effectively call 
the mmc block_write() function seems to cause an unnecessary amount of 
overhead; and the only thing that it really provides is a proven method 
of calculating the "number of blocks to write"...

I would be more interested in this backend if it would provide:
- handling of the "sparse image format"
	-- would a CONFIG option to include this in the DFU_OP_WRITE case of 
the "mmc_block_op()" be acceptable?
- a method which uses "get_partition_info_efi_by_name()"
	-- no ideas yet...

If the consensus is to use this DFU backend, then I will continue is 
this direction.

Please advise,
Thanks, Steve


More information about the U-Boot mailing list