blob: b2f8932e1c7a67ca1843b4428a74fc1d33f99e29 [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>
Simon Glass0af6e2d2019-08-01 09:46:52 -06009#include <env.h>
Maxime Ripard00e8eb72015-10-15 14:34:13 +020010#include <fastboot.h>
Alex Kiernand5aa57c2018-05-29 15:30:53 +000011#include <fastboot-internal.h>
Steve Rae792ac482014-08-26 11:47:27 -070012#include <fb_mmc.h>
Simon Glass8e201882020-05-10 11:39:54 -060013#include <flash.h>
Maxime Ripard6af49bc2015-10-15 14:34:19 +020014#include <image-sparse.h>
Simon Glass2dc9c342020-05-10 11:40:01 -060015#include <image.h>
Simon Glass0f2af882020-05-10 11:40:05 -060016#include <log.h>
Steve Rae792ac482014-08-26 11:47:27 -070017#include <part.h>
Dileep Kattab1228202015-02-17 18:48:23 +053018#include <mmc.h>
Siarhei Siamashka58f30d82015-10-28 06:24:16 +020019#include <div64.h>
Sam Protsenko540eb952017-05-18 15:04:59 +030020#include <linux/compat.h>
21#include <android_image.h>
Steve Rae792ac482014-08-26 11:47:27 -070022
Alex Kiernand5aa57c2018-05-29 15:30:53 +000023#define FASTBOOT_MAX_BLK_WRITE 16384
24
Sam Protsenko540eb952017-05-18 15:04:59 +030025#define BOOT_PARTITION_NAME "boot"
26
Maxime Riparda58e9c72015-10-15 14:34:14 +020027struct fb_mmc_sparse {
Simon Glasse3394752016-02-29 15:25:34 -070028 struct blk_desc *dev_desc;
Maxime Riparda58e9c72015-10-15 14:34:14 +020029};
30
Petr Kulhavy9f174c92016-09-09 10:27:16 +020031static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc,
Simon Glassc1c4a8f2020-05-10 11:39:57 -060032 const char *name, struct disk_partition *info)
Michael Scottced33492015-03-11 10:02:31 -070033{
34 int ret;
35
Petr Kulhavy712257e2016-09-09 10:27:15 +020036 ret = part_get_info_by_name(dev_desc, name, info);
Alex Deymoe2f689f2017-04-02 01:49:50 -070037 if (ret < 0) {
Alex Kiernan50f12232019-04-09 05:30:05 +000038 /* strlen("fastboot_partition_alias_") + PART_NAME_LEN + 1 */
39 char env_alias_name[25 + PART_NAME_LEN + 1];
Michael Scottced33492015-03-11 10:02:31 -070040 char *aliased_part_name;
41
42 /* check for alias */
43 strcpy(env_alias_name, "fastboot_partition_alias_");
Alex Kiernan50f12232019-04-09 05:30:05 +000044 strncat(env_alias_name, name, PART_NAME_LEN);
Simon Glass64b723f2017-08-03 12:22:12 -060045 aliased_part_name = env_get(env_alias_name);
Michael Scottced33492015-03-11 10:02:31 -070046 if (aliased_part_name != NULL)
Petr Kulhavy712257e2016-09-09 10:27:15 +020047 ret = part_get_info_by_name(dev_desc,
Michael Scottced33492015-03-11 10:02:31 -070048 aliased_part_name, info);
49 }
50 return ret;
51}
52
Alex Kiernand5aa57c2018-05-29 15:30:53 +000053/**
54 * fb_mmc_blk_write() - Write/erase MMC in chunks of FASTBOOT_MAX_BLK_WRITE
55 *
56 * @block_dev: Pointer to block device
57 * @start: First block to write/erase
58 * @blkcnt: Count of blocks
59 * @buffer: Pointer to data buffer for write or NULL for erase
60 */
61static lbaint_t fb_mmc_blk_write(struct blk_desc *block_dev, lbaint_t start,
62 lbaint_t blkcnt, const void *buffer)
63{
64 lbaint_t blk = start;
65 lbaint_t blks_written;
66 lbaint_t cur_blkcnt;
67 lbaint_t blks = 0;
68 int i;
69
70 for (i = 0; i < blkcnt; i += FASTBOOT_MAX_BLK_WRITE) {
71 cur_blkcnt = min((int)blkcnt - i, FASTBOOT_MAX_BLK_WRITE);
72 if (buffer) {
73 if (fastboot_progress_callback)
74 fastboot_progress_callback("writing");
75 blks_written = blk_dwrite(block_dev, blk, cur_blkcnt,
76 buffer + (i * block_dev->blksz));
77 } else {
78 if (fastboot_progress_callback)
79 fastboot_progress_callback("erasing");
80 blks_written = blk_derase(block_dev, blk, cur_blkcnt);
81 }
82 blk += blks_written;
83 blks += blks_written;
84 }
85 return blks;
86}
87
Steve Rae8cf58db2016-06-07 11:19:36 -070088static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info,
89 lbaint_t blk, lbaint_t blkcnt, const void *buffer)
Maxime Riparda58e9c72015-10-15 14:34:14 +020090{
Steve Rae8cf58db2016-06-07 11:19:36 -070091 struct fb_mmc_sparse *sparse = info->priv;
Simon Glasse3394752016-02-29 15:25:34 -070092 struct blk_desc *dev_desc = sparse->dev_desc;
Maxime Riparda58e9c72015-10-15 14:34:14 +020093
Alex Kiernand5aa57c2018-05-29 15:30:53 +000094 return fb_mmc_blk_write(dev_desc, blk, blkcnt, buffer);
Maxime Riparda58e9c72015-10-15 14:34:14 +020095}
96
Steve Rae8a99be82016-06-07 11:19:38 -070097static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info,
98 lbaint_t blk, lbaint_t blkcnt)
99{
100 return blkcnt;
101}
102
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600103static void write_raw_image(struct blk_desc *dev_desc,
104 struct disk_partition *info, const char *part_name,
105 void *buffer, u32 download_bytes, char *response)
Steve Rae792ac482014-08-26 11:47:27 -0700106{
107 lbaint_t blkcnt;
108 lbaint_t blks;
109
110 /* determine number of blocks to write */
111 blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1));
Siarhei Siamashka58f30d82015-10-28 06:24:16 +0200112 blkcnt = lldiv(blkcnt, info->blksz);
Steve Rae792ac482014-08-26 11:47:27 -0700113
114 if (blkcnt > info->size) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900115 pr_err("too large for partition: '%s'\n", part_name);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000116 fastboot_fail("too large for partition", response);
Steve Rae792ac482014-08-26 11:47:27 -0700117 return;
118 }
119
120 puts("Flashing Raw Image\n");
121
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000122 blks = fb_mmc_blk_write(dev_desc, info->start, blkcnt, buffer);
123
Steve Rae792ac482014-08-26 11:47:27 -0700124 if (blks != blkcnt) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900125 pr_err("failed writing to device %d\n", dev_desc->devnum);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000126 fastboot_fail("failed writing to device", response);
Steve Rae792ac482014-08-26 11:47:27 -0700127 return;
128 }
129
130 printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz,
131 part_name);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000132 fastboot_okay(NULL, response);
Steve Rae792ac482014-08-26 11:47:27 -0700133}
134
developer6a105562020-01-16 16:11:42 +0800135#ifdef CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT
136static int fb_mmc_erase_mmc_hwpart(struct blk_desc *dev_desc)
137{
138 lbaint_t blks;
139
140 debug("Start Erasing mmc hwpart[%u]...\n", dev_desc->hwpart);
141
142 blks = fb_mmc_blk_write(dev_desc, 0, dev_desc->lba, NULL);
143
144 if (blks != dev_desc->lba) {
145 pr_err("Failed to erase mmc hwpart[%u]\n", dev_desc->hwpart);
146 return 1;
147 }
148
149 printf("........ erased %lu bytes from mmc hwpart[%u]\n",
150 dev_desc->lba * dev_desc->blksz, dev_desc->hwpart);
151
152 return 0;
153}
154
155static void fb_mmc_boot1_ops(struct blk_desc *dev_desc, void *buffer,
156 u32 buff_sz, char *response)
157{
158 lbaint_t blkcnt;
159 lbaint_t blks;
160 unsigned long blksz;
161
162 // To operate on EMMC_BOOT1 (mmc0boot0), we first change the hwpart
163 if (blk_dselect_hwpart(dev_desc, 1)) {
164 pr_err("Failed to select hwpart\n");
165 fastboot_fail("Failed to select hwpart", response);
166 return;
167 }
168
169 if (buffer) { /* flash */
170
171 /* determine number of blocks to write */
172 blksz = dev_desc->blksz;
173 blkcnt = ((buff_sz + (blksz - 1)) & ~(blksz - 1));
174 blkcnt = lldiv(blkcnt, blksz);
175
176 if (blkcnt > dev_desc->lba) {
177 pr_err("Image size too large\n");
178 fastboot_fail("Image size too large", response);
179 return;
180 }
181
182 debug("Start Flashing Image to EMMC_BOOT1...\n");
183
184 blks = fb_mmc_blk_write(dev_desc, 0, blkcnt, buffer);
185
186 if (blks != blkcnt) {
187 pr_err("Failed to write EMMC_BOOT1\n");
188 fastboot_fail("Failed to write EMMC_BOOT1", response);
189 return;
190 }
191
192 printf("........ wrote %lu bytes to EMMC_BOOT1\n",
193 blkcnt * blksz);
194 } else { /* erase */
195 if (fb_mmc_erase_mmc_hwpart(dev_desc)) {
196 fastboot_fail("Failed to erase EMMC_BOOT1", response);
197 return;
198 }
199 }
200
201 fastboot_okay(NULL, response);
202}
203#endif
204
Sam Protsenko540eb952017-05-18 15:04:59 +0300205#ifdef CONFIG_ANDROID_BOOT_IMAGE
206/**
207 * Read Android boot image header from boot partition.
208 *
209 * @param[in] dev_desc MMC device descriptor
210 * @param[in] info Boot partition info
211 * @param[out] hdr Where to store read boot image header
212 *
213 * @return Boot image header sectors count or 0 on error
214 */
215static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600216 struct disk_partition *info,
Alex Kiernan27b69de2018-05-29 15:30:40 +0000217 struct andr_img_hdr *hdr,
218 char *response)
Sam Protsenko540eb952017-05-18 15:04:59 +0300219{
220 ulong sector_size; /* boot partition sector size */
221 lbaint_t hdr_sectors; /* boot image header sectors count */
222 int res;
223
224 /* Calculate boot image sectors count */
225 sector_size = info->blksz;
226 hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size);
227 if (hdr_sectors == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000228 pr_err("invalid number of boot sectors: 0\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000229 fastboot_fail("invalid number of boot sectors: 0", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300230 return 0;
231 }
232
233 /* Read the boot image header */
234 res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr);
Tom Rinibda6f772017-08-14 21:00:44 -0400235 if (res != hdr_sectors) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000236 pr_err("cannot read header from boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000237 fastboot_fail("cannot read header from boot partition",
238 response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300239 return 0;
240 }
241
242 /* Check boot header magic string */
243 res = android_image_check_header(hdr);
244 if (res != 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000245 pr_err("bad boot image magic\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000246 fastboot_fail("boot partition not initialized", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300247 return 0;
248 }
249
250 return hdr_sectors;
251}
252
253/**
254 * Write downloaded zImage to boot partition and repack it properly.
255 *
256 * @param dev_desc MMC device descriptor
257 * @param download_buffer Address to fastboot buffer with zImage in it
258 * @param download_bytes Size of fastboot buffer, in bytes
259 *
260 * @return 0 on success or -1 on error
261 */
262static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
263 void *download_buffer,
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000264 u32 download_bytes,
Alex Kiernan27b69de2018-05-29 15:30:40 +0000265 char *response)
Sam Protsenko540eb952017-05-18 15:04:59 +0300266{
Tom Rini0ac605c2017-06-10 09:15:37 -0400267 uintptr_t hdr_addr; /* boot image header address */
Sam Protsenko540eb952017-05-18 15:04:59 +0300268 struct andr_img_hdr *hdr; /* boot image header */
269 lbaint_t hdr_sectors; /* boot image header sectors */
270 u8 *ramdisk_buffer;
271 u32 ramdisk_sector_start;
272 u32 ramdisk_sectors;
273 u32 kernel_sector_start;
274 u32 kernel_sectors;
275 u32 sectors_per_page;
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600276 struct disk_partition info;
Sam Protsenko540eb952017-05-18 15:04:59 +0300277 int res;
278
279 puts("Flashing zImage\n");
280
281 /* Get boot partition info */
282 res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info);
283 if (res < 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000284 pr_err("cannot find boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000285 fastboot_fail("cannot find boot partition", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300286 return -1;
287 }
288
289 /* Put boot image header in fastboot buffer after downloaded zImage */
Tom Rini0ac605c2017-06-10 09:15:37 -0400290 hdr_addr = (uintptr_t)download_buffer + ALIGN(download_bytes, PAGE_SIZE);
Sam Protsenko540eb952017-05-18 15:04:59 +0300291 hdr = (struct andr_img_hdr *)hdr_addr;
292
293 /* Read boot image header */
Alex Kiernan27b69de2018-05-29 15:30:40 +0000294 hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr, response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300295 if (hdr_sectors == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000296 pr_err("unable to read boot image header\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000297 fastboot_fail("unable to read boot image header", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300298 return -1;
299 }
300
301 /* Check if boot image has second stage in it (we don't support it) */
302 if (hdr->second_size > 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000303 pr_err("moving second stage is not supported yet\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000304 fastboot_fail("moving second stage is not supported yet",
305 response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300306 return -1;
307 }
308
309 /* Extract ramdisk location */
310 sectors_per_page = hdr->page_size / info.blksz;
311 ramdisk_sector_start = info.start + sectors_per_page;
312 ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) *
313 sectors_per_page;
314 ramdisk_sectors = DIV_ROUND_UP(hdr->ramdisk_size, hdr->page_size) *
315 sectors_per_page;
316
317 /* Read ramdisk and put it in fastboot buffer after boot image header */
318 ramdisk_buffer = (u8 *)hdr + (hdr_sectors * info.blksz);
319 res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors,
320 ramdisk_buffer);
Tom Rinibda6f772017-08-14 21:00:44 -0400321 if (res != ramdisk_sectors) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000322 pr_err("cannot read ramdisk from boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000323 fastboot_fail("cannot read ramdisk from boot partition",
324 response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300325 return -1;
326 }
327
328 /* Write new kernel size to boot image header */
329 hdr->kernel_size = download_bytes;
330 res = blk_dwrite(dev_desc, info.start, hdr_sectors, (void *)hdr);
331 if (res == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000332 pr_err("cannot writeback boot image header\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000333 fastboot_fail("cannot write back boot image header", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300334 return -1;
335 }
336
337 /* Write the new downloaded kernel */
338 kernel_sector_start = info.start + sectors_per_page;
339 kernel_sectors = DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) *
340 sectors_per_page;
341 res = blk_dwrite(dev_desc, kernel_sector_start, kernel_sectors,
342 download_buffer);
343 if (res == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000344 pr_err("cannot write new kernel\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000345 fastboot_fail("cannot write new kernel", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300346 return -1;
347 }
348
349 /* Write the saved ramdisk back */
350 ramdisk_sector_start = info.start + sectors_per_page;
351 ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) *
352 sectors_per_page;
353 res = blk_dwrite(dev_desc, ramdisk_sector_start, ramdisk_sectors,
354 ramdisk_buffer);
355 if (res == 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000356 pr_err("cannot write back original ramdisk\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000357 fastboot_fail("cannot write back original ramdisk", response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300358 return -1;
359 }
360
361 puts("........ zImage was updated in boot partition\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000362 fastboot_okay(NULL, response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300363 return 0;
364}
365#endif
366
Alex Kiernan32c21942018-05-29 15:30:48 +0000367/**
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000368 * fastboot_mmc_get_part_info() - Lookup eMMC partion by name
369 *
370 * @part_name: Named partition to lookup
371 * @dev_desc: Pointer to returned blk_desc pointer
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600372 * @part_info: Pointer to returned struct disk_partition
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000373 * @response: Pointer to fastboot response buffer
374 */
Sam Protsenko0fb37ee2019-06-13 21:11:07 +0300375int fastboot_mmc_get_part_info(const char *part_name,
376 struct blk_desc **dev_desc,
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600377 struct disk_partition *part_info, char *response)
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000378{
379 int r;
380
381 *dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
382 if (!*dev_desc) {
383 fastboot_fail("block device not found", response);
384 return -ENOENT;
385 }
Eugeniu Rosca8eba90b2019-03-28 14:31:33 +0100386 if (!part_name || !strcmp(part_name, "")) {
387 fastboot_fail("partition not given", response);
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000388 return -ENOENT;
389 }
390
391 r = part_get_info_by_name_or_alias(*dev_desc, part_name, part_info);
392 if (r < 0) {
393 fastboot_fail("partition not found", response);
394 return r;
395 }
396
397 return r;
398}
399
400/**
Alex Kiernan32c21942018-05-29 15:30:48 +0000401 * fastboot_mmc_flash_write() - Write image to eMMC for fastboot
402 *
403 * @cmd: Named partition to write image to
404 * @download_buffer: Pointer to image data
405 * @download_bytes: Size of image data
406 * @response: Pointer to fastboot response buffer
407 */
408void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000409 u32 download_bytes, char *response)
Steve Rae792ac482014-08-26 11:47:27 -0700410{
Simon Glasse3394752016-02-29 15:25:34 -0700411 struct blk_desc *dev_desc;
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600412 struct disk_partition info;
Steve Rae792ac482014-08-26 11:47:27 -0700413
Simon Glassbe1e9bb2016-02-29 15:25:42 -0700414 dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
Steve Rae792ac482014-08-26 11:47:27 -0700415 if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900416 pr_err("invalid mmc device\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000417 fastboot_fail("invalid mmc device", response);
Steve Rae792ac482014-08-26 11:47:27 -0700418 return;
419 }
420
developer6a105562020-01-16 16:11:42 +0800421#ifdef CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT
422 if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) {
423 fb_mmc_boot1_ops(dev_desc, download_buffer,
424 download_bytes, response);
425 return;
426 }
427#endif
428
Patrick Delaunay8a4f2bd2017-01-27 11:00:41 +0100429#if CONFIG_IS_ENABLED(EFI_PARTITION)
developer6a105562020-01-16 16:11:42 +0800430#ifndef CONFIG_FASTBOOT_MMC_USER_NAME
Steve Rae7d059342014-12-12 15:51:54 -0800431 if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
developer6a105562020-01-16 16:11:42 +0800432#else
433 if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0 ||
434 strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) {
435#endif
Steve Rae7d059342014-12-12 15:51:54 -0800436 printf("%s: updating MBR, Primary and Backup GPT(s)\n",
437 __func__);
438 if (is_valid_gpt_buf(dev_desc, download_buffer)) {
439 printf("%s: invalid GPT - refusing to write to flash\n",
440 __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000441 fastboot_fail("invalid GPT partition", response);
Steve Rae7d059342014-12-12 15:51:54 -0800442 return;
443 }
444 if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
445 printf("%s: writing GPT partitions failed\n", __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000446 fastboot_fail("writing GPT partitions failed",
447 response);
Steve Rae7d059342014-12-12 15:51:54 -0800448 return;
449 }
450 printf("........ success\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000451 fastboot_okay(NULL, response);
Steve Rae7d059342014-12-12 15:51:54 -0800452 return;
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200453 }
454#endif
455
Patrick Delaunayf7e07722017-01-27 11:00:37 +0100456#if CONFIG_IS_ENABLED(DOS_PARTITION)
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200457 if (strcmp(cmd, CONFIG_FASTBOOT_MBR_NAME) == 0) {
458 printf("%s: updating MBR\n", __func__);
459 if (is_valid_dos_buf(download_buffer)) {
460 printf("%s: invalid MBR - refusing to write to flash\n",
461 __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000462 fastboot_fail("invalid MBR partition", response);
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200463 return;
464 }
465 if (write_mbr_partition(dev_desc, download_buffer)) {
466 printf("%s: writing MBR partition failed\n", __func__);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000467 fastboot_fail("writing MBR partition failed",
468 response);
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200469 return;
470 }
471 printf("........ success\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000472 fastboot_okay(NULL, response);
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200473 return;
474 }
475#endif
476
Sam Protsenko540eb952017-05-18 15:04:59 +0300477#ifdef CONFIG_ANDROID_BOOT_IMAGE
478 if (strncasecmp(cmd, "zimage", 6) == 0) {
Alex Kiernan27b69de2018-05-29 15:30:40 +0000479 fb_mmc_update_zimage(dev_desc, download_buffer,
480 download_bytes, response);
Sam Protsenko540eb952017-05-18 15:04:59 +0300481 return;
482 }
483#endif
484
Alex Deymoe2f689f2017-04-02 01:49:50 -0700485 if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900486 pr_err("cannot find partition: '%s'\n", cmd);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000487 fastboot_fail("cannot find partition", response);
Steve Rae792ac482014-08-26 11:47:27 -0700488 return;
489 }
490
Maxime Riparda58e9c72015-10-15 14:34:14 +0200491 if (is_sparse_image(download_buffer)) {
492 struct fb_mmc_sparse sparse_priv;
Steve Rae8cf58db2016-06-07 11:19:36 -0700493 struct sparse_storage sparse;
Jassi Brar427e6692018-04-06 12:05:09 +0530494 int err;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200495
496 sparse_priv.dev_desc = dev_desc;
497
Steve Rae8cf58db2016-06-07 11:19:36 -0700498 sparse.blksz = info.blksz;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200499 sparse.start = info.start;
500 sparse.size = info.size;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200501 sparse.write = fb_mmc_sparse_write;
Steve Rae8a99be82016-06-07 11:19:38 -0700502 sparse.reserve = fb_mmc_sparse_reserve;
Jassi Brar427e6692018-04-06 12:05:09 +0530503 sparse.mssg = fastboot_fail;
Maxime Riparda58e9c72015-10-15 14:34:14 +0200504
505 printf("Flashing sparse image at offset " LBAFU "\n",
Steve Rae8cf58db2016-06-07 11:19:36 -0700506 sparse.start);
Maxime Riparda58e9c72015-10-15 14:34:14 +0200507
Steve Rae8cf58db2016-06-07 11:19:36 -0700508 sparse.priv = &sparse_priv;
Alex Kiernan27b69de2018-05-29 15:30:40 +0000509 err = write_sparse_image(&sparse, cmd, download_buffer,
510 response);
Jassi Brar427e6692018-04-06 12:05:09 +0530511 if (!err)
Alex Kiernan27b69de2018-05-29 15:30:40 +0000512 fastboot_okay(NULL, response);
Maxime Riparda58e9c72015-10-15 14:34:14 +0200513 } else {
Steve Raec6015672014-08-26 11:47:30 -0700514 write_raw_image(dev_desc, &info, cmd, download_buffer,
Alex Kiernan27b69de2018-05-29 15:30:40 +0000515 download_bytes, response);
Maxime Riparda58e9c72015-10-15 14:34:14 +0200516 }
Steve Rae792ac482014-08-26 11:47:27 -0700517}
Dileep Kattab1228202015-02-17 18:48:23 +0530518
Alex Kiernan32c21942018-05-29 15:30:48 +0000519/**
520 * fastboot_mmc_flash_erase() - Erase eMMC for fastboot
521 *
522 * @cmd: Named partition to erase
523 * @response: Pointer to fastboot response buffer
524 */
525void fastboot_mmc_erase(const char *cmd, char *response)
Dileep Kattab1228202015-02-17 18:48:23 +0530526{
527 int ret;
Simon Glasse3394752016-02-29 15:25:34 -0700528 struct blk_desc *dev_desc;
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600529 struct disk_partition info;
Dileep Kattab1228202015-02-17 18:48:23 +0530530 lbaint_t blks, blks_start, blks_size, grp_size;
531 struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
532
533 if (mmc == NULL) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000534 pr_err("invalid mmc device\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000535 fastboot_fail("invalid mmc device", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530536 return;
537 }
538
Simon Glassbe1e9bb2016-02-29 15:25:42 -0700539 dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
Dileep Kattab1228202015-02-17 18:48:23 +0530540 if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000541 pr_err("invalid mmc device\n");
Alex Kiernan27b69de2018-05-29 15:30:40 +0000542 fastboot_fail("invalid mmc device", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530543 return;
544 }
developer6a105562020-01-16 16:11:42 +0800545
546#ifdef CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT
547 if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) {
548 /* erase EMMC boot1 */
549 fb_mmc_boot1_ops(dev_desc, NULL, 0, response);
550 return;
551 }
552#endif
553
554#ifdef CONFIG_FASTBOOT_MMC_USER_NAME
555 if (strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) {
556 /* erase EMMC userdata */
557 if (fb_mmc_erase_mmc_hwpart(dev_desc))
558 fastboot_fail("Failed to erase EMMC_USER", response);
559 else
560 fastboot_okay(NULL, response);
561 return;
562 }
563#endif
Dileep Kattab1228202015-02-17 18:48:23 +0530564
Petr Kulhavy9f174c92016-09-09 10:27:16 +0200565 ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
Alex Deymoe2f689f2017-04-02 01:49:50 -0700566 if (ret < 0) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000567 pr_err("cannot find partition: '%s'\n", cmd);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000568 fastboot_fail("cannot find partition", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530569 return;
570 }
571
572 /* Align blocks to erase group size to avoid erasing other partitions */
573 grp_size = mmc->erase_grp_size;
574 blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
575 if (info.size >= grp_size)
576 blks_size = (info.size - (blks_start - info.start)) &
577 (~(grp_size - 1));
578 else
579 blks_size = 0;
580
581 printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
582 blks_start, blks_start + blks_size);
583
Alex Kiernand5aa57c2018-05-29 15:30:53 +0000584 blks = fb_mmc_blk_write(dev_desc, blks_start, blks_size, NULL);
585
Dileep Kattab1228202015-02-17 18:48:23 +0530586 if (blks != blks_size) {
Alex Kiernan82fe3f22018-05-29 15:30:43 +0000587 pr_err("failed erasing from device %d\n", dev_desc->devnum);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000588 fastboot_fail("failed erasing from device", response);
Dileep Kattab1228202015-02-17 18:48:23 +0530589 return;
590 }
591
592 printf("........ erased " LBAFU " bytes from '%s'\n",
593 blks_size * info.blksz, cmd);
Alex Kiernan27b69de2018-05-29 15:30:40 +0000594 fastboot_okay(NULL, response);
Dileep Kattab1228202015-02-17 18:48:23 +0530595}