Understanding eMMC User Capacity

eMMC Apparently Misreporting Capacity

Many users have pointed out that the eMMC flash ROM of HTC Vision and other models reports itself via it's CID register as a Samsung "SEM04G" (SDIN5C2-4G) which has a User Data capacity of 3,957,325,824 bytes (7,729,152 x 512-byte sectors). However, according to the kernel, the device capacity is only 2.10GiB (2,254,858,240 bytes or 4,404,020 x 512-byte sectors):

INFO  [    5.501770] mmcblk0: mmc0:0001 SEM04G 2.10 GiB 

That leaves 1,702,467,584 bytes (3,325,132 x 512-byte sectors) apparently unavailable or missing. The "2.10 GiB" figure is calculated as an approximation of the exact value and there can be a small unreported remainder.

A picture says a thousand words

Visualisation of eMMC enhanced on capacity

In this diagram some partitions are shown as allocated to make understanding the entire capacity issue easier.


The answer is in the eMMC specification but is not spelled out clearly. The total user capacity of the embedded MultiMediaCard (eMMC) is the sum of the size of the enhanced user data area and the remaining user data area. The eMMC EXT_CSD registers accurately reflect the user capacity.

The SanDisk SDIN5C2-4G uses Multi-Level Cell (MLC) X4 technology that SanDisk acquired when they  bought Israeli company M-Systems in November 2006. The  X4 (multiply by four) technology allows detection of sixteen separate voltages, representing 8 binary bits, in the  floating-gate (FG) MOSFET transistors used in NAND flash devices. X4 allows increased storage for the same number of FG-MOSFETs but with increased errors due to the difficulty of accurately detecting the smaller voltage differences in a cell.

The enhanced mode of X4 eMMC simply reduces the cells to X2 (8 separate voltage levels) representing 4 binary bits.

Having less voltage levels to detect with larger differences means enhanced reliability at the expense of halving the storage capacity.

The eMMC can be programmed once in its lifetime with enhanced capabilities. This is done at the same time as the eMMC is partitioned by the manufacturer of the device that contains the eMMC. The eMMC has two Boot partitions, a Replay Protected Memory Block (RPMB), four General Purpose partitions (which can be zero length) and a User Data area.

Because not all data storage applications require this enhanced reliability eMMC provides for assigning a range of logical sectors in the user data area as enhanced. The starting location of this enhanced user data area can also be specified. The effect is that the enhanced X2 storage areas require twice as much space as regular X4 un-enhanced areas. When enhanced reliability is selected the RPMB and Boot partitions are automatically also enhanced. The four General Purpose partitions can be individually set as enhanced using the WR_REL_SET register in EXT_CSD.

The SEM04G is partitioned by HTC in the Vision as:

Boot1, Boot2, each 1 MiB
RPMB 128 kiB
GP1-GP4, each 0 MiB
User Data (in two disconnected chunks) 528 MiB
Enhanced User Data (offset 512 MiB into User Data) 1.5859375 GiB

Crunching the Numbers

This is a systematic reduction of the numbers using the values reported by a SEM04G eMMC via its EXT_CSD registers. The device_size_mismatch of 6.25MiB between the calculation and the maximum user capacity that SanDisk publish could be due to how they define the maximum capacity - sectors reserved for bad blocks, reliable write and so on might not be reflected in the EXT_CSD values.

# UPPERCASE are eMMC specification-defined registers in EXT_CSD

# 0x00434000
SEC_COUNT = 4407296

#ENH_SIZE_MULT_2 = 0x00
#ENH_SIZE_MULT_1 = 0x00
#ENH_SIZE_MULT_0 = 0x00

# 0x04

# 0x04

# 0x0000EC

# 0x00100000
ENH_START_ADDR = 1048576

# 512kB multiplier used by eMMC specification
size_multiplier = 524288

# bytes in a single addressable block
sector_size = 512

total_capacity = SEC_COUNT * sector_size
# 2256535552 (2.1015625 GiB)

enhanced_size = ENH_SIZE_MULT * HC_WP_GRP_SIZE x HC_ERASE_GPR_SIZE * size_multiplier
# 1702887424 (1.5859375 GiB)

enh_sector_count = enhanced_size / sector_size
# 3325952

unenhanced_sector_count = SEC_COUNT - enh_sector_count
# 1081344

unenhanced_size = unenhanced_sector_count * sector_size
# 553648128

user_data_prefix = sector_size * ENH_START_ADDRESS
# 536870912 (0.5 GiB)

user_data_suffix = unenhanced_size - user_data_prefix
# 16777216

# 128kB multiplier used by eMMC specification
boot_size_multipler = 131072


boot_part_size = BOOT_SIZE_MULTI * boot_size_multiplier
# 1048576

# device has two boot partitions
boot_part_qty = 2

boot_parts_size = boot_part_qty * boot_part_size
# 2097152

# 0x01

rpmb_size = RPMB_SIZE_MULT * boot_size_multiplier
# 131072

enhanced_boot_size = boot_parts_size + rpmb_size
# 2228224

# 0x04 : bit 2 = EN_REL_WR (The device supports the enhanced definition of reliable write)
#      : bit 0 = HS_CTRL_REL (All the WR_DATA_REL parameters in the WR_REL_SET register are read only bits)
WR_REL_PARAM = b00000100

# 0x17
WR_REL_SET = b00010111


total_user_size = unenhanced_size + (2 * enhanced_size)
# 3959422976
# 3.6875 GiB

total_size = total_user_size + (2 * enhanced_boot_size)
# 3963879424
# 3.691650391 GiB

# SanDisk specification for the SEM04G part
#  3.685546875 GiB
sandisk_user_max_sector_count = 7729152 
sandisk_user_max_size = 3957325824

device_size_mismatch = total_size - sandisk_user_max_size
# 6553600
# 6.25 MiB

capacity_mismatch = total_capacity - unenhanced_size - enhanced_size
# 0