summaryrefslogtreecommitdiff
path: root/mmc_cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'mmc_cmds.c')
-rw-r--r--mmc_cmds.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/mmc_cmds.c b/mmc_cmds.c
index cea943f..2fc8d4a 100644
--- a/mmc_cmds.c
+++ b/mmc_cmds.c
@@ -498,6 +498,89 @@ int set_partitioning_setting_completed(int dry_run, const char * const device,
return 0;
}
+int check_enhanced_area_total_limit(const char * const device, int fd)
+{
+ __u8 ext_csd[512];
+ __u32 regl;
+ unsigned long max_enh_area_sz, user_area_sz, enh_area_sz = 0;
+ unsigned long gp4_part_sz, gp3_part_sz, gp2_part_sz, gp1_part_sz;
+ unsigned int wp_sz, erase_sz;
+ int ret;
+
+ ret = read_extcsd(fd, ext_csd);
+ if (ret) {
+ fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
+ exit(1);
+ }
+ wp_sz = get_hc_wp_grp_size(ext_csd);
+ erase_sz = get_hc_erase_grp_size(ext_csd);
+
+ regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_4_2] << 16) |
+ (ext_csd[EXT_CSD_GP_SIZE_MULT_4_1] << 8) |
+ ext_csd[EXT_CSD_GP_SIZE_MULT_4_0];
+ gp4_part_sz = 512l * regl * erase_sz * wp_sz;
+ if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_4) {
+ enh_area_sz += gp4_part_sz;
+ printf("Enhanced GP4 Partition Size [GP_SIZE_MULT_4]: 0x%06x\n", regl);
+ printf(" i.e. %lu KiB\n", gp4_part_sz);
+ }
+
+ regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_3_2] << 16) |
+ (ext_csd[EXT_CSD_GP_SIZE_MULT_3_1] << 8) |
+ ext_csd[EXT_CSD_GP_SIZE_MULT_3_0];
+ gp3_part_sz = 512l * regl * erase_sz * wp_sz;
+ if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_3) {
+ enh_area_sz += gp3_part_sz;
+ printf("Enhanced GP3 Partition Size [GP_SIZE_MULT_3]: 0x%06x\n", regl);
+ printf(" i.e. %lu KiB\n", gp3_part_sz);
+ }
+
+ regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_2_2] << 16) |
+ (ext_csd[EXT_CSD_GP_SIZE_MULT_2_1] << 8) |
+ ext_csd[EXT_CSD_GP_SIZE_MULT_2_0];
+ gp2_part_sz = 512l * regl * erase_sz * wp_sz;
+ if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_2) {
+ enh_area_sz += gp2_part_sz;
+ printf("Enhanced GP2 Partition Size [GP_SIZE_MULT_2]: 0x%06x\n", regl);
+ printf(" i.e. %lu KiB\n", gp2_part_sz);
+ }
+
+ regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_1_2] << 16) |
+ (ext_csd[EXT_CSD_GP_SIZE_MULT_1_1] << 8) |
+ ext_csd[EXT_CSD_GP_SIZE_MULT_1_0];
+ gp1_part_sz = 512l * regl * erase_sz * wp_sz;
+ if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_1) {
+ enh_area_sz += gp1_part_sz;
+ printf("Enhanced GP1 Partition Size [GP_SIZE_MULT_1]: 0x%06x\n", regl);
+ printf(" i.e. %lu KiB\n", gp1_part_sz);
+ }
+
+ regl = (ext_csd[EXT_CSD_ENH_SIZE_MULT_2] << 16) |
+ (ext_csd[EXT_CSD_ENH_SIZE_MULT_1] << 8) |
+ ext_csd[EXT_CSD_ENH_SIZE_MULT_0];
+ user_area_sz = 512l * regl * erase_sz * wp_sz;
+ if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_USR) {
+ enh_area_sz += user_area_sz;
+ printf("Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x%06x\n", regl);
+ printf(" i.e. %lu KiB\n", user_area_sz);
+ }
+
+ regl = (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_2] << 16) |
+ (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_1] << 8) |
+ ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_0];
+ max_enh_area_sz = 512l * regl * erase_sz * wp_sz;
+ printf("Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x%06x\n", regl);
+ printf(" i.e. %lu KiB\n", max_enh_area_sz);
+ if (enh_area_sz > max_enh_area_sz) {
+ fprintf(stderr,
+ "Programmed total enhanced size %lu KiB cannot exceed max enhanced area %lu KiB %s\n",
+ enh_area_sz, max_enh_area_sz, device);
+ return 1;
+ }
+
+ return 0;
+}
+
int do_enh_area_set(int nargs, char **argv)
{
__u8 value;
@@ -619,8 +702,8 @@ int do_enh_area_set(int nargs, char **argv)
EXT_CSD_ENH_SIZE_MULT_0, device);
exit(1);
}
-
- ret = write_extcsd_value(fd, EXT_CSD_PARTITIONS_ATTRIBUTE, EXT_CSD_ENH_USR);
+ 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",
@@ -628,6 +711,10 @@ int do_enh_area_set(int nargs, char **argv)
exit(1);
}
+ ret = check_enhanced_area_total_limit(device, fd);
+ if (ret)
+ exit(1);
+
printf("Done setting ENH_USR area on %s\n", device);
if (!set_partitioning_setting_completed(dry_run, device, fd))