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