BPI-R3 SD card image from stable build is corrupt

With the latest stable build for BPI-R3 from https://downloads.openwrt.org/releases/24.10.2/targets/mediatek/filogic/, I cannot boot into production or recovery from the SD card. I cannot flash NAND or NOR from the U-Boot menu.

I used the following process to create the SD card:

> wipefs -a /dev/mmcblk0
/dev/mmcblk0: 8 bytes were erased at offset 0x00000200 (gpt): 45 46 49 20 50 41 52 54
/dev/mmcblk0: 8 bytes were erased at offset 0xedc9ffe00 (gpt): 45 46 49 20 50 41 52 54
/dev/mmcblk0: 2 bytes were erased at offset 0x000001fe (PMBR): 55 aa
/dev/mmcblk0: calling ioctl to re-read partition table: Success
> lsblk
NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
mmcblk0                   179:0    0  59.4G  0 disk
nvme0n1                   259:0    0 953.9G  0 disk
├─nvme0n1p1               259:1    0     1G  0 part /boot/efi
├─nvme0n1p2               259:2    0     2G  0 part /boot
└─nvme0n1p3               259:3    0 950.8G  0 part
  └─ubuntu--vg-ubuntu--lv 252:0    0   100G  0 lvm  /
> gzip -cd openwrt-24.10.2-mediatek-filogic-bananapi_bpi-r3-sdcard.img.gz | dd of=/dev/mmcblk0
154112+1 records in
154112+1 records out
78905348 bytes (79 MB, 75 MiB) copied, 7.89326 s, 10.0 MB/s
> lsblk
NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
mmcblk0                   179:0    0  59.4G  0 disk
├─mmcblk0p1               179:1    0     4M  0 part
├─mmcblk0p2               179:2    0   512K  0 part
├─mmcblk0p3               179:3    0     2M  0 part
├─mmcblk0p4               179:4    0     4M  0 part
├─mmcblk0p5               179:5    0    32M  0 part
├─mmcblk0p6               179:6    0    20M  0 part
└─mmcblk0p7               179:7    0   448M  0 part
nvme0n1                   259:0    0 953.9G  0 disk
├─nvme0n1p1               259:1    0     1G  0 part /boot/efi
├─nvme0n1p2               259:2    0     2G  0 part /boot
└─nvme0n1p3               259:3    0 950.8G  0 part
  └─ubuntu--vg-ubuntu--lv 252:0    0   100G  0 lvm  /

I put all DIP switches up with the plan to flash NAND so that I could flash eMMC. This is the log from booting into the U-Boot menu:

F0: 102B 0000
FA: 1040 0000
FA: 1040 0000 [0200]
F9: 103F 0000
F3: 1001 0000 [0200]
F3: 1001 0000
F6: 300C 0028
F5: 0000 0000
V0: 0000 0000 [0001]
00: 0000 0000
BP: 2400 0041 [0000]
G0: 1190 0000
EC: 0000 0000 [3000]
T0: 0000 01B6 [010F]
Jump to BL

NOTICE:  BL2: v2.10.0   (release):OpenWrt v2024.01.17~bacca82a-3 (mt7986-sdmmc-ddr4)
NOTICE:  BL2: Built : 20:40:36, Jun 23 2025
NOTICE:  WDT: [40000000] Software reset (reboot)
NOTICE:  CPU: MT7986 (2000MHz)
NOTICE:  EMI: Using DDR4 settings
NOTICE:  EMI: Detected DRAM size: 2048MB
NOTICE:  EMI: complex R/W mem test passed
NOTICE:  BL2: Booting BL31
NOTICE:  BL31: v2.10.0  (release):OpenWrt v2024.01.17~bacca82a-3 (mt7986-sdmmc-ddr4)
NOTICE:  BL31: Built : 20:40:36, Jun 23 2025


U-Boot 2024.10-OpenWrt-r28739-d9340319c6 (Jun 23 2025 - 20:40:36 +0000)

CPU:   MediaTek MT7986
Model: BananaPi BPi-R3
DRAM:  2 GiB
Core:  54 devices, 24 uclasses, devicetree: embed
jedec_spi_nor spi_nor@0: unrecognized JEDEC id bytes: ff, ef, aa
MMC:   mmc@11230000: 0
Loading Environment from MMC... *** Warning - bad CRC, using default environment

Reading from MMC(0)... In:    serial@11002000
Out:   serial@11002000
Err:   serial@11002000
Loading Environment from MMC... *** Warning - bad CRC, using default environment

Reading from MMC(0)... Net:
Warning: ethernet@15100000 (eth0) using random MAC address - c2:d5:07:60:e6:dc
eth0: ethernet@15100000
Saving Environment to MMC... Writing to MMC(0)... failed
Failed (1)
Saving Environment to MMC... Writing to MMC(0)... failed
Failed (1)
Button 'reset' not found (err=-16)


        ( ( ( OpenWrt ) ) )  [SD card]       U-Boot 2024.10-OpenWrt-r28739-d9340319c6 (Jun 23 2025 - 20:40:36 +0000)

      1. Run default boot command.
      2. Boot system via TFTP.
      3. Boot production system from SD card.
      4. Boot recovery system from SD card.
      5. Load production system via TFTP then write to SD card.
      6. Load recovery system via TFTP then write to SD card.
      7. Install bootloader, recovery and production to NOR.
      8. Install bootloader, recovery and production to NAND.
      9. Reboot.
      a. Reset all settings to factory defaults.
      0. Exit


  Press UP/DOWN to move, ENTER to select, ESC to quit

There are errors reading the environment in from the SD card due to invalid CRCs in the GPT table.

By pulling the SD card and looking at it from a separate Ubuntu machine, I was able to verify the reported problems with the GPT table.

> parted -s /dev/mmcblk0 print
Error: The backup GPT table is corrupt, but the primary appears OK, so that will be used.
Warning: Not all of the space available to /dev/mmcblk0 appears to be used, you can fix the GPT to use all of the space (an extra 123621343 blocks) or continue with the current setting?
Model: SD SD64G (sd/mmc)
Disk /dev/mmcblk0: 63.8GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name        Flags
 1      17.4kB  4194kB  4177kB               bl2         hidden, legacy_boot
 2      4194kB  4719kB  524kB                ubootenv    hidden
 3      4719kB  6816kB  2097kB               factory     hidden
 4      6816kB  11.0MB  4194kB               fip         boot, hidden, esp
 5      12.6MB  46.1MB  33.6MB               recovery    boot, hidden, esp
 6      46.1MB  67.1MB  21.0MB               install     boot, hidden, esp
 7      67.1MB  537MB   470MB                production

> sgdisk -v /dev/mmcblk0
Caution: invalid backup GPT header, but valid main header; regenerating
backup header from main header.

Warning! One or more CRCs don't match. You should repair the disk!
Main header: OK
Backup header: ERROR
Main partition table: OK
Backup partition table: OK

Invalid partition data!
Verification may miss some problems or report too many!

Problem: The secondary header's self-pointer indicates that it doesn't reside
at the end of the disk. If you've added a disk to a RAID array, use the 'e'
option on the experts' menu to adjust the secondary header's and partition
table's locations.

Warning: There is a gap between the secondary partition table (ending at sector
1048607) and the secondary metadata (sector 1048608).
This is helpful in some exotic configurations, but is generally ill-advised.
Using 'k' on the experts' menu can adjust this gap.

Problem: MBR partitions 1 and 2 overlap!

Identified 2 problems!

I’m not a disk or filesystem expert. On my first attempt to fix the GPT table, I corrupted the disk to where the BL2=>BL31=>U-Boot boot process no longer worked.

I’m planning to try again, but I would appreciate any help.

First to remember: difference from main to backup gpt is normal state,because main gpt is at beginning of disk and written by image. Backup gpt is at the end of disk and old one survives image flashing.

How have you tried to fix the layout?

I did it this way:

sudo sgdisk --backup=bpi-r3_sgdisk.gpt /dev/sdb
sudo sgdisk --load-backup=bpi-r3_sgdisk.gpt /dev/sdb

This worked for me,but r3 sometimes have issues detecting sd card in uboot. Not sure why openwrt cannot write its env,maybe it looks for a partition which not yet exists.

This one is imho a real problem,but maybe caused by your fix…

This error:

Problem: MBR partitions 1 and 2 overlap!

is present for me immediately after copying to the SD card, so it isn’t related to trying to fix the layout. I’m trying to learn more about what the problem is and what it means. LBA0 (logical block) should be a protective MBR (GPT Disk Layout Spec - Protective MBR). That spec is for UEFI. I couldn’t find anything specific to U-Boot, and I’m not sure exactly how U-Boot uses UEFI. Hopefully, it is close enough…

Here is what the protective MBR looks like on the disk immediately after copying to SD card:

> dd if=/dev/mmcblk0 bs=512 count=1 | hexdump -C
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001b0  00 00 00 00 00 00 00 00  4f 57 52 54 00 00 00 00  |........OWRT....|
000001c0  02 00 ee 86 25 41 01 00  00 00 1f 00 10 00 80 00  |....%A..........|
000001d0  23 00 83 82 02 00 22 00  00 00 de 1f 00 00 00 00  |#.....".........|
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|

The first 440 bytes are all zeros is fine because that is the Boot Code and is unused space in the protective MBR spec.

> dd if=/dev/mmcblk0 bs=440 count=1 | hexdump -C 
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

The Unique MBR Disk Signature is set to “OWRT” and the next two bytes are 0x00 per the spec.

> dd if=/dev/mmcblk0 bs=1 skip=440 count=6 | hexdump -C
00000000  4f 57 52 54 00 00                                 |OWRT..|

The next thing in the MBR should be 4 MBR partition records, and one of them should be a “protective” according to the spec and cover the entire disk after the MBR where the GPT layout is written.

> dd if=/dev/mmcblk0 bs=1 skip=446 count=64 | hexdump -C
00000000  00 00 02 00 ee 86 25 41  01 00 00 00 1f 00 10 00  |......%A........|
00000010  80 00 23 00 83 82 02 00  22 00 00 00 de 1f 00 00  |..#.....".......|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

This shows two records, and two records zeroed out.

The first partition record appears to be protective with the BootIndicator set to 0x00 and the StartingCHS set to 0x000200 as dictated by the spec. OSType is set to 0xEE (GPT protective). The EndingCHS (cylinder, head, sector) is set to 0x862541, which I don’t know if that is even meaningful with modern disks. StartingLBA is set to little-endian 0x00000001, which matches the spec. EndingLBA is set to 0x0010001F, which is 65567 in decimal * 512 block size = 33,570,304, or 33.5MB. I’m not sure that is enough to cover the remaining disk, but maybe that doesn’t matter. I could make it longer or set it to 0xFFFFFFFF as allowed by the spec.

The second partition record is problematic. I’m wondering why it is even there. The StartingLBA is 0x00000022 (or 34 * 512 = 17408), which is overlapping and is probably the cause of the error message. The EndingLBA is 0x00001FDE (or 8158 * 512 = 4,176,896). That’s also in the middle of what’s specified in the first MBR partition record. It is marked as bootable (0x80) and the OSType is set to 0x83, or Linux. It also has CHS start and end set, but again, I don’t know if that is used by anything modern, especially not on a flash disk.

The 0x55AA signature for protective MBR is present at the end of the block.

I think I’m going to try just manually removing the second MBR partition record. I’m curious about the CRC warnings in the GPT table itself, but I don’t have time to look at those until later.

I will also try the backup and restore method you suggested.

You could try using parted on the device, perhaps it will fix it.

This is how partition layout is created for my images. Openwrt does it a bit differently,but first partition was imho same (bl2).

@frank-w sgdisk would not create the backup file for me, possibly due to the problems it encountered, so I couldn’t reload it. I tried the interactive mode instead. I decided not to fiddle with the overlapping MBR partition records or the secondary GPT header location.

> gdisk /dev/mmcblk0                                                  
GPT fdisk (gdisk) version 1.0.10                                                                                      
                                                                                                                      
Caution: invalid backup GPT header, but valid main header; regenerating                                               
backup header from main header.                                                                                       
                                                                                                                      
Warning! One or more CRCs don't match. You should repair the disk!                                                    
Main header: OK                                                                                                       
Backup header: ERROR                                                                                                  
Main partition table: OK                                                                                              
Backup partition table: OK                                                                                            
                                                                                                                      
Partition table scan:                                                                                                 
  MBR: hybrid                                                                                                         
  BSD: not present                                                                                                    
  APM: not present                                                                                                    
  GPT: damaged                                                                                                        
                                                                                                                      
Found valid MBR and corrupt GPT. Which do you want to use? (Using the                                                 
GPT MAY permit recovery of GPT data.)                                                                                 
 1 - MBR                                                                                                              
 2 - GPT                                                                                                              
 3 - Create blank GPT                                                                                                 
                                                                                                                      
Your answer: 2                                                                                                        
                                                                                                                      
Command (? for help): w                                                                                               
Warning! Secondary header is placed too early on the disk! Do you want to                                             
correct this problem? (Y/N): n                                                                                        
Have not corrected the problem. Strange problems may occur in the future!                                             
                                                                                                                      
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING                                          
PARTITIONS!!                                                                                                          
                                                                                                                      
Do you want to proceed? (Y/N): y                                                                                      
OK; writing new GUID partition table (GPT) to /dev/mmcblk0.                                                           
                                                                                                                      
Problem: MBR partitions 1 and 2 overlap!                                                                              
Warning! An error was reported when writing the partition table! This error                                           
MIGHT be harmless, or the disk might be damaged! Checking it is advisable.                                            
                                                                                                                      
Command (? for help): q

The CRC errors reported by parted have gone away.

>parted -s /dev/mmcblk0 print
Warning: Not all of the space available to /dev/mmcblk0 appears to be used, you can fix the GPT to use all of the space (an extra 123621343 blocks) or continue with the current setting? 
Model: SD SD64G (sd/mmc)
Disk /dev/mmcblk0: 63.8GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name        Flags
 1      17.4kB  4194kB  4177kB               bl2         hidden, legacy_boot
 2      4194kB  4719kB  524kB                ubootenv    hidden
 3      4719kB  6816kB  2097kB               factory     hidden
 4      6816kB  11.0MB  4194kB               fip         boot, hidden, esp
 5      12.6MB  46.1MB  33.6MB               recovery    boot, hidden, esp
 6      46.1MB  67.1MB  21.0MB               install     boot, hidden, esp
 7      67.1MB  537MB   470MB                production

But, it still has the same CRC errors about the environment when I try to boot.

F0: 102B 0000
FA: 1040 0000
FA: 1040 0000 [0200]
F9: 103F 0000
F3: 1001 0000 [0200]
F3: 1001 0000
F6: 300C 0028
F5: 0000 0000
V0: 0000 0000 [0001]
00: 0000 0000
BP: 2400 0041 [0000]
G0: 1190 0000
EC: 0000 0000 [3000]
T0: 0000 028D [010F]
Jump to BL

NOTICE:  BL2: v2.10.0   (release):OpenWrt v2024.01.17~bacca82a-3 (mt7986-sdmmc-ddr4)
NOTICE:  BL2: Built : 20:40:36, Jun 23 2025
NOTICE:  WDT: Cold boot
NOTICE:  WDT: disabled
NOTICE:  CPU: MT7986 (2000MHz)
NOTICE:  EMI: Using DDR4 settings
NOTICE:  EMI: Detected DRAM size: 2048MB
NOTICE:  EMI: complex R/W mem test passed
NOTICE:  BL2: Booting BL31
NOTICE:  BL31: v2.10.0  (release):OpenWrt v2024.01.17~bacca82a-3 (mt7986-sdmmc-ddr4)
NOTICE:  BL31: Built : 20:40:36, Jun 23 2025


U-Boot 2024.10-OpenWrt-r28739-d9340319c6 (Jun 23 2025 - 20:40:36 +0000)

CPU:   MediaTek MT7986
Model: BananaPi BPi-R3
DRAM:  2 GiB
Core:  54 devices, 24 uclasses, devicetree: embed
jedec_spi_nor spi_nor@0: unrecognized JEDEC id bytes: ff, ef, aa
MMC:   mmc@11230000: 0
Loading Environment from MMC... *** Warning - bad CRC, using default environment

Reading from MMC(0)... In:    serial@11002000
Out:   serial@11002000
Err:   serial@11002000
Loading Environment from MMC... *** Warning - bad CRC, using default environment

Reading from MMC(0)... Net:
Warning: ethernet@15100000 (eth0) using random MAC address - da:1e:ae:f2:1e:40
eth0: ethernet@15100000
Saving Environment to MMC... Writing to MMC(0)... failed
Failed (1)
Saving Environment to MMC... Writing to MMC(0)... failed
Failed (1)
Button 'reset' not found (err=-16)


        ( ( ( OpenWrt ) ) )  [SD card]       U-Boot 2024.10-OpenWrt-r28739-d9340319c6 (Jun 23 2025 - 20:40:36 +0000)

      1. Run default boot command.
      2. Boot system via TFTP.
      3. Boot production system from SD card.
      4. Boot recovery system from SD card.
      5. Load production system via TFTP then write to SD card.
      6. Load recovery system via TFTP then write to SD card.
      7. Install bootloader, recovery and production to NOR.
      8. Install bootloader, recovery and production to NAND.
      9. Reboot.
      a. Reset all settings to factory defaults.
      0. Exit


  Press UP/DOWN to move, ENTER to select, ESC to quit

Are those totally different CRC errors that have something to do with loading the environment itself? I think maybe the default environment doesn’t work with this image and that may be the whole trouble.

This is what I have in my environment:

MT7986> printenv
boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever
boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu
boot_production=led $bootled_pwr on ; run boot_update_conf ; run sdmmc_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off
boot_recovery=led $bootled_rec on ; run boot_update_conf ; run sdmmc_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off
boot_sdmmc=run boot_production ; run boot_recovery
boot_tftp=run boot_update_conf ; tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf
boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done
boot_tftp_production=run boot_update_conf ; tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run sdmmc_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi
boot_tftp_recovery=run boot_update_conf ; tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run sdmmc_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi
boot_update_conf=if nand info ; then setenv bootconf $bootconf_base#$bootconf_sd#$bootconf_nand ; else if sf probe ; then setenv bootconf $bootconf_base#$bootconf_sd#$bootconf_nor ; else setenv bootconf $bootconf_base#$bootconf_sd ; fi ; fi
bootargs=root=/dev/fit0 rootwait
bootcmd=if pstore check ; then run boot_recovery ; else run boot_sdmmc ; fi
bootconf=config-mt7986a-bananapi-bpi-r3
bootconf_base=config-mt7986a-bananapi-bpi-r3
bootconf_emmc=mt7986a-bananapi-bpi-r3-emmc
bootconf_nand=mt7986a-bananapi-bpi-r3-nand
bootconf_nor=mt7986a-bananapi-bpi-r3-nor
bootconf_sd=mt7986a-bananapi-bpi-r3-sd
bootdelay=3
bootfile=openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb
bootfile_upg=openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb
bootled_pwr=green:status
bootled_rec=blue:status
bootmenu_0=Run default boot command.=run boot_default
bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return
bootmenu_2=Boot production system from SD card.=run boot_production ; run bootmenu_confirm_return
bootmenu_3=Boot recovery system from SD card.=run boot_recovery ; run bootmenu_confirm_return
bootmenu_4=Load production system via TFTP then write to SD card.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return
bootmenu_5=Load recovery system via TFTP then write to SD card.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return
bootmenu_6=Install bootloader, recovery and production to NOR.=if sf probe ; then run nor_init ; else echo "NOR not detected" ; fi ; run bootmenu_confirm_return
bootmenu_7=Install bootloader, recovery and production to NAND.=if nand info ; then run ubi_init ; else echo "NAND not detected" ; fi ; run bootmenu_confirm_return
bootmenu_8=Reboot.=reset
bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset
bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60
bootmenu_default=0
bootmenu_delay=3
bootmenu_title=      ( ( ( OpenWrt ) ) )  [SD card]       U-Boot 2024.10-OpenWrt-r28739-d9340319c6 (Jun 23 2025 - 20:40:36 +0000)
console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0
ethaddr=da:1e:ae:f2:1e:40
ipaddr=192.168.1.1
loadaddr=0x46000000
mmc_read_vol=mmc read $loadaddr $part_addr 0x100 && imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc read $loadaddr 0x$part_addr 0x$image_size && setexpr filesize $image_size * 0x200
mmc_write_vol=imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc erase 0x$part_addr 0x$image_size && mmc write $loadaddr 0x$part_addr 0x$image_size
nor_erase_env=mtd erase u-boot-env
nor_init=run nor_init_bl && run nor_init_openwrt
nor_init_bl=run sdmmc_read_nor_bl2 && run nor_write_bl2 && run sdmmc_read_nor_fip && run nor_write_fip && run nor_erase_env
nor_init_openwrt=run sdmmc_read_recovery && iminfo $loadaddr && run nor_write_recovery ; run sdmmc_read_production && iminfo $loadaddr && run nor_write_production
nor_pad_size=imsz $loadaddr image_size ; setexpr image_eb 0x$image_size / 0x10000 ; setexpr tmp1 0x$image_size % 0x10000 ; test 0x$tmp1 -gt 0 && setexpr image_eb 0x$image_eb + 1 ; setexpr image_eb $image_eb * 0x10000
nor_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr
nor_write_fip=mtd erase fip && mtd write fip $loadaddr
nor_write_production=run nor_pad_size ; test 0x$image_eb -le 0x3000000 && mtd erase fit && mtd write fit $loadaddr 0x0 $image_eb
nor_write_recovery=run nor_pad_size ; test 0x$image_eb -le 0x900000 && mtd erase recovery 0x0 0x$image_eb && mtd write recovery $loadaddr 0x0 $image_eb
part_default=production
part_recovery=recovery
reset_factory=eraseenv && reset
sdmmc_read_emmc_install=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x3800 && mmc read $loadaddr $offset 0x4000
sdmmc_read_nor_bl2=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x2800 && mmc read $loadaddr $offset 0x400
sdmmc_read_nor_fip=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x3000 && mmc read $loadaddr $offset 0x1000
sdmmc_read_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_read_vol
sdmmc_read_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_read_vol
sdmmc_read_snand_bl2=part start mmc 0 install part_addr && mmc read $loadaddr $part_addr 0x400
sdmmc_read_snand_fip=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x800 && mmc read $loadaddr $offset 0x1000
sdmmc_write_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_write_vol
sdmmc_write_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_write_vol
serverip=192.168.1.254
snand_write_bl2=mtd erase bl2 0x0 0x100000 && mtd write bl2 $loadaddr 0x0 0x40000 && mtd write bl2 $loadaddr 0x40000 0x40000 && mtd write bl2 $loadaddr 0x80000 0x40000 && mtd write bl2 $loadaddr 0xc0000 0x40000
ubi_format=ubi detach ; mtd erase ubi && ubi part ubi
ubi_init=run ubi_format && run ubi_init_bl && run ubi_init_openwrt && run ubi_init_emmc_install
ubi_init_bl=run sdmmc_read_snand_bl2 && run snand_write_bl2 && run sdmmc_read_snand_fip && run ubi_write_fip
ubi_init_emmc_install=run sdmmc_read_emmc_install && run ubi_write_emmc_install
ubi_init_openwrt=run sdmmc_read_recovery && iminfo $loadaddr && run ubi_write_recovery ; run sdmmc_read_production && iminfo $loadaddr && run ubi_write_production
ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi
ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data
ubi_write_emmc_install=ubi check emmc_install && ubi remove emmc_install ; ubi create emmc_install 0x800000 dynamic ; ubi write $loadaddr emmc_install 0x800000
ubi_write_fip=run ubi_remove_rootfs ; ubi check fip && ubi remove fip ; ubi create fip 0x200000 static ; ubi write $loadaddr fip 0x200000
ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic && ubi write $loadaddr fit $filesize
ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic && ubi write $loadaddr recovery $filesize
ver=U-Boot 2024.10-OpenWrt-r28739-d9340319c6 (Jun 23 2025 - 20:40:36 +0000)

Environment size: 7870/262139 bytes

So, as I look through the commands listed in the boot menu, I should be able to flash to NAND using these commands:

if nand info ; then run ubi_init ; else echo "NAND not detected" ; fi ; run bootmenu_confirm_return

Running the commands independently just to see what’s going on… checking the conditional first:

MT7986> if nand info ; then echo "NAND detected" ; else echo "NAND not detected" ; fi
spi-nand: spi_nand spi_nand@1: Winbond SPI NAND was found.
spi-nand: spi_nand spi_nand@1: 128 MiB, block size: 128 KiB, page size: 2048, OOB size: 64
jedec_spi_nor spi_nor@0: unrecognized JEDEC id bytes: 00, ef, aa
'spi-nand0' is now active device
* spi-nand0
  - device: spi_nand@1
  - parent: spi@1100a000
  - driver: spi_nand
  - type: NAND flash
  - block size:        0x20000 bytes
  - page size:         0x800 bytes
  - OOB size:          64 bytes
  - OOB available:     24 bytes
  - 0x000000000000-0x000008000000 : "spi-nand0"
          - 0x000000000000-0x000000200000 : "bl2"
          - 0x000000200000-0x000008000000 : "ubi"
NAND detected

And then, the ubi_init command is going to runn all of the following:

run ubi_format && run ubi_init_bl && run ubi_init_openwrt && run ubi_init_emmc_install

So, I’ll run each of those one at a time:

MT7986> run ubi_format
jedec_spi_nor spi_nor@0: unrecognized JEDEC id bytes: ff, ef, aa
Erasing 0x00000000 ... 0x07dfffff (1008 eraseblock(s))
jedec_spi_nor spi_nor@0: unrecognized JEDEC id bytes: 00, ef, aa
ubi0: default fastmap pool size: 50
ubi0: default fastmap WL pool size: 25
ubi0: attaching mtd2
ubi0: scanning is finished
ubi0: empty MTD device detected
ubi0: attached mtd2 (name "ubi", size 126 MiB)
ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096
ubi0: good PEBs: 1008, bad PEBs: 0, corrupted PEBs: 0
ubi0: user volume: 0, internal volumes: 1, max. volumes count: 128
ubi0: max/mean erase counter: 0/0, WL threshold: 4096, image sequence number: 0
ubi0: available PEBs: 982, total reserved PEBs: 26, PEBs reserved for bad PEB handling: 20

But, run ubi_init_bl returned nothing…

MT7986> run ubi_init_bl

Drilling down one level and the read command fails with no output, so getting the exact values for that command:

MT7986> run sdmmc_read_snand_bl2
MT7986> echo "$sdmmc_read_snand_bl2"
part start mmc 0 install part_addr && mmc read $loadaddr $part_addr 0x400

Then, running that command, which according to the help should load the part_addr variable with the location (in blocks) of the start of the install partition, but that isn’t working.

MT7986> part start mmc 0 install part_addr
MT7986> echo "$part_addr"

MT7986>

And, then we are back to the original problem reported on other threads about the latest SD cards.

MT7986> part list mmc 0
## Unknown partition table type 0
MT7986> mmc part
## Unknown partition table type 0

Ah you mean this message…The environment crc can be ignored as you have not stored environment to mmc via saveenv so this space is empty…you see builtin environment.

I do not know all commands,but maybe you have to select mmc first with mmc dev 0.afaik openwrt stores the nand_bl2 in the sdcard image and this seems to be the part_addr(later fip with offset) which seems missing.

@dangowrt can you help here?

@frank-w I’m finally able to get back to this.

Writing code helps me understand things, so I wrote this gpt-reader utility based on the GPT spec: https://gist.github.com/petrsnd/856288765c6eef9f03979b98885e4c51

When I run that on the SD card image, you can see some of the problems…

  • You can see that the protective MBR [0] doesn’t actually cover the entire disk image:

    53,688,6784 bytes < 78,905,348

  • You can see the overlapping MBR record [1] (that also happens to point to BL2, is that to try to boot legacy??)

  • It is interesting that the secondary GPT supposedly starts on the LBA right after the protective MBR record ends. Spoiler: it isn’t actually there.

  • The GPT header says there are 128 partitions in the array, but there are only 7. The rest of them are all zeros. Maybe this is because space for a minimum of 128 partitions has to be allocated??

  • You can see a small gap between fip and recovery – I don’t think that’s a problem.

  • The CRC of the header matches if you include all the zeroed entries, but if you calculate the CRC for only the populated entries, it doesn’t match.

> ./gpt-reader -f openwrt-24.10.2-mediatek-filogic-bananapi_bpi-r3-sdcard.img
Read in the protective MBR and look for issues...

Protective MBR
--------------
[0] Protective MBR, start: 1 (offset 0x200), size: 1048607 (536886784 bytes)
[1] Standard MBR, start: 34 (offset 0x4400), size: 8158 (4176896 bytes)
[2] Standard MBR, start: 0 (offset 0x0), size: 0 (0 bytes)
[3] Standard MBR, start: 0 (offset 0x0), size: 0 (0 bytes)

Read in the primary GPT header and look for issues...

GPT Header
----------
GPT LBA: 1
GPT secondary LBA: 1048608
Partition entries start LBA: 2
First usable LBA: 34
Last usable LBA: 1048575
Number of partition entries: 128
Size of each partition entry: 128
Partition entry array CRC: 0x2101666490

Partitions -- start/end: LBA (byte offset)
------------------------------------------
[0] bl2 -- start: 34 (0x4400), end: 8191 (0x3ffe00)
[1] ubootenv -- start: 8192 (0x400000), end: 9215 (0x47fe00)
[2] factory -- start: 9216 (0x480000), end: 13311 (0x67fe00)
[3] fip -- start: 13312 (0x680000), end: 21503 (0xa7fe00)
[4] recovery -- start: 24576 (0xc00000), end: 90111 (0x2bffe00)
[5] install -- start: 90112 (0x2c00000), end: 131071 (0x3fffe00)
[6] production -- start: 131072 (0x4000000), end: 1048575 (0x1ffffe00)

121 blank GPT entries

GPT header partition array CRC: 0x7d44e2ba
Calculated CRC of all entries: 0x7d44e2ba
Calculated CRC of only populated entries: 0x5e4cfaba

Read in the secondary GPT header and look for issues...
GPT header not found or invalid!

I was able to find the secondary GPT, but it isn’t where it is supposed to be:

> dd if=openwrt-24.10.2-mediatek-filogic-bananapi_bpi-r3-sdcard.img bs=512 | hexdump -C | grep "45 46 49 20 50 41 52 54  00 00 01 00"
00000200  45 46 49 20 50 41 52 54  00 00 01 00 5c 00 00 00  |EFI PART....\...|
03800200  45 46 49 20 50 41 52 54  00 00 01 00 5c 00 00 00  |EFI PART....\...|

The actual location is:

0x03800200 = 58,720,768 bytes / 512 blocksize = LBA: 114689

And, it is definitely there, followed by all the GPT partition entries:

dd if=/openwrt-24.10.2-mediatek-filogic-bananapi_bpi-r3-sdcard.img bs=512 skip=114689 count=8 | hexdump -C
8+0 records in
8+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 6.2776e-05 s, 65.2 MB/s
00000000  45 46 49 20 50 41 52 54  00 00 01 00 5c 00 00 00  |EFI PART....\...|
00000010  49 77 e5 32 00 00 00 00  01 00 00 00 00 00 00 00  |Iw.2............|
00000020  20 00 10 00 00 00 00 00  22 00 00 00 00 00 00 00  | .......".......|
00000030  ff ff 0f 00 00 00 00 00  4f 57 52 54 11 22 33 44  |........OWRT."3D|
00000040  55 66 77 88 99 aa bb 00  02 00 00 00 00 00 00 00  |Ufw.............|
00000050  80 00 00 00 80 00 00 00  03 74 ee c9 00 00 00 00  |.........t......|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  af 3d c6 0f 83 84 72 47  8e 79 3d 69 d8 47 7d e4  |.=....rG.y=i.G}.|
00000210  4f 57 52 54 11 22 33 44  55 66 77 88 99 aa bb 01  |OWRT."3DUfw.....|
00000220  00 20 00 00 00 00 00 00  ff 23 00 00 00 00 00 00  |. .......#......|
00000230  05 00 00 00 00 00 00 00  75 00 62 00 6f 00 6f 00  |........u.b.o.o.|
00000240  74 00 65 00 6e 00 76 00  00 00 00 00 00 00 00 00  |t.e.n.v.........|
00000250  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000280  af 3d c6 0f 83 84 72 47  8e 79 3d 69 d8 47 7d e4  |.=....rG.y=i.G}.|
00000290  4f 57 52 54 11 22 33 44  55 66 77 88 99 aa bb 02  |OWRT."3DUfw.....|
000002a0  00 24 00 00 00 00 00 00  ff 33 00 00 00 00 00 00  |.$.......3......|
000002b0  01 00 00 00 00 00 00 00  66 00 61 00 63 00 74 00  |........f.a.c.t.|
000002c0  6f 00 72 00 79 00 00 00  00 00 00 00 00 00 00 00  |o.r.y...........|
000002d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000300  28 73 2a c1 1f f8 d2 11  ba 4b 00 a0 c9 3e c9 3b  |(s*......K...>.;|
00000310  4f 57 52 54 11 22 33 44  55 66 77 88 99 aa bb 03  |OWRT."3DUfw.....|
00000320  00 34 00 00 00 00 00 00  ff 53 00 00 00 00 00 00  |.4.......S......|
00000330  01 00 00 00 00 00 00 00  66 00 69 00 70 00 00 00  |........f.i.p...|
00000340  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000380  28 73 2a c1 1f f8 d2 11  ba 4b 00 a0 c9 3e c9 3b  |(s*......K...>.;|
00000390  4f 57 52 54 11 22 33 44  55 66 77 88 99 aa bb 04  |OWRT."3DUfw.....|
000003a0  00 60 00 00 00 00 00 00  ff 5f 01 00 00 00 00 00  |.`......._......|
000003b0  01 00 00 00 00 00 00 00  72 00 65 00 63 00 6f 00  |........r.e.c.o.|
000003c0  76 00 65 00 72 00 79 00  00 00 00 00 00 00 00 00  |v.e.r.y.........|
000003d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400  83 be e9 ca 5f b1 cc 49  86 3f 08 1b 74 4a 2d 93  |...._..I.?..tJ-.|
00000410  4f 57 52 54 11 22 33 44  55 66 77 88 99 aa bb 05  |OWRT."3DUfw.....|
00000420  00 00 02 00 00 00 00 00  ff ff 0f 00 00 00 00 00  |................|
00000430  00 00 00 00 00 00 00 00  70 00 72 00 6f 00 64 00  |........p.r.o.d.|
00000440  75 00 63 00 74 00 69 00  6f 00 6e 00 00 00 00 00  |u.c.t.i.o.n.....|
00000450  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000

There is a spot in my code to plug that in as a magic number, and rerunning it you can see some differences between the two CRC values:

> ./gpt-reader -f openwrt-24.10.2-mediatek-filogic-bananapi_bpi-r3-sdcard.img
Read in the protective MBR and look for issues...

Protective MBR
--------------
[0] Protective MBR, start: 1 (offset 0x200), size: 1048607 (536886784 bytes)
[1] Standard MBR, start: 34 (offset 0x4400), size: 8158 (4176896 bytes)
[2] Standard MBR, start: 0 (offset 0x0), size: 0 (0 bytes)
[3] Standard MBR, start: 0 (offset 0x0), size: 0 (0 bytes)

Read in the primary GPT header and look for issues...

GPT Header
----------
GPT LBA: 1
GPT secondary LBA: 1048608
Partition entries start LBA: 2
First usable LBA: 34
Last usable LBA: 1048575
Number of partition entries: 128
Size of each partition entry: 128
Partition entry array CRC: 0x2101666490

Partitions -- start/end: LBA (byte offset)
------------------------------------------
[0] bl2 -- start: 34 (0x4400), end: 8191 (0x3ffe00)
[1] ubootenv -- start: 8192 (0x400000), end: 9215 (0x47fe00)
[2] factory -- start: 9216 (0x480000), end: 13311 (0x67fe00)
[3] fip -- start: 13312 (0x680000), end: 21503 (0xa7fe00)
[4] recovery -- start: 24576 (0xc00000), end: 90111 (0x2bffe00)
[5] install -- start: 90112 (0x2c00000), end: 131071 (0x3fffe00)
[6] production -- start: 131072 (0x4000000), end: 1048575 (0x1ffffe00)

121 blank GPT entries

GPT header partition array CRC: 0x7d44e2ba
Calculated CRC of all entries: 0x7d44e2ba
Calculated CRC of only populated entries: 0x5e4cfaba

Read in the secondary GPT header and look for issues...

GPT Header
----------
GPT LBA: 1
GPT secondary LBA: 1048608
Partition entries start LBA: 2
First usable LBA: 34
Last usable LBA: 1048575
Number of partition entries: 128
Size of each partition entry: 128
Partition entry array CRC: 0x3387847683

Partitions -- start/end: LBA (byte offset)
------------------------------------------
[0] bl2 -- start: 34 (0x4400), end: 8191 (0x3ffe00)
[1] ubootenv -- start: 8192 (0x400000), end: 9215 (0x47fe00)
[2] factory -- start: 9216 (0x480000), end: 13311 (0x67fe00)
[3] fip -- start: 13312 (0x680000), end: 21503 (0xa7fe00)
[4] recovery -- start: 24576 (0xc00000), end: 90111 (0x2bffe00)
[5] install -- start: 90112 (0x2c00000), end: 131071 (0x3fffe00)
[6] production -- start: 131072 (0x4000000), end: 1048575 (0x1ffffe00)

121 blank GPT entries

GPT header partition array CRC: 0xc9ee7403
Calculated CRC of all entries: 0x7d44e2ba
Calculated CRC of only populated entries: 0x5e4cfaba

GPT headers do not match!

There are like 20MiB of stuff at the end of this disk after the secondary GPT. I didn’t try to figure out what it was. I’m not sure how this SD card image was built, but it was definitely shuffled around and messed with after it was laid out.

The disk that was “corrected” by sgdisk doesn’t boot to the u-boot menu anymore. Maybe that is because it tries to relocate the secondary GPT and fix a bunch of other things that probably aren’t necessary. I could try to fix up the CRCs and GPT pointers manually with a hex editor based on what I’ve learned, but I think it would be easier to just build a new image. I’ll see if I can figure that out based on the script that you posted earlier.

Wow,you are much more deeper in that than me :slight_smile:

I have not found the scripts/definition in openwrt source to check how they create the image. But basicly the secondary gpt is always on wrong position as end of image is not end of disk.same for size of protective mbr (no idea how to fix this without low level hex editing if not done by my sgdisk command).

Edit: found gpt creation in openwrt sourcecode:

@frank-w

It looks like ptgen is a custom tool included with openwrt source code:

ptgen definitely includes code for writing the extra legacy boot MBR record.

I wrote a script to set up an SD card from scratch with basic Linux commands with exactly the contents from the OpenWRT SD card image but with a perfectly formatted GPT and no weird overlapping MBR. Now, sgdisk reports no problems with the SD card.

I load it back into the BPI-R3, and it boots just fine into the OpenWRT boot menu just like the supplied image did, but U-Boot still can’t read information from the MMC interface. :frowning:

Either U-Boot has a problem reading GPT from MMC (SD Card), which I am doubtful about, or the image has a problem, but I can’t get this working… There are no errors on this SD card, yet I still get:

MT7986> mmc info
Device: mmc@11230000
Manufacturer ID: 3
OEM: 5344
Name: SD64G
Bus Speed: 50000000
Mode: SD High Speed (50MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 59.4 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
MT7986> part list mmc 0
## Unknown partition table type 0
MT7986> mmc part
## Unknown partition table type 0

If U-Boot can’t read the MMC (SD Card) then there is no way for it to install to other memory devices and there is no way for it to boot. This is feeling like a bug, but it doesn’t seem like anyone is interested in solving it…

I suppose I can get everything set up to boot a running system from TFTP, which I think I did a few months ago. Then, maybe I can flash NAND from inside a running OpenWRT or another Linux, but I feel like I would need to decipher what these boot menu commands are doing in order to flash it correctly manually. I’m new to this OpenWRT layout thing…

The reason I think of using TFTP is because I can’t get U-Boot to load ANYTHING from MMC (SD Card), so even if I built an image based on the format you sent me, I don’t think U-Boot can load partition data from the disk to boot OpenWRT.

I bought this BPI-R3 to be an OpenWRT router, and I have been able to get it working with a support OpenWRT SD Card image. Either, those images should be taken down or they should be made to work.

This is very frustrating… Who else can help with this issue?

Also, where is the default environment stored when I don’t load it from the saved ubootenv partition? Because, the commands from that environment are expected to work with the SD Card setup. Is it just embedded in the fip?

I also got the gpt reading issue on mt7986 sdmmc,but it only was sometimes and not reproducable. I reported to mtk,but without a way to reproduce it is nearly impossible to fix. After a powercycle mostly it worked again.

If you have this always you can try reducing speed on sdmmc as i had similar issue on r4pro…i guess some kind of electrical interference on sdmmc traces.

And yes ptgen is a openwrt tool,but the most important parts are the params…but i agree that we do not see how protectice mbr is done

Try another type and/or brand sd card. U-Boot has trouble with some cards, others are no problem at all. Even when ATF and linux have no trouble at all with the card, it may not function in U-Boot. I had that with some cards on R64, since then I always get SanDisk

Always follow this command with the sync command, to make sure everything is written. There is also an option for dd that does the same.