Install Debian on WD My Cloud home

Of course. I wonder why the original was deleted. Does the recipe not work anymore…?

Thanks Alex, that at least shows it won’t be so easy.

Would you mind sharing some details ?
Which rescue image did you use, and which partition did you have to mount to replace that file ?

Since some of the apps are now running in docker images I wondered if the console instance might not also be in a wrapper or jail of some kind.

Hey @bigdude , have a look here New software - #59 by Alex-N

The update writes to either sda19 or sda20 (SYSTEM_A or SYSTEM_B) depending on your current bootConfig. There is a image.cfs which contains a SQASHFS filesystem and is loop mounted to /usr/local/modules.
If you look at the rootfs, there are plenty of links to that part of the filesystem.

For a quick look you can open image.cfs in 7zip otherwise you’ll have to use unsquashfs.

I already tried enabling everything for remote SSH access New software - #49 by Alex-N but there is a fw_verify command in system_init which requires some certificate whihch we don’t have :frowning:

Since none of the system directories are R/W, you’d have to modify the ROOT_FS or image.cfs

I’m glad there will be some more eyes looking into this now :slight_smile:


As for the rescue image, I used the “original” Russian rescue rootfs and commented out all the image installation steps. That way I can use it from telnet or serial for new software inspection :wink:

For some reason that rescue image would not boot for me even though I have used it in the past. I did discover something odd and interesting though. Apparently when WD deployed the upgrade to the newer version they left the older image in place on the eMMC (I assume it’s in one of the ‘fallow’ partitions).

I looked through the U-Boot code and found that if you have a console connection and press the esc key you reach the U-Boot console which accepts a number of variations of the go command. In the source I saw that ‘go r’ tells the system to boot from the Flash based recovery image, so I decided to try that to see what I got.

Instead of a recovery image I found it loaded the complete preceding version of the MCHD firmware which still had an unlocked console (and a public share). All of the applets executed fine, but the new SMB share configuration was gone and the console was unlocked… It doesn’t really help with unlocking the new image, but I thought others might find it a curious alternative to using a Flash image.

If you decide to try it be warned that the changes in filesystems do force ext2fs and maybe some of the update scripts to be re-run when you reboot to the newer firmware, so that return to the newer version is a fairly slow reboot with lots of disk activity.

EDIT: Do this at your own risk, testing shows go r swaps back and forth between image A and image B. The problem is it disables local network access and then it cannot be re-enabled manually, but after a while it re-enabled local access on its own. This is a bit quirky CAVEAT EMPTOR

I am not familiar with the MCHD as I only have a few MCH. I assume the “firmware” partitions are in eMMC for MCHD while they are on disk for the MCH.

Anyways, I went a different route and disabled the fw_verify in the system_init found under /scripts/ in the image.cfs (New software - #41 by zeusjan)

You just have to make sure to replace the correct image.cfs as there are two paritions holding the last two fw updates (for MCH its /dev/sataa19 and /dev/sataa20).
The partition with the most recent change date is the one the device is probably currently using.

I took the sshd from Debian Bullseye for aarch64 (ARM). The public key has to use ed25519 .

I am now logged on via SSH. Here is the reason why you’re being asked for a password over Serial:

cat /etc/inittab
# This is run first except when booting in single-user mode.

# /bin/sh invocations on selected ttys
# Must be first 'respawn' entries to avoid ^C problem
# Start a shell on the console

#ttyS0::respawn:/sbin/getty 115200 ttyS0
#tty2::respawn:/sbin/getty 9600 tty2

# Start an "askfirst" shell on /dev/ttyS1


Is there a guide to upgrade the kernel from 4.1.17 to 5.x somewhere?

MCH and MCHD are very similar. If you looked through the source for MCH (Monarch), you’ll see conditional scripts selecting Monarch or Pelican because they use a common source tree. (Monarch is MCH, Pelican is MCHD). The partition maps differ a bit from what I see in the code the config lives on sata in one eMMC in the other so they are similar but not identical.

I only got the source tree a short while ago because it was on one of WD’s international sites… I was just thinking of checking the init scripts but you beat me to it…

There is also a check made during bootup for the presence of sshd and a cert on the USB drive, it looks like you can load those without altering the image, but I have yet to test it. That is probably in the init script somewhere. Could you look and see what the cert file name needs to be ?

I linked the part of the system_init where the ssh enabling takes place New software - #41 by zeusjan

This is part of the current firmware (image.cfs) and can’t be found in the sources (they are rather useful for UBoot documentation).

We cannot create the required certificate ourselves. The fw_verify used to check the certificate is a Go program.
I tried looking for certs during the OTA but there are none.
And the more I think about it, the more likely some checksum of the sshd binary went into creating the cert. Hence we can’t simply use any cert we might find.

For now I recreated the SquashFs image and disabled the fw_verify in it.


hey guys,

I have 2 MCH units, both with UART cable attached. on one I get the root prompt on the other one I’m being asked the password. as far as I can see from the bootlog this is one diff:

on the unit I get the password prompt:

Info: Try to add new node /factory...
factory {
        bootstate = "3";
        bna = "0";
        nbr = "B";
        cbr = "B";
        ver = "4.1.4";
        serial = "****";
        ipaddr = "";
        ethaddr = "****";

on the other unit where I get root prompt:

Info: Try to add new node /factory...
factory {
        bootstate = "0";
        bna = "0";
        nbr = "F";
        cbr = "B";
        ver = "4.1.4";
        serial = "*****";
        ipaddr = "";
        ethaddr = "****";

on the one I have root prompt I can see:

# cat /wd_config/bootConfig

if I do env print from the Realtek prompt, I have nbr=B on both units.

how cold I get the root prompt on the other one as well? is there a way to achieve it from the Realtek> prompt?

By reading cmd_boot.c from the bootloader source it looks like your current config loads the previous firmware, hence the passwordless prompt.

NextBootRegion (NBR) and CurrentBootRegion (CBR) should probably not be the same :slight_smile:

Your BootState is “3” = BOOT_STATE_OTA_PASSED

typedef enum{

gBootConfig is actually read from disc/MMC - the contents of bootConfig

static int wd_read_boot_config(void)
	char cmdBuf[128];
	volatile unsigned int addr = 0x4000000;

	char str_bstate[2] = {0 ,'\0'};
	char str_nbr[2] = {0 ,'\0'};
	char str_bna[2] = {0 ,'\0'};

	char readBuf[10];
	memset(cmdBuf, 0, sizeof(cmdBuf));
	memset(readBuf, 0, sizeof(readBuf));
	sprintf(cmdBuf, "fatload sata 0:12 0x4000000 %s 10", BOOT_CONFIG_FILE_NAME);    
	sprintf(cmdBuf, "fatload mmc 0:1 0x4000000 %s 10", BOOT_CONFIG_FILE_NAME);
		printf("\n[INFO]: OTA passed, boot NBR and update CBR\n");
        // Ok, the last nbr boot is sucessful, update the cbr
        if (update_cbr_from_nbr() == -1) {
            printf("[ERR]: %s return failure.\n", __func__);
        // Set bootState to BOOT_STATE_NO_OTA for next boot
        gBootConfig.bState = BOOT_STATE_NO_OTA;
        // write a invalid nbr here, to make sure next OTA has the right value
        // written to it
        gBootConfig.nextBootRegion = 'F';
        updateBootConfig = 1;

Next cbr gets the value of your nbr

static int update_cbr_from_nbr(void)
    char nbr[2] = { 0 ,'\0'};
    // update the cbr with valid nbr only
    if (gBootConfig.nextBootRegion == 'A' ||
        gBootConfig.nextBootRegion == 'B') {
        nbr[0] = gBootConfig.nextBootRegion;
        setenv("cbr", nbr);
		if (run_command("env save", 0) != 0) {
		    printf("Failed to write cbr to uboot env, exit\n");
		    return -1;
    }else return -1;

    return 0;

Finally the boot decision is made according to cbr (= ‘B’) = B image

static int wd_boot_cbr(void)
	char *cbr = NULL;
	cbr = getenv("cbr");
	if(cbr != NULL)	{
		if( strncmp(cbr, "A", 1 ) == 0 ){
		// set the boot_mode
			boot_mode = BOOT_NORMAL_MODE;		// A image
		} else if( strncmp(cbr, "B", 1 ) == 0 )	{
			boot_mode = BOOT_RESCUE_MODE;		// B image
		}else {
			printf("[FATAL ERROR] Invalid CBR(%s) from uboot env, boot USB rescue mode.", cbr);
			gUSB_MODE = 1;
			return -1;
	}else {	//unknown cbr
		printf("[FATAL ERROR] CBR not found, boot USB rescue mode.\n");
		gUSB_MODE = 1;
		return -1;

	return 0;

I guess your “A image” got updated, on MCH that should be /dev/sda19 and you’re still booting from /dev/sda20 - try mounting both and compare timestamps.

This is actually great if you don’t want automatic updates.

I wonder why your bootConfig reads something different though.
The only thing I can think of is that your /factory/env.txt overrides the bootConfig.

Some time ago I figured out how to read the /factory/env.txt, I didn’t dare to change it yet as this is part of the flash :smiley:

cd /
dd if=/dev/mtd0 bs=1 count=9216 skip=98304 | tar x
cat /tmp/factory/env.txt


I might have written a lot of bullsh*t above :frowning:
cmd_boot.c actually reads all bootConfig from disk. I don’t know how the uBoot factory env comes into play here…


thanks a lot for the in depth answer. where do you read the uboot source code? I cannot find these functions here.
Interestingly even on the device I get the root prompt, /bin/login is called in inittab:

root@MyCloud-7PC8HS  # grep -v ^# /etc/inittab

is there a way to boot into single-user mode from uboot?

also there’s this wdpp wd boot partition tool command, tried to set it to A, but env print still reports both cbr and nbr as B.

Realtek> wdpp get
=== wdpp_get ===
GPT: first_usable_lba: 0x0000000000000022
GPT: last_usable_lba:  0x00000002BAA0F4AB
GPT: last lba:         0x00000002BAA0F4B0
alloc_read_gpt_entries: count = 128 * 128 = 16384
validate_gpt_entries 158: 0x29fcc8f8 vs 0x29fcc8f8
get_partition_info_efi: start 0x6a000, size 0x10000, name CONFIG
        0   rtkfat32.txt
        2   current_pp

2 file(s), 0 dir(s)

GPT: first_usable_lba: 0x0000000000000022
GPT: last_usable_lba:  0x00000002BAA0F4AB
GPT: last lba:         0x00000002BAA0F4B0
alloc_read_gpt_entries: count = 128 * 128 = 16384
validate_gpt_entries 158: 0x29fcc8f8 vs 0x29fcc8f8
get_partition_info_efi: start 0x6a000, size 0x10000, name CONFIG
reading current_pp
Filesize: 2 bytes
2 bytes
Warning: read blknr 0x6a0aa but blkcnt is 0
Warning: read blknr 0x6a0aa but blkcnt is 0
Size: 2, got: 2

2 bytes read (take 16ms)
current_pp = A

hi did you revert to the original firmware? i’m trying but something went wrong now im in bootloop :weary:

The UBoot is part of the older GPL sources


Didn’t get a backup to try it. Did you use your backup?

Did you try downloading the Recovery from here Index of /wd/Cloud_Home/Recovery/?

At the very last you would need all the “GOLD_” partitions.

parted -l
Model: ATA WDC WD80EFAX-68L (scsi)
Disk /dev/sataa: 8002GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start      End           Size          File system     Name         Flags
 1      34s        2047s         2014s                         FW_TABLE     msftdata
 2      2048s      67583s        65536s                        KERNEL_A     msftdata
 3      67584s     133119s       65536s                        ROOTFS_A     msftdata
 4      133120s    198655s       65536s                        ROOTFS_B     msftdata
 5      198656s    200703s       2048s                         FDT_A        msftdata
 6      200704s    202751s       2048s                         FDT_B        msftdata
 7      202752s    210943s       8192s                         AFW_A        msftdata
 8      210944s    276479s       65536s                        KERNEL_B     msftdata
 9      276480s    342015s       65536s                        ROOTFS_GOLD  msftdata
10      342016s    344063s       2048s                         FDT_GOLD     msftdata
11      344064s    352255s       8192s                         AFW_B        msftdata
12      352256s    354303s       2048s                         BOOTCODE32   msftdata
13      354304s    356351s       2048s                         BOOTCODE64   msftdata
14      356352s    358399s       2048s                         BL31         msftdata
15      358400s    360447s       2048s                         BL32         msftdata
16      360448s    425983s       65536s                        KERNEL_GOLD  msftdata
17      425984s    434175s       8192s                         AFW_GOLD     msftdata
18      434176s    499711s       65536s        fat32           CONFIG       msftdata
19      499712s    2138111s      1638400s      ext4            SYSTEM_A     msftdata
20      2138112s   3776511s      1638400s      ext4            SYSTEM_B     msftdata
21      3776512s   5414911s      1638400s      ext4            CACHE        msftdata
22      5414912s   9609215s      4194304s      ext4            DATA         msftdata
23      9609216s   13803519s     4194304s      linux-swap(v1)  SWAP         msftdata
24      13803520s  15628053163s  15614249644s  ext4            DISKVOLUME1  msftdata

You can use the fwtablectl tool to recreate the correct checksums (GitHub - sgissi/wdmch-tools: Tools for WD My Cloud Home)

My original table (8TB) looked like this:

Firmware 1: GoldKernel RO:true Compressed:false Version: 0 Size: 12727296 (12727296 with padding) Disk Offset: 184549376 (sector 360448) Load Address: 0x03000000 Checksum: 0x4b610726
Firmware 2: GoldRescueDeviceTree RO:true Compressed:false Version: 0 Size: 61199 (61440 with padding) Disk Offset: 175112192 (sector 342016) Load Address: 0x01f00000 Checksum: 0x001eb5dc
Firmware 3: GoldRescueRootfs RO:true Compressed:false Version: 0 Size: 12582912 (12582912 with padding) Disk Offset: 141557760 (sector 276480) Load Address: 0x02200000 Checksum: 0x3fff93a7
Firmware 4: GoldAudio RO:true Compressed:false Version: 0 Size: 3243056 (3243520 with padding) Disk Offset: 218103808 (sector 425984) Load Address: 0x01b00000 Checksum: 0x0dd71a22
Firmware 5: uBoot RO:true Compressed:false Version: 0 Size: 0 (0 with padding) Disk Offset: 181403648 (sector 354304) Load Address: 0x00000000 Checksum: 0x00000000
Firmware 6: Kernel RO:true Compressed:false Version: 0 Size: 12710400 (12710400 with padding) Disk Offset: 1048576 (sector 2048) Load Address: 0x03000000 Checksum: 0x4b571cf5
Firmware 7: RescueDeviceTree RO:true Compressed:false Version: 0 Size: 62778 (62976 with padding) Disk Offset: 102760448 (sector 200704) Load Address: 0x01f00000 Checksum: 0x001ff85e
Firmware 8: KernelDeviceTree RO:true Compressed:false Version: 0 Size: 62778 (62976 with padding) Disk Offset: 101711872 (sector 198656) Load Address: 0x01f00000 Checksum: 0x001ff85e
Firmware 9: RescueRootFS RO:true Compressed:false Version: 0 Size: 4194304 (4194304 with padding) Disk Offset: 68157440 (sector 133120) Load Address: 0x02200000 Checksum: 0x0df89573
Firmware 10: KernelRootFS RO:true Compressed:false Version: 0 Size: 4194304 (4194304 with padding) Disk Offset: 34603008 (sector 67584) Load Address: 0x02200000 Checksum: 0x14169514
Firmware 11: Audio RO:true Compressed:false Version: 0 Size: 3243056 (3243520 with padding) Disk Offset: 103809024 (sector 202752) Load Address: 0x01b00000 Checksum: 0x0dd71a22
Firmware 12: RescueAudio RO:true Compressed:false Version: 0 Size: 3243056 (3243520 with padding) Disk Offset: 176160768 (sector 344064) Load Address: 0x01b00000 Checksum: 0x0dd71a22
Firmware 13: RescueKernel RO:true Compressed:false Version: 0 Size: 8983912 (8984064 with padding) Disk Offset: 108003328 (sector 210944) Load Address: 0x03000000 Checksum: 0x37f0c764


Would I need to crack open the case?

Can you boot into your system and open a remote shell? Then you should be all set:

  • Re-create the original partition layout
  • Write the *GOLD partitions to the proper locations on disk
  • Update the FWTable Checksums if they are any different
  • Write something like 5:B:2: into the bootConfig file on partition 18.
  • Reboot and hope for the best - just let it sit there for a while :slight_smile:

In case this doesn’t work you should still be able to re-Install OMV via USB method.
The USB method can always be used to inspect your system. If you don’t want to build your own rootfs, you could use the first Russian OMV installer and remove the 20-root.tar.gz… 22-usr.tar.gz files. This should boot you into a telnet shell, from where you can perform further actions.


Yep I can. Will give it a shot. Thanks :slight_smile:

One question. Where do I get the GOLD fw files?