I'm pretty sure that this isn't just platform specific, but also depending on the actual firmware vendor.
As another ipq8065 example, I'll try to explain the ZyXEL NBG6817. This particular router has two flash chips, the bootloader is on a 4 MB SPI-NOR, kernel and rootfs (dual-partition) are on an additional 4 GB eMMC - for installing/ updating LEDE the SPI-NOR chip is never touched. The mtd partitionioning is interpreted slightly differently between the OEM ZyXEL firmware and LEDE.
OEM:
m25p80 spi5.0: found mx25u3235f, expected s25fl512s
m25p80 spi5.0: mx25u3235f (4096 Kbytes)
8 cmdlinepart partitions found on MTD device m25p80
Creating 8 MTD partitions on "m25p80":
0x000000000000-0x0000000c0000 : "SBL"
0x0000000c0000-0x000000100000 : "TZ"
0x000000100000-0x000000140000 : "RPM"
0x000000140000-0x0000001c0000 : "u-boot"
0x0000001c0000-0x0000001d0000 : "env"
0x0000001d0000-0x0000001e0000 : "ART"
0x0000001e0000-0x0000001f0000 : "dualflag"
0x0000001f0000-0x000000400000 : "reserved"
LEDE:
spi_qup 1a280000.spi: IN:block:16, fifo:64, OUT:block:16, fifo:64
m25p80 spi32766.0: mx25u3235f (4096 Kbytes)
13 qcom-smem partitions found on MTD device spi32766.0
Creating 13 MTD partitions on "spi32766.0":
0x000000000000-0x000000020000 : "0:SBL1"
0x000000020000-0x000000040000 : "0:MIBIB"
0x000000040000-0x000000060000 : "0:SBL2"
0x000000060000-0x0000000a0000 : "0:SBL3"
0x0000000a0000-0x0000000b0000 : "0:DDRCONFIG"
0x0000000b0000-0x0000000c0000 : "0:SSD"
0x0000000c0000-0x000000100000 : "0:TZ"
0x000000100000-0x000000140000 : "0:RPM"
0x000000140000-0x0000001c0000 : "0:APPSBL"
0x0000001c0000-0x0000001d0000 : "0:APPSBLENV"
0x0000001d0000-0x0000001e0000 : "0:ART"
0x0000001e0000-0x0000001f0000 : "0:DUAL_FLAG"
0x0000001f0000-0x000000400000 : "0:RESERVED"
The eMMC is partitioned like this:
Found valid GPT with protective MBR; using GPT.
Disk mmcblk0: 7471104 sectors, 3.6 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): XXX
Partition table holds up to 12 entries
First usable sector is 34, last usable sector is 7471070
Partitions will be aligned on 2-sector boundaries
Total free space is 1 sectors (512 bytes)
Number Start (sector) End (sector) Size Code Name
1 34 8225 4.0 MiB FFFF rootfs_data
2 8226 16417 4.0 MiB FFFF romd
3 16418 18465 1024.0 KiB FFFF header
4 18466 26657 4.0 MiB FFFF kernel
5 26658 157729 64.0 MiB FFFF rootfs
6 157730 159777 1024.0 KiB FFFF header_1
7 159778 167969 4.0 MiB FFFF kernel_1
8 167970 299041 64.0 MiB FFFF rootfs_1
9 299042 823329 256.0 MiB FFFF bu1
10 823330 7471069 3.2 GiB FFFF bu2
So far LEDE can only be installed to /dev/mmcblk0p4 (kernel) and /dev/mmcblk0p5 (rootfs), the OEM firmware alternates between mmcblk0p4/ mmcblk0p5 and mmcblk0p7/ mmcblk0p8. LEDE never touches mmcblk0p3 (header) or mmcblk0p6 (header_1), the OEM firmware stores the firmware version number "V1.00(ABCS.2)C0" there:
00000000 00 00 a7 74 01 32 f0 00 56 31 2e 30 30 28 41 42 |...t.2..V1.00(AB|
00000010 43 53 2e 32 29 43 30 00 ff ff ff ff ff ff ff ff |CS.2)C0.........|
00000020 ff ff ff ff ff ff ff ff 00 00 d5 dc 4e 42 47 36 |............NBG6|
00000030 38 31 37 00 ff ff ff ff ff ff ff ff ff ff ff ff |817.............|
00000040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
...
fw_printenv (OEM):
addmtd=setenv bootargs ${bootargs} ${mtdparts}
addtty=setenv bootargs ${bootargs} console=ttyHSL1,${baudrate}n8
baudrate=115200
boot_mmc=run setmtdparts flashargs addtty addmtd;mmc read ${loadaddr} ${kernel_paddr} ${kernel_psize};bootm ${loadaddr}
boot_mmc_1=run setmtdparts flashargs_1 addtty addmtd;mmc read ${loadaddr} ${kernel1_paddr} ${kernel1_psize};bootm ${loadaddr}
boot_zld=sf probe&&sf read ${loadaddr} ${zld_paddr} ${zld_psize}&&bootm ${loadaddr}
bootcmd=run boot_mmc
bootcmd_1=run boot_mmc_1
bootdelay=3
bu1_paddr=0x00049022
bu1_psize=0x80000
bu2_paddr=0x000C9022
bu2_psize=0x656FBC
dualflag_paddr=0x1E0000
dualflag_psize=0x10000
eedualflag=sf probe; sf erase ${dualflag_paddr} +${dualflag_psize}
eenv=sf probe; sf erase ${env_paddr} +${env_psize}
eerfdat=sf probe; sf erase ${rfdat_paddr} +${rfdat_psize}
env_paddr=0x1C0000
env_psize=0x10000
eth1addr=0:3:7f:ba:db:2
ethact=eth1
flashargs=setenv bootargs board=NBG6817 root=/dev/mmcblk0p5 rootwait ${bootmode} ${zld_ver}
flashargs_1=setenv bootargs board=NBG6817 root=/dev/mmcblk0p8 rootwait ${bootmode} ${zld_ver}
hdr1_paddr=0x00026822
hdr1_psize=0x800
hdr_paddr=0x00004022
hdr_psize=0x800
hostname=NBG6817
img_prefix=nbg6817-
ipaddr=192.168.1.1
kernel1_paddr=0x00027022
kernel1_psize=0x2000
kernel_paddr=0x00004822
kernel_psize=0x2000
ldr_paddr=0x140000
ldr_psize=0x80000
loadaddr=0x44000000
lu=tftpboot ${loadaddr} ${dir}u-boot.mbn || setenv stdout serial && echo tftpboot download fail && exit 1;sf probe;sf erase ${ldr_paddr} +${ldr_psize} || setenv stdout serial && echo sf erase fail && exit 1;sf write ${fileaddr} ${ldr_paddr} ${filesize}
machid=136d
mtdids=nand1=m25p80
netretry=no
readonly=ro
reserved_paddr=0x1F0000
reserved_psize=0x210000
rfdat_paddr=0x1D0000
rfdat_psize=0x10000
rfs1_paddr=0x00029022
rfs1_psize=0x20000
rfs_paddr=0x00006822
rfs_psize=0x20000
rfsdat_paddr=0x00000022
rfsdat_psize=0x2000
romd_paddr=0x00002022
romd_psize=0x2000
serverip=192.168.1.99
setmtdparts=setenv mtdparts mtdparts=m25p80:0xC0000(SBL)ro,0x40000(TZ)ro,0x40000(RPM)ro,${ldr_psize}(u-boot)${readonly},${env_psize}(env)${readonly},${rfdat_psize}(ART)${readonly},${dualflag_psize}(dualflag),${reserved_psize}(reserved)
stderr=serial
stdin=serial
stdout=serial
uboot_env_ver=1.5
zld_paddr=0x1A4000
zld_psize=0x10000
serialnum=XXX
countrycode=E1
ethaddr=XXX
While it would be possible to change the bootcmd around, like on Linksys mvebu router, the vendor firmware doesn't change those settings - it uses the dualflag/ 0:DUAL_FLAG mtd partition instead. This 64 KB partition is completely initialized with 0xff, to toggle the boot order, only the very first byte of this partition is changed between 0x01 (boot from mmcblk0p7/ mmcblk0p8) or 0xff (boot from mmcblk0p4/ mmcblk0p5).
Boot from mmcblk0p4/ mmcblk0p5:
00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00010000
Boot from mmcblk0p7/ mmcblk0p8:
00000000 01 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00010000
The OEM firmware updater uses echo to toggle this settings, but printf is obviously safer (and works on both):
WARNING, the mtd number differs between ZyXEL OEM firmware (/dev/mtdblock6) and LEDE(/dev/mtdblock11)!
So assuming you're booted into the OEM firmware running from mmcblk0p7/ mmcblk0p8, all you need to do is
printf "\xff" >/dev/mtdblock6
in order to boot from LEDE on mmcblk0p4/ mmcblk0p5, on LEDE booted from there, you can simply reverse this
printf "\x01" >/dev/mtdblock11
and after rebooting you're back to the OEM firmware on mmcblk0p7/ mmcblk0p8.