Skip to Content

Seagate Personal Cloud (1/2)

This post is a rambling information dump of my journey of investigation into the innards of a Seagate Personal Cloud.

Background

I have been toying with the idea of buying a NAS, but was not keen on the idea of being stuck with software that was not to my liking. I wanted something I could choose to install Debian on, so I have full control of it.

I came across the instructions to install Debian on Seagate Personal Cloud, so I bought a 2nd hand Seagate Personal Cloud (4TB). The purchase took place in March 2018, and some preliminary investigation was done then. I am finally dusting off the project.

The Debian instructions outline how to get access to the U-Boot command line, and launch the Debian installer. At this point, it should be a fairly standard Debian install.

What made me pause the installation was the instructions include the following paragraph:

The Personal Cloud devices come with the Seagate NAS firmware pre-installed and there is no easy way to re-install the Seagate NAS firmware after you install Debian. We therefore suggest you create a disk image before you install Debian.

I wanted the capability to be able to revert to stock firmware, even if I never used it. It also suggests that if the disk dies, you can’t simply drop in a replacement.

The classic way to create a recovery image would be to extract the hard disk from the case, and use Clonezilla to image it. I abandoned that idea after finding a YouTube video (Russian) that showed the disk removal is possible, but would involve peeling off tape. I would investigate less intrusive methods first.

I decided that the approach I would use would be to launch the Debian Installer, and drop into a shell for investigation.


U-Boot

The first step was to connect to the U-Boot console using clunc as described in the ‘U-Boot access’ section of the Debian documentation.

I did get side-tracked creating a Python implementation of clunc after working out why the lacie-nas.org version no longer worked for me out of the box.

The first piece of information to be captured was the current U-Boot configuration. This will give clues about the device boots, and details that would need to be restored if uninstalling Debian.

I ran printenv to view the current variables. I knew from the installation instructions that bootcmd was an important setting, so I started there.

Here are some highlights from the full output.

bootcmd=run nexus_boot
nexus_boot=test -n ${resetFlag_env} && forced=${resetFlag_env}; for disk in ${disk_list}; do run disk_expand; echo Booting Nexus OS from disk ${disk}...; countfail=0; bootfail=0; user=0; if run nexus_load_flags; then run nexus_rescue_countfail && countfail=1; run nexus_set_root; kern_img=/boot/uImage; dtb_img=/boot/target.dtb; test -n $board_dtb && dtb_img=/boot/$board_dtb; run nexus_load_image || bootfail=1; run nexus_rescue_user && user=1; if run nexus_can_boot; then run nexus_inc_count; run nexus_save_flags; run nexus_bootargs; bootm ${kern_addr} - ${dtb_addr}; bootfail=1; fi; run nexus_boot_rescue; fi; done; bootfail=1; countfail=; user=;run nexus_panic
nexus_boot_part=2
nexus_boot_rescue=echo Booting Nexus rescue system from disk ${disk}...; root_part=2; kern_img=/rescue/uImage; dtb_img=/rescue/target.dtb; test -n $board_dtb && dtb_img=/rescue/$board_dtb; if run nexus_load_image; then if test -n ${panic}; then run nexus_uuid; setenv bootargs ${bootargs} root=UUID=${root_uuid}; else run nexus_bootargs; fi; run nexus_rescue_bootargs; bootm ${kern_addr} - ${dtb_addr}; fi
nexus_bootargs=run nexus_uuid; setenv bootargs ${console} boot=UUID=${boot_uuid} root=UUID=${root_uuid}
nexus_can_boot=test ${bootfail} -eq 0 -a ${countfail} -eq 0 -a ${forced} -eq 0 -a ${user} -eq 0
nexus_inc_count=if test ${boot_count} -eq 0; then setenv boot_count 1; elif test ${boot_count} -eq 1; then setenv boot_count 2; else setenv boot_count ${nexus_max_count}; fi
nexus_load_flags=ext2get ${disk_iface} ${disk_num}:${nexus_nv_part} /ubootenv boot_count saved_entry
nexus_load_image=ext2load ${disk_iface} ${disk_num}:${root_part} ${dtb_addr} ${dtb_img}; ext2load ${disk_iface} ${disk_num}:${root_part} ${kern_addr} ${kern_img} && iminfo ${kern_addr}
nexus_max_count=3
nexus_nv_part=3
nexus_panic=panic=1; for disk in ${disk_list}; do run disk_expand; run nexus_boot_rescue; done
nexus_rescue_bootargs=test -n ${bootfail} && setenv bootargs bootfail=${bootfail} ${bootargs}; test -n ${countfail} && setenv bootargs countfail=${countfail} ${bootargs}; test -n ${user} && setenv bootargs user=${user} ${bootargs}; test -n ${forced} && setenv bootargs forced=${forced} ${bootargs}
nexus_rescue_countfail=test ${boot_count} -ge ${nexus_max_count}
nexus_rescue_user=ext2get ${disk_iface} ${disk_num}:3 /ubootenv rescue && test ${rescue} -eq 1
nexus_save_flags=ext2set ${disk_iface} ${disk_num}:${nexus_nv_part} /ubootenv boot_count ${boot_count}
nexus_set_root=if test $saved_entry -eq 1; then root_part=5; else root_part=4; fi
nexus_uuid=ext2uuid ${disk_iface} ${disk_num}:${nexus_boot_part}; boot_uuid=${uuid}; ext2uuid ${disk_iface} ${disk_num}:${root_part}; root_uuid=${uuid}

From this I deduced the following:

  • performs rescue boot after 3 failed normal boot attempts
  • partition #2 is boot fs for both normal and rescue boot
  • partition #3 is used to hold non-volatile settings
    • boot_count - running count of boot attempts
    • saved_entry - select partition to use for root fs
    • rescue - perhaps user initiated reboot into rescue?
  • partition #4 or partition #5 is used as root fs for normal boot (dependent on “saved_entry”)
  • I suspect that “resetFlag_env” is set when the NAS boots with reset held in.

Booting Linux

The next step is to follow the instructions in ‘Loading Debian installer’. The installer boots with a different IP address (due to using a random MAC address). I found the IP used, and connected using SSH.

$ ssh installer@192.168.1.101

I saw the familiar Debian installer dialog with the the message “This is the network console for the Debian installer”. I could see from the the menu bar at the top that it uses Screen which means it is possible to switch between virtual terminals without launching a new SSH session (and installer).

Initially I just tried switching to an interactive shell, but I discovered a this point the hard disk has not been detected, and there are insufficient tools for the purposes of investigation. So I chose to use the Debian installer, but abandon installation before any updates were made.

I selected “Start installer (expert mode)", configured the mirror, and selected ‘buster’ as the Debian version. I then selected “Download installer components”, and selected the following components:

  • fdisk-udeb
  • lvmcfg
  • mdcfg

After that completed, I skipped down to “Detect disks” (leaving ‘usb-storage’ selected). It is now time for investigation, so I switched to one of the shell terminals using “Ctrl-a 2” (I could also have selected “Execute a shell”).


Partitions (I)

I used ‘fdisk’ to check the disk had been detected, and what the partitions were:

$ fdisk -l
Disk /dev/sda: 3.7 TiB, 4000787030016 bytes, 7814037168 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
Disklabel type: gpt
Disk identifier: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

Device       Start        End    Sectors  Size Type
/dev/sda1     2048       4095       2048    1M BIOS boot
/dev/sda2     4096     397311     393216  192M Linux filesystem
/dev/sda3   397312     399359       2048    1M Linux filesystem
/dev/sda4   399360    3545087    3145728  1.5G Linux RAID
/dev/sda5  3545088    6690815    3145728  1.5G Linux RAID
/dev/sda6  6690816    8787967    2097152    1G Linux RAID
/dev/sda7  8787968    9836543    1048576  512M Linux RAID
/dev/sda8  9836544 7814035455 7804198912  3.6T Linux RAID

We see that in addition to the partitions in the U-Boot configuration, we have partitions #1, #6, #7 and #8.

The disk uses GPT, and has a standard protective MBR partition.

$ fdisk -l -t dos
...
Device     Boot Start        End    Sectors Size Id Type
/dev/sda1           1 4294967295 4294967295   2T ee GPT

To examine the contents of a partition, I would create a directory as a mount-point, and then mount the filesystem read-only. For example:

~ # mkdir -p /mnt/sda2
~ # mount -r -t ext4 /dev/sda2 /mnt/sda2

I started by looking at the contents of partition ‘sda2’, which appeared to be the boot and rescue partition.

~ # ls -l /mnt/sda2
drwx------    2 root     root         12288 Nov 28  2014 lost+found
drwxr-xr-x    2 root     root          1024 Jul 13  2017 rescue
~ # ls -l /mnt/sda2/rescue
-rw-r--r--    1 root     root         11059 Oct 10  2014 armada-370-n090102.dtb
-rw-r--r--    1 root     root         11051 Oct 10  2014 armada-370-n090103.dtb
-rw-r--r--    1 root     root         12101 Oct 10  2014 armada-370-n090201.dtb
-rw-r--r--    1 root     root         11231 Oct 10  2014 armada-370-n090203.dtb
-rw-r--r--    1 root     root         13312 Oct 10  2014 armada-370-n090401.dtb
-rw-r--r--    1 root     root           669 Oct 10  2014 description.xml
-rw-r--r--    1 root     root           379 Jul 13  2017 nexus.map
-rw-r--r--    1 root     root      90198740 Jul 13  2017 product_image.tar.lzma
-rw-r--r--    1 root     root         11051 Oct 10  2014 target.dtb
lrwxrwxrwx    1 root     root            17 Nov 28  2014 uImage -> uImage_1.5.16-arm
-rw-r--r--    1 root     root      16113832 Oct 10  2014 uImage_1.5.16-arm
-rw-r--r--    1 root     root            48 Jul 13  2017 versions

This had the expected boot files (as referenced from U-Boot configuration), but also had the files description.xml, nexus.map, product.image.tar.lzma, and versions.

Three of these were small enough and contained text so I could view. The contents of the compressed tar file would have to wait.

The file descriptions.xml contains information consistent with the hardware. The hardware id matches the value in U-Boot setting board_dtb, and the SHA1 checksum matches the uImage file.

<rescue>
    <xml_version>1.0</xml_version>
    <device>
        <hardware>
            <arch>arm</arch>
            <subarch>armada</subarch>
            <id>n090103</id>
            <revision>1.0</revision>
        </hardware>
        <product_id>cumulus</product_id>
        <product_name>'Cumulus'</product_name>
        <vendor_id></vendor_id>
        <vendor_name>'Seagate'</vendor_name>
        <vendor_custom_id></vendor_custom_id>
    </device>
    <release_date>2014-10-10</release_date>
    <main>
        <rescue_version>1.5.16</rescue_version>
        <file>uImage</file>
        <sha1>a386942e67a508b74ac6a2b77a0043449ab7904c</sha1>
    </main>
</rescue>

The file nexus.map is a text representation of the partition table. This gives us clues about the newly discovered partitions. We have a BIOS boot partiton in sda1, temporary files in sda6, swap in sda7, and data in sda8.

# npart name        size(MiB) type  fstype     fsoption
  1     grub_core   1         ef02 
  2     boot_rescue 192       8300  ext2
  3     nv_data     1         8300  ext2
  4     root_1      1536      fd00  ext2
  5     root_2      1536      fd00  ext2
  6     var         1024      fd00  ext3
  7     swap        512       fd00  linux-swap
  8     user_data   0         fd00

The file ‘versions’ looks straightforward.

SOFTWARE_VERSION=4.3.15.1
RESCUE_VERSION=1.5.16

The partition ‘sda3’ is expected to hold non-volatile information used by U-Boot.

~ # ls -l /mnt/sda3
drwx------    2 root     root         12288 Nov 28  2014 lost+found
-rw-r--r--    1 root     root            32 Dec 27 11:42 ubootenv
-rw-r--r--    1 root     root           100 Nov 28  2014 uuid.cfg

Looking at the ubootenv file, I can see the strings boot_count and saved_entry which match references from the printenv above.

In addition, the file uuid.cfg holds the UUIDs for two file-systems. I suspect that these relate to the root file systems on sda4 and sda5.

rootfs1_uuid=c195e11f-ef59-4e64-984a-c18ab1ed7d0a
rootfs2_uuid=722a8e00-5e51-4f95-9571-b8dc53128040

RAID on a single disk?

It was time to investigate the partitions marked as RAID.

~ # mdadm --assemble --scan
mdadm: /dev/md/vg:8 has been started with 1 drive.
mdadm: /dev/md/(none):7 has been started with 1 drive.
mdadm: /dev/md/(none):6 has been started with 1 drive.
mdadm: /dev/md/(none):5 has been started with 1 drive.
mdadm: /dev/md/(none):4 has been started with 1 drive.

Following this, the contents of /proc/mdstat was:

Personalities : [raid1] 
md123 : active raid1 sda4[0]
      1572852 blocks super 1.0 [1/1] [U]
      
md124 : active raid1 sda5[0]
      1572852 blocks super 1.0 [1/1] [U]
      
md125 : active raid1 sda6[0]
      1048564 blocks super 1.0 [1/1] [U]
      
md126 : active raid1 sda7[0]
      524276 blocks super 1.0 [1/1] [U]
      
md127 : active raid1 sda8[0]
      3902099320 blocks super 1.0 [1/1] [U]
      
unused devices: <none>

So each of the partitions is a RAID-1 mirror containing only a single drive. I wasn’t even aware you could do that.

The Seagate Personal Cloud also comes in a 2-bay version, so I suspect the use of RAID is to allow the same firmware to be used in both variants.


Partitions (II)

With the RAID partitions activated, it is possible to dig a little deeper.

~ # blkid | grep /md
/dev/md127: UUID="S1IcAG-J4rq-lNuG-j9pO-2qdS-0Kxb-k3Fb1F" TYPE="LVM2_member"
/dev/md126: TYPE="swap"
/dev/md125: UUID="5c5ed39e-8759-407b-921c-3000e9cf35d3" SEC_TYPE="ext2" TYPE="ext3"
/dev/md124: UUID="722a8e00-5e51-4f95-9571-b8dc53128040" TYPE="ext2"
/dev/md123: UUID="c195e11f-ef59-4e64-984a-c18ab1ed7d0a" TYPE="ext2"

We have further confirmation from the UUID that md123 (sda4) and md124 (sda5) are the two 1.5 GiB root partitions, and that md125 (sda6) is the 512 MiB swap partition.

Looking at the root partitions:

~ # ls -l /mnt/md123
drwxr-xr-x    2 root     root          4096 Mar 24  2018 bin
drwxr-xr-x    2 root     root          4096 Mar 24  2018 boot
drwxrwxr-x    2 root     root          4096 Mar 24  2018 dev
drwxr-xr-x   57 root     root          4096 Mar 24  2018 etc
drwxr-xr-x    2 root     100           4096 Nov 17  2017 home
drwxr-xr-x    4 root     root          4096 Mar 24  2018 lacie
drwxr-xr-x    6 root     root          4096 Mar 24  2018 lib
lrwxrwxrwx    1 root     root            11 Mar 24  2018 linuxrc -> bin/busybox
drwx------    2 root     root         16384 Mar 24  2018 lost+found
drwxr-xr-x    2 root     root          4096 Nov 17  2017 media
drwxr-xr-x    2 root     root          4096 Nov 17  2017 mnt
drwxr-xr-x    2 root     root          4096 Nov 17  2017 opt
drwxr-xr-x    2 root     root          4096 Nov 17  2017 proc
drwxr-x---    2 root     root          4096 Mar 24  2018 root
lrwxrwxrwx    1 root     root             8 Mar 24  2018 run -> /var/run
drwxr-xr-x    2 root     root          4096 Mar 24  2018 rw
drwxr-xr-x    2 root     root          4096 Mar 24  2018 sbin
drwxr-xr-x    2 root     root          4096 Mar 24  2018 shares
drwxr-xr-x    2 root     root          4096 Nov 17  2017 sys
drwxrwxrwt    2 root     root          4096 Mar 24  2018 tmp
drwxr-xr-x   11 root     root          4096 Mar 24  2018 usr
drwxr-xr-x   16 root     root          4096 Mar 24  2018 var
drwxr-xr-x   12 root     root          4096 Mar 24  2018 www
~ # ls -l /mnt/md124
drwxr-xr-x    2 root     root          4096 Dec 27 11:22 bin
drwxr-xr-x    2 root     root          4096 Dec 27 11:22 boot
drwxrwxr-x    2 root     root          4096 Dec 27 11:22 dev
drwxr-xr-x   59 root     root          4096 Dec 27 11:22 etc
drwxr-xr-x    2 root     100           4096 Jan 17  2019 home
drwxr-xr-x    4 root     root          4096 Dec 27 11:22 lacie
drwxr-xr-x    7 root     root          4096 Dec 27 11:22 lib
lrwxrwxrwx    1 root     root            11 Dec 27 11:22 linuxrc -> bin/busybox
drwx------    2 root     root         16384 Dec 27 11:21 lost+found
drwxr-xr-x    2 root     root          4096 Jan 17  2019 media
drwxr-xr-x    2 root     root          4096 Jan 17  2019 mnt
drwxr-xr-x    2 root     root          4096 Jan 17  2019 optkkk
drwxr-xr-x    2 root     root          4096 Jan 17  2019 proc
drwxr-x---    2 root     root          4096 Dec 27 11:22 root
lrwxrwxrwx    1 root     root             8 Dec 27 11:22 run -> /var/run
drwxr-xr-x    2 root     root          4096 Dec 27 11:23 rw
drwxr-xr-x    2 root     root          4096 Dec 27 11:22 sbin
drwxr-xr-x    2 root     root          4096 Dec 27 11:23 shares
drwxr-xr-x    2 root     root          4096 Jan 17  2019 sys
drwxrwxrwt    2 root     root          4096 Dec 27 11:22 tmp
drwxr-xr-x   11 root     root          4096 Dec 27 11:22 usr
drwxr-xr-x   16 root     root          4096 Dec 27 11:22 var
drwxr-xr-x   12 root     root          4096 Dec 27 11:22 www

The contents of md124 used to have timestamps from 2000, so it is clear that the recent update has switched the root partition to md124.

Looking at the 1024 MiB ‘var’ partition md125 (sda5) I see there are two sub-directories, 0 and 1, which judging by the contents of var/log in them, correspond to the value of saved_entry that map to the root partition.

~ # ls -l /mnt/md125
drwxr-xr-x    5 root     root          4096 Mar 24  2018 0
drwxr-xr-x    5 root     root          4096 Dec 27 11:22 1
drwxr-xr-x    2 root     root          4096 Oct 28  2017 default_apps
drwx------    2 root     root         16384 Nov 28  2014 lost+found
drwxr-xr-x    2 root     root          4096 Dec 27 11:22 tmp

The 0/1 directories contain etc, root and var sub-directories. The var directory contains standard layout for /var. The root directory looks like a home directory, so is probably mounted as /root. The etc directory looks to be a copy of /etc, with a few recent timestamps. I expect this is the working copy, and is mounted on `/etc'.


Partitions (III)

The final partition md123 (sda4) is a 3.6 TiB LVM member, which corresponds to the size of the data volume reported.

To activate the lvmcfg component, I switched back to the installer, and selected “Partition Disks”. I then used “Go Back” to return to the main menu without making changes.

I can now see the LVM volume group.

~ # vgs
  VG #PV #LV #SN Attr   VSize VFree
  vg   1   1   0 wz--n- 3.63t    0
~ # blkid | grep mapper
/dev/mapper/vg-lv: UUID="a5e35600-f588-4e42-8983-5f10a4947a2c" TYPE="ext4"
~ # ls -l /mnt/vg-lv
drwxr-xr-x    2 root     root          4096 Dec 27  2020 afp_db
drwxr-xr-x    2 root     root          4096 Jan  1  2010 autoupdate
drwx------    2 root     root         16384 Jan  1  2010 lost+found
drwxr-xr-x    4 root     root          4096 Mar 24  2018 rainbow
drwxr-xr-x    2 root     root          4096 Jan  1  2010 reserved
drwxr-xr-x    4 root     root          4096 Mar 24  2018 shares
drwxr-xr-x    2 root     root          4096 Dec 27  2020 tmp
drwxr-xr-x    2 root     root          4096 Jan  1  2010 torrent_dir
drwxr-xr-x    5 root     root          4096 Mar 24  2018 var

It appears that although the data partition uses LVM, there is only a single volume, and it spans the entire space. I’m concluding the content location, and access are managed by Personal Cloud.


In Part 2 I’ll pull data off the device, where I can use a full toolset to inspect them. I’ll also create disk images for potential reinstallation of the Seagate NAS firmware.