顯示具有 embedded linux 標籤的文章。 顯示所有文章
顯示具有 embedded linux 標籤的文章。 顯示所有文章

2025年12月18日 星期四

Making Jetson Nano Filesystem Tolerant to Power Loss with a Read-Only Rootfs


Jetson Nano boots and runs its root filesystem directly from an SD card, which makes the system fragile under real-world power conditions. Sudden power loss can corrupt the filesystem, and in many cases the entire SD card becomes unbootable and must be fully re-imaged. After this happens a few times, the card itself may no longer be reliable at all.

This post records a set of system-level skills used to make Jetson Nano more tolerant to power cuts and unstable power sources. The focus is simple: minimize runtime writes to the SD card, reduce the chance of filesystem corruption, and—when appropriate—avoid writing to the SD card altogether.
The approaches covered include : (⭐represents the level of power-loss tolerance)

  • SWAP tuning for system stability : reducing swap-induced SD card writes ⭐⭐
  • Journald to RAM : keeping system logs off the SD card ⭐⭐⭐⭐
  • TMPFS for /tmp : avoiding temporary file writes to disk ⭐⭐⭐
  • Disable access-time logging : reducing filesystem metadata writes on read ⭐
  • Dirty page flush tuning : adjusting kernel write-back timing ⭐⭐⭐⭐
  • Enable hardware watchdog auto-reboot : automatic recovery from hard freezes ⭐
  • Root filesystem overlay via initramfs switch : eliminating runtime writes to the system partition ⭐⭐⭐⭐⭐

※  The last one, overlay mode is the ultimate protection against SD card corruption. However, it is not suitable during active development, where a writable root filesystem is often required. Running in writable mode restores flexibility, but also removes this layer of protection.

Not all methods need to be applied together. For development systems, applying ⭐⭐⭐ and above items is usually sufficient (overlay excluded).

一. SWAP tuning for system stability ⭐⭐


Swap allows the kernel to move inactive memory pages from RAM to secondary storage when RAM is under pressure. On Jetson Nano, swap typically resides on the SD card, which effectively turns the SD card into very slow and wear-prone RAM.

The swappiness parameter controls how aggressively the kernel starts using swap, expressed as a percentage threshold. The default value is 60, meaning the kernel will begin swapping relatively early even when a significant amount of RAM is still available. Lowering this value reduces SD card writes and improves tolerance to abrupt power loss, at the cost of potential lag when RAM is fully exhausted.

※ This tuning is useful in normal (non-overlay) systems. It is not needed when running with a fully read-only root filesystem and RAM overlay.

Check current swappiness:

cat /proc/sys/vm/swappiness

(Default is 60 unless previously modified.)

Set swappiness to 10 via sysctl: 

sudo vi /etc/sysctl.d/99-swappiness.conf

Add the line:

vm.swappiness=10

Apply and verify:

sudo sysctl -p /etc/sysctl.d/99-swappiness.conf
cat /proc/sys/vm/swappiness

Or simply reboot:

sudo reboot

Inspect current swap usage:

cat /proc/swaps
swapon --show
free -h

(Optional) Recreate swap file

Only needed if your current /swapfile is too small or has been removed.

Disable and remove the old swap file:

sudo swapoff /swapfile
sudo rm /swapfile

Create a new 1 GB swap file:

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Enable it at boot:

sudo vi /etc/fstab

Add the line:

/swapfile swap swap defaults 0 0

Confirm:

swapon --show


二. Journald to RAM ⭐⭐⭐⭐

By default, systemd-journald can store logs on disk under /var/log/journal, which creates continuous writes on an SD card. Switching journald to volatile mode keeps logs in RAM (/run/log/journal), so they disappear after reboot and no longer wear the SD card during normal operation.

※ Not needed in full read-only + RAM overlay mode.

Switch journald to RAM-only by modify the file journald.conf:

# sudo vi /etc/systemd/journald.conf

# Change or add journal storage setting
Storage=volatile       # Always store logs in RAM (/run/log/journal)
#Storage=auto          # Use RAM if /var/log/journal does not exist, otherwise use disk
#Storage=persistent    # Always store logs on disk (/var/log/journal)

SystemMaxFileSize=32M  # Limit individual journal file size

Restart journald or reboot:

# Restart journald service
sudo systemctl restart systemd-journald

# Or reboot to apply
sudo reboot

Verify usage and location:

# Check disk usage of journal
journalctl --disk-usage

# Check actual journal storage location
journalctl --verify

# → Shows /run/log/journal if stored in RAM (volatile mode)
# → Shows /var/log/journal if stored on disk (persistent mode)

三. TMPFS for /tmp ⭐⭐⭐

/tmp is used for short-lived temporary files. Mounting it as tmpfs keeps these writes in RAM instead of on the SD card, reducing wear at the cost of some RAM usage.

※ Not needed if a read-only root filesystem with overlay is already enabled, but useful in normal writable mode.

Configure /tmp as tmpfs

# Mount /tmp in RAM (512MB)
# sudo vi /etc/fstab

# Add line:
/tmpfs /tmp tmpfs defaults,noatime,nosuid,nodev,size=512M,mode=1777 0 0

Apply without reboot (or reboot)

# Mount now without reboot
sudo mount -a
mount | grep /tmp

# Or reboot to apply
sudo reboot

Confirm usage

# Confirm /tmp is mounted as tmpfs
findmnt /tmp

# Show how much space is used in /tmp
sudo du -sh /tmp

四. Disable access-time logging on root filesystem ⭐

By default, every file or directory read can update its access time (atime) on disk. Disabling access-time logging stops these updates on read operations, while file modification times are still recorded as usual.

※ Useful in normal writable mode to reduce unnecessary SD card writes. Has no effect when a read-only overlay is active.

Edit root filesystem mount options

# Remove access-time logging on root filesystem
# sudo vi /etc/fstab

# Replace:
/dev/root / ext4 defaults 0 1

# With:
/dev/root / ext4 defaults,noatime,nodiratime,errors=remount-ro 0 1

Reboot and verify

# Reboot to apply
sudo reboot

# Output should show "noatime,nodiratime" in mount options
mount | grep 'on / '

五. Dirty page flush tuning ⭐⭐⭐⭐

When an application writes data, the kernel does not immediately write it to disk. Instead, the data is temporarily kept in RAM as dirty pages and written back to disk later in batches. This improves performance, but increases the risk of data loss if power is suddenly cut.

By flushing dirty pages to disk earlier and more frequently, the time window during which written data exists only in RAM is reduced, improving resilience against power loss.

※ Useful in normal writable mode when minimizing data loss on power failure. Has no effect in read-only or overlay modes.

Create a dirty-page tuning config

sudo vi /etc/sysctl.d/99-dirty-flush.conf

Add:

# Start background writeback at 5% dirty memory (default: 10%)
vm.dirty_background_ratio=5

# Block new writes at 10% dirty memory (default: 20%)
vm.dirty_ratio=10

# Force writeback after 5 seconds (default: 30 seconds)
vm.dirty_expire_centisecs=500

# Check for dirty pages every 1 second (default: 5 seconds)
vm.dirty_writeback_centisecs=100

Reboot and verify

sudo reboot

# Verify dirty page parameters
sysctl -a | grep dirty

六. Enable hardware watchdog auto-reboot ⭐

If the system hard-freezes, a hardware watchdog can automatically reboot the device when it stops responding. Jetson Nano provides a built-in watchdog that can be managed by systemd.

In practice, this mainly acts as a last-resort recovery mechanism for complete system hangs, and does not prevent data corruption by itself.

※ Optional. Mostly relevant for unattended or appliance-style systems; limited benefit during active development.

Check watchdog support

zcat /proc/config.gz | grep -Ei 'dog|tegra_wdt'

You should see entries indicating that the Tegra watchdog is enabled in the kernel.

Test the watchdog directly (forces reboot)

sudo sh -c 'echo V > /dev/watchdog'

If working, the system should reboot after roughly one minute.
Do NOT run this on a system with unsaved work.

Configure systemd to use the watchdog

sudo vi /etc/systemd/system.conf

Set:

RuntimeWatchdogSec=30

Reboot and confirm

sudo reboot

# Verify watchdog timeout
systemctl show --property=RuntimeWatchdogUSec

The reported value should correspond to 30 seconds.


七. Root filesystem overlay via initramfs switch ⭐⭐⭐⭐⭐

All previous sections aim to make a writable, SD-card–based system less fragile. However, for real deployments where power loss is expected, the only robust approach is to stop writing to the system partition entirely.

An initramfs-based root filesystem overlay achieves this by mounting the base root filesystem as read-only and redirecting all runtime writes to a RAM-backed overlay. The system runs normally, but any changes made at runtime are discarded on reboot unless explicitly committed in writable mode.

※ Ideal for deployment, but largely unusable during active development, where a writable root filesystem is required.
※ Any data that must persist at runtime must be stored on a separate, non-system partition; this typically requires explicit disk partitioning and mount configuration.

Clone the overlay setup tool

git clone https://github.com/lehni/root-ro.git
cd root-ro

Install the Jetson Nano preset

sudo ./install-nano.sh

This installs a custom initramfs and helper tools that allow booting into either:

  • Read-only root filesystem with a tmpfs overlay (normal safe mode)

  • Fully writable root filesystem (maintenance / upgrade mode)

Reboot into readonly or writable mode

sudo reboot-ro   # Boot with overlay (rootfs effectively read-only)
sudo reboot-rw   # Boot with normal writable rootfs

Switch mode temporarily without full reboot (for testing)

mount-ro   # Remount with overlay (read-only)
mount-rw   # Remount writable (with chroot)

The exact behavior of these commands depends on the root-ro tool’s implementation. The intended workflow is to perform development, debugging, and system updates in writable mode, then return to read-only mode for normal operation.



2025年5月14日 星期三

Ensure SD Card Backups Are Flashable to Any Same-Size Card for Jetson Nano

 ※if you are not interested in the manual steps as below, there is a script to deal with the equivalent procedures for 64GB. It might also work for the other sizes if you adjust the variable LABELED_GB to match your SD card labeled capacity in GB, but this has not been tested. 
# Make the script executable (only needed once)
# chmod +x backup_jetson_nano_64GB_img.sh
sudo ./backup_jetson_nano_64GB_img.sh jetson.img /dev/sdX
# Run without arguments to show help
# ./backup_jetson_nano_64GB_img.sh
Morerover, it may be necesary to read the last session 補說 to know how to use the fully SD card capacity before flashing.

Cloning a Jetson Nano SD card with dd creates a full-size image — but not all SD cards labeled with the same size have the identical usable capacity. Some may be a few megabytes smaller, which will lead to the flashing error : Target device is too small. 

On the other hand,  if you flash the image to the larger SD card(e.g. from 64 GB to 128 GB), The system is likely to fail to boot.

This guide shows how to safely trim the unused space at the end of the imae, align it properly, and fix GPT headers — so your .img backup can be reliably flashed to other SD cards of the same advertised size (e.g. 64GB) using Etcher or dd.

零. Full backup SD card to .img

Insert the SD card and identify the device name:
lsblk -dpno NAME,SIZE,MODEL | grep -Ev 'loop|nvme|sda|boot'
Example output:
/dev/sdb     58.2G   SD/MMC

In this case, the SD card is /dev/sdb.

Create a full image backup:

sudo dd if=/dev/sdx of=jetson_backup.img bs=16M status=progress conv=fsync

Replace /dev/sdX with your SD card device. You can rename jetson_backup.img as needed.


壹. Shrink main partition and truncate the image size

Attach image as loop device:
sudo losetup -Pf --show jetson_backup.img
Example output:
/dev/loop47

Use GParted to shrink the main partition:
sudo gparted /dev/loop47

To shrink the largest ext4 partition (usually labeled "APP" — typically the root partition in Jetson Nano images), follow the steps below:

  • Right-click on the APP partition (such as /dev/loop47p1, ext4, 59.51 GiB in the screenshot).

  • Select "Resize/Move" from the context menu.

  • In the "Resize/Move" dialog:

    • Set "Free space following (MiB)" to 8192 (i.e., 8 GiB).

    • Do NOT change "Free space preceding(MiB)" value.

    • Click the "Resize/Move" button to return to the main GParted window and confirm the change.

  • Go to Edit → Apply All Operations to apply the shrink operation.

Detach the loop device:
sudo losetup -d /dev/loop47



貳. Extend image by 1 MB buffer and align to 512 bytes

Find the partition end (in bytes):
sudo parted jetson_backup.img unit B print
Example output:
Number  Start       End            Size            File system  Name
1       14680064B   63892881407B   63878201344B    ext4         APP
In this example, the end is 63892881407.

Then:
# Add 1MB buffer (1,048,576 bytes)
# 63892881407 + 1048576 = 63893929983
sudo truncate -s 63893929983 jetson_backup.img

Align to next 512-byte boundary (required for GPT):
sudo truncate -s $(( ( $(stat -c %s jetson_backup.img) / 512 + 1 ) * 512 )) \
jetson_backup.img 



參. Fix GPT backup header and verify partition table

Start gdisk:
sudo gdisk jetson_backup.img
In the gdisk prompt, type:
w
y

Inspect the partition table to ensure there are no errors
sudo gdisk -l jetson_backup.img
sudo fdisk -l jetson_backup.img 


肆. (Optional) Compress image 

Zip the image file:
zip -9 -v jetson_backup.img.zip jetson_backup.img

Then, remove the image:
rm jetson_backup.img


補說. Flash the image to the SD card and fully use its capacity.

You can flash either the .img or .img.zip file using:

Etcher (balenaEtcher)
Or via terminal for flashing the .img:
sudo dd if=jetson_backup.img of=/dev/sdX bs=16M status=progress conv=fsync

Optional but recommended: After flashing, you may run the following to relocate the GPT backup header to the actual end of the card (avoids partition warnings):
sudo sgdisk -e /dev/sdX # Relocate the GPT backup header

Optional: Extend the ext4 partition ("APP") to use the full capacity of the SD card.
sudo growpart  /dev/sdX 1     # Expand the APP partition
sudo resize2fs -f /dev/sdX1   # Resize the ext4 filesystem
sudo gdisk -l /dev/sdX        # Verify that GPT looks correct


2019年7月10日 星期三

Cross-Compile the Qt Libraries for Nvidia® Jetson TX2 and Set the QtCreator Environment

   

※ 2021, 5, 28, update to Qt version 5.15.2.
  
     For some high-end use cases, like car self-driving, medical devices, telemetry equipments and so forth, the specifications for the devices are usually peculiar.Nvidia® Jetson series are for filling the requirements : the embedded systems integrated with the CUDA function : a special system, with the special peripherals and sensors, with the special computation ability for the special purpose.
 
    However, the Nvidia® Jetson documents for building the Qt Libraries are limited. So, I write this post to show how to cross-compile shared libraries, and set the environment and set the QtCreator for Jetson TX2 Qt applications. The same procedures also works for TX1.

   Due to the application on an embedded system is only for a specific purpose, the GUI system is not necessary to be window form : the whole system is for an application only. Therefore, maybe it is necessary to build the Qt libraries supporting with the full-screen form.


零. Download Jetpack and use it to flash the TX2.
    The Jetpacks is here, you need to register a Nvidia account for the downloading. I use v. 3.3.
    There are some detail tutorials and videos for the Jetpack setting, like this or this or this.  I denote 2 precautions here:

   甲. Your host Linux must be installed with xterm, or the Jetpack will be hanging while it should start downloading (after Network layout page).

  乙. You could not run the Jetpack on LXDE environment, or the Jetpack program would be hanging in the component manager page.


After the flashing has been done, make sure your host is able to connect to the TX2. You could use ssh command in your host, to check is the connection workable or not.

ssh nvidia@your_tx2_ip
the password is also nvidia in default.

※ How to set TX2 UART could be found here.


一. Prepare the necessary libraries and headers on TX2.
   ※The works are all in the TX2.

  甲. install some packets to support the Qt build.
sudo apt-get install '.*libxcb.*' libxrender-dev libxi-dev libfontconfig1-dev
libudev-dev libxkbcommon-dev libxkbcommon-x11-dev

   乙. Extract the GLES and EGL headers, and put them under /usr/include.
  The commands are :
mkdir /home/nvidia/GLES
cd /home/nvidia/GLES
apt-get download libgles2-mesa-dev
ar x libgles2*.deb
tar -xvf data.tar.xz
mkdir /home/nvidia/EGL
cd /home/nvidia/EGL
apt-get download libegl1-mesa-dev
ar x libegl1*.deb
tar -xvf data.tar.xz
cd /home/nvidia/GLES/usr/include
sudo cp -r GLES2 GLES3 /usr/include
cd /home/nvidia/EGL/usr/include
sudo cp -r EGL KHR /usr/include

   丙. Create a symbolic link libGLESv2.so  :
sudo ln -s /usr/lib/aarch64-linux-gnu/tegra-egl/libGLESv2.so.2 \
 /usr/lib/aarch64-linux-gnu/libGLESv2.so

  丁. To leave the Nvidia-built Qt librares intact, we prepare a new directory to content the new build :
mkdir /usr/local/qt5
sudo chown nvidia /usr/local/qt5

install some packets to support the Qt build
sudo apt-get install '.*libxcb.*' \
 libx11-xcb-dev libxrender-dev libxi-dev \
 libfontconfig1-dev libudev-dev \
 libxkbcommon-dev libxkbcommon-x11-dev \
 libgles2-mesa-dev libegl1-mesa libegl1-mesa-dev \
 libglu1-mesa-dev libxrender-dev libxi-dev \
 libinput*  \
 mesa-utils  mesa-utils-extra libgles2-mesa-dev
 To here, the work on TX2 comes a stop.


二. Prepare the cross-compilation environment in the host.
       ※ The works are in the host machine.
   甲. Create a directory as the TX2's rootfs , and change your current directory to that, then copy the necessary folders from the TX2:
#cd your_tx2_rootfs_in_your_host
rsync -avz -e ssh nvidia@your_tx2_ip:/lib/aarch64-linux-gnu lib
rsync -avz -e ssh nvidia@your_tx2_ip:/usr/include usr
rsync -avz -e ssh nvidia@your_tx2_ip:/usr/lib usr
rsync -avz -e ssh nvidia@your_tx2_ip:/usr/aarch64-linux-gnu usr

   乙. Fix the necessary symbolic links :
ln -sf $PWD/lib/aarch64-linux-gnu/libz.so.1  $PWD/usr/lib/aarch64-linux-gnu/libz.so
ln -sf $PWD/lib/aarch64-linux-gnu/libm.so.6  $PWD/usr/lib/aarch64-linux-gnu/libm.so
ln -sf $PWD/lib/aarch64-linux-gnu/libdl.so.2 $PWD/usr/lib/aarch64-linux-gnu/libdl.so
ln -sf $PWD/lib/aarch64-linux-gnu/libpng12.so.0.54.0  $PWD/usr/lib/aarch64-linux-gnu/libpng.so
※ The libpng version or location may be changed with the Jetpack version, you should use find -name libpng* under folder TX2_rootfs_in_the_host_path to find out where it is by checking what soft-links to TX2_rootfs_in_the_host_path/usr/lib/aarch64-linux-gnu/libpng.so

  丙. Install the prerequisite packages.
sudo apt-get install -y 'libxcb.*' \
    libx11-xcb-dev libglu1-mesa-dev \
    libxrender-dev libxi-dev libinput* \
    mtdev* mesa-utils \
    mesa-utils-extra libgles2-mesa-dev
※ Some packets may be not necessary.

  丁. Prepare the toolchain:
sudo apt-get install g++-aarch64-linux-gnu
  and use aarch64-linux-gnu-g++ -v  to check the version, I use g++ 7.X;   
Linaro GCC 5.5 is here,  please download  the gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xz file, and move it to an appropriate location, then extract it.
tar -xvf gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xz
  I strongly recommend you should NOT use the aarch64-linux-gnu-g++ from apt-get, it will make the toolchain path setting complicated.

   
 戊. Download Qt everywhere.
    Qt everywhere is here. download a qt-everywhere tar ball, (I download qt-everywhere-src-5.13.0.tar.xz  qt-everywhere-src-5.15.2.tar.xz) and extract it.


三. Compilation Qt for TX2.

 甲.  There is no mkspecs file for TX2, we use the TX1's. But the TX1's mkspecs needs to be modified,  to avoid the compilation error.
※ The modification is necessary even your build is for TX1, as it is a bug of include path duplicate.

Comment out the line 29, in file where_the_qt_everywhere_extracted/qtbase/mkspecs/devices/linux-jetson-tx1-g++/qmake.conf.
include(../common/linux_device_pre.conf)

QMAKE_INCDIR_POST += \
#    $$[QT_SYSROOT]/usr/include \
    $$[QT_SYSROOT]/usr/include/aarch64-linux-gnu

QMAKE_LIBDIR_POST += \

 乙 Configuration for build.

 Move your directory to the root of where_the_qt_everywhere_extracted, and configurate Qt as below :
./configure -shared -c++std c++14 \
 -opensource -release --confirm-license -no-pkg-config \
 -device linux-jetson-tx1-g++ \
 -device-option CROSS_COMPILE=linaro_toolchain_folder_path/gcc-linaro-6.5.0-2018.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- \
 -sysroot TX2_rootfs_in_the_host_path \
 -nomake examples -nomake tests \
 -prefix /usr/local/qt5 \
 -extprefix qt_everywhere_path/JetsonTX2/qt5 \
 -hostprefix qt_everywhere_path/JetsonTX2/qt5-host \
 -skip webview -skip qtwebengine \ -opengl es2  


./configure -shared -c++std c++14 \
 -opensource -release --confirm-license \
 -no-pkg-config -device linux-jetson-tx1-g++ \
 -device-option CROSS_COMPILE=aarch64-linux-gnu- \
 -sysroot TX2_rootfs_in_the_host \
 -prefix /usr/local/qt5.15.2 \
 -extprefix TX2_qt5.15.2_libary_path_in_host \
 -hostprefix TX2_qt5.15.2_host_tool_path \
 -nomake examples -nomake tests \
 -opengl es2 -skip qtwebengine \
 -skip qtwebglplugin -skip qtwebsockets \
 -skip qtwebview -skip qtwinextras \
 -skip qtquick3d -skip qtquickcontrols \
 -skip qtquickcontrols2 -skip qtquicktimeline \
 -skip qtwayland -skip qtandroidextras \
 -skip qtdoc -skip translations \
 -skip qtdeclarative -skip qtpurchasing \
 -skip qtwebchannel -skip qtspeech \
 -skip qtlocation -skip qtremoteobjects \
 -skip qtscript -skip qtmacextras \
 -skip qtdoc -skip qtxmlpatterns
Below explain the arguments about the path.

-prefix: indicates where the built libraries will be placed in the TX2, my argument is /usr/local/qt5 /usr/local/qt5.15.2.

-extprefix :  It specifies where the built libraries will be placed in the host, I require the path is qt_everywhere_folder/JetsonTX2/qt5  /home/gaiger/JetsonTX2/qt5.15.2-device .

-hostprefix : the compilation tools path. The compilation tools would be imported into the QtCreator in the host. My argument is qt_everywhere_folder/JetsonTX2/qt5-host  /home/gaiger/JetsonTX2/qt5.15.2-host .

Denote : All the paths had better to be the absolute paths.
※ To save the TX2 disk space and build time, I skip the modules I will not use, you you check here to find out what modules are comprised of version 5.15.2.
 丙. build Qt libraries:
make -j4
make install

The build process costs a long time.
After "make install",  the Qt libraries for TX2 (qt_everywhere folder/JetsonTX2/qt5 TX2_qt5.15.2_libary_path_in_host) and the host tools(qt_everywhere folder/JetsonTX2/qt5-host TX2_qt5.15.2_host_tool_path) will be generated. Now we copy the libraries to the TX2 :
scp -r TX2_qt5.15.2_libary_folder nvidia@your_tx2_ip:/home/nvidia
# login into TX2, rename the folder as qt5.15.2
# and move it to be under /usr/local


四. Set Qt running environment on TX2.
  ※The works are all in the TX2.

The window mode, on XCB :

 Create a file /etc/profile.d/qt_xcb.sh in your TX2, the file contents :
export DISPLAY=:0.0
export QT_QPA_PLATFORM=xcb
export QT_QPA_FONTDIR=/usr/share/fonts/truetype
※ The variable DISPLAY may be :1.0

And bring the values into the current shell :
source /etc/profile.d/qt_xcb.sh

Test if the Qt application works or not :

 /usr/local/qt5/bin/qdbusviewer




The fullscreen mode,  on EGLFS:

Create a file /etc/profile.d/qt_eglfs.sh in your TX2, the file contents :
export DISPLAY=:0.0
export QT_QPA_PLATFORM=eglfs
export QT_QPA_EGLFS_PHYSICAL_WIDTH=360 export QT_QPA_EGLFS_PHYSICAL_HEIGHT=240 export QT_QPA_FONTDIR=/usr/share/fonts/truetype export XDG_RUNTIME_DIR=/tmp/runtime-nvidia 
※ The variable DISPLAY may be :1.0 
※We specify the Qt applications running on EGLFS, therefore, we need to set the EGLFS environment variables. The description of all EGLFS variables is here.

Create a file under the directory /etc/udev/rules.d to enable the access permission of /dev/input/eventX. The file name could be as your wish, mine is 00-event.rules. Its content is:
ACTION=="add", KERNEL=="event[0-8]*", MODE="0666"
Then , reboot your TX2.

/usr/local/qt5/bin/qtbusviewer would appear like below figure, that is fullscreen application.

Attention :: The application is full screen, so there is no max, min or close button.


五. Integrate the toolchain and host tools into QtCreator.
※ I assume your TX2 is online and be with your host at the same network segment.
 Open QtCreator,  go to Menu -> Tools -> Options, then the row Build and Run.

  甲. Page Qt Versions, to add the qmake file, which located in the host_tool_path/bin (qt_everywhere_folder/JetsonTX2/qt5-host TX2_qt5.15.2_host_tool_path, the argument of -hostprefix).


  乙. Page compilers, to add the linaro C++ compilers, the compiler you just use it to build the Qt libaries, aarch64-linux-gnu-g++. Besides, you might also need to add the C compiler.


  丙. Page debugger, add the linaro debugger, aarch64-linux-gnu-gdb, set Multiarch GDB as path /usr/bin/gdb-multiarch. (you may need to install it ahead via sudo apt-get install -y gdb-multiarch)



丁. In row devices, add a device for TX2, and set its ip, user id and password (default: nvidia/nvidia).


  戊. Back row Build & Run, in page Kits, add a kit for TX2, and  set the device, rootfs, compiler, Qt versions and so forth for TX2.

己. Qtcreator will overwrite the environment varibles whilt it is debugging, thus you need to set up the variable DISPLAY value at Project->Run->Run Environment, also please check the value of QT_QPA_PLATFORM.

 


庚.   Create a Qt application in the QtCreator, select the kit for TX2. While the project has been generated automatically, add the 2 lines in the .pro file :
target.path = /home/nvidia
INSTALLS += target
The lines could be placed anywhere of .pro.

  辛. Press Run or Start Debugging button, the application will run in the TX2, and the debugger should work perfectly. You must login the TX2 locally (use the TX2's screen/keyboard/mouse to login), or there would be no screen to show the GUI and leads to crash.



2018年8月4日 星期六

Exploit Scapy to Generate WIFI Probe Request Packets on x86 Linux Distribution and OpenWRT


      Thought there are discussing threads and posts about how to use scapy library to generate probe request packets, but based on my searching, all of those are not organized and detail. This post would like to fill the gap.

   I assume you have install the python and scapy in your linux, if you have not done that, please refer to those:

Python: http://ubuntuhandbook.org/index.php/2017/07/install-python-3-6-1-in-ubuntu-16-04-lts/
Anaconda :  https://conda.io/docs/user-guide/install/linux.html  (optional)
Scapy : https://scapy.readthedocs.io/en/latest/installation.html#installing-scapy-v2-x

一. Broadcasting the probe-request in the x86-based Linux distribution:

below is the python code, named as broadcastproberequest.py,  to call scapy for generating probe-request:

#!/usr/bin/python
#coding:utf-8

import time
from scapy.all import *


def KeepBroadcastingProbeRequest(interface="wlan0", interval=0.1, \
        duration=30, ssid="譖路由器"):
    
    count = duration/interval

    packet = RadioTap()/Dot11(type=0, subtype=4, \
    addr1="ff:ff:ff:ff:ff:ff", addr2="00:11:22:33:44:55" ,addr3="ff:ff:ff:ff:ff:ff") \
    /Dot11Elt(ID="SSID", info=ssid)

    sendp(packet,  iface= iface, inter=interval, count=count)


if __name__ == '__main__':

    iface = 'wlan0'
    interval = 0.1
    duration = 30
    ssid = "開源路由器"
    try:
        opts, args = getopt.getopt(sys.argv[1:],"i:t:s:d:")
    except getopt.GetoptError as e:
        print("-i <iface>  -t <interval> -s <SSID> -d <duration>")
        sys.exit(-1)

    for opt, arg in opts:
        if opt == '-i':
            iface = arg
        elif opt == '-t':
            interval = float(arg)
        elif opt == '-s':
            ssid = arg   
        elif opt == '-d':
            duration = int(arg)
        elif opt == '-h':
            print("-i <iface>  -t <interval> -s <SSID> -d <duration>")
            sys.exit(1)

    print( "iface=%s, interval=%1.3f, duration=%d, SSID=%s" \
        %(iface, interval, duration, ssid))

    KeepBroadcastingProbeRequest(interface=iface, interval=interval, ssid=ssid, duration=duration)

Before you run your code,  if you currently use this wifi-interface (network card) online,  YOU SHOULD DISCONNECT IT AND SET THIS INTERFACE AS MINOTORING MODE :

Inquiry the network-interfaces statue:
gaiger@i5-3210M:~$ ifconfig
:
wlp3s0    Link encap:Ethernet  HWaddr 60:67:20:a5:44:ae  
          inet addr:192.168.1.140  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fd80:d8b6:da22:0:69c3:1d2c:cf5:ce18/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:818b:1644:e8b:d756/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:a068:21d:dfe8:f717/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:2cae:5b7f:d19e:1280/64 Scope:Global
          inet6 addr: fd80:d8b6:da22::a34/128 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:3b50:b57d:b0c8:4a68/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:99e4:c8ee:ea9a:bfe8/64 Scope:Global
          inet6 addr: fe80::f19c:8dd9:2058:c699/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1337204 errors:0 dropped:555386 overruns:0 frame:0
          TX packets:543649 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:528846681 (504.3 MiB)  TX bytes:79969190 (76.2 MiB)


Inquiry the wireless interface statue:
gaiger@i5-3210M:~$ iwconfig
wlp3s0    IEEE 802.11abgn  ESSID:"Tenda 3270 "  
          Mode:Managed  Frequency:2.437 GHz  Access Point: C8:3A:35:78:2D:98   
          Bit Rate=72.2 Mb/s   Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          Link Quality=70/70  Signal level=-35 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:13   Missed beacon:0
:


The WIFI-interface in this computer is named as wlp3s0. I DISCONNECT IT FROM ROUTER and set it as monitoring mode in channel 1( 2.412 GHz):
gaiger@i5-3210M:~$ sudo ifconfig wlp3s0 down
gaiger@i5-3210M:~$ sudo iwconfig wlp3s0 mode monitor
gaiger@i5-3210M:~$ sudo iwconfig wlp3s0 channel 1
gaiger@i5-3210M:~$ sudo ifconfig wlp3s0 up
gaiger@i5-3210M:~$ sudo iwconfig wlp3s0
wlp3s0    IEEE 802.11abgn  Mode:Monitor  Frequency:2.412 GHz  Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on


Of course, I could set the other channels, below is the result I set it as channel 6.
wlp3s0    IEEE 802.11abgn  Mode:Monitor  Frequency:2.437 GHz  Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on

Now the code is able to be workable:
gaiger@i5-3210M:~/sandbox/python-spider$ sudo python broadcastproberequest.py -i mon0 -t 0.02 -s 偽測探 -d 300


  I use the other device(ESP8266), to achieve the sniffing purpose, it is the sniffed result:


About the arguments :

-i <iface> -t <interval> -s <SSID> -d <duration>
 iface : interface name, default is wlan0
interval :  broadcasting interval, in unit of second, default is 0.1.
SSID : the fake ssid you would like to broadcast, it supports UTF-8 for international purpose. Default is 開源路由器
duration : how long would the broadcasting last, in unit of second. default is 30 seconds.


二. Run the code in OpenWRT.

  甲. Check there is over 7.5 MB storage space available on your OpenWRT device :

root@JoySince:~# df -h
Filesystem                Size      Used Available Use% Mounted on
rootfs                   12.3M      2.7M      9.6M  22% /
:

If your space is not adequate, you could try to adopt extroof skill.

 乙. Install those package, libffi, python-mini and python:
root@JoySince:~#opkg update
root@JoySince:~#opkg install libffi
root@JoySince:~#opkg install python-mini
root@JoySince:~#opkg install python


丙. install scapy.

   Before install scapy, you need to install tcpdump and unzip.
root@JoySince:~#opkg install python tcpdump unzip

After the installation has done, download the scapy from here and move the downloaded scapy.XXX.tar.gz file to your OpenWRT.

install the scapy.XXX.tar.gz file (mine is scapy-2.4.0.tar.gz), I assume the scapy.XXX.tar.gz is located in /tmp folder:

root@JoySince:/tmp~#tar -zxvf scapy-2.4.0.tar.gz
root@JoySince:/tmp~#cd scapy-2.4.0
root@JoySince:/tmp~#python setup.py install

After the installation has been done, you could remove the tar.gz file and the unzip scapy folder.


丁.  Set the WIFI interface on OpenWRT in monitor mode.

Modify the file /etc/config/wireless as :
config wifi-device 'radio0'
        option type 'mac80211'
#       option channel '8'
        option channel '1' ##
        option hwmode '11g'
        option path 'platform/ar933x_wmac'
        option htmode 'HT40'
        option txpower '30'
        option country 'US'

config wifi-iface
        option device 'radio0'
        option mode monitor ##
#       option mode 'ap'
#       option ssid 'JoySince'
        option network 'lan'
        option encryption 'psk'
        option key '12345678'

The lines begins from # are what I commented out, the lines end in ## are what I added.
After the modification has been done, set this configuration applied:
root@JoySince:/tmp# wifi
root@JoySince:/tmp# iw wlan0 info
Interface wlan0
        ifindex 6
        wdev 0x2
        addr 00:ca:01:06:0d:da
        type monitor
        wiphy 0
        channel 1 (2412 MHz), width: 20 MHz (no HT), center1: 2412 MHz

If it does not work, reboot your OpenWRT.


丁. Move the code broadcastproberequest.py to your OpenWRT,  and run the code.

root@JoySince:~# python broadcastproberequest.py -d 300  -t 0.05 -s 白羅剎


Result :


※ You could adopt the other OpenWRT with the same configuration of file /etc/config/wireless to monitor the broadcasted probe-request packets :

root@JoySince:~# tcpdump -i wlan0 -e -s 1024 type mgt subtype probe-req -vv

But you could not use ONLY ONE openWRT to broadcast and monitor probe-request  at the same time.