Home | History | Annotate | Download | only in mmc-utils
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    425 int do_hwreset_en(int nargs, char **argv)
    426 {
    427 	return do_hwreset(EXT_CSD_HW_RESET_EN, nargs, argv);
    428 }
    429 
    430 int do_hwreset_dis(int nargs, char **argv)
    431 {
    432 	return do_hwreset(EXT_CSD_HW_RESET_DIS, nargs, argv);
    433 }
    434 
    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 
    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 
    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 
    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 
    516 unsigned int get_hc_wp_grp_size(__u8 *ext_csd)
    517 {
    518 	return ext_csd[221];
    519 }
    520 
    521 unsigned int get_hc_erase_grp_size(__u8 *ext_csd)
    522 {
    523 	return ext_csd[224];
    524 }
    525 
    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 
    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 
    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 
    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 
    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 
    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 
   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  */
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2027 int do_cache_en(int nargs, char **argv)
   2028 {
   2029 	return do_cache_ctrl(1, nargs, argv);
   2030 }
   2031 
   2032 int do_cache_dis(int nargs, char **argv)
   2033 {
   2034 	return do_cache_ctrl(0, nargs, argv);
   2035 }
   2036