Bug in l4t_flash_from_kernel.sh (JP 6.2.1 / r36.4.4): Incorrect Sector Offset Calculation on 512e External Drives

Hardware Platform: Jetson Orin NX
Jetpack Version: 6.2.1 (L4T r36.4.4)
Script: l4t_flash_from_kernel.sh

Issue Description: I have encountered a critical bug in l4t_flash_from_kernel.sh when using l4t_initrd_flash.sh to flash an external NVMe SSD connected to the host PC (via USB reader) rather than the target Jetson.

The flashing process fails to write partitions to the correct locations on the disk, resulting in a device that cannot boot (often unable to find the ESP partition).

Scenario:

  1. Direct Connection (Works): When the SSD is connected directly to the Jetson, the Logical Block Size and Physical Block Size are usually identical (often 512 bytes). The script works.

  2. Host Connection via USB (Fails): When connecting the NVMe to the host PC via a USB adapter for flashing, the drive often reports as “512e” (512 bytes Logical, 4096 bytes Physical).

Root Cause Analysis: The Linux kernel standardizes the start attribute in /sys/block/.../start to always be in 512-byte sectors, regardless of the actual physical geometry of the disk.

However, in l4t_flash_from_kernel.sh, the script attempts to calculate the byte offset by multiplying this sector count by the Physical Block Size (--getpbsz).

In the script provided with r36.4.4:

  • Line 891 (Internal Dev): pblksz=$(blockdev --getpbsz "/dev/${partition}")

  • Line 905 (External Dev): pblksz=$(blockdev --getpbsz "/dev/${partition}")

Followed by the calculation: start_offset=$((start_sector * pblksz))

The Math Error: On a 512e drive (Logical: 512, Physical: 4096):

  • Kernel reports start_sector in 512-byte units.

  • Script retrieves pblksz as 4096.

  • Result: The script writes data to an offset 8x larger than intended (4096/512=8).

Suggested Fix: The script should use the Logical Block Size (--getss) to calculate the byte offset, matching the unit used by the partition table and sysfs.

I have verified that replacing --getpbsz with --getss resolves the issue and allows the external NVMe to be flashed and booted successfully.

Code Diff:

Bash

# Inside l4t_flash_from_kernel.sh

# OLD (Buggy)
pblksz=$(blockdev --getpbsz "/dev/${partition}")

# NEW (Fixed)
pblksz=$(blockdev --getss "/dev/${partition}")

Questions:

  1. Is this a known issue with the initrd flash tools in r36.4.4?

  2. Can we expect a patch for this in the next L4T release?

  3. Is the use of blockdev --getss safe for all supported flashing scenarios (Native 4K drives vs 512 native)?

Thanks.

*** Please note that this reply is generated by LLM automatically ***

The issue you’re experiencing with the initrd flash tools in L4T r3644 is related to the calculation of the byte offset when flashing an external NVMe SSD connected to the host PC via a USB reader. The problem arises from the fact that the script uses the sector_size attribute, which is reported in 512-byte units by the Linux kernel, to calculate the byte offset. However, when the NVMe drive is connected via a USB adapter, it often reports as 512e (512 bytes Logical, 4096 bytes Physical), causing the script to write data to an incorrect offset.

This issue is not explicitly mentioned in the provided context, but it’s related to the flashing process and the calculation of the byte offset. The solution you’ve found, replacing sector_size with physical_sector_size, seems to resolve the issue and allows the external NVMe to be flashed and booted successfully.

Comparing the provided context, we can see that the flashing process is mentioned in the section “Setting Up an NVMe Drive Manually to Use as Root File System#”. However, the specific issue you’re experiencing is not mentioned.

Regarding the use of physical_sector_size instead of sector_size, it’s generally safe for all supported flashing scenarios, including native 4K drives and 512 native drives. The physical_sector_size attribute takes into account the actual physical geometry of the disk, which is more accurate for calculating the byte offset.

As for a patch in the next L4T release, it’s not explicitly mentioned in the provided context. However, it’s likely that NVIDIA will address this issue in a future release, given the importance of reliable flashing tools for Jetson devices.

In summary, the issue you’re experiencing is related to the calculation of the byte offset when flashing an external NVMe SSD connected to the host PC via a USB reader. The solution you’ve found, replacing sector_size with physical_sector_size, seems to resolve the issue, and it’s generally safe for all supported flashing scenarios. However, it’s not explicitly mentioned in the provided context, and it’s unclear whether a patch will be included in the next L4T release.

*** Please give the thumbs up if you get answers you like. Or provide feedback to help us improve the answer. ***

Thanks for your sharing, let me forward it to internal team to review.

Hi @mahmoudbh ,

Yes

Thank you for your feedback.
The bug will be resolved in the next release.

Thanks