├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── custom_bsp_for_nano_dev_kit
├── cmdline.txt
├── desktop
│ └── terminal.desktop
├── extlinux.conf
├── kernel_tegra210-p3448-0000-p3449-0000-b00-enable-spi1.dtb
├── onboard
│ ├── onboard-autostart.desktop
│ └── onboard-defaults.conf
├── step3b_customize_bsp.sh
├── u-boot.bin
└── xfce
│ ├── xfce4-desktop.xml
│ └── xfce4-panel.xml
├── do_all.sh
├── find_mirrors.sh
├── step0_env.sh
├── step1_make_rootfs.sh
├── step2_customize_rootfs.sh
├── step2a_install.sh
├── step2b_cleanup.sh
├── step2c_fix_broken_install.sh
├── step3_apply_bsp.sh
├── step4_flash.sh
├── step5_create_image.sh
└── step6_flash_SD.sh
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text eol=lf
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.tgz
2 | *.tbz*
3 | *.tar*
4 | *.img
5 | custom/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 vuquangtrong
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 | # jetson-custom-image
2 | Create a custom image for Jetson boards
3 |
4 |
5 | ## How to
6 |
7 | 1. Firstly, edit the variables in `step0_env.sh`
8 |
9 | In here, you can change release version of Ubuntu and Jetson BSP.
10 | You have to set directories for RootFs and Build image
11 | You can choose a Desktop Environment.
12 |
13 | 2. Run `step1_make_rootfs.sh`
14 |
15 | This step creates a base RootFs in `ROOT_DIR`.
16 | The base version of Ubuntu will be downloaded and unpacked.
17 |
18 | 3. Run `step2_customize_rootfs.sh`
19 |
20 | This step installs necessary packages for Jetson libs, and X11 GUI server.
21 | It will download a Desktop environment if you do select one.
22 | It does some configurations to the RootFs.
23 |
24 | 4. Run `step3_apply_bsp.sh`
25 |
26 | This step downloads Jetson BSP including bootloader, Linux kernel, Linux headers, drivers and libraries.
27 | It also create an user for you too.
28 |
29 | 5. Run `step4_flash.sh`
30 |
31 | Put your board into Recovery Mode, and this step will flash your board with new system image.
32 |
33 | 6. Run `step5_create_image.sh`
34 |
35 | If you want to create and image file for flashing to a micro-SD Card, run this step before doing the next step.
36 |
37 | 7. Run `step6_flash_SD.sh`
38 |
39 | This step will write the system image to your micro-SD card.
40 | It also expands the application partition to use all of space of your card.
41 |
42 | ## License
43 |
44 | MIT
45 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/cmdline.txt:
--------------------------------------------------------------------------------
1 | tegraid=21.1.2.0.0 ddr_die=4096M@2048M section=512M memtype=0 vpr_resize usb_port_owner_info=0 lane_owner_info=0 emc_max_dvfs=0 touch_id=0@63 video=tegrafb no_console_suspend=1 debug_uartport=lsport,4 earlyprintk=uart8250-32bit,0x70006000 maxcpus=4 usbcore.old_scheme_first=1 lp0_vec=0x1000@0xff780000 core_edp_mv=1075 core_edp_ma=4000 gpt tegra_fbmem=0x800000@0x92ca9000 is_hdmi_initialised=1 earlycon=uart8250,mmio32,0x70006000 root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=tty0 fbcon=map:0 net.ifnames=0 quiet
2 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/desktop/terminal.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Type=Application
3 | Name=Terminal
4 | Exec=/usr/bin/gnome-terminal
5 | Terminal=false
6 | Icon=gnome-terminal
7 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/extlinux.conf:
--------------------------------------------------------------------------------
1 | TIMEOUT 1
2 | DEFAULT JetsonIO
3 |
4 | MENU TITLE L4T boot options
5 |
6 | LABEL JetsonIO
7 | MENU LABEL Tegra 210 - no console on ttyS0, enable spi1
8 | LINUX /boot/Image
9 | FDT /boot/kernel_tegra210-p3448-0000-p3449-0000-b00-enable-spi1.dtb
10 | INITRD /boot/initrd
11 | # flash.sh will add ROOT_DEV and CMDLINE_ADD from the conf file to APPEND variable
12 | APPEND tegraid=21.1.2.0.0 ddr_die=4096M@2048M section=512M memtype=0 vpr_resize usb_port_owner_info=0 lane_owner_info=0 emc_max_dvfs=0 touch_id=0@63 video=tegrafb no_console_suspend=1 debug_uartport=lsport,4 earlyprintk=uart8250-32bit,0x70006000 maxcpus=4 usbcore.old_scheme_first=1 lp0_vec=0x1000@0xff780000 core_edp_mv=1075 core_edp_ma=4000 gpt tegra_fbmem=0x800000@0x92ca9000 is_hdmi_initialised=1 earlycon=uart8250,mmio32,0x70006000 quiet
13 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/kernel_tegra210-p3448-0000-p3449-0000-b00-enable-spi1.dtb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuquangtrong/jetson-custom-image/a63fb5ad3bc814ec3c31281142fd904fd4ef99cf/custom_bsp_for_nano_dev_kit/kernel_tegra210-p3448-0000-p3449-0000-b00-enable-spi1.dtb
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/onboard/onboard-autostart.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | X-XFCE-Autostart-Override=true
3 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/onboard/onboard-defaults.conf:
--------------------------------------------------------------------------------
1 | [main]
2 | start-minimized=True
3 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/step3b_customize_bsp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 3: apply JETSON_BSP
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ../step0_env.sh
20 |
21 | WORK_ROOT_DIR=${WORK_DIR}/Linux_for_Tegra/rootfs
22 |
23 | ##########
24 | echo "Set script options"
25 |
26 | set -e # exit on error
27 | set -o pipefail # exit on pipeline error
28 | set -u # treat unset variable as error
29 |
30 | ##########
31 | echo "Replace U-boot"
32 | install -Dm644 u-boot.bin ${WORK_DIR}/Linux_for_Tegra/bootloader/t210ref/p3450-0000/u-boot.bin
33 |
34 | echo "Replace Linux boot menu"
35 | # note that flash.sh or make_image.sh will change add some extra boot commands based on the target boot device (SDcard/eMMC/etc.)
36 | install -Dm644 extlinux.conf ${WORK_ROOT_DIR}/boot/extlinux/extlinux.conf
37 |
38 | echo "Add overlay Device tree"
39 | # this file is generated using sudo python /opt/nvidia/jetson-io/jetson-io.py on-board
40 | install -Dm644 kernel_tegra210-p3448-0000-p3449-0000-b00-enable-spi1.dtb ${WORK_ROOT_DIR}/boot/kernel_tegra210-p3448-0000-p3449-0000-b00-enable-spi1.dtb
41 |
42 | echo "Insert SPI driver"
43 | # Jetpack 4.6 does not add driver automatically
44 | cat << EOF >> ${WORK_ROOT_DIR}/etc/modules
45 | spidev
46 | EOF
47 |
48 | echo "Disable console to take control ttyS0"
49 | sed -i 's/console=ttyS0,115200n8//g' ${WORK_DIR}/Linux_for_Tegra/p3448-0000.conf.common
50 |
51 | echo "Enable autologin"
52 | cat << EOF > ${WORK_ROOT_DIR}/etc/lightdm/lightdm.conf.d/autologin.conf
53 | [Seat:*]
54 | autologin-guest=false
55 | autologin-session=xubuntu
56 | autologin-user=${JETSON_USR}
57 | autologin-user-timeout=0
58 | EOF
59 |
60 | WIFI_SSID="HomeSweetHome"
61 | WIFI_PASS="Kh0ngch0d@u"
62 | cat << EOF > ${WORK_ROOT_DIR}/etc/netplan/01-netconf.yaml
63 | network:
64 | version: 2
65 | renderer: NetworkManager
66 | ethernets:
67 | eth0:
68 | optional: true
69 | dhcp4: true
70 | # add wifi setup information here ...
71 | wifis:
72 | wlan0:
73 | access-points:
74 | "${WIFI_SSID}":
75 | password: "${WIFI_PASS}"
76 | dhcp4: true
77 | dhcp4-overrides:
78 | route-metric: 50
79 | EOF
80 |
81 | echo "Enable color prompt for ${JETSON_USR} console"
82 | sed -i 's/^#force_color_prompt=yes/force_color_prompt=yes/g' ${WORK_ROOT_DIR}/home/${JETSON_USR}/.bashrc
83 |
84 | echo "Install qemu-aarch64-static"
85 | # for next steps
86 | install -Dm755 $(which qemu-aarch64-static) ${WORK_ROOT_DIR}/usr/bin/qemu-aarch64-static
87 |
88 | if [[ ${JETSON_DESKTOP} == 'xubuntu' ]]; then
89 | echo "Add default XFCE settings"
90 | install -Dm644 xfce/xfce4-panel.xml ${WORK_ROOT_DIR}/home/${JETSON_USR}/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
91 | install -Dm644 xfce/xfce4-desktop.xml ${WORK_ROOT_DIR}/home/${JETSON_USR}/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml
92 | fi
93 |
94 | echo "Add default desktop icons"
95 | rm -rf ${WORK_ROOT_DIR}/home/${JETSON_USR}/Desktop/*
96 | install -Dm755 desktop/terminal.desktop ${WORK_ROOT_DIR}/home/${JETSON_USR}/Desktop/terminal.desktop
97 |
98 | chroot ${WORK_ROOT_DIR} bash -c "chmod +x /home/${JETSON_USR}/Desktop/*.desktop"
99 | chroot ${WORK_ROOT_DIR} bash -c "chown ${JETSON_USR}:${JETSON_USR} /home/${JETSON_USR}/Desktop/*.desktop"
100 |
101 | echo "Start onboard"
102 | install -Dm644 onboard/onboard-defaults.conf ${WORK_ROOT_DIR}/usr/share/onboard/onboard-defaults.conf
103 | install -Dm644 onboard/onboard-autostart.desktop ${WORK_ROOT_DIR}/home/${JETSON_USR}/.config/autostart/onboard-autostart.desktop
104 |
105 | echo "Set owner ${JETSON_USR} for .config"
106 | chroot ${WORK_ROOT_DIR} bash -c "chown -R ${JETSON_USR}:${JETSON_USR} /home/${JETSON_USR}/.config"
107 |
108 | # echo "Install extra packages"
109 | # chroot ${WORK_ROOT_DIR} apt install -y --no-install-recommends \
110 | # xfce4-whiskermenu-plugin
111 |
112 | echo "Disable nvgetty to take control ttyTHS1"
113 | chroot ${WORK_ROOT_DIR} systemctl disable nvgetty
114 |
115 | echo "Add user to groups"
116 | chroot ${WORK_ROOT_DIR} usermod -a -G tty,dialout,gpio ${JETSON_USR}
117 |
118 | echo "Clean up"
119 | chroot ${WORK_ROOT_DIR} apt autoremove -y
120 | chroot ${WORK_ROOT_DIR} apt clean
121 |
122 | echo "Remove qemu-aarch64-static"
123 | rm -f ${WORK_ROOT_DIR}/usr/bin/qemu-aarch64-static
124 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/u-boot.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuquangtrong/jetson-custom-image/a63fb5ad3bc814ec3c31281142fd904fd4ef99cf/custom_bsp_for_nano_dev_kit/u-boot.bin
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/xfce/xfce4-desktop.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/custom_bsp_for_nano_dev_kit/xfce/xfce4-panel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/do_all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # do all defined steps
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 |
18 | source ./step0_env.sh
19 | ./step1_make_rootfs.sh
20 | ./step2_customize_rootfs.sh
21 | ./step3_apply_bsp.sh
22 | pushd custom_bsp_for_nano_dev_kit
23 | ./step3b_customize_bsp.sh
24 | popd
25 | ./step5_create_image.sh
26 |
27 | echo "Done!"
28 |
--------------------------------------------------------------------------------
/find_mirrors.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # thanks for Malte Skoruppa
4 | # https://askubuntu.com/questions/428698/are-there-alternative-repositories-to-ports-ubuntu-com-for-arm
5 |
6 | # URL of the Launchpad mirror list
7 | MIRROR_LIST=https://launchpad.net/ubuntu/+archivemirrors
8 |
9 | # Set to the architecture you're looking for (e.g., amd64, i386, arm64, armhf, armel, powerpc, ...).
10 | # See https://wiki.ubuntu.com/UbuntuDevelopment/PackageArchive#Architectures
11 | ARCH=$1
12 |
13 | # Set to the Ubuntu distribution you need (e.g., precise, saucy, trusty, ...)
14 | # See https://wiki.ubuntu.com/DevelopmentCodeNames
15 | DIST=$2
16 |
17 | # Set to the repository you're looking for (main, restricted, universe, multiverse)
18 | # See https://help.ubuntu.com/community/Repositories/Ubuntu
19 | REPO=$3
20 |
21 | # Set flags to check speed of repo
22 | SPDCHK=$4
23 |
24 | # First, we retrieve the Launchpad mirror list, and obtain a newline-separated list of HTTP mirrors
25 | mirrorList=()
26 | for url in $(curl -s $MIRROR_LIST | grep -Po 'http://.*(?=/">http)'); do
27 | # if [[ $url == *".vn"* ]]; then
28 | # echo $url
29 | mirrorList+=( "$url" )
30 | # fi
31 | done
32 |
33 |
34 | # Second, we try to connect to the site at `$url/dists/$DIST/$REPO/binary-$ARCH/`
35 | for url in "${mirrorList[@]}"; do
36 | (
37 | rurl=$url/dists/$DIST/$REPO/binary-$ARCH/
38 | # If you like some output while the script is running (feel free to comment out the following line)
39 | # echo "Processing $rurl"
40 | # retrieve the header; check if status code is 200
41 | if curl --connect-timeout 5 -s --head $rurl | head -n 1 | grep -q 'HTTP/[12].*200';
42 | then
43 | if [ $SPDCHK = "speed" ]
44 | then
45 | echo $(curl -s -w '%{time_total}\n' -o /dev/null $rurl) "$url"
46 | else
47 | echo "$url"
48 | fi
49 | fi
50 | ) &
51 | done
52 |
53 | wait
54 |
55 | echo "Search done!"
56 |
--------------------------------------------------------------------------------
/step0_env.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 0: set up environment
7 |
8 | ##########
9 | echo "Set target architecture"
10 |
11 | ARCH=arm64
12 |
13 | echo "Set target distro"
14 |
15 | # Ubuntu release version, e.g. Ubuntu 18.04.6
16 | RELEASE=bionic
17 |
18 | # Use below script to get the fastest repo, after that skip script to run faster
19 | # if [ -z "${REPO}" ]
20 | # then
21 | # REPO=$(./find_mirrors.sh ${ARCH} ${RELEASE} main speed | sort -k 1 | head -n 1 | awk '{print $2}')
22 | # fi
23 |
24 | REPO=http://repo.jing.rocks/ubuntu-ports
25 | # If REPO is empty, http://ports.ubuntu.com/ubuntu-ports will be used, or set a REPO below
26 |
27 | echo "Set target platform"
28 |
29 | JETSON_BOARD=jetson-nano-devkit
30 | JETSON_STORAGE=mmcblk0p1
31 | JETSON_BOARD_IMG=jetson-nano
32 | JETSON_BOARD_REV=300
33 | JETSON_PLAT=t210
34 | JETSON_REL=r32.7.5
35 | JETSON_BSP=jetson-210_linux_r32.7.5_aarch64.tbz2
36 | JETSON_BSP_URL=https://developer.nvidia.com/downloads/embedded/l4t/r32_release_v7.5/t210/jetson-210_linux_r32.7.5_aarch64.tbz2
37 |
38 | echo "Set target directories"
39 |
40 | ROOT_DIR=/tmp/jetson-custom/rootfs
41 | WORK_DIR=/tmp/jetson-custom/build
42 |
43 | echo "Set system users"
44 |
45 | ROOT_PWD=root
46 | JETSON_NAME=nvidia
47 | JETSON_USR=jetson
48 | JETSON_PWD=cccccc
49 |
50 | echo "Set desktop manager"
51 |
52 | # leave it empty to not install any DE
53 | # JETSON_DESKTOP=
54 |
55 | # just a minimal desktop
56 | # JETSON_DESKTOP=openbox
57 |
58 | # some panels from lxde
59 | # JETSON_DESKTOP=lxde
60 |
61 | # look better and lightweight
62 | JETSON_DESKTOP=xubuntu
63 |
64 | # more similar to ubuntu
65 | # JETSON_DESKTOP=ubuntu-mate
66 |
67 | echo "Set network settings"
68 |
69 | WIFI_SSID=
70 | WIFI_PASS=
71 |
72 | ##########
73 | echo "Prepare environment"
74 |
75 | mkdir -p ${ROOT_DIR}
76 | mkdir -p ${WORK_DIR}
77 |
78 | echo "ARCH = ${ARCH}"
79 | echo "RELEASE = ${RELEASE}"
80 | echo "REPO = ${REPO}"
81 |
82 | echo "JETSON_PLAT = ${JETSON_PLAT}"
83 | echo "JETSON_REL = ${JETSON_REL}"
84 | echo "JETSON_BSP = ${JETSON_BSP}"
85 | echo "JETSON_BSP_URL = ${JETSON_BSP_URL}"
86 |
87 | echo "ROOT_DIR = ${ROOT_DIR}"
88 | echo "WORK_DIR = ${WORK_DIR}"
89 |
90 | echo "ROOT_PWD =${ROOT_PWD}"
91 | echo "JETSON_NAME = ${JETSON_NAME}"
92 | echo "JETSON_USR = ${JETSON_USR}"
93 | echo "JETSON_PWD = ${JETSON_PWD}"
94 | echo "JETSON_DESKTOP = ${JETSON_DESKTOP}"
95 |
96 | echo "WIFI_SSID = ${WIFI_SSID}"
97 | echo "WIFI_PASS = ${WIFI_PASS}"
98 |
--------------------------------------------------------------------------------
/step1_make_rootfs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 1: make rootfs
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ./step0_env.sh
20 |
21 | ##########
22 | echo "Set script options"
23 |
24 | set -e # exit on error
25 | set -o pipefail # exit on pipeline error
26 | set -u # treat unset variable as error
27 |
28 | ##########
29 | echo "Install tools"
30 |
31 | apt install -y --no-install-recommends \
32 | qemu-user-static \
33 | debootstrap \
34 | binfmt-support \
35 | libxml2-utils
36 |
37 | ##########
38 | echo "Debootstrap a base"
39 |
40 | # create a zip file for laster use
41 | # delete the zip file to get new version of packages
42 | # however, app packages will be updated later
43 | if [ ! -f ${ARCH}-${RELEASE}.tgz ]
44 | then
45 | echo "Download packages to ${ARCH}-${RELEASE}.tgz"
46 | debootstrap \
47 | --verbose \
48 | --foreign \
49 | --arch=${ARCH} \
50 | ${RELEASE} \
51 | ${ROOT_DIR} \
52 | ${REPO}
53 | tar -cvzf ${ARCH}-${RELEASE}.tgz -C ${ROOT_DIR} .
54 | fi
55 |
56 | echo "Install packages from ${ARCH}-${RELEASE}.tgz"
57 | rm -rf ${ROOT_DIR}
58 | mkdir -p ${ROOT_DIR}
59 | tar -xvzf ${ARCH}-${RELEASE}.tgz -C ${ROOT_DIR}
60 |
61 | ##########
62 | echo "Install virtual machine"
63 |
64 | # qemu-aarch64-static will be called by chroot
65 | install -Dm755 $(which qemu-aarch64-static) ${ROOT_DIR}/usr/bin/qemu-aarch64-static
66 |
67 | # ubuntu-keyring package can be installed, but this way is a bit faster ?
68 | install -Dm644 /usr/share/keyrings/ubuntu-archive-keyring.gpg ${ROOT_DIR}/usr/share/keyrings/ubuntu-archive-keyring.gpg
69 |
70 | ##########
71 | echo "Unpack ${ROOT_DIR}"
72 |
73 | chroot ${ROOT_DIR} /debootstrap/debootstrap --second-stage
74 |
--------------------------------------------------------------------------------
/step2_customize_rootfs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 2: customize rootfs
7 |
8 | ./step2a_install.sh # run installation
9 | ret=$? # return 0 if no error
10 | if [ $ret -ne 0 ]; then
11 | ./step2b_cleanup.sh # clean up if something is wrong
12 | fi
13 |
--------------------------------------------------------------------------------
/step2a_install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 2: customize rootfs
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ./step0_env.sh
20 |
21 | ##########
22 | echo "Set script options"
23 |
24 | set -e # exit on error
25 | set -o pipefail # exit on pipeline error
26 | set -u # treat unset variable as error
27 |
28 | ##########
29 | echo "Mount dependency points"
30 |
31 | # these mount points are needed for chroot?
32 | # if script halts before unmounting these point, you have to unmount manually
33 | # that is the reason, this script is called in a wrapper, see step2_customize_rootfs.sh
34 | for mnt in sys proc dev dev/pts tmp; do
35 | mount -o bind "/$mnt" "${ROOT_DIR}/$mnt"
36 | done
37 |
38 | ##########
39 | echo "Setup locale"
40 |
41 | chroot ${ROOT_DIR} locale-gen en_US
42 | chroot ${ROOT_DIR} locale-gen en_US.UTF-8
43 | chroot ${ROOT_DIR} update-locale LC_ALL=en_US.UTF-8
44 |
45 | ##########
46 | echo "Add nameserver"
47 |
48 | cat << EOF > ${ROOT_DIR}/etc/resolv.conf
49 | nameserver 8.8.8.8
50 | nameserver 8.8.4.4
51 | EOF
52 |
53 | ##########
54 | echo "Add repos for ${ARCH}"
55 |
56 | cat << EOF > ${ROOT_DIR}/etc/apt/apt.conf.d/99verify-peer.conf
57 | Acquire::https::Verify-Peer "false";
58 | Acquire::https::Verify-Host "false";
59 | EOF
60 |
61 | cat << EOF > ${ROOT_DIR}/etc/apt/sources.list
62 | deb [arch=${ARCH}] ${REPO} ${RELEASE} main restricted universe multiverse
63 | deb [arch=${ARCH}] ${REPO} ${RELEASE}-updates main restricted universe multiverse
64 | deb [arch=${ARCH}] ${REPO} ${RELEASE}-security main restricted universe multiverse
65 | EOF
66 |
67 | ##########
68 | echo "Update repo source list"
69 |
70 | chroot ${ROOT_DIR} apt update
71 | chroot ${ROOT_DIR} apt upgrade -y
72 |
73 | ##########
74 | echo "Install required packages"
75 |
76 | # below packages are needed for installing Jetson packages in step #3
77 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
78 | libasound2 \
79 | libcairo2 \
80 | libdatrie1 \
81 | libegl1 \
82 | libegl1-mesa \
83 | libevdev2 \
84 | libfontconfig1 \
85 | libgles2 \
86 | libgstreamer1.0-0 \
87 | libgstreamer-plugins-base1.0-0 \
88 | libgstreamer-plugins-bad1.0-0 \
89 | libgtk-3-0 \
90 | libharfbuzz0b \
91 | libinput10 \
92 | libjpeg-turbo8 \
93 | libpango-1.0-0 \
94 | libpangocairo-1.0-0 \
95 | libpangoft2-1.0-0 \
96 | libpixman-1-0 \
97 | libpng16-16 \
98 | libunwind8 \
99 | libwayland-client0 \
100 | libwayland-cursor0 \
101 | libwayland-egl1-mesa \
102 | libx11-6 \
103 | libxext6 \
104 | libxkbcommon0 \
105 | libxrender1 \
106 | python \
107 | python3 \
108 |
109 | ##########
110 | echo "Install systen packages"
111 |
112 | # below packages are needed for systen
113 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
114 | wget \
115 | curl \
116 | linux-firmware \
117 | device-tree-compiler \
118 | network-manager \
119 | net-tools \
120 | wireless-tools \
121 | ssh \
122 |
123 | ##########
124 | echo "Install X GUI"
125 |
126 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
127 | xorg
128 |
129 | if [ ! -z ${JETSON_DESKTOP} ]; then
130 |
131 | if [ ${JETSON_DESKTOP} == 'openbox' ]; then
132 | echo "Install Openbox"
133 |
134 | # minimal desktop, only greeter, no taskbar and background
135 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
136 | lightdm-gtk-greeter \
137 | lightdm \
138 | openbox \
139 |
140 | fi
141 |
142 | if [ ${JETSON_DESKTOP} == 'lxde' ]; then
143 | echo "Install LXDE core"
144 |
145 | # lxde with some components
146 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
147 | lightdm-gtk-greeter \
148 | lightdm \
149 | lxde-icon-theme \
150 | lxde-core \
151 | lxde-common \
152 | policykit-1 lxpolkit \
153 | lxsession-logout \
154 | gvfs-backends \
155 |
156 | fi
157 |
158 | if [ ${JETSON_DESKTOP} == 'xubuntu' ]; then
159 | echo "Install Xubuntu core"
160 |
161 | # Xubuntu, better than lxde
162 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
163 | xubuntu-core \
164 |
165 | fi
166 |
167 | if [ ${JETSON_DESKTOP} == 'ubuntu-mate' ]; then
168 | echo "Install Ubuntu Mate"
169 |
170 | # Ubuntu-Mate, similar to Ubuntu
171 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
172 | ubuntu-mate-core \
173 |
174 | fi
175 |
176 | # below packages are needed for desktop
177 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
178 | onboard \
179 |
180 | fi
181 |
182 | ##########
183 | echo "Install extra packages"
184 |
185 | # below packages are needed for desktop
186 | chroot ${ROOT_DIR} apt install -y --no-install-recommends \
187 | htop \
188 | nano \
189 |
190 | ##########
191 | echo "Clean up"
192 |
193 | chroot ${ROOT_DIR} apt autoremove -y
194 | chroot ${ROOT_DIR} apt clean
195 |
196 | ##########
197 | echo "Set up networks"
198 |
199 | # Since Ubuntu 18.04, netplan does not use /etc/network/interfaces anymore
200 | if [ ! -z ${WIFI_SSID} ]; then
201 | cat << EOF > ${ROOT_DIR}/etc/netplan/01-netconf.yaml
202 | network:
203 | version: 2
204 | renderer: NetworkManager
205 | ethernets:
206 | eth0:
207 | optional: true
208 | dhcp4: true
209 | # add wifi setup information here ...
210 | wifis:
211 | wlan0:
212 | access-points:
213 | "${WIFI_SSID}":
214 | password: "${WIFI_PASS}"
215 | dhcp4: true
216 | dhcp4-overrides:
217 | route-metric: 50
218 | EOF
219 | fi
220 |
221 | cat << EOF > ${ROOT_DIR}/etc/hostname
222 | ${JETSON_NAME}
223 | EOF
224 |
225 | ##########
226 | echo "Unmount dependency points"
227 |
228 | for mnt in tmp dev/pts dev proc sys; do
229 | umount "${ROOT_DIR}/$mnt"
230 | done
231 |
--------------------------------------------------------------------------------
/step2b_cleanup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 2: customize rootfs
7 |
8 | ##########
9 | echo "Get environment"
10 |
11 | . ./step0_env.sh
12 |
13 | ##########
14 | echo "Set script options"
15 |
16 | set -e # exit on error
17 | set -o pipefail # exit on pipeline error
18 | set -u # treat unset variable as error
19 |
20 | ##########
21 | echo "Unmount dependency points"
22 |
23 | for mnt in dev/pts dev proc sys; do
24 | umount "${ROOT_DIR}/$mnt"
25 | done
26 |
--------------------------------------------------------------------------------
/step2c_fix_broken_install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 2: customize rootfs
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ../jetson-custom-image/step0_env.sh
20 |
21 | ##########
22 | echo "Set script options"
23 |
24 | set -e # exit on error
25 | set -o pipefail # exit on pipeline error
26 | set -u # treat unset variable as error
27 |
28 | ##########
29 | echo "Mount dependency points"
30 |
31 | # these mount points are needed for chroot?
32 | # if script halts before unmounting these point, you have to unmount manually
33 | # that is the reason, this script is called in a wrapper, see step2_customize_rootfs.sh
34 | for mnt in sys proc dev dev/pts tmp; do
35 | mount -o bind "/$mnt" "${ROOT_DIR}/$mnt"
36 | done
37 |
38 | ##########
39 | echo "Add repos for ${ARCH}"
40 |
41 | cat << EOF > ${ROOT_DIR}/etc/apt/apt.conf.d/99verify-peer.conf
42 | Acquire::https::Verify-Peer "false";
43 | Acquire::https::Verify-Host "false";
44 | EOF
45 |
46 | cat << EOF > ${ROOT_DIR}/etc/apt/sources.list
47 | deb [arch=${ARCH}] ${REPO} ${RELEASE} main restricted universe multiverse
48 | deb [arch=${ARCH}] ${REPO} ${RELEASE}-updates main restricted universe multiverse
49 | deb [arch=${ARCH}] ${REPO} ${RELEASE}-security main restricted universe multiverse
50 | EOF
51 |
52 | ##########
53 | echo "Update repo source list"
54 |
55 | chroot ${ROOT_DIR} apt install --fix-broken
56 |
57 | ##########
58 | echo "Unmount dependency points"
59 |
60 | for mnt in tmp dev/pts dev proc sys; do
61 | umount "${ROOT_DIR}/$mnt"
62 | done
63 |
--------------------------------------------------------------------------------
/step3_apply_bsp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 3: apply JETSON_BSP
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ./step0_env.sh
20 |
21 | ##########
22 | echo "Set script options"
23 |
24 | set -e # exit on error
25 | set -o pipefail # exit on pipeline error
26 | set -u # treat unset variable as error
27 |
28 | ##########
29 |
30 | if [ ! -f ${JETSON_BSP} ]; then
31 | echo "Download JETSON_BSP"
32 | wget ${JETSON_BSP_URL}
33 | fi
34 |
35 | ##########
36 |
37 | if [ ! -d ${WORK_DIR}/Linux_for_Tegra ]; then
38 | echo "Extract JETSON_BSP"
39 | tar jxpf ${JETSON_BSP} -C ${WORK_DIR}
40 | fi
41 |
42 | ##########
43 | echo "Copy rootfs"
44 |
45 | rm -rf ${WORK_DIR}/Linux_for_Tegra/rootfs
46 | cp -rf ${ROOT_DIR} ${WORK_DIR}/Linux_for_Tegra/
47 |
48 | # below device files conflict with L4T package install
49 | declare -a remove_files=(
50 | "dev/random"
51 | "dev/urandom"
52 | )
53 |
54 | for file in "${remove_files[@]}"; do
55 | uri=${WORK_DIR}/Linux_for_Tegra/rootfs/$file
56 | if [ -e "$uri" ]
57 | then
58 | rm -f $uri
59 | fi
60 | done
61 |
62 | ##########
63 | echo "Set up permission"
64 |
65 | # copy from rootfs to L4T does not keep the sudo flag
66 | # so, do set the flag here
67 | chroot ${WORK_DIR}/Linux_for_Tegra/rootfs bash -c "echo root:$ROOT_PWD | chpasswd"
68 | chroot ${WORK_DIR}/Linux_for_Tegra/rootfs bash -c "chown root:root /usr/bin/sudo"
69 | chroot ${WORK_DIR}/Linux_for_Tegra/rootfs bash -c "chmod u+s /usr/bin/sudo"
70 |
71 | # this to fix error when install package
72 | chroot ${WORK_DIR}/Linux_for_Tegra/rootfs bash -c "chown -R man:man /var/cache/man"
73 | chroot ${WORK_DIR}/Linux_for_Tegra/rootfs bash -c "chmod -R 775 /var/cache/man"
74 |
75 | ##########
76 | echo "Apply jetson binaries"
77 |
78 | pushd ${WORK_DIR}/Linux_for_Tegra/
79 | ./apply_binaries.sh
80 | popd
81 |
82 | ##########
83 | echo "Add user: ${JETSON_USR}"
84 |
85 | pushd ${WORK_DIR}/Linux_for_Tegra/tools
86 | # ./l4t_create_default_user.sh -u ${JETSON_USR} -p ${JETSON_PWD} -n ${JETSON_NAME} --accept-license
87 | ./l4t_create_default_user.sh -u ${JETSON_USR} -p ${JETSON_PWD} -n ${JETSON_NAME} --autologin --accept-license
88 | popd
89 |
90 | cat << EOF > ${WORK_DIR}/Linux_for_Tegra/rootfs/etc/sudoers.d/${JETSON_USR}
91 | ${JETSON_USR} ALL=(ALL) NOPASSWD: ALL
92 | EOF
93 |
94 |
95 | ##########
96 | # if you want to modify BSP, please do that here
97 | # e.g.
98 | # ./custom_bsp_for_nano_dev_kit/step3b_customize_bsp.sh
--------------------------------------------------------------------------------
/step4_flash.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 4: flash image
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ./step0_env.sh
20 |
21 | ##########
22 | echo "Set script options"
23 |
24 | set -e # exit on error
25 | set -o pipefail # exit on pipeline error
26 | set -u # treat unset variable as error
27 |
28 | ##########
29 | echo "Flash image"
30 |
31 | pushd ${WORK_DIR}/Linux_for_Tegra
32 |
33 | ./flash.sh ${JETSON_BOARD} ${JETSON_STORAGE}
34 |
--------------------------------------------------------------------------------
/step5_create_image.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 5: create image
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ./step0_env.sh
20 |
21 | ##########
22 | echo "Set script options"
23 |
24 | set -e # exit on error
25 | set -o pipefail # exit on pipeline error
26 | set -u # treat unset variable as error
27 |
28 | ##########
29 | IMAGE=${JETSON_BOARD}_${RELEASE}_${JETSON_PLAT}_${JETSON_REL}_${JETSON_DESKTOP}.img
30 | echo "Create image ${IMAGE}"
31 |
32 | pushd ${WORK_DIR}/Linux_for_Tegra/tools
33 |
34 | ./jetson-disk-image-creator.sh -o ${IMAGE} -b ${JETSON_BOARD_IMG} -r ${JETSON_BOARD_REV}
35 |
36 | if [ -f ${IMAGE} ]; then
37 | echo "Please copy the image at ${IMAGE}"
38 | fi
39 |
--------------------------------------------------------------------------------
/step6_flash_SD.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a base custom image for jetson nano
4 | # vuquangtrong@gmail.com
5 | #
6 | # step 6: flash SD card
7 |
8 | ##########
9 | echo "Check root permission"
10 |
11 | if [ "x$(whoami)" != "xroot" ]; then
12 | echo "This script requires root privilege!!!"
13 | exit 1
14 | fi
15 |
16 | ##########
17 | echo "Get environment"
18 |
19 | source ./step0_env.sh
20 |
21 | ##########
22 | echo "Set script options"
23 |
24 | set -e # exit on error
25 | set -o pipefail # exit on pipeline error
26 | set -u # treat unset variable as error
27 |
28 | ##########
29 | echo "Check that $1 is a block device"
30 |
31 | if [ ! -b $1 ] || [ "$(lsblk | grep -w $(basename $1) | awk '{print $6}')" != "disk" ]; then
32 | echo "$1 is not a block device!!!"
33 | exit 1
34 | fi
35 |
36 | ##########
37 | IMAGE=${WORK_DIR}/Linux_for_Tegra/tools/${JETSON_BOARD}_${RELEASE}_${JETSON_PLAT}_${JETSON_REL}_${JETSON_DESKTOP}.img
38 | echo "Using ${IMAGE}"
39 |
40 |
41 | ##########
42 | if [ "$(mount | grep $1)" ]; then
43 | echo "Unmount $1"
44 | for mount_point in $(mount | grep $1 | awk '{ print $1}'); do
45 | sudo umount $mount_point
46 | done
47 | fi
48 |
49 | ##########
50 | echo "Flash $1"
51 | dd if=${IMAGE} of=$1 bs=4M conv=fsync status=progress
52 |
53 | ##########
54 | echo "Extend the partition"
55 |
56 | partprobe $1
57 | sgdisk -e $1
58 |
59 | end_sector=$(sgdisk -p $1 | grep -i "Total free space is" | awk '{ print $5 }')
60 | start_sector=$(sgdisk -i 1 $1 | grep "First sector" | awk '{print $3}')
61 |
62 | echo "start_sector = ${start_sector}"
63 | echo "end_sector = ${end_sector}"
64 |
65 | sgdisk -d 1 $1
66 | sgdisk -n 1:${start_sector}:${end_sector} $1
67 | sgdisk -c 1:APP $1
68 |
69 | ##########
70 | echo "Extend the filesystem"
71 |
72 | if [[ $(basename $1) =~ mmc ]]; then
73 | e2fsck -fp $1"p1"
74 | resize2fs $1"p1"
75 | fi
76 |
77 | if [[ $(basename $1) =~ sd ]]; then
78 | e2fsck -fp $1"1"
79 | resize2fs $1"1"
80 | fi
81 |
82 | sync
83 |
84 | echo "DONE!"
85 |
--------------------------------------------------------------------------------