├── LICENSE ├── README.md ├── adafruit-pi-externalroot-helper └── debian ├── adafruit-pi-externalroot-helper.substvars ├── changelog ├── compat ├── control ├── copyright ├── docs ├── install ├── rules └── source └── format /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Adafruit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Adafruit-Pi-ExternalRoot-helper 2 | =============================== 3 | 4 | A shell script for configuring an external USB drive as root filesystem 5 | on a Raspberry Pi running Raspbian. It's a companion to [Using an 6 | External Drive as a Raspberry Pi Root Filesystem][tutorial], which you 7 | should read first. 8 | 9 | Using adafruit-pi-externalroot-helper 10 | ------------------------------------- 11 | 12 | First, read the [tutorial][tutorial]. 13 | 14 | On a Raspberry Pi running Raspbian, with a USB-connected storage device you 15 | wish to use for your root filesystem: 16 | 17 | git clone git@github.com:adafruit/Adafruit-Pi-ExternalRoot-Helper.git 18 | cd Adafruit-Pi-ExternalRoot-Helper 19 | sudo ./adafruit-pi-externalroot-helper -d /dev/sda 20 | 21 | ...where `/dev/sda` is the external USB you wish to use for a root filesystem. 22 | 23 | Sources and Further Reading 24 | --------------------------- 25 | 26 | This script is mostly an implementation of the process outlined in paulv's 27 | [HOWTO: Move the filesystem to a USB stick][1] on the Raspberry Pi forums, with 28 | additional help from the following sources: 29 | 30 | - The Arch Linux wiki, [GUID Partition Table][2] for what a GPT is and 31 | some `parted` commands. 32 | - [GUID Partition Table][wp], Wikipedia 33 | - [Booting from an external USB drive][3], from the Raspberry Pi StackExchange. 34 | - [Booting a Raspberry Pi reliably from USB in the presence of multiple USB drives][4], 35 | by Stefan Krastanov. 36 | - [Speed up your Pi by booting to a USB flash drive][5], by Sam Hobbs. 37 | - [This comment][6] on `root=` in `init/do_mounts.c` in the Linux source tree. 38 | 39 | Along with manual / info pages for: 40 | 41 | - [gdisk](http://manpages.debian.org/cgi-bin/man.cgi?query=gdisk&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en) 42 | - [parted](http://manpages.debian.org/cgi-bin/man.cgi?query=parted&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en) 43 | - [blkid](http://manpages.debian.org/cgi-bin/man.cgi?query=blkid&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en) 44 | - [mkfs](http://manpages.debian.org/cgi-bin/man.cgi?query=mkfs&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en) 45 | - [tune2fs](http://manpages.debian.org/cgi-bin/man.cgi?query=tune2fs&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en) 46 | 47 | [1]: https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=44177 48 | [2]: https://wiki.archlinux.org/index.php/GUID_Partition_Table 49 | [3]: http://raspberrypi.stackexchange.com/questions/12404/booting-from-an-external-usb-drive 50 | [4]: http://blog.krastanov.org/2014/01/30/booting-pi-reliably-from-usb/ 51 | [5]: https://samhobbs.co.uk/2013/10/speed-up-your-pi-by-booting-to-a-usb-flash-drive 52 | [wp]: https://en.wikipedia.org/wiki/GUID_Partition_Table 53 | [6]: https://github.com/torvalds/linux/blob/10975933da3d65f8833d4ce98dcc2ecc63a695d6/init/do_mounts.c#L183 54 | [tutorial]: https://learn.adafruit.com/external-drive-as-raspberry-pi-root 55 | -------------------------------------------------------------------------------- /adafruit-pi-externalroot-helper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # adafruit-pi-externalroot-helper 4 | # 5 | # Configure a Raspbian system to use an external USB drive as root filesystem. 6 | # 7 | # See README.md for details and sources. 8 | 9 | set -e 10 | 11 | function print_version() { 12 | echo "Adafruit Pi External Root Helper v0.1.0" 13 | exit 1 14 | } 15 | 16 | function print_help() { 17 | echo "Usage: $0 -d [target device]" 18 | echo " -h Print this help" 19 | echo " -v Print version information" 20 | echo " -d [device] Specify path of device to convert to root" 21 | echo 22 | echo "You must specify a device. See:" 23 | echo "https://learn.adafruit.com/external-drive-as-raspberry-pi-root" 24 | exit 1 25 | } 26 | 27 | 28 | # Display an error message and quit: 29 | function bail() { 30 | FG="1;31m" 31 | BG="40m" 32 | echo -en "[\033[${FG}\033[${BG}error\033[0m] " 33 | echo "$*" 34 | exit 1 35 | } 36 | 37 | # Display an info message: 38 | function info() { 39 | task="$1" 40 | shift 41 | FG="1;32m" 42 | BG="40m" 43 | echo -e "[\033[${FG}\033[${BG}${task}\033[0m] $*" 44 | } 45 | 46 | if [[ $EUID -ne 0 ]]; then 47 | bail "must be run as root. try: sudo adafruit-pi-externalroot-helper" 48 | fi 49 | 50 | # Handle arguments: 51 | args=$(getopt -uo 'hvd:' -- $*) 52 | [ $? != 0 ] && print_help 53 | set -- $args 54 | 55 | for i 56 | do 57 | case "$i" 58 | in 59 | -h) 60 | print_help 61 | ;; 62 | -v) 63 | print_version 64 | ;; 65 | -d) 66 | target_drive="$2" 67 | echo "Target drive = ${2}" 68 | shift 69 | shift 70 | ;; 71 | esac 72 | done 73 | 74 | if [[ ! -e "$target_drive" ]]; then 75 | bail "Target ${target_drive} must be existing device (use -d /dev/foo to specify)" 76 | fi 77 | 78 | info "start" "Will create new ext4 filesystem on ${target_drive}" 79 | info "start" "If there is data on ${target_drive}, it will be lost." 80 | read -p "Really proceed? (y)es / (n)o " -n 1 -r 81 | echo 82 | if [[ ! $REPLY =~ ^[Yy]$ ]] 83 | then 84 | echo "Quitting." 85 | exit 86 | fi 87 | 88 | export target_partition="${target_drive}1" 89 | 90 | info "dependencies" "Installing gdisk, rsync, and parted." 91 | # All except gdisk are probably installed, but let's make sure. 92 | apt-get install gdisk rsync parted 93 | 94 | info "fs create" "Creating ${target_partition}" 95 | # The alternative here seems to be to pipe a series of commands 96 | # to fdisk(1), similar to how it's done by raspi-config: 97 | # https://github.com/asb/raspi-config/blob/3a5d75340a1f9fe5d7eebfb28fee0e24033f4fd3/raspi-config#L68 98 | # This seemed to work, but I was running into weirdness because 99 | # that doesn't seem to make a GPT, and later on I couldn't get 100 | # partition unique GUID from gdisk. parted(1) is also a nice 101 | # option because it's scriptable and allows partition sizes to 102 | # be specified in percentages. 103 | parted --script "${target_drive}" mklabel gpt 104 | parted --script --align optimal "${target_drive}" mkpart primary ext4 0% 100% 105 | 106 | info "fs create" "Creating ext4 filesystem on ${target_partition}" 107 | sleep 5 108 | mkfs -t ext4 -L rootfs "${target_partition}" 109 | 110 | info "fs id" "Getting UUID for target partition" 111 | eval `blkid -o export "${target_partition}"` 112 | export target_partition_uuid=$UUID 113 | 114 | info "fs id" "Getting Partition unique GUID for target filesystem" 115 | # Ok, so the only way I was able to get this was using gdisk. 116 | # I don't quite understand the different between this value and 117 | # the one you can get with blkid and tune2fs (which seem to give 118 | # the same thing). Nevertheless, this seems to be necessary to 119 | # get a value that can be used in cmdline.txt. I think it's a 120 | # GUID specifically for the GPT partition table entry. 121 | export partition_unique_guid=`echo 'i' | sudo gdisk "${target_drive}" | grep 'Partition unique GUID:' | awk '{print $4}'` 122 | 123 | info "fs id" "Target partition UUID: ${target_partition_uuid}" 124 | info "fs id" "Partition unique GUID: ${partition_unique_guid}" 125 | 126 | info "fs copy" "Mounting ${target_partition} on /mnt" 127 | mount "${target_partition}" /mnt 128 | 129 | info "fs copy" "Copying root filesystem to ${target_partition} with rsync" 130 | info "fs copy" "This will take quite a while. Please be patient!" 131 | rsync -ax / /mnt 132 | 133 | info "boot config" "Configuring boot from {$target_partition}" 134 | # rootdelay=5 is likely not necessary here, but seems to do no harm. 135 | cp /boot/cmdline.txt /boot/cmdline.txt.bak 136 | sed -i "s|root=\/dev\/mmcblk0p2|root=PARTUUID=${partition_unique_guid} rootdelay=5|" /boot/cmdline.txt 137 | 138 | info "boot config" "Commenting out old root partition in /etc/fstab, adding new one" 139 | # These changes are made on the new drive after copying so that they 140 | # don't have to be undone in order to switch back to booting from the 141 | # SD card. 142 | sed -i '/mmcblk0p2/s/^/#/' /mnt/etc/fstab 143 | echo "/dev/disk/by-uuid/${target_partition_uuid} / ext4 defaults,noatime 0 1" >> /mnt/etc/fstab 144 | 145 | info "boot config" "Ok, your system should be ready. You may wish to check:" 146 | info "boot config" " /mnt/etc/fstab" 147 | info "boot config" " /boot/cmdline.txt" 148 | info "boot config" "Your new root drive is currently accessible under /mnt." 149 | info "boot config" "In order to restart with this drive at /, please type:" 150 | info "boot config" "sudo reboot" 151 | -------------------------------------------------------------------------------- /debian/adafruit-pi-externalroot-helper.substvars: -------------------------------------------------------------------------------- 1 | misc:Depends= 2 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | adafruit-pi-externalroot-helper (0.1.0-1) unstable; urgency=medium 2 | 3 | * Fix hardcoded target drive in gdisk call. 4 | 5 | -- Brennen Bearnes Mon, 08 Jun 2015 16:19:01 -0600 6 | 7 | adafruit-pi-externalroot-helper (0.0.1-1) unstable; urgency=low 8 | 9 | * First pass at helper script. 10 | 11 | -- Brennen Bearnes Sun, 12 Apr 2015 12:36:01 -0600 12 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 8 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: adafruit-pi-externalroot-helper 2 | Section: utils 3 | Priority: extra 4 | Maintainer: Brennen Bearnes 5 | Build-Depends: debhelper (>= 8.0.0) 6 | Standards-Version: 3.9.3 7 | Homepage: https://github.com/adafruit/Adafruit-Pi-ExternaRoot-Helper 8 | # Vcs-Git: https://github.com/adafruit/Adafruit-Pi-ExternalRoot-Helper.git 9 | # Vcs-Browser: https://github.com/adafruit/Adafruit-Pi-ExternalRoot-Helper 10 | 11 | Package: adafruit-pi-externalroot-helper 12 | Architecture: armhf 13 | Depends: ${shlibs:Depends}, ${misc:Depends}, rsync, parted, gdisk 14 | Description: Configuration helper for using an external drive as root FS 15 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: adafruit-pi-externalroot-helper 3 | Source: https://github.com/adafruit/Adafruit-Pi-ExternalRoot-Helper 4 | 5 | Files: * 6 | Copyright: 2015 Adafruit Industries 7 | License: MIT 8 | The MIT License (MIT) 9 | . 10 | Copyright (c) 2015 Adafruit Industries 11 | . 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | . 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | . 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README.md 2 | -------------------------------------------------------------------------------- /debian/install: -------------------------------------------------------------------------------- 1 | adafruit-pi-externalroot-helper usr/bin 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | # export DH_VERBOSE=1 11 | 12 | %: 13 | dh $@ 14 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | --------------------------------------------------------------------------------