├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── LICENSE
├── README.md
├── copyRootToUSB.sh
├── partUUID.sh
└── sample-extlinux.conf
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Issue report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the issue**
11 | Please describe the issue
12 |
13 | **What version of L4T/JetPack**
14 | L4T/JetPack version:
15 |
16 | **Which Jetson**
17 | Jetson:
18 |
19 | **To Reproduce**
20 | Steps to reproduce the behavior:
21 | For example, what command line did you run?
22 |
23 | **Expected behavior**
24 | A clear and concise description of what you expected to happen.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[FEATURE REQUEST]"
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Jetsonhacks
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bootFromUSB
2 | Boot NVIDIA Jetson Nano Developer Kit from a mass storage USB device. This includes Jetson Nano 2GB, and may also work with the TX1. This setup is done from the Jetson Development Kit itself.
3 |
4 | WARNING: This is a low level system change. You may have issues which are not easily solved. You should do this working on a freshly flashed micro SD card, and certainly do not attempt this with valuable data on the card itself. A serial debug console is useful if things go wrong.
5 |
6 | A new feature of JetPack 4.5 (L4T 32.5) is the ability to boot from a USB device with mass storage class and bulk only protocol. This includes devices such as a USB HDD, USB SSD and flash drives.
7 |
8 | In order to setup a Jetson to boot from a USB device, there are several steps.
9 |
10 |
11 | ## Step 1: Setup and Boot the Jetson
12 | You will need to do an initial setup of the Jetson with JetPack 4.5+ in order to load updated firmware into the Jetson Module QSPI-NOR flash memory. Follow the 'Getting Started' instructions on the JetPack site: https://developer.nvidia.com/embedded/jetpack
13 |
14 | The JetPack archives are located here: https://developer.nvidia.com/embedded/jetpack-archive
15 |
16 | During the initial setup of L4T 32.5+, the firmware for the Jetson Nano developer kits relocates the boot firmware from the micro SD card to the Jetson module integrated QSPI-NOR flash memory. This also changes the layout of the SD card. This layout is now analagous to the BIOS in a PC.
17 |
18 | ## Step 2: Prepare the USB Drive
19 | Plug in the USB drive.
20 |
21 | Prepare the USB drive (USB 3.0+, SSD, HDD, or flash drive) by formatting the disk as GPT with an Ext4 partition. Formatting the disk will erase any data that is on that disk. When finished, the disk should show as /dev/sda1 or similar. Note: Make sure that the partition is Ext4, as other formats will appear to copy correctly but cause issues later on. You may set the volume label during this process.
22 |
23 | You can prepare the USB drive by using the Disks app. Formatting the disk using Format and creating a partition are two different tasks. Format the disk as GPT, then add a partition formatted as Ext4. Name the newly created partition APP so that Jetson system apps recognize it correctly.
24 |
25 | Once the disk is ready, mount the disk. If you are using a desktop, you can do this by clicking on the USB disk icon and opening a file browser on its contents.
26 |
27 | ## Step 3 Copy the rootfs to the USB drive
28 | Copy the application area of the micro SD card to the USB drive. copyRootToUSB.sh copies the contents of the entire system micro SD card to the USB drive. Naturally, the USB drive storage should be larger than the micro SD card. Note: Make sure that the USB drive is mounted before running the script, the script will complain if you do not.
29 |
30 |
31 | In order to copyRootToUSB:
32 |
33 | ```
34 | usage: ./copyRootToUSB.sh [OPTIONS]
35 |
36 | -d | --directory Directory path to parent of kernel
37 |
38 | -v | --volume_label Label of Volume to lookup
39 |
40 | -p | --path Device Path to USB drive (e.g. /dev/sda1)
41 |
42 | -h | --help This message
43 | ```
44 | For example:
45 |
46 | ```
47 | $ ./copyRootToUSB.sh -p /dev/sda1
48 | ```
49 |
50 |
Note
51 |
52 | The most likely device address of the USB drive will be /dev/sda1 Please note that if you do not find a version ending with a number, you probably do not have a partition allocated on that drive. For example,
53 |
54 | ```
55 | $ ls /dev/sd*
56 | ```
57 |
58 | assuming that there is a partition, should respond as:
59 |
60 | ```
61 | $ /dev/sda /dev/sda1
62 | ```
63 |
64 | sda1 is where you want to copy the rootfs from the SD card. If you only see /dev/sda, it means that there is no partition.
65 |
66 |
67 | ## Step 4 Modify extlinux.conf for the boot sequence
68 | Use the file browser to navigate to the USB drive, find the boot/extlinux directory, and then open a terminal from the context menu.
69 |
70 | Before editing the extlinux.conf file make a copy of it for backup purposes. This is in a system protected area so you will need privileges to change the file, ie 'sudo'.
71 |
72 | Modify the /boot/extlinux/extlinux.conf file located on the USB drive. This is in a system protected area, so you will need privileges to change the file, ie 'sudo gedit'. Make a copy of the 'PRIMARY' entry and rename it sdcard.
73 |
74 | In the PRIMARY entry change the location of the root to point to the USB drive, ie change 'root=/dev/mmcblk0p1' which is the address of the SD card. Provided in this repository is a sample configuration file: sample-extlinux.conf as an example.
75 |
76 | While using root=/dev/sda1 in the extlinux.conf works, it can be a good idea to use the PARTUUID of the disk to identify the disk location. Because USB devices are not guaranteed to enumerate in the same order every time, it is possible that that /dev/sda1 points to a different device. This may happen if an extra flash drive is plugged into the Jetson along with the USB boot drive, for example.
77 |
78 | The UUID of the disk in the GPT partition table is called the PARTUUID. This is a low level descriptor. Note that there is another identifier, referred to as UUID, which is given by the Linux file system. Use the PARTUUID for this application, as UUID has been reported to cause issues at the present time in this use case.
79 |
80 | There is a convenience file: partUUID.sh which will determine the PARTUUID of a given device. This is useful in determining the PARTUUID of the USB drive. Note: If the PARTUUID returned is not similar in length to the sample-extlinux.conf example (32a76e0a-9aa7-4744-9954-dfe6f353c6a7), then it is likely that the device is not formatted correctly.
81 |
82 | ```
83 | $ ./partUUID.sh
84 | ```
85 |
86 | While this defaults to sda1 (/dev/sda1), you can also determine other drive PARTUUIDs. The /dev/ is assumed, use the -d flag. For example:
87 |
88 | ```
89 | $ ./partUUID.sh -d sdb1
90 | ```
91 |
92 | ## Step 5 Try It Out!
93 |
94 | Remove the micro SD card, and boot the system.
95 |
96 |
97 | Release Notes
98 | March, 2021
99 |
100 | * JetPack 4.5.1
101 | * L4T 32.5.1
102 | * Remove payload updater, the JetPack update addresses this issue
103 | * Slightly more generous readme
104 | * Tested on Jetson Nano
105 |
106 |
107 | February, 2021
108 |
109 | * JetPack 4.5
110 | * L4T 32.5
111 | * Initial Release
112 | * Tested on Jetson Nano
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/copyRootToUSB.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright (c) 2016-21 Jetsonhacks
3 | # MIT License
4 | # Copy the root directory to the given volume
5 |
6 | DESTINATION_TARGET=""
7 | VOLUME_LABEL=""
8 |
9 | function usage
10 | {
11 | echo "usage: ./copyRootToUSB.sh [OPTION]"
12 | echo "-d | --directory Directory path to parent of kernel)"
13 | echo "-p | --path e.g. /dev/sda1"
14 | echo "-v | --volume_label Name of the volume label"
15 | echo "-h | --help This message"
16 | }
17 |
18 | # Iterate through command line inputs
19 | while [ "$1" != "" ]; do
20 | case $1 in
21 | -d | --directory ) shift
22 | DESTINATION_TARGET=$1
23 | ;;
24 | -v | --volume_label ) shift
25 | VOLUME_LABEL=$1
26 | ;;
27 | -p | --path ) shift
28 | DEVICE_PATH=$1
29 | ;;
30 | -h | --help ) usage
31 | exit
32 | ;;
33 | * ) usage
34 | exit
35 | ;;
36 | esac
37 | shift
38 | done
39 |
40 | if [ "$DEVICE_PATH" != "" ] ; then
41 | echo "Device Path: "$DEVICE_PATH
42 | DESTINATION_TARGET=$(findmnt -rno TARGET "$DEVICE_PATH")
43 | if [ "$DESTINATION_TARGET" = "" ] ; then
44 | echo "Unable to find the mount point of: ""$DEVICE_PATH"
45 | exit 1
46 | fi
47 | else
48 | if [ "$DESTINATION_TARGET" = "" ] ; then
49 | if [ "$VOLUME_LABEL" = "" ] ; then
50 | # No destination path, no volume label
51 | usage
52 | exit 1
53 | else
54 | DEVICE_PATH=$(findfs LABEL="$VOLUME_LABEL")
55 | if [ "$DEVICE_PATH" = "" ] ; then
56 | echo "Unable to find mounted volume: ""$VOLUME_LABEL"
57 | exit 1
58 | else
59 | echo "Device Path: "$DEVICE_PATH
60 | DESTINATION_TARGET=$(findmnt -rno TARGET "$DEVICE_PATH")
61 | echo "Destination Target: "$DESTINATION_TARGET
62 | if [ "$DESTINATION_TARGET" = "" ] ; then
63 | echo "Unable to find the mount point of: ""$VOLUME_LABEL"
64 | exit 1
65 | fi
66 | fi
67 | fi
68 | fi
69 | fi
70 |
71 | echo "Target: "$DESTINATION_TARGET
72 | # apt-get update should make rsync available on a new system
73 | sudo apt-get update
74 | sudo apt-get install rsync -y
75 | sudo rsync -axHAWX --numeric-ids --info=progress2 --exclude=/proc / "$DESTINATION_TARGET"
76 |
77 |
--------------------------------------------------------------------------------
/partUUID.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright (c) 2016-2021 Jetsonhacks
3 | # MIT License
4 | # print out the PARTUUID of the given disk partition
5 | # PARTUUID is a partition table level UUID for the partition, a feature of GPT partitioned disks
6 | # UUID is a file system UUID which is retrieved from the filesystem metadata inside a partion
7 |
8 | PARTITION_TARGET="/dev/sda1"
9 | function usage
10 | {
11 | echo "usage: ./partUUID.sh [partition [-p partition ] | [-h]]"
12 | echo "-p | --partition ; default /dev/sda1"
13 | echo "-h | --help This message"
14 | }
15 |
16 | # Iterate through command line inputs
17 | while [ "$1" != "" ]; do
18 | case $1 in
19 | -p | --partition ) shift
20 | PARTITION_TARGET=$1
21 | ;;
22 | -h | --help ) usage
23 | exit
24 | ;;
25 | * )
26 | ;;
27 | esac
28 | shift
29 | done
30 |
31 | PARTUUID_STRING=$(sudo blkid -o value -s PARTUUID $PARTITION_TARGET)
32 | echo PARTUUID of Partition: $PARTITION_TARGET
33 | echo $PARTUUID_STRING
34 | echo
35 | echo Sample snippet for /boot/extlinux/extlinux.conf entry:
36 | echo 'APPEND ${cbootargs} root=PARTUUID='$PARTUUID_STRING rootwait rootfstype=ext4
37 |
--------------------------------------------------------------------------------
/sample-extlinux.conf:
--------------------------------------------------------------------------------
1 | TIMEOUT 30
2 | DEFAULT primary
3 |
4 | MENU TITLE L4T boot options
5 | # Sample extlinux.conf file for booting from USB
6 | # You will need to set the root environment variable to match your system
7 | #
8 | # You can set the root to various levels of specificity
9 | # If you have multiple USB storage devices, the PARTUUID approach is very useful
10 | # PARTUUID is the PARTUUID of the USB device; most exact - recommended
11 | # LABELNAME is a little more specific; root=LABEL=jetson_drive
12 | # /dev/sda1 is the most general; root=/dev/sda1
13 | # Note: The UUID options seems to have some issues on the Jetson
14 | LABEL primary
15 | MENU LABEL primary kernel
16 | LINUX /boot/Image
17 | INITRD /boot/initrd
18 | APPEND ${cbootargs} quiet root=PARTUUID=32a76e0a-9aa7-4744-9954-dfe6f353c6a7 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0
19 |
20 | # When testing a custom kernel, it is recommended that you create a backup of
21 | # the original kernel and add a new entry to this file so that the device can
22 | # fallback to the original kernel. To do this:
23 | #
24 | # 1, Make a backup of the original kernel
25 | # sudo cp /boot/Image /boot/Image.backup
26 | #
27 | # 2, Copy your custom kernel into /boot/Image
28 | #
29 | # 3, Uncomment below menu setting lines for the original kernel
30 | #
31 | # 4, Reboot
32 |
33 | LABEL sdcard
34 | MENU LABEL primary kernel
35 | LINUX /boot/Image
36 | INITRD /boot/initrd
37 | APPEND ${cbootargs} quiet root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0
38 |
39 |
--------------------------------------------------------------------------------