• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public
4  * License v2 as published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9  * General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the
13  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14  * Boston, MA 021110-1307, USA.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/ioctl.h>
21 #include <sys/types.h>
22 #include <sys/endian.h>
23 #include <dirent.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <libgen.h>
28 #include <limits.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <stdint.h>
32 #include <assert.h>
33 
34 #include "mmc.h"
35 #include "mmc_cmds.h"
36 #include "3rdparty/hmac_sha/hmac_sha2.h"
37 
read_extcsd(int fd,__u8 * ext_csd)38 int read_extcsd(int fd, __u8 *ext_csd)
39 {
40 	int ret = 0;
41 	struct mmc_ioc_cmd idata;
42 	memset(&idata, 0, sizeof(idata));
43 	memset(ext_csd, 0, sizeof(__u8) * 512);
44 	idata.write_flag = 0;
45 	idata.opcode = MMC_SEND_EXT_CSD;
46 	idata.arg = 0;
47 	idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
48 	idata.blksz = 512;
49 	idata.blocks = 1;
50 	mmc_ioc_cmd_set_data(idata, ext_csd);
51 
52 	ret = ioctl(fd, MMC_IOC_CMD, &idata);
53 	if (ret)
54 		perror("ioctl");
55 
56 	return ret;
57 }
58 
write_extcsd_value(int fd,__u8 index,__u8 value)59 int write_extcsd_value(int fd, __u8 index, __u8 value)
60 {
61 	int ret = 0;
62 	struct mmc_ioc_cmd idata;
63 
64 	memset(&idata, 0, sizeof(idata));
65 	idata.write_flag = 1;
66 	idata.opcode = MMC_SWITCH;
67 	idata.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
68 			(index << 16) |
69 			(value << 8) |
70 			EXT_CSD_CMD_SET_NORMAL;
71 	idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
72 
73 	ret = ioctl(fd, MMC_IOC_CMD, &idata);
74 	if (ret)
75 		perror("ioctl");
76 
77 	return ret;
78 }
79 
send_status(int fd,__u32 * response)80 int send_status(int fd, __u32 *response)
81 {
82 	int ret = 0;
83 	struct mmc_ioc_cmd idata;
84 
85 	memset(&idata, 0, sizeof(idata));
86 	idata.opcode = MMC_SEND_STATUS;
87 	idata.arg = (1 << 16);
88 	idata.flags = MMC_RSP_R1 | MMC_CMD_AC;
89 
90 	ret = ioctl(fd, MMC_IOC_CMD, &idata);
91 	if (ret)
92 	perror("ioctl");
93 
94 	*response = idata.response[0];
95 
96 	return ret;
97 }
98 
print_writeprotect_status(__u8 * ext_csd)99 void print_writeprotect_status(__u8 *ext_csd)
100 {
101 	__u8 reg;
102 	__u8 ext_csd_rev = ext_csd[EXT_CSD_REV];
103 
104 	/* A43: reserved [174:0] */
105 	if (ext_csd_rev >= 5) {
106 		printf("Boot write protection status registers"
107 			" [BOOT_WP_STATUS]: 0x%02x\n", ext_csd[174]);
108 
109 		reg = ext_csd[EXT_CSD_BOOT_WP];
110 		printf("Boot Area Write protection [BOOT_WP]: 0x%02x\n", reg);
111 		printf(" Power ro locking: ");
112 		if (reg & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
113 			printf("not possible\n");
114 		else
115 			printf("possible\n");
116 
117 		printf(" Permanent ro locking: ");
118 		if (reg & EXT_CSD_BOOT_WP_B_PERM_WP_DIS)
119 			printf("not possible\n");
120 		else
121 			printf("possible\n");
122 
123 		printf(" ro lock status: ");
124 		if (reg & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
125 			printf("locked until next power on\n");
126 		else if (reg & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
127 			printf("locked permanently\n");
128 		else
129 			printf("not locked\n");
130 	}
131 }
132 
do_writeprotect_get(int nargs,char ** argv)133 int do_writeprotect_get(int nargs, char **argv)
134 {
135 	__u8 ext_csd[512];
136 	int fd, ret;
137 	char *device;
138 
139 	CHECK(nargs != 2, "Usage: mmc writeprotect get </path/to/mmcblkX>\n",
140 			  exit(1));
141 
142 	device = argv[1];
143 
144 	fd = open(device, O_RDWR);
145 	if (fd < 0) {
146 		perror("open");
147 		exit(1);
148 	}
149 
150 	ret = read_extcsd(fd, ext_csd);
151 	if (ret) {
152 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
153 		exit(1);
154 	}
155 
156 	print_writeprotect_status(ext_csd);
157 
158 	return ret;
159 }
160 
do_writeprotect_set(int nargs,char ** argv)161 int do_writeprotect_set(int nargs, char **argv)
162 {
163 	__u8 ext_csd[512], value;
164 	int fd, ret;
165 	char *device;
166 
167 	CHECK(nargs != 2, "Usage: mmc writeprotect set </path/to/mmcblkX>\n",
168 			  exit(1));
169 
170 	device = argv[1];
171 
172 	fd = open(device, O_RDWR);
173 	if (fd < 0) {
174 		perror("open");
175 		exit(1);
176 	}
177 
178 	ret = read_extcsd(fd, ext_csd);
179 	if (ret) {
180 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
181 		exit(1);
182 	}
183 
184 	value = ext_csd[EXT_CSD_BOOT_WP] |
185 		EXT_CSD_BOOT_WP_B_PWR_WP_EN;
186 	ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value);
187 	if (ret) {
188 		fprintf(stderr, "Could not write 0x%02x to "
189 			"EXT_CSD[%d] in %s\n",
190 			value, EXT_CSD_BOOT_WP, device);
191 		exit(1);
192 	}
193 
194 	return ret;
195 }
196 
do_disable_512B_emulation(int nargs,char ** argv)197 int do_disable_512B_emulation(int nargs, char **argv)
198 {
199 	__u8 ext_csd[512], native_sector_size, data_sector_size, wr_rel_param;
200 	int fd, ret;
201 	char *device;
202 
203 	CHECK(nargs != 2, "Usage: mmc disable 512B emulation </path/to/mmcblkX>\n", exit(1));
204 	device = argv[1];
205 
206 	fd = open(device, O_RDWR);
207 	if (fd < 0) {
208 		perror("open");
209 		exit(1);
210 	}
211 
212 	ret = read_extcsd(fd, ext_csd);
213 	if (ret) {
214 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
215 		exit(1);
216 	}
217 
218 	wr_rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
219 	native_sector_size = ext_csd[EXT_CSD_NATIVE_SECTOR_SIZE];
220 	data_sector_size = ext_csd[EXT_CSD_DATA_SECTOR_SIZE];
221 
222 	if (native_sector_size && !data_sector_size &&
223 	   (wr_rel_param & EN_REL_WR)) {
224 		ret = write_extcsd_value(fd, EXT_CSD_USE_NATIVE_SECTOR, 1);
225 
226 		if (ret) {
227 			fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
228 					1, EXT_CSD_BOOT_WP, device);
229 			exit(1);
230 		}
231 		printf("MMC disable 512B emulation successful.  Now reset the device to switch to 4KB native sector mode.\n");
232 	} else if (native_sector_size && data_sector_size) {
233 		printf("MMC 512B emulation mode is already disabled; doing nothing.\n");
234 	} else {
235 		printf("MMC does not support disabling 512B emulation mode.\n");
236 	}
237 
238 	return ret;
239 }
240 
do_write_boot_en(int nargs,char ** argv)241 int do_write_boot_en(int nargs, char **argv)
242 {
243 	__u8 ext_csd[512];
244 	__u8 value = 0;
245 	int fd, ret;
246 	char *device;
247 	int boot_area, send_ack;
248 
249 	CHECK(nargs != 4, "Usage: mmc bootpart enable <partition_number> "
250 			  "<send_ack> </path/to/mmcblkX>\n", exit(1));
251 
252 	/*
253 	 * If <send_ack> is 1, the device will send acknowledgment
254 	 * pattern "010" to the host when boot operation begins.
255 	 * If <send_ack> is 0, it won't.
256 	 */
257 	boot_area = strtol(argv[1], NULL, 10);
258 	send_ack = strtol(argv[2], NULL, 10);
259 	device = argv[3];
260 
261 	fd = open(device, O_RDWR);
262 	if (fd < 0) {
263 		perror("open");
264 		exit(1);
265 	}
266 
267 	ret = read_extcsd(fd, ext_csd);
268 	if (ret) {
269 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
270 		exit(1);
271 	}
272 
273 	value = ext_csd[EXT_CSD_PART_CONFIG];
274 
275 	switch (boot_area) {
276 	case EXT_CSD_PART_CONFIG_ACC_BOOT0:
277 		value |= (1 << 3);
278 		value &= ~(3 << 4);
279 		break;
280 	case EXT_CSD_PART_CONFIG_ACC_BOOT1:
281 		value |= (1 << 4);
282 		value &= ~(1 << 3);
283 		value &= ~(1 << 5);
284 		break;
285 	case EXT_CSD_PART_CONFIG_ACC_USER_AREA:
286 		value |= (boot_area << 3);
287 		break;
288 	default:
289 		fprintf(stderr, "Cannot enable the boot area\n");
290 		exit(1);
291 	}
292 	if (send_ack)
293 		value |= EXT_CSD_PART_CONFIG_ACC_ACK;
294 	else
295 		value &= ~EXT_CSD_PART_CONFIG_ACC_ACK;
296 
297 	ret = write_extcsd_value(fd, EXT_CSD_PART_CONFIG, value);
298 	if (ret) {
299 		fprintf(stderr, "Could not write 0x%02x to "
300 			"EXT_CSD[%d] in %s\n",
301 			value, EXT_CSD_PART_CONFIG, device);
302 		exit(1);
303 	}
304 	return ret;
305 }
306 
do_boot_bus_conditions_set(int nargs,char ** argv)307 int do_boot_bus_conditions_set(int nargs, char **argv)
308 {
309 	__u8 ext_csd[512];
310 	__u8 value = 0;
311 	int fd, ret;
312 	char *device;
313 
314 	CHECK(nargs != 5, "Usage: mmc: bootbus set <boot_mode> "
315 	      "<reset_boot_bus_conditions> <boot_bus_width> <device>\n",
316 		exit(1));
317 
318 	if (strcmp(argv[1], "single_backward") == 0)
319 		value |= 0;
320 	else if (strcmp(argv[1], "single_hs") == 0)
321 		value |= 0x8;
322 	else if (strcmp(argv[1], "dual") == 0)
323 		value |= 0x10;
324 	else {
325 		fprintf(stderr, "illegal <boot_mode> specified\n");
326 		exit(1);
327 	}
328 
329 	if (strcmp(argv[2], "x1") == 0)
330 		value |= 0;
331 	else if (strcmp(argv[2], "retain") == 0)
332 		value |= 0x4;
333 	else {
334 		fprintf(stderr,
335 			"illegal <reset_boot_bus_conditions> specified\n");
336 		exit(1);
337 	}
338 
339 	if (strcmp(argv[3], "x1") == 0)
340 		value |= 0;
341 	else if (strcmp(argv[3], "x4") == 0)
342 		value |= 0x1;
343 	else if (strcmp(argv[3], "x8") == 0)
344 		value |= 0x2;
345 	else {
346 		fprintf(stderr,	"illegal <boot_bus_width> specified\n");
347 		exit(1);
348 	}
349 
350 	device = argv[4];
351 	fd = open(device, O_RDWR);
352 	if (fd < 0) {
353 		perror("open");
354 		exit(1);
355 	}
356 
357 	ret = read_extcsd(fd, ext_csd);
358 	if (ret) {
359 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
360 		exit(1);
361 	}
362 	printf("Changing ext_csd[BOOT_BUS_CONDITIONS] from 0x%02x to 0x%02x\n",
363 		ext_csd[EXT_CSD_BOOT_BUS_CONDITIONS], value);
364 
365 	ret = write_extcsd_value(fd, EXT_CSD_BOOT_BUS_CONDITIONS, value);
366 	if (ret) {
367 		fprintf(stderr, "Could not write 0x%02x to "
368 			"EXT_CSD[%d] in %s\n",
369 			value, EXT_CSD_BOOT_BUS_CONDITIONS, device);
370 		exit(1);
371 	}
372 	close(fd);
373 	return ret;
374 }
375 
do_hwreset(int value,int nargs,char ** argv)376 int do_hwreset(int value, int nargs, char **argv)
377 {
378 	__u8 ext_csd[512];
379 	int fd, ret;
380 	char *device;
381 
382 	CHECK(nargs != 2, "Usage: mmc hwreset enable </path/to/mmcblkX>\n",
383 			  exit(1));
384 
385 	device = argv[1];
386 
387 	fd = open(device, O_RDWR);
388 	if (fd < 0) {
389 		perror("open");
390 		exit(1);
391 	}
392 
393 	ret = read_extcsd(fd, ext_csd);
394 	if (ret) {
395 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
396 		exit(1);
397 	}
398 
399 	if ((ext_csd[EXT_CSD_RST_N_FUNCTION] & EXT_CSD_RST_N_EN_MASK) ==
400 	    EXT_CSD_HW_RESET_EN) {
401 		fprintf(stderr,
402 			"H/W Reset is already permanently enabled on %s\n",
403 			device);
404 		exit(1);
405 	}
406 	if ((ext_csd[EXT_CSD_RST_N_FUNCTION] & EXT_CSD_RST_N_EN_MASK) ==
407 	    EXT_CSD_HW_RESET_DIS) {
408 		fprintf(stderr,
409 			"H/W Reset is already permanently disabled on %s\n",
410 			device);
411 		exit(1);
412 	}
413 
414 	ret = write_extcsd_value(fd, EXT_CSD_RST_N_FUNCTION, value);
415 	if (ret) {
416 		fprintf(stderr,
417 			"Could not write 0x%02x to EXT_CSD[%d] in %s\n",
418 			value, EXT_CSD_RST_N_FUNCTION, device);
419 		exit(1);
420 	}
421 
422 	return ret;
423 }
424 
do_hwreset_en(int nargs,char ** argv)425 int do_hwreset_en(int nargs, char **argv)
426 {
427 	return do_hwreset(EXT_CSD_HW_RESET_EN, nargs, argv);
428 }
429 
do_hwreset_dis(int nargs,char ** argv)430 int do_hwreset_dis(int nargs, char **argv)
431 {
432 	return do_hwreset(EXT_CSD_HW_RESET_DIS, nargs, argv);
433 }
434 
do_write_bkops_en(int nargs,char ** argv)435 int do_write_bkops_en(int nargs, char **argv)
436 {
437 	__u8 ext_csd[512], value = 0;
438 	int fd, ret;
439 	char *device;
440 
441 	CHECK(nargs != 2, "Usage: mmc bkops enable </path/to/mmcblkX>\n",
442 			exit(1));
443 
444 	device = argv[1];
445 
446 	fd = open(device, O_RDWR);
447 	if (fd < 0) {
448 		perror("open");
449 		exit(1);
450 	}
451 
452 	ret = read_extcsd(fd, ext_csd);
453 	if (ret) {
454 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
455 		exit(1);
456 	}
457 
458 	if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
459 		fprintf(stderr, "%s doesn't support BKOPS\n", device);
460 		exit(1);
461 	}
462 
463 	ret = write_extcsd_value(fd, EXT_CSD_BKOPS_EN, BKOPS_ENABLE);
464 	if (ret) {
465 		fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
466 			value, EXT_CSD_BKOPS_EN, device);
467 		exit(1);
468 	}
469 
470 	return ret;
471 }
472 
do_status_get(int nargs,char ** argv)473 int do_status_get(int nargs, char **argv)
474 {
475 	__u32 response;
476 	int fd, ret;
477 	char *device;
478 
479 	CHECK(nargs != 2, "Usage: mmc status get </path/to/mmcblkX>\n",
480 		exit(1));
481 
482 	device = argv[1];
483 
484 	fd = open(device, O_RDWR);
485 	if (fd < 0) {
486 		perror("open");
487 		exit(1);
488 	}
489 
490 	ret = send_status(fd, &response);
491 	if (ret) {
492 		fprintf(stderr, "Could not read response to SEND_STATUS from %s\n", device);
493 		exit(1);
494 	}
495 
496 	printf("SEND_STATUS response: 0x%08x\n", response);
497 
498 	return ret;
499 }
500 
get_sector_count(__u8 * ext_csd)501 unsigned int get_sector_count(__u8 *ext_csd)
502 {
503 	return (ext_csd[EXT_CSD_SEC_COUNT_3] << 24) |
504 	(ext_csd[EXT_CSD_SEC_COUNT_2] << 16) |
505 	(ext_csd[EXT_CSD_SEC_COUNT_1] << 8)  |
506 	ext_csd[EXT_CSD_SEC_COUNT_0];
507 }
508 
is_blockaddresed(__u8 * ext_csd)509 int is_blockaddresed(__u8 *ext_csd)
510 {
511 	unsigned int sectors = get_sector_count(ext_csd);
512 
513 	return (sectors > (2u * 1024 * 1024 * 1024) / 512);
514 }
515 
get_hc_wp_grp_size(__u8 * ext_csd)516 unsigned int get_hc_wp_grp_size(__u8 *ext_csd)
517 {
518 	return ext_csd[221];
519 }
520 
get_hc_erase_grp_size(__u8 * ext_csd)521 unsigned int get_hc_erase_grp_size(__u8 *ext_csd)
522 {
523 	return ext_csd[224];
524 }
525 
set_partitioning_setting_completed(int dry_run,const char * const device,int fd)526 int set_partitioning_setting_completed(int dry_run, const char * const device,
527 		int fd)
528 {
529 	int ret;
530 
531 	if (dry_run) {
532 		fprintf(stderr, "NOT setting PARTITION_SETTING_COMPLETED\n");
533 		fprintf(stderr, "These changes will not take effect neither "
534 			"now nor after a power cycle\n");
535 		return 1;
536 	}
537 
538 	fprintf(stderr, "setting OTP PARTITION_SETTING_COMPLETED!\n");
539 	ret = write_extcsd_value(fd, EXT_CSD_PARTITION_SETTING_COMPLETED, 0x1);
540 	if (ret) {
541 		fprintf(stderr, "Could not write 0x1 to "
542 			"EXT_CSD[%d] in %s\n",
543 			EXT_CSD_PARTITION_SETTING_COMPLETED, device);
544 		return 1;
545 	}
546 
547 	__u32 response;
548 	ret = send_status(fd, &response);
549 	if (ret) {
550 		fprintf(stderr, "Could not get response to SEND_STATUS "
551 			"from %s\n", device);
552 		return 1;
553 	}
554 
555 	if (response & R1_SWITCH_ERROR) {
556 		fprintf(stderr, "Setting OTP PARTITION_SETTING_COMPLETED "
557 			"failed on %s\n", device);
558 		return 1;
559 	}
560 
561 	fprintf(stderr, "Setting OTP PARTITION_SETTING_COMPLETED on "
562 		"%s SUCCESS\n", device);
563 	fprintf(stderr, "Device power cycle needed for settings to "
564 		"take effect.\n"
565 		"Confirm that PARTITION_SETTING_COMPLETED bit is set "
566 		"using 'extcsd read' after power cycle\n");
567 
568 	return 0;
569 }
570 
check_enhanced_area_total_limit(const char * const device,int fd)571 int check_enhanced_area_total_limit(const char * const device, int fd)
572 {
573 	__u8 ext_csd[512];
574 	__u32 regl;
575 	unsigned long max_enh_area_sz, user_area_sz, enh_area_sz = 0;
576 	unsigned long gp4_part_sz, gp3_part_sz, gp2_part_sz, gp1_part_sz;
577 	unsigned long total_sz, total_gp_user_sz;
578 	unsigned int wp_sz, erase_sz;
579 	int ret;
580 
581 	ret = read_extcsd(fd, ext_csd);
582 	if (ret) {
583 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
584 		exit(1);
585 	}
586 	wp_sz = get_hc_wp_grp_size(ext_csd);
587 	erase_sz = get_hc_erase_grp_size(ext_csd);
588 
589 	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_4_2] << 16) |
590 		(ext_csd[EXT_CSD_GP_SIZE_MULT_4_1] << 8) |
591 		ext_csd[EXT_CSD_GP_SIZE_MULT_4_0];
592 	gp4_part_sz = 512l * regl * erase_sz * wp_sz;
593 	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_4) {
594 		enh_area_sz += gp4_part_sz;
595 		printf("Enhanced GP4 Partition Size [GP_SIZE_MULT_4]: 0x%06x\n", regl);
596 		printf(" i.e. %lu KiB\n", gp4_part_sz);
597 	}
598 
599 	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_3_2] << 16) |
600 		(ext_csd[EXT_CSD_GP_SIZE_MULT_3_1] << 8) |
601 		ext_csd[EXT_CSD_GP_SIZE_MULT_3_0];
602 	gp3_part_sz = 512l * regl * erase_sz * wp_sz;
603 	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_3) {
604 		enh_area_sz += gp3_part_sz;
605 		printf("Enhanced GP3 Partition Size [GP_SIZE_MULT_3]: 0x%06x\n", regl);
606 		printf(" i.e. %lu KiB\n", gp3_part_sz);
607 	}
608 
609 	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_2_2] << 16) |
610 		(ext_csd[EXT_CSD_GP_SIZE_MULT_2_1] << 8) |
611 		ext_csd[EXT_CSD_GP_SIZE_MULT_2_0];
612 	gp2_part_sz = 512l * regl * erase_sz * wp_sz;
613 	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_2) {
614 		enh_area_sz += gp2_part_sz;
615 		printf("Enhanced GP2 Partition Size [GP_SIZE_MULT_2]: 0x%06x\n", regl);
616 		printf(" i.e. %lu KiB\n", gp2_part_sz);
617 	}
618 
619 	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_1_2] << 16) |
620 		(ext_csd[EXT_CSD_GP_SIZE_MULT_1_1] << 8) |
621 		ext_csd[EXT_CSD_GP_SIZE_MULT_1_0];
622 	gp1_part_sz = 512l * regl * erase_sz * wp_sz;
623 	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_1) {
624 		enh_area_sz += gp1_part_sz;
625 		printf("Enhanced GP1 Partition Size [GP_SIZE_MULT_1]: 0x%06x\n", regl);
626 		printf(" i.e. %lu KiB\n", gp1_part_sz);
627 	}
628 
629 	regl = (ext_csd[EXT_CSD_ENH_SIZE_MULT_2] << 16) |
630 		(ext_csd[EXT_CSD_ENH_SIZE_MULT_1] << 8) |
631 		ext_csd[EXT_CSD_ENH_SIZE_MULT_0];
632 	user_area_sz = 512l * regl * erase_sz * wp_sz;
633 	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_USR) {
634 		enh_area_sz += user_area_sz;
635 		printf("Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x%06x\n", regl);
636 		printf(" i.e. %lu KiB\n", user_area_sz);
637 	}
638 
639 	regl = (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_2] << 16) |
640 		(ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_1] << 8) |
641 		ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_0];
642 	max_enh_area_sz = 512l * regl * erase_sz * wp_sz;
643 	printf("Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x%06x\n", regl);
644 	printf(" i.e. %lu KiB\n", max_enh_area_sz);
645 	if (enh_area_sz > max_enh_area_sz) {
646 		fprintf(stderr,
647 			"Programmed total enhanced size %lu KiB cannot exceed max enhanced area %lu KiB %s\n",
648 			enh_area_sz, max_enh_area_sz, device);
649 		return 1;
650 	}
651 	total_sz = get_sector_count(ext_csd) / 2;
652 	total_gp_user_sz = gp4_part_sz + gp3_part_sz + gp2_part_sz +
653 				gp1_part_sz + user_area_sz;
654 	if (total_gp_user_sz > total_sz) {
655 		fprintf(stderr,
656 			"requested total partition size %lu KiB cannot exceed card capacity %lu KiB %s\n",
657 			total_gp_user_sz, total_sz, device);
658 		return 1;
659 	}
660 
661 	return 0;
662 }
663 
do_create_gp_partition(int nargs,char ** argv)664 int do_create_gp_partition(int nargs, char **argv)
665 {
666 	__u8 value;
667 	__u8 ext_csd[512];
668 	__u8 address;
669 	int fd, ret;
670 	char *device;
671 	int dry_run = 1;
672 	int partition, enh_attr, ext_attr;
673 	unsigned int length_kib, gp_size_mult;
674 	unsigned long align;
675 
676 	CHECK(nargs != 7, "Usage: mmc gp create <-y|-n> <length KiB> "
677 		"<partition> <enh_attr> <ext_attr> </path/to/mmcblkX>\n", exit(1));
678 
679 	if (!strcmp("-y", argv[1]))
680 		dry_run = 0;
681 
682 	length_kib = strtol(argv[2], NULL, 10);
683 	partition = strtol(argv[3], NULL, 10);
684 	enh_attr = strtol(argv[4], NULL, 10);
685 	ext_attr = strtol(argv[5], NULL, 10);
686 	device = argv[6];
687 
688 	if (partition < 0 || partition > 4) {
689 		printf("Invalid gp parition number valid range [1-4]\n");
690 		exit(1);
691 	}
692 
693 	if (enh_attr && ext_attr) {
694 		printf("Not allowed to set both enhanced attribute and extended attribute\n");
695 		exit(1);
696 	}
697 
698 	fd = open(device, O_RDWR);
699 	if (fd < 0) {
700 		perror("open");
701 		exit(1);
702 	}
703 
704 	ret = read_extcsd(fd, ext_csd);
705 	if (ret) {
706 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
707 		exit(1);
708 	}
709 
710 	/* assert not PARTITION_SETTING_COMPLETED */
711 	if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED]) {
712 		printf(" Device is already partitioned\n");
713 		exit(1);
714 	}
715 
716 	align = 512l * get_hc_wp_grp_size(ext_csd) * get_hc_erase_grp_size(ext_csd);
717 	gp_size_mult = (length_kib + align/2l) / align;
718 
719 	/* set EXT_CSD_ERASE_GROUP_DEF bit 0 */
720 	ret = write_extcsd_value(fd, EXT_CSD_ERASE_GROUP_DEF, 0x1);
721 	if (ret) {
722 		fprintf(stderr, "Could not write 0x1 to EXT_CSD[%d] in %s\n",
723 			EXT_CSD_ERASE_GROUP_DEF, device);
724 		exit(1);
725 	}
726 
727 	value = (gp_size_mult >> 16) & 0xff;
728 	address = EXT_CSD_GP_SIZE_MULT_1_2 + (partition - 1) * 3;
729 	ret = write_extcsd_value(fd, address, value);
730 	if (ret) {
731 		fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
732 			value, address, device);
733 		exit(1);
734 	}
735 	value = (gp_size_mult >> 8) & 0xff;
736 	address = EXT_CSD_GP_SIZE_MULT_1_1 + (partition - 1) * 3;
737 	ret = write_extcsd_value(fd, address, value);
738 	if (ret) {
739 		fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
740 			value, address, device);
741 		exit(1);
742 	}
743 	value = gp_size_mult & 0xff;
744 	address = EXT_CSD_GP_SIZE_MULT_1_0 + (partition - 1) * 3;
745 	ret = write_extcsd_value(fd, address, value);
746 	if (ret) {
747 		fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
748 			value, address, device);
749 		exit(1);
750 	}
751 
752 	value = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
753 	if (enh_attr)
754 		value |= (1 << partition);
755 	else
756 		value &= ~(1 << partition);
757 
758 	ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value);
759 	if (ret) {
760 		fprintf(stderr, "Could not write EXT_CSD_ENH_%x to EXT_CSD[%d] in %s\n",
761 			partition, EXT_CSD_PARTITIONS_ATTRIBUTE, device);
762 		exit(1);
763 	}
764 
765 	address = EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_0 + (partition - 1) / 2;
766 	value = ext_csd[address];
767 	if (ext_attr)
768 		value |= (ext_attr << (4 * ((partition - 1) % 2)));
769 	else
770 		value &= (0xF << (4 * ((partition % 2))));
771 
772 	ret = write_extcsd_value(fd, address, value);
773 	if (ret) {
774 		fprintf(stderr, "Could not write 0x%x to EXT_CSD[%d] in %s\n",
775 			value, address, device);
776 		exit(1);
777 	}
778 
779 	ret = check_enhanced_area_total_limit(device, fd);
780 	if (ret)
781 		exit(1);
782 
783 	if (!set_partitioning_setting_completed(dry_run, device, fd))
784 		exit(1);
785 
786 	return 0;
787 }
788 
do_enh_area_set(int nargs,char ** argv)789 int do_enh_area_set(int nargs, char **argv)
790 {
791 	__u8 value;
792 	__u8 ext_csd[512];
793 	int fd, ret;
794 	char *device;
795 	int dry_run = 1;
796 	unsigned int start_kib, length_kib, enh_start_addr, enh_size_mult;
797 	unsigned long align;
798 
799 	CHECK(nargs != 5, "Usage: mmc enh_area set <-y|-n> <start KiB> <length KiB> "
800 			  "</path/to/mmcblkX>\n", exit(1));
801 
802 	if (!strcmp("-y", argv[1]))
803 		dry_run = 0;
804 
805 	start_kib = strtol(argv[2], NULL, 10);
806 	length_kib = strtol(argv[3], NULL, 10);
807 	device = argv[4];
808 
809 	fd = open(device, O_RDWR);
810 	if (fd < 0) {
811 		perror("open");
812 		exit(1);
813 	}
814 
815 	ret = read_extcsd(fd, ext_csd);
816 	if (ret) {
817 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
818 		exit(1);
819 	}
820 
821 	/* assert ENH_ATTRIBUTE_EN */
822 	if (!(ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & EXT_CSD_ENH_ATTRIBUTE_EN))
823 	{
824 		printf(" Device cannot have enhanced tech.\n");
825 		exit(1);
826 	}
827 
828 	/* assert not PARTITION_SETTING_COMPLETED */
829 	if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED])
830 	{
831 		printf(" Device is already partitioned\n");
832 		exit(1);
833 	}
834 
835 	align = 512l * get_hc_wp_grp_size(ext_csd) * get_hc_erase_grp_size(ext_csd);
836 
837 	enh_size_mult = (length_kib + align/2l) / align;
838 
839 	enh_start_addr = start_kib * 1024 / (is_blockaddresed(ext_csd) ? 512 : 1);
840 	enh_start_addr /= align;
841 	enh_start_addr *= align;
842 
843 	/* set EXT_CSD_ERASE_GROUP_DEF bit 0 */
844 	ret = write_extcsd_value(fd, EXT_CSD_ERASE_GROUP_DEF, 0x1);
845 	if (ret) {
846 		fprintf(stderr, "Could not write 0x1 to "
847 			"EXT_CSD[%d] in %s\n",
848 			EXT_CSD_ERASE_GROUP_DEF, device);
849 		exit(1);
850 	}
851 
852 	/* write to ENH_START_ADDR and ENH_SIZE_MULT and PARTITIONS_ATTRIBUTE's ENH_USR bit */
853 	value = (enh_start_addr >> 24) & 0xff;
854 	ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_3, value);
855 	if (ret) {
856 		fprintf(stderr, "Could not write 0x%02x to "
857 			"EXT_CSD[%d] in %s\n", value,
858 			EXT_CSD_ENH_START_ADDR_3, device);
859 		exit(1);
860 	}
861 	value = (enh_start_addr >> 16) & 0xff;
862 	ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_2, value);
863 	if (ret) {
864 		fprintf(stderr, "Could not write 0x%02x to "
865 			"EXT_CSD[%d] in %s\n", value,
866 			EXT_CSD_ENH_START_ADDR_2, device);
867 		exit(1);
868 	}
869 	value = (enh_start_addr >> 8) & 0xff;
870 	ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_1, value);
871 	if (ret) {
872 		fprintf(stderr, "Could not write 0x%02x to "
873 			"EXT_CSD[%d] in %s\n", value,
874 			EXT_CSD_ENH_START_ADDR_1, device);
875 		exit(1);
876 	}
877 	value = enh_start_addr & 0xff;
878 	ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_0, value);
879 	if (ret) {
880 		fprintf(stderr, "Could not write 0x%02x to "
881 			"EXT_CSD[%d] in %s\n", value,
882 			EXT_CSD_ENH_START_ADDR_0, device);
883 		exit(1);
884 	}
885 
886 	value = (enh_size_mult >> 16) & 0xff;
887 	ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_2, value);
888 	if (ret) {
889 		fprintf(stderr, "Could not write 0x%02x to "
890 			"EXT_CSD[%d] in %s\n", value,
891 			EXT_CSD_ENH_SIZE_MULT_2, device);
892 		exit(1);
893 	}
894 	value = (enh_size_mult >> 8) & 0xff;
895 	ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_1, value);
896 	if (ret) {
897 		fprintf(stderr, "Could not write 0x%02x to "
898 			"EXT_CSD[%d] in %s\n", value,
899 			EXT_CSD_ENH_SIZE_MULT_1, device);
900 		exit(1);
901 	}
902 	value = enh_size_mult & 0xff;
903 	ret = write_extcsd_value(fd, EXT_CSD_ENH_SIZE_MULT_0, value);
904 	if (ret) {
905 		fprintf(stderr, "Could not write 0x%02x to "
906 			"EXT_CSD[%d] in %s\n", value,
907 			EXT_CSD_ENH_SIZE_MULT_0, device);
908 		exit(1);
909 	}
910 	value = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] | EXT_CSD_ENH_USR;
911 	ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value);
912 	if (ret) {
913 		fprintf(stderr, "Could not write EXT_CSD_ENH_USR to "
914 			"EXT_CSD[%d] in %s\n",
915 			EXT_CSD_PARTITIONS_ATTRIBUTE, device);
916 		exit(1);
917 	}
918 
919 	ret = check_enhanced_area_total_limit(device, fd);
920 	if (ret)
921 		exit(1);
922 
923 	printf("Done setting ENH_USR area on %s\n", device);
924 
925 	if (!set_partitioning_setting_completed(dry_run, device, fd))
926 		exit(1);
927 
928 	return 0;
929 }
930 
do_write_reliability_set(int nargs,char ** argv)931 int do_write_reliability_set(int nargs, char **argv)
932 {
933 	__u8 value;
934 	__u8 ext_csd[512];
935 	int fd, ret;
936 
937 	int dry_run = 1;
938 	int partition;
939 	char *device;
940 
941 	CHECK(nargs != 4, "Usage: mmc write_reliability set <-y|-n> "
942 			"<partition> </path/to/mmcblkX>\n", exit(1));
943 
944 	if (!strcmp("-y", argv[1]))
945 		dry_run = 0;
946 
947 	partition = strtol(argv[2], NULL, 10);
948 	device = argv[3];
949 
950 	fd = open(device, O_RDWR);
951 	if (fd < 0) {
952 		perror("open");
953 		exit(1);
954 	}
955 
956 	ret = read_extcsd(fd, ext_csd);
957 	if (ret) {
958 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
959 		exit(1);
960 	}
961 
962 	/* assert not PARTITION_SETTING_COMPLETED */
963 	if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED])
964 	{
965 		printf(" Device is already partitioned\n");
966 		exit(1);
967 	}
968 
969 	/* assert HS_CTRL_REL */
970 	if (!(ext_csd[EXT_CSD_WR_REL_PARAM] & HS_CTRL_REL)) {
971 		printf("Cannot set write reliability parameters, WR_REL_SET is "
972 				"read-only\n");
973 		exit(1);
974 	}
975 
976 	value = ext_csd[EXT_CSD_WR_REL_SET] | (1<<partition);
977 	ret = write_extcsd_value(fd, EXT_CSD_WR_REL_SET, value);
978 	if (ret) {
979 		fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
980 				value, EXT_CSD_WR_REL_SET, device);
981 		exit(1);
982 	}
983 
984 	printf("Done setting EXT_CSD_WR_REL_SET to 0x%02x on %s\n",
985 		value, device);
986 
987 	if (!set_partitioning_setting_completed(dry_run, device, fd))
988 		exit(1);
989 
990 	return 0;
991 }
992 
do_read_extcsd(int nargs,char ** argv)993 int do_read_extcsd(int nargs, char **argv)
994 {
995 	__u8 ext_csd[512], ext_csd_rev, reg;
996 	__u32 regl;
997 	int fd, ret;
998 	char *device;
999 	const char *str;
1000 
1001 	CHECK(nargs != 2, "Usage: mmc extcsd read </path/to/mmcblkX>\n",
1002 			  exit(1));
1003 
1004 	device = argv[1];
1005 
1006 	fd = open(device, O_RDWR);
1007 	if (fd < 0) {
1008 		perror("open");
1009 		exit(1);
1010 	}
1011 
1012 	ret = read_extcsd(fd, ext_csd);
1013 	if (ret) {
1014 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
1015 		exit(1);
1016 	}
1017 
1018 	ext_csd_rev = ext_csd[EXT_CSD_REV];
1019 
1020 	switch (ext_csd_rev) {
1021 	case 7:
1022 		str = "5.0";
1023 		break;
1024 	case 6:
1025 		str = "4.5";
1026 		break;
1027 	case 5:
1028 		str = "4.41";
1029 		break;
1030 	case 3:
1031 		str = "4.3";
1032 		break;
1033 	case 2:
1034 		str = "4.2";
1035 		break;
1036 	case 1:
1037 		str = "4.1";
1038 		break;
1039 	case 0:
1040 		str = "4.0";
1041 		break;
1042 	default:
1043 		goto out_free;
1044 	}
1045 	printf("=============================================\n");
1046 	printf("  Extended CSD rev 1.%d (MMC %s)\n", ext_csd_rev, str);
1047 	printf("=============================================\n\n");
1048 
1049 	if (ext_csd_rev < 3)
1050 		goto out_free; /* No ext_csd */
1051 
1052 	/* Parse the Extended CSD registers.
1053 	 * Reserved bit should be read as "0" in case of spec older
1054 	 * than A441.
1055 	 */
1056 	reg = ext_csd[EXT_CSD_S_CMD_SET];
1057 	printf("Card Supported Command sets [S_CMD_SET: 0x%02x]\n", reg);
1058 	if (!reg)
1059 		printf(" - Standard MMC command sets\n");
1060 
1061 	reg = ext_csd[EXT_CSD_HPI_FEATURE];
1062 	printf("HPI Features [HPI_FEATURE: 0x%02x]: ", reg);
1063 	if (reg & EXT_CSD_HPI_SUPP) {
1064 		if (reg & EXT_CSD_HPI_IMPL)
1065 			printf("implementation based on CMD12\n");
1066 		else
1067 			printf("implementation based on CMD13\n");
1068 	}
1069 
1070 	printf("Background operations support [BKOPS_SUPPORT: 0x%02x]\n",
1071 		ext_csd[502]);
1072 
1073 	if (ext_csd_rev >= 6) {
1074 		printf("Max Packet Read Cmd [MAX_PACKED_READS: 0x%02x]\n",
1075 			ext_csd[501]);
1076 		printf("Max Packet Write Cmd [MAX_PACKED_WRITES: 0x%02x]\n",
1077 			ext_csd[500]);
1078 		printf("Data TAG support [DATA_TAG_SUPPORT: 0x%02x]\n",
1079 			ext_csd[499]);
1080 
1081 		printf("Data TAG Unit Size [TAG_UNIT_SIZE: 0x%02x]\n",
1082 			ext_csd[498]);
1083 		printf("Tag Resources Size [TAG_RES_SIZE: 0x%02x]\n",
1084 			ext_csd[497]);
1085 		printf("Context Management Capabilities"
1086 			" [CONTEXT_CAPABILITIES: 0x%02x]\n", ext_csd[496]);
1087 		printf("Large Unit Size [LARGE_UNIT_SIZE_M1: 0x%02x]\n",
1088 			ext_csd[495]);
1089 		printf("Extended partition attribute support"
1090 			" [EXT_SUPPORT: 0x%02x]\n", ext_csd[494]);
1091 		printf("Generic CMD6 Timer [GENERIC_CMD6_TIME: 0x%02x]\n",
1092 			ext_csd[248]);
1093 		printf("Power off notification [POWER_OFF_LONG_TIME: 0x%02x]\n",
1094 			ext_csd[247]);
1095 		printf("Cache Size [CACHE_SIZE] is %d KiB\n",
1096 			ext_csd[249] << 0 | (ext_csd[250] << 8) |
1097 			(ext_csd[251] << 16) | (ext_csd[252] << 24));
1098 	}
1099 
1100 	/* A441: Reserved [501:247]
1101 	    A43: reserved [246:229] */
1102 	if (ext_csd_rev >= 5) {
1103 		printf("Background operations status"
1104 			" [BKOPS_STATUS: 0x%02x]\n", ext_csd[246]);
1105 
1106 		/* CORRECTLY_PRG_SECTORS_NUM [245:242] TODO */
1107 
1108 		printf("1st Initialisation Time after programmed sector"
1109 			" [INI_TIMEOUT_AP: 0x%02x]\n", ext_csd[241]);
1110 
1111 		/* A441: reserved [240] */
1112 		printf("Power class for 52MHz, DDR at 3.6V"
1113 			" [PWR_CL_DDR_52_360: 0x%02x]\n", ext_csd[239]);
1114 		printf("Power class for 52MHz, DDR at 1.95V"
1115 			" [PWR_CL_DDR_52_195: 0x%02x]\n", ext_csd[238]);
1116 
1117 		/* A441: reserved [237-236] */
1118 
1119 		if (ext_csd_rev >= 6) {
1120 			printf("Power class for 200MHz at 3.6V"
1121 				" [PWR_CL_200_360: 0x%02x]\n", ext_csd[237]);
1122 			printf("Power class for 200MHz, at 1.95V"
1123 				" [PWR_CL_200_195: 0x%02x]\n", ext_csd[236]);
1124 		}
1125 		printf("Minimum Performance for 8bit at 52MHz in DDR mode:\n");
1126 		printf(" [MIN_PERF_DDR_W_8_52: 0x%02x]\n", ext_csd[235]);
1127 		printf(" [MIN_PERF_DDR_R_8_52: 0x%02x]\n", ext_csd[234]);
1128 		/* A441: reserved [233] */
1129 		printf("TRIM Multiplier [TRIM_MULT: 0x%02x]\n", ext_csd[232]);
1130 		printf("Secure Feature support [SEC_FEATURE_SUPPORT: 0x%02x]\n",
1131 			ext_csd[231]);
1132 	}
1133 	if (ext_csd_rev == 5) { /* Obsolete in 4.5 */
1134 		printf("Secure Erase Multiplier [SEC_ERASE_MULT: 0x%02x]\n",
1135 			ext_csd[230]);
1136 		printf("Secure TRIM Multiplier [SEC_TRIM_MULT: 0x%02x]\n",
1137 			ext_csd[229]);
1138 	}
1139 	reg = ext_csd[EXT_CSD_BOOT_INFO];
1140 	printf("Boot Information [BOOT_INFO: 0x%02x]\n", reg);
1141 	if (reg & EXT_CSD_BOOT_INFO_ALT)
1142 		printf(" Device supports alternative boot method\n");
1143 	if (reg & EXT_CSD_BOOT_INFO_DDR_DDR)
1144 		printf(" Device supports dual data rate during boot\n");
1145 	if (reg & EXT_CSD_BOOT_INFO_HS_MODE)
1146 		printf(" Device supports high speed timing during boot\n");
1147 
1148 	/* A441/A43: reserved [227] */
1149 	printf("Boot partition size [BOOT_SIZE_MULTI: 0x%02x]\n", ext_csd[226]);
1150 	printf("Access size [ACC_SIZE: 0x%02x]\n", ext_csd[225]);
1151 
1152 	reg = get_hc_erase_grp_size(ext_csd);
1153 	printf("High-capacity erase unit size [HC_ERASE_GRP_SIZE: 0x%02x]\n",
1154 		reg);
1155 	printf(" i.e. %u KiB\n", 512 * reg);
1156 
1157 	printf("High-capacity erase timeout [ERASE_TIMEOUT_MULT: 0x%02x]\n",
1158 		ext_csd[223]);
1159 	printf("Reliable write sector count [REL_WR_SEC_C: 0x%02x]\n",
1160 		ext_csd[222]);
1161 
1162 	reg = get_hc_wp_grp_size(ext_csd);
1163 	printf("High-capacity W protect group size [HC_WP_GRP_SIZE: 0x%02x]\n",
1164 		reg);
1165 	printf(" i.e. %lu KiB\n", 512l * get_hc_erase_grp_size(ext_csd) * reg);
1166 
1167 	printf("Sleep current (VCC) [S_C_VCC: 0x%02x]\n", ext_csd[220]);
1168 	printf("Sleep current (VCCQ) [S_C_VCCQ: 0x%02x]\n", ext_csd[219]);
1169 	/* A441/A43: reserved [218] */
1170 	printf("Sleep/awake timeout [S_A_TIMEOUT: 0x%02x]\n", ext_csd[217]);
1171 	/* A441/A43: reserved [216] */
1172 
1173 	unsigned int sectors =	get_sector_count(ext_csd);
1174 	printf("Sector Count [SEC_COUNT: 0x%08x]\n", sectors);
1175 	if (is_blockaddresed(ext_csd))
1176 		printf(" Device is block-addressed\n");
1177 	else
1178 		printf(" Device is NOT block-addressed\n");
1179 
1180 	/* A441/A43: reserved [211] */
1181 	printf("Minimum Write Performance for 8bit:\n");
1182 	printf(" [MIN_PERF_W_8_52: 0x%02x]\n", ext_csd[210]);
1183 	printf(" [MIN_PERF_R_8_52: 0x%02x]\n", ext_csd[209]);
1184 	printf(" [MIN_PERF_W_8_26_4_52: 0x%02x]\n", ext_csd[208]);
1185 	printf(" [MIN_PERF_R_8_26_4_52: 0x%02x]\n", ext_csd[207]);
1186 	printf("Minimum Write Performance for 4bit:\n");
1187 	printf(" [MIN_PERF_W_4_26: 0x%02x]\n", ext_csd[206]);
1188 	printf(" [MIN_PERF_R_4_26: 0x%02x]\n", ext_csd[205]);
1189 	/* A441/A43: reserved [204] */
1190 	printf("Power classes registers:\n");
1191 	printf(" [PWR_CL_26_360: 0x%02x]\n", ext_csd[203]);
1192 	printf(" [PWR_CL_52_360: 0x%02x]\n", ext_csd[202]);
1193 	printf(" [PWR_CL_26_195: 0x%02x]\n", ext_csd[201]);
1194 	printf(" [PWR_CL_52_195: 0x%02x]\n", ext_csd[200]);
1195 
1196 	/* A43: reserved [199:198] */
1197 	if (ext_csd_rev >= 5) {
1198 		printf("Partition switching timing "
1199 			"[PARTITION_SWITCH_TIME: 0x%02x]\n", ext_csd[199]);
1200 		printf("Out-of-interrupt busy timing"
1201 			" [OUT_OF_INTERRUPT_TIME: 0x%02x]\n", ext_csd[198]);
1202 	}
1203 
1204 	/* A441/A43: reserved	[197] [195] [193] [190] [188]
1205 	 * [186] [184] [182] [180] [176] */
1206 
1207 	if (ext_csd_rev >= 6)
1208 		printf("I/O Driver Strength [DRIVER_STRENGTH: 0x%02x]\n",
1209 			ext_csd[197]);
1210 
1211 	/* DEVICE_TYPE in A45, CARD_TYPE in A441 */
1212 	reg = ext_csd[196];
1213 	printf("Card Type [CARD_TYPE: 0x%02x]\n", reg);
1214 	if (reg & 0x20) printf(" HS200 Single Data Rate eMMC @200MHz 1.2VI/O\n");
1215 	if (reg & 0x10) printf(" HS200 Single Data Rate eMMC @200MHz 1.8VI/O\n");
1216 	if (reg & 0x08) printf(" HS Dual Data Rate eMMC @52MHz 1.2VI/O\n");
1217 	if (reg & 0x04)	printf(" HS Dual Data Rate eMMC @52MHz 1.8V or 3VI/O\n");
1218 	if (reg & 0x02)	printf(" HS eMMC @52MHz - at rated device voltage(s)\n");
1219 	if (reg & 0x01) printf(" HS eMMC @26MHz - at rated device voltage(s)\n");
1220 
1221 	printf("CSD structure version [CSD_STRUCTURE: 0x%02x]\n", ext_csd[194]);
1222 	/* ext_csd_rev = ext_csd[EXT_CSD_REV] (already done!!!) */
1223 	printf("Command set [CMD_SET: 0x%02x]\n", ext_csd[191]);
1224 	printf("Command set revision [CMD_SET_REV: 0x%02x]\n", ext_csd[189]);
1225 	printf("Power class [POWER_CLASS: 0x%02x]\n", ext_csd[187]);
1226 	printf("High-speed interface timing [HS_TIMING: 0x%02x]\n",
1227 		ext_csd[185]);
1228 	/* bus_width: ext_csd[183] not readable */
1229 	printf("Erased memory content [ERASED_MEM_CONT: 0x%02x]\n",
1230 		ext_csd[181]);
1231 	reg = ext_csd[EXT_CSD_BOOT_CFG];
1232 	printf("Boot configuration bytes [PARTITION_CONFIG: 0x%02x]\n", reg);
1233 	switch ((reg & EXT_CSD_BOOT_CFG_EN)>>3) {
1234 	case 0x0:
1235 		printf(" Not boot enable\n");
1236 		break;
1237 	case 0x1:
1238 		printf(" Boot Partition 1 enabled\n");
1239 		break;
1240 	case 0x2:
1241 		printf(" Boot Partition 2 enabled\n");
1242 		break;
1243 	case 0x7:
1244 		printf(" User Area Enabled for boot\n");
1245 		break;
1246 	}
1247 	switch (reg & EXT_CSD_BOOT_CFG_ACC) {
1248 	case 0x0:
1249 		printf(" No access to boot partition\n");
1250 		break;
1251 	case 0x1:
1252 		printf(" R/W Boot Partition 1\n");
1253 		break;
1254 	case 0x2:
1255 		printf(" R/W Boot Partition 2\n");
1256 		break;
1257 	case 0x3:
1258 		printf(" R/W Replay Protected Memory Block (RPMB)\n");
1259 		break;
1260 	default:
1261 		printf(" Access to General Purpose partition %d\n",
1262 			(reg & EXT_CSD_BOOT_CFG_ACC) - 3);
1263 		break;
1264 	}
1265 
1266 	printf("Boot config protection [BOOT_CONFIG_PROT: 0x%02x]\n",
1267 		ext_csd[178]);
1268 	printf("Boot bus Conditions [BOOT_BUS_CONDITIONS: 0x%02x]\n",
1269 		ext_csd[177]);
1270 	printf("High-density erase group definition"
1271 		" [ERASE_GROUP_DEF: 0x%02x]\n", ext_csd[EXT_CSD_ERASE_GROUP_DEF]);
1272 
1273 	print_writeprotect_status(ext_csd);
1274 
1275 	if (ext_csd_rev >= 5) {
1276 		/* A441]: reserved [172] */
1277 		printf("User area write protection register"
1278 			" [USER_WP]: 0x%02x\n", ext_csd[171]);
1279 		/* A441]: reserved [170] */
1280 		printf("FW configuration [FW_CONFIG]: 0x%02x\n", ext_csd[169]);
1281 		printf("RPMB Size [RPMB_SIZE_MULT]: 0x%02x\n", ext_csd[168]);
1282 
1283 		reg = ext_csd[EXT_CSD_WR_REL_SET];
1284 		const char * const fast = "existing data is at risk if a power "
1285 				"failure occurs during a write operation";
1286 		const char * const reliable = "the device protects existing "
1287 				"data if a power failure occurs during a write "
1288 				"operation";
1289 		printf("Write reliability setting register"
1290 			" [WR_REL_SET]: 0x%02x\n", reg);
1291 
1292 		printf(" user area: %s\n", reg & (1<<0) ? reliable : fast);
1293 		int i;
1294 		for (i = 1; i <= 4; i++) {
1295 			printf(" partition %d: %s\n", i,
1296 				reg & (1<<i) ? reliable : fast);
1297 		}
1298 
1299 		reg = ext_csd[EXT_CSD_WR_REL_PARAM];
1300 		printf("Write reliability parameter register"
1301 			" [WR_REL_PARAM]: 0x%02x\n", reg);
1302 		if (reg & 0x01)
1303 			printf(" Device supports writing EXT_CSD_WR_REL_SET\n");
1304 		if (reg & 0x04)
1305 			printf(" Device supports the enhanced def. of reliable "
1306 				"write\n");
1307 
1308 		/* sanitize_start ext_csd[165]]: not readable
1309 		 * bkops_start ext_csd[164]]: only writable */
1310 		printf("Enable background operations handshake"
1311 			" [BKOPS_EN]: 0x%02x\n", ext_csd[163]);
1312 		printf("H/W reset function"
1313 			" [RST_N_FUNCTION]: 0x%02x\n", ext_csd[162]);
1314 		printf("HPI management [HPI_MGMT]: 0x%02x\n", ext_csd[161]);
1315 		reg = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
1316 		printf("Partitioning Support [PARTITIONING_SUPPORT]: 0x%02x\n",
1317 			reg);
1318 		if (reg & EXT_CSD_PARTITIONING_EN)
1319 			printf(" Device support partitioning feature\n");
1320 		else
1321 			printf(" Device NOT support partitioning feature\n");
1322 		if (reg & EXT_CSD_ENH_ATTRIBUTE_EN)
1323 			printf(" Device can have enhanced tech.\n");
1324 		else
1325 			printf(" Device cannot have enhanced tech.\n");
1326 
1327 		regl = (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_2] << 16) |
1328 			(ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_1] << 8) |
1329 			ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_0];
1330 
1331 		printf("Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x%06x\n",
1332 			   regl);
1333 		unsigned int wp_sz = get_hc_wp_grp_size(ext_csd);
1334 		unsigned int erase_sz = get_hc_erase_grp_size(ext_csd);
1335 		printf(" i.e. %lu KiB\n", 512l * regl * wp_sz * erase_sz);
1336 
1337 		printf("Partitions attribute [PARTITIONS_ATTRIBUTE]: 0x%02x\n",
1338 			ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE]);
1339 		reg = ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED];
1340 		printf("Partitioning Setting"
1341 			" [PARTITION_SETTING_COMPLETED]: 0x%02x\n",
1342 			reg);
1343 		if (reg)
1344 			printf(" Device partition setting complete\n");
1345 		else
1346 			printf(" Device partition setting NOT complete\n");
1347 
1348 		printf("General Purpose Partition Size\n"
1349 			" [GP_SIZE_MULT_4]: 0x%06x\n", (ext_csd[154] << 16) |
1350 			(ext_csd[153] << 8) | ext_csd[152]);
1351 		printf(" [GP_SIZE_MULT_3]: 0x%06x\n", (ext_csd[151] << 16) |
1352 			   (ext_csd[150] << 8) | ext_csd[149]);
1353 		printf(" [GP_SIZE_MULT_2]: 0x%06x\n", (ext_csd[148] << 16) |
1354 			   (ext_csd[147] << 8) | ext_csd[146]);
1355 		printf(" [GP_SIZE_MULT_1]: 0x%06x\n", (ext_csd[145] << 16) |
1356 			   (ext_csd[144] << 8) | ext_csd[143]);
1357 
1358 		regl =	(ext_csd[EXT_CSD_ENH_SIZE_MULT_2] << 16) |
1359 			(ext_csd[EXT_CSD_ENH_SIZE_MULT_1] << 8) |
1360 			ext_csd[EXT_CSD_ENH_SIZE_MULT_0];
1361 		printf("Enhanced User Data Area Size"
1362 			" [ENH_SIZE_MULT]: 0x%06x\n", regl);
1363 		printf(" i.e. %lu KiB\n", 512l * regl *
1364 		       get_hc_erase_grp_size(ext_csd) *
1365 		       get_hc_wp_grp_size(ext_csd));
1366 
1367 		regl =	(ext_csd[EXT_CSD_ENH_START_ADDR_3] << 24) |
1368 			(ext_csd[EXT_CSD_ENH_START_ADDR_2] << 16) |
1369 			(ext_csd[EXT_CSD_ENH_START_ADDR_1] << 8) |
1370 			ext_csd[EXT_CSD_ENH_START_ADDR_0];
1371 		printf("Enhanced User Data Start Address"
1372 			" [ENH_START_ADDR]: 0x%06x\n", regl);
1373 		printf(" i.e. %lu bytes offset\n", (is_blockaddresed(ext_csd) ?
1374 				1l : 512l) * regl);
1375 
1376 		/* A441]: reserved [135] */
1377 		printf("Bad Block Management mode"
1378 			" [SEC_BAD_BLK_MGMNT]: 0x%02x\n", ext_csd[134]);
1379 		/* A441: reserved [133:0] */
1380 	}
1381 	/* B45 */
1382 	if (ext_csd_rev >= 6) {
1383 		int j;
1384 		/* tcase_support ext_csd[132] not readable */
1385 		printf("Periodic Wake-up [PERIODIC_WAKEUP]: 0x%02x\n",
1386 			ext_csd[131]);
1387 		printf("Program CID/CSD in DDR mode support"
1388 			" [PROGRAM_CID_CSD_DDR_SUPPORT]: 0x%02x\n",
1389 			   ext_csd[130]);
1390 
1391 		for (j = 127; j >= 64; j--)
1392 			printf("Vendor Specific Fields"
1393 				" [VENDOR_SPECIFIC_FIELD[%d]]: 0x%02x\n",
1394 				j, ext_csd[j]);
1395 
1396 		printf("Native sector size [NATIVE_SECTOR_SIZE]: 0x%02x\n",
1397 			ext_csd[63]);
1398 		printf("Sector size emulation [USE_NATIVE_SECTOR]: 0x%02x\n",
1399 			ext_csd[62]);
1400 		printf("Sector size [DATA_SECTOR_SIZE]: 0x%02x\n", ext_csd[61]);
1401 		printf("1st initialization after disabling sector"
1402 			" size emulation [INI_TIMEOUT_EMU]: 0x%02x\n",
1403 			ext_csd[60]);
1404 		printf("Class 6 commands control [CLASS_6_CTRL]: 0x%02x\n",
1405 			ext_csd[59]);
1406 		printf("Number of addressed group to be Released"
1407 			"[DYNCAP_NEEDED]: 0x%02x\n", ext_csd[58]);
1408 		printf("Exception events control"
1409 			" [EXCEPTION_EVENTS_CTRL]: 0x%04x\n",
1410 			(ext_csd[57] << 8) | ext_csd[56]);
1411 		printf("Exception events status"
1412 			"[EXCEPTION_EVENTS_STATUS]: 0x%04x\n",
1413 			(ext_csd[55] << 8) | ext_csd[54]);
1414 		printf("Extended Partitions Attribute"
1415 			" [EXT_PARTITIONS_ATTRIBUTE]: 0x%04x\n",
1416 			(ext_csd[53] << 8) | ext_csd[52]);
1417 
1418 		for (j = 51; j >= 37; j--)
1419 			printf("Context configuration"
1420 				" [CONTEXT_CONF[%d]]: 0x%02x\n", j, ext_csd[j]);
1421 
1422 		printf("Packed command status"
1423 			" [PACKED_COMMAND_STATUS]: 0x%02x\n", ext_csd[36]);
1424 		printf("Packed command failure index"
1425 			" [PACKED_FAILURE_INDEX]: 0x%02x\n", ext_csd[35]);
1426 		printf("Power Off Notification"
1427 			" [POWER_OFF_NOTIFICATION]: 0x%02x\n", ext_csd[34]);
1428 		printf("Control to turn the Cache ON/OFF"
1429 			" [CACHE_CTRL]: 0x%02x\n", ext_csd[33]);
1430 		/* flush_cache ext_csd[32] not readable */
1431 		/*Reserved [31:0] */
1432 	}
1433 
1434 out_free:
1435 	return ret;
1436 }
1437 
do_sanitize(int nargs,char ** argv)1438 int do_sanitize(int nargs, char **argv)
1439 {
1440 	int fd, ret;
1441 	char *device;
1442 
1443 	CHECK(nargs != 2, "Usage: mmc sanitize </path/to/mmcblkX>\n",
1444 			exit(1));
1445 
1446 	device = argv[1];
1447 
1448 	fd = open(device, O_RDWR);
1449 	if (fd < 0) {
1450 		perror("open");
1451 		exit(1);
1452 	}
1453 
1454 	ret = write_extcsd_value(fd, EXT_CSD_SANITIZE_START, 1);
1455 	if (ret) {
1456 		fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
1457 			1, EXT_CSD_SANITIZE_START, device);
1458 		exit(1);
1459 	}
1460 
1461 	return ret;
1462 
1463 }
1464 
1465 #define DO_IO(func, fd, buf, nbyte)					\
1466 	({												\
1467 		ssize_t ret = 0, r;							\
1468 		do {										\
1469 			r = func(fd, buf + ret, nbyte - ret);	\
1470 			if (r < 0 && errno != EINTR) {			\
1471 				ret = -1;							\
1472 				break;								\
1473 			}										\
1474 			else if (r > 0)							\
1475 				ret += r;							\
1476 		} while (r != 0 && (size_t)ret != nbyte);	\
1477 													\
1478 		ret;										\
1479 	})
1480 
1481 enum rpmb_op_type {
1482 	MMC_RPMB_WRITE_KEY = 0x01,
1483 	MMC_RPMB_READ_CNT  = 0x02,
1484 	MMC_RPMB_WRITE     = 0x03,
1485 	MMC_RPMB_READ      = 0x04,
1486 
1487 	/* For internal usage only, do not use it directly */
1488 	MMC_RPMB_READ_RESP = 0x05
1489 };
1490 
1491 struct rpmb_frame {
1492 	u_int8_t  stuff[196];
1493 	u_int8_t  key_mac[32];
1494 	u_int8_t  data[256];
1495 	u_int8_t  nonce[16];
1496 	u_int32_t write_counter;
1497 	u_int16_t addr;
1498 	u_int16_t block_count;
1499 	u_int16_t result;
1500 	u_int16_t req_resp;
1501 };
1502 
1503 /* Performs RPMB operation.
1504  *
1505  * @fd: RPMB device on which we should perform ioctl command
1506  * @frame_in: input RPMB frame, should be properly inited
1507  * @frame_out: output (result) RPMB frame. Caller is responsible for checking
1508  *             result and req_resp for output frame.
1509  * @out_cnt: count of outer frames. Used only for multiple blocks reading,
1510  *           in the other cases -EINVAL will be returned.
1511  */
do_rpmb_op(int fd,const struct rpmb_frame * frame_in,struct rpmb_frame * frame_out,unsigned int out_cnt)1512 static int do_rpmb_op(int fd,
1513 					  const struct rpmb_frame *frame_in,
1514 					  struct rpmb_frame *frame_out,
1515 					  unsigned int out_cnt)
1516 {
1517 	int err;
1518 	u_int16_t rpmb_type;
1519 
1520 	struct mmc_ioc_cmd ioc = {
1521 		.arg        = 0x0,
1522 		.blksz      = 512,
1523 		.blocks     = 1,
1524 		.write_flag = 1,
1525 		.opcode     = MMC_WRITE_MULTIPLE_BLOCK,
1526 		.flags      = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
1527 		.data_ptr   = (uintptr_t)frame_in
1528 	};
1529 
1530 	if (!frame_in || !frame_out || !out_cnt)
1531 		return -EINVAL;
1532 
1533 	rpmb_type = be16toh(frame_in->req_resp);
1534 
1535 	switch(rpmb_type) {
1536 	case MMC_RPMB_WRITE:
1537 	case MMC_RPMB_WRITE_KEY:
1538 		if (out_cnt != 1) {
1539 			err = -EINVAL;
1540 			goto out;
1541 		}
1542 
1543 		/* Write request */
1544 		ioc.write_flag |= (1<<31);
1545 		err = ioctl(fd, MMC_IOC_CMD, &ioc);
1546 		if (err < 0) {
1547 			err = -errno;
1548 			goto out;
1549 		}
1550 
1551 		/* Result request */
1552 		memset(frame_out, 0, sizeof(*frame_out));
1553 		frame_out->req_resp = htobe16(MMC_RPMB_READ_RESP);
1554 		ioc.write_flag = 1;
1555 		ioc.data_ptr = (uintptr_t)frame_out;
1556 		err = ioctl(fd, MMC_IOC_CMD, &ioc);
1557 		if (err < 0) {
1558 			err = -errno;
1559 			goto out;
1560 		}
1561 
1562 		/* Get response */
1563 		ioc.write_flag = 0;
1564 		ioc.opcode = MMC_READ_MULTIPLE_BLOCK;
1565 		err = ioctl(fd, MMC_IOC_CMD, &ioc);
1566 		if (err < 0) {
1567 			err = -errno;
1568 			goto out;
1569 		}
1570 
1571 		break;
1572 	case MMC_RPMB_READ_CNT:
1573 		if (out_cnt != 1) {
1574 			err = -EINVAL;
1575 			goto out;
1576 		}
1577 		/* fall through */
1578 
1579 	case MMC_RPMB_READ:
1580 		/* Request */
1581 		err = ioctl(fd, MMC_IOC_CMD, &ioc);
1582 		if (err < 0) {
1583 			err = -errno;
1584 			goto out;
1585 		}
1586 
1587 		/* Get response */
1588 		ioc.write_flag = 0;
1589 		ioc.opcode   = MMC_READ_MULTIPLE_BLOCK;
1590 		ioc.blocks   = out_cnt;
1591 		ioc.data_ptr = (uintptr_t)frame_out;
1592 		err = ioctl(fd, MMC_IOC_CMD, &ioc);
1593 		if (err < 0) {
1594 			err = -errno;
1595 			goto out;
1596 		}
1597 
1598 		break;
1599 	default:
1600 		err = -EINVAL;
1601 		goto out;
1602 	}
1603 
1604 out:
1605 	return err;
1606 }
1607 
do_rpmb_write_key(int nargs,char ** argv)1608 int do_rpmb_write_key(int nargs, char **argv)
1609 {
1610 	int ret, dev_fd, key_fd;
1611 	struct rpmb_frame frame_in = {
1612 		.req_resp = htobe16(MMC_RPMB_WRITE_KEY)
1613 	}, frame_out;
1614 
1615 	CHECK(nargs != 3, "Usage: mmc rpmb write-key </path/to/mmcblkXrpmb> </path/to/key>\n",
1616 			exit(1));
1617 
1618 	dev_fd = open(argv[1], O_RDWR);
1619 	if (dev_fd < 0) {
1620 		perror("device open");
1621 		exit(1);
1622 	}
1623 
1624 	if (0 == strcmp(argv[2], "-"))
1625 		key_fd = STDIN_FILENO;
1626 	else {
1627 		key_fd = open(argv[2], O_RDONLY);
1628 		if (key_fd < 0) {
1629 			perror("can't open key file");
1630 			exit(1);
1631 		}
1632 	}
1633 
1634 	/* Read the auth key */
1635 	ret = DO_IO(read, key_fd, frame_in.key_mac, sizeof(frame_in.key_mac));
1636 	if (ret < 0) {
1637 		perror("read the key");
1638 		exit(1);
1639 	} else if (ret != sizeof(frame_in.key_mac)) {
1640 		printf("Auth key must be %lu bytes length, but we read only %d, exit\n",
1641 			   (unsigned long)sizeof(frame_in.key_mac),
1642 			   ret);
1643 		exit(1);
1644 	}
1645 
1646 	/* Execute RPMB op */
1647 	ret = do_rpmb_op(dev_fd, &frame_in, &frame_out, 1);
1648 	if (ret != 0) {
1649 		perror("RPMB ioctl failed");
1650 		exit(1);
1651 	}
1652 
1653 	/* Check RPMB response */
1654 	if (frame_out.result != 0) {
1655 		printf("RPMB operation failed, retcode 0x%04x\n",
1656 			   be16toh(frame_out.result));
1657 		exit(1);
1658 	}
1659 
1660 	close(dev_fd);
1661 	if (key_fd != STDIN_FILENO)
1662 		close(key_fd);
1663 
1664 	return ret;
1665 }
1666 
rpmb_read_counter(int dev_fd,unsigned int * cnt)1667 int rpmb_read_counter(int dev_fd, unsigned int *cnt)
1668 {
1669 	int ret;
1670 	struct rpmb_frame frame_in = {
1671 		.req_resp = htobe16(MMC_RPMB_READ_CNT)
1672 	}, frame_out;
1673 
1674 	/* Execute RPMB op */
1675 	ret = do_rpmb_op(dev_fd, &frame_in, &frame_out, 1);
1676 	if (ret != 0) {
1677 		perror("RPMB ioctl failed");
1678 		exit(1);
1679 	}
1680 
1681 	/* Check RPMB response */
1682 	if (frame_out.result != 0)
1683 		return be16toh(frame_out.result);
1684 
1685 	*cnt = be32toh(frame_out.write_counter);
1686 
1687 	return 0;
1688 }
1689 
do_rpmb_read_counter(int nargs,char ** argv)1690 int do_rpmb_read_counter(int nargs, char **argv)
1691 {
1692 	int ret, dev_fd;
1693 	unsigned int cnt;
1694 
1695 	CHECK(nargs != 2, "Usage: mmc rpmb read-counter </path/to/mmcblkXrpmb>\n",
1696 			exit(1));
1697 
1698 	dev_fd = open(argv[1], O_RDWR);
1699 	if (dev_fd < 0) {
1700 		perror("device open");
1701 		exit(1);
1702 	}
1703 
1704 	ret = rpmb_read_counter(dev_fd, &cnt);
1705 
1706 	/* Check RPMB response */
1707 	if (ret != 0) {
1708 		printf("RPMB operation failed, retcode 0x%04x\n", ret);
1709 		exit(1);
1710 	}
1711 
1712 	close(dev_fd);
1713 
1714 	printf("Counter value: 0x%08x\n", cnt);
1715 
1716 	return ret;
1717 }
1718 
do_rpmb_read_block(int nargs,char ** argv)1719 int do_rpmb_read_block(int nargs, char **argv)
1720 {
1721 	int i, ret, dev_fd, data_fd, key_fd = -1;
1722 	uint16_t addr, blocks_cnt;
1723 	unsigned char key[32];
1724 	struct rpmb_frame frame_in = {
1725 		.req_resp    = htobe16(MMC_RPMB_READ),
1726 	}, *frame_out_p;
1727 
1728 	CHECK(nargs != 5 && nargs != 6, "Usage: mmc rpmb read-block </path/to/mmcblkXrpmb> <address> <blocks count> </path/to/output_file> [/path/to/key]\n",
1729 			exit(1));
1730 
1731 	dev_fd = open(argv[1], O_RDWR);
1732 	if (dev_fd < 0) {
1733 		perror("device open");
1734 		exit(1);
1735 	}
1736 
1737 	/* Get block address */
1738 	errno = 0;
1739 	addr = strtol(argv[2], NULL, 0);
1740 	if (errno) {
1741 		perror("incorrect address");
1742 		exit(1);
1743 	}
1744 	frame_in.addr = htobe16(addr);
1745 
1746 	/* Get blocks count */
1747 	errno = 0;
1748 	blocks_cnt = strtol(argv[3], NULL, 0);
1749 	if (errno) {
1750 		perror("incorrect blocks count");
1751 		exit(1);
1752 	}
1753 
1754 	if (!blocks_cnt) {
1755 		printf("please, specify valid blocks count number\n");
1756 		exit(1);
1757 	}
1758 
1759 	frame_out_p = calloc(sizeof(*frame_out_p), blocks_cnt);
1760 	if (!frame_out_p) {
1761 		printf("can't allocate memory for RPMB outer frames\n");
1762 		exit(1);
1763 	}
1764 
1765 	/* Write 256b data */
1766 	if (0 == strcmp(argv[4], "-"))
1767 		data_fd = STDOUT_FILENO;
1768 	else {
1769 		data_fd = open(argv[4], O_WRONLY | O_CREAT | O_APPEND,
1770 					   S_IRUSR | S_IWUSR);
1771 		if (data_fd < 0) {
1772 			perror("can't open output file");
1773 			exit(1);
1774 		}
1775 	}
1776 
1777 	/* Key is specified */
1778 	if (nargs == 6) {
1779 		if (0 == strcmp(argv[5], "-"))
1780 			key_fd = STDIN_FILENO;
1781 		else {
1782 			key_fd = open(argv[5], O_RDONLY);
1783 			if (key_fd < 0) {
1784 				perror("can't open input key file");
1785 				exit(1);
1786 			}
1787 		}
1788 
1789 		ret = DO_IO(read, key_fd, key, sizeof(key));
1790 		if (ret < 0) {
1791 			perror("read the key data");
1792 			exit(1);
1793 		} else if (ret != sizeof(key)) {
1794 			printf("Data must be %lu bytes length, but we read only %d, exit\n",
1795 				   (unsigned long)sizeof(key),
1796 				   ret);
1797 			exit(1);
1798 		}
1799 	}
1800 
1801 	/* Execute RPMB op */
1802 	ret = do_rpmb_op(dev_fd, &frame_in, frame_out_p, blocks_cnt);
1803 	if (ret != 0) {
1804 		perror("RPMB ioctl failed");
1805 		exit(1);
1806 	}
1807 
1808 	/* Check RPMB response */
1809 	if (frame_out_p[blocks_cnt - 1].result != 0) {
1810 		printf("RPMB operation failed, retcode 0x%04x\n",
1811 			   be16toh(frame_out_p[blocks_cnt - 1].result));
1812 		exit(1);
1813 	}
1814 
1815 	/* Do we have to verify data against key? */
1816 	if (nargs == 6) {
1817 		unsigned char mac[32];
1818 		hmac_sha256_ctx ctx;
1819 		struct rpmb_frame *frame_out = NULL;
1820 
1821 		hmac_sha256_init(&ctx, key, sizeof(key));
1822 		for (i = 0; i < blocks_cnt; i++) {
1823 			frame_out = &frame_out_p[i];
1824 			hmac_sha256_update(&ctx, frame_out->data,
1825 							   sizeof(*frame_out) -
1826 								   offsetof(struct rpmb_frame, data));
1827 		}
1828 
1829 		hmac_sha256_final(&ctx, mac, sizeof(mac));
1830 
1831 		/* Impossible */
1832 		assert(frame_out);
1833 
1834 		/* Compare calculated MAC and MAC from last frame */
1835 		if (memcmp(mac, frame_out->key_mac, sizeof(mac))) {
1836 			printf("RPMB MAC missmatch\n");
1837 			exit(1);
1838 		}
1839 	}
1840 
1841 	/* Write data */
1842 	for (i = 0; i < blocks_cnt; i++) {
1843 		struct rpmb_frame *frame_out = &frame_out_p[i];
1844 		ret = DO_IO(write, data_fd, frame_out->data, sizeof(frame_out->data));
1845 		if (ret < 0) {
1846 			perror("write the data");
1847 			exit(1);
1848 		} else if (ret != sizeof(frame_out->data)) {
1849 			printf("Data must be %lu bytes length, but we wrote only %d, exit\n",
1850 				   (unsigned long)sizeof(frame_out->data),
1851 				   ret);
1852 			exit(1);
1853 		}
1854 	}
1855 
1856 	free(frame_out_p);
1857 	close(dev_fd);
1858 	if (data_fd != STDOUT_FILENO)
1859 		close(data_fd);
1860 	if (key_fd != -1 && key_fd != STDIN_FILENO)
1861 		close(key_fd);
1862 
1863 	return ret;
1864 }
1865 
do_rpmb_write_block(int nargs,char ** argv)1866 int do_rpmb_write_block(int nargs, char **argv)
1867 {
1868 	int ret, dev_fd, key_fd, data_fd;
1869 	unsigned char key[32];
1870 	uint16_t addr;
1871 	unsigned int cnt;
1872 	struct rpmb_frame frame_in = {
1873 		.req_resp    = htobe16(MMC_RPMB_WRITE),
1874 		.block_count = htobe16(1)
1875 	}, frame_out;
1876 
1877 	CHECK(nargs != 5, "Usage: mmc rpmb write-block </path/to/mmcblkXrpmb> <address> </path/to/input_file> </path/to/key>\n",
1878 			exit(1));
1879 
1880 	dev_fd = open(argv[1], O_RDWR);
1881 	if (dev_fd < 0) {
1882 		perror("device open");
1883 		exit(1);
1884 	}
1885 
1886 	ret = rpmb_read_counter(dev_fd, &cnt);
1887 	/* Check RPMB response */
1888 	if (ret != 0) {
1889 		printf("RPMB read counter operation failed, retcode 0x%04x\n", ret);
1890 		exit(1);
1891 	}
1892 	frame_in.write_counter = htobe32(cnt);
1893 
1894 	/* Get block address */
1895 	errno = 0;
1896 	addr = strtol(argv[2], NULL, 0);
1897 	if (errno) {
1898 		perror("incorrect address");
1899 		exit(1);
1900 	}
1901 	frame_in.addr = htobe16(addr);
1902 
1903 	/* Read 256b data */
1904 	if (0 == strcmp(argv[3], "-"))
1905 		data_fd = STDIN_FILENO;
1906 	else {
1907 		data_fd = open(argv[3], O_RDONLY);
1908 		if (data_fd < 0) {
1909 			perror("can't open input file");
1910 			exit(1);
1911 		}
1912 	}
1913 
1914 	ret = DO_IO(read, data_fd, frame_in.data, sizeof(frame_in.data));
1915 	if (ret < 0) {
1916 		perror("read the data");
1917 		exit(1);
1918 	} else if (ret != sizeof(frame_in.data)) {
1919 		printf("Data must be %lu bytes length, but we read only %d, exit\n",
1920 			   (unsigned long)sizeof(frame_in.data),
1921 			   ret);
1922 		exit(1);
1923 	}
1924 
1925 	/* Read the auth key */
1926 	if (0 == strcmp(argv[4], "-"))
1927 		key_fd = STDIN_FILENO;
1928 	else {
1929 		key_fd = open(argv[4], O_RDONLY);
1930 		if (key_fd < 0) {
1931 			perror("can't open key file");
1932 			exit(1);
1933 		}
1934 	}
1935 
1936 	ret = DO_IO(read, key_fd, key, sizeof(key));
1937 	if (ret < 0) {
1938 		perror("read the key");
1939 		exit(1);
1940 	} else if (ret != sizeof(key)) {
1941 		printf("Auth key must be %lu bytes length, but we read only %d, exit\n",
1942 			   (unsigned long)sizeof(key),
1943 			   ret);
1944 		exit(1);
1945 	}
1946 
1947 	/* Calculate HMAC SHA256 */
1948 	hmac_sha256(
1949 		key, sizeof(key),
1950 		frame_in.data, sizeof(frame_in) - offsetof(struct rpmb_frame, data),
1951 		frame_in.key_mac, sizeof(frame_in.key_mac));
1952 
1953 	/* Execute RPMB op */
1954 	ret = do_rpmb_op(dev_fd, &frame_in, &frame_out, 1);
1955 	if (ret != 0) {
1956 		perror("RPMB ioctl failed");
1957 		exit(1);
1958 	}
1959 
1960 	/* Check RPMB response */
1961 	if (frame_out.result != 0) {
1962 		printf("RPMB operation failed, retcode 0x%04x\n",
1963 			   be16toh(frame_out.result));
1964 		exit(1);
1965 	}
1966 
1967 	close(dev_fd);
1968 	if (data_fd != STDIN_FILENO)
1969 		close(data_fd);
1970 	if (key_fd != STDIN_FILENO)
1971 		close(key_fd);
1972 
1973 	return ret;
1974 }
1975 
do_cache_ctrl(int value,int nargs,char ** argv)1976 int do_cache_ctrl(int value, int nargs, char **argv)
1977 {
1978 	__u8 ext_csd[512];
1979 	int fd, ret;
1980 	char *device;
1981 
1982 	CHECK(nargs != 2, "Usage: mmc cache enable </path/to/mmcblkX>\n",
1983 			  exit(1));
1984 
1985 	device = argv[1];
1986 
1987 	fd = open(device, O_RDWR);
1988 	if (fd < 0) {
1989 		perror("open");
1990 		exit(1);
1991 	}
1992 
1993 	ret = read_extcsd(fd, ext_csd);
1994 	if (ret) {
1995 		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
1996 		exit(1);
1997 	}
1998 
1999 	if (ext_csd[EXT_CSD_REV] < EXT_CSD_REV_V4_5) {
2000 		fprintf(stderr,
2001 			"The CACHE option is only availabe on devices >= "
2002 			"MMC 4.5 %s\n", device);
2003 		exit(1);
2004 	}
2005 
2006 	/* If the cache size is zero, this device does not have a cache */
2007 	if (!(ext_csd[EXT_CSD_CACHE_SIZE_3] ||
2008 			ext_csd[EXT_CSD_CACHE_SIZE_2] ||
2009 			ext_csd[EXT_CSD_CACHE_SIZE_1] ||
2010 			ext_csd[EXT_CSD_CACHE_SIZE_0])) {
2011 		fprintf(stderr,
2012 			"The CACHE option is not available on %s\n",
2013 			device);
2014 		exit(1);
2015 	}
2016 	ret = write_extcsd_value(fd, EXT_CSD_CACHE_CTRL, value);
2017 	if (ret) {
2018 		fprintf(stderr,
2019 			"Could not write 0x%02x to EXT_CSD[%d] in %s\n",
2020 			value, EXT_CSD_CACHE_CTRL, device);
2021 		exit(1);
2022 	}
2023 
2024 	return ret;
2025 }
2026 
do_cache_en(int nargs,char ** argv)2027 int do_cache_en(int nargs, char **argv)
2028 {
2029 	return do_cache_ctrl(1, nargs, argv);
2030 }
2031 
do_cache_dis(int nargs,char ** argv)2032 int do_cache_dis(int nargs, char **argv)
2033 {
2034 	return do_cache_ctrl(0, nargs, argv);
2035 }
2036