storaged-project / udisks

The UDisks project provides a daemon, tools and libraries to access and manipulate disks, storage devices and technologies.
https://storaged.org/doc/udisks2-api/latest/
Other
349 stars 142 forks source link

eMMC drives are recognized as (media) removable devices #358

Open KamilaBorowska opened 7 years ago

KamilaBorowska commented 7 years ago

The device block name in this case is /dev/mmcblk0. This causes KDE Device Notifier to consider this device removable. This is an eMMC (embedded MMC) device, not an MMC card. udisks 2.7.1 is used.

$ cat /sys/block/mmcblk0/removable 
0
$ gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/drives/BGND3R_0x35f4b45d --method org.freedesktop.DBus.Properties.Get org.freedesktop.UDisks2.Drive Removable
(<true>,)
$ gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/drives/BGND3R_0x35f4b45d --method org.freedesktop.DBus.Properties.Get org.freedesktop.UDisks2.Drive MediaRemovable
(<true>,)
$ lsblk
NAME         MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
mmcblk0      179:0    0  29,1G  0 disk 
├─mmcblk0p1  179:1    0   128M  0 part /boot
├─mmcblk0p2  179:2    0   1,7G  0 part [SWAP]
└─mmcblk0p3  179:3    0  27,3G  0 part /
mmcblk0boot0 179:8    0     4M  1 disk 
mmcblk0boot1 179:16   0     4M  1 disk 
mmcblk0rpmb  179:24   0     4M  0 disk 
zram0        254:0    0 478,9M  0 disk
vpodzime commented 7 years ago

Could you please also add the information from udev? (udevadm info -qall /dev/mmcblk0) We need some way to recognize the drive as embedded.

KamilaBorowska commented 7 years ago
P: /devices/pci0000:00/80860F14:00/mmc_host/mmc0/mmc0:0001/block/mmcblk0
N: mmcblk0
S: disk/by-id/mmc-BGND3R_0x35f4b45d
S: disk/by-path/platform-80860F14:00
E: DEVLINKS=/dev/disk/by-id/mmc-BGND3R_0x35f4b45d /dev/disk/by-path/platform-80860F14:00
E: DEVNAME=/dev/mmcblk0
E: DEVPATH=/devices/pci0000:00/80860F14:00/mmc_host/mmc0/mmc0:0001/block/mmcblk0
E: DEVTYPE=disk
E: ID_DRIVE_FLASH_SD=1
E: ID_DRIVE_MEDIA_FLASH_SD=1
E: ID_NAME=BGND3R
E: ID_PART_TABLE_TYPE=gpt
E: ID_PART_TABLE_UUID=23139e2c-2d11-4fe9-b1ad-38d49a8d0846
E: ID_PATH=platform-80860F14:00
E: ID_PATH_TAG=platform-80860F14_00
E: ID_SERIAL=0x35f4b45d
E: MAJOR=179
E: MINOR=0
E: SUBSYSTEM=block
E: TAGS=:systemd:
E: USEC_INITIALIZED=3439383
vpodzime commented 7 years ago

Hmm, I don't see anything eMMC specific. :(

pali commented 7 years ago

eMMC talks with normal mmc protocol, so de-facto it is mmc card. You should probably take removable flag from /sys/block/mmcblk0/removable... I do not know about way how to check or distinguish if block mmc device is SD card or eMMC.

E.g. on Nokia N900, there is internal eMMC (non-removable) and external slot for uSD card (so uSD card is removable). And both are handled by same driver and by same initialization code (just with different slot number). So if somebody wire up uSD slot instead of eMMC I think nothing would happen and uSD should work there.

So I'm really not sure if there is way how to distinguish between removable cards and internal eMMC.

And e.g. on Nokia N810 it was possible to remove also eMMC and replace it...

vpodzime commented 7 years ago

You should probably take removable flag from /sys/block/mmcblk0/removable...

And is at least that value correct?

pali commented 7 years ago

Good question. Better ask on some kernel mailing list discussion.

vpodzime commented 7 years ago

What does /sys/block/mmcblk0/removable say for your eMMC drive?

pali commented 7 years ago

On Nokia N900 for eMMC (mmcblk0) /sys/block/mmcblk0/removable says 0. And for uSD (mmcblk1) /sys/block/mmcblk1/removable says 0 too :-( But I have there old kernel, just 2.6.28. I'm afraid, but seems there is no way to distinguish eMMC and uSD, other sysfs attributes are not useful too. But maybe it is because of old kernel? Do not know.

KamilaBorowska commented 6 years ago

Got another eMMC device if that helps. I believe it is Toshiba 128G32.

~ $ cat /sys/block/mmcblk1/removable 
0
~ $ gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/drives/128G32_0x6b3be234 --method org.freedesktop.DBus.Properties.Get org.freedesktop.UDisks2.Drive Removable
(<true>,)
~ $ gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/drives/128G32_0x6b3be234 --method org.freedesktop.DBus.Properties.Get org.freedesktop.UDisks2.Drive MediaRemovable
(<true>,)
~ $ udevadm info -qall /dev/mmcblk1
P: /devices/pci0000:00/0000:00:1c.0/mmc_host/mmc1/mmc1:0001/block/mmcblk1
N: mmcblk1
S: disk/by-id/mmc-128G32_0x6b3be234
E: DEVLINKS=/dev/disk/by-id/mmc-128G32_0x6b3be234
E: DEVNAME=/dev/mmcblk1
E: DEVPATH=/devices/pci0000:00/0000:00:1c.0/mmc_host/mmc1/mmc1:0001/block/mmcblk1
E: DEVTYPE=disk
E: ID_DRIVE_FLASH_SD=1
E: ID_DRIVE_MEDIA_FLASH_SD=1
E: ID_NAME=128G32
E: ID_PART_TABLE_TYPE=gpt
E: ID_PART_TABLE_UUID=5cde66b8-71ec-4a33-80e2-14ba7ceb1d19
E: ID_SERIAL=0x6b3be234
E: MAJOR=179
E: MINOR=0
E: SUBSYSTEM=block
E: TAGS=:systemd:
E: USEC_INITIALIZED=13759219
wjt commented 6 years ago

Some past discussion of this problem https://bugs.freedesktop.org/show_bug.cgi?id=49844

tbzatek commented 4 years ago

Some past discussion of this problem https://bugs.freedesktop.org/show_bug.cgi?id=49844

I think that pretty much explains the state of things. I'm not aware of any reliable source of information about actual removable/builtin flag for eMMC devices. This would need to be provided by kernel first. One possible source of information could be ACPI device tree, however quirky that is.

Related: https://github.com/storaged-project/udisks/blob/master/src/udiskslinuxblock.c#L398

pali commented 4 years ago

eMMC is non-removable. So you just need to distinguish between SD card and eMMC to detect if device is removable (only SD card is removable). And this should be done by quering device type also from userspace via sending mmc command...

tbzatek commented 4 years ago

Backtrack, some more useful information: https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/739

tbzatek commented 4 years ago

eMMC is non-removable. So you just need to distinguish between SD card and eMMC to detect if device is removable (only SD card is removable). And this should be done by quering device type also from userspace via sending mmc command...

Interesting, thanks for the hint. We should give https://www.kernel.org/doc/html/latest/driver-api/mmc/mmc-tools.html a try and see what sort of information can we get from the device.

pali commented 3 years ago

There is even easier way how to distinguish what is connected to mmc subsystem. Just look into /sys/block/$dev/device/type file. It can contain one of these values:

Also this value is present in /sys/block/$dev/device/uevent file with key MMC_TYPE=.

tbzatek commented 3 years ago

Confirming on my Intel Atom x5-Z8350 (Cherry Trail) tablet: mmcblk0 reads MMC and mmcblk2 reads SD as supposed. Kernel 5.7.0-rc2+

What about an old MMC card in a SD slot?

pali commented 3 years ago

Content of uevent files should be available for udev, so based on this MMC_TYPE= should be possible to udev rules.

If you mean these https://en.wikipedia.org/wiki/MultiMediaCard cards then I have no idea. I have not used these cards for 10 years and I do not have native (non-USB) reader for them.

vojtechtrefny commented 3 years ago

Confirming on my Intel Atom x5-Z8350 (Cherry Trail) tablet: mmcblk0 reads MMC and mmcblk2 reads SD as supposed. Kernel 5.7.0-rc2+

Seems to be working correctly on ARM too and nothing usually works there :-)

[root@pine64 ~]# cat /sys/block/mmcblk0/device/type
SD
[root@pine64 ~]# cat /sys/block/mmcblk1/device/type
MMC
wjt commented 3 years ago

Pleasantly surprised to report that this works on the eMMC laptop I have to hand, too.

(Over on the GNOME bug report I mention the existence of hardware products with internal SD card slots – I expect those would be reported as SD, which is technically correct (it is a user-removable SD card) even though it is not practically correct (it is inside the case which is not intended to be dismantled by the user). I think a device-specific quirk work be appropriate in this case.)

pali commented 3 years ago

I do not see reason why it should not work. It is standard kernel feature and reports exact value which mmc chips reports. If it reports incorrect value then blame chip not kernel.

tbzatek commented 3 years ago

Great, thanks for confirming! Let me come up with a patch (for udisks-2.9.2)...

pali commented 3 years ago

I have found one 1GB RS-MMC card with adapter to full-size MMC. And surprisingly when I connected this card into my laptop's SDHC slot (which has native mmc controller on PCIe, not some shity usb controller) it worked out of the box with linux kernel, which detected it!

[123420.628777] mmc0: switch to bus width 8 failed
[123420.629034] mmc0: new high speed MMC card at address 0001
[123420.630087] mmcblk0: mmc0:0001 000000 980 MiB

But problem here begins, kernel reports MMC_TYPE=MMC:

$ grep . /sys/class/mmc_host/mmc0/mmc0\:0001/*
/sys/class/mmc_host/mmc0/mmc0:0001/cid:15000030303030303010100000581a00
/sys/class/mmc_host/mmc0/mmc0:0001/cmdq_en:0
/sys/class/mmc_host/mmc0/mmc0:0001/csd:9026012a0f5903d3f6dbbfe992404000
/sys/class/mmc_host/mmc0/mmc0:0001/date:01/2007
/sys/class/mmc_host/mmc0/mmc0:0001/dsr:0x404
/sys/class/mmc_host/mmc0/mmc0:0001/enhanced_area_offset:0
/sys/class/mmc_host/mmc0/mmc0:0001/enhanced_area_size:0
/sys/class/mmc_host/mmc0/mmc0:0001/erase_size:262144
/sys/class/mmc_host/mmc0/mmc0:0001/ffu_capable:0
/sys/class/mmc_host/mmc0/mmc0:0001/fwrev:0x0
/sys/class/mmc_host/mmc0/mmc0:0001/hwrev:0x0
/sys/class/mmc_host/mmc0/mmc0:0001/life_time:0x00 0x00
/sys/class/mmc_host/mmc0/mmc0:0001/manfid:0x000015
/sys/class/mmc_host/mmc0/mmc0:0001/name:000000
/sys/class/mmc_host/mmc0/mmc0:0001/ocr:0x00200000
/sys/class/mmc_host/mmc0/mmc0:0001/oemid:0x0000
/sys/class/mmc_host/mmc0/mmc0:0001/pre_eol_info:0x00
/sys/class/mmc_host/mmc0/mmc0:0001/preferred_erase_size:2097152
/sys/class/mmc_host/mmc0/mmc0:0001/prv:0x10
/sys/class/mmc_host/mmc0/mmc0:0001/raw_rpmb_size_mult:0x0
/sys/class/mmc_host/mmc0/mmc0:0001/rca:0x0001
/sys/class/mmc_host/mmc0/mmc0:0001/rel_sectors:0x0
/sys/class/mmc_host/mmc0/mmc0:0001/rev:0x1
/sys/class/mmc_host/mmc0/mmc0:0001/serial:0x10000058
/sys/class/mmc_host/mmc0/mmc0:0001/type:MMC
/sys/class/mmc_host/mmc0/mmc0:0001/uevent:DRIVER=mmcblk
/sys/class/mmc_host/mmc0/mmc0:0001/uevent:MMC_TYPE=MMC
/sys/class/mmc_host/mmc0/mmc0:0001/uevent:MMC_NAME=000000
/sys/class/mmc_host/mmc0/mmc0:0001/uevent:MODALIAS=mmc:block

I would be probably because these cards talks with mmc protocol (not SD). And some other mmc-tools would be needed to distinguish between eMMC and MMC/RS-MMC cards.

If you need to do more tests, let me know I can insert this card to my laptop when needed.

tbzatek commented 3 years ago

Thanks @pali, this is in line with expectations. This was a compromise to make as there was no easy way to distinguish the real MMC card and built-in eMMC scenario. I don't see anything in your output to indicate card removability or something else that could help us.

There's always a way to override this through the udev rules.

pali commented 3 years ago

I know...

Anyway, another option if particular MMC_TYPE=MMC card is removable, is to look where it is connected. Embedded hardware with eMMC has mmc controller directly in SoC / CPU and thefore uses native mmc kernel driver. On computers are often MMC/RS-MMC cards connected via USB or PCI(e) controllers. So what about looking where is mmc controller connected and based on this decide if MMC_TYPE=MMC is removable or not?

This RS-MMC card is connected to mmc controller which is connected via PCIe:

$ readlink -f /sys/class/mmc_host/mmc0/device
/sys/devices/pci0000:00/0000:00:1c.7/0000:0e:00.0
$ cat /sys/class/mmc_host/mmc0/device/uevent 
DRIVER=sdhci-pci
PCI_CLASS=80501
PCI_ID=1217:8520
PCI_SUBSYS_ID=1028:05BD
PCI_SLOT_NAME=0000:0e:00.0
MODALIAS=pci:v00001217d00008520sv00001028sd000005BDbc08sc05i01
KamilaBorowska commented 3 years ago

I would like to point out in two cases I posted previously eMMC was also connected using PCI according to kernel.

pali commented 3 years ago

I see :-( so this would not work.

I will look if we can retrive MMC/eMMC type via mmc commands.

pali commented 3 years ago

@xfix: can you post output of following commands?

tbzatek commented 3 years ago

I will look if we can retrive MMC/eMMC type via mmc commands.

The possibly best way to make this sustainable is to write extra udev rules that would call the mmc tools to retrieve extra information and expose that as udev attributes. This way the rules can be shipped along the mmc tools and udev will take care of probing the devices as they appear, not blocking udisksd for the job.

KamilaBorowska commented 3 years ago

Unfortunately, I cannot really post the output of those commands as I don't use those computers anymore.

pali commented 3 years ago

Ok, I read mmc standards and there is a way how to distinguish between embedded BGA and removable card types. It is via CID register, which is accessible to userspace via /sys/class/mmc_host/mmcX/mmcY:ZZZZ/cid sysfs file (it returns hexdump).

We need to look at CBX bits [113:112] of CID register.

CBX indicates the device type. Possible values are:

is to write extra udev rules that would call the mmc tools

Sorry, this does not help as mmc tools does not easily provide this information.

pali commented 3 years ago

So this command for card identified by X, Y, ZZZZ should print CBX value.

$ echo $((0x`cut -b 4 /sys/class/mmc_host/mmcX/mmcY:ZZZZ/cid` & 0x3))

(-b is indexed from 1; CID is 128 bit; sysfs returns hex bytes from most significat, therefore hex byte is at positions (127-112) / 8 * 2 + 0 + 1 (127-112) / 8 * 2 + 1 + 1; low 4 bits at (127-112) / 8 * 2 + 1 + 1 = 4 and low 2 bits by & 0x3)

It prints output in decimal (not binary; not hexadecimal).

Any non-zero value can be considered as non-removable (both BGA and PoP types cannot be removed and reserved is just reserved).

I have tested it and it is working! On ARM device with eMMC it prints:

$ echo $((0x`cut -b 4 /sys/class/mmc_host/mmc0/mmc0:0001/cid` & 0x3))
1

And on my computer with that RS-MMC card it prints:

$ echo $((0x`cut -b 4 /sys/class/mmc_host/mmc0/mmc0:0001/cid` & 0x3))
0
pali commented 3 years ago

@tbzatek: Do you have enough information to implement it now correctly?

Olf0 commented 3 years ago

Thanks @pali: When I started reading this thread, I repeatedly thought, "oh no, pali is pushing in the wrong direction: Treating eMMC and MMC (cards) alike", but that's it!

@tbzatek, what do you think?

Olf0 commented 3 years ago

@tbzatek, BTW the cut in @pali's statement should be used with the -c ("characters") option (instead of -b for "bytes"), because this is (ASCII) encoded text.

It can also be written without bashisms, but hardly as a one liner AFAICS, e.g.:

So this command for card identified by X, Y, ZZZZ should print CBX value.

CID="$(cut -c 4 /sys/class/mmc_host/mmcX/mmcY:ZZZZ/cid)"
case "$CID" in
[a-f]) CID="$(expr "$(echo -n "$CID" | hexdump -e '"%03d"')" - 87)"
;;
esac
CBX="$(expr "$CID" '%' 4)"