From 4faad557205a191560cf417d3e9702015009600d Mon Sep 17 00:00:00 2001 From: Dmitry Ilyin <6576495+widgetii@users.noreply.github.com> Date: Thu, 22 Oct 2026 15:07:06 +0300 Subject: [PATCH 1/2] load_novatek: refuse to load HDAL over the kernel's own memory The vendor U-Boot lays memory out from osmem (DT memory node up to it, HDAL pool from it), while the kernel takes its RAM from mem= alone. The bootcmd the wiki gives these boards re-runs the saved bootargs, so the two drift apart as soon as one is changed without the other. Booted with mem= past the node, the kernel owns the start of the HDAL pool and nvtmpp_heap_init in kflow_common oopses (mmioset, NULL dereference) and panics the camera, every boot. Compare mem= with the DT memory node first. When it runs past it, say so, skip the HDAL modules, and write the size U-Boot used back into bootargs so the next boot is consistent. Proven on an NT98566 + SC501AI: saved mem=54M with osmem=32M boots without the panic and heals on the next reboot. --- .../files/script/load_novatek | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/general/package/novatek-osdrv-nt9856x/files/script/load_novatek b/general/package/novatek-osdrv-nt9856x/files/script/load_novatek index 1ab7584223..420c69e024 100755 --- a/general/package/novatek-osdrv-nt9856x/files/script/load_novatek +++ b/general/package/novatek-osdrv-nt9856x/files/script/load_novatek @@ -152,6 +152,35 @@ insert_ko() { #insmod hdal/kdrv_videoout/fbdev/nvt_fb.ko } +# The vendor U-Boot lays memory out from osmem: the DT memory node it hands +# over ends there and the HDAL pool starts there. The kernel's RAM comes from +# mem= alone, and the bootcmd these boards were given re-runs the saved +# bootargs, so an osmem changed later never reaches mem=. Booted with mem= +# past the node, the kernel owns the start of the HDAL pool and +# nvtmpp_heap_init in kflow_common panics the camera into a reboot loop. +# The opposite drift leaves the DT above the kernel's RAM and hangs it before +# the console, which nothing here can catch. #2107. +check_mem() { + reg=/proc/device-tree/memory/reg + [ -r $reg ] || return 0 + dt_mem=$(( 0x$(hexdump -ve '1/1 "%02x"' $reg | cut -c9-16) >> 20 )) + booted_mem=$(awk -F '=' '$1=="mem" && $2 ~ /^[0-9]+M$/ {print $2+0; exit}' RS=" " /proc/cmdline) + [ -n "$booted_mem" ] && [ "$booted_mem" -gt "$dt_mem" ] || return 0 + + logger -s -p daemon.err -t novatek "Kernel booted with mem=${booted_mem}M, past the ${dt_mem}M U-Boot laid out from osmem; HDAL would overwrite kernel memory, not loading it" + bootargs=$(fw_printenv -n bootargs 2>/dev/null) + case " $bootargs" in + *" mem=${booted_mem}M"*) + bootargs=$(echo " $bootargs" | sed "s/ mem=${booted_mem}M/ mem=${dt_mem}M/; s/^ //") + fw_setenv bootargs "$bootargs" && + logger -s -p daemon.err -t novatek "bootargs set to mem=${dt_mem}M; reboot to load HDAL" + ;; + esac + exit 1 +} + +check_mem + cd /lib/modules/4.19.91/novatek insert_ko From 3bb6eb83ef3962970a9f3d3bc25e9dda31e4e25f Mon Sep 17 00:00:00 2001 From: Dmitry Ilyin <6576495+widgetii@users.noreply.github.com> Date: Thu, 22 Oct 2026 15:33:03 +0300 Subject: [PATCH 2/2] load_novatek: read mem= as a whole argument, the last one included A space-separated awk record kept /proc/cmdline's trailing newline on the final argument, so a mem= placed last never matched and the guard let HDAL load over the kernel. Split the command line in the shell instead. --- .../files/script/load_novatek | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/general/package/novatek-osdrv-nt9856x/files/script/load_novatek b/general/package/novatek-osdrv-nt9856x/files/script/load_novatek index 420c69e024..ce2be0bd60 100755 --- a/general/package/novatek-osdrv-nt9856x/files/script/load_novatek +++ b/general/package/novatek-osdrv-nt9856x/files/script/load_novatek @@ -164,8 +164,20 @@ check_mem() { reg=/proc/device-tree/memory/reg [ -r $reg ] || return 0 dt_mem=$(( 0x$(hexdump -ve '1/1 "%02x"' $reg | cut -c9-16) >> 20 )) - booted_mem=$(awk -F '=' '$1=="mem" && $2 ~ /^[0-9]+M$/ {print $2+0; exit}' RS=" " /proc/cmdline) - [ -n "$booted_mem" ] && [ "$booted_mem" -gt "$dt_mem" ] || return 0 + booted_mem= + for arg in $(cat /proc/cmdline); do + case "$arg" in + mem=*M) + booted_mem=${arg#mem=} + booted_mem=${booted_mem%M} + break + ;; + esac + done + case "$booted_mem" in + "" | *[!0-9]*) return 0 ;; + esac + [ "$booted_mem" -gt "$dt_mem" ] || return 0 logger -s -p daemon.err -t novatek "Kernel booted with mem=${booted_mem}M, past the ${dt_mem}M U-Boot laid out from osmem; HDAL would overwrite kernel memory, not loading it" bootargs=$(fw_printenv -n bootargs 2>/dev/null)