Pi5 nvme 4tb 8tb drives

(post deleted by author)

1 Like

Hi,

Thank you a lot for your manual :) it will be very helpful

You did it only with SSH terminal, right ?

I will buy the SSD and try this 🀞🏽

Have a good day,
Thanks

(post deleted by author)

1 Like

Thank you :) I will test all of these

(post deleted by author)

1 Like

Thank you a lot. I will order the SSD :)

1 Like

Here the latest script:

#!/bin/bash
# MBR to GPT converter by Patrick R. Wallner (https://mcpat.com/)
# Results and discussion at https://nvme.mcpat.com/
#
# v1.0
# To run the converter use the following command:
# sudo curl https://raw.githubusercontent.com/pwallner/NVMe/master/gptconverter.sh | sudo bash
#
# Changelog
# v0.9
#  - First release
# v1.0
#  - Check firstboot
#  - config.txt entries

# Initialize variables
DEVICE=/dev/nvme0n1
MNTPATH="/tmp/gptconverter-mnt"
MNTED=FALSE
FIRSTBOOT=FALSE

# Fix language settings for utf8
export LC_ALL=C

# Terminal colors
BLACK=$(tput setaf 0)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
LIME_YELLOW=$(tput setaf 190)
POWDER_BLUE=$(tput setaf 153)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
BRIGHT=$(tput bold)
NORMAL=$(tput sgr0)
BLINK=$(tput blink)
REVERSE=$(tput smso)
UNDERLINE=$(tput smul)

# Whether apt update has ran
AptUpdated="0"

# Prints a line with color using terminal codes
Print_Style() {
  printf "%s\n" "${2}$1${NORMAL}"
}

# Install apt package
Install_Apt_Package() {
  echo "Install $1"
  if [ "$AptUpdated" -ne "1" ]; then
    export AptUpdated="1"
    apt-get update
  fi
  apt-get install --no-install-recommends "$1" -y
}

# Compare Version
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }

errexit()
{
  echo ""
  Print_Style "$1" "$RED"
  echo ""
  if [ "${MNTED}" = "TRUE" ]; then
    umount "${MNTPATH}/" &> /dev/null
  fi
  rm -rf "${MNTPATH}/" &> /dev/null
  exit 1
}

mntpart()
{
  if [ ! -d "${MNTPATH}/" ]; then
    mkdir "${MNTPATH}/"
    if [ $? -ne 0 ]; then
      errexit "Unable to make partition mount point"
    fi
  fi
  mount "$1" "${MNTPATH}/"
  if [ $? -ne 0 ]; then
    errexit "Unable to mount $2 partition"
  fi
  MNTED=TRUE
}

umntpart()
{
  umount "${MNTPATH}/"
  if [ $? -ne 0 ]; then
    errexit "Unable to unmount partition"
  fi
  MNTED=FALSE
  rm -r "${MNTPATH}/"
}

# Check if script is running as root first
if [[ "$(whoami)" != "root" ]]; then
  errexit "$0 must be run as root user! Example: sudo ./gptconverter.sh"
fi

Print_Style "Pre checks ..." "$YELLOW"
# Get host information
if [[ "$(cat /proc/device-tree/model | grep -c "Pi 5")" > 0 ]]; then
  Print_Style "It's a Pi5 ..." "$NORMAL"
else
  errexit "It's not a Pi5 ..."
fi

if [ ! $(version $(cat /etc/debian_version)) -ge $(version "12.4") ]; then
	errexit "Debian version is not up to date ..."
else
	Print_Style "Debian version is $(cat /etc/debian_version) ..." "$NORMAL"
fi

# NVMe exists ?
if [ ! -b "$DEVICE" ]; then
  errexit "NVMe does not exist!"
fi
Print_Style "NVMe found ..." "$NORMAL"

#Partitions
DEVICE_P="${DEVICE}"
DEVICE_P+='p'
DriveSuffix=$(echo "$DEVICE" | cut -d"/" -f3)
if [ -z "$DriveSuffix" ]; then
  DriveSuffix=$(echo "$BootDrive" | cut -d"/" -f2)
fi
if [ -z "$DriveSuffix" ]; then
  DriveSuffix=$(echo "$BootDrive" | cut -d"/" -f1)
fi
if [ -z "$DriveSuffix" ]; then
  DriveSuffix="$DEVICE"
fi
Drivesuffix_P="${DriveSuffix}"
Drivesuffix_P+='p'
totalPartitions=$(grep -c "$Drivesuffix_P[0-9]" /proc/partitions)
echo "Total partitions: $totalPartitions"
for i in $(seq 1 1 $totalPartitions)
do
	if grep "$Drivesuffix_P"$i /etc/mtab > /dev/null 2>&1; then
		errexit "$Drivesuffix_P$i is mounted!"
	fi
done
Print_Style "NVMe has no mounted partitions ..." "$NORMAL"

# First boot check
#Print_Style "Check firstboot ..." "$NORMAL"
mntpart "${DEVICE_P}1" "BOOT"
if [[ "$(cat "${MNTPATH}/cmdline.txt" | grep -c "firstboot")" > 0 ]]; then
    umntpart
    errexit "System needs firstly a boot from NVMe, remove SD and reboot, then poweroff, insert SD again and run this script again ..."
    #FIRSTBOOT=TRUE
    #Print_Style "First boot detected ..." "$NORMAL"
else
    Print_Style "First boot already done ..." "$NORMAL"
fi
umntpart

# Install required components
Print_Style "Fetching required components ..." "$YELLOW"
if [ -z "$(which gparted)" ]; then Install_Apt_Package "gparted"; fi
Print_Style "gparted installed ..." "$NORMAL"
if [ -z "$(which gdisk)" ]; then Install_Apt_Package "gdisk"; fi
Print_Style "gdisk installed ..." "$NORMAL"

# Get drive informations
Print_Style "Fetching informations ..." "$YELLOW"
PTTYPE="$(blkid ${DEVICE} | sed -n 's|^.*PTTYPE="\(\S\+\)".*|\1|p')"
PTTYPE="$(tr [a-z] [A-Z] <<< "${PTTYPE}")"
if [ "${PTTYPE}" = "DOS" ]; then
  PTTYPE="MBR"
fi
if [[ "${PTTYPE}" != "MBR" && "${PTTYPE}" != "GPT" ]]; then
  errexit "Unsupported partition table type!"
fi
echo "Partition table type is ${PTTYPE}"
if [ "${PTTYPE}" = "MBR" ]; then
  echo -n "Ok to convert ${DEVICE} to GPT (y/n)? "
  while read -r -n 1 -s answer; do
    if [[ "${answer}" = [yYnN] ]]; then
      echo "${answer}"
      if [[ "${answer}" = [yY] ]]; then
        break
      else
        errexit "Aborted"
      fi
    fi
  done
  sgdisk -z "${DEVICE}" &> /dev/null
fi

# Check if partition overlaps and if unallocated space exists
INFO="$(gdisk -l ${DEVICE} 2> /dev/null)"
START=$(sed -n "s|^\s\+$totalPartitions\s\+\(\S\+\).*|\1|p" <<< "${INFO}")
SHRINK=FALSE
EXPAND=FALSE
if [ $(grep -c "Warning! Secondary partition table overlaps the last partition" <<< "${INFO}") -ne 0 ]; then
  echo "ROOT partition overlaps the Secondary partition table area"
  echo -n "Ok to resize ROOT partition (y/n)? "
  while read -r -n 1 -s answer; do
    if [[ "${answer}" = [yYnN] ]]; then
      echo "${answer}"
      if [[ "${answer}" = [yY] ]]; then
        break
      else
        errexit "Aborted"
      fi
    fi
  done
  SHRINK=TRUE
elif [[ "$(parted /dev/nvme0n1 unit GB print free | grep 'Free Space' | tail -n1 | awk '{print $3}')" != "0.00GB" ]]; then
  echo -n "Expand last partition to use all available space (y/n)? "
  while read -r -n 1 -s answer; do
    if [[ "${answer}" = [yYnN] ]]; then
      echo "${answer}"
      if [[ "${answer}" = [yY] ]]; then
        EXPAND=TRUE
      fi
      break
    fi
  done
fi

# Run process
if [[ "${PTTYPE}" = "MBR" || "${SHRINK}" = "TRUE" || "${EXPAND}" = "TRUE" ]]; then
  Print_Style "Start converting ..." "$YELLOW"
  if [ "${SHRINK}" = "TRUE" ]; then
    resize2fs -f -M "${DEVICE_P}${totalPartitions}" > /dev/null 2>&1
	Print_Style "Shrinked partition ..." "$NORMAL"
  fi
  if [[ "${SHRINK}" = "TRUE" || "${EXPAND}" = "TRUE" ]]; then
    gdisk "${DEVICE}" <<EOF &> /dev/null
d
${totalPartitions}
n
${totalPartitions}
${START}


w
y
EOF
    resize2fs -f "${DEVICE_P}${totalPartitions}" > /dev/null 2>&1
    Print_Style "Resized partition ..." "$NORMAL"
  fi
  gdisk "${DEVICE}" <<EOF &> /dev/null
r
h
1
n
0c
n
n
w
y
EOF
  Print_Style "Expanded ..." "$NORMAL"
  Print_Style "Start writing cmdline.txt, config.txt and fstab ..." "$YELLOW"
  PARTUUID_1="$(blkid ${DEVICE_P}1 | sed -n 's|^.*PARTUUID="\(\S\+\)".*|\1|p')"
  PARTUUID_2="$(blkid ${DEVICE_P}2 | sed -n 's|^.*PARTUUID="\(\S\+\)".*|\1|p')"
  mntpart "${DEVICE_P}1" "BOOT"
  sed -i '/^[[:space:]]*#/!s| init=/usr/lib/raspi-config/init_resize\.sh||' "${MNTPATH}/cmdline.txt"
  sed -i "/^[[:space:]]*#/!s|^\(.*root=\)\S\+\(\s\+.*\)$|\1PARTUUID=${PARTUUID_2}\2|" "${MNTPATH}/cmdline.txt"
  Print_Style "cmdline.txt written ..." "$NORMAL"
  echo '# Enable the PCIe External connector' >> "${MNTPATH}/config.txt"
  echo 'dtparam=pciex1' >> "${MNTPATH}/config.txt"
  echo "" >> "${MNTPATH}/config.txt"
  echo '# Force Gen 3.0 speeds' >> "${MNTPATH}/config.txt"
  echo 'dtparam=pciex1_gen=3' >> "${MNTPATH}/config.txt"
  Print_Style "config.txt written ..." "$NORMAL" 
  umntpart
  mntpart "${DEVICE_P}2" "ROOT"
  sed -i "/^[[:space:]]*#/!s|^\S\+\(\s\+/boot\S*\s\+vfat\s\+.*\)$|PARTUUID=${PARTUUID_1}\1|" "${MNTPATH}/etc/fstab"
  sed -i "/^[[:space:]]*#/!s|^\S\+\(\s\+/\s\+.*\)$|PARTUUID=${PARTUUID_2}\1|" "${MNTPATH}/etc/fstab"
  Print_Style "fstab written ..." "$NORMAL"
  if [[ "${FIRSTBOOT}" = "TRUE" ]]; then
	#Firstboot resize
	rm "${MNTPATH}/etc/init.d/resize2fs_once"
	rm "${MNTPATH}/etc/rc3.d/S01resize2fs_once"
	Print_Style "'resize2fs_once' removed from init.d and rc3.d ..." "$NORMAL"
	#Manipulate init_resize.sh
	sed -i 's/check_variables () {/check_variables_old () {/' "${MNTPATH}/usr/lib/raspi-config/init_resize.sh"
	sed -i '3i check_variables () {'\\n'  FAIL_REASON=\"GPT Drive detected\"'\\n'  return 1'\\n'}'\\n'' "${MNTPATH}/usr/lib/raspi-config/init_resize.sh"
	Print_Style "File 'init_resize.sh' patched ..." "$NORMAL"
	#Patch firstboot
	sed -i 's/  whiptail --infobox \"Fix PARTUUID...\" 20 60/  /' "${MNTPATH}/usr/lib/raspberrypi-sys-mods/firstboot"
	sed -i 's/  fix_partuuid/  /' "${MNTPATH}/usr/lib/raspberrypi-sys-mods/firstboot"
	Print_Style "File 'firstboot' patched ..." "$NORMAL"
  fi
  umntpart
  Print_Style "Finished ..." "$MAGENTA"
else
  Print_Style "Finished, filesystem is already expanded ..." "$MAGENTA"
fi
2 Likes

To keep it simple and always up to date, visit my page.

You can run the script with

sudo -i
bash <(curl -s https://nvme.mcpat.com/gptconverter.sh)

Hi @mcpat,

I’m waiting for X1001 and then I can test all of this :)

I read your website. Thanks for your tutorials :) You write : β€œ1. Boot your pi with a SD card and already installed NVMe, and install an image with imager on the rpi desktop, you can also make the settings (e.g. username, password, wifi, …)”.

I have the OS lite on my SD card on my Pi 5. Do you think it’s ok if I install an image with imager on my NVme SSD from my Desktop PC and then install the NVMe on the X1001 board and then boot the Pi like you write and follow your instructions ? Or I have to install an image from the Rpi desktop ?

Thank you
Have a good day

You can also do it from your pc if you have an adapter. I don’t have it, so I had to use desktop version on pi and installed the image there.
But nevertheless, after you did it, first boot from nvme and then reboot with sd. Then you can use my script. I got the confirmation already from another member that it is working.

@mcpat great ! Thank you for your answer :) I will test it and inform you

Hi,

@mcpat I follow your tutorial and everything seems working! I have ~4TB πŸ™ŒπŸ½ I really want to thank you. Thanks !

May I ask you a question. I would like to transfer all my medias (~2TB) on the SSD. If I use network, it will be slower than using my PC. I would like to transfer it from my PC with my NVMe adapter but I can’t see the NVMe SSD on my PC Desktop. Do you have any idea if I can do it with my PC ?

Thank you
Have a good night

@uyan
thx for feedback! Good to hear that everything is working. I suppose best would be to connect your hdd with the media to the rpi, mount it, and then copy it to the new place. Alternative you can use WinSCP to connect via SSH and then copy from your pc to the rpi (slow! maybe fast enough if you connect the pi with network cable). The partition on the m.2 is β€œext4”, so a normal pc cannot read it! Normal (Windows)PC can read fat, fat32, ntfs, exfat, but none of the linux formats (e.g. ext4).

1 Like

Thank you for your ideas πŸ™‚

Like you said, The best solution is to connect the HDD to the Pi and then share it from Casa Os. It works very good and very fast.

1 Like

Hi,
I copied my existing 500Gb MBR nvme boot drive to the new one connected via USB (ugreen M.2 carrier) using rpi-clone. SD card copier did not work. I then installed the copy in the nvme base and booted with a good SD card following the instructions here: https://forums.raspberrypi.com/viewtopic.php?t=364768

Worked a treat!
alwi