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.