@@ -87,14 +87,42 @@ static struct Command commands[] = {
"Set the eMMC data sector size to 4KB by disabling emulation on\n<device>.",
NULL
},
- { do_create_gp_partition, -6,
- "gp create", "<-y|-n|-c> " "<length KiB> " "<partition> " "<enh_attr> " "<ext_attr> " "<device>\n"
- "Create general purpose partition for the <device>.\nDry-run only unless -y or -c is passed.\nUse -c if more partitioning settings are still to come.\nNOTE! This is a one-time programmable (unreversible) change.\nTo set enhanced attribute to general partition being created set\n <enh_attr> to 1 else set it to 0.\nTo set extended attribute to general partition\n set <ext_attr> to 1,2 else set it to 0",
+ { do_create_gp_partition, 4,
+ "gp create", "<-y|-n|-c> " "<length KiB> " "<partition> " "<device>\n"
+ "Create general purpose partition for the <device>.\n"
+ "Dry-run only unless -y or -c is passed.\n"
+ "Use -c if more partitioning settings are still to come.\n"
+ "NOTE! This is a one-time programmable (unreversible) change.",
NULL
},
- { do_enh_area_set, -4,
- "enh_area set", "<-y|-n|-c> " "<start KiB> " "<length KiB> " "<device>\n"
- "Enable the enhanced user area for the <device>.\nDry-run only unless -y or -c is passed.\nUse -c if more partitioning settings are still to come.\nNOTE! This is a one-time programmable (unreversible) change.",
+ { do_gp_set_extended, 3,
+ "gp set_extended", "<-y|-n|-c> " "<partition-mask> " "<device>\n"
+ "Set extended attribute on specified general purpose partitions for the <device>.\n"
+ "GP4=bit[15:12], GP3=bit[11:8], GP2=bit[7:4], GP1=bit[3:0]\n"
+ "e.g setting <partition-mask> to 0x0120 will set extended attribute 0x02 on 'GP2'\n"
+ " partition and extended attribute 0x01 on 'GP3' partition\n"
+ "Dry-run only unless -y or -c is passed.\n"
+ "Use -c if more partitioning settings are still to come.\n"
+ "NOTE! This is a one-time programmable (unreversible) change.",
+ NULL
+ },
+ { do_enh_area_set_user_data, -4,
+ "enh_area set_user_data", "<-y|-n|-c> " "<start KiB> " "<length KiB> " "<device>\n"
+ "Set the size and offset of the enhanced user data area for the <device>.\n"
+ "Dry-run only unless -y or -c is passed.\n"
+ "Use -c if more partitioning settings are still to come.\n"
+ "NOTE! This is a one-time programmable (unreversible) change.",
+ NULL
+ },
+ { do_enh_area_set_partitions, 3,
+ "enh_area set_partitions", "<-y|-n|-c> " "<partition-mask> " "<device>\n"
+ "Enable enhanced attribute on specified partitions for the <device>.\n"
+ "User area=bit[0], GP1=bit[1], GP2=bit[2], GP3=bit[3], GP4=bit[4]\n"
+ "e.g setting <partition-mask> to 0x03 will set 'User Area' and 'GP1' partitions \n"
+ " with enhanced attribute, and all others without enhanced attribute.\n"
+ "Dry-run only unless -y or -c is passed.\n"
+ "Use -c if more partitioning settings are still to come.\n"
+ "NOTE! This is a one-time programmable (unreversible) change.",
NULL
},
{ do_write_reliability_set_register, -2,
@@ -102,7 +130,7 @@ static struct Command commands[] = {
"Set the write-reliability register (WR_REL_SET) for the <device>.\n"
"User area=bit0, GP1=bit1, GP2=bit2, GP3=bit3, GP4=bit4\n"
"e.g setting register to 0x03 will set 'User Area' and 'GP1' partitions \n"
- "with write-reliability, and all others without write-reliability.\n"
+ " with write-reliability, and all others without write-reliability.\n"
"NOTE! This is a one-time programmable (irreversible) change.",
NULL
},
@@ -967,6 +967,81 @@ int check_enhanced_area_total_limit(const char * const device, int fd)
return 0;
}
+// TODO: check if enhanced attributes set on GP partitions (only allowed either enhanced or extended attribute)
+int do_gp_set_extended(int nargs, char **argv)
+{
+ __u8 value;
+ __u8 ext_csd[512];
+ __u8 address;
+ int fd, ret;
+ char *device;
+ int dry_run = 1;
+ long partition_mask;
+ char *endptr;
+
+ if (nargs != 4) {
+ fprintf(stderr, "Usage: mmc gp set_extended <-y|-n|-c> <partition-mask> </path/to/mmcblkX>\n");
+ exit(1);
+ }
+
+ if (!strcmp("-y", argv[1])) {
+ dry_run = 0;
+ } else if (!strcmp("-c", argv[1])) {
+ dry_run = 2;
+ }
+
+ errno = 0;
+ partition_mask = strtol(argv[2], &endptr, 0);
+ if (errno != 0 || endptr == argv[2] || *endptr != 0 || partition_mask < 0 || partition_mask > 0xffff) {
+ fprintf(stderr, "Partition mask invalid: %s\n", argv[2]);
+ exit(1);
+ }
+
+ device = argv[3];
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ ret = read_extcsd(fd, ext_csd);
+ if (ret) {
+ fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
+ exit(1);
+ }
+
+ /* assert not PARTITION_SETTING_COMPLETED */
+ if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED]) {
+ printf(" Device is already partitioned\n");
+ exit(1);
+ }
+
+ value = (__u8)partition_mask;
+ address = EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_0;
+ ret = write_extcsd_value(fd, address, value);
+ fprintf(stderr, "Writing 0x%02x to EXT_CSD[%d]\n", value, address);
+ if (ret) {
+ fprintf(stderr, "Could not write 0x%x to EXT_CSD[%d] in %s\n",
+ value, address, device);
+ exit(1);
+ }
+
+ value = (__u8)(partition_mask >> 8);
+ address = EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_1;
+ ret = write_extcsd_value(fd, address, value);
+ fprintf(stderr, "Writing 0x%02x to EXT_CSD[%d]\n", value, address);
+ if (ret) {
+ fprintf(stderr, "Could not write 0x%x to EXT_CSD[%d] in %s\n",
+ value, address, device);
+ exit(1);
+ }
+
+ if (set_partitioning_setting_completed(dry_run, device, fd))
+ exit(1);
+
+ return 0;
+}
+
int do_create_gp_partition(int nargs, char **argv)
{
__u8 value;
@@ -975,12 +1050,12 @@ int do_create_gp_partition(int nargs, char **argv)
int fd, ret;
char *device;
int dry_run = 1;
- int partition, enh_attr, ext_attr;
+ int partition;
unsigned int length_kib, gp_size_mult;
unsigned long align;
- if (nargs != 7) {
- fprintf(stderr, "Usage: mmc gp create <-y|-n|-c> <length KiB> <partition> <enh_attr> <ext_attr> </path/to/mmcblkX>\n");
+ if (nargs != 5) {
+ fprintf(stderr, "Usage: mmc gp create <-y|-n|-c> <length KiB> <partition> </path/to/mmcblkX>\n");
exit(1);
}
@@ -992,20 +1067,13 @@ int do_create_gp_partition(int nargs, char **argv)
length_kib = strtol(argv[2], NULL, 10);
partition = strtol(argv[3], NULL, 10);
- enh_attr = strtol(argv[4], NULL, 10);
- ext_attr = strtol(argv[5], NULL, 10);
- device = argv[6];
+ device = argv[4];
if (partition < 1 || partition > 4) {
printf("Invalid gp partition number; valid range [1-4].\n");
exit(1);
}
- if (enh_attr && ext_attr) {
- printf("Not allowed to set both enhanced attribute and extended attribute\n");
- exit(1);
- }
-
fd = open(device, O_RDWR);
if (fd < 0) {
perror("open");
@@ -1060,30 +1128,52 @@ int do_create_gp_partition(int nargs, char **argv)
exit(1);
}
- value = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
- if (enh_attr)
- value |= (1 << partition);
- else
- value &= ~(1 << partition);
+ if (set_partitioning_setting_completed(dry_run, device, fd))
+ exit(1);
- ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value);
- if (ret) {
- fprintf(stderr, "Could not write EXT_CSD_ENH_%x to EXT_CSD[%d] in %s\n",
- partition, EXT_CSD_PARTITIONS_ATTRIBUTE, device);
+ return 0;
+}
+
+// TODO: check if extended attributes set on GP partitions (only allowed either enhanced or extended attribute)
+int do_enh_area_set_partitions(int nargs, char **argv)
+{
+ int fd, ret;
+ char *device;
+ int dry_run = 1;
+ long partition_mask;
+ char *endptr;
+
+ if (nargs != 4) {
+ fprintf(stderr, "Usage: mmc enh_area set_partitions <-y|-n|-c> <partition-mask> </path/to/mmcblkX>\n");
exit(1);
}
- address = EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_0 + (partition - 1) / 2;
- value = ext_csd[address];
- if (ext_attr)
- value |= (ext_attr << (4 * ((partition - 1) % 2)));
- else
- value &= (0xF << (4 * ((partition % 2))));
+ if (!strcmp("-y", argv[1])) {
+ dry_run = 0;
+ } else if (!strcmp("-c", argv[1])) {
+ dry_run = 2;
+ }
- ret = write_extcsd_value(fd, address, value);
+ errno = 0;
+ partition_mask = strtol(argv[2], &endptr, 0);
+ if (errno != 0 || endptr == argv[2] || *endptr != 0 || partition_mask < 0 || partition_mask > 0x1f) {
+ fprintf(stderr, "Partition mask invalid: %s\n", argv[2]);
+ exit(1);
+ }
+
+ device = argv[3];
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, (__u8)partition_mask);
if (ret) {
- fprintf(stderr, "Could not write 0x%x to EXT_CSD[%d] in %s\n",
- value, address, device);
+ fprintf(stderr, "Could not write 0x%02x to "
+ "EXT_CSD[%d] in %s\n",
+ (__u8)partition_mask,
+ EXT_CSD_PARTITIONS_ATTRIBUTE, device);
exit(1);
}
@@ -1097,7 +1187,7 @@ int do_create_gp_partition(int nargs, char **argv)
return 0;
}
-int do_enh_area_set(int nargs, char **argv)
+int do_enh_area_set_user_data(int nargs, char **argv)
{
__u8 value;
__u8 ext_csd[512];
@@ -1108,7 +1198,7 @@ int do_enh_area_set(int nargs, char **argv)
unsigned long align;
if (nargs != 5) {
- fprintf(stderr, "Usage: mmc enh_area set <-y|-n|-c> <start KiB> <length KiB> </path/to/mmcblkX>\n");
+ fprintf(stderr, "Usage: mmc enh_area set_user_data <-y|-n|-c> <start KiB> <length KiB> </path/to/mmcblkX>\n");
exit(1);
}
@@ -1148,6 +1238,13 @@ int do_enh_area_set(int nargs, char **argv)
exit(1);
}
+ /* assert enhanced attribute is set on user partition */
+ if (!(ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_USR))
+ {
+ fprintf(stderr, "error: User partition must be set with enhanced attribute first\n");
+ exit(1);
+ }
+
align = 512l * get_hc_wp_grp_size(ext_csd) * get_hc_erase_grp_size(ext_csd);
enh_size_mult = (length_kib + align/2l) / align;
@@ -1165,7 +1262,7 @@ int do_enh_area_set(int nargs, char **argv)
exit(1);
}
- /* write to ENH_START_ADDR and ENH_SIZE_MULT and PARTITIONS_ATTRIBUTE's ENH_USR bit */
+ /* write to ENH_START_ADDR and ENH_SIZE_MULT */
value = (enh_start_addr >> 24) & 0xff;
ret = write_extcsd_value(fd, EXT_CSD_ENH_START_ADDR_3, value);
if (ret) {
@@ -1223,14 +1320,6 @@ int do_enh_area_set(int nargs, char **argv)
EXT_CSD_ENH_SIZE_MULT_0, device);
exit(1);
}
- value = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] | EXT_CSD_ENH_USR;
- ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, value);
- if (ret) {
- fprintf(stderr, "Could not write EXT_CSD_ENH_USR to "
- "EXT_CSD[%d] in %s\n",
- EXT_CSD_PARTITIONS_ATTRIBUTE, device);
- exit(1);
- }
ret = check_enhanced_area_total_limit(device, fd);
if (ret)
@@ -33,7 +33,9 @@ int do_hwreset_dis(int nargs, char **argv);
int do_sanitize(int nargs, char **argv);
int do_status_get(int nargs, char **argv);
int do_create_gp_partition(int nargs, char **argv);
-int do_enh_area_set(int nargs, char **argv);
+int do_gp_set_extended(int nargs, char **argv);
+int do_enh_area_set_user_data(int nargs, char **argv);
+int do_enh_area_set_partitions(int nargs, char **argv);
int do_write_reliability_set_register(int nargs, char **argv);
int do_rpmb_write_key(int nargs, char **argv);
int do_rpmb_read_counter(int nargs, char **argv);
The enhanced and extended attributes must be set on all required partitions in a single command instead of one command per partition. Remove the enhanced and extended attribute setting parameters from the "gp create" and "enh_area set" commands and create new commands: * "enh_area set_partitions" * "enh_area set_user_data" * "gp set_extended" Signed-off-by: James Nuss <jamesnuss@nanometrics.ca> --- mmc.c | 42 ++++++++++++--- mmc_cmds.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++--------------- mmc_cmds.h | 4 +- 3 files changed, 167 insertions(+), 48 deletions(-)