How to Build Custom Firmware

This guide will demonstrate how to build custom firmware for the WD My Cloud PR4100 NAS. Much of the build process has been automated to make it easier, but this process should not be taken for granted. Things can wrong, often with little or no warning. Firmware modification and building packages are beyond the scope of this guide.

WARNING: THE FOLLOWING PROCEDURES MAY VOID YOUR WARRANTY OR BRICK YOUR NAS, USE EXTREME CAUTION AT ALL TIMES

BASIC LINUX SKILLS AND ROOT ACCESS VIA SSH ARE REQUIRED

The following instructions are based on the WD My Cloud PR4100 NAS firmware, but they may be applicable to other WD My Cloud models, possibly with minor variations applied as required.

Download the firmware GPL source code from the following link and save it to your build computer. Currently WDMyCloud_PR4100_GPL_v2.30.165_20170321.tar.gz is the latest firmware version.

WARNING: The firmware ABSOLUTELY must be built on a Linux ext4 formatted partition, or the firmware will appear to function correctly, when in fact it does not.

Copy the following firmware build script (custom_firmware.sh) into a text editor and save it to your computer. Within the script, change SOURCE_FILE_BASE_NAME to match the path/name of the firmware GPL source code file previously downloaded.

#!/bin/bash

# Must run as root (sudo su).
# ./custom_firmware.sh |& tee build_log.txt

# Change path/file to match firmware location.
# Do not include file extension (expects .tar.gz).

SOURCE_FILE_BASE_NAME="WDMyCloud_PR4100_GPL_v2.30.165_20170321"

echo "INSTALL PACKAGES *****************************************************************************************"
apt-get update
apt-get install -y build-essential binutils gcc-multilib g++-multilib lib32gcc1 lib32ncurses5 lib32z1 git
apt-get install -y autoconf libtool pkg-config libncurses-dev
echo ""

echo "EXTRACT SOURCECODE *****************************************************************************************"
rm -rf ${SOURCE_FILE_BASE_NAME}
tar zxvf ${SOURCE_FILE_BASE_NAME}.tar.gz
cd ${SOURCE_FILE_BASE_NAME}
echo ""

echo "GIT ********************************************************************************************************"
git init
echo ""

echo "INSTALL TOOLCHAIN ******************************************************************************************"
cd toolchain
tar zxvf x86_64-intel-linux-gnu-WD-00.02B-04272014.1721.tar.gz
source source.me
echo ""

echo "BUILD KERNEL ***********************************************************************************************"
cd $HOME_DIR/kernel
tar zxvf linux-4.1.13.tar.gz
tar zxvf netatop-0.6.tar.gz
cd linux-4.1.13
./xbuild.sh clean
./xbuild.sh build
./xbuild.sh install
echo ""

# Compensate for broken install method of xbuild.sh which does not copy newly built uImage file.
echo "MOVE KERNEL (uImage) ***************************************************************************************"
mv -vf uImage ${ROOTDIR}/merge/
echo ""

echo "CREATE RAMDISK (initramfs) *********************************************************************************"
cd $HOME_DIR/firmware/ramdisk
./create_ramdisk.sh
mv -vf uRamdisk ../merge/
echo ""

echo "CREATE IMAGE.CFS *******************************************************************************************"
cd $HOME_DIR/firmware/module
./create_image.sh
mv -vf image.cfs ../merge/image.cfs
echo ""

###############################################################################################################
# WARNING: WD merge program produces invalid firmware, resulting in a corrupt uRamdisk (initramfs) on the NAS.
###############################################################################################################

# echo "MERGE PROCESS **********************************************************************************************"
cd $HOME_DIR/firmware/merge
# ./merge
echo ""

echo "MOVE FILES *************************************************************************************************"
# mv -vf WD-NAS-firmware ../../../WD-NAS-firmware.bin
mv -vf uImage ../../../uImage
mv -vf uRamdisk ../../../uRamdisk
mv -vf image.cfs ../../../image.cfs
mv -vf grub.tgz ../../../grub.tgz
mv -vf default.tar.gz ../../../default.tar.gz
cd ../../../
rm -rf ${SOURCE_FILE_BASE_NAME}

CAUTION: Do not build the firmware using a virtual environment. A real Linux environment must be used, or unpredictable problems may arise. My personal preference is to use an uBuntu live ISO image to create a bootable USB flash drive. This ensures that the build computer boots to a clean build environment every time. Also, the build computer must use an x86_64 architecture.

On the build computer… become root (sudo su), then make the custom firmware build script executable and run it. The script is intended to run on a live ISO Linux environment. If running it on a static Linux installation, the required packages (in the script) should be installed, then commented out of the script so they don’t install every time the script is executed.

# chmod +x custom_firmware.sh
# ./custom_firmware.sh |& tee build_log.txt

After the firmware has finished building, review the build_log.txt file, located in the same directory as the build script. A few warning messages are normal, but if any unusual errors are encountered… STOP!

Attached is part 2 of a successful 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)

The following build errors or warning messages are normal, and should be no cause for concern.

Copy Error (build script compensates, caused by broken xbuild script install method):

cp: cannot create regular file ‘/Build/WDMyCloud_PR4100_GPL_v10.30.165_20170321/toolchain/…/firmware/merge/WDMyCloud/bzImage’: No such file or directory
cp: cannot create regular file ‘/Build/WDMyCloud_PR4100_GPL_v10.30.165_20170321/toolchain/…/firmware/merge/WDMyCloud/’: Not a directory

Git Error (ignore, originates in xbuild script):

fatal: Needed a single revision

Kernel Module Signing (ignore or install certs):

No X.509 certificates found

Unresolved (ignore, probably a bug):

drivers/target/target_core_pr.c: In function 'core_scsi3_pr_seq_non_holder:
drivers/target/target_core_pr.c:332:3: warning: ‘return’ with no value, in function returning non-void [-Wreturn-type]
return;

WARNING: Do NOT use the WD merge tool, included with the WD My cloud firmware GPL source code files. The WD-NAS-firmware file that it generates WILL BRICK YOUR NAS!

For the time being, the required files must be manually copied to the NAS.

Insert a fat32 formatted USB flash drive into the build computer and copy the newly created uImage, uRamdisk, and image.cfs files to it. If required, also copy the grub.tgz file to it. Installing the GRUB bootloader is optional, unless it’s configuration must be changed to accomodate a new firmware version and/or build. The default.tar.gz file is normally not required.

Remove the USB flash drive and insert it into the NAS, then establish an SSH connection and navigate to the USB flash drive. The USB path may vary, but it should resemble /mnt/USB/USB3_c1 or something similar. Change the paths below starting with /mnt/USB to match the path to the USB flash drive where the required files are located.

Create Temp Directory:

# mkdir /tmp/wdnas_temp

GRUB Bootloader (wdnas_efi):

# tar -xvzf /mnt/USB/USB3_c1/grub.tgz
# mount /dev/mmcblk0p1 /tmp/wdnas_temp
# cp -rf /mnt/USB/USB3_c1/grub/EFI /tmp/wdnas_temp
# umount /tmp/wdnas_temp

Linux Kernel (wdnas_kernel):

# mount /dev/mmcblk0p2 /tmp/wdnas_temp
# cp -f /mnt/USB/USB3_c1/uImage /tmp/wdnas_temp
# umount /tmp/wdnas_temp

Initial RAM Filesystem (wdnas_initramfs):

# mount /dev/mmcblk0p3 /tmp/wdnas_temp
# cp -f /mnt/USB/USB3_c1/uRamdisk /tmp/wdnas_temp
# umount /tmp/wdnas_temp

Root Filesystem (wdnas_image.cfs):

# mount /dev/mmcblk0p4 /tmp/wdnas_temp
# cp -f /mnt/USB/USB3_c1/image.cfs /tmp/wdnas_temp
# umount /tmp/wdnas_temp

At this point, the custom firmware build is installed and ready to be tested, but the NAS must be rebooted for it to run. The build process has been extensively tested, but many unpredictable variables can cause things to go wrong. If this should happen, the following guides may be helpful.
.


1 Like

Have you changed anything on the kernel? When I built the kernel as it’s, attaching USB freezed the NAS. It turns out “uas” needs to be disabled.
Thanks,

This process can be done within NAS using docker although not as quickly as PC.
I successfully build using “32bit/debian” image.

You can change kernel features. For example, I added overlayfs for Docker.
Can you please test whether usbcore - uas is enabled?

On my download of GPL source code, it’s enabled, but it’s disabled on original firmware.

Got it.
It seems to me GPL source code is from previous firmware. This USB freezing (this is fixed in this firmware) and the default.tar.gz file you mentioned are two things that result me to think it.

From your log:

The kernel you build is not copied to merge folder,

‘uImage’ -> ‘/Build/WDMyCloud_PR4100_GPL_v2.30.165_20170321/toolchain/…/firmware/merge/WDMyCloud/’
cp: cannot create regular file ‘/Build/WDMyCloud_PR4100_GPL_v2.30.165_20170321/toolchain/…/firmware/merge/WDMyCloud/’: Not a directory

UAS is enabled.
" CC drivers/usb/storage/uas.o"