Author Archives: Hal Martin

About Hal Martin

In my free time I like experiment with hardware and embedded systems. Here I write about personal projects and random adventures into firmware land.

From Amazon with love: not quite 32GB micro SD cards

I needed more space in my tablet and phone, so I went to everyone’s favourite online merchant, Amazon, and purchased two SanDisk 32GB Class 10 micro SDHC cards.

Now, if you haven’t bought SanDisk micro SD cards lately, let me warn you now, the silk screen looks horrible. At first I thought they were counterfeit, it’s that bad. I wonder if the guys at SanDisk did some research to see how shitty they could make the silk screen and not have it appear in cell phone photos. My potato camera phone has just enough noise that it’s difficult to tell just how bad the SanDisk logo looks, but it’s awful.

My camera phone isn't the greatest, but these cards look just blurry and noisy in reality

My camera phone isn’t the greatest, but these cards look just as blurry and noisy in reality

But a bad silk screen can be overlooked if the cards themselves still function, which brings me to my next point:

[38853.623229] scsi 9:0:0:0: Direct-Access     Generic- SD/MMC           1.00 PQ: 0 ANSI: 0 CCS
[38854.311664] sd 9:0:0:0: [sdb] 60367872 512-byte logical blocks: (30.9 GB/28.7 GiB)
[38854.312801] sd 9:0:0:0: [sdb] Write Protect is off
[38854.312812] sd 9:0:0:0: [sdb] Mode Sense: 03 00 00 00
[38854.313898] sd 9:0:0:0: [sdb] No Caching mode page found
[38854.313917] sd 9:0:0:0: [sdb] Assuming drive cache: write through
[38854.329950]  sdb: sdb1
[38854.333772] sd 9:0:0:0: [sdb] Attached SCSI removable disk

Disk /dev/sdb: 28.8 GiB, 30908350464 bytes, 60367872 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdb1        8192 60367871 60359680 28.8G  c W95 FAT32 (LBA)

28.7GiB?! What the hell? I know storage manufacturers have redefined a gigabyte to be 1,000,000,000 bytes (1 billion bytes) instead of 1,073,741,824 bytes (1024^3) but this is some next level math happening here.

For comparison, here is a Transcend 32GB Class 10 micro SDHC card:

[38782.491351] scsi 7:0:0:0: Direct-Access     Generic- SD/MMC           1.00 PQ: 0 ANSI: 0 CCS
[38783.265974] sd 7:0:0:0: [sdb] 61831168 512-byte logical blocks: (31.6 GB/29.4 GiB)
[38783.267091] sd 7:0:0:0: [sdb] Write Protect is off
[38783.267099] sd 7:0:0:0: [sdb] Mode Sense: 03 00 00 00
[38783.268192] sd 7:0:0:0: [sdb] No Caching mode page found
[38783.268197] sd 7:0:0:0: [sdb] Assuming drive cache: write through
[38783.273707]  sdb: sdb1
[38783.277183] sd 7:0:0:0: [sdb] Attached SCSI removable disk

Disk /dev/sdb: 29.5 GiB, 31657558016 bytes, 61831168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x000db221

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdb1        2048 61831167 61829120 29.5G  c W95 FAT32 (LBA)

29.4GiB is a lot closer to what we expect from a 32GB (32,000,000,000 byte) card. The precise number is 29.80232GiB, but okay, it’s not much less.

So the SanDisk card is a about 700MB smaller than the Transcend. That alone was enough to make me apply for an RMA…

but-wait-theres-myrrh

A Class 10 SD card is defined as having at least 10MB/s sequential write performance. Since we already know these cards over-advertise their capacity, what is the performance like?

Card 1

Card 1

Card 1 makes it past the Class 10 specification, averaging a sequential write speed of 11.7MB/s using H2testw with a fresh FAT filesystem. Not great, but at least it’s within specifications.

Card 2

Card 2

Card 2 however, barely makes it past Class 4. With an average write speed of only 5.55MB/s, this card is just abysmal.

What about read speeds? Well, Amazon claims up to 48MB/s (megabytes per second) reading speed:

sandisk_48MBs_read

Card 1 managed a semi-respectable 18.2MB/s read speed. Card 2 however, was just awful and couldn’t give more than 7.2MB/s read speed.

Verdict:
Back to Amazon you go, shitty SanDisk SD cards. Next time I am going to buy Transcend, and from now on I’ll be testing any cards I buy to make sure they:
A) Are actually the advertised capacity
B) Meet the minimum specifications for their advertised Class
C) Can be read in all my devices, unlike these cards which wouldn’t read at all in my MacBook Pro

Testing method:
Both cards were tested in a Dell Venue 8 Pro running Windows 8.1.

I would have liked to have tested their raw speed using dd in Linux, but unfortunately my MacBook Pro would not read the cards at all! dmesg was full of SD sector and command errors when I put the cards in the reader.

Edit (26.07.2015): I bought Transcend cards from Amazon, and again they were not true 32GB cards. My old Transcend card was made in Taiwan, whereas all the “32GB” cards I have gotten from Amazon this year are made in China.

It makes me wonder if SanDisk and Transcend have licensed an ODM to produce cards for them, and then stuck their silk screen on the cards. I suspect this because both the SanDisk and Transcend cards I received identified themselves as SL32G cards, whereas my Taiwan manufactured Transcend identifies as USD.

For the time being, I have ceased to purchase 32GB microSDHC cards from Amazon until I can find a brand that sells a card that is actually 32GB.

From SATURN with love: a bad USB power supply

Recently I needed another USB charger for my devices. I went to Saturn and picked up this Innergie adapter, which is rated for 10W (2A at 5V).

innergie_front

innergie_rear

But, it doesn’t work. Sure, it can put out 2.5A, if you short it. I managed to get 0.6A out of it charging a 24Wh lithium-polymer battery, but at that current the voltage drops to 4.5V, which is outside of the USB specification and will not charge a mobile phone or tablet.

innergie_fluke_voltage_current

When I did plug in a mobile phone, it drew about 0.3A (1.5W) but the charging light did not turn on. The Innergie cannot even hold up at 1.5W, it dropped to 4.75V!

I lost the receipt, otherwise I would return it for my money back. So into the junk pile this goes… Lesson learned, next time save the receipt!

Installing CentOS 7 with a chroot

I needed to install CentOS 7 on an embedded PC with UEFI and 2 SSD disks in mdadm RAID1.

While I’m sure the guys at Red Hat work very hard on CentOS, the installer is a piece of cr*p, especially when it comes to disk partitioning. I have never hated any installer more than the CentOS disk partitioner. I don’t know what happened. The disk partitioning tool in CentOS 6 installer was fine, I had no problems using it, but in the 7 installer it’s just a nightmare to do anything. In my opinion Windows installer does a better job of disk partitioning than the CentOS 7 installer.

While many people who like CentOS will proclaim that the error is between the keyboard and chair, I welcome them to provide a write-up and screenshots of how to accomplish my desired partitioning scheme using the graphical installer. If the instructions are shorter than this blog post, next time I won’t use a chroot to install.

I loosely based my method off of this post, but immediately found I had to deviate because I didn’t have USB install media with all the required commands on it.

Required tools:
1) USB stick with some Linux distro on it (I prefer the Gentoo minimal installer, it’s small and it includes lots of useful utilities)
2) USB stick with the CentOS minimal installer on it
3) About 2GB of free space, you can use a ramdisk, or create an extra partition using the free space on the USB sticks (CentOS occupies about 800MB, Gentoo about 300MB)

Steps:
1) Boot the Gentoo installer off the USB stick
2) Partition your disks however you like using gdisk, fdisk, or parted
3) Create your mdadm array(s)
4) Plug in the CentOS 7 USB stick and mount it to a temporary mount point (e.g. /tmp/centos)

Inside the CentOS USB stick you will find LiveOS/squashfs.img, you need to loopback mount this:

livecd ~ # mount -o loop /tmp/cinstall/LiveOS/squashfs.img /tmp/csquashfs/

Now we have yet another image to mount, this one within the squashfs image:

livecd ~ # mount -o loop /tmp/csquashfs/LiveOS/rootfs.img /tmp/croot

Finally we have a Linux filesystem. But unfortunately we cannot use it for anything as it is mounted read-only and there is no resolv.conf present, so no domain names can be resolved. This is why you need ~2GB of free space somewhere (or 4GB of RAM).

livecd ~ # mkfs -q /dev/ram1 1572864
livecd ~ # mkdir -p /tmp/ramdisk
livecd ~ # mount /dev/ram1 /tmp/ramdisk
livecd ~ # rsync -avHp /tmp/croot /tmp/ramdisk

Now that we have the installer rootfs somewhere writable, copy /etc/resolv.conf to the filesystem:

livecd ~ # cp /etc/resolv.conf /tmp/ramdisk/etc/resolv.conf

Mount your destination partition for CentOS somewhere you can access from within the chroot:

livecd ~ # mount /dev/vg0/centos /tmp/ramdisk/mnt

Chroot to the installer environment:

livecd ~ # chroot /tmp/ramdisk

Download the CentOS release RPM and install it to the destination partition:

bash-4.2# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/centos-release-7-0.1406.el7.centos.2.3.x86_64.rpm
bash-4.2# rpm --root=/mnt --nodeps -i centos-release-7-0.1406.el7.centos.2.3.x86_64.rpm

Because yum is missing the yummain module in the installation environment, we need to download and install the yum RPM on the installer partition:

bash-4.2# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/yum-3.4.3-118.el7.centos.noarch.rpm
bash-4.2# rpm -i --nodeps yum-3.4.3-118.el7.centos.noarch.rpm

Now finally we can run yum on the destination partition to install CentOS:

bash-4.2# yum --installroot=/mnt update
bash-4.2# yum --installroot=/mnt install -y yum
bash-4.2# yum --installroot=/mnt install -y @core kernel
bash-4.2# yum --installroot=/mnt install -y grub2-efi efibootmgr lvm2 mdadm \
dosfstools kernel

Now unfortunately I hit a small snag: the Gentoo installer isn’t EFI aware. Exit the chroot, but remember to copy /etc/resolv.conf to the destination partition:

livecd ~ # cp /etc/resolv.conf /tmp/ramdisk/mnt/etc/

Poweroff and unplug the Gentoo installer USB stick. Plug in the CentOS installer stick and boot to the rescue environment. Skip rootfs detection.

Mount the partition/LV slice containing your CentOS installation:

sh-4.2# mkdir /mnt/centos
sh-4.2# mount /dev/vg0/centos /mnt/centos
sh-4.2# mount -t proc proc /mnt/centos/proc
sh-4.2# mount --rbind /dev /mnt/centos/dev
sh-4.2# mount --rbind /sys /mnt/centos/sys
sh-4.2# chroot /mnt/centos /bin/bash

Save the mdadm array information to the mdadm.conf configuration file:

bash-4.2# mdadm --detail --scan > /etc/mdadm.conf

Format your EFI boot partition:

bash-4.2# mkfs.vfat /dev/sda1
bash-4.2# mkdir /boot/efi
bash-4.2# mount /dev/sda1 /boot/efi

Install grub:

bash-4.2# grub2-install
Installing for x86_64-efi platform
...
Installation finished. No error reported.

Now, dear reader, this is the part where you do not see the hours I spent debugging why dracut would not find my root partition (hint: see Fedora wiki for dracut debugging steps). The tl;dr is that the mdadm array wasn’t being assembled, for reasons still unknown. To solve this we need to add our array UUID as an additional kernel parameter for grub:

bash-4.2# MD_UUID=$(mdadm -D /dev/md0 | grep UUID | awk '{print $3}')
bash-4.2# grubby --update-kernel=/boot/vmlinuz-3.10.0-123.20.1.el7.x86_64 \
--args="rd_MD_UUID=$MD_UUID"
bash-4.2# grub2-mkconfig -o /boot/grub2/grub.cfg

Absolutely verify in /boot/grub2/grub.cfg that the correct rd_MD_UUID was appended to linuxefi, or like me, you may be left wondering why your system won’t boot.

Check with efibootmgr that a menu entry was created:

bash-4.2# efibootmgr -v
...
Boot0014* grub  HD(1,800,32000,SUPER-LONG-UUID)File(\EFI\grub\grubx64.efi)

Don’t forget to set a root password:

bash-4.2# passwd
Changing password for user root.
New password:
Retype new password:
passwd: all authentication tokens updated successfully

Configuring the hostname (using hostnamectl, or editing /etc/sysconfig/network and /etc/hostname), udev rules for eth* interface names, and static network configuration in /etc/sysconfig/network-scripts/ifcfg-eth* is left as an exercise for the reader.

After rebooting

If when you reboot you find that you cannot login as root using the password you specified, it’s probably SELinux. Normally I hate disabling SELinux, but in this case I was so tired of spending a day and a half debugging booting issues, I just disabled it and went on with the setup.

Despite what the wonderful CentOS installer tells you, you do not require a separate /boot partition. Right now this is what the partition layout looks like:

Disk /dev/sda: 128.0 GB, 128035676160 bytes, 250069680 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: gpt


#         Start          End    Size  Type            Name
 1         2048       206847    100M  EFI System      EFI System
 2       206848    250069646  119.1G  Linux RAID      Linux RAID

Because the contents of /boot/efi is static, and cannot be mdraid, remember to copy the contents of /dev/sda1 to /dev/sdb1 so that if your first drive ever dies, you will still have the required EFI components to boot off the second drive.

Overall, I can’t say this was a lot of fun. But I did learn a lot more about dracut and the CentOS booting process, and I can still say with confidence that I hate the CentOS 7 installer.