My Cloud PR4100 / PR2100 Firmware Analysis


#109

I believe I’ve successfully reverse engineered the firmware binary file structure, except that I’m now having trouble determining exactly what method is used to generate checksums, which look like crc32, except that no checksum tool or method I’ve tried generates the same values.

Bypassing the firmware merge/upload process is trivial, except that I would rather make things easier, or is that too much to ask? Frankly, I’m getting sick of these stupid compiled binary roadblocks, which are strategically placed within the firmware to prevent it from being modified, or so it appears.

Either the firmware is GPL open source or it is not.


#110

Can you elaborate? I’ve tried several XOR methods to generate a matching checksum, but none worked. I suspect that the same checksum method may be used for the firmware header.


#111

checker.txt (549 Bytes)

Rename to .py and run it with python2.7
I forgot to remove the unused imports, if you lack any, just remove them.

Note that the WD tool adds the header in-place, so it’s best to make a copy of the original file.

I forgot my battery charger so I can’t go much deeper today. Maybe tomorrow :slight_smile:


#112

The WD merge program gets the firmware version from the following location within the firmware GPL source code file.

\WDMyCloud_PR4100_GPL_v10.30.165_20170321\firmware\module\crfs\default\config.xml

This little detail had been nagging me for some time, until I remembered the config.xml file. It doesn’t make much sense to alter the firmware without changing the version, so I decided to track it down.

There is also a config.xml file within the default.tar.gz file, but it’s not the right one. This config.xml file appears to be used as a backup or fallback for a system restore. If you see the following, you’re looking at the wrong config.xml file.

<sw_ver_1>2.21.111</sw_ver_1>
<sw_ver_2>2.21.111.0629.2016</sw_ver_2>
<hw_ver>MyCloudPR4100</hw_ver>
<model_number>BNFA</model_number>

The correct config.xml file location was confirmed by changing the firmware version before performing a complete firmware build. The repeating sequence of 9’s at the end were added to determine the exact length of it’s location within the firmware bin file header.

Before:

<sw_ver_1>2.30.165</sw_ver_1>
<sw_ver_2>2.30.165.0321.2017</sw_ver_2>
<hw_ver>MyCloudPR4100</hw_ver>
<model_number>BNFA</model_number>

After:

<sw_ver_1>10.30.165</sw_ver_1>
<sw_ver_2>10.30.165.0321.2017.9999.9999.9999.9999.9999.9999.9999.9999</sw_ver_2>
<hw_ver>MyCloudPR4100</hw_ver>
<model_number>BNFA</model_number>

Result:

kernel name = uImage
firmware name = WD-NAS-firmware
size of structure = 128
default path=../module/crfs/default/config.xml
Product     ID = 0
Custom      ID = 14
Model       ID = 7
Hardware    ID = 1
Sub         ID = 1
CH off 1 = 128
CH len 1 = 5800432
CH off 2 = 5800560
CH len 2 = 3860996
CH off 3 = 9661556
CH len 3 = 102950912
CH off 4 = 112612468
CH len 4 = 16220
alignment = 1 , file name:uRamdisk
alignment = 1 , file name:default.tar.gz
CH checksum 1 = B36E0F3D
CH checksum 2 = 21EC1FFB
CH checksum 3 = 622E000
CH checksum 4 = 4F316EC6
Next_offset = 0x06B693D0
#@#@#@#@ header_checksum = 0x6f51e0c0 #@#@#@#@
Directory = /tmp, Filename = grub.tgz
alignment = 3 , file name:grub.tgz
==========================================================
File Name: /tmp/grub.tgz
EX offset   = 0x06b69430
EX len      = 182872
EX checksum = 0x3adae984
Next_offset = 0x00000000
len = 51800
fw ver : 10.30.165.0321.2017.9999.9999.9999.9999.9999.9999.9999.9999

#113

The following image depicts what I’ve discovered about the WD My Cloud PR4100 Firmware bin file header. Items 13 and 15 are still a bit of a mystery, but the values (0x55, 0xAA) do offer some clues. Further research required…

My Cloud PR4100 Firmware Bin File Header Map


#115

The firmware build process is now fully automated, with the exception of the problems encountered while using the WD merge tool. After having tested it countless times, I’m now confident that the firmware build process is ready for prime time.

Attached is part 2 of the firmware build log, starting where the Linux kernel is compiled. The complete firmware build log is too big to upload as a text file, and for whatever reason, this forum does not allow zip files.

firmware_build_log_part_2.txt (2.5 MB)

Who wants to build some firmware?


#116

#117

ACPI Table Descriptions:

APIC (Multiple APIC Description Table)
CSRT (Core System Resources Table)
DSDT (Differentiated System Description Table)
FACP (Fixed ACPI Description Table)
FACS (Firmware ACPI Control Structure)
FIDT (Unknown)
FPDT (Firmware Performance Data Table)
LPIT (Low Power Idle Table)
MCFG (PCI Memory Mapped Configuration table)
SSDT1 (Unknown, Processor and Operating System Driver Capabilities)
SSDT2 (Unknown, Processor Throttling Control)
SSDT3 (Unknown, Processor Throttling Control)
SSDT4 (Unknown, Performance Control)
SSDT5 (Unknown, Performance Control)
UEFI (UEFI Boot Optimization Table)

Boot:

 # dmesg|grep APIC
[    0.000000] ACPI: APIC 0x00000000775FE998 000084 (v03 ALASKA A M I    01072009 AMI  00010013)
# dmesg|grep CSRT
[    0.000000] ACPI: CSRT 0x00000000775FF810 00014C (v00 INTEL  LANFORDC 00000005 MSFT 0100000D)
# dmesg|grep DSDT
[    0.000000] ACPI: DSDT 0x00000000775F4190 00A6F1 (v02 ALASKA A M I    01072009 INTL 20120913)
# dmesg|grep FACP
[    0.000000] ACPI: FACP 0x00000000775FE888 00010C (v05 ALASKA A M I    01072009 AMI  00010013)
# dmesg|grep FACS
[    0.000000] ACPI: FACS 0x0000000077684E80 000040
# dmesg|grep FIDT
[    0.000000] ACPI: FIDT 0x00000000775FEA68 00009C (v01 ALASKA A M I    01072009 AMI  00010013)
# dmesg|grep FPDT
[    0.000000] ACPI: FPDT 0x00000000775FEA20 000044 (v01 ALASKA A M I    01072009 AMI  00010013)
# dmesg|grep LPIT
[    0.000000] ACPI: LPIT 0x00000000775FF708 000104 (v01 ALASKA A M I    00000005 MSFT 0100000D)
# dmesg|grep MCFG
[    0.000000] ACPI: MCFG 0x00000000775FEB08 00003C (v01 ALASKA A M I    01072009 MSFT 00000097)
# dmesg|grep UEFI
[    0.000000] ACPI: UEFI 0x00000000775FF6C0 000042 (v01 ALASKA A M I    00000000      00000000)
# dmesg|grep SSDT1
# dmesg|grep SSDT2
# dmesg|grep SSDT3
# dmesg|grep SSDT4
# dmesg|grep SSDT5

Export:

# cat /sys/firmware/acpi/tables/APIC > /tmp/_apic.dat
# cat /sys/firmware/acpi/tables/CSRT > /tmp/_csrt.dat
# cat /sys/firmware/acpi/tables/DSDT > /tmp/_dsdt.dat
# cat /sys/firmware/acpi/tables/FACP > /tmp/_facp.dat
# cat /sys/firmware/acpi/tables/FACS > /tmp/_facs.dat
# cat /sys/firmware/acpi/tables/FIDT > /tmp/_fidt.dat
# cat /sys/firmware/acpi/tables/FPDT > /tmp/_fpdt.dat
# cat /sys/firmware/acpi/tables/LPIT > /tmp/_lpit.dat
# cat /sys/firmware/acpi/tables/MCFG > /tmp/_mcfg.dat
# cat /sys/firmware/acpi/tables/UEFI > /tmp/_uefi.dat
# cat /sys/firmware/acpi/tables/SSDT1 > /tmp/_ssdt1.dat
# cat /sys/firmware/acpi/tables/SSDT2 > /tmp/_ssdt2.dat
# cat /sys/firmware/acpi/tables/SSDT3 > /tmp/_ssdt3.dat
# cat /sys/firmware/acpi/tables/dynamic/SSDT4 > /tmp/_ssdt4.dat
# cat /sys/firmware/acpi/tables/dynamic/SSDT5 > /tmp/_ssdt5.dat

Specifications:

http://www.uefi.org/specifications
http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf

Linux ACPI Resources:

https://01.org/linux-acpi

Does ACPI control the fan on this system?

Virtually no desktops or servers use ACPI fan control. Instead, they use an embedded controller or other hardware on the motherboard that is independent of ACPI.

Note that sometimes you can view and control this hardware with BIOS SETUP. Some systems, for example, run all fans at maximum speed by default and require you to enable fan speed control in SETUP.

From Linux, you may be able to view and sometimes control native fan speed control with CONFIG_HWMON=y and the appropriate drivers sensors sub-system. Note, however, that some machines have conflicts between CONFIG_HWMON and CONFIG_ACPI because they may access the same underlying hardware using two different methods.

Most notebooks also use native fan control instead of ACPI. There are, however, a couple of notable exceptions: HP/Compaq, Acer, and Fujitsu-Siemens often use ACPI-based fan-control.

If /proc/acpi/fan is empty and /proc/acpi/thermal_zone/*/trip_points has no active trip points (those starting with “AC”) then there is no ACPI-based fan control on your system.

If you have dis-assembled the DSDT, you can also check if the device “PNP0C0B” is present. That is the standard identifier for a fan device.

From: https://01.org/linux-acpi/documentation/debug-how-isolate-linux-acpi-issues


#118

The following are most/all of the compiled binaries and shared libraries responsible for hardware control on the WD My Cloud PR4100 NAS. Why on Earth WD decided to make these closed-source is beyond me. It’s hardware for Pete’s sakes… What are they hiding?

Kernel Modules:

/usr/local/modules/opt/wd/kmodules/rstbtn.ko

Binaries:

/usr/local/modules/usrsbin/fan_control
/opt/wd/bin/wdhwutil
/opt/wd/bin/wdlcds
/opt/wd/bin/wdhws
/opt/wd/bin/wdtms
/opt/wd/bin/power_monitor
/usr/local/modules/usrsbin/up_send_ctl
/usr/local/modules/usrsbin/wdlcd_sub_init_info
/usr/local/modules/usrsbin/wdlcd_sub_daemon_ctl
/usr/local/modules/usrsbin/wdlcd_sub_daemon

Common Dependencies:

/opt/wd/lib/libwdhw.so.1
/opt/wd/lib/libthermal_management.so.1
/opt/wd/lib/libthermal_service.so.1
/opt/wd/lib/liblcd_management.so.1
/opt/wd/lib/boost/libboost_system.so.1.55.0
/opt/wd/lib/boost/libboost_thread.so.1.55.0
/opt/wd/lib/boost/libboost_filesystem.so.1.55.0
/opt/wd/lib/boost/libboost_regex.so.1.55.0

Config:

/opt/wd/bin/wdlcds -config=/etc/wd/sprite-lcd.xml
/opt/wd/bin/wdtms -config=/etc/wd/BNFA-thermal.xml
/opt/wd/bin/wdhws -config=/etc/wd/sprite-wdhw.xml
/opt/wd/bin/power_monitor -config=/etc/wd/sprite-power_monitor.xml

Binaries with Dependencies:

/usr/sbin/fan_control
/opt/wd/lib/libwdhw.so.1
/opt/wd/lib/libthermal_service.so.1
/opt/wd/lib/boost/libboost_system.so.1.55.0
/opt/wd/lib/boost/libboost_thread.so.1.55.0

/opt/wd/bin/wdtms
/opt/wd/lib/libthermal_management.so.1
/opt/wd/lib/boost/libboost_system.so.1.55.0
/opt/wd/lib/boost/libboost_thread.so.1.55.0

/opt/wd/bin/wdlcds
/opt/wd/lib/boost/libboost_system.so.1.55.0
/opt/wd/lib/boost/libboost_thread.so.1.55.0
/opt/wd/lib/boost/libboost_filesystem.so.1.55.0

/opt/wd/bin/wdhwutil
/opt/wd/lib/boost/libboost_system.so.1.55.0

/opt/wd/bin/wdhws
/opt/wd/lib/boost/libboost_system.so.1.55.0
/opt/wd/lib/boost/libboost_thread.so.1.55.0
/opt/wd/lib/boost/libboost_filesystem.so.1.55.0
/opt/wd/lib/boost/libboost_regex.so.1.55.0

/opt/wd/bin/power_monitor
/opt/wd/lib/libthermal_management.so.1
/opt/wd/lib/boost/libboost_system.so.1.55.0
/opt/wd/lib/boost/libboost_thread.so.1.55.0

/usr/local/modules/usrsbin/up_send_ctl
/opt/wd/lib/liblcd_management.so.1

/usr/local/modules/usrsbin/wdlcd_sub_init_info
/opt/wd/lib/liblcd_management.so.1
/opt/wd/lib/boost/libboost_system.so.1.55.0

/usr/local/modules/usrsbin/wdlcd_sub_daemon_ctl
/opt/wd/lib/liblcd_management.so.1
/opt/wd/lib/boost/libboost_system.so.1.55.0

/usr/local/modules/usrsbin/wdlcd_sub_daemon
/opt/wd/lib/liblcd_management.so.1
/opt/wd/lib/boost/libboost_system.so.1.55.0

#120

I’m now convinced that the STMicroelectronics 32-bit ARM Cortex MCU (STM32F030R8T6) found on the motherboard of the PR4100 is the key to gaining full hardware control. Previously, I allowed myself to become distracted by other potential possibilities, but now I believe I"m finally on the right path.

Fortunately, the STM32F030R8T6 chip seems to be quite common, and cheap development boards are widely available, thus making experimentation less risky than than forging ahead blindly on the actual PR4100 hardware. The chip appears to support debugging, where the keys to the kingdom may reside.

Currently, I know nothing about ARM programming, but it may be an interesting learning experience.
I simply have to learn how to communicate directly with the chip. Question is… where is the interface port located?


#121

How to Program and Develop with ARM Microcontrollers - Tutorial Series
From: https://newbiehack.com


#122

This one caused me a bit of a headache today. I was trying to mount image.cfs to grab some files for testing, but inadvertently added a space after the comma. It took a while to find it.

# Mount WD Root Filesystem
mount -t ext4 LABEL=wdnas_image.cfs /usr/local/tmp
mount -t squashfs -o loop,offset=2048 /usr/local/tmp/image.cfs /usr/local/modules

Good:
loop,offset=2048

Bad:
loop, offset=2048


#123

The following code, found in the system_init script, explains why the /dev/mmcblk0p7 (wdnas_reserve1) and /dev/mmcblk0p8 (wdnas_reserve2) eMMC flash partitions are not visible when booting the stock WD firmware.

# To protect from user _easily_ accessing reserved part7 and part8,
# we remove the device nodes.
# Anyone who want to access them must create the nodes itself.
for dn in `blkid | grep wdnas_reserve | awk -F ":" '{ print $1 }'`; do
	rm -f $dn
done

To recreate the missing eMMC block devices on the PR4100, execute the following commands.

# mknod /dev/mmcblk0p7 b 179 7
# mknod /dev/mmcblk0p8 b 179 8

To mount the recreated eMMC block devices, execute the following commands.

# mkdir /mnt/wdnas_reserve1
# mount /dev/mmcblk0p7 /mnt/wdnas_reserve1

# mkdir /mnt/wdnas_reserve2
# mount /dev/mmcblk0p8 /mnt/wdnas_reserve2

#124

The following code, found in the S14hwinit script, shows the i2c protocol being used for the reset button kernel module.

#!/bin/bash
insmod /opt/wd/kmodules/rstbtn.ko 2>/dev/null
mknod /dev/i2c-0 c 89 0 2>/dev/null

#125

Dump the entire eMMC flash device to a hex file.

# dd if=/dev/mmcblk0 of=/shares/Public/mmcblk0.bin

Dump the each eMMC flash partition to separate hex files.

# dd if=/dev/mmcblk0p1 of=/shares/Public/mmcblk0p1.bin
# dd if=/dev/mmcblk0p2 of=/shares/Public/mmcblk0p2.bin
# dd if=/dev/mmcblk0p3 of=/shares/Public/mmcblk0p3.bin
# dd if=/dev/mmcblk0p4 of=/shares/Public/mmcblk0p4.bin
# dd if=/dev/mmcblk0p5 of=/shares/Public/mmcblk0p5.bin
# dd if=/dev/mmcblk0p6 of=/shares/Public/mmcblk0p6.bin
# dd if=/dev/mmcblk0p7 of=/shares/Public/mmcblk0p7.bin
# dd if=/dev/mmcblk0p8 of=/shares/Public/mmcblk0p8.bin
# dd if=/dev/mmcblk0p9 of=/shares/Public/mmcblk0p9.bin

#126

Trying to control the hardware (fan, lcd display, leds, etc) has been more difficult that I had anticipated, so I’ve decided to try another approach. It’s a bit of a hack, plus it relies on closed-source WD binary files, but it will have to do until a better solution can be found.

After extensive research, and a bit of trial and error, I’ve managed to trace hardware control back to 4 shared library files. Various techniques were used to locate the correct functions/methods required by each. However, I still haven’t managed to locate the required arguments and corresponding types for all of them.

Using this method requires C/C++ programming to write small programs to pass arguments to the shared libraries, but it’s not too difficult to achieve.

liblcd_management.so.1

lcd_clear_all
lcd_clear_page
lcd_set_page
lcd_set_sleep_mode
lcd_set_weighted_page

libthermal_management.so.1

fan_has_rpm(int)
get_fan_rpm(int)
is_fan_active(int)
is_fan_functional(int)
decrement_fan_speed(int, int, int)
increment_fan_speed(int, int, int)
fan_controller_interface()
factory()

libthermal_service.so.1

fan_has_rpm
get_cpu_temperature
get_cpu_temperature_count
get_drive_count
get_drive_temperature
get_fan_count
get_fan_rpm
get_system_temp
is_fan_active
is_fan_functional

The following shared library file is particularly interesting because it appears to control everything, with the exception of the reset button, which appears to be loaded as a kernel driver (rstbtn.ko) module.

libwdhw.so.1

FindSMBusID(std::string const&, std::string const&, std::string&)
TryOpenSMBus(HWHandle*)
CheckBay(HWHandle*, int)
MapBay(HWHandle*, int)
HWGetCpuDTS(HWHandle*, int, _DTS_DATA*)
HWGetCPUTemperature(HWHandle*, int, float*)
HWInternalGetSysInfo(HWHandle*, _SYS_INFO*)
HWGetCPUDTSTemperature(HWHandle*, int, float*)
HWGetMemoryTemperature(HWHandle*, int, float*)
HWGetSystemTemperature(HWHandle*, int, float*)
HWGetChipsetTemperature(HWHandle*, int, float*)
HWGetRAIDControllerTemperature(HWHandle*, int, float*)
HWInternalGetCPUTemperature(int, int*)
CalculatePCHTemperature(unsigned char)
GetBoardId(unsigned int*)
ReadLineFromFile(char const*, char*, int)
iomem_read(unsigned long, unsigned int*)
iomem_write(unsigned long, unsigned int)
GetFileData(std::string const&, std::string&)
get_command_output(std::string const&)
is_good_c_string(char const*, int)
parse_wdhw_service_config()
has_parsed_wdhw_service_config()
IdentifyPMC()
OpenPCHThermal()
OpenLpc()
OpenPMC()
ClosePMC(void*)
OpenSMBus()

HWCancelWaitForButtonChange
HWCancelWaitForDriveBayChange
HWCancelWaitForReset
HWCloseHandle
HWGetDriveBayStatus
HWGetErrorString
HWGetFanRPM
HWGetFanStatus
HWGetLcdBacklit
HWGetLed
HWGetLedBlink
HWGetLedPulse
HWGetPMCVersion
HWGetPowerRestoreAction
HWGetPowerSupplyStatus
HWGetSysInfo
HWGetTemperature
HWOpenHandle
HWResetButtonHeldAtBoot
HWSetDriveBayPower
HWSetFanSpeed
HWSetLcd
HWSetLcdBacklit
HWSetLed
HWSetLedBlink
HWSetLedPulse
HWSetPowerRestoreAction
HWWaitForButtonChange
HWWaitForDriveBayChange
HWWaitForReset

#127

Similar section on the EX4100 as well, but don’t think it actually does anything.

# To protect from user _easily_ accessing reserved part7 and part8,
# we remove the device nodes.
# Anyone who want to access them must create the nodes itself.
for dn in `blkid | grep wdnas_reserve | awk -F ":" '{ print $1 }'`; do
        rm -f $dn
done

In /dev/ have the following devices:

root@WDMyCloudEX4100 /dev # ls -al mt* ubi*
crw-rw----    1 root     root       90,   0 Nov 15 06:47 mtd0
crw-rw----    1 root     root       90,   1 Nov 15 06:47 mtd0ro
crw-rw----    1 root     root       90,   2 Nov 15 06:47 mtd1
crw-rw----    1 root     root       90,   3 Nov 15 06:47 mtd1ro
crw-rw----    1 root     root       90,   4 Nov 15 06:47 mtd2
crw-rw----    1 root     root       90,   5 Nov 15 06:47 mtd2ro
crw-rw----    1 root     root       90,   6 Nov 15 06:47 mtd3
crw-rw----    1 root     root       90,   7 Nov 15 06:47 mtd3ro
crw-rw----    1 root     root       90,   8 Nov 15 06:47 mtd4
crw-rw----    1 root     root       90,   9 Nov 15 06:47 mtd4ro
crw-rw----    1 root     root       90,  10 Nov 15 06:47 mtd5
crw-rw----    1 root     root       90,  11 Nov 15 06:47 mtd5ro
crw-rw----    1 root     root       90,  13 Nov 15 06:47 mtd6ro
crw-rw----    1 root     root       90,  15 Nov 15 06:47 mtd7ro
brw-rw----    1 root     root       31,   0 Nov 15 06:47 mtdblock0
brw-rw----    1 root     root       31,   1 Nov 15 06:47 mtdblock1
brw-rw----    1 root     root       31,   2 Nov 15 06:47 mtdblock2
brw-rw----    1 root     root       31,   3 Nov 15 06:47 mtdblock3
brw-rw----    1 root     root       31,   4 Nov 15 06:47 mtdblock4
brw-rw----    1 root     root       31,   5 Nov 15 06:47 mtdblock5
brw-rw----    1 root     root       31,   6 Nov 15 06:47 mtdblock6
brw-rw----    1 root     root       31,   7 Nov 15 06:47 mtdblock7
crw-rw----    1 root     root      250,   0 Nov 15 06:48 ubi0
crw-rw----    1 root     root      250,   1 Nov 15 06:48 ubi0_0
crw-rw----    1 root     root      249,   0 Nov 15 06:48 ubi1
crw-rw----    1 root     root      249,   1 Nov 15 06:48 ubi1_0
crw-rw----    1 root     root      248,   0 Nov 15 06:48 ubi2
crw-rw----    1 root     root      248,   1 Nov 15 06:48 ubi2_0
crw-rw----    1 root     root       10,  60 Nov 15 06:47 ubi_ctrl

#128

The for loop finds and enumerates a list of block devices matching the string wdnas_reserve and the rm -f $dn command forces their removal from the /dev tree.

for dn in `blkid | grep wdnas_reserve | awk -F ":" '{ print $1 }'`; do
        rm -f $dn
done

The blkid command returns string containing a list of all block devices, and the grep command narrows down the list to block devices labeled wdnas_reserve. The wdnas_reserve devices are hidden after a normal boot process, so changing it to wdnas_ will return all block devices with matching labels. In this case, they are all eMMC flash partitions.

# blkid | grep wdnas_

/dev/mmcblk0p1: LABEL="wdnas_efi" UUID="9FE3-0940" TYPE="vfat" PARTLABEL="EFI System" PARTUUID="843f11b3-8959-464f-9481-d57ab38b4287"
/dev/mmcblk0p2: LABEL="wdnas_kernel" UUID="b5d6e030-cf55-4731-99e4-cbb2e5b771e2" TYPE="ext4" PARTLABEL="kernel" PARTUUID="30f4b3f3-8c9d-4e3d-a516-66dc8ca88fba"
/dev/mmcblk0p3: LABEL="wdnas_initramfs" UUID="5bab9bea-3650-4944-84ea-a6fc4ba3fdd0" TYPE="ext4"
/dev/mmcblk0p4: LABEL="wdnas_image.cfs" UUID="00035529-6b69-5fca-b0fd-cde0cd805a00" TYPE="ext4"
/dev/mmcblk0p5: LABEL="wdnas_rescue_fw" UUID="9c54a8c2-8055-407c-bab1-5985d107fb3a" TYPE="ext4"
/dev/mmcblk0p6: LABEL="wdnas_config" UUID="42eafe4c-2303-401e-b288-6cba67952ac9" TYPE="ext4"
/dev/mmcblk0p9: LABEL="wdnas_backup" UUID="45330f66-5e9f-4862-9053-6ba3461685be" TYPE="ext4"

The awk command splits the string returned by grep, using the colon “:” character as a separator. The '{print $1}' command tells awk which part of the string to return.

# blkid | grep wdnas_ | awk -F “:” '{print $1}'

/dev/mmcblk0p1
/dev/mmcblk0p2
/dev/mmcblk0p3
/dev/mmcblk0p4
/dev/mmcblk0p5
/dev/mmcblk0p6
/dev/mmcblk0p9

# blkid | grep wdnas_ | awk -F “:” '{print $2}'

 LABEL="wdnas_efi" UUID="9FE3-0940" TYPE="vfat" PARTLABEL="EFI System" PARTUUID="843f11b3-8959-464f-9481-d57ab38b4287"
 LABEL="wdnas_kernel" UUID="b5d6e030-cf55-4731-99e4-cbb2e5b771e2" TYPE="ext4" PARTLABEL="kernel" PARTUUID="30f4b3f3-8c9d-4e3d-a516-66dc8ca88fba"
 LABEL="wdnas_initramfs" UUID="5bab9bea-3650-4944-84ea-a6fc4ba3fdd0" TYPE="ext4"
 LABEL="wdnas_image.cfs" UUID="00035529-6b69-5fca-b0fd-cde0cd805a00" TYPE="ext4"
 LABEL="wdnas_rescue_fw" UUID="9c54a8c2-8055-407c-bab1-5985d107fb3a" TYPE="ext4"
 LABEL="wdnas_config" UUID="42eafe4c-2303-401e-b288-6cba67952ac9" TYPE="ext4"
 LABEL="wdnas_backup" UUID="45330f66-5e9f-4862-9053-6ba3461685be" TYPE="ext4"

The commands together in a for loop, which returns a list of all block devices with labels matching the wdnas_ string.

# for dn in `blkid | grep wdnas_ | awk -F ":" '{ print $1 }'`; do echo $dn; done

/dev/mmcblk0p1
/dev/mmcblk0p2
/dev/mmcblk0p3
/dev/mmcblk0p4
/dev/mmcblk0p5
/dev/mmcblk0p6
/dev/mmcblk0p9

#129

Taxing the hard drives too much is a valid concern, plus the My Cloud NAS devices typically have poor hardware (CPU, etc) specs, but I believe that 1% of the maximum speed is a bit too restrictive. While taxing the hard drives too much can cause problems, taxing them for too long can be just as bad. In other words, time is definitely a factor.

Considering the circumstances, I believe a speed of 10% to 50% of the maximum would strike a better balance between speed and reliability. And if the installed hard drives are all NAS drives, a speed of 50% to 75% of the maximum might be even better, assuming the hardware (CPU, etc) can handle it.

Maximum Possible Speed:

 (1000 / 100000) * 100  =  1% --> current default
(10000 / 100000) * 100  = 10%
(50000 / 100000) * 100  = 50%
(75000 / 100000) * 100  = 75%

Regardless, one is asking for trouble if they decide to use consumer-grade hard drives without TLER (Time Limited Error Recovery) in a NAS RAID array. That, and I believe that using RAID (especially software RAID) in a non-enterprise environment is generally a bad idea.


#130

@dswv42,

Let me clarify my post above. I don’t believe the command does anything because I don’t see labels defined on any of the remaining devices, so follows that they are probably not using labels at all. However, I just looked on my NAS and the “entware-ng” version of “blkid” produces the following:

root@WDMyCloudEX4100 root # blkid
/dev/dm-1: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1"
/dev/dm-0: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1"
/dev/md1: UUID="0ddbf58d-693a-4731-819d-2736d4a373e7"
/dev/loop1: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1"
/dev/sdd4: UUID="a084a048-6978-450e-a326-bd82ab81785a"
/dev/sdc4: UUID="cb05b2ed-2555-4ac0-a8c3-1fb38c952c10"
/dev/sdc2: UUID="0ddbf58d-693a-4731-819d-2736d4a373e7"
/dev/sdb4: UUID="35d44091-85fe-4f0a-8a0b-7f29d717c8da"
/dev/sdb2: UUID="5f42d319-6fb3-4ac0-b710-23292db2f778"
/dev/sda4: UUID="62e2a499-e3d8-4ce7-b67c-2b37a505fbcd"
/dev/ram0: UUID="42f62123-de52-447c-a5b9-335168f0f750"
/dev/mapper/docker-9:1-80347142-b0cf4a948d6e1744d31feab8a471a604cdc87583ff9b5d7fc676eed5e359f292: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1"
/dev/mapper/docker-9:1-80347142-pool: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1"

Here is the results from the stock version of blkid::

root@WDMyCloudEX4100 / # /usr/local/modules/bin/blkid
/dev/ubi2_0: UUID="21e2b22d-facd-45c6-a6b5-d2c4ed2d9201" TYPE="ubifs"
/dev/ubi1_0: UUID="7f2ffc37-f41c-4db4-a6db-0916da6130dd" TYPE="ubifs"
/dev/ubi0_0: UUID="0a896697-098b-48b8-9a65-39cc54496495" TYPE="ubifs"
/dev/loop0: TYPE="squashfs"
/dev/loop1: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1" TYPE="ext4"
/dev/sda1: UUID="fd2208cd-deed-8e53-fea7-3141da34f03c" TYPE="linux_raid_member" PARTLABEL="Linux swap" PARTUUID="62425411-2600-46ea-9c7f-50f41ace1ff7"
/dev/sda2: UUID="c1313c36-9e56-a51b-5092-13c3fee1bf24" UUID_SUB="ce102707-dba4-065a-64d7-ea9e44e1da5a" LABEL="1" TYPE="linux_raid_member" PARTLABEL="Microsoft basic data" PARTUUID="453fb6fb-9246-4773-b03e-4519b60f2b39"
/dev/sda4: UUID="62e2a499-e3d8-4ce7-b67c-2b37a505fbcd" TYPE="ext4"
/dev/sdb1: UUID="fd2208cd-deed-8e53-fea7-3141da34f03c" TYPE="linux_raid_member" PARTLABEL="Linux swap" PARTUUID="64e425f3-c936-4301-8fe1-aaad5de10486"
/dev/sdb2: UUID="c1313c36-9e56-a51b-5092-13c3fee1bf24" UUID_SUB="18145e0e-44c5-5571-c750-f01e6b8832e2" LABEL="1" TYPE="linux_raid_member" PARTLABEL="Microsoft basic data" PARTUUID="12426d19-8608-4cea-8f7d-f9299cc95d29"
/dev/sdb4: UUID="35d44091-85fe-4f0a-8a0b-7f29d717c8da" TYPE="ext4"
/dev/sdd1: UUID="fd2208cd-deed-8e53-fea7-3141da34f03c" TYPE="linux_raid_member" PARTLABEL="Linux swap" PARTUUID="e51a267e-f2be-4202-a3ef-ee338968350d"
/dev/sdd2: UUID="c1313c36-9e56-a51b-5092-13c3fee1bf24" UUID_SUB="ad6e31ff-4002-22b2-79a5-f66ca815ee1a" LABEL="1" TYPE="linux_raid_member" PARTLABEL="Microsoft basic data" PARTUUID="4074e139-fba8-466f-bb63-e6e01827b5d2"
/dev/sdd4: UUID="a084a048-6978-450e-a326-bd82ab81785a" TYPE="ext4"
/dev/sdc1: UUID="fd2208cd-deed-8e53-fea7-3141da34f03c" TYPE="linux_raid_member" PARTLABEL="Linux swap" PARTUUID="07a98576-7fee-4944-9464-42b1b93edd9b"
/dev/sdc2: UUID="c1313c36-9e56-a51b-5092-13c3fee1bf24" UUID_SUB="abb832fe-2b2d-6faa-f4b7-b696224cb8b0" LABEL="1" TYPE="linux_raid_member" PARTLABEL="Microsoft basic data" PARTUUID="28b5df5a-b06e-4509-a024-57e13fd59787"
/dev/sdc4: UUID="cb05b2ed-2555-4ac0-a8c3-1fb38c952c10" TYPE="ext4"
/dev/md0: UUID="d18442c4-1816-46f2-9efa-6ceb4d642da6" TYPE="swap"
/dev/md1: UUID="0ddbf58d-693a-4731-819d-2736d4a373e7" TYPE="ext4"
/dev/mapper/docker-9:1-80347142-pool: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1" TYPE="ext4"
/dev/mapper/docker-9:1-80347142-b0cf4a948d6e1744d31feab8a471a604cdc87583ff9b5d7fc676eed5e359f292: UUID="bc20761f-907d-4361-a348-6440dd0b5fa1" TYPE="ext4"

Cheers,

JediNite