Display new attributes in Extended CSD register introduced by eMMC 5.0: 'mmc extcsd read /dev/mmcblk0' returns for eMMC 5.0 device: ============================================= Extended CSD rev 1.7 (MMC 5.0) ============================================= Card Supported Command sets [S_CMD_SET: 0x01] ... Extended partition attribute support [EXT_SUPPORT: 0x03] Supported modes [SUPPORTED_MODES: 0x01] FFU features [FFU_FEATURES: 0x00] Operation codes timeout [OPERATION_CODE_TIMEOUT: 0x00] FFU Argument [FFU_ARG: 0x00000000] Number of FW sectors correctly programmed [NUMBER_OF_FW_SECTORS_CORRECTLY_PROGRAMMED: 0] Vendor proprietary health report: [VENDOR_PROPRIETARY_HEALTH_REPORT[301]]: 0x00 ... [VENDOR_PROPRIETARY_HEALTH_REPORT[270]]: 0x00 Device life time estimation type B [DEVICE_LIFE_TIME_EST_TYP_B: 0x01] i.e. 0% - 10% device life time used Device life time estimation type B [DEVICE_LIFE_TIME_EST_TYP_A: 0x01] i.e. 0% - 10% device life time used Pre EOL information [PRE_EOL_INFO: 0x01] i.e. Normal Optimal read size [OPTIMAL_READ_SIZE: 0x00] Optimal write size [OPTIMAL_WRITE_SIZE: 0x10] Optimal trim unit size [OPTIMAL_TRIM_UNIT_SIZE: 0x01] Device version [DEVICE_VERSION: 0x00 - 0x00] Firmware version: [FIRMWARE_VERSION[261]]: 0x00 ... [FIRMWARE_VERSION[254]]: 0x05 Power class for 200MHz, DDR at VCC= 3.6V [PWR_CL_DDR_200_360: 0x00] Generic CMD6 Timer [GENERIC_CMD6_TIME: 0x0a] Power off notification [POWER_OFF_LONG_TIME: 0x3c] Cache Size [CACHE_SIZE] is 65536 KiB ... Signed-off-by: Gwendal Grignou <gwendal@xxxxxxxxxxxx> Reviewed-by: Grant Grundler <grundler@xxxxxxxxxxxx> --- mmc_cmds.c | 146 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 44 deletions(-) diff --git a/mmc_cmds.c b/mmc_cmds.c index b8afa74..4b9b12e 100644 --- a/mmc_cmds.c +++ b/mmc_cmds.c @@ -424,12 +424,17 @@ int do_status_get(int nargs, char **argv) return ret; } +__u32 get_word_from_ext_csd(__u8 *ext_csd_loc) +{ + return (ext_csd_loc[3] << 24) | + (ext_csd_loc[2] << 16) | + (ext_csd_loc[1] << 8) | + ext_csd_loc[0]; +} + unsigned int get_sector_count(__u8 *ext_csd) { - return (ext_csd[EXT_CSD_SEC_COUNT_3] << 24) | - (ext_csd[EXT_CSD_SEC_COUNT_2] << 16) | - (ext_csd[EXT_CSD_SEC_COUNT_1] << 8) | - ext_csd[EXT_CSD_SEC_COUNT_0]; + return get_word_from_ext_csd(&ext_csd[EXT_CSD_SEC_COUNT_0]); } int is_blockaddresed(__u8 *ext_csd) @@ -701,6 +706,23 @@ int do_read_extcsd(int nargs, char **argv) int fd, ret; char *device; const char *str; + const char *ver_str[] = { + "4.0", /* 0 */ + "4.1", /* 1 */ + "4.2", /* 2 */ + "4.3", /* 3 */ + "Obsolete", /* 4 */ + "4.41", /* 5 */ + "4.5", /* 6 */ + "5.0", /* 7 */ + }; + int boot_access; + const char* boot_access_str[] = { + "No access to boot partition", /* 0 */ + "R/W Boot Partition 1", /* 1 */ + "R/W Boot Partition 2", /* 2 */ + "R/W Replay Protected Memory Block (RPMB)", /* 3 */ + }; CHECK(nargs != 2, "Usage: mmc extcsd read </path/to/mmcblkX>\n", exit(1)); @@ -721,28 +743,12 @@ int do_read_extcsd(int nargs, char **argv) ext_csd_rev = ext_csd[192]; - switch (ext_csd_rev) { - case 6: - str = "4.5"; - break; - case 5: - str = "4.41"; - break; - case 3: - str = "4.3"; - break; - case 2: - str = "4.2"; - break; - case 1: - str = "4.1"; - break; - case 0: - str = "4.0"; - break; - default: + if ((ext_csd_rev < sizeof(ver_str)/sizeof(char*)) && + (ext_csd_rev != 4)) + str = ver_str[ext_csd_rev]; + else goto out_free; - } + printf("=============================================\n"); printf(" Extended CSD rev 1.%d (MMC %s)\n", ext_csd_rev, str); printf("=============================================\n\n"); @@ -789,13 +795,77 @@ int do_read_extcsd(int nargs, char **argv) ext_csd[495]); printf("Extended partition attribute support" " [EXT_SUPPORT: 0x%02x]\n", ext_csd[494]); + } + if (ext_csd_rev >= 7) { + int j; + int eol_info; + char* eol_info_str[] = { + "Not Defined", /* 0 */ + "Normal", /* 1 */ + "Warning", /* 2 */ + "Urgent", /* 3 */ + }; + + printf("Supported modes [SUPPORTED_MODES: 0x%02x]\n", + ext_csd[493]); + printf("FFU features [FFU_FEATURES: 0x%02x]\n", + ext_csd[492]); + printf("Operation codes timeout" + " [OPERATION_CODE_TIMEOUT: 0x%02x]\n", + ext_csd[491]); + printf("FFU Argument [FFU_ARG: 0x%08x]\n", + get_word_from_ext_csd(&ext_csd[487])); + printf("Number of FW sectors correctly programmed" + " [NUMBER_OF_FW_SECTORS_CORRECTLY_PROGRAMMED: %d]\n", + get_word_from_ext_csd(&ext_csd[302])); + printf("Vendor proprietary health report:\n"); + for (j = 301; j >= 270; j--) + printf("[VENDOR_PROPRIETARY_HEALTH_REPORT[%d]]:" + " 0x%02x\n", j, ext_csd[j]); + for (j = 269; j >= 268; j--) { + __u8 life_used=ext_csd[j]; + printf("Device life time estimation type B" + " [DEVICE_LIFE_TIME_EST_TYP_%c: 0x%02x]\n", + 'B' + (j - 269), life_used); + if (life_used >= 0x1 && life_used <= 0xa) + printf(" i.e. %d%% - %d%% device life time" + " used\n", + (life_used - 1) * 10, life_used * 10); + else if (life_used == 0xb) + printf(" i.e. Exceeded its maximum estimated" + " device life time\n"); + } + eol_info = ext_csd[267]; + printf("Pre EOL information [PRE_EOL_INFO: 0x%02x]\n", + eol_info); + if (eol_info < sizeof(eol_info_str)/sizeof(char*)) + printf(" i.e. %s\n", eol_info_str[eol_info]); + else + printf(" i.e. Reserved\n"); + + printf("Optimal read size [OPTIMAL_READ_SIZE: 0x%02x]\n", + ext_csd[266]); + printf("Optimal write size [OPTIMAL_WRITE_SIZE: 0x%02x]\n", + ext_csd[265]); + printf("Optimal trim unit size" + " [OPTIMAL_TRIM_UNIT_SIZE: 0x%02x]\n", ext_csd[264]); + printf("Device version [DEVICE_VERSION: 0x%02x - 0x%02x]\n", + ext_csd[263], ext_csd[262]); + printf("Firmware version:\n"); + for (j = 261; j >= 254; j--) + printf("[FIRMWARE_VERSION[%d]]:" + " 0x%02x\n", j, ext_csd[j]); + + printf("Power class for 200MHz, DDR at VCC= 3.6V" + " [PWR_CL_DDR_200_360: 0x%02x]\n", ext_csd[253]); + } + if (ext_csd_rev >= 6) { printf("Generic CMD6 Timer [GENERIC_CMD6_TIME: 0x%02x]\n", ext_csd[248]); printf("Power off notification [POWER_OFF_LONG_TIME: 0x%02x]\n", ext_csd[247]); printf("Cache Size [CACHE_SIZE] is %d KiB\n", - ext_csd[249] << 0 | (ext_csd[250] << 8) | - (ext_csd[251] << 16) | (ext_csd[252] << 24)); + get_word_from_ext_csd(&ext_csd[249])); } /* A441: Reserved [501:247] @@ -945,24 +1015,12 @@ int do_read_extcsd(int nargs, char **argv) printf(" User Area Enabled for boot\n"); break; } - switch (reg & EXT_CSD_BOOT_CFG_ACC) { - case 0x0: - printf(" No access to boot partition\n"); - break; - case 0x1: - printf(" R/W Boot Partition 1\n"); - break; - case 0x2: - printf(" R/W Boot Partition 2\n"); - break; - case 0x3: - printf(" R/W Replay Protected Memory Block (RPMB)\n"); - break; - default: + boot_access = reg & EXT_CSD_BOOT_CFG_ACC; + if (boot_access < sizeof(boot_access_str) / sizeof(char*)) + printf(" %s\n", boot_access_str[boot_access]); + else printf(" Access to General Purpose partition %d\n", - (reg & EXT_CSD_BOOT_CFG_ACC) - 3); - break; - } + boot_access - 3); printf("Boot config protection [BOOT_CONFIG_PROT: 0x%02x]\n", ext_csd[178]); -- 1.9.0.rc1.175.g0b1dcb5 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html