SD memory card register decoder

This is a utility for decoding SD card registers. On Linux if you have a MMC type card reader (not USB) then you can get the register values with a command similar to:

cat /sys/block/mmcblkX/device/cid
cat /sys/block/mmcblkX/device/csd

Replace X with the number of your device (use lsblk). That will return the CID and CSD respectively. The CID contains identification information and the CSD contains the card interface specifications.

This decoder is based on the official specifications located here. No information is sent to this site about your CID or CSD. It is all decoded locally in your browser.

Other people have done work in this area like Dr Lui. See pages here and here. I hope to collaborate and build a bigger database.

The “Scrub CID” removes the serial number from a CID.

Enter hex:

Posted in Programming | Tagged , , | Leave a comment

applesmc-next: Battery charge thresholds for Linux on Apple hardware

This is a set of patches for the Linux kernel that enable changing the battery charge thresholds. This is useful for example to limit the charge to 80% to prolong the life of your battery if you leave the charger connected all the time.

The project on Github: https://github.com/c—/applesmc-next

Arch Linux AUR package: https://aur.archlinux.org/packages/applesmc-next-dkms

Posted in Programming | Tagged , , , | Leave a comment

Quick script for testing new drives

This script is for testing new drives. ALL DATA WILL BE ERASED

#!/bin/sh

if [ ! -e "$1" ]; then
   echo "usage: $0 <drive-path>"
   exit 127
else
   read -p "'$1' is going to be erased, type YES to continue: " ANS
   if [ "$ANS" != "YES" ]; then
      echo "Aborted"
      exit 127
   fi
fi

DRIVE="$1"

echo "Performing initial read-only test"
ERRORS=$(badblocks -s -v -e 1 -b 1048576 "$DRIVE")
if [ -n "$ERRORS" ]; then
   echo "First read test failed"
   exit 127
fi

CRYPT="$(basename "$DRIVE")_crypt"
KEY="$(mktemp)" ||
   { echo "mktemp failed"; exit 127; }

terminate() {
   sync
   cryptsetup close "$CRYPT" >/dev/null 2>&1
   rm -f "$KEY"
}

trap terminate EXIT

openssl rand 64 >> "$KEY" ||
   { echo "openssl failed"; exit 127; }

cryptsetup open --type=plain --cipher=aes-xts-plain64 --key-size=512 --key-file="$KEY" "$DRIVE" "$CRYPT" || 
   { echo "cryptsetup1 failed"; exit 127; }

echo "Writing data..."
dd if=/dev/zero of="/dev/mapper/$CRYPT" bs=1M status=progress oflag=direct

# the device won't close if it's still "in use"
sync; sync
sleep 5
sync; sync
cryptsetup close "$CRYPT"
sync; sync

cryptsetup open --type=plain --cipher=aes-xts-plain64 --key-size=512 --key-file="$KEY" "$DRIVE" "$CRYPT" ||
   { echo "cryptsetup2 failed"; exit 127; }

echo "Verifying data..."
badblocks -s -v -e 1 -b 1048576 -t 0 "/dev/mapper/$CRYPT" >/dev/null

Posted in Programming | Tagged , , , , , , | Leave a comment

3D-printed 4-in-3 HDD bay

Updated version 2: Fix the drive rail part STL.

This is a 4-in-3 hard drive cage with cooling fan. It fits four 3.5″ drives in to three 5.25″ slots. It can be used inside a standard PC case or on its own with no case.

I often need portable drive cages for moving drives around with built-in cooling so I designed this. It’s a compact rigid structure. I recommend printing it “face down” with infill for the first 7mm then no infill for the rest of it. I usually use a fast “draft” mode (0.3mm) for printing the cage faster since it doesn’t need to look nice.

The drives are held in place with small tool-less rails for easy drive swapping.

The drive rails can be tricky to print depending on your printer. I recommend printing them in “normal” orientation with the pins sticking out to the side. This requires a tiny amount of support material for the pins but will make them very strong. The Z axis accuracy of the printer and first layer is very important for the rails to fit the cage. They are suppose to be exactly 6.2mm wide (or “tall” on the print bed). This is critical for getting a good fit.

I know the fan is a bit of a pain to mount, requiring screws on the inside. I tried designing retainers that could be inserted from the front but they’re too small and thin to be printed on a FDM printer reliably.

Some notable points about this design:

  • This is a rigid structure that does not flex much and when a fan is mounted it’s even stronger.
  • The weight is distributed to the sides to prevent flexing.
  • The drive rails distribute the weight to the sides across a wide cross-section in the strongest direction of the plastic. Less chance of the plastic layers separating over time.
  • It is tool-less. No screws unless your PC case requires them. Not using screws also helps prevent the plastic from separating over time.
  • This will fit in PC cases that use shelves for the 5.25″ slots.
  • Active cooling directly attached via 120mm fan.

Note: This cage only works with drives that have 3 mounting holes on the sides.

This design is on printables as well.

Posted in Projects | Tagged , , , , | Leave a comment

Feit SEC3000/CAM “bricked”

Recently had to repair a bricked Fiet security camera. If too long of a WPA password is used it will cause a buffer overflow and the camera will crash which results in an endless boot-loop. There doesn’t appear to be a way to recover from this condition without getting serial access or access to the flash memory itself.

Fortunately on the main PCB there are serial connection points. A regular TTY-to-USB converter at 3.3V works. Beware when taking it apart. There is a plastic ring around the PIR sensor that needs to be removed first to get to some screws. It’s just snapped on and I used a spudger to free it. Only the two screws near the main body of the light need to be removed and the PIR sensors can be left in place if you want.

Once you have serial access then the boot process can be stopped to get to the U-Boot menu which will allow you to flash a custom root-fs that has a root password you know.

Warning: r8168#0 failed to set MAC address

set ethaddr = <NULL>
set ipaddr = <NULL>
set netmask = <NULL>
LIN003:Hit any key to stop autoboot:

I used the uboot commands to extract the entire flash memory over the serial port (took about 2 hours). This can be done with sf read 80000000 0 1000000 followed by md 80000000 400000. Note the memory display command is real flaky and may hang if you use a size it doesn’t like. It also displays hex with the endianess reversed so every 4 bytes have to be flipped around. Then the root-fs can be sliced out and extracted with unsquashfs. The root password can be created with mkpasswd -m md5crypt. Then recreate the squashfs, patch the filesystem binary with rootfs_tool.py, put the binary on the SD card, then use the fatload command to load it in to memory, then write it to flash with sf write.

During boot there is a second option to stop the boot process. Press q then you can log in as root.

mmcblk0: mmc0:59b4 USD00 118 GiB
 mmcblk0: p1
If you want to run app by yourself, please input q
=======================Press q -> Entry

The problem lies within the /mnt/mtd/aoni_ipc daemon that runs on the camera. This is a large master binary that handles all sorts of activities. I couldn’t find source code for it so I had to hack the binary itself. The problem lies in the Config_Read_String_Params function. When the WiFi configuration is read it uses two buffers. The first buffer is 300 bytes but the second one is only 68 bytes. The first buffer is copied to the second during processing. The configuration is base64 encoded so a standard 63-character WPA password will overflow the 68-byte buffer and cause a SEGFAULT.

To fix this issue I modified the binary so that WIFI_PWD is not base64 encoded. This way it will fit within the 68-byte buffer and WPA passwords are text anyway. Near the end of the binary is the WIFI_PWD string surrounded by a bunch of nulls. This is the table that determines which parameters are base64 encoded. I simply changed the string to WIFY_PWD so that when the camera checks to see if it needs to do base64 encoding it does not find WIFI_PWD.

002799f0  4e 65 74 00 00 00 00 00  00 00 00 00 00 00 00 00  |Net.............|
00279a00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00279a70  57 49 46 49 5f 50 57 44  00 00 00 00 00 00 00 00  |WIFI_PWD........|
00279a80  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

I also corrected a typo in the latest Feit firmware for the same aoni_ipc binary. It was trying to call ifocnfig instead of ifconfig.

Posted in Projects | Tagged , | Leave a comment

Adding a serial header to the Wyzecam V2

I have been meaning to try the open-source Intergenic bootloader for years and only just got around to it. This bootloader allows 1080p mode when using Dafang-Hacks. When messing with the bootloader it’s a good idea to have the serial connection ready for debugging or recovery so I added a header that is easy to plug on to. Also make sure to use the correct bootloader image.

In my case the first attempt didn’t work. I successfully flashed the bootloader but when the camera booted it hung looking for the root filesystem on the SD card.

[    1.663096] TCP: cubic registered
[    1.666583] NET: Registered protocol family 17
[    1.671298] Key type dns_resolver registered
[    1.676844] input: gpio-keys as /devices/platform/gpio-keys/input/input0
[    1.684078] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
[    1.692649] Waiting for root device /dev/mmcblk0p2...
[    1.815134] dwc2 dwc2:  ++OTG Interrupt: A-Device Timeout Change++
... Hang Forever ...

This was due to my uEnv.txt configuration which was set to boot off the SD card instead of NAND. I switched to the NAND uEnv.txt and the camera started fine.

Posted in Projects | Tagged | Leave a comment

Acer XC-1660G-UW93 mini desktop

I made a 3D printed block-off plate so I can remove the DVD drive.

Posted in Projects | Tagged | Leave a comment

QEMU/KVM GPU Passthrough

Was getting BSOD trying to pass through a 280X to Windows guest. Using an added PCIe root seems to fix it. Using the i440fx machine in QEMU also seems to fix the BSOD. I need to benchmark that against the PCIe with Q35.

Standard options for the various modes using Q35 QEMU machine:

BIOS Default:

-device vfio-pci,host=xx:00.0,multifunction=on,x-vga=xx,romfile=xx -device vfio-pci,host=xx:00.1

UEFI Default:

-bios /usr/share/ovmf/OVMF.fd -device vfio-pci,host=xx:00.0,multifunction=on,x-vga=xx,romfile=xx -device vfio-pci,host=xx:00.1

BIOS PCIe:

-device pcie-root-port,bus=pcie.0,id=pcie0 -device vfio-pci,host=xx:00.0,multifunction=on,bus=pcie0,x-vga=xx,romfile=xx -device vfio-pci,host=xx:00.1,bus=pcie0

UEFI PCIe:

-bios /usr/share/ovmf/OVMF.fd -device pcie-root-port,bus=pcie.0,id=pcie0 -device vfio-pci,host=xx:00.0,multifunction=on,bus=pcie0,x-vga=xx,romfile=xx -device vfio-pci,host=xx:00.1,bus=pcie0

HIS Radeon 280X Turbo Boost (romfile is stock VBIOS in position 1)

BootPCIx-vgaromfileDisplayResult
BIOSDefaultOffNononeNo display
BIOSDefaultOffNovmwareBSOD
BIOSDefaultOffYesnoneNo display
BIOSDefaultOffYesvmwareBSOD
BIOSDefaultOnNononeBoots to Windows login then BSOD
BIOSDefaultOnNovmwareNo display
BIOSDefaultOnYesnoneBoots to Windows login then BSOD
BIOSDefaultOnYesvmwareNo display
BIOSPCIeOffNononeNo display
BIOSPCIeOffNovmwareQEMU display first then QEMU+GPU after login
BIOSPCIeOffYesnoneNo display
BIOSPCIeOffYesvmwareQEMU display first then QEMU+GPU after login
BIOSPCIeOnNononeBoots to Windows login then BSOD
BIOSPCIeOnNovmwareQEMU display first then QEMU+GPU after login
BIOSPCIeOnYesnoneBoots to Windows login then BSOD
BIOSPCIeOnYesvmwareQEMU display first then QEMU+GPU after login
UEFIDefaultOffNononeGPU incorrect resolution
UEFIDefaultOffNovmwareQEMU display but GPU does not work
UEFIDefaultOffYesnoneGPU incorrect resolution
UEFIDefaultOffYesvmwareQEMU display but GPU does not work
UEFIDefaultOnNononeGPU incorrect resolution
UEFIDefaultOnNovmwareQEMU display but GPU does not work
UEFIDefaultOnYesnoneGPU incorrect resolution
UEFIDefaultOnYesvmwareQEMU display but GPU does not work
UEFIPCIeOffNononeWorks
UEFIPCIeOffNovmwareWorks; Primary display on GPU
UEFIPCIeOffYesnoneWorks
UEFIPCIeOffYesvmwareWorks; Primary display on GPU
UEFIPCIeOnNononeWorks
UEFIPCIeOnNovmwareWorks; Primary display on GPU
UEFIPCIeOnYesnoneWorks
UEFIPCIeOnYesvmwareWorks; Primary display on GPU

MSI nVidia GT1030 OC (romfile is supposed to be a newer version of the stock VBIOS but doesn’t say MSI inside so, unknown)

BootPCIx-vgaromfileDisplayResult
BIOSDefaultOffNononeNo display
BIOSDefaultOffNovmwareQEMU display first then QEMU+GPU after login
BIOSDefaultOffYesnoneNo display
BIOSDefaultOffYesvmwareQEMU display first then QEMU+GPU after login
BIOSDefaultOnNononeNo display
BIOSDefaultOnNovmwareBlack screen
BIOSDefaultOnYesnoneNo display
BIOSDefaultOnYesvmwareBlack screen
BIOSPCIeOffNononeNo display
BIOSPCIeOffNovmwareQEMU display first then QEMU+GPU after login
BIOSPCIeOffYesnoneNo display
BIOSPCIeOffYesvmwareQEMU display first then QEMU+GPU after login
BIOSPCIeOnNononeNo display
BIOSPCIeOnNovmwareQEMU display first then QEMU+GPU after login
BIOSPCIeOnYesnoneNo display
BIOSPCIeOnYesvmwareQEMU display first then QEMU+GPU after login
UEFIDefaultOffNononeWorks; Primary display on GPU
UEFIDefaultOffNovmwareWorks; Primary display on GPU
UEFIDefaultOffYesnoneBoots to Windows login then BSOD
UEFIDefaultOffYesvmwareBoots to Windows login then BSOD
UEFIDefaultOnNononeWorks
UEFIDefaultOnNovmwareWorks; Primary display on GPU
UEFIDefaultOnYesnoneBoots to Windows login then BSOD
UEFIDefaultOnYesvmwareBoots to Windows login then BSOD
UEFIPCIeOffNononeWorks
UEFIPCIeOffNovmwareWorks; Primary display on QEMU
UEFIPCIeOffYesnoneBoots to Windows login then BSOD
UEFIPCIeOffYesvmwareBoots to Windows login then BSOD
UEFIPCIeOnNononeWorks
UEFIPCIeOnNovmwareWorks; Primary display on QEMU
UEFIPCIeOnYesnoneBoots to Windows login then BSOD
UEFIPCIeOnYesvmwareBoots to Windows login then BSOD
Posted in Projects | Tagged , , , | Leave a comment

Forget WASD

WASD is the QWERTY of movement control.

What you want is ASZD. A: Forward — Z: Backwards — S: Left — D: Right

Less hand movement and stretching = better performance.

Keyboard
Posted in Tips | Leave a comment

Random phone IMEI calculator

Generate a fake random IMEI based on your real IMEI. This allows you to give your random IMEI to anyone without exposing your real IMEI. Useful for websites that decode the IMEI and display phone model information.

No information is sent to this site for this calculation. It’s all done in your browser locally. You only need to enter the first 8 digits.

Enter your IMEI:
Random IMEI: 000000000000000

How the IMEI is calculated.

Posted in Calculators | Tagged , | Leave a comment