diff --git a/sdcard-images-utils/nvidia/patches/hardware/nvidia/t23x/nv-public/0020-overlay-adsd3500_dual-Fix-GPIO-line-name.patch b/sdcard-images-utils/nvidia/patches/hardware/nvidia/t23x/nv-public/0020-overlay-adsd3500_dual-Fix-GPIO-line-name.patch new file mode 100644 index 000000000..9730a75ad --- /dev/null +++ b/sdcard-images-utils/nvidia/patches/hardware/nvidia/t23x/nv-public/0020-overlay-adsd3500_dual-Fix-GPIO-line-name.patch @@ -0,0 +1,43 @@ +From 984ee10b17034a4a832a3df110efec5ed8333c9f Mon Sep 17 00:00:00 2001 +From: Sivasubramanaiyan Padmanaban +Date: Fri, 23 Jan 2026 15:45:47 +0530 +Subject: [PATCH] overlay: adsd3500_dual: Fix GPIO line name + +- Fixed the inconsistent naming for "I2CM SEL" to "I2CM_SEL" to maintain uniformity. +- Fixed the inconsistent naming for "NET HOST_IO_SEL" to "NET_HOST_IO_SEL" to maintain uniformity. + +Signed-off-by: Sivasubramanaiyan Padmanaban +--- + ...p3767-camera-p3768-dual-adsd3500-adsd3100-arducam-ar0234.dts | 2 +- + overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100.dts | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100-arducam-ar0234.dts b/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100-arducam-ar0234.dts +index 4a624f0..78dcba0 100644 +--- a/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100-arducam-ar0234.dts ++++ b/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100-arducam-ar0234.dts +@@ -414,7 +414,7 @@ + reg = <0x68>; + gpio-controller; + #gpio-cells = <2>; +- gpio-line-names = "EN_1P8", "EN_0P8", "P2", "I2CM SEL", "ISP_BS3/ISP_INT", "NET HOST_IO_SEL", "ISP_BS0", "ISP_BS1", "HOST_IO_DIR", "ISP_BS4", "ISP_BS5", "FSYNC_DIR", "EN_VAUX", "EN_VAUX_LS", "EN_SYS"; ++ gpio-line-names = "EN_1P8", "EN_0P8", "P2", "I2CM_SEL", "ISP_BS3/ISP_INT", "NET_HOST_IO_SEL", "ISP_BS0", "ISP_BS1", "HOST_IO_DIR", "ISP_BS4", "ISP_BS5", "FSYNC_DIR", "EN_VAUX", "EN_VAUX_LS", "EN_SYS"; + }; + adsd3500@38 { + compatible = "adi,adsd3500"; +diff --git a/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100.dts b/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100.dts +index b621234..5e8ef94 100644 +--- a/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100.dts ++++ b/overlay/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100.dts +@@ -2459,7 +2459,7 @@ + reg = <0x68>; + gpio-controller; + #gpio-cells = <2>; +- gpio-line-names = "EN_1P8", "EN_0P8", "P2", "I2CM SEL", "ISP_BS3/ISP_INT", "NET HOST_IO_SEL", "ISP_BS0", "ISP_BS1", "HOST_IO_DIR", "ISP_BS4", "ISP_BS5", "FSYNC_DIR", "EN_VAUX", "EN_VAUX_LS", "EN_SYS"; ++ gpio-line-names = "EN_1P8", "EN_0P8", "P2", "I2CM_SEL", "ISP_BS3/ISP_INT", "NET_HOST_IO_SEL", "ISP_BS0", "ISP_BS1", "HOST_IO_DIR", "ISP_BS4", "ISP_BS5", "FSYNC_DIR", "EN_VAUX", "EN_VAUX_LS", "EN_SYS"; + }; + }; + pwm: pwm-gpio { +-- +2.25.1 + diff --git a/sdcard-images-utils/nvidia/patches/kernel/kernel-jammy-src/0007-arch-arm64-configs-defconfig-build-Tegra194-PCIe-and.patch b/sdcard-images-utils/nvidia/patches/kernel/kernel-jammy-src/0007-arch-arm64-configs-defconfig-build-Tegra194-PCIe-and.patch new file mode 100644 index 000000000..bc3849f4a --- /dev/null +++ b/sdcard-images-utils/nvidia/patches/kernel/kernel-jammy-src/0007-arch-arm64-configs-defconfig-build-Tegra194-PCIe-and.patch @@ -0,0 +1,41 @@ +From b7724648ee98cb832295b3ca1827f32652a42483 Mon Sep 17 00:00:00 2001 +From: Sivasubramanaiyan Padmanaban +Date: Thu, 22 Jan 2026 11:15:56 +0530 +Subject: [PATCH] arch: arm64: configs: defconfig: build Tegra194 PCIe and NVMe + drivers into kernel + +- Build the Tegra194 PCIe host/endpoint drivers and the NVMe block +driver into the kernel to ensure availability during early boot. + +Signed-off-by: Sivasubramanaiyan Padmanaban +--- + arch/arm64/configs/defconfig | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig +index 2a9c2815df00..7a8d9568d9e5 100644 +--- a/arch/arm64/configs/defconfig ++++ b/arch/arm64/configs/defconfig +@@ -270,8 +270,8 @@ CONFIG_PCIE_QCOM=y + CONFIG_PCIE_ARMADA_8K=y + CONFIG_PCIE_KIRIN=y + CONFIG_PCIE_HISI_STB=y +-CONFIG_PCIE_TEGRA194_HOST=m +-CONFIG_PCIE_TEGRA194_EP=m ++CONFIG_PCIE_TEGRA194_HOST=y ++CONFIG_PCIE_TEGRA194_EP=y + CONFIG_PCIE_LAYERSCAPE_GEN4=y + CONFIG_PCI_ENDPOINT=y + CONFIG_PCI_ENDPOINT_CONFIGFS=y +@@ -314,7 +314,7 @@ CONFIG_ZRAM=m + CONFIG_BLK_DEV_LOOP=y + CONFIG_BLK_DEV_NBD=m + CONFIG_VIRTIO_BLK=y +-CONFIG_BLK_DEV_NVME=m ++CONFIG_BLK_DEV_NVME=y + CONFIG_NVME_TCP=m + CONFIG_NVME_TARGET=m + CONFIG_NVME_TARGET_TCP=m +-- +2.25.1 + diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-external-fsync.sh b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-external-fsync.sh index a2bb25748..47fc54b44 100755 --- a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-external-fsync.sh +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-external-fsync.sh @@ -1,5 +1,6 @@ #!/bin/bash +# Discover adsd3500 V4L2 sub-device and video nodes by parsing the media controller graph MEDIA_DEVICE="/dev/media0" DOT_OUTPUT=$(media-ctl -d "$MEDIA_DEVICE" --print-dot) DOT_OUTPUT=$(echo "$DOT_OUTPUT" | sed 's/\\n/\n/g') @@ -14,25 +15,30 @@ else exit 1 fi -# export NET HOST_IO_SEL Pin -if [ ! -d /sys/class/gpio/gpio305 ] -then - echo 305 > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio305/direction -fi - -# export HOST_IO_DIR Pin -if [ ! -d /sys/class/gpio/gpio308 ] -then - echo 308 > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio308/direction -fi +# Declare GPIO mapping directly +declare -A GPIO=( + [EN_1P8]=300 + [EN_0P8]=301 + [P2]=302 + [I2CM_SEL]=303 + [ISP_BS3]=304 + [NET_HOST_IO_SEL]=305 + [ISP_BS0]=306 + [ISP_BS1]=307 + [HOST_IO_DIR]=308 + [ISP_BS4]=309 + [ISP_BS5]=310 + [FSYNC_DIR]=311 + [EN_VAUX]=312 + [EN_VAUX_LS]=313 + [EN_SYS]=314 +) # Set 0: EXT_FSYNC / 1: ISP_INT -echo 0 > /sys/class/gpio/gpio305/value +echo 0 > /sys/class/gpio/gpio${GPIO[NET_HOST_IO_SEL]}/value # Set 0: EXT_FSYNC / 1: ISP_INT -echo 0 > /sys/class/gpio/gpio308/value +echo 0 > /sys/class/gpio/gpio${GPIO[HOST_IO_DIR]}/value # Enable external fsync v4l2-ctl --set-ctrl=fsync_trigger=0 -d $SUBDEV_PATH diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-interrupt.sh b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-interrupt.sh index 062f371f2..3f11d305f 100755 --- a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-interrupt.sh +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-enable-interrupt.sh @@ -1,5 +1,6 @@ #!/bin/bash +# Discover adsd3500 V4L2 sub-device and video nodes by parsing the media controller graph MEDIA_DEVICE="/dev/media0" DOT_OUTPUT=$(media-ctl -d "$MEDIA_DEVICE" --print-dot) DOT_OUTPUT=$(echo "$DOT_OUTPUT" | sed 's/\\n/\n/g') @@ -14,25 +15,30 @@ else exit 1 fi -# export NET HOST_IO_SEL Pin -if [ ! -d /sys/class/gpio/gpio305 ] -then - echo 305 > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio305/direction -fi - -# export HOST_IO_DIR Pin -if [ ! -d /sys/class/gpio/gpio308 ] -then - echo 308 > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio308/direction -fi +# Declare GPIO mapping directly +declare -A GPIO=( + [EN_1P8]=300 + [EN_0P8]=301 + [P2]=302 + [I2CM_SEL]=303 + [ISP_BS3]=304 + [NET_HOST_IO_SEL]=305 + [ISP_BS0]=306 + [ISP_BS1]=307 + [HOST_IO_DIR]=308 + [ISP_BS4]=309 + [ISP_BS5]=310 + [FSYNC_DIR]=311 + [EN_VAUX]=312 + [EN_VAUX_LS]=313 + [EN_SYS]=314 +) # Set 0: EXT_FSYNC / 1: ISP_INT -echo 1 > /sys/class/gpio/gpio305/value +echo 1 > /sys/class/gpio/gpio${GPIO[NET_HOST_IO_SEL]}/value # Set 0: EXT_FSYNC / 1: ISP_INT -echo 1 > /sys/class/gpio/gpio308/value +echo 1 > /sys/class/gpio/gpio${GPIO[HOST_IO_DIR]}/value -# Enable interrupt support +# Enable external fsync v4l2-ctl --set-ctrl=fsync_trigger=1 -d $SUBDEV_PATH diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-reset.sh b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-reset.sh index 75159bd4e..59501f012 100755 --- a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-reset.sh +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/adi-adsd3500-reset.sh @@ -1,8 +1,10 @@ #!/bin/bash -echo 0 > /sys/class/gpio/PAC.00/value +GPIO_NAME="PAC.00" + +echo 0 > /sys/class/gpio/$GPIO_NAME/value sleep 1 -echo 1 > /sys/class/gpio/PAC.00/value +echo 1 > /sys/class/gpio/$GPIO_NAME/value diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-host-boot.sh b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-host-boot.sh index e08b8a99f..59cae5567 100755 --- a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-host-boot.sh +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-host-boot.sh @@ -1,6 +1,28 @@ #!/bin/bash -MODULE=$(strings /proc/device-tree/tegra-camera-platform/modules/module0/badge) +# Scan all camera module badge entries and assign MODULE to the first one matching the ADI ToF sensor +TARGET="adi_dual_adsd3500_adsd3100" +MODULE="" + +for badge in \ + /proc/device-tree/tegra-camera-platform/modules/module0/badge \ + /proc/device-tree/tegra-camera-platform/modules/module1/badge +do + if [[ -f "$badge" ]]; then + value=$(strings "$badge") + if echo "$value" | grep -q "$TARGET"; then + MODULE="$value" + break + fi + fi +done + +if [[ -z "$MODULE" ]]; then + echo "Target module not found" + exit 0 +fi + +echo "Matched MODULE: $MODULE" MEDIA_DEVICE="/dev/media0" DOT_OUTPUT=$(media-ctl -d "$MEDIA_DEVICE" --print-dot) @@ -16,48 +38,62 @@ else exit 1 fi -adsd3500_power_sequence(){ - - #Pull ADSD3500 reset low - echo 0 > /sys/class/gpio/PAC.00/value - - #Disable the the supply voltage - #EN_1P8 - gpioset 2 0=0 +GPIO_NAME="PAC.00" - #EN_0P8 - gpioset 2 1=0 +# Declare GPIO mapping directly +declare -A GPIO=( + [EN_1P8]=300 + [EN_0P8]=301 + [P2]=302 + [I2CM_SEL]=303 + [ISP_BS3]=304 + [NET_HOST_IO_SEL]=305 + [ISP_BS0]=306 + [ISP_BS1]=307 + [HOST_IO_DIR]=308 + [ISP_BS4]=309 + [ISP_BS5]=310 + [FSYNC_DIR]=311 + [EN_VAUX]=312 + [EN_VAUX_LS]=313 + [EN_SYS]=314 +) - sleep 0.2 +adsd3500_power_sequence() { - #I2CM_SET - gpioset 2 3=0 + # Pull ADSD3500 reset low + echo 0 > /sys/class/gpio/$GPIO_NAME/value - #ISP_BS0 - gpioset 2 6=1 + # Disable the supply voltage + echo 0 > /sys/class/gpio/gpio${GPIO[EN_1P8]}/value + echo 0 > /sys/class/gpio/gpio${GPIO[EN_0P8]}/value - #ISP_BS1 - gpioset 2 7=0 + sleep 0.2 - #ISP_BS4 - gpioset 2 9=0 + # I2CM_SEL + echo 0 > /sys/class/gpio/gpio${GPIO[I2CM_SEL]}/value - #ISP_BS5 - gpioset 2 10=0 + # ISP_BS0 + echo 1 > /sys/class/gpio/gpio${GPIO[ISP_BS0]}/value - #EN_1P8 - gpioset 2 0=1 + # ISP_BS1 + echo 0 > /sys/class/gpio/gpio${GPIO[ISP_BS1]}/value - sleep 0.2 + # ISP_BS4 + echo 0 > /sys/class/gpio/gpio${GPIO[ISP_BS4]}/value - #EN_0P8 - gpioset 2 1=1 + # ISP_BS5 + echo 0 > /sys/class/gpio/gpio${GPIO[ISP_BS5]}/value - sleep 0.2 + # Re-enable the supply voltage + echo 1 > /sys/class/gpio/gpio${GPIO[EN_1P8]}/value + sleep 0.2 - #Pull ADSD3500 reset high - echo 1 > /sys/class/gpio/PAC.00/value + echo 1 > /sys/class/gpio/gpio${GPIO[EN_0P8]}/value + sleep 0.2 + # Pull ADSD3500 reset high + echo 1 > /sys/class/gpio/$GPIO_NAME/value } load_firmware() { diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-self-boot.sh b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-self-boot.sh index 77874dd41..604e13c57 100755 --- a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-self-boot.sh +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/Tools/host_boot_tools/adi-adsd3500-self-boot.sh @@ -1,49 +1,99 @@ #!/bin/bash -MODULE=$(strings /proc/device-tree/tegra-camera-platform/modules/module0/badge) - -adsd3500_power_sequence(){ - - #Pull ADSD3500 reset low - echo 0 > /sys/class/gpio/PAC.00/value - - #Disable the the supply voltage - #EN_1P8 - gpioset 2 0=0 - - #EN_0P8 - gpioset 2 1=0 - - sleep 0.2 - - #I2CM_SET - gpioset 2 3=0 - - #ISP_BS0 - gpioset 2 6=0 - - #ISP_BS1 - gpioset 2 7=0 - - #ISP_BS4 - gpioset 2 9=0 - - #ISP_BS5 - gpioset 2 10=0 - - #EN_1P8 - gpioset 2 0=1 - - sleep 0.2 - - #EN_0P8 - gpioset 2 1=1 - - sleep 0.2 - - #Pull ADSD3500 reset high - echo 1 > /sys/class/gpio/PAC.00/value - +# Scan all camera module badge entries and assign MODULE to the first one matching the ADI ToF sensor +TARGET="adi_dual_adsd3500_adsd3100" +MODULE="" + +for badge in \ + /proc/device-tree/tegra-camera-platform/modules/module0/badge \ + /proc/device-tree/tegra-camera-platform/modules/module1/badge +do + if [[ -f "$badge" ]]; then + value=$(strings "$badge") + if echo "$value" | grep -q "$TARGET"; then + MODULE="$value" + break + fi + fi +done + +if [[ -z "$MODULE" ]]; then + echo "Target module not found" + exit 0 +fi + +echo "Matched MODULE: $MODULE" + +MEDIA_DEVICE="/dev/media0" +DOT_OUTPUT=$(media-ctl -d "$MEDIA_DEVICE" --print-dot) +DOT_OUTPUT=$(echo "$DOT_OUTPUT" | sed 's/\\n/\n/g') +SUBDEV_PATH=$(echo "$DOT_OUTPUT" | awk '/adsd3500/ {getline; if ($0 ~ /\/dev\/v4l-subdev/) print $1}' | tr -d '",') +VIDEO_PATH=$(echo "$DOT_OUTPUT" | awk '/vi-output, adsd3500/ {getline; if ($0 ~ /\/dev\/video/) print $1}' | tr -d '",') + +if [[ -n "$SUBDEV_PATH" && -n "$VIDEO_PATH" ]]; then + echo "adsd3500 subdev: $SUBDEV_PATH" > /dev/null + echo "adsd3500 video : $VIDEO_PATH" > /dev/null +else + echo "adsd3500 device not found in $MEDIA_DEVICE" + exit 1 +fi + +GPIO_NAME="PAC.00" + +# Declare GPIO mapping directly +declare -A GPIO=( + [EN_1P8]=300 + [EN_0P8]=301 + [P2]=302 + [I2CM_SEL]=303 + [ISP_BS3]=304 + [NET_HOST_IO_SEL]=305 + [ISP_BS0]=306 + [ISP_BS1]=307 + [HOST_IO_DIR]=308 + [ISP_BS4]=309 + [ISP_BS5]=310 + [FSYNC_DIR]=311 + [EN_VAUX]=312 + [EN_VAUX_LS]=313 + [EN_SYS]=314 +) + +adsd3500_power_sequence() { + + # Pull ADSD3500 reset low + echo 0 > /sys/class/gpio/$GPIO_NAME/value + + # Disable the supply voltage + echo 0 > /sys/class/gpio/gpio${GPIO[EN_1P8]}/value + echo 0 > /sys/class/gpio/gpio${GPIO[EN_0P8]}/value + + sleep 0.2 + + # I2CM_SEL + echo 0 > /sys/class/gpio/gpio${GPIO[I2CM_SEL]}/value + + # ISP_BS0 + echo 0 > /sys/class/gpio/gpio${GPIO[ISP_BS0]}/value + + # ISP_BS1 + echo 0 > /sys/class/gpio/gpio${GPIO[ISP_BS1]}/value + + # ISP_BS4 + echo 0 > /sys/class/gpio/gpio${GPIO[ISP_BS4]}/value + + # ISP_BS5 + echo 0 > /sys/class/gpio/gpio${GPIO[ISP_BS5]}/value + + # Re-enable the supply voltage + echo 1 > /sys/class/gpio/gpio${GPIO[EN_1P8]}/value + sleep 0.2 + + echo 1 > /sys/class/gpio/gpio${GPIO[EN_0P8]}/value + sleep 0.2 + + # Pull ADSD3500 reset high + echo 1 > /sys/class/gpio/$GPIO_NAME/value } enable_self_boot(){ @@ -53,7 +103,6 @@ enable_self_boot(){ echo "Running on DUAL ADSD3500 + ADSD3100" adsd3500_power_sequence echo "Self boot completed" - ;; *) echo "Invalid camera module" diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/etc/systemd/system/jetson-performance.service b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/etc/systemd/system/jetson-performance.service new file mode 100644 index 000000000..f95e1e99c --- /dev/null +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/etc/systemd/system/jetson-performance.service @@ -0,0 +1,11 @@ +[Unit] +Description=Jetson Orin Nano Max Performance Mode +After=usb-gadget.target + +[Service] +Type=oneshot +ExecStart=/usr/share/systemd/jetson-perf.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/etc/udev/rules.d/99-gpio.rules b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/etc/udev/rules.d/99-gpio.rules index a4e8058ae..ac03dafd4 100644 --- a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/etc/udev/rules.d/99-gpio.rules +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/etc/udev/rules.d/99-gpio.rules @@ -1,4 +1,16 @@ ACTION=="add", KERNEL=="PAC.00", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/PAC.00/value" +ACTION=="add", KERNEL=="gpio300", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio300/value" +ACTION=="add", KERNEL=="gpio301", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio301/value" +ACTION=="add", KERNEL=="gpio302", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio302/value" +ACTION=="add", KERNEL=="gpio303", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio303/value" +ACTION=="add", KERNEL=="gpio304", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio304/value" ACTION=="add", KERNEL=="gpio305", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio305/value" +ACTION=="add", KERNEL=="gpio306", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio306/value" +ACTION=="add", KERNEL=="gpio307", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio307/value" ACTION=="add", KERNEL=="gpio308", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio308/value" +ACTION=="add", KERNEL=="gpio309", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio309/value" +ACTION=="add", KERNEL=="gpio310", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio310/value" ACTION=="add", KERNEL=="gpio311", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio311/value" +ACTION=="add", KERNEL=="gpio312", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio312/value" +ACTION=="add", KERNEL=="gpio313", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio313/value" +ACTION=="add", KERNEL=="gpio314", SUBSYSTEM=="gpio", RUN+="/bin/chmod 666 /sys/class/gpio/gpio314/value" diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/usr/share/systemd/jetson-perf.sh b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/usr/share/systemd/jetson-perf.sh new file mode 100755 index 000000000..7ddf55065 --- /dev/null +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/usr/share/systemd/jetson-perf.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +#Set the power model to MAXN SUPER +nvpmodel -m 2 +jetson_clocks + +# Lock camera subsystem clocks +echo 1 > /sys/kernel/debug/bpmp/debug/clk/vi/mrq_rate_locked +echo 1 > /sys/kernel/debug/bpmp/debug/clk/isp/mrq_rate_locked +echo 1 > /sys/kernel/debug/bpmp/debug/clk/nvcsi/mrq_rate_locked +echo 1 > /sys/kernel/debug/bpmp/debug/clk/emc/mrq_rate_locked + +cat /sys/kernel/debug/bpmp/debug/clk/vi/max_rate > /sys/kernel/debug/bpmp/debug/clk/vi/rate +cat /sys/kernel/debug/bpmp/debug/clk/isp/max_rate > /sys/kernel/debug/bpmp/debug/clk/isp/rate +cat /sys/kernel/debug/bpmp/debug/clk/nvcsi/max_rate > /sys/kernel/debug/bpmp/debug/clk/nvcsi/rate +cat /sys/kernel/debug/bpmp/debug/clk/emc/max_rate > /sys/kernel/debug/bpmp/debug/clk/emc/rate + +# Ensure CPU governor is performance +for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do + echo performance > $cpu +done + +# Debug print at the end +echo "Debug: Jetson Orin Nano clocks locked and CPU governors set to performance." diff --git a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/usr/share/systemd/tof-power-en.sh b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/usr/share/systemd/tof-power-en.sh index 028115088..c799e79a5 100755 --- a/sdcard-images-utils/nvidia/patches/ubuntu_overlay/usr/share/systemd/tof-power-en.sh +++ b/sdcard-images-utils/nvidia/patches/ubuntu_overlay/usr/share/systemd/tof-power-en.sh @@ -1,175 +1,143 @@ #!/bin/bash - -MODULE=$(strings /proc/device-tree/tegra-camera-platform/modules/module0/badge) -MODULE1=$(strings /proc/device-tree/tegra-camera-platform/modules/module1/badge) - -if [[ $MODULE == "adi_adsd3500_adsd3100" ]]; then - echo "Module name: $MODULE" - echo "export CAM0_PWDN and set direction as output" - - # export ADSD3500 reset Pin - if [ ! -d /sys/class/gpio/PH.06 ] - then - echo 397 > /sys/class/gpio/export - echo out > /sys/class/gpio/PH.06/direction - fi - - #pull ADSD3500 reset low - sudo echo 0 > /sys/class/gpio/PH.06/value - - #Disable the supply voltage - #EN_1P8 - sudo gpioset 3 6=0 - - sleep 1 - - #EN_0P8 - sudo gpioset 3 7=0 - - # Boot strap MAX7321 - #OC0 - sudo gpioset 2 0=0 - - #OC1 - sudo gpioset 2 1=0 - - #OC2 - sudo gpioset 2 2=0 - - #OC3 - sudo gpioset 2 3=0 - - #OC4 - sudo gpioset 2 4=0 - - #OC5 - sudo gpioset 2 5=0 - - #OC6 - sudo gpioset 2 6=0 - - #FLASH_WP - sudo gpioset 2 7=1 - - - # Boot strap MAX7320 - #U0 - sudo gpioset 3 3=0 - - #DS2 - sudo gpioset 3 5=1 - - #EN_1P8 - sudo gpioset 3 6=1 - - sleep 1 - - #EN_0P8 - sudo gpioset 3 7=1 - - #Pull ADSD3500 reset high - sudo echo 1 > /sys/class/gpio/PH.06/value - echo "ToF power sequence completed" +# ToF sensor power/reset sequence using max7327 GPIOs via sysfs + +# Scan all camera module badge entries and assign MODULE to the first one matching the ADI ToF sensor +TARGET="adi_dual_adsd3500_adsd3100" +MODULE="" + +for badge in \ + /proc/device-tree/tegra-camera-platform/modules/module0/badge \ + /proc/device-tree/tegra-camera-platform/modules/module1/badge +do + if [[ -f "$badge" ]]; then + value=$(strings "$badge") + if echo "$value" | grep -q "$TARGET"; then + MODULE="$value" + break + fi + fi +done + +if [[ -z "$MODULE" ]]; then + echo "Skipping ToF power sequence: MODULE=$MODULE" + exit 0 fi -if [[ $MODULE == "adi_dual_adsd3500_adsd3100" || $MODULE1 == "adi_dual_adsd3500_adsd3100" ]]; then - echo "Module name: $MODULE" - echo "export CAM1_PWDN and set direction as output" - - # export ADSD3500 reset Pin - if [ ! -d /sys/class/gpio/PAC.00 ] - then - echo 486 > /sys/class/gpio/export - echo out > /sys/class/gpio/PAC.00/direction - fi - - # Export ISP_BS3/ISP_INT pin as input - if [ ! -d /sys/class/gpio/gpio304 ] - then - echo 304 > /sys/class/gpio/export - echo in > /sys/class/gpio/gpio304/direction - fi - - # Export NET HOST_IO_SEL pin as output - if [ ! -d /sys/class/gpio/gpio305 ] - then - echo 305 > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio305/direction - fi - - # Export HOST_IO_DIR pin as output - if [ ! -d /sys/class/gpio/gpio308 ] - then - echo 308 > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio308/direction - fi - - # Export FSYNC_DIR pin as output - if [ ! -d /sys/class/gpio/gpio311 ] - then - echo 311 > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio311/direction - fi - - # Set NET HOST_IO_SEL: EXT_FSYNC = 0 / ISP_INT = 1 - echo 1 > /sys/class/gpio/gpio305/value - - #Set HOST_IO_DIR: EXT_FSYNC = 0 / ISP_INT = 1 - echo 1 > /sys/class/gpio/gpio308/value - - #Set FSYNC_DIR: External = 0 / Internal = 1 - echo 1 > /sys/class/gpio/gpio311/value - - #Pull ADSD3500 reset low - sudo echo 0 > /sys/class/gpio/PAC.00/value - - #Disable the the supply voltage - #EN_1P8 - sudo gpioset 2 0=0 - - #EN_0P8 - sudo gpioset 2 1=0 - - sleep 0.2 - - #I2CM_SET - sudo gpioset 2 3=0 - - #ISP_BS0 - sudo gpioset 2 6=0 - - #ISP_BS1 - sudo gpioset 2 7=0 - - #ISP_BS4 - sudo gpioset 2 9=0 - - #ISP_BS5 - sudo gpioset 2 10=0 - - #EN_1P8 - sudo gpioset 2 0=1 - - sleep 0.2 - - #EN_0P8 - sudo gpioset 2 1=1 - - sleep 0.2 - - #EN_VSYS - sudo gpioset 2 14=1 - - #EN_VAUX_LS - sudo gpioset 2 13=1 - - #EN_VAUX - sudo gpioset 2 12=1 - sleep 0.2 - - #Pull ADSD3500 reset high - sudo echo 1 > /sys/class/gpio/PAC.00/value - - echo "ToF power sequence completed" +echo "Matched MODULE: $MODULE" + +# --- Dynamically fetch GPIO labels --- +declare -A GPIO + +# List of GPIO labels we are interested in, including ISP_RST at the start +GPIO_LIST=("ISP_RST" "EN_1P8" "EN_0P8" "P2" "I2CM_SEL" "ISP_BS3" "NET_HOST_IO_SEL" "ISP_BS0" "ISP_BS1" "HOST_IO_DIR" "ISP_BS4" "ISP_BS5" "FSYNC_DIR" "EN_VAUX" "EN_VAUX_LS" "EN_SYS") + +# GPIO name to search for (easy to change later) +GPIO_NAME="PAC.00" + +# Check for the GPIO name and assign it to ISP_RST +GPIO_RESULT=$(sudo cat /sys/kernel/debug/gpio | grep -i "\b${GPIO_NAME}\b") +if [[ -n "$GPIO_RESULT" ]]; then + gpio_num=$(echo "$GPIO_RESULT" | sed -E 's/.*gpio-([0-9]+).*/\1/') + if [[ -n "$gpio_num" ]]; then + GPIO["ISP_RST"]=$gpio_num + echo "Special case: ${GPIO_NAME} assigned to ISP_RST -> $gpio_num" + echo $gpio_num > /sys/class/gpio/export + echo out > /sys/class/gpio/$GPIO_NAME/direction + else + echo "${GPIO_NAME} found, but GPIO number not extracted correctly" + exit 0 + fi +else + echo "${GPIO_NAME} not found" + exit 0 fi +# Now process the GPIO labels, starting from the second element (index 1) +for label in "${GPIO_LIST[@]:1}"; do + # Search for each GPIO label in the debug output and extract the GPIO number + result=$(sudo cat /sys/kernel/debug/gpio | grep -i "\b$label\b") + + # Check if the result is non-empty and contains the GPIO number + if [[ -n "$result" ]]; then + gpio_num=$(echo "$result" | sed -E 's/.*gpio-([0-9]+).*/\1/') + + # Store the GPIO number in the associative array + if [[ -n "$gpio_num" ]]; then + GPIO["$label"]=$gpio_num + echo "Label: $label -> $gpio_num" + else + echo "Label: $label found, but GPIO number not extracted correctly" + exit 0 + fi + else + echo "Label: $label not found" + exit 0 + fi +done + +# Function to export and configure GPIO +setup_gpio() { + local gpio=$1 + local direction=$2 + local value=${3:-0} + + [ ! -d /sys/class/gpio/gpio$gpio ] && echo "$gpio" > /sys/class/gpio/export + sleep 0.05 + echo "$direction" > /sys/class/gpio/gpio$gpio/direction + [[ "$direction" == "out" ]] && echo "$value" > /sys/class/gpio/gpio$gpio/value +} + +echo "Configuring GPIOs via sysfs..." + +# Configure all GPIOs: ISP_BS3 as input, others as output low +for label in "${GPIO_LIST[@]:1}"; do + gpio=${GPIO[$label]} + if [ "$label" == "ISP_BS3" ]; then + setup_gpio "$gpio" "in" + else + setup_gpio "$gpio" "out" 0 + fi +done + +echo "GPIO configuration complete." +echo "Starting ToF power sequence..." + +# --- Step 1-3: Direction/selection lines --- +echo 1 > /sys/class/gpio/gpio${GPIO[NET_HOST_IO_SEL]}/value +echo 1 > /sys/class/gpio/gpio${GPIO[HOST_IO_DIR]}/value +echo 1 > /sys/class/gpio/gpio${GPIO[FSYNC_DIR]}/value + +# --- Step 4: Pull ADSD3500 reset low --- +echo 0 > /sys/class/gpio/$GPIO_NAME/value + +# --- Step 5: Disable supply voltages --- +for pin in EN_1P8 EN_0P8; do + echo 0 > /sys/class/gpio/gpio${GPIO[$pin]}/value +done +sleep 0.2 + +# --- Step 6: I2CM_SEL low --- +echo 0 > /sys/class/gpio/gpio${GPIO[I2CM_SEL]}/value + +# --- Step 7: ISP_BS0/1/4/5 low --- +for pin in ISP_BS0 ISP_BS1 ISP_BS4 ISP_BS5; do + echo 0 > /sys/class/gpio/gpio${GPIO[$pin]}/value +done + +# --- Step 8: Enable supply voltages --- +for pin in EN_1P8 EN_0P8; do + echo 1 > /sys/class/gpio/gpio${GPIO[$pin]}/value + sleep 0.2 +done + +# --- Step 9: Enable EN_SYS, EN_VAUX_LS, EN_VAUX --- +for pin in EN_SYS EN_VAUX_LS EN_VAUX; do + echo 1 > /sys/class/gpio/gpio${GPIO[$pin]}/value +done +sleep 0.2 + +# --- Step 10: Pull ADSD3500 reset high --- +echo 1 > /sys/class/gpio/$GPIO_NAME/value + +echo "ToF power sequence completed." + diff --git a/sdcard-images-utils/nvidia/runme.sh b/sdcard-images-utils/nvidia/runme.sh index 617f9beb9..21845e3db 100755 --- a/sdcard-images-utils/nvidia/runme.sh +++ b/sdcard-images-utils/nvidia/runme.sh @@ -175,7 +175,7 @@ function sw_version_info() echo -n "Branch Name : " >> $SW_VERSION_FILE ; echo "$BRANCH" >> $SW_VERSION_FILE echo -n "Branch Commit : " >> $SW_VERSION_FILE ; echo "$BR_COMMIT" >> $SW_VERSION_FILE echo -n "Build Date : " >> $SW_VERSION_FILE ; date >> $SW_VERSION_FILE - echo "Kernel Version : 5.15.148-tegra" >> $SW_VERSION_FILE + echo "Kernel Version : 5.15.148-adi-tegra" >> $SW_VERSION_FILE mv $SW_VERSION_FILE $PATCH_DIR } @@ -188,7 +188,7 @@ function main() build_kernel_Image copy_ubuntu_overlay sw_version_info - cp $ROOTDIR/scripts/system_upgrade/apply_patch.sh $PATCH_DIR + cp $ROOTDIR/scripts/system_upgrade/*.sh $PATCH_DIR cd $ROOTDIR/build ARCHIVE_FILENAME="NVIDIA_ToF_ADSD3500_REL_PATCH_$(date +"%d%b%y").zip" diff --git a/sdcard-images-utils/nvidia/scripts/flash_jetson/README.md b/sdcard-images-utils/nvidia/scripts/flash_jetson/README.md new file mode 100644 index 000000000..0cf496c34 --- /dev/null +++ b/sdcard-images-utils/nvidia/scripts/flash_jetson/README.md @@ -0,0 +1,22 @@ +Jetson BSP Linux source: + +https://developer.nvidia.com/embedded/jetson-linux-r3644 + +System Prerequisites: + +Host PC : Ubuntu 20.04/22.04/24.04 + +Target : Jetson Orin nano 8Gb SOM. + +A. Flash procedure with only ext4 root partition: + +Use flash_nvme.sh to flash external media connected to a frame grabber v2 carrier board with jetson orin nano SoM. This script uses the recovery initial ramdisk to do the flashing, and can flash external media using the same procedure. Because this script uses the kernel for flashing, it is generally faster and creates only one ext4 root partition. + +1. Copy the flash_nvme.sh shell script to ADCAM/sdcard-images-utils/nvidia directory + +2. Change the permission and execute the shell script. + + $ chmod +x flash_nvme.sh + + $ sudo ./flash_nvme.sh + diff --git a/sdcard-images-utils/nvidia/scripts/flash_jetson/flash_nvme.sh b/sdcard-images-utils/nvidia/scripts/flash_jetson/flash_nvme.sh new file mode 100755 index 000000000..ffff27120 --- /dev/null +++ b/sdcard-images-utils/nvidia/scripts/flash_jetson/flash_nvme.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +set -ex + +if [[ $EUID > 0 ]]; then + echo "This script must be run as root user" + echo "Usage: sudo ./flash_nvme.sh" + exit +fi + +ROOTDIR=`pwd` +BUILD_DIR="$ROOTDIR/build" +mkdir -p $BUILD_DIR + +JETSON_LINUX_URL="https://developer.nvidia.com/downloads/embedded/l4t/r36_release_v4.4/release/Jetson_Linux_r36.4.4_aarch64.tbz2" +SAMPLE_ROOTFS_URL="https://developer.nvidia.com/downloads/embedded/l4t/r36_release_v4.4/release/Tegra_Linux_Sample-Root-Filesystem_r36.4.4_aarch64.tbz2" + +function install_flash_prerequisties() +{ + echo "Install tge additional packages required for flashing" + + cd $BUILD_DIR/Linux_for_Tegra + + sudo ./apply_binaries.sh + + sudo ./tools/l4t_flash_prerequisites.sh + +} + +function download_bsp_source() +{ + # Check if the BSP source is already downloaded + if [ ! -d "$BUILD_DIR/Linux_for_Tegra" ]; then + echo "Download and Extract the NVIDIA Jetson Linux 36.4.4 BSP Driver package" + cd $BUILD_DIR + wget -q -O- "$JETSON_LINUX_URL" | tar xj + echo "Cloned the NVIDIA L4T linux kernel sources" + cd Linux_for_Tegra/ + pushd . + else + echo "BSP source already downloaded, skipping..." + fi +} + +function download_sample_rootfs() +{ + # Check if the rootfs directory exists and contains expected files + if [ ! -d "$BUILD_DIR/Linux_for_Tegra/rootfs" ] || [ ! -d "$BUILD_DIR/Linux_for_Tegra/rootfs/etc" ] || [ ! -d "$BUILD_DIR/Linux_for_Tegra/rootfs/bin" ]; then + echo "Download and extract the sample root file system" + cd $BUILD_DIR/Linux_for_Tegra + mkdir -p rootfs + cd rootfs + wget -q -O- $SAMPLE_ROOTFS_URL | tar xj + cd .. + install_flash_prerequisties + else + echo "Sample root filesystem already downloaded and extracted, skipping..." + fi +} + +function main() +{ + + download_bsp_source + + download_sample_rootfs + + sudo ./tools/l4t_create_default_user.sh -u analog -p analog -n ubuntu + + sudo ./tools/kernel_flash/l4t_initrd_flash.sh --external-device nvme0n1p1 -c tools/kernel_flash/flash_l4t_t234_nvme.xml -p '-c bootloader/generic/cfg/flash_t234_qspi.xml' --showlogs --network usb0 jetson-orin-nano-devkit-super internal + + cd $ROOOTDIR +} + +main diff --git a/sdcard-images-utils/nvidia/scripts/system_upgrade/apply_patch.sh b/sdcard-images-utils/nvidia/scripts/system_upgrade/apply_patch.sh index acc61546e..0753890d3 100755 --- a/sdcard-images-utils/nvidia/scripts/system_upgrade/apply_patch.sh +++ b/sdcard-images-utils/nvidia/scripts/system_upgrade/apply_patch.sh @@ -41,6 +41,7 @@ function update_kernel() mkdir test && tar -xjf kernel_supplements.tbz2 -C test > /dev/null 2>&1 sudo rm -rf /boot/adi sudo mkdir -p /boot/adi/ + sudo mkdir -p /lib/firmware/adi sudo cp Image /boot/adi/Image sudo cp -rf tegra234-p3767-camera-p3768-*.dtbo /boot/adi/ cd test/lib/modules/ @@ -56,11 +57,44 @@ function start_services() sudo systemctl start systemd-networkd sudo systemctl enable adi-tof sudo systemctl start adi-tof + sudo systemctl enable jetson-performance + sudo systemctl start jetson-performance } extlinux_conf_file="/boot/extlinux/extlinux.conf" +function get_boot_device_type() +{ + if [[ ! -f "$extlinux_conf_file" ]]; then + echo "ERROR: File not found: ${extlinux_conf_file}" + boot_device_type="unknown" + return 1 + fi + + # Check for PARTUUID (SSD/NVMe boot) + if grep -q "PARTUUID" "${extlinux_conf_file}"; then + partuuid=$(grep -oP '(?<=PARTUUID=).{36}' "${extlinux_conf_file}" | head -n 1) + boot_device_type="ssd" + boot_device_info="${partuuid}" + echo "Boot device: SSD (NVMe)" + echo "PARTUUID: ${partuuid}" + return 0 + # Check for microSD card boot + elif grep -q "root=/dev/mmcblk0p1" "${extlinux_conf_file}"; then + boot_device_type="sdcard" + boot_device_info="/dev/mmcblk0p1" + echo "Boot device: microSD card" + echo "Root device: /dev/mmcblk0p1" + return 0 + else + boot_device_type="unknown" + boot_device_info="" + echo "WARNING: Unable to determine boot device type" + return 2 + fi +} + function truncate_file() { if [[ ! -f "$extlinux_conf_file" ]]; then echo "File not found!" @@ -73,53 +107,63 @@ function truncate_file() { sed -i "s/^DEFAULT .*/DEFAULT primary/" "$extlinux_conf_file" } -function get_root_count() -{ - count_value="$(grep -c "root=/dev/mmcblk0p1" ${extlinux_conf_file})" - echo "get_root_count = ${count_value}" -} - function add_boot_label() { + # Determine DTB file dynamically + DTB_FILE=$(basename "$(ls /boot/dtb/*.dtb 2>/dev/null | head -n 1)") + + if [[ -z "${DTB_FILE}" ]]; then + echo "ERROR: No DTB file found in /boot/dtb" + exit 1 + fi + + # Determine root device based on boot type + local root_device + if [[ "${boot_device_type}" == "ssd" ]]; then + root_device="root=PARTUUID=${boot_device_info}" + else + root_device="root=/dev/mmcblk0p1" + fi + sudo -s <> ${extlinux_conf_file} echo "LABEL backup" >> ${extlinux_conf_file} echo " MENU LABEL backup kernel" >> ${extlinux_conf_file} echo " LINUX /boot/Image.backup" >> ${extlinux_conf_file} - echo " FDT /boot/dtb/kernel_tegra234-p3768-0000+p3767-0005-nv-super.dtb" >> ${extlinux_conf_file} + echo " FDT /boot/dtb/${DTB_FILE}" >> ${extlinux_conf_file} echo " INITRD /boot/initrd" >> ${extlinux_conf_file} - echo " APPEND ${cbootargs} root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} + echo " APPEND \${cbootargs} ${root_device} rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} echo " " >> ${extlinux_conf_file} echo "Add the ADSD3500+ADSD3100 label" echo "LABEL ADSD3500+ADSD3100" >> ${extlinux_conf_file} echo " MENU LABEL ADSD3500: " >> ${extlinux_conf_file} echo " LINUX /boot/adi/Image" >> ${extlinux_conf_file} - echo " FDT /boot/dtb/kernel_tegra234-p3768-0000+p3767-0005-nv-super.dtb" >> ${extlinux_conf_file} + echo " FDT /boot/dtb/${DTB_FILE}" >> ${extlinux_conf_file} echo " OVERLAYS /boot/adi/tegra234-p3767-camera-p3768-adsd3500.dtbo" >> ${extlinux_conf_file} echo " INITRD /boot/initrd" >> ${extlinux_conf_file} - echo " APPEND ${cbootargs} root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} + echo " APPEND \${cbootargs} ${root_device} rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} echo " " >> ${extlinux_conf_file} echo "Add the ADSD3500-DUAL+ADSD3100 label" echo "LABEL ADSD3500-DUAL+ADSD3100" >> ${extlinux_conf_file} echo " MENU LABEL ADSD3500-DUAL: " >> ${extlinux_conf_file} echo " LINUX /boot/adi/Image" >> ${extlinux_conf_file} - echo " FDT /boot/dtb/kernel_tegra234-p3768-0000+p3767-0005-nv-super.dtb" >> ${extlinux_conf_file} + echo " FDT /boot/dtb/${DTB_FILE}" >> ${extlinux_conf_file} echo " OVERLAYS /boot/adi/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100.dtbo" >> ${extlinux_conf_file} echo " INITRD /boot/initrd" >> ${extlinux_conf_file} - echo " APPEND ${cbootargs} root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} + echo " APPEND \${cbootargs} ${root_device} rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} echo " " >> ${extlinux_conf_file} echo "Add the ADSD3500-DUAL+ADSD3100+AR0234 label" echo "LABEL ADSD3500-DUAL+ADSD3100+AR0234" >> ${extlinux_conf_file} echo " MENU LABEL ADSD3500-DUAL: " >> ${extlinux_conf_file} echo " LINUX /boot/adi/Image" >> ${extlinux_conf_file} - echo " FDT /boot/dtb/kernel_tegra234-p3768-0000+p3767-0005-nv-super.dtb" >> ${extlinux_conf_file} + echo " FDT /boot/dtb/${DTB_FILE}" >> ${extlinux_conf_file} echo " OVERLAYS /boot/adi/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100-arducam-ar0234.dtbo" >> ${extlinux_conf_file} echo " INITRD /boot/initrd" >> ${extlinux_conf_file} - echo " APPEND ${cbootargs} root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} + echo " APPEND \${cbootargs} ${root_device} rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0" >> ${extlinux_conf_file} echo " " >> ${extlinux_conf_file} exit @@ -136,10 +180,28 @@ function main() { echo "******* Update the Extlinux Conf file *******" truncate_file - get_root_count - if [[ "${count_value}" == 1 ]]; then - add_boot_label + + echo "******* Detect Boot Device Type *******" + get_boot_device_type + + if [[ "${boot_device_type}" == "unknown" ]]; then + echo "ERROR: Cannot proceed without valid boot device detection" + exit 1 + fi + + # Check if boot labels need to be added + if [[ "${boot_device_type}" == "sdcard" ]]; then + # For SD card, check if root device is present + if grep -q "root=/dev/mmcblk0p1" "${extlinux_conf_file}"; then + add_boot_label + fi + elif [[ "${boot_device_type}" == "ssd" ]]; then + # For SSD, check if PARTUUID is present + if grep -q "PARTUUID" "${extlinux_conf_file}"; then + add_boot_label + fi fi + set_default_boot_label echo "******* Apply Ubuntu Overlay *******" diff --git a/sdcard-images-utils/nvidia/scripts/system_upgrade/patch_validation.sh b/sdcard-images-utils/nvidia/scripts/system_upgrade/patch_validation.sh new file mode 100755 index 000000000..ab40e1f4e --- /dev/null +++ b/sdcard-images-utils/nvidia/scripts/system_upgrade/patch_validation.sh @@ -0,0 +1,705 @@ +#!/bin/bash + +# Patch Validation Script for NVIDIA Jetson Orin Nano +# This script validates that all patches from apply_patch.sh were applied successfully +# Version: 1.0 +# Date: 2026-01-27 + +# Exit on error, but allow individual checks to fail gracefully +set -o pipefail + +# Set a timeout for hanging commands (30 seconds per command) +export TMOUT=30 + +# Color codes for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Counters +TOTAL_CHECKS=0 +PASSED_CHECKS=0 +FAILED_CHECKS=0 +WARNING_CHECKS=0 + +# Log file +LOG_FILE="/var/log/adi-patch-validation-$(date '+%Y%m%d-%H%M%S').log" +VALIDATION_REPORT="/boot/adi-patch-validation-report.txt" + +# Configuration +extlinux_conf_file="/boot/extlinux/extlinux.conf" + +# Device validation configuration +I2C_BUS=2 +I2C_ADDRESSES=(0x38 0x58 0x68) +GPIO_LIST=("ISP_RST" "EN_1P8" "EN_0P8" "P2" "I2CM_SEL" "ISP_BS3" "NET_HOST_IO_SEL" "ISP_BS0" "ISP_BS1" "HOST_IO_DIR" "ISP_BS4" "ISP_BS5" "FSYNC_DIR" "EN_VAUX" "EN_VAUX_LS" "EN_SYS") +declare -gA GPIO_MAP + +############################################################################## +# Logging Functions +############################################################################## + +function log_message() { + local level=$1 + shift + local message="$@" + local timestamp=$(date '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "unknown") + echo "[${timestamp}] [${level}] ${message}" 2>/dev/null | sudo tee -a "${LOG_FILE}" > /dev/null 2>&1 || true +} + +function print_header() { + echo -e "${BLUE}================================================================${NC}" + echo -e "${BLUE} ADI ToF Patch Validation Script${NC}" + echo -e "${BLUE} Date: $(date '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo 'unknown')${NC}" + echo -e "${BLUE}================================================================${NC}" + log_message "INFO" "Starting patch validation" +} + +function print_check() { + local check_name="$1" + echo -e "\n${BLUE}[CHECK]${NC} ${check_name}" + ((TOTAL_CHECKS++)) +} + +function print_pass() { + local message="$1" + echo -e "${GREEN}[PASS]${NC} ${message}" + log_message "PASS" "${message}" + ((PASSED_CHECKS++)) +} + +function print_fail() { + local message="$1" + echo -e "${RED}[FAIL]${NC} ${message}" + log_message "FAIL" "${message}" + ((FAILED_CHECKS++)) +} + +function print_warning() { + local message="$1" + echo -e "${YELLOW}[WARN]${NC} ${message}" + log_message "WARN" "${message}" + ((WARNING_CHECKS++)) +} + +############################################################################## +# Validation Functions +############################################################################## + +function validate_boot_device_detection() { + print_check "Boot Device Detection" + + if [[ ! -f "$extlinux_conf_file" ]]; then + print_fail "Extlinux configuration file not found: ${extlinux_conf_file}" + return 1 + fi + + if grep -q "PARTUUID" "${extlinux_conf_file}"; then + boot_device_type="ssd" + partuuid=$(grep -oP '(?<=PARTUUID=).{36}' "${extlinux_conf_file}" | head -n 1) + print_pass "Boot device: SSD (NVMe) with PARTUUID: ${partuuid}" + elif grep -q "root=/dev/mmcblk0p1" "${extlinux_conf_file}"; then + boot_device_type="sdcard" + print_pass "Boot device: microSD card (root=/dev/mmcblk0p1)" + else + print_fail "Unable to determine boot device type" + return 1 + fi + + return 0 +} + +function validate_extlinux_config() { + print_check "Extlinux Configuration" + + # Check if default label is set correctly + if grep -q "^DEFAULT ADSD3500-DUAL+ADSD3100" "${extlinux_conf_file}"; then + print_pass "Default boot label set to ADSD3500-DUAL+ADSD3100" + else + print_fail "Default boot label not set correctly" + fi + + # Check for required boot labels + local required_labels=("backup" "ADSD3500+ADSD3100" "ADSD3500-DUAL+ADSD3100" "ADSD3500-DUAL+ADSD3100+AR0234") + for label in "${required_labels[@]}"; do + if grep -q "LABEL ${label}" "${extlinux_conf_file}"; then + print_pass "Boot label '${label}' exists" + else + print_warning "Boot label '${label}' not found" + fi + done + + # Verify correct root device in APPEND lines + local expected_root_pattern + if [[ "${boot_device_type}" == "ssd" ]]; then + expected_root_pattern="root=PARTUUID=" + else + expected_root_pattern="root=/dev/mmcblk0p1" + fi + + if grep "APPEND" "${extlinux_conf_file}" | grep -q "${expected_root_pattern}"; then + print_pass "Root device correctly configured in APPEND lines" + else + print_fail "Root device not correctly configured in APPEND lines" + fi +} + +function validate_kernel_files() { + print_check "Kernel Files" + + # Check ADI kernel + if [[ -f "/boot/adi/Image" ]]; then + print_pass "ADI kernel image exists: /boot/adi/Image" + else + print_fail "ADI kernel image not found: /boot/adi/Image" + fi + + # Check backup kernel + if [[ -f "/boot/Image.backup" ]]; then + print_pass "Backup kernel exists: /boot/Image.backup" + else + print_warning "Backup kernel not found: /boot/Image.backup" + fi + + # Check sw-versions file + if [[ -f "/boot/sw-versions" ]]; then + print_pass "Software versions file exists: /boot/sw-versions" + cat /boot/sw-versions >> "${LOG_FILE}" + else + print_warning "Software versions file not found: /boot/sw-versions" + fi +} + +function validate_device_tree_overlays() { + print_check "Device Tree Overlays" + + local dtbo_files=( + "/boot/adi/tegra234-p3767-camera-p3768-adsd3500.dtbo" + "/boot/adi/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100.dtbo" + "/boot/adi/tegra234-p3767-camera-p3768-dual-adsd3500-adsd3100-arducam-ar0234.dtbo" + ) + + for dtbo in "${dtbo_files[@]}"; do + if [[ -f "${dtbo}" ]]; then + print_pass "Device tree overlay exists: $(basename ${dtbo})" + else + print_fail "Device tree overlay not found: ${dtbo}" + fi + done +} + +function validate_kernel_modules() { + print_check "Kernel Modules" + + local module_dir="/lib/modules/5.15.148-adi-tegra" + + if [[ -d "${module_dir}" ]]; then + print_pass "ADI kernel modules directory exists: ${module_dir}" + + # Check for specific critical modules + local module_count=$(find "${module_dir}" -name "*.ko" 2>/dev/null | wc -l) + if [[ ${module_count} -gt 0 ]]; then + print_pass "Found ${module_count} kernel modules" + else + print_warning "No kernel modules (.ko files) found in ${module_dir}" + fi + else + print_fail "ADI kernel modules directory not found: ${module_dir}" + fi +} + +function validate_firmware_directory() { + print_check "Firmware Directory" + + if [[ -d "/lib/firmware/adi" ]]; then + print_pass "ADI firmware directory exists: /lib/firmware/adi" + else + print_warning "ADI firmware directory not found: /lib/firmware/adi (may be created on first boot)" + fi +} + +function validate_network_configuration() { + print_check "Network Configuration" + + # Check NetworkManager configuration + if [[ -f "/etc/NetworkManager/conf.d/10-ignore-interface.conf" ]]; then + print_pass "NetworkManager configuration exists" + else + print_fail "NetworkManager configuration not found" + fi + + # Check systemd network configuration + if [[ -f "/etc/systemd/network/10-rndis0.network" ]]; then + print_pass "Systemd network configuration exists" + + # Check MTU setting + if grep -q "15000" "/etc/systemd/network/10-rndis0.network"; then + print_pass "MTU size configured to 15000" + else + print_warning "MTU size not set to 15000" + fi + else + print_fail "Systemd network configuration not found" + fi + + # Check USB device mode configuration + if [[ -f "/opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-config.sh" ]]; then + if grep -q "net_dhcp_lease_time=1500" "/opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-config.sh"; then + print_pass "DHCP lease time configured to 1500" + else + print_warning "DHCP lease time not set to 1500" + fi + else + print_warning "USB device mode configuration not found" + fi + + if [[ -f "/opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-start.sh" ]]; then + if grep -q "sudo ip link set l4tbr0 mtu 15000" "/opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-start.sh"; then + print_pass "L4T bridge MTU size configured" + else + print_warning "L4T bridge MTU size not configured" + fi + fi +} + +function validate_systemd_services() { + print_check "Systemd Services" + + local services=("adi-tof" "jetson-performance" "systemd-networkd") + + for service in "${services[@]}"; do + # Check if systemctl is available + if ! command -v systemctl &> /dev/null; then + print_warning "systemctl command not available, skipping service checks" + break + fi + + if systemctl is-enabled "${service}" &>/dev/null; then + print_pass "Service '${service}' is enabled" + + if systemctl is-active "${service}" &>/dev/null; then + print_pass "Service '${service}' is running" + else + print_warning "Service '${service}' is not running (may start on next boot)" + fi + else + # Check if service file exists at least + if systemctl list-unit-files "${service}.service" &>/dev/null | grep -q "${service}"; then + print_warning "Service '${service}' exists but is not enabled" + else + print_fail "Service '${service}' is not found" + fi + fi + done +} + +function validate_udev_rules() { + print_check "Udev Rules" + + if [[ -f "/etc/udev/rules.d/99-gpio.rules" ]]; then + print_pass "GPIO udev rules exist" + else + print_fail "GPIO udev rules not found" + fi +} + +function validate_shell_scripts() { + print_check "Shell Scripts" + + local script_dir="/usr/share/systemd" + local script_count=$(find "${script_dir}" -maxdepth 1 -name "*.sh" -type f 2>/dev/null | wc -l) + + if [[ ${script_count} -gt 0 ]]; then + print_pass "Found ${script_count} shell scripts in ${script_dir}" + else + print_warning "No shell scripts found in ${script_dir}" + fi +} + +function validate_system_info() { + print_check "System Information" + + # Kernel version + local kernel_version=$(uname -r 2>/dev/null || echo "unknown") + print_pass "Current kernel: ${kernel_version}" + log_message "INFO" "Kernel version: ${kernel_version}" + + # Check if running on Jetson + if [[ -f "/etc/nv_tegra_release" ]]; then + local tegra_version=$(cat /etc/nv_tegra_release 2>/dev/null | head -n 1 || echo "unknown") + print_pass "NVIDIA Tegra platform detected: ${tegra_version}" + log_message "INFO" "Tegra version: ${tegra_version}" + else + print_warning "Not running on NVIDIA Tegra platform" + fi + + # Check boot device + local current_root=$(findmnt -n -o SOURCE / 2>/dev/null || echo "unknown") + if [[ "${current_root}" != "unknown" ]]; then + print_pass "Current root filesystem: ${current_root}" + log_message "INFO" "Root filesystem: ${current_root}" + else + print_warning "Unable to determine root filesystem (findmnt not available)" + current_root=$(mount | grep ' / ' | cut -d' ' -f1 || echo "unknown") + if [[ "${current_root}" != "unknown" ]]; then + print_pass "Current root filesystem: ${current_root}" + log_message "INFO" "Root filesystem: ${current_root}" + fi + fi +} + +function validate_camera_devices() { + print_check "Camera Devices (V4L2)" + + # Check if v4l2-ctl is available + if ! command -v v4l2-ctl &> /dev/null; then + print_warning "v4l2-ctl not available, skipping detailed camera check" + print_warning "Please run the command install the v4l2-ctl package" + print_warning "sudo apt install v4l-utils" + # Still check for video devices + if ls /dev/video* &>/dev/null; then + local video_devices=$(ls -1 /dev/video* 2>/dev/null | wc -l) + print_pass "Found ${video_devices} video device(s)" + else + print_warning "No video devices found (camera may need to be connected or system rebooted)" + fi + return 0 + fi + + local video_devices=$(ls -1 /dev/video* 2>/dev/null | wc -l) + + if [[ ${video_devices} -gt 0 ]]; then + print_pass "Found ${video_devices} video device(s)" + + # List video devices + for dev in /dev/video*; do + if [[ -c "${dev}" ]]; then + local dev_name=$(v4l2-ctl --device="${dev}" --info 2>/dev/null | grep "Card type" | cut -d ':' -f 2 | xargs || echo "Unknown") + log_message "INFO" "Video device: ${dev} - ${dev_name}" + fi + done + else + print_warning "No video devices found (camera may need to be connected or system rebooted)" + fi +} + +############################################################################## +# Device Hardware Validation Functions +############################################################################## + +function validate_i2c_devices() { + print_check "I2C Device Detection" + + # Check if i2cdetect is available + if ! command -v i2cdetect &> /dev/null; then + print_warning "i2cdetect not available (install i2c-tools), skipping I2C checks" + return 0 + fi + + # Check if I2C bus exists + if [[ ! -e "/dev/i2c-${I2C_BUS}" ]]; then + print_fail "I2C bus ${I2C_BUS} not found (/dev/i2c-${I2C_BUS})" + return 1 + fi + + print_pass "I2C bus ${I2C_BUS} exists" + + # Scan I2C bus + local output + output=$(i2cdetect -y -r "$I2C_BUS" 2>/dev/null) + + if [[ -z "$output" ]]; then + print_fail "Unable to scan I2C bus ${I2C_BUS}" + return 1 + fi + + local all_present=0 + + for addr in "${I2C_ADDRESSES[@]}"; do + local row=$(printf "%02x" $((addr & 0xF0))) + local col=$((addr & 0x0F)) + + local value=$(echo "$output" | awk -v row="$row" -v col="$col" ' + $1 == row ":" { print $(col + 2) } + ') + + if [[ "$value" != "--" && -n "$value" ]]; then + print_pass "I2C device present at address 0x$(printf "%02x" $addr)" + log_message "INFO" "I2C device at 0x$(printf "%02x" $addr): ${value}" + else + print_fail "I2C device NOT present at address 0x$(printf "%02x" $addr)" + log_message "ERROR" "I2C device missing at 0x$(printf "%02x" $addr)" + all_present=1 + fi + done + + if [[ $all_present -eq 0 ]]; then + print_pass "All required I2C devices detected" + else + print_fail "One or more I2C devices missing" + fi + + return $all_present +} + +function validate_gpio_labels() { + print_check "GPIO Label Detection" + + # Check if debugfs gpio is available + if [[ ! -f "/sys/kernel/debug/gpio" ]]; then + print_warning "GPIO debugfs not available (/sys/kernel/debug/gpio), skipping GPIO label checks" + return 0 + fi + + local gpio_data + gpio_data=$(cat /sys/kernel/debug/gpio 2>/dev/null) + + if [[ -z "$gpio_data" ]]; then + print_fail "Unable to read GPIO information from debugfs" + return 1 + fi + + local all_found=0 + local found_count=0 + + for label in "${GPIO_LIST[@]:1}"; do + local result=$(echo "$gpio_data" | grep -i "\b$label\b" || true) + + if [[ -n "$result" ]]; then + local gpio_num=$(echo "$result" | sed -E 's/.*gpio-([0-9]+).*/\1/' || echo "") + + if [[ -n "$gpio_num" ]]; then + GPIO_MAP["$label"]=$gpio_num + print_pass "GPIO label '${label}' found -> gpio-${gpio_num}" + log_message "INFO" "GPIO: ${label} = gpio-${gpio_num}" + ((found_count++)) + else + print_warning "GPIO label '${label}' found, but GPIO number extraction failed" + log_message "WARN" "GPIO ${label}: number extraction failed" + fi + else + print_fail "GPIO label '${label}' not found in debugfs" + log_message "ERROR" "GPIO label '${label}' not found" + all_found=1 + fi + done + + if [[ $all_found -eq 0 ]]; then + print_pass "All ${found_count} GPIO labels detected successfully" + else + print_fail "One or more GPIO labels not found" + fi + + return $all_found +} + +function validate_tof_service() { + print_check "ToF Service Execution" + + # Check if journalctl is available + if ! command -v journalctl &> /dev/null; then + print_warning "journalctl not available, skipping ToF service validation" + return 0 + fi + + local service="adi-tof.service" + local logs + + # Get logs for this boot only + logs=$(journalctl -u "$service" -b --no-pager 2>/dev/null || echo "") + + if [[ -z "$logs" ]]; then + print_warning "No logs found for ${service} (service may not have run yet)" + return 0 + fi + + # Explicit skip case (not an error) + if echo "$logs" | grep -q "Skipping ToF power sequence"; then + print_pass "ToF power sequence intentionally skipped (as configured)" + log_message "INFO" "ToF power sequence skipped by configuration" + return 0 + fi + + # Hard failure indicators + if echo "$logs" | grep -qiE "not found|not extracted correctly|GPIO detection failed|I2C check failed"; then + print_fail "GPIO/I2C detection failure found in service logs" + log_message "ERROR" "ToF service reported GPIO/I2C failures" + echo "$logs" | tail -n 20 >> "${LOG_FILE}" 2>/dev/null || true + return 1 + fi + + # Expected execution checkpoints + local required_msgs=( + "Matched MODULE:" + "Configuring GPIOs via sysfs..." + "GPIO configuration complete." + "Starting ToF power sequence..." + "ToF power sequence completed." + ) + + local all_msgs_found=0 + + for msg in "${required_msgs[@]}"; do + if echo "$logs" | grep -q "$msg"; then + print_pass "Found checkpoint: ${msg}" + log_message "INFO" "ToF service checkpoint: ${msg}" + else + print_fail "Missing checkpoint: ${msg}" + log_message "ERROR" "ToF service missing checkpoint: ${msg}" + all_msgs_found=1 + fi + done + + if [[ $all_msgs_found -eq 0 ]]; then + print_pass "ToF power/reset sequence validated successfully" + else + print_fail "ToF service validation incomplete" + echo "$logs" | tail -n 30 >> "${LOG_FILE}" 2>/dev/null || true + fi + + return $all_msgs_found +} + +############################################################################## +# Report Generation +############################################################################## + +function generate_validation_report() { + local report_file="${VALIDATION_REPORT}" + + # Create report directory if needed + mkdir -p "$(dirname ${report_file})" 2>/dev/null || true + + { + echo "================================================================" + echo " ADI ToF Patch Validation Report" + echo " Generated: $(date '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo 'unknown')" + echo "================================================================" + echo "" + echo "SUMMARY:" + echo " Total Checks: ${TOTAL_CHECKS}" + echo " Passed: ${PASSED_CHECKS}" + echo " Failed: ${FAILED_CHECKS}" + echo " Warnings: ${WARNING_CHECKS}" + echo "" + + if [[ ${FAILED_CHECKS} -eq 0 ]]; then + echo "RESULT: PASS (All critical checks passed)" + else + echo "RESULT: FAIL (${FAILED_CHECKS} critical check(s) failed)" + fi + + echo "" + echo "BOOT DEVICE:" + echo " Type: ${boot_device_type:-unknown}" + echo "" + echo "SYSTEM INFO:" + echo " Kernel: $(uname -r 2>/dev/null || echo 'unknown')" + echo " Architecture: $(uname -m 2>/dev/null || echo 'unknown')" + if [[ -f /etc/os-release ]]; then + echo " OS: $(cat /etc/os-release 2>/dev/null | grep PRETTY_NAME | cut -d '=' -f 2 | tr -d '\"' || echo 'unknown')" + fi + echo "" + echo "HARDWARE DEVICES:" + echo " I2C Bus: ${I2C_BUS}" + echo " Expected I2C Devices: ${#I2C_ADDRESSES[@]}" + echo " Expected GPIO Labels: ${#GPIO_LIST[@]}" + if [[ ${#GPIO_MAP[@]} -gt 0 ]]; then + echo " Detected GPIO Labels: ${#GPIO_MAP[@]}" + fi + echo "" + echo "For detailed logs, see: ${LOG_FILE}" + echo "================================================================" + } > "${report_file}" 2>/dev/null || { + echo -e "${YELLOW}Warning: Cannot write validation report to ${report_file}${NC}" + } + + if [[ -f "${report_file}" ]]; then + echo -e "\n${BLUE}Validation report saved to: ${report_file}${NC}" + fi +} + +function print_summary() { + echo -e "\n${BLUE}================================================================${NC}" + echo -e "${BLUE} VALIDATION SUMMARY${NC}" + echo -e "${BLUE}================================================================${NC}" + echo -e " Total Checks: ${TOTAL_CHECKS}" + echo -e " ${GREEN}Passed: ${PASSED_CHECKS}${NC}" + echo -e " ${RED}Failed: ${FAILED_CHECKS}${NC}" + echo -e " ${YELLOW}Warnings: ${WARNING_CHECKS}${NC}" + echo -e "${BLUE}================================================================${NC}\n" + + if [[ ${FAILED_CHECKS} -eq 0 ]]; then + echo -e "${GREEN}✓ All critical checks passed!${NC}\n" + log_message "INFO" "Validation completed successfully" + return 0 + else + echo -e "${RED}✗ ${FAILED_CHECKS} critical check(s) failed!${NC}\n" + echo -e "${YELLOW}Please review the errors above and the log file: ${LOG_FILE}${NC}\n" + log_message "ERROR" "Validation failed with ${FAILED_CHECKS} errors" + return 1 + fi +} + +############################################################################## +# Main Execution +############################################################################## + +function main() { + # Check if running as root or with sudo + if [[ $EUID -ne 0 ]]; then + echo -e "${RED}This script must be run as root or with sudo${NC}" + exit 1 + fi + + # Create log directory if needed + mkdir -p "$(dirname ${LOG_FILE})" 2>/dev/null || true + touch "${LOG_FILE}" 2>/dev/null || { + echo -e "${YELLOW}Warning: Cannot create log file ${LOG_FILE}, continuing without logging${NC}" + LOG_FILE="/dev/null" + } + + print_header + + echo -e "\n${BLUE}Starting validation checks...${NC}\n" + + # Run all validations with error handling + validate_system_info || echo -e "${YELLOW}System info check encountered issues${NC}" + validate_boot_device_detection || echo -e "${YELLOW}Boot device detection encountered issues${NC}" + validate_extlinux_config || echo -e "${YELLOW}Extlinux config check encountered issues${NC}" + validate_kernel_files || echo -e "${YELLOW}Kernel files check encountered issues${NC}" + validate_device_tree_overlays || echo -e "${YELLOW}Device tree overlay check encountered issues${NC}" + validate_kernel_modules || echo -e "${YELLOW}Kernel modules check encountered issues${NC}" + validate_firmware_directory || echo -e "${YELLOW}Firmware directory check encountered issues${NC}" + validate_network_configuration || echo -e "${YELLOW}Network configuration check encountered issues${NC}" + validate_systemd_services || echo -e "${YELLOW}Systemd services check encountered issues${NC}" + validate_udev_rules || echo -e "${YELLOW}Udev rules check encountered issues${NC}" + validate_shell_scripts || echo -e "${YELLOW}Shell scripts check encountered issues${NC}" + validate_camera_devices || echo -e "${YELLOW}Camera devices check encountered issues${NC}" + + echo -e "\n${BLUE}================================================================${NC}" + echo -e "${BLUE} HARDWARE DEVICE VALIDATION${NC}" + echo -e "${BLUE}================================================================${NC}\n" + + # Run hardware device validations + validate_i2c_devices || echo -e "${YELLOW}I2C device check encountered issues${NC}" + validate_gpio_labels || echo -e "${YELLOW}GPIO label check encountered issues${NC}" + validate_tof_service || echo -e "${YELLOW}ToF service check encountered issues${NC}" + + # Generate report and print summary + generate_validation_report + print_summary + + # Exit with appropriate code + if [[ ${FAILED_CHECKS} -eq 0 ]]; then + exit 0 + else + exit 1 + fi +} + +# Run main function +main "$@" +