blob: 0a335db3a6152b5b7a764ba4820a4b3d4ff26379 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Steve Rae792ac482014-08-26 11:47:27 -07002/*
3 * Copyright 2014 Broadcom Corporation.
Steve Rae792ac482014-08-26 11:47:27 -07004 */
5
Steve Rae7d059342014-12-12 15:51:54 -08006#include <config.h>
Steve Rae792ac482014-08-26 11:47:27 -07007#include <common.h>
Simon Glass2ee8ada2016-02-29 15:25:52 -07008#include <blk.h>
Maxime Ripard00e8eb72015-10-15 14:34:13 +02009#include <fastboot.h>
Alex Kiernand5aa57c2018-05-29 15:30:53 +000010#include <fastboot-internal.h>
Steve Rae792ac482014-08-26 11:47:27 -070011#include <fb_mmc.h>
Maxime Ripard6af49bc2015-10-15 14:34:19 +020012#include <image-sparse.h>
Steve Rae792ac482014-08-26 11:47:27 -070013#include <part.h>
Dileep Kattab1228202015-02-17 18:48:23 +053014#include <mmc.h>
Siarhei Siamashka58f30d82015-10-28 06:24:16 +020015#include <div64.h>
Sam Protsenko540eb952017-05-18 15:04:59 +030016#include <linux/compat.h>
17#include <android_image.h>
Steve Rae792ac482014-08-26 11:47:27 -070018
Alex Kiernand5aa57c2018-05-29 15:30:53 +000019#define FASTBOOT_MAX_BLK_WRITE 16384
20
Sam Protsenko540eb952017-05-18 15:04:59 +030021#define BOOT_PARTITION_NAME "boot"
22
Maxime Riparda58e9c72015-10-15 14:34:14 +020023struct fb_mmc_sparse {
Simon Glasse3394752016-02-29 15:25:34 -070024 struct blk_desc *dev_desc;
Maxime Riparda58e9c72015-10-15 14:34:14 +020025};
26
Petr Kulhavy9f174c92016-09-09 10:27:16 +020027static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc,
Michael Scottced33492015-03-11 10:02:31 -070028 const char *name, disk_partition_t *info)
29{
30 int ret;
31
Petr Kulhavy712257e2016-09-09 10:27:15 +020032 ret = part_get_info_by_name(dev_desc, name, info);
Alex Deymoe2f689f2017-04-02 01:49:50 -070033 if (ret < 0) {
Alex Kiernan50f12232019-04-09 05:30:05 +000034 /* strlen("fastboot_partition_alias_") + PART_NAME_LEN + 1 */
35 char env_alias_name[25 + PART_NAME_LEN + 1];
Michael Scottced33492015-03-11 10:02:31 -070036 char *aliased_part_name;
37
38 /* check for alias */
39 strcpy(env_alias_name, "fastboot_partition_alias_");
Alex Kiernan50f12232019-04-09 05:30:05 +000040 strncat(env_alias_name, name, PART_NAME_LEN);
Simon Glass64b723f2017-08-03 12:22:12 -060041 aliased_part_name = env_get(env_alias_name);
Michael Scottced33492015-03-11 10:02:31 -070042 if (aliased_part_name != NULL)
Petr Kulhavy712257e2016-09-09 10:27:15 +020043 ret = part_get_info_by_name(dev_desc,
Michael Scottced33492015-03-11 10:02:31 -070044 aliased_part_name, info);
45 }
46 return ret;
47}
48
Alex Kiernand5aa57c2018-05-29 15:30:53 +000049/**
50 * fb_mmc_blk_write() - Write/erase MMC in chunks of FASTBOOT_MAX_BLK_WRITE
51 *
52 * @block_dev: Pointer to block device
53 * @start: First block to write/erase
54 * @blkcnt: Count of blocks
55 * @buffer: Pointer to data buffer for write or NULL for erase
56 */
57static lbaint_t fb_mmc_blk_write(struct blk_desc *block_dev, lbaint_t start,
58 lbaint_t blkcnt, const void *buffer)
59{
60 lbaint_t blk = start;
61 lbaint_t blks_written;
62 lbaint_t cur_blkcnt;
63 lbaint_t blks = 0;
64 int i;
65
66 for (i = 0; i < blkcnt; i += FASTBOOT_MAX_BLK_WRITE) {
67 cur_blkcnt = min((int)blkcnt - i, FASTBOOT_MAX_BLK_WRITE);
68 if (buffer) {
69 if (fastboot_progress_callback)
70 fastboot_progress_callback("writing");
71 blks_written = blk_dwrite(block_dev, blk, cur_blkcnt,
72 buffer + (i * block_dev->blksz));
73 } else {
74 if (fastboot_progress_callback)
75 fastboot_progress_callback("erasing");
76 blks_written = blk_derase(block_dev, blk, cur_blkcnt);
77 }
78 blk += blks_written;
79 blks += blks_written;
80 }
81 return blks;
82}
83
Steve Rae8cf58db2016-06-07 11:19:36 -070084static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info,
85 lbaint_t blk, lbaint_t blkcnt, const void *buffer)
Maxime Riparda58e9c72015-10-15 14:34:14 +020086{
Steve Rae8cf58db2016-06-07 11:19:36 -070087 struct fb_mmc_sparse *sparse = info->priv;
Simon Glasse3394752016-02-29 15:25:34 -070088 struct blk_desc *dev_desc = sparse->dev_desc;
Maxime Riparda58e9c72015-10-15 14:34:14 +020089
Alex Kiernand5aa57c2018-05-29 15:30:53 +000090 return fb_mmc_blk_write(dev_desc, blk, blkcnt, buffer);
Maxime Riparda58e9c72015-10-15 14:34:14 +020091}
92
Steve Rae8a99be82016-06-07 11:19:38 -070093static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info,
94 lbaint_t blk, lbaint_t blkcnt)
95{
96 return blkcnt;
97}
98
Simon Glasse3394752016-02-29 15:25:34 -070099static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info,
Steve Rae792ac482014-08-26 11:47:27 -0700100 const char *part_name, void *buffer,
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000101 u32 download_bytes, char *response)
Steve Rae792ac482014-08-26 11:47:27 -0700102{
103 lbaint_t blkcnt;
104 lbaint_t blks;
105
106 /* determine number of blocks to write */
107 blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1));
Siarhei Siamashka58f30d82015-10-28 06:24:16 +0200108 blkcnt = lldiv(blkcnt, info->blksz);
Steve Rae792ac482014-08-26 11:47:27 -0700109
110 if (blkcnt > info->size) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900111 pr_err("too large for partition: '%s'\n", part_name);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000112 fastboot_fail("too large for partition", response);
Steve Rae792ac482014-08-26 11:47:27 -0700113 return;
114 }
115
116 puts("Flashing Raw Image\n");
117
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000118 blks = fb_mmc_blk_write(dev_desc, info->start, blkcnt, buffer);
119
Steve Rae792ac482014-08-26 11:47:27 -0700120 if (blks != blkcnt) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900121 pr_err("failed writing to device %d\n", dev_desc->devnum);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000122 fastboot_fail("failed writing to device", response);
Steve Rae792ac482014-08-26 11:47:27 -0700123 return;
124 }
125
126 printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz,
127 part_name);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000128 fastboot_okay(NULL, response);
Steve Rae792ac482014-08-26 11:47:27 -0700129}
130
Sam Protsenko540eb952017-05-18 15:04:59 +0300131#ifdef CONFIG_ANDROID_BOOT_IMAGE
132/**
133 * Read Android boot image header from boot partition.
134 *
135 * @param[in] dev_desc MMC device descriptor
136 * @param[in] info Boot partition info
137 * @param[out] hdr Where to store read boot image header
138 *
139 * @return Boot image header sectors count or 0 on error
140 */
141static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
142 disk_partition_t *info,
Alex Kiernan27b69de2018-05-29 15:30:40 +0000143 struct andr_img_hdr *hdr,
144 char *response)
Sam Protsenko540eb952017-05-18 15:04:59 +0300145{
146 ulong sector_size; /* boot partition sector size */
147 lbaint_t hdr_sectors; /* boot image header sectors count */
148 int res;
149
150 /* Calculate boot image sectors count */
151 sector_size = info->blksz;
152 hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size);
153 if (hdr_sectors == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000154 pr_err("invalid number of boot sectors: 0\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000155 fastboot_fail("invalid number of boot sectors: 0", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300156 return 0;
157 }
158
159 /* Read the boot image header */
160 res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr);
Tom Rinibda6f772017-08-14 21:00:44 -0400161 if (res != hdr_sectors) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000162 pr_err("cannot read header from boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000163 fastboot_fail("cannot read header from boot partition",
164 response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300165 return 0;
166 }
167
168 /* Check boot header magic string */
169 res = android_image_check_header(hdr);
170 if (res != 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000171 pr_err("bad boot image magic\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000172 fastboot_fail("boot partition not initialized", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300173 return 0;
174 }
175
176 return hdr_sectors;
177}
178
179/**
180 * Write downloaded zImage to boot partition and repack it properly.
181 *
182 * @param dev_desc MMC device descriptor
183 * @param download_buffer Address to fastboot buffer with zImage in it
184 * @param download_bytes Size of fastboot buffer, in bytes
185 *
186 * @return 0 on success or -1 on error
187 */
188static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
189 void *download_buffer,
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000190 u32 download_bytes,
Alex Kiernan27b69de2018-05-29 15:30:40 +0000191 char *response)
Sam Protsenko540eb952017-05-18 15:04:59 +0300192{
Tom Rini0ac605c2017-06-10 09:15:37 -0400193 uintptr_t hdr_addr; /* boot image header address */
Sam Protsenko540eb952017-05-18 15:04:59 +0300194 struct andr_img_hdr *hdr; /* boot image header */
195 lbaint_t hdr_sectors; /* boot image header sectors */
196 u8 *ramdisk_buffer;
197 u32 ramdisk_sector_start;
198 u32 ramdisk_sectors;
199 u32 kernel_sector_start;
200 u32 kernel_sectors;
201 u32 sectors_per_page;
202 disk_partition_t info;
203 int res;
204
205 puts("Flashing zImage\n");
206
207 /* Get boot partition info */
208 res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info);
209 if (res < 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000210 pr_err("cannot find boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000211 fastboot_fail("cannot find boot partition", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300212 return -1;
213 }
214
215 /* Put boot image header in fastboot buffer after downloaded zImage */
Tom Rini0ac605c2017-06-10 09:15:37 -0400216 hdr_addr = (uintptr_t)download_buffer + ALIGN(download_bytes, PAGE_SIZE);
Sam Protsenko540eb952017-05-18 15:04:59 +0300217 hdr = (struct andr_img_hdr *)hdr_addr;
218
219 /* Read boot image header */
Alex Kiernan27b69de2018-05-29 15:30:40 +0000220 hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr, response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300221 if (hdr_sectors == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000222 pr_err("unable to read boot image header\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000223 fastboot_fail("unable to read boot image header", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300224 return -1;
225 }
226
227 /* Check if boot image has second stage in it (we don't support it) */
228 if (hdr->second_size > 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000229 pr_err("moving second stage is not supported yet\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000230 fastboot_fail("moving second stage is not supported yet",
231 response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300232 return -1;
233 }
234
235 /* Extract ramdisk location */
236 sectors_per_page = hdr->page_size / info.blksz;
237 ramdisk_sector_start = info.start + sectors_per_page;
238 ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) *
239 sectors_per_page;
240 ramdisk_sectors = DIV_ROUND_UP(hdr->ramdisk_size, hdr->page_size) *
241 sectors_per_page;
242
243 /* Read ramdisk and put it in fastboot buffer after boot image header */
244 ramdisk_buffer = (u8 *)hdr + (hdr_sectors * info.blksz);
245 res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors,
246 ramdisk_buffer);
Tom Rinibda6f772017-08-14 21:00:44 -0400247 if (res != ramdisk_sectors) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000248 pr_err("cannot read ramdisk from boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000249 fastboot_fail("cannot read ramdisk from boot partition",
250 response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300251 return -1;
252 }
253
254 /* Write new kernel size to boot image header */
255 hdr->kernel_size = download_bytes;
256 res = blk_dwrite(dev_desc, info.start, hdr_sectors, (void *)hdr);
257 if (res == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000258 pr_err("cannot writeback boot image header\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000259 fastboot_fail("cannot write back boot image header", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300260 return -1;
261 }
262
263 /* Write the new downloaded kernel */
264 kernel_sector_start = info.start + sectors_per_page;
265 kernel_sectors = DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) *
266 sectors_per_page;
267 res = blk_dwrite(dev_desc, kernel_sector_start, kernel_sectors,
268 download_buffer);
269 if (res == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000270 pr_err("cannot write new kernel\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000271 fastboot_fail("cannot write new kernel", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300272 return -1;
273 }
274
275 /* Write the saved ramdisk back */
276 ramdisk_sector_start = info.start + sectors_per_page;
277 ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) *
278 sectors_per_page;
279 res = blk_dwrite(dev_desc, ramdisk_sector_start, ramdisk_sectors,
280 ramdisk_buffer);
281 if (res == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000282 pr_err("cannot write back original ramdisk\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000283 fastboot_fail("cannot write back original ramdisk", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300284 return -1;
285 }
286
287 puts("........ zImage was updated in boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000288 fastboot_okay(NULL, response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300289 return 0;
290}
291#endif
292
Alex Kiernan32c21942018-05-29 15:30:48 +0000293/**
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000294 * fastboot_mmc_get_part_info() - Lookup eMMC partion by name
295 *
296 * @part_name: Named partition to lookup
297 * @dev_desc: Pointer to returned blk_desc pointer
298 * @part_info: Pointer to returned disk_partition_t
299 * @response: Pointer to fastboot response buffer
300 */
Sam Protsenko0fb37ee2019-06-13 21:11:07 +0300301int fastboot_mmc_get_part_info(const char *part_name,
302 struct blk_desc **dev_desc,
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000303 disk_partition_t *part_info, char *response)
304{
305 int r;
306
307 *dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
308 if (!*dev_desc) {
309 fastboot_fail("block device not found", response);
310 return -ENOENT;
311 }
Eugeniu Rosca8eba90b2019-03-28 14:31:33 +0100312 if (!part_name || !strcmp(part_name, "")) {
313 fastboot_fail("partition not given", response);
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000314 return -ENOENT;
315 }
316
317 r = part_get_info_by_name_or_alias(*dev_desc, part_name, part_info);
318 if (r < 0) {
319 fastboot_fail("partition not found", response);
320 return r;
321 }
322
323 return r;
324}
325
326/**
Alex Kiernan32c21942018-05-29 15:30:48 +0000327 * fastboot_mmc_flash_write() - Write image to eMMC for fastboot
328 *
329 * @cmd: Named partition to write image to
330 * @download_buffer: Pointer to image data
331 * @download_bytes: Size of image data
332 * @response: Pointer to fastboot response buffer
333 */
334void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000335 u32 download_bytes, char *response)
Steve Rae792ac482014-08-26 11:47:27 -0700336{
Simon Glasse3394752016-02-29 15:25:34 -0700337 struct blk_desc *dev_desc;
Steve Rae792ac482014-08-26 11:47:27 -0700338 disk_partition_t info;
339
Simon Glassbe1e9bb2016-02-29 15:25:42 -0700340 dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
Steve Rae792ac482014-08-26 11:47:27 -0700341 if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900342 pr_err("invalid mmc device\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000343 fastboot_fail("invalid mmc device", response);
Steve Rae792ac482014-08-26 11:47:27 -0700344 return;
345 }
346
Patrick Delaunay8a4f2bd2017-01-27 11:00:41 +0100347#if CONFIG_IS_ENABLED(EFI_PARTITION)
Steve Rae7d059342014-12-12 15:51:54 -0800348 if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
349 printf("%s: updating MBR, Primary and Backup GPT(s)\n",
350 __func__);
351 if (is_valid_gpt_buf(dev_desc, download_buffer)) {
352 printf("%s: invalid GPT - refusing to write to flash\n",
353 __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000354 fastboot_fail("invalid GPT partition", response);
Steve Rae7d059342014-12-12 15:51:54 -0800355 return;
356 }
357 if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
358 printf("%s: writing GPT partitions failed\n", __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000359 fastboot_fail("writing GPT partitions failed",
360 response);
Steve Rae7d059342014-12-12 15:51:54 -0800361 return;
362 }
363 printf("........ success\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000364 fastboot_okay(NULL, response);
Steve Rae7d059342014-12-12 15:51:54 -0800365 return;
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200366 }
367#endif
368
Patrick Delaunayf7e07722017-01-27 11:00:37 +0100369#if CONFIG_IS_ENABLED(DOS_PARTITION)
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200370 if (strcmp(cmd, CONFIG_FASTBOOT_MBR_NAME) == 0) {
371 printf("%s: updating MBR\n", __func__);
372 if (is_valid_dos_buf(download_buffer)) {
373 printf("%s: invalid MBR - refusing to write to flash\n",
374 __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000375 fastboot_fail("invalid MBR partition", response);
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200376 return;
377 }
378 if (write_mbr_partition(dev_desc, download_buffer)) {
379 printf("%s: writing MBR partition failed\n", __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000380 fastboot_fail("writing MBR partition failed",
381 response);
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200382 return;
383 }
384 printf("........ success\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000385 fastboot_okay(NULL, response);
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200386 return;
387 }
388#endif
389
Sam Protsenko540eb952017-05-18 15:04:59 +0300390#ifdef CONFIG_ANDROID_BOOT_IMAGE
391 if (strncasecmp(cmd, "zimage", 6) == 0) {
Alex Kiernan27b69de2018-05-29 15:30:40 +0000392 fb_mmc_update_zimage(dev_desc, download_buffer,
393 download_bytes, response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300394 return;
395 }
396#endif
397
Alex Deymoe2f689f2017-04-02 01:49:50 -0700398 if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900399 pr_err("cannot find partition: '%s'\n", cmd);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000400 fastboot_fail("cannot find partition", response);
Steve Rae792ac482014-08-26 11:47:27 -0700401 return;
402 }
403
Maxime Riparda58e9c72015-10-15 14:34:14 +0200404 if (is_sparse_image(download_buffer)) {
405 struct fb_mmc_sparse sparse_priv;
Steve Rae8cf58db2016-06-07 11:19:36 -0700406 struct sparse_storage sparse;
Jassi Brar427e6692018-04-06 12:05:09 +0530407 int err;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200408
409 sparse_priv.dev_desc = dev_desc;
410
Steve Rae8cf58db2016-06-07 11:19:36 -0700411 sparse.blksz = info.blksz;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200412 sparse.start = info.start;
413 sparse.size = info.size;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200414 sparse.write = fb_mmc_sparse_write;
Steve Rae8a99be82016-06-07 11:19:38 -0700415 sparse.reserve = fb_mmc_sparse_reserve;
Jassi Brar427e6692018-04-06 12:05:09 +0530416 sparse.mssg = fastboot_fail;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200417
418 printf("Flashing sparse image at offset " LBAFU "\n",
Steve Rae8cf58db2016-06-07 11:19:36 -0700419 sparse.start);
Maxime Riparda58e9c72015-10-15 14:34:14 +0200420
Steve Rae8cf58db2016-06-07 11:19:36 -0700421 sparse.priv = &sparse_priv;
Alex Kiernan27b69de2018-05-29 15:30:40 +0000422 err = write_sparse_image(&sparse, cmd, download_buffer,
423 response);
Jassi Brar427e6692018-04-06 12:05:09 +0530424 if (!err)
Alex Kiernan27b69de2018-05-29 15:30:40 +0000425 fastboot_okay(NULL, response);
Maxime Riparda58e9c72015-10-15 14:34:14 +0200426 } else {
Steve Raec6015672014-08-26 11:47:30 -0700427 write_raw_image(dev_desc, &info, cmd, download_buffer,
Alex Kiernan27b69de2018-05-29 15:30:40 +0000428 download_bytes, response);
Maxime Riparda58e9c72015-10-15 14:34:14 +0200429 }
Steve Rae792ac482014-08-26 11:47:27 -0700430}
Dileep Kattab1228202015-02-17 18:48:23 +0530431
Alex Kiernan32c21942018-05-29 15:30:48 +0000432/**
433 * fastboot_mmc_flash_erase() - Erase eMMC for fastboot
434 *
435 * @cmd: Named partition to erase
436 * @response: Pointer to fastboot response buffer
437 */
438void fastboot_mmc_erase(const char *cmd, char *response)
Dileep Kattab1228202015-02-17 18:48:23 +0530439{
440 int ret;
Simon Glasse3394752016-02-29 15:25:34 -0700441 struct blk_desc *dev_desc;
Dileep Kattab1228202015-02-17 18:48:23 +0530442 disk_partition_t info;
443 lbaint_t blks, blks_start, blks_size, grp_size;
444 struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
445
446 if (mmc == NULL) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000447 pr_err("invalid mmc device\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000448 fastboot_fail("invalid mmc device", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530449 return;
450 }
451
Simon Glassbe1e9bb2016-02-29 15:25:42 -0700452 dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
Dileep Kattab1228202015-02-17 18:48:23 +0530453 if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000454 pr_err("invalid mmc device\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000455 fastboot_fail("invalid mmc device", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530456 return;
457 }
458
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200459 ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
Alex Deymoe2f689f2017-04-02 01:49:50 -0700460 if (ret < 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000461 pr_err("cannot find partition: '%s'\n", cmd);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000462 fastboot_fail("cannot find partition", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530463 return;
464 }
465
466 /* Align blocks to erase group size to avoid erasing other partitions */
467 grp_size = mmc->erase_grp_size;
468 blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
469 if (info.size >= grp_size)
470 blks_size = (info.size - (blks_start - info.start)) &
471 (~(grp_size - 1));
472 else
473 blks_size = 0;
474
475 printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
476 blks_start, blks_start + blks_size);
477
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000478 blks = fb_mmc_blk_write(dev_desc, blks_start, blks_size, NULL);
479
Dileep Kattab1228202015-02-17 18:48:23 +0530480 if (blks != blks_size) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000481 pr_err("failed erasing from device %d\n", dev_desc->devnum);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000482 fastboot_fail("failed erasing from device", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530483 return;
484 }
485
486 printf("........ erased " LBAFU " bytes from '%s'\n",
487 blks_size * info.blksz, cmd);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000488 fastboot_okay(NULL, response);
Dileep Kattab1228202015-02-17 18:48:23 +0530489}