How to clone b01 nano devkit SD card (Contain changed logo)?

I have two b01 nano devkit, and I had solved the following article at one of b01 nano devkit.

However, I wanna clone the SD image to another nano now.
Not only SD card image, but also logo.

First, I wanna ask that, cloning SD card image will contain changed logo? So, If I simply clone a SD card to another SD card, it’s correct?

And then, example the following articles, I don’t understand their different. I should use which method to solve my question.

The SD card models also contain QSPI memory on the module itself. Depending on which L4T release you are using, different amounts of the boot content are in the QSPI, and not on the SD card. Later releases (I think after 32.4.1?) put all boot content in QSPI memory. I think (but am not positive, someone please verify) that the boot logo is part of that content. That content is changed by flash, and not via SD card, so I don’t think simply changing the SD card is enough to preserve custom boot logos.

You mean simply copy the SD card image isn’t enough to preserve custom boot logos.

Therefore, If I wanna copy not only SD card image but also logo at QSPI to another b01 nano devkit.

Accordingly,these articles only copy SD card image? Can’t copy logo at QSPI ?

So, how to solve that? I wil try that at tomorrow working. Thank you so much.

There are lots of partitions over the jetson nano. Each partition stores different content.

For example, flash.sh -k BMP means flashing the “BMP” partition and this partition stores your boot logo.

However, on jetson nano, most of partitions are on the jetson nano module QSPI-NOR. The sdcard only has kernel related and rootfs partitions.

Which means keep changing the sdcard will never really update the BMP partition over the QSPI of the module…

The sdcard image is just for some newbie to just start to use jetson nano. Actually, for true development, it is always better to use flash.sh and the tools inside Linux_for_Tegra.

Sorry, I first sure a thing.

Now, I already used SDK Manager to flash my nano devkit, and logo.

This thing means I already used flash.sh and the tools inside Linux_for_Tegra? Or not, I just used SD card flash image?

Because I thinky used SDK Manager that means used flash.sh and the tools inside Linux_for_Tegra.

Therefore, if I wanna clone SD card image and logo to new nano devkit.

I must use the following? Help me sure that, thank you.

  1. “flash.sh -k BMP means flashing the “BMP” partition and this partition stores your boot logo.”

  2. Clone my SD card image
    “sudo ./flash.sh -r -k APP -G backup.img jetson-nano-sd mmcblk0p1”
    “sudo ./flash.sh -r -k APP jetson-nano-sd mmcblk0p1”

You already flashed one partition on your QSPI-NOR. You didn’t flash the whole QSPI+ your sdcard.

Your sdcard still uses the sdcard image content.

Therefore, if I wanna clone SD card image and logo to new nano devkit.

It is possible to clone the sdcard but not possible to clone the logo. What you can do is flash you second nano devkit again to update the logo.

Wait, sorry I don’t understand that “You didn’t flash the whole QSPI+ your sdcard. Your sdcard still uses the sdcard image content.”

Because I use SDK Manager to finsh that now.
I have a empty nano devkit and empty SD card image, I use SDK Manager to finish that. And then, I can use jetpack system and my new logo.

So, if I wanna copy system and new logo to many new nano devkit.
I must first use SDK Manager or Command on new nano devkit to solve logo problem.

And then using command “sudo ./flash.sh -r -k APP -G backup.img jetson-nano-sd mmcblk0p1” and “sudo ./flash.sh -r -k APP jetson-nano-sd mmcblk0p1” to clone the jetpack of SD card image?

This will clone rootfs (your file system). Other partitions are still the same. But should satisfy your purpose.

I understand that.

sudo ./flash.sh -r -k APP “platform” mmcblk0p1
<=== Therefor, “platform”, should I type what?

jetson-nano-devkit-sd?
jetson-nano-sd?

Which? And how do I query my platform name? Thank you so much.

This is not a fixed string in the script.

It is just actually the board conf file under your Linux_for_Tegra. For example, jetson-nano-sd stands for jetson-nano-sd.conf.

Which means even writing a 123.conf can let you run flash.sh 123 mmcblk01.

Just use the one that has “qspi-sd” inside the name.

In reality, if you want to clone your SD card, you don’t need to use the flash software. You can just mount it to your PC, and then use something like dd to create as many copies as you want. However, this will never do anything to clone boot logo. The hardware containing that logo is separate, and the flash software is what normally deals with that.

I could see adding a command within the rootfs which would read the logo (and any changes needed for it) to the SD card, and then another program to write to the QSPI for the logo. I have no idea what difficulties this would entail, but it would be risky since you could end up needing to flash again to restore botched QSPI writing. Also, in some cases signed content is used, and in some cases you might find that the same QSPI content for some subset of a module’s memory will break boot if changed if for no other reason than signing no longer being valid.

I guess all of the above is to say it isn’t practical to do what you want unless you are willing to go through a large learning curve and do a lot of reading on flashing and booting. You could do it, but there would be nothing “simple” about it.

I implement the command about “sudo ./flash.sh -r -k APP -G backup.img jetson-nano-qspi-sd mmcblk0p1”, it appears these messages, it’s correct? Therefore, I need to continue to wait for that?

###############################################################################

L4T BSP Information:

R32 , REVISION: 5.1

###############################################################################

Target Board Information:

Name: jetson-nano-qspi-sd, Board Family: t210ref, SoC: Tegra 210,

OpMode: production, Boot Authentication: ,

Disk encryption: disabled ,

###############################################################################
./tegraflash.py --chip 0x21 --applet “/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/nvtboot_recovery.bin” --skipuid --cmd “dump eeprom boardinfo cvm.bin”
Welcome to Tegra Flash
version 1.0.0
Type ? or help for help and q or quit to exit
Use ! to execute system commands

[ 0.0012 ] Generating RCM messages
[ 0.0017 ] tegrarcm --listrcm rcm_list.xml --chip 0x21 0 --download rcm /home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/nvtboot_recovery.bin 0 0
[ 0.0022 ] RCM 0 is saved as rcm_0.rcm
[ 0.0024 ] RCM 1 is saved as rcm_1.rcm
[ 0.0024 ] List of rcm files are saved in rcm_list.xml
[ 0.0024 ]
[ 0.0024 ] Signing RCM messages
[ 0.0029 ] tegrasign --key None --list rcm_list.xml --pubkeyhash pub_key.key
[ 0.0033 ] Assuming zero filled SBK key
[ 0.0065 ]
[ 0.0065 ] Copying signature to RCM mesages
[ 0.0070 ] tegrarcm --chip 0x21 0 --updatesig rcm_list_signed.xml
[ 0.0077 ]
[ 0.0078 ] Boot Rom communication
[ 0.0083 ] tegrarcm --chip 0x21 0 --rcm rcm_list_signed.xml --skipuid
[ 0.0087 ] RCM version 0X210001
[ 0.0517 ] Boot Rom communication completed
[ 1.0601 ]
[ 1.0602 ] dump EEPROM info
[ 1.0630 ] tegrarcm --oem platformdetails eeprom /home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/cvm.bin
[ 1.0653 ] Applet version 00.01.0000
[ 1.0684 ] Saved platform info in /home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/cvm.bin
[ 1.1452 ]
[ 1.1477 ] tegrarcm --reboot recovery
[ 1.1498 ] Applet version 00.01.0000
[ 1.1659 ]
Board ID(3448) version(401)
copying bctfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/BCT/P3448_A00_lpddr4_204Mhz_P987.cfg)… done.
copying bootloader(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/cboot.bin)… done.
copying initrd(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/l4t_initrd.img)… done.
Making Boot image… done.
Existing sosfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/nvtboot_recovery.bin) reused.
copying tegraboot(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/nvtboot.bin)… done.
copying cpu_bootloader(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/cboot.bin)… done.
copying bpffile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/sc7entry-firmware.bin)… done.
Existing badpagefile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/badpage.bin) reused.
copying wb0boot(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/warmboot.bin)… done.
Existing tosfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/tos-mon-only.img) reused.
Existing eksfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/eks.img) reused.
copying dtbfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/kernel/dtb/tegra210-p3448-0000-p3449-0000-b00.dtb)… done.
Copying nv_boot_control.conf to rootfs
Skip generating system.img
Existing tbcfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/nvtboot_cpu.bin) reused.
copying tbcdtbfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/kernel/dtb/tegra210-p3448-0000-p3449-0000-b00.dtb)… done.
copying cfgfile(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/cfg/flash_l4t_t210_max-spi_sd_p3448.xml) to flash.xml… done.
copying flasher(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/t210ref/cboot.bin)… done.
Existing flashapp(/home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/bootloader/tegraflash.py) reused.
*** Reading [APP] and storing to /home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/backup.img ***
./tegraflash.py --bl cboot.bin --bldtb kernel_tegra210-p3448-0000-p3449-0000-b00.dtb --chip 0x21 --applet nvtboot_recovery.bin --bct P3448_A00_lpddr4_204Mhz_P987.cfg --cfg flash.xml --odmdata 0xa4000 --cmd “read APP /home/minggatsby/src/nvidia/nvidia_sdk/JetPack_4.5.1_Linux_JETSON_NANO_DEVKIT/Linux_for_Tegra/backup.img”
Welcome to Tegra Flash
version 1.0.0
Type ? or help for help and q or quit to exit
Use ! to execute system commands

[ 0.0023 ] Generating RCM messages
[ 0.0029 ] tegrarcm --listrcm rcm_list.xml --chip 0x21 0 --download rcm nvtboot_recovery.bin 0 0
[ 0.0034 ] RCM 0 is saved as rcm_0.rcm
[ 0.0037 ] RCM 1 is saved as rcm_1.rcm
[ 0.0037 ] List of rcm files are saved in rcm_list.xml
[ 0.0037 ]
[ 0.0037 ] Signing RCM messages
[ 0.0041 ] tegrasign --key None --list rcm_list.xml --pubkeyhash pub_key.key
[ 0.0046 ] Assuming zero filled SBK key
[ 0.0077 ]
[ 0.0077 ] Copying signature to RCM mesages
[ 0.0082 ] tegrarcm --chip 0x21 0 --updatesig rcm_list_signed.xml
[ 0.0089 ]
[ 0.0089 ] Boot Rom communication
[ 0.0094 ] tegrarcm --chip 0x21 0 --rcm rcm_list_signed.xml
[ 0.0098 ] BR_CID: 0x32101001642e12c42400000010050300
[ 0.0102 ] RCM version 0X210001
[ 0.0269 ] Boot Rom communication completed
[ 1.0350 ]
[ 1.0351 ] Parsing partition layout
[ 1.0377 ] tegraparser --pt flash.xml.tmp
[ 1.0411 ]
[ 1.0413 ] Creating list of images to be signed
[ 1.0436 ] tegrahost --chip 0x21 0 --partitionlayout flash.xml.bin --list images_list.xml
[ 1.0513 ]
[ 1.0514 ] Generating signatures
[ 1.0519 ] tegrasign --key None --list images_list.xml --pubkeyhash pub_key.key
[ 1.0524 ] Assuming zero filled SBK key
[ 1.0864 ]
[ 1.0864 ] Send BCT from Host
[ 1.0865 ] Generating br-bct
[ 1.0871 ] tegrabct --bct P3448_A00_lpddr4_204Mhz_P987.cfg --chip 0x21 0
[ 1.0876 ] Copying Sdram info from 2 to 3 set
[ 1.0892 ]
[ 1.0892 ] Updating boot device parameters
[ 1.0896 ] tegrabct --bct P3448_A00_lpddr4_204Mhz_P987.bct --chip 0x21 0 --updatedevparam flash.xml.bin
[ 1.0901 ] Warning: No sdram params
[ 1.0902 ]
[ 1.0902 ] Updating bl info
[ 1.0907 ] tegrabct --bct P3448_A00_lpddr4_204Mhz_P987.bct --chip 0x21 0 --updateblinfo flash.xml.bin --updatesig images_list_signed.xml
[ 1.0915 ]
[ 1.0915 ] Updating secondary storage information into bct
[ 1.0919 ] tegraparser --pt flash.xml.bin --chip 0x21 0 --updatecustinfo P3448_A00_lpddr4_204Mhz_P987.bct
[ 1.0925 ]
[ 1.0925 ] Updating Odmdata
[ 1.0930 ] tegrabct --bct P3448_A00_lpddr4_204Mhz_P987.bct --chip 0x21 0 --updatefields Odmdata =0xa4000
[ 1.0934 ] Warning: No sdram params
[ 1.0936 ]
[ 1.0936 ] Get Signed section of bct
[ 1.0940 ] tegrabct --bct P3448_A00_lpddr4_204Mhz_P987.bct --chip 0x21 0 --listbct bct_list.xml
[ 1.0945 ]
[ 1.0945 ] Signing BCT
[ 1.0954 ] tegrasign --key None --list bct_list.xml --pubkeyhash pub_key.key
[ 1.0959 ] Assuming zero filled SBK key
[ 1.0961 ]
[ 1.0961 ] Updating BCT with signature
[ 1.0966 ] tegrabct --bct P3448_A00_lpddr4_204Mhz_P987.bct --chip 0x21 0 --updatesig bct_list_signed.xml
[ 1.0971 ]
[ 1.0971 ] Sending BCTs
[ 1.0975 ] tegrarcm --download bct P3448_A00_lpddr4_204Mhz_P987.bct
[ 1.0979 ] Applet version 00.01.0000
[ 1.1123 ] Sending bct
[ 1.1124 ] […] 100%
[ 1.3356 ]
[ 1.3357 ] Retrieving storage infomation
[ 1.3369 ] tegrarcm --oem platformdetails storage storage_info.bin
[ 1.3378 ] Applet version 00.01.0000
[ 1.3526 ] 00000003: Could not initialize storage device
[ 1.8182 ]
[ 1.8210 ] tegradevflash --oem platformdetails storage storage_info.bin

Sorry, can you teach me how to use dd to clone SD card? Which commands? Thank you!

I reference the article, it’s correct?

As result as, I use SDK Manager to solve logo problem, and then, I use dd to solve SD card image problem.

When you use dd to clone an SD card make sure the SD card partitions are not mounted. Before starting, it is useful to know about how to list devices and mount points with “lsblk”. If you run “lsblk” on your host PC prior to having the SD card present you’ll see what partitions and devices your PC uses normally. For example, this is from an NVMe drive on a system which boots both Linux and Windows, plus it has a spare partition for future releases of Linux:

# lsblk
nvme0n1                                                                                         
├─nvme0n1p1                vfat                          7199-294E                              /boot/efi
├─nvme0n1p2                ntfs                          26E36D5F78BC0006                       
├─nvme0n1p3                ext4              ROOTS1      129f5c55-57fe-4d55-bdd3-286744c9346b   /
└─nvme0n1p4                ext4              ROOTS2      6da04e95-d046-4514-a507-6a478417db7d   

The NVMe itself is “/dev/nvme0n1”. This could have also been an ordinary SATA device, in which case it might have a name like “/dev/sda” or “/dev/sdb”. Individual partitions are appended to the name, e.g., “nvme0n1p1” is the first partition on the NVMe device, while “sda1” would be the first device on a SATA disk. For the examples I am going to say “/dev/sdb”, but you’ll need to make sure you use whatever device name the SD card is.

If you monitor “dmesg --follow” prior to connecting the SD card to your PC, then you’ll see log lines added as you insert the SD card. Part of that tells you the name of the device to use, e.g., it might tell you that it sees the device as “sdb”. Remember that designation.

Also, in the example “lsblk”, note that the last column is the mount point. That example shows two partitions are mounted. “/dev/nvmen0p1” is mounted on “/boot/efi”, and “/dev/nvmen1p3” is mounted on “/”. You definitely don’t want to unmount the wrong thing, but as you connect the SD card it is likely an automounter will mount some partition of the SD card.

For every mounted partition of the SD you want to first unmount it. So lets pretend automount has mounted “/dev/sdb1”. To unmount (command is short one letter, it is “umount”):
sudo umount /dev/sdb1
…and after this, “lsblk” should show the partition no longer has a mount point.

Before you start be absolutely sure your host PC has room to hold the clone if your destination is to the host PC. Most people would clone to PC, and then later use that PC’s clone file to write to some new SD card. It is possible, if your PC does not have enough disk space, to name a clone as directly to a second SD card, or to a thumb drive, or to an external storage device if you have one. Let me know if you need to use an alternate destination…my example will be cloning directly to the host PC.

The command “df -H -t ext4” will list how much space is used or available on any partition which is both mounted and of type ext4. You’ll need extra space which is the size of the SD card, plus spare space. So if your SD card is 64GB, then your spare PC space needs to be significantly more than 64GB at the destination location, e.g., I’d say have an extra 16GB or 32GB on top of the example 64GB. If your SD card is smaller, then required size goes down.

Now that your source SD card is present and there is no mount of any partition of that particular SD card you have to find a place where you want to clone to. As an example I am going to create this directory:
mkdir -p ~/nvidia/clone

Then I will go there since that is to be my destination:
cd ~/nvidia/clone

Now I am going to clone the entire SD card (pretending it is “/dev/sdb”):
sudo dd if=/dev/sdb of=my_clone.img bs=1M status=progress

In the above command you could actually leave out the block size ("bs=1M"), and you could leave out the “status=progress”. The block size just makes it go a bit faster by using a buffer, and the “status” just gives you messages to the console as the clone progresses to tell you have far it has gone. If I were doing a data recovery process on a failing drive I would use a block size which is the same size as the disk’s sector size, but you can ignore that since you want to know about errors.

When done you will have a file “~/nvidia/clone/my_clone.img” which is an exact byte-for-byte match to the SD card, including hidden metadata plus all partitions.

Note that the destination could name some specific location other than where you start from, but in the example this just happens to be where the user is at the moment (which happens to be “~/nvidia/clone”. A full path could be named to something else, e.g., to a thumb drive or external drive.

Let’s say you have finished and the source SD card is no longer there. Now you’ve plugged in a new SD card which equal to or larger than the original SD card size. We’re going to pretend that since the old SD card is removed, then the new card has designation “/dev/sdb” (this could just as easily been enumerated as “/dev/sdc”…you need to check “dmesg” to see if you have the correct device…using the wrong device will destroy the content on that device, and dd will happily destroy your operating system if you tell it to). The restore to the new sdb is:

cd ~/nvidia/clone
sudo dd if=my_clone.img of=/dev/sdb bs=1M status=progress

In that example the input file is “my_clone.img”, and the output file is “/dev/sdb” (which is a disk and not a file). Once done your new SD card will be a 100% exact match to the original.

Incidentally, you can mount and examine a clone file from the PC using loopback to make the file appear to be a disk. Something like this:

cd ~/nvidia/clone
sudo mount -o loop my_clone.img /mnt
ls /mnt
sudo umount /mnt

Thus you can pick and choose things to copy or modify on the clone at any time.