xref: /rk3399_rockchip-uboot/common/fb_mmc.c (revision e17ddcea32b2fa7b82fb079f37195855a55e39a2)
1 /*
2  * Copyright 2014 Broadcom Corporation.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <config.h>
8 #include <common.h>
9 #include <blk.h>
10 #include <fastboot.h>
11 #include <fb_mmc.h>
12 #include <image-sparse.h>
13 #include <part.h>
14 #include <mmc.h>
15 #include <div64.h>
16 #include <linux/compat.h>
17 #include <android_image.h>
18 #ifdef CONFIG_RKIMG_BOOTLOADER
19 #include <boot_rkimg.h>
20 #endif
21 /*
22  * FIXME: Ensure we always set these names via Kconfig once xxx_PARTITION is
23  * migrated
24  */
25 #ifndef CONFIG_FASTBOOT_GPT_NAME
26 #define CONFIG_FASTBOOT_GPT_NAME "gpt"
27 #endif
28 
29 
30 #ifndef CONFIG_FASTBOOT_MBR_NAME
31 #define CONFIG_FASTBOOT_MBR_NAME "mbr"
32 #endif
33 
34 #define BOOT_PARTITION_NAME "boot"
35 #define FASTBOOT_MAX_BLK_WRITE 16384
36 static ulong timer;
37 
38 struct fb_mmc_sparse {
39 	struct blk_desc	*dev_desc;
40 };
41 
42 static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc,
43 		const char *name, disk_partition_t *info)
44 {
45 	int ret;
46 
47 	ret = part_get_info_by_name(dev_desc, name, info);
48 	if (ret < 0) {
49 		/* strlen("fastboot_partition_alias_") + 32(part_name) + 1 */
50 		char env_alias_name[25 + 32 + 1];
51 		char *aliased_part_name;
52 
53 		/* check for alias */
54 		strcpy(env_alias_name, "fastboot_partition_alias_");
55 		strncat(env_alias_name, name, 32);
56 		aliased_part_name = env_get(env_alias_name);
57 		if (aliased_part_name != NULL)
58 			ret = part_get_info_by_name(dev_desc,
59 					aliased_part_name, info);
60 	}
61 	return ret;
62 }
63 
64 static lbaint_t fb_mmc_blk_write(struct blk_desc *block_dev, lbaint_t start,
65 		lbaint_t blkcnt, const void *buffer)
66 {
67 	lbaint_t blk = start;
68 	lbaint_t blks_written;
69 	lbaint_t cur_blkcnt;
70 	lbaint_t blks = 0;
71 	int i;
72 	for (i = 0; i < blkcnt; i += FASTBOOT_MAX_BLK_WRITE) {
73 		cur_blkcnt = min((int)blkcnt-i, FASTBOOT_MAX_BLK_WRITE);
74 		if (buffer != NULL) {
75 			timed_send_info(&timer, "writing");
76 			blks_written = blk_dwrite(block_dev, blk, cur_blkcnt,
77 					buffer+(i*block_dev->blksz));
78 		} else {
79 			timed_send_info(&timer, "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 
88 static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info,
89 		lbaint_t blk, lbaint_t blkcnt, const void *buffer)
90 {
91 	struct fb_mmc_sparse *sparse = info->priv;
92 	struct blk_desc *dev_desc = sparse->dev_desc;
93 
94 	return fb_mmc_blk_write(dev_desc, blk, blkcnt, buffer);
95 }
96 
97 static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info,
98 		lbaint_t blk, lbaint_t blkcnt)
99 {
100 	return blkcnt;
101 }
102 
103 static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info,
104 		const char *part_name, void *buffer,
105 		unsigned int download_bytes, char *response)
106 {
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));
112 	blkcnt = lldiv(blkcnt, info->blksz);
113 
114 	if (blkcnt > info->size) {
115 		pr_err("too large for partition: '%s'\n", part_name);
116 		fastboot_fail("too large for partition", response);
117 		return;
118 	}
119 
120 	puts("Flashing Raw Image\n");
121 
122 	blks = fb_mmc_blk_write(dev_desc, info->start, blkcnt, buffer);
123 	if (blks != blkcnt) {
124 		pr_err("failed writing to device %d\n", dev_desc->devnum);
125 		fastboot_fail("failed writing to device", response);
126 		return;
127 	}
128 
129 	printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz,
130 	       part_name);
131 	fastboot_okay("", response);
132 }
133 
134 #ifdef CONFIG_ANDROID_BOOT_IMAGE
135 /**
136  * Read Android boot image header from boot partition.
137  *
138  * @param[in] dev_desc MMC device descriptor
139  * @param[in] info Boot partition info
140  * @param[out] hdr Where to store read boot image header
141  *
142  * @return Boot image header sectors count or 0 on error
143  */
144 static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
145 				       disk_partition_t *info,
146 				       struct andr_img_hdr *hdr,
147 				       char *response)
148 {
149 	ulong sector_size;		/* boot partition sector size */
150 	lbaint_t hdr_sectors;		/* boot image header sectors count */
151 	int res;
152 
153 	/* Calculate boot image sectors count */
154 	sector_size = info->blksz;
155 	hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size);
156 	if (hdr_sectors == 0) {
157 		pr_err("invalid number of boot sectors: 0");
158 		fastboot_fail("invalid number of boot sectors: 0", response);
159 		return 0;
160 	}
161 
162 	/* Read the boot image header */
163 	res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr);
164 	if (res != hdr_sectors) {
165 		pr_err("cannot read header from boot partition");
166 		fastboot_fail("cannot read header from boot partition", response);
167 		return 0;
168 	}
169 
170 	/* Check boot header magic string */
171 	res = android_image_check_header(hdr);
172 	if (res != 0) {
173 		pr_err("bad boot image magic");
174 		fastboot_fail("boot partition not initialized", response);
175 		return 0;
176 	}
177 
178 	return hdr_sectors;
179 }
180 
181 /**
182  * Write downloaded zImage to boot partition and repack it properly.
183  *
184  * @param dev_desc MMC device descriptor
185  * @param download_buffer Address to fastboot buffer with zImage in it
186  * @param download_bytes Size of fastboot buffer, in bytes
187  *
188  * @return 0 on success or -1 on error
189  */
190 static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
191 				void *download_buffer,
192 				unsigned int download_bytes,
193 				char *response)
194 {
195 	uintptr_t hdr_addr;			/* boot image header address */
196 	struct andr_img_hdr *hdr;		/* boot image header */
197 	lbaint_t hdr_sectors;			/* boot image header sectors */
198 	u8 *ramdisk_buffer;
199 	u32 ramdisk_sector_start;
200 	u32 ramdisk_sectors;
201 	u32 kernel_sector_start;
202 	u32 kernel_sectors;
203 	u32 sectors_per_page;
204 	disk_partition_t info;
205 	int res;
206 
207 	puts("Flashing zImage\n");
208 
209 	/* Get boot partition info */
210 	res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info);
211 	if (res < 0) {
212 		pr_err("cannot find boot partition");
213 		fastboot_fail("cannot find boot partition", response);
214 		return -1;
215 	}
216 
217 	/* Put boot image header in fastboot buffer after downloaded zImage */
218 	hdr_addr = (uintptr_t)download_buffer + ALIGN(download_bytes, PAGE_SIZE);
219 	hdr = (struct andr_img_hdr *)hdr_addr;
220 
221 	/* Read boot image header */
222 	hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr, response);
223 	if (hdr_sectors == 0) {
224 		pr_err("unable to read boot image header");
225 		fastboot_fail("unable to read boot image header", response);
226 		return -1;
227 	}
228 
229 	/* Check if boot image has second stage in it (we don't support it) */
230 	if (hdr->second_size > 0) {
231 		pr_err("moving second stage is not supported yet");
232 		fastboot_fail("moving second stage is not supported yet", response);
233 		return -1;
234 	}
235 
236 	/* Extract ramdisk location */
237 	sectors_per_page = hdr->page_size / info.blksz;
238 	ramdisk_sector_start = info.start + sectors_per_page;
239 	ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) *
240 					     sectors_per_page;
241 	ramdisk_sectors = DIV_ROUND_UP(hdr->ramdisk_size, hdr->page_size) *
242 				       sectors_per_page;
243 
244 	/* Read ramdisk and put it in fastboot buffer after boot image header */
245 	ramdisk_buffer = (u8 *)hdr + (hdr_sectors * info.blksz);
246 	res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors,
247 			ramdisk_buffer);
248 	if (res != ramdisk_sectors) {
249 		pr_err("cannot read ramdisk from boot partition");
250 		fastboot_fail("cannot read ramdisk from boot partition", response);
251 		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) {
258 		pr_err("cannot writeback boot image header");
259 		fastboot_fail("cannot write back boot image header", response);
260 		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) {
270 		pr_err("cannot write new kernel");
271 		fastboot_fail("cannot write new kernel", response);
272 		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) {
282 		pr_err("cannot write back original ramdisk");
283 		fastboot_fail("cannot write back original ramdisk", response);
284 		return -1;
285 	}
286 
287 	puts("........ zImage was updated in boot partition\n");
288 	fastboot_okay("", response);
289 	return 0;
290 }
291 #endif
292 
293 void fb_mmc_flash_write(const char *cmd, void *download_buffer,
294 			unsigned int download_bytes, char *response)
295 {
296 	struct blk_desc *dev_desc;
297 	disk_partition_t info;
298 #if CONFIG_IS_ENABLED(EFI_PARTITION)
299 	u64 disksize = 0;
300 	char reason[128] = {0};
301 #endif
302 #ifdef CONFIG_RKIMG_BOOTLOADER
303 	dev_desc = rockchip_get_bootdev();
304 #else
305 	dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
306 #endif
307 	if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
308 		pr_err("invalid mmc device\n");
309 		fastboot_fail("invalid mmc device", response);
310 		return;
311 	}
312 
313 #if CONFIG_IS_ENABLED(EFI_PARTITION)
314 	if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
315 		printf("%s: updating MBR, Primary and Backup GPT(s)\n",
316 		       __func__);
317 		if (is_valid_gpt_buf(dev_desc, download_buffer)) {
318 			printf("%s: invalid GPT - refusing to write to flash\n",
319 			       __func__);
320 			disksize = dev_desc->blksz * cpu_to_le64(dev_desc->lba);
321 			snprintf(reason, ARRAY_SIZE(reason),
322 				 "%s - %s '%lld.%lld MiB')",
323 					"invalid GPT partition",
324 					"Actual Disk Size",
325 					disksize/0x100000,
326 					disksize%0x100000);
327 			fastboot_fail(reason, response);
328 			return;
329 		}
330 		if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
331 			printf("%s: writing GPT partitions failed\n", __func__);
332 			fastboot_fail(
333 				      "writing GPT partitions failed", response);
334 			return;
335 		}
336 		printf("........ success\n");
337 		fastboot_okay("", response);
338 		return;
339 	}
340 #endif
341 
342 #if CONFIG_IS_ENABLED(DOS_PARTITION)
343 	if (strcmp(cmd, CONFIG_FASTBOOT_MBR_NAME) == 0) {
344 		printf("%s: updating MBR\n", __func__);
345 		if (is_valid_dos_buf(download_buffer)) {
346 			printf("%s: invalid MBR - refusing to write to flash\n",
347 			       __func__);
348 			fastboot_fail("invalid MBR partition", response);
349 			return;
350 		}
351 		if (write_mbr_partition(dev_desc, download_buffer)) {
352 			printf("%s: writing MBR partition failed\n", __func__);
353 			fastboot_fail("writing MBR partition failed", response);
354 			return;
355 		}
356 		printf("........ success\n");
357 		fastboot_okay("", response);
358 		return;
359 	}
360 #endif
361 
362 #ifdef CONFIG_ANDROID_BOOT_IMAGE
363 	if (strncasecmp(cmd, "zimage", 6) == 0) {
364 		fb_mmc_update_zimage(dev_desc, download_buffer, download_bytes, response);
365 		return;
366 	}
367 #endif
368 
369 	if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
370 		pr_err("cannot find partition: '%s'\n", cmd);
371 		fastboot_fail("cannot find partition", response);
372 		return;
373 	}
374 
375 	if (is_sparse_image(download_buffer)) {
376 		struct fb_mmc_sparse sparse_priv;
377 		struct sparse_storage sparse;
378 
379 		sparse_priv.dev_desc = dev_desc;
380 
381 		sparse.blksz = info.blksz;
382 		sparse.start = info.start;
383 		sparse.size = info.size;
384 		sparse.write = fb_mmc_sparse_write;
385 		sparse.reserve = fb_mmc_sparse_reserve;
386 
387 		printf("Flashing sparse image at offset " LBAFU "\n",
388 		       sparse.start);
389 
390 		sparse.priv = &sparse_priv;
391 		write_sparse_image(&sparse, cmd, download_buffer,
392 				   download_bytes, response);
393 	} else {
394 		write_raw_image(dev_desc, &info, cmd, download_buffer,
395 				download_bytes, response);
396 	}
397 }
398 
399 void fb_mmc_erase(const char *cmd, char *response)
400 {
401 	int ret;
402 	struct blk_desc *dev_desc;
403 	disk_partition_t info;
404 	lbaint_t blks, blks_start, blks_size, grp_size;
405 	struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
406 
407 	if (mmc == NULL) {
408 		pr_err("invalid mmc device");
409 		fastboot_fail("invalid mmc device", response);
410 		return;
411 	}
412 
413 #ifdef CONFIG_RKIMG_BOOTLOADER
414 	dev_desc = rockchip_get_bootdev();
415 #else
416 	dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
417 #endif
418 	if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
419 		pr_err("invalid mmc device");
420 		fastboot_fail("invalid mmc device", response);
421 		return;
422 	}
423 
424 	ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
425 	if (ret < 0) {
426 		pr_err("cannot find partition: '%s'", cmd);
427 		fastboot_fail("cannot find partition", response);
428 		return;
429 	}
430 
431 	/* Align blocks to erase group size to avoid erasing other partitions */
432 	grp_size = mmc->erase_grp_size;
433 	blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
434 	if (info.size >= grp_size)
435 		blks_size = (info.size - (blks_start - info.start)) &
436 				(~(grp_size - 1));
437 	else
438 		blks_size = 0;
439 
440 	printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
441 	       blks_start, blks_start + blks_size);
442 
443 	blks = fb_mmc_blk_write(dev_desc, blks_start, blks_size, NULL);
444 	if (blks != blks_size) {
445 		pr_err("failed erasing from device %d", dev_desc->devnum);
446 		fastboot_fail("failed erasing from device", response);
447 		return;
448 	}
449 
450 	printf("........ erased " LBAFU " bytes from '%s'\n",
451 	       blks_size * info.blksz, cmd);
452 	fastboot_okay("", response);
453 }
454