we have custom boards based on i.MX 8M Mini Quad CPU (MIMX8MM6CVTKZAA) that are being booted from RAW NAND. NAND chip used is: Micron MT29F8G08ABBCAH4.
Boards are being flashed by mfgtools USB booting the board and then using imx-kobs as FBK command. Flash image is generated with Yocto and signed with CST tool. Bootloader is U-Boot.
The issue is that some of the boards do boot from NAND after successful flash and restart, while others don't. Image and flashing procedure for boards is the same, as are board electrical components and layout. Only difference on boards that we could find so far is CPU lot number written on CPU chip:
Fuses that are programed on boards are SRK Hash, GP10, GP11, and BOOT CFG0 fuses.
Device is not locked for the moment.
ROM Log Events (https://www.nxp.com/docs/en/application-note/AN12853.pdf) for:
0090E558 = E0000000 10000000 22000000 41000000 0090E568 = 50000000 60000000 80000000 0000009C 0090E578 = 81000000 000000D7 90000000 00000200 0090E588 = 91000000 00000105 90000000 00000202 0090E598 = 91000000 000005A9 A0000000 000000F0 0090E5A8 = 000061A4 C0000000 007E1000 00006253
0090E558 = E0000000 10000000 22000000 41000000 0090E568 = 50000000 60000000 80000000 00000072 0090E578 = 81000000 00000099 90000000 00000200 0090E588 = 91000000 000000C7 90000000 00000202 0090E598 = 91000000 0000056A A0000000 FFC01833 0090E5A8 = 000032D6 C0000000 007E1000 00003385
Seems that Image authentication failed with status 0xFFC01833 (from HAB4 API document), output is the same regardless of SRK Hash fuses programed or not:
After failed authentication board still proceeds to boot from NAND since it is not locked but fails and reboots.
Same image does work correctly when used for booting from USB (serial downloader) or SD card (tested using SD Manufacture boot).
imx-kobs output (mtd0 size is 6 MiB):
Start Cmd:FBK: ucmd source /mytmpfs/mtd.sh; cd /tmp; kobs-ng init -x -v --chip_0_device_path=/dev/mtd0 /mytmpfs/boot MTD CONFIG: chip_0_device_path = "/dev/mtd0" chip_1_device_path = "(null)" search_exponent = 2 data_setup_time = 80 data_hold_time = 60 address_setup_time = 25 data_sample_time = 6 row_address_size = 3 column_address_size = 2 read_command_code1 = 0 read_command_code2 = 48 boot_stream_major_version = 1 boot_stream_minor_version = 0 boot_stream_sub_version = 0 ncb_version = 3 boot_stream_1_address = 0 boot_stream_2_address = 0 secondary_boot_stream_off_in_MB = 64 -- We add the 1k-padding to the uboot. .tmp_kobs_ng: verifying using key '00000000000000000000000000000000' .tmp_kobs_ng: is a valid bootstream for key '00000000000000000000000000000000' mtd: use new bch layout raw access mode mtd: opening: "/dev/mtd0" NFC geometry : ECC Strength : 8 Page Size in Bytes : 4210 Metadata size : 10 ECC Chunk Size in byte : 512 ECC Chunk count : 8 Block Mark Byte Offset : 3995 Block Mark Bit Offset : 0 ==================================================== mtd: opened '/dev/mtd0' - '(null)' mtd: max_boot_stream_size_in_bytes = 2097152 mtd: boot_stream_size_in_bytes = 253952 mtd: boot_stream_size_in_pages = 62 mtd: extra_boot_stream_size_in_bytes =253952 mtd: extra_boot_stream_size_in_pages = 62 mtd: #1 0x00200000 - 0x00400000 (0x0023e000) mtd: #2 0x00400000 - 0x00600000 (0x0043e000) FCB m_u32Checksum = 0x00000000 m_u32FingerPrint = 0x20424346 m_u32Version = 0x01000000 m_NANDTiming.m_u8DataSetup = 80 m_NANDTiming.m_u8DataHold = 60 m_NANDTiming.m_u8AddressSetup = 25 m_NANDTiming.m_u8DSAMPLE_TIME = 6 m_u32PageDataSize = 4096 m_u32TotalPageSize = 4320 m_u32SectorsPerBlock = 64 m_u32NumberOfNANDs = 0 m_u32TotalInternalDie = 0 m_u32CellType = 0 m_u32EccBlockNEccType = 4 m_u32EccBlock0Size = 512 m_u32EccBlockNSize = 512 m_u32EccBlock0EccType = 4 m_u32MetadataBytes = 10 m_u32NumEccBlocksPerPage = 7 m_u32EccBlockNEccLevelSDK = 0 m_u32EccBlock0SizeSDK = 0 m_u32EccBlockNSizeSDK = 0 m_u32EccBlock0EccLevelSDK = 0 m_u32NumEccBlocksPerPageSDK = 0 m_u32MetadataBytesSDK = 0 m_u32EraseThreshold = 0 m_u32Firmware1_startingPage = 512 m_u32Firmware2_startingPage = 1024 m_u32PagesInFirmware1 = 62 m_u32PagesInFirmware2 = 62 m_u32DBBTSearchAreaStartAddress = 256 m_u32BadBlockMarkerByte = 3995 m_u32BadBlockMarkerStartBit = 0 m_u32BBMarkerPhysicalOffset = 4096 m_u32BCHType = 0 m_NANDTMTiming.m_u32TMTiming2_ReadLatency = 0 m_NANDTMTiming.m_u32TMTiming2_PreambleDelay = 0 m_NANDTMTiming.m_u32TMTiming2_CEDelay = 0 m_NANDTMTiming.m_u32TMTiming2_PostambleDelay = 0 m_NANDTMTiming.m_u32TMTiming2_CmdAddPause = 0 m_NANDTMTiming.m_u32TMTiming2_DataPause = 0 m_NANDTMTiming.m_u32TMSpeed = 0 m_NANDTMTiming.m_u32TMTiming1_BusyTimeout = 0 m_u32DISBBM = 0 m_u32BBMarkerPhysicalOffsetInSpareData = 0 m_u32OnfiSyncEnable = 0 m_NANDONFITiming.m_u32ONFISpeed = 0 m_NANDONFITiming.m_u32ONFITiming_ReadLatency = 0 m_NANDONFITiming.m_u32ONFITiming_CEDelay = 0 m_NANDONFITiming.m_u32ONFITiming_PreambleDelay = 0 m_NANDONFITiming.m_u32ONFITiming_PostambleDelay = 0 m_NANDONFITiming.m_u32ONFITiming_CmdAddPause = 0 m_NANDONFITiming.m_u32ONFITiming_DataPause = 0 m_NANDONFITiming.m_u32ONFITiming_BusyTimeout = 0 m_u32DISBBSearch = 0 m_u32RandomizerEnable = 0 m_u32ReadRetryEnable = 0 m_u32ReadRetrySeqLength = 0 DBBT m_u32Checksum = 0x00000000 m_u32FingerPrint = 0x54424244 m_u32Version = 0x01000000 m_u32DBBTNumOfPages = 0 Firmware: image #0 @ 0x200000 size 0x3e000 - available 0x200000 Firmware: image #1 @ 0x400000 size 0x3e000 - available 0x200000 Extra Firmware: image #0 @ 0x240000 size 0x3e000 - available 0x1c0000 Firmware: image #1 @ 0x440000 size 0x3e000 - available 0x1c0000 -------------- Start to write the [ FCB ] ----- mtd: erasing @0:0x0-0x40000 mtd: Writing FCB0 [ @0:0x0 ] (10e0) * mtd: erasing @0:0x40000-0x80000 mtd: Writing FCB1 [ @0:0x40000 ] (10e0) * mtd: erasing @0:0x80000-0xc0000 mtd: Writing FCB2 [ @0:0x80000 ] (10e0) * mtd: erasing @0:0xc0000-0x100000 mtd: Writing FCB3 [ @0:0xc0000 ] (10e0) * mtd_commit_bcb(FCB): status 0 -------------- Start to write the [ DBBT ] ----- mtd: erasing @0:0x100000-0x140000 mtd: Writing DBBT0 [ @0:0x100000 ] (1000) * mtd: erasing @0:0x140000-0x180000 mtd: Writing DBBT1 [ @0:0x140000 ] (1000) * mtd: erasing @0:0x180000-0x1c0000 mtd: Writing DBBT2 [ @0:0x180000 ] (1000) * mtd: erasing @0:0x1c0000-0x200000 mtd: Writing DBBT3 [ @0:0x1c0000 ] (1000) * mtd_commit_bcb(DBBT): status 0 ---------- Start to write the [ .tmp_kobs_ng ]---- mtd: Writting .tmp_kobs_ng: #0 @0: 0x00200000 - 0x0023e000 mtd: erasing @0:0x200000-0x240000 mtd: We write one page for save guard. * mtd: Writting .tmp_kobs_ng: #1 @0: 0x00400000 - 0x0043e000 mtd: erasing @0:0x400000-0x440000 mtd: We write one page for save guard. * write the second part of boot stream ---------- Start to write the [ .tmp_kobs_ng ]---- mtd: Writting .tmp_kobs_ng: #0 @0: 0x00240000 - 0x0027e000 mtd: Writting .tmp_kobs_ng: #0 @0: 0x00240000 - 0x0027e000 mtd: erasing @0:0x240000-0x280000 mtd: We write one page for save guard. * mtd: Writting .tmp_kobs_ng: #1 @0: 0x00440000 - 0x0047e000 mtd: Writting .tmp_kobs_ng: #1 @0: 0x00440000 - 0x0047e000 mtd: erasing @0:0x440000-0x480000 mtd: We write one page for save guard. *
Is there some difference in IMX8 lots regarding the NAND boot or we are missing some fuse config?
I've tried in U-Boot console nand torture command for testing NAND and simple RAM mtest and they have both passed. Also tried dumping mtd0 partition that contains boot structures and data and compared between working and non working board, they are the same.
Do note that boards that don't boot from NAND, do work correctly when only SPL is booted from SD (mtd0 wiped clean, boards switch to SD manufacture boot) and then when the SPL loads from SD it fetches rest of the image from NAND.
What I've also tried to be sure that our built imx-boot image is not corrupted is using imx-boot (imx-boot-imx8mmddr4evk-nand.bin-flash_ddr4_evk) from NXPs L5.4.24-2.1.0_images_MX8MMEVK archive.
I suspect that problem when booting from NAND is prior to actually entering SPL and that board never reaches it or initializes RAM (there is no output on console at all) and that maybe SPL image data gets corrupted while being read from NAND and copied to TCML? Is there some way to test that?