From d9fb91881ce645255bc49227d5b8430348d48569 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=91=E7=8C=AB?= <133520@live.cn>
Date: Thu, 11 May 2023 15:47:08 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ipq6018/config.xml | 160 +++++
ipq6018/flash_partition/nand-4k-partition.xml | 220 ++++++
.../nand-audio-4k-partition.xml | 210 ++++++
.../flash_partition/nand-audio-partition.xml | 210 ++++++
ipq6018/flash_partition/nand-partition.xml | 158 +++++
.../flash_partition/nand-partition.xml.bak | 220 ++++++
ipq6018/in/partition_tool | Bin 0 -> 30601 bytes
prepareSingleImage.py | 368 ++++++++++
scripts/gen_flash_partition_bin.py | 668 ++++++++++++++++++
scripts/nand_mbn_generator.py | 178 +++++
命令.txt | 1 +
说明.txt | 3 +
12 files changed, 2396 insertions(+)
create mode 100644 ipq6018/config.xml
create mode 100644 ipq6018/flash_partition/nand-4k-partition.xml
create mode 100644 ipq6018/flash_partition/nand-audio-4k-partition.xml
create mode 100644 ipq6018/flash_partition/nand-audio-partition.xml
create mode 100644 ipq6018/flash_partition/nand-partition.xml
create mode 100644 ipq6018/flash_partition/nand-partition.xml.bak
create mode 100644 ipq6018/in/partition_tool
create mode 100644 prepareSingleImage.py
create mode 100644 scripts/gen_flash_partition_bin.py
create mode 100644 scripts/nand_mbn_generator.py
create mode 100644 命令.txt
create mode 100644 说明.txt
diff --git a/ipq6018/config.xml b/ipq6018/config.xml
new file mode 100644
index 0000000..b03fe67
--- /dev/null
+++ b/ipq6018/config.xml
@@ -0,0 +1,160 @@
+
+
+
+
+
+ ipq6018
+
+
+
+ 256
+ 256
+ 256
+
+
+
+
+ 2048
+ 64
+ 4096
+
+
+ 2048
+ 64
+ 4096
+
+
+ 4096
+ 64
+ 4096
+
+
+ 4096
+ 64
+ 4096
+
+
+
+
+
+ 7634944
+ gpt_main0.bin
+ gpt_backup0.bin
+
+
+
+ 256
+ 256
+ 256
+
+
+
+ 256
+ 512
+ 256
+ 256
+ gpt_main1.bin
+ gpt_backup1.bin
+
+
+
+
+ 0x8030000
+ AP-CP01-C1
+ false
+ 256M32_DDR3
+
+
+ 0x8030001
+ AP-CP01-C2
+ false
+ 256M32_DDR3
+
+
+ 0x8030002
+ AP-CP01-C3
+ false
+ 256M32_DDR3
+
+
+ 0x8030003
+ AP-CP01-C4
+ false
+ 256M32_DDR3
+ true
+
+
+ 0x8030100
+ AP-CP02-C1
+ false
+ 256M32_DDR4
+
+
+ 0x8030200
+ AP-CP03-C1
+ false
+ 256M16_DDR3
+
+
+ 0x1030000
+ DB-CP01
+ false
+ 256M32_DDR3
+
+
+ 0x1030100
+ DB-CP02
+ false
+ 1024M32_DDR4
+
+
+ 0xF030000
+ CP-EMU
+ false
+ 256M32_DDR3
+
+
+
+
+
+ /boot_images/build/ms/bin/8074/nor/sbl1_nor.mbn
+ /boot_images/build/ms/bin/8074/nand/sbl1_nand.mbn
+ /boot_images/build/ms/bin/8074/emmc/sbl1_emmc.mbn
+ /boot_images/build/ms/bin/8074/flashless/sbl1_flashless.mbn
+ /boot_images/core/bsp/tools/flash/partition_tool_exe/build/partition_tool
+ /boot_images/core/bsp/tools/flash/bootconfig_exe/build/bootconfig_tool
+
+
+ /trustzone_images/build/ms/bin/SANAANAA/tz.mbn
+ /trustzone_images/build/ms/bin/SANAANAA/devcfg_noac.mbn
+ /trustzone_images/build/ms/bin/SANAANAA/devcfg_nosmmu.mbn
+
+
+ /apss_proc/out/ipq807x/openwrt-ipq807x-u-boot.elf
+ /apss_proc/out/ipq807x/openwrt-ipq-ipq807x-squashfs-root.img
+ /apss_proc/out/ipq807x/openwrt-ipq-ipq807x-qcom-ipq807x-hkxx-fit-uImage.itb
+ /apss_proc/out/ipq807x/openwrt-ipq-ipq807x-ubi-root.img
+ /apss_proc/out/pack.py
+
+
+ /apss_proc/out/ipq807x/openwrt-ipq807x-u-boot.elf
+ /apss_proc/out/ipq807x_64/openwrt-ipq-ipq807x_64-squashfs-root.img
+ /apss_proc/out/ipq807x_64/openwrt-ipq-ipq807x_64-qcom-ipq807x-hkxx-fit-uImage.itb
+ /apss_proc/out/ipq807x_64/openwrt-ipq-ipq807x_64-ubi-root.img
+ /apss_proc/out/pack.py
+
+
+ /rpm_proc/build/ms/bin/8074/rpm.mbn
+
+
+ /wlan_proc/build/ms/bin/wifi_fw_squashfs.img
+ /wlan_proc/build/ms/bin/wifi_fw_ubi.img
+
+
+
diff --git a/ipq6018/flash_partition/nand-4k-partition.xml b/ipq6018/flash_partition/nand-4k-partition.xml
new file mode 100644
index 0000000..3d20fc4
--- /dev/null
+++ b/ipq6018/flash_partition/nand-4k-partition.xml
@@ -0,0 +1,220 @@
+
+
+
+
+
+ 0xAA7D1B9A
+ 0x1F7D48BC
+
+ 0x4
+
+
+ 0:SBL1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ xbl_nand.elf
+
+
+ 0:MIBIB
+ 512
+ 512
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ nand-system-partition-ipq6018-m4096-p256KiB.bin
+
+
+ 0:BOOTCONFIG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig.bin
+
+
+ 0:BOOTCONFIG1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig.bin
+
+
+ 0:QSEE
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ tz.mbn
+
+
+ 0:QSEE_1
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:DEVCFG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ devcfg.mbn
+
+
+ 0:DEVCFG_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:RPM
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ rpm.mbn
+
+
+ 0:RPM_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:CDT
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ cdt.bin
+
+
+ 0:CDT_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBLENV
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBL
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq6018-u-boot.mbn
+
+
+ 0:APPSBL_1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:ART
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ rootfs
+ 85504
+ 1024
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq-ipq60xx-ubi-root-m4096-p256KiB.img
+ openwrt-ipq-ipq60xx_64-ubi-root-m4096-p256KiB.img
+
+
+ rootfs_1
+ 85504
+ 1024
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:ETHPHYFW
+ 2048
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+
+
diff --git a/ipq6018/flash_partition/nand-audio-4k-partition.xml b/ipq6018/flash_partition/nand-audio-4k-partition.xml
new file mode 100644
index 0000000..8fea8ba
--- /dev/null
+++ b/ipq6018/flash_partition/nand-audio-4k-partition.xml
@@ -0,0 +1,210 @@
+
+
+
+
+
+ 0xAA7D1B9A
+ 0x1F7D48BC
+
+ 0x4
+
+
+ 0:SBL1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ xbl_nand.elf
+
+
+ 0:MIBIB
+ 512
+ 512
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ nand-audio-system-partition-ipq6018-m4096-p256KiB.bin
+
+
+ 0:BOOTCONFIG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig-audio.bin
+
+
+ 0:BOOTCONFIG1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig-audio.bin
+
+
+ 0:QSEE
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ tz.mbn
+
+
+ 0:QSEE_1
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:DEVCFG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ devcfg_noac.mbn
+
+
+ 0:DEVCFG_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:RPM
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ rpm.mbn
+
+
+ 0:RPM_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:CDT
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ cdt.bin
+
+
+ 0:CDT_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBLENV
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBL
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq6018-u-boot.mbn
+
+
+ 0:APPSBL_1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:ART
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ rootfs
+ 197120
+ 1024
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq-ipq60xx-ubi-root-m4096-p256KiB.img
+ openwrt-ipq-ipq60xx_64-ubi-root-m4096-p256KiB.img
+
+
+ 0:ETHPHYFW
+ 2048
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+
+
diff --git a/ipq6018/flash_partition/nand-audio-partition.xml b/ipq6018/flash_partition/nand-audio-partition.xml
new file mode 100644
index 0000000..adb44b0
--- /dev/null
+++ b/ipq6018/flash_partition/nand-audio-partition.xml
@@ -0,0 +1,210 @@
+
+
+
+
+
+ 0xAA7D1B9A
+ 0x1F7D48BC
+
+ 0x4
+
+
+ 0:SBL1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ xbl_nand.elf
+
+
+ 0:MIBIB
+ 512
+ 512
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ nand-audio-system-partition-ipq6018-m2048-p128KiB.bin
+
+
+ 0:BOOTCONFIG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig-audio.bin
+
+
+ 0:BOOTCONFIG1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig-audio.bin
+
+
+ 0:QSEE
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ tz.mbn
+
+
+ 0:QSEE_1
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:DEVCFG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ devcfg_noac.mbn
+
+
+ 0:DEVCFG_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:RPM
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ rpm.mbn
+
+
+ 0:RPM_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:CDT
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ cdt.bin
+
+
+ 0:CDT_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBLENV
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBL
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq6018-u-boot.mbn
+
+
+ 0:APPSBL_1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:ART
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ rootfs
+ 108544
+ 1024
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq-ipq60xx-ubi-root.img
+ openwrt-ipq-ipq60xx_64-ubi-root.img
+
+
+ 0:ETHPHYFW
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+
+
diff --git a/ipq6018/flash_partition/nand-partition.xml b/ipq6018/flash_partition/nand-partition.xml
new file mode 100644
index 0000000..5497e1c
--- /dev/null
+++ b/ipq6018/flash_partition/nand-partition.xml
@@ -0,0 +1,158 @@
+
+
+
+
+
+ 0xAA7D1B9A
+ 0x1F7D48BC
+
+ 0x4
+
+
+ 0:SBL1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ xbl_nand.elf
+
+
+ 0:MIBIB
+ 512
+ 512
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ nand-system-partition-ipq6018.bin
+
+
+ 0:QSEE
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ tz.mbn
+
+
+ 0:DEVCFG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ devcfg.mbn
+
+
+ 0:RPM
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ rpm.mbn
+
+
+ 0:CDT
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ cdt.bin
+
+
+ 0:APPSBLENV
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBL
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq6018-u-boot.mbn
+
+
+ 0:ART
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ bdata
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ crash
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ crash_syslog
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ rootfs
+ 113664
+ 1024
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq-ipq60xx-ubi-root.img
+ openwrt-ipq-ipq60xx_64-ubi-root.img
+
+
+
+
diff --git a/ipq6018/flash_partition/nand-partition.xml.bak b/ipq6018/flash_partition/nand-partition.xml.bak
new file mode 100644
index 0000000..805987d
--- /dev/null
+++ b/ipq6018/flash_partition/nand-partition.xml.bak
@@ -0,0 +1,220 @@
+
+
+
+
+
+ 0xAA7D1B9A
+ 0x1F7D48BC
+
+ 0x4
+
+
+ 0:SBL1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ xbl_nand.elf
+
+
+ 0:MIBIB
+ 512
+ 512
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ nand-system-partition-ipq6018.bin
+
+
+ 0:BOOTCONFIG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig.bin
+
+
+ 0:BOOTCONFIG1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ bootconfig.bin
+
+
+ 0:QSEE
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ tz.mbn
+
+
+ 0:QSEE_1
+ 1792
+ 1792
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:DEVCFG
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ devcfg.mbn
+
+
+ 0:DEVCFG_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:RPM
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ rpm.mbn
+
+
+ 0:RPM_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:CDT
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ cdt.bin
+
+
+ 0:CDT_1
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBLENV
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:APPSBL
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq6018-u-boot.mbn
+
+
+ 0:APPSBL_1
+ 768
+ 768
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:ART
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ rootfs
+ 53760
+ 1024
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+ openwrt-ipq-ipq60xx-ubi-root.img
+ openwrt-ipq-ipq60xx_64-ubi-root.img
+
+
+ rootfs_1
+ 53760
+ 1024
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+ 0:ETHPHYFW
+ 256
+ 256
+ 0
+ 0xFF
+ 0xFF
+ 0x00
+ 0xFF
+
+
+
+
diff --git a/ipq6018/in/partition_tool b/ipq6018/in/partition_tool
new file mode 100644
index 0000000000000000000000000000000000000000..df46f67011dc48f51f0732afb4df268e9e0f6ceb
GIT binary patch
literal 30601
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 \n"
+
+ print "--arch \t\tArch(e.g ipq40xx/ipq807x/ipq807x_64/ipq6018/ipq6018_64/ipq5018/ipq5018_64/ipq9048/ipq9048_64)\n"
+ print " \t\te.g python prepareSingleImage.py --arch ipq807x\n\n"
+
+ print "--fltype \tFlash Type (nor/nand/emmc/norplusnand/norplusemmc)"
+ print " \t\tMultiple flashtypes can be passed by a comma separated string"
+ print " \t\tDefault is all. i.e If \"--fltype\" is not passed image for all the flash-type will be created.\n"
+ print " \t\te.g python prepareSingleImage.py --fltype nor,nand,norplusnand\n\n"
+
+ print "--in \t\tGenerated binaries and images needed for singleimage will be copied to this location"
+ print "\t\tDefault path: .//in/\n"
+ print "\t\te.g python prepareSingleImage.py --gencdt --in ./\n\n"
+
+ print "--bootimg \tBoot image path"
+ print "\t\tIf specified the boot images available at will be copied to the directory provided with \"--in\"\n"
+ print "\t\te.g python prepareSingleImage.py --bootimg \n\n"
+
+ print "--tzimg \tTZ image path"
+ print "\t\tIf specified the TZ images available at will be copied to the directory provided with \"--in\"\n"
+ print "\t\te.g python prepareSingleImage.py --tzimg \n\n"
+
+ print "--nhssimg \tNHSS image path"
+ print "\t\tIf specified the NHSS images available at will be copied to the directory provided with \"--in\"\n"
+ print "\t\te.g python prepareSingleImage.py --nhssimg \n\n"
+
+ print "--rpmimg \tRPM image path"
+ print "\t\tIf specified the RPM images available at will be copied to the directory provided with \"--in\"\n"
+ print "\t\te.g python prepareSingleImage.py --rpmimg \n\n"
+
+ print "--gencdt \tWhether CDT binaries to be generated"
+ print "\t\tIf not specified CDT binary will not be generated"
+ print "\t\tThis Argument does not take any value\n"
+ print "\t\te.g python prepareSingleImage.py --gencdt\n\n"
+
+ print "--memory \tWhether to use Low Memory Profiles for cdt binaries to be generated"
+ print "\t\tThis option depends on '--gencdt'\n"
+ print "\t\tIf specified the is taken as memory size in generating cdt binaries\n"
+ print "\t\te.g python prepareSingleImage.py --gencdt --memory \n\n"
+
+ print "--genpart \tWhether flash partition table(s) to be generated"
+ print "\t\tIf not specified partition table(s) will not be generated"
+ print "\t\tThis Argument does not take any value\n"
+ print "\t\te.g python prepareSingleImage.py --genpart\n\n"
+
+ print "--genbootconf \tWhether bootconfig binaries to be generated"
+ print "\t\tIf not specified bootconfig binaries will not be generated"
+ print "\t\tThis Argument does not take any value\n"
+ print "\t\te.g python prepareSingleImage.py --genbootconf\n\n"
+
+ print "--genmbn \tWhether u-boot.elf to be converted to u-boot.mbn"
+ print "\t\tIf not specified u-boot.mbn will not be generated"
+ print "\t\tThis is currently used/needed only for IPQ807x, IPQ6018, IPQ5018"
+ print "\t\tThis Argument does not take any value\n"
+ print "\t\te.g python prepareSingleImage.py --genmbn\n\n"
+
+ print "--lk \t\tWhether lkboot.elf to be converted to lkboot.mbn"
+ print "\t\tIf not specified lkboot.mbn will not be generated"
+ print "\t\tThis is currently used/needed only for IPQ807x"
+ print "\t\tThis Argument does not take any value"
+ print "\t\tThis option depends on '--genmbn'\n"
+ print "\t\te.g python prepareSingleImage.py --genmbn --lk\n\n"
+
+ print "--genbootldr \tWhether bootldr binaries to be generated"
+ print "\t\tIf not specified bootldr binaries will not be generated"
+ print "\t\tThis Argument does not take any value\n"
+ print "\t\te.g python prepareSingleImage.py --genbootldr\n\n"
+
+ print "--help \t\tPrint This Message\n\n"
+
+ print "\t\t\t\t <<<<<<<<<<<<< A Sample Run >>>>>>>>>>>>>\n"
+ print "python prepareSingleImage.py --arch ipq40xx --fltype nor,nand,norplusnand --gencdt --genbootconf --genpart --in ./in_put/\n\n\n"
+
+
+def copy_images(image_type, build_dir):
+ global arch
+ global configDir
+
+ tree = ET.parse(configDir)
+ root = tree.getroot()
+
+ entries = root.findall("./data[@type='COPY_IMAGES']/image[@type='" + image_type + "']/entry")
+ for entry in entries:
+ image_path = entry.find(".//image_path")
+ image_path.text = build_dir.rstrip() + image_path.text
+ print "image_path.text:" + image_path.text
+ print "cp " + image_path.text + " " + inDir
+ os.system("cp " + image_path.text + " " + inDir)
+
+def gen_cdt():
+ global srcDir
+ global configDir
+ global memory
+
+ cdt_path = srcDir + '/gen_cdt_bin.py'
+ prc = subprocess.Popen(['python', cdt_path, '-c', configDir, '-o', inDir, '-m', memory], cwd=cdir)
+ prc.wait()
+
+ if prc.returncode != 0:
+ print 'ERROR: unable to create CDT binary'
+ return prc.returncode
+ return 0
+
+def gen_part(flash):
+ global srcDir
+ global configDir
+
+ flash_partition_path = srcDir + '/gen_flash_partition_bin.py'
+ for flash_type in flash.split(","):
+ prc = subprocess.Popen(['python', flash_partition_path, '-c', configDir, '-f', flash_type, '-o', inDir], cwd=cdir)
+ prc.wait()
+
+ if prc.returncode != 0:
+ print 'ERROR: unable to generate partition table for ' + flash_type
+ return prc.returncode
+ return 0
+
+def gen_bootconfig():
+ global srcDir
+ global configDir
+
+ bootconfig_path = srcDir + '/gen_bootconfig_bin.py'
+ print "Creating Bootconfig"
+ prc = subprocess.Popen(['python', bootconfig_path, '-c', configDir, '-o', inDir], cwd=cdir)
+ prc.wait()
+
+ if prc.returncode != 0:
+ print 'ERROR: unable to create bootconfig binary'
+ return prc.returncode
+ return 0
+
+def gen_bootldr():
+ global srcDir
+ global configDir
+ global memory
+
+ bootldr_path = srcDir + '/gen_bootldr_bin.py'
+ print "Creating bootldr"
+ prc = subprocess.Popen(['python', bootldr_path, '-c', configDir, '-o', inDir, '-m', memory], cwd=cdir)
+ prc.wait()
+
+ if prc.returncode != 0:
+ print 'ERROR: unable to create bootldr binary'
+ return prc.returncode
+ return 0
+
+def gen_mbn():
+ global srcDir
+ global mbn_v6
+
+ bootconfig_path = srcDir + '/elftombn.py'
+ print "Converting u-boot elf to mbn ..."
+ tiny_path=inDir + "/openwrt-" + arch + "_tiny" + "-u-boot.elf"
+
+ if mbn_v6 != "true":
+ prc = subprocess.Popen(['python', bootconfig_path, '-f', inDir + "/openwrt-" + arch + "-u-boot.elf", '-o', inDir + "/openwrt-" + arch + "-u-boot.mbn"], cwd=cdir)
+ if os.path.exists(tiny_path):
+ prc = subprocess.Popen(['python', bootconfig_path, '-f', inDir + "/openwrt-" + arch + "_tiny" + "-u-boot.elf", '-o', inDir + "/openwrt-" + arch + "_tiny" + "-u-boot.mbn"], cwd=cdir)
+
+ else:
+ prc = subprocess.Popen(['python', bootconfig_path, '-f', inDir + "/openwrt-" + arch + "-u-boot.elf", '-o', inDir + "/openwrt-" + arch + "-u-boot.mbn", '-v', "6"], cwd=cdir)
+
+ if os.path.exists(tiny_path):
+ prc = subprocess.Popen(['python', bootconfig_path, '-f', inDir + "/openwrt-" + arch + "_tiny" + "-u-boot.elf", '-o', inDir + "/openwrt-" + arch + "_tiny" + "-u-boot.mbn", '-v', "6"], cwd=cdir)
+
+ prc.wait()
+
+ if prc.returncode != 0:
+ print 'ERROR: unable to convert U-Boot .elf to .mbn'
+ return prc.returncode
+ else:
+ print "U-Boot .mbn file is created"
+ return 0
+
+def gen_lk_mbn():
+ global srcDir
+
+ bootconfig_path = srcDir + '/elftombn.py'
+ print "Converting LK elf to mbn ..."
+ if mbn_v6 != "true":
+ prc = subprocess.Popen(['python', bootconfig_path, '-f', inDir + "/openwrt-" + arch + "-lkboot.elf", '-o', inDir + "/openwrt-" + arch + "-lkboot.mbn"], cwd=cdir)
+ else:
+ prc = subprocess.Popen(['python', bootconfig_path, '-f', inDir + "/openwrt-" + arch + "-lkboot.elf", '-o', inDir + "/openwrt-" + arch + "-lkboot.mbn", '-v', "6"], cwd=cdir)
+ prc.wait()
+
+ if prc.returncode != 0:
+ print 'ERROR: unable to convert LK .elf to .mbn'
+ return prc.returncode
+ else:
+ print "LK .mbn file is created"
+ return 0
+
+def main():
+ global flash
+ global arch
+ global bootImgDir
+ global tzImgDir
+ global nhssImgDir
+ global rpmImgDir
+ global wififwImgDir
+ global srcDir
+ global configDir
+ global inDir
+ global mode
+ global mbn_v6
+ global memory
+
+ to_generate_cdt = "false"
+ to_generate_part = "false"
+ to_generate_bootconf = "false"
+ to_generate_mbn = "false"
+ to_generate_lk_mbn = "false"
+ to_generate_bootldr = "false"
+ memory = "default"
+
+ if len(sys.argv) > 1:
+ try:
+ opts, args = getopt(sys.argv[1:], "h", ["arch=", "fltype=", "in=", "bootimg=", "tzimg=", "nhssimg=", "rpmimg=", "wififwimg", "gencdt", "memory=", "genpart", "genbootconf", "genmbn", "lk", "genbootldr", "help"])
+ except GetoptError, e:
+ print_help()
+ raise
+
+ for option, value in opts:
+ if option == "--arch":
+ arch = value
+ if arch not in ["ipq40xx", "ipq806x", "ipq807x", "ipq807x_64", "ipq6018", "ipq6018_64", "ipq5018", "ipq5018_64", "ipq9048", "ipq9048_64"]:
+ print "Invalid arch type: " + arch
+ print_help()
+ return -1
+ if arch == "ipq807x" or arch == "ipq5018" or arch == "ipq9048":
+ mode = "32"
+ elif arch == "ipq807x_64" or arch == "ipq5018_64" or arch == "ipq9048_64":
+ mode = "64"
+ arch = arch[:-3]
+
+ if arch == "ipq6018":
+ mode = "32"
+ elif arch == "ipq6018_64":
+ mode = "64"
+ arch = "ipq6018"
+
+ elif option == "--fltype":
+ flash = value
+ for flash_type in flash.split(","):
+ if flash_type not in ["nor", "tiny-nor", "nand", "norplusnand", "emmc", "norplusemmc", "tiny-nor-debug"]:
+ print "Invalid flash type: " + flash_type
+ print_help()
+ return -1
+ elif option == "--in":
+ inDir = value
+ elif option == "--bootimg":
+ bootImgDir = value
+ elif option == "--tzimg":
+ tzImgDir = value
+ elif option == "--nhssimg":
+ nhssImgDir = value
+ elif option == "--rpmimg":
+ rpmImgDir = value
+ elif option == "--wififwimg":
+ wififwImgDir = value
+ elif option == "--gencdt":
+ to_generate_cdt = "true"
+ elif option == "--memory":
+ memory = value
+ elif option == "--genbootconf":
+ to_generate_bootconf = "true"
+ elif option == "--genpart":
+ to_generate_part = "true"
+ elif option == "--genmbn":
+ to_generate_mbn = "true"
+ elif option == "--lk":
+ to_generate_lk_mbn = "true"
+ elif option == "--genbootldr":
+ to_generate_bootldr = "true"
+
+ elif (option == "-h" or option == "--help"):
+ print_help()
+ return 0
+
+ srcDir="$$/scripts"
+ srcDir = srcDir.replace('$$', cdir)
+ configDir="$$/" + arch + "/config.xml"
+ configDir = configDir.replace('$$', cdir)
+
+ if inDir == "":
+ inDir="$$/" + arch + "/in"
+ inDir = inDir.replace('$$', cdir)
+
+ inDir = os.path.abspath(inDir + "/")
+
+ if not os.path.exists(inDir):
+ os.makedirs(inDir)
+
+ if bootImgDir != "":
+ copy_images("BOOT", bootImgDir)
+ if tzImgDir != "":
+ copy_images("TZ", tzImgDir)
+ if nhssImgDir != "":
+ copy_images("NHSS" + mode, nhssImgDir)
+ if rpmImgDir != "":
+ copy_images("RPM", rpmImgDir)
+ if wififwImgDir != "":
+ copy_images("WIFIFW", wififwImgDir)
+
+ if to_generate_cdt == "true":
+ if gen_cdt() != 0:
+ return -1
+
+ if to_generate_bootconf == "true":
+ if gen_bootconfig() != 0:
+ return -1
+
+ if to_generate_part == "true":
+ if gen_part(flash) != 0:
+ return -1
+
+ if to_generate_bootldr == "true":
+ if gen_bootldr() != 0:
+ return -1
+
+ if to_generate_mbn == "true":
+ if arch == "ipq807x" or arch == "ipq6018" or arch == "ipq5018" or arch == "ipq9048":
+ if arch == "ipq6018":
+ mbn_v6 = "true"
+ if gen_mbn() != 0:
+ return -1
+ if to_generate_lk_mbn == "true" and gen_lk_mbn() != 0:
+ return -1
+ else:
+ print "Invalid arch \"" + arch + "\" for mbn conversion"
+ print "--genmbn is needed/used only for ipq807x, ipq6018, ipq5018 and ipq9048 type"
+ return 0
+ else:
+ print_help()
+ return 0
+
+if __name__ == '__main__':
+ main()
+
diff --git a/scripts/gen_flash_partition_bin.py b/scripts/gen_flash_partition_bin.py
new file mode 100644
index 0000000..c4c471d
--- /dev/null
+++ b/scripts/gen_flash_partition_bin.py
@@ -0,0 +1,668 @@
+# ===========================================================================
+#Copyright (c) 2017 Qualcomm Technologies, Inc.
+#All Rights Reserved.
+#Confidential and Proprietary - Qualcomm Technologies, Inc.
+# ===========================================================================
+
+from collections import namedtuple
+
+import xml.etree.ElementTree as ET
+import os
+import subprocess
+import sys
+from getopt import getopt
+from getopt import GetoptError
+
+cdir = os.path.dirname("")
+cdir = os.path.abspath(cdir)
+Nor_Params = namedtuple("Nor_Params", "pagesize pages_per_block total_blocks")
+Nand_Params = namedtuple("nand_Params", "pagesize pages_per_block total_blocks")
+outputdir = ""
+
+def process_nand_device(pagesize, pages_per_block, total_blocks, entry, nand_type):
+
+ global mbn_gen
+ global nandsyspartition
+ global partition_tool
+ global cdir
+ global ARCH_NAME
+ global outputdir
+ global QCN9000
+
+ nand_pagesize = pagesize
+ nand_pages_per_block = pages_per_block
+ nand_total_blocks = total_blocks
+
+ if nand_type == "audio-4k":
+ nand_partition = "$$/" + ARCH_NAME + "/flash_partition/nand-audio-4k-partition.xml"
+ elif nand_type == "audio-2k":
+ nand_partition = "$$/" + ARCH_NAME + "/flash_partition/nand-audio-partition.xml"
+ elif nand_type == "4k":
+ nand_partition = "$$/" + ARCH_NAME + "/flash_partition/nand-4k-partition.xml"
+ elif nand_type == "2k":
+ if QCN9000:
+ nand_partition = "$$/" + ARCH_NAME + "/flash_partition/nand-partition-qcn9000.xml"
+ else:
+ nand_partition = "$$/" + ARCH_NAME + "/flash_partition/nand-partition.xml"
+
+ nand_partition = nand_partition.replace('$$', cdir)
+
+ nand_parts = Nand_Params(nand_pagesize, nand_pages_per_block, nand_total_blocks)
+
+ mbn_gen = '$$/scripts/nand_mbn_generator.py'
+ mbn_gen = mbn_gen.replace('$$', cdir)
+
+ if ARCH_NAME == "ipq806x":
+ partition_tool = outputdir + '/nor_tool'
+ else:
+ partition_tool = outputdir + '/partition_tool'
+ os.chmod(partition_tool, 0744)
+
+ if entry == False or (entry == True and nand_pagesize == 2048 and nand_type == '2k'):
+ if QCN9000:
+ nandsyspartition = outputdir + '/nand-system-partition-' + ARCH_NAME + '-qcn9000.bin'
+ nanduserpartition = 'nand-user-partition-qcn9000.bin'
+ else:
+ nandsyspartition = outputdir + '/nand-system-partition-' + ARCH_NAME + '.bin'
+ nanduserpartition = 'nand-user-partition.bin'
+ else:
+ nand_blocksize = (nand_pagesize * nand_pages_per_block) / 1024
+ if nand_type == "audio-2k" or nand_type == "audio-4k":
+ nand_type = "audio-"
+ elif nand_type == "4k":
+ nand_type = ""
+ nandsyspartition = outputdir + '/nand-' + nand_type + 'system-partition-' + ARCH_NAME + '-m' + str(nand_pagesize) + '-p' + str(nand_blocksize) + 'KiB.bin'
+ nanduserpartition = 'nand-' + nand_type + 'user-partition-m' + str(nand_pagesize) + '-p' + str(nand_blocksize) + 'KiB.bin'
+
+ nanduserbin= os.path.splitext(nanduserpartition)[0] + ".bin"
+
+ print '\tNand page size: ' + str(nand_parts.pagesize) + ', pages/block: ' \
+ + str(nand_parts.pages_per_block) + ', total blocks: ' \
+ + str(nand_parts.total_blocks)
+ print '\tPartition info: ' + nand_partition
+
+ print '\tCreating user partition',
+ prc = subprocess.Popen(['python', mbn_gen, nand_partition,
+ nanduserbin], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create user partition'
+ return prc.returncode
+ else:
+ print '...User partition created'
+ userpart_path = os.path.join(outputdir, nanduserbin)
+
+ print '\tCreating system partition'
+ prc = subprocess.Popen([
+ partition_tool,
+ '-s',
+ str(nand_parts.pagesize),
+ '-p',
+ str(nand_parts.pages_per_block),
+ '-b',
+ str(nand_parts.total_blocks),
+ '-u',
+ userpart_path,
+ '-o',
+ nandsyspartition,
+ ], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create system partition'
+ return prc.returncode
+ else:
+ print '...System partition created'
+ return 0
+
+
+def process_nand(config_path, flash_type):
+ global mbn_gen
+ global nandsyspartition
+ global partition_tool
+ global cdir
+ global ARCH_NAME
+ global outputdir
+ global QCN9000
+
+ tree = ET.parse(config_path)
+ root = tree.getroot()
+
+ arch = root.find(".//data[@type='ARCH']/SOC")
+ ARCH_NAME = str(arch.text)
+ entry = False
+ QCN9000 = False
+
+ if ARCH_NAME == "ipq807x":
+ QCN9000 = True
+
+ if root.find(".//data[@type='NAND_PARAMETER']/entry") != None:
+
+ entry = True
+ entries = root.findall("./data[@type='NAND_PARAMETER']/entry")
+ for nand_param in entries:
+ nand_pagesize = int(nand_param.find(".//page_size").text)
+ nand_pages_per_block = int(nand_param.find(".//pages_per_block").text)
+ nand_total_blocks = int(nand_param.find(".//total_block").text)
+ nand_type = nand_param.get('type')
+
+ if QCN9000:
+ if process_nand_device(nand_pagesize, nand_pages_per_block, nand_total_blocks, entry, nand_type) != 0:
+ return -1
+ QCN9000 = False
+
+ if process_nand_device(nand_pagesize, nand_pages_per_block, nand_total_blocks, entry, nand_type) != 0:
+ return -1
+ else:
+ nand_param = root.find(".//data[@type='NAND_PARAMETER']")
+ nand_pagesize = int(nand_param.find('page_size').text)
+ nand_pages_per_block = int(nand_param.find('pages_per_block').text)
+ nand_total_blocks = int(nand_param.find('total_block').text)
+
+ if QCN9000:
+ if process_nand_device(nand_pagesize, nand_pages_per_block, nand_total_blocks, entry, "2k") != 0:
+ return -1
+ QCN9000 = False
+
+ if process_nand_device(nand_pagesize, nand_pages_per_block, nand_total_blocks, entry, "2k") != 0:
+ return -1
+
+ return 0
+
+
+def process_nor(config_path, flash_type):
+ global mbn_gen
+ global syspart
+ global partition_tool
+ global cdir
+ global ARCH_NAME
+ global outputdir
+
+ tree = ET.parse(config_path)
+ root = tree.getroot()
+
+ arch = root.find(".//data[@type='ARCH']/SOC")
+ ARCH_NAME = str(arch.text)
+
+ nor_param = root.find(".//data[@type='NOR_PARAMETER']")
+ nor_pagesize = int(nor_param.find('page_size').text)
+ nor_pages_per_block = int(nor_param.find('pages_per_block').text)
+ nor_total_blocks = int(nor_param.find('total_block').text)
+ block_size = (nor_pagesize * nor_pages_per_block) / 1024
+ density = (block_size * nor_total_blocks) / 1024
+
+ nor_partition = "$$/" + ARCH_NAME + "/flash_partition/" + flash_type + "-partition.xml"
+ nor_partition = nor_partition.replace('$$', cdir)
+
+ if ARCH_NAME != "ipq806x":
+ root_part = ET.parse(nor_partition)
+ part = root_part.find(".//partitions/partition[2]")
+ part[5].text = str(block_size)
+ part[6].text = str(density)
+ root_part.write(nor_partition)
+
+ nor_parts = Nor_Params(nor_pagesize, nor_pages_per_block, nor_total_blocks)
+
+ mbn_gen = '$$/scripts/nand_mbn_generator.py'
+ mbn_gen = mbn_gen.replace('$$', cdir)
+
+ if ARCH_NAME == "ipq806x":
+ partition_tool = outputdir + '/nor_tool'
+ else:
+ partition_tool = outputdir + '/partition_tool'
+ os.chmod(partition_tool, 0744)
+
+ syspart = outputdir + '/' + flash_type + '-system-partition-' + ARCH_NAME + '.bin'
+ userpart = flash_type + '-user-partition.bin'
+ noruserbin= os.path.splitext(userpart)[0] + ".bin"
+
+ print '\tNor page size: ' + str(nor_parts.pagesize) + ', pages/block: ' \
+ + str(nor_parts.pages_per_block) + ', total blocks: ' \
+ + str(nor_parts.total_blocks) + ', partition info: ' + nor_partition
+
+ print '\tCreating user partition',
+ prc = subprocess.Popen(['python', mbn_gen, nor_partition,
+ noruserbin], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create user partition'
+ return prc.returncode
+ else:
+ print '...User partition created'
+
+ userpart_path = os.path.join(outputdir, noruserbin)
+
+ print '\tCreating system partition'
+ prc = subprocess.Popen([
+ partition_tool,
+ '-s',
+ str(nor_parts.pagesize),
+ '-p',
+ str(nor_parts.pages_per_block),
+ '-b',
+ str(nor_parts.total_blocks),
+ '-c',
+ str(1),
+ '-u',
+ userpart_path,
+ '-o',
+ syspart,
+ ], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create system partition'
+ return prc.returncode
+ else:
+ print '...System partition created'
+
+ return 0
+
+
+def process_norplusnand_device(nor_pagesize, nor_pages_per_block, nor_total_blocks,
+ nand_pagesize, nand_pages_per_block, nand_total_blocks, entry):
+ global mbn_gen
+ global norplusnandsyspartition
+ global partition_tool
+ global cdir
+ global ARCH_NAME
+ global outputdir
+ global QCN9000
+
+ if nand_pagesize == 2048:
+ if QCN9000:
+ norplusnand_partition = "$$/" + ARCH_NAME + "/flash_partition/norplusnand-partition-qcn9000.xml"
+ else:
+ norplusnand_partition = "$$/" + ARCH_NAME + "/flash_partition/norplusnand-partition.xml"
+ else:
+ norplusnand_partition = "$$/" + ARCH_NAME + "/flash_partition/norplusnand-4k-partition.xml"
+
+ norplusnand_partition = norplusnand_partition.replace('$$', cdir)
+ nand_parts = Nand_Params(nand_pagesize, nand_pages_per_block, nand_total_blocks)
+ nor_parts = Nor_Params(nor_pagesize, nor_pages_per_block, nor_total_blocks)
+
+ mbn_gen = '$$/scripts/nand_mbn_generator.py'
+ mbn_gen = mbn_gen.replace('$$', cdir)
+
+ if ARCH_NAME == "ipq806x":
+ partition_tool = outputdir + '/nor_tool'
+ else:
+ partition_tool = outputdir + '/partition_tool'
+ os.chmod(partition_tool, 0744)
+
+ if entry == False or (entry == True and nand_pagesize == 2048):
+ if QCN9000:
+ norplusnandsyspartition = outputdir + '/norplusnand-system-partition-' + ARCH_NAME + '-qcn9000.bin'
+ userpart = 'norplusnand-user-partition-qcn9000.bin'
+ else:
+ norplusnandsyspartition = outputdir + '/norplusnand-system-partition-' + ARCH_NAME + '.bin'
+ userpart = 'norplusnand-user-partition.bin'
+ else:
+ nand_blocksize = (nand_pagesize * nand_pages_per_block) / 1024
+ norplusnandsyspartition = outputdir + '/norplusnand-system-partition-' + ARCH_NAME + '-m' + str(nand_pagesize) + '-p' + str(nand_blocksize) + 'KiB.bin'
+ userpart = 'norplusnand-user-partition-m' + str(nand_pagesize) + '-p' + str(nand_blocksize) + 'KiB.bin'
+
+ norplusnanduserbin= os.path.splitext(userpart)[0] +".bin"
+
+ print '\tNor page size: ' + str(nor_parts.pagesize) + ', pages/block: ' \
+ + str(nor_parts.pages_per_block) + ', total blocks: ' \
+ + str(nor_parts.total_blocks)
+ print '\tPartition info: ' + norplusnand_partition
+
+ print '\tCreating user partition',
+ prc = subprocess.Popen(['python', mbn_gen, norplusnand_partition,
+ norplusnanduserbin], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create user partition'
+ return prc.returncode
+ else:
+ print '...User partition created'
+
+ userpart_path = os.path.join(outputdir, norplusnanduserbin)
+
+ print '\tCreating system partition'
+ prc = subprocess.Popen([
+ partition_tool,
+ '-s',
+ str(nor_parts.pagesize),
+ '-p',
+ str(nor_parts.pages_per_block),
+ '-b',
+ str(nor_parts.total_blocks),
+ '-x',
+ str(nand_parts.pagesize),
+ '-y',
+ str(nand_parts.pages_per_block),
+ '-z',
+ str(nand_parts.total_blocks),
+ '-c',
+ str(1),
+ '-u',
+ userpart_path,
+ '-o',
+ norplusnandsyspartition,
+ ], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create system partition'
+ return prc.returncode
+ else:
+ print '...System partition created'
+ return 0
+
+
+def process_norplusnand(config_path, flash_type):
+ global mbn_gen
+ global norplusnandsyspartition
+ global partition_tool
+ global cdir
+ global ARCH_NAME
+ global outputdir
+ global QCN9000
+
+ tree = ET.parse(config_path)
+ root = tree.getroot()
+
+ arch = root.find(".//data[@type='ARCH']/SOC")
+ ARCH_NAME = str(arch.text)
+
+ nor_param = root.find(".//data[@type='NOR_PARAMETER']")
+ nor_pagesize = int(nor_param.find('page_size').text)
+ nor_pages_per_block = int(nor_param.find('pages_per_block').text)
+ nor_total_blocks = int(nor_param.find('total_block').text)
+
+ norplusnand_partition = "$$/" + ARCH_NAME + "/flash_partition/norplusnand-partition.xml"
+ norplusnand_partition = norplusnand_partition.replace('$$', cdir)
+
+ if ARCH_NAME != "ipq806x":
+ root_part = ET.parse(norplusnand_partition)
+ part = root_part.find(".//partitions/partition[2]")
+ block_size = (nor_pagesize * nor_pages_per_block) / 1024
+ density = (block_size * nor_total_blocks) / 1024
+ part[5].text = str(block_size)
+ part[6].text = str(density)
+ root_part.write(norplusnand_partition)
+
+ entry = False
+ QCN9000 = False
+
+ if ARCH_NAME == "ipq807x":
+ QCN9000 = True
+
+ if root.find(".//data[@type='NAND_PARAMETER']/entry") != None:
+
+ entry = True
+ entries = root.findall("./data[@type='NAND_PARAMETER']/entry")
+ for nand_param in entries:
+ nand_pagesize = int(nand_param.find(".//page_size").text)
+ nand_pages_per_block = int(nand_param.find(".//pages_per_block").text)
+ nand_total_blocks = int(nand_param.find(".//total_block").text)
+
+ if QCN9000:
+ if process_norplusnand_device(nor_pagesize,
+ nor_pages_per_block, nor_total_blocks, nand_pagesize,
+ nand_pages_per_block, nand_total_blocks, entry) != 0:
+ return -1
+ QCN9000 = False
+
+ if process_norplusnand_device(nor_pagesize,
+ nor_pages_per_block, nor_total_blocks, nand_pagesize,
+ nand_pages_per_block, nand_total_blocks, entry) != 0:
+ return -1
+
+ else:
+ nand_param = root.find(".//data[@type='NAND_PARAMETER']")
+ nand_pagesize = int(nand_param.find('page_size').text)
+ nand_pages_per_block = int(nand_param.find('pages_per_block').text)
+ nand_total_blocks = int(nand_param.find('total_block').text)
+
+ if QCN9000:
+ if process_norplusnand_device(nor_pagesize,
+ nor_pages_per_block, nor_total_blocks, nand_pagesize,
+ nand_pages_per_block, nand_total_blocks, entry) != 0:
+ return -1
+ QCN9000 = False
+
+ if process_norplusnand_device(nor_pagesize,
+ nor_pages_per_block, nor_total_blocks, nand_pagesize,
+ nand_pages_per_block, nand_total_blocks, entry) != 0:
+ return -1
+ return 0
+
+
+def process_emmc(config_path, flash_type):
+ global ptool
+ global msp
+ global ARCH_NAME
+ global outputdir
+
+ tree = ET.parse(config_path)
+ root = tree.getroot()
+
+ arch = root.find(".//data[@type='ARCH']/SOC")
+ ARCH_NAME = str(arch.text)
+ emmc_partition = "$$/" + ARCH_NAME + "/flash_partition/emmc-partition.xml"
+ emmc_partition = emmc_partition.replace('$$', cdir)
+
+ emmc_total_blocks = None
+
+ emmc_entry = root.find(".//data[@type='EMMC_PARAMETER']/total_block")
+ total_blocks = int(emmc_entry.text)
+
+ ptool = '$$/scripts/ptool.py'
+ ptool = ptool.replace('$$', cdir)
+ msp = '$$/scripts/msp.py'
+ msp = msp.replace('$$', cdir)
+
+ emmc_total_blocks = total_blocks
+
+ print '\tTotal blocks: ' + str(emmc_total_blocks)
+ print '\tPartition info: ' + emmc_partition
+ print '\temmc path: ' + outputdir
+
+ print '\tCreating rawprogram0.xml and patch0.xml',
+ prc = subprocess.Popen(['python', ptool, '-x', emmc_partition], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create rawprogram0.xml and patch0.xml'
+ return prc.returncode
+ else:
+ print '...rawprogram0.xml and patch0.xml created'
+
+ rawprogram_path = os.path.join(outputdir, 'rawprogram0.xml')
+ patch_path = os.path.join(outputdir, 'patch0.xml')
+
+ print '\t rawprogram' + rawprogram_path
+ print '\t patch' + patch_path
+
+ print '\tRunning msp.py to update gpt_main0.bin partition'
+ prc = subprocess.Popen([
+ 'python',
+ msp,
+ '-r',
+ rawprogram_path,
+ '-p',
+ patch_path,
+ '-d',
+ str(emmc_total_blocks),
+ '-n',
+ ], cwd=outputdir)
+ prc.wait()
+
+ if prc.returncode != 0:
+ print 'ERROR: unable to create system partition'
+ return prc.returncode
+ else:
+ print '...System partition created'
+ return 0
+
+
+def process_norplusemmc(config_path, flash_type):
+ global mbn_gen
+ global syspart
+ global partition_tool
+ global cdir
+ global ptool
+ global msp
+ global ARCH_NAME
+ global outputdir
+
+ tree = ET.parse(config_path)
+ root = tree.getroot()
+
+ arch = root.find(".//data[@type='ARCH']/SOC")
+ ARCH_NAME = str(arch.text)
+
+ blocks = root.find(".//data[@type='EMMC_PARAMETER']")
+ emmc_total_blocks = int(blocks.find('total_block').text)
+
+ nor_param = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
+ nor_pagesize = int(nor_param.find('page_size').text)
+ nor_pages_per_block = int(nor_param.find('pages_per_block').text)
+ nor_total_blocks = int(nor_param.find('total_block').text)
+ norplusemmc_partition = "$$/" + ARCH_NAME + "/flash_partition/norplusemmc-partition.xml"
+ emmc_partition = "$$/" + ARCH_NAME + "/flash_partition/emmc-partition.xml"
+ norplusemmc_partition = norplusemmc_partition.replace('$$', cdir)
+ emmc_partition = emmc_partition.replace('$$', cdir)
+
+ if ARCH_NAME != "ipq806x":
+ root_part = ET.parse(norplusemmc_partition)
+ part = root_part.find(".//partitions/partition[2]")
+ block_size = (nor_pagesize * nor_pages_per_block) / 1024
+ density = (block_size * nor_total_blocks) / 1024
+ part[5].text = str(block_size)
+ part[6].text = str(density)
+ root_part.write(norplusemmc_partition)
+
+ nor_parts = Nor_Params(nor_pagesize, nor_pages_per_block, nor_total_blocks)
+
+ mbn_gen = '$$/scripts/nand_mbn_generator.py'
+ mbn_gen = mbn_gen.replace('$$', cdir)
+
+ ptool = '$$/scripts/ptool.py'
+ ptool = ptool.replace('$$', cdir)
+ msp = '$$/scripts/msp.py'
+ msp = msp.replace('$$', cdir)
+
+ if ARCH_NAME == "ipq806x":
+ partition_tool = outputdir + '/nor_tool'
+ else:
+ partition_tool = outputdir + '/partition_tool'
+ os.chmod(partition_tool, 0744)
+
+ syspart = outputdir + '/norplusemmc-system-partition-' + ARCH_NAME + '.bin'
+ userpart = 'norplusemmc-user-partition.bin'
+ norplusemmcuserbin= os.path.splitext(userpart)[0] + ".bin"
+
+ print '\tNor page size: ' + str(nor_parts.pagesize) + ', pages/block: ' \
+ + str(nor_parts.pages_per_block) + ', total blocks: ' \
+ + str(nor_parts.total_blocks) + ', partition info: ' + norplusemmc_partition
+
+ print '\tCreating user partition',
+ prc = subprocess.Popen(['python', mbn_gen, norplusemmc_partition,
+ norplusemmcuserbin], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create user partition'
+ return prc.returncode
+ else:
+ print '...User partition created'
+
+ userpart_path = os.path.join(outputdir, norplusemmcuserbin)
+
+ print '\tCreating system partition'
+ prc = subprocess.Popen([
+ partition_tool,
+ '-s',
+ str(nor_parts.pagesize),
+ '-p',
+ str(nor_parts.pages_per_block),
+ '-b',
+ str(nor_parts.total_blocks),
+ '-c',
+ str(1),
+ '-u',
+ userpart_path,
+ '-o',
+ syspart,
+ ], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create system partition'
+ return prc.returncode
+ else:
+ print '...System partition created'
+
+ print '\tCreating rawprogram1.xml and patch1.xml',
+ prc = subprocess.Popen(['python', ptool, '-x', emmc_partition, '-p', '1'], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create rawprogram1.xml and patch1.xml'
+ return prc.returncode
+ else:
+ print '...rawprogram1.xml and patch1.xml created'
+
+ rawprogram_path = os.path.join(outputdir, 'rawprogram1.xml')
+ patch_path = os.path.join(outputdir, 'patch1.xml')
+
+ print '\t rawprogram' + rawprogram_path
+ print '\t patch' + patch_path
+
+ print '\tRunning msp.py to update gpt_main0.bin partition',
+ prc = subprocess.Popen([
+ 'python',
+ msp,
+ '-r',
+ rawprogram_path,
+ '-p',
+ patch_path,
+ '-d',
+ str(emmc_total_blocks),
+ '-n',
+ ], cwd=outputdir)
+ prc.wait()
+ if prc.returncode != 0:
+ print 'ERROR: unable to create system partition'
+ return prc.returncode
+ else:
+ print '...System partition created'
+ return 0
+
+def main():
+
+ global cdir
+ global ARCH_NAME
+ global outputdir
+
+ funcdict = {
+ 'nor': process_nor,
+ 'tiny-nor': process_nor,
+ 'nand': process_nand,
+ 'norplusnand': process_norplusnand,
+ 'emmc': process_emmc,
+ 'norplusemmc': process_norplusemmc,
+ 'tiny-nor-debug': process_nor
+ }
+
+ if len(sys.argv) > 1:
+ try:
+ opts, args = getopt(sys.argv[1:], "c:f:o:")
+ except GetoptError, e:
+ print "Configuration xml, flash type and output path are needed to generate cdt files"
+ raise
+
+ for option, value in opts:
+ if option == "-c":
+ config_path = value
+ if option == "-o":
+ outputdir = value
+ if option == "-f":
+ flash_type = value
+ print flash_type
+ else:
+ print "Configuration xml, flash type and output path are needed to generate cdt files"
+
+ if funcdict[flash_type](config_path, flash_type) < 0:
+ return -1
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/nand_mbn_generator.py b/scripts/nand_mbn_generator.py
new file mode 100644
index 0000000..afdda09
--- /dev/null
+++ b/scripts/nand_mbn_generator.py
@@ -0,0 +1,178 @@
+# ===========================================================================
+#Copyright (c) 2017 Qualcomm Technologies, Inc.
+#All Rights Reserved.
+#Confidential and Proprietary - Qualcomm Technologies, Inc.
+# ===========================================================================
+
+import re
+import sys
+
+c_file_name = "boot_cdt_array.c"
+debug = True
+
+if len(sys.argv) < 3:
+ print "Usage: cdt_generator.py filename.xml binfile.bin"
+ sys.exit(1);
+
+filename = sys.argv[1]
+bin_file_name = sys.argv[2]
+token_stack = []
+ignore_tags = ['comment', 'img_name', 'layout']
+xml_comment_tag = '!--'
+partitions_parent_tag_name = "partition"
+partition_table_header_size = 16
+partition_entry_size = 28
+num_partition_entries = 32
+full_file_length = (partition_table_header_size + (partition_entry_size * num_partition_entries))
+header = []
+metadata = []
+blockdata = []
+footer = []
+all_data = []
+
+def clean_string(some_string):
+ from string import printable
+ some_string = "".join([ ch for ch in some_string if ch in printable ])
+ some_string = some_string.replace("\n", "")
+ some_string = some_string.replace("\r", "")
+ return some_string
+
+def strip_hex(hex_string):
+ if len(hex_string) < 3 or not (hex_string[:2] == "0x" or hex_string[:2] == "0X"):
+ return hex_string
+ return hex_string[2:]
+
+def little_endian(hex_string):
+ if len(hex_string) % 2 != 0:
+ print "%s is an invalid value to convert to little endian!" % (hex_string)
+ return
+ swap_list = []
+ for i in range(0, len(hex_string), 2):
+ swap_list.insert(0, hex_string[i:i+2])
+ return ''.join(swap_list)
+
+def get_attribute(token, att_name):
+ tag = get_tag_name(token)
+ tag_att_list = re.split('\s+', strip_tags(token))
+ tag_att_list.remove(tag)
+ for att in tag_att_list:
+ att_val = att.split("=")
+ if len(att_val) == 2 and att_val[0] == att_name:
+ return att_val[1].strip('"').strip("'")
+ return None
+
+def pad_string(token, length, rightjust=True):
+ if len(token) >= length:
+ return token
+ else:
+ return (rightjust and token.rjust(length, '0') or token.ljust(length, '0'))
+
+def is_tag(token):
+ return (len(token) > 2 and token[0] == '<' and token[-1] == '>')
+
+def strip_tags(token):
+ if is_tag(token):
+ return token[1:-1]
+
+def is_closing_tag(token):
+ return (is_tag(token) and token[1] == '/')
+
+def get_tag_name(tag):
+ if is_closing_tag(tag):
+ return tag[2:-1]
+ else:
+ tag_split = re.split('\s+', tag[1:-1])
+ return tag_split[0]
+
+def process_tag(tag):
+ tag_name = get_tag_name(tag)
+ parent_tag_name = len(token_stack) >= 2 and get_tag_name(token_stack[-2]) or ""
+
+ if is_closing_tag(tag):
+ if tag_name == partitions_parent_tag_name:
+ if len(metadata) == 0:
+ metadata.append(1)
+ else:
+ metadata[0] = metadata[0] + 1
+
+def process_data(data, token_stack):
+ tag = token_stack[-1]
+ tag_name = get_tag_name(tag)
+ parent_tag_name = len(token_stack) >= 2 and get_tag_name(token_stack[-2]) or ""
+
+ if tag_name in ignore_tags:
+ return
+
+ clean_data = data
+ data_length = get_attribute(tag, "length")
+ data_type = get_attribute(tag, "type")
+ if not data_type == "string":
+ clean_data = "%02X" % eval(clean_data)
+ else:
+ clean_data = "".join(["%02x" % ord(x) for x in clean_data])
+ if not data_length is None:
+ data_length = int(data_length)
+ clean_data = pad_string(clean_data, data_length * 2, data_type != "string")
+
+ data_endianness = get_attribute(tag, "endian")
+ # assuming big-endian by default
+ # assuming 'string's need to be converted to little endian
+ if not data_type == "string" or ((not data_endianness is None) and data_endianness.lower() == "little"):
+ clean_data = little_endian(clean_data)
+
+ if not parent_tag_name == partitions_parent_tag_name:
+ header.append(clean_data)
+ else:
+ blockdata.append(clean_data)
+
+def generate_metadata():
+ if len(metadata) > 0:
+ metadata[0] = little_endian(pad_string("%02X" % metadata[0], 4*2))
+
+def generate_footer():
+ current_file_len = 0
+ for x in all_data:
+ current_file_len = current_file_len + len(x)/2
+ footer.append("0" * 2 * (full_file_length - current_file_len))
+
+def write_bin_file(filename, data):
+ fp = open(filename, 'wb')
+ for i in range(0, len(data), 2):
+ data_item = data[i:i+2]
+ fp.write(chr(int(data_item, 16)))
+ fp.close()
+
+file_string = open(filename, 'r').read()
+file_string = re.sub(r'>\s+', ">", file_string)
+file_string = re.sub(r'\s+<', "<", file_string)
+file_string = clean_string(file_string)
+
+# A token is either a tag i.e. <[^>\s]*> or it is a (non-tag) value i.e. [^<>]+
+#splitter = re.compile('(<\/?\S+[^>]*>|[^<>]+)')
+splitter = re.compile('(<[^>]*>|[^<>]+)')
+token_list = splitter.findall(file_string)
+
+for token in token_list:
+ #print "Processing", token
+ if is_tag(token):
+ if get_tag_name(token) == xml_comment_tag or get_tag_name(token) == "?xml":
+ continue
+ if is_closing_tag(token):
+ token_stack.pop()
+ else:
+ token_stack.append(token)
+ process_tag(token)
+ else:
+ process_data(token, token_stack)
+
+generate_metadata()
+
+all_data.extend(header)
+all_data.extend(metadata)
+all_data.extend(blockdata)
+
+generate_footer()
+
+all_data.extend(footer)
+all_data = "".join(all_data)
+write_bin_file(bin_file_name, all_data)
diff --git a/命令.txt b/命令.txt
new file mode 100644
index 0000000..210e296
--- /dev/null
+++ b/命令.txt
@@ -0,0 +1 @@
+python prepareSingleImage.py --arch ipq6018 --fltype nand --genpart
\ No newline at end of file
diff --git a/说明.txt b/说明.txt
new file mode 100644
index 0000000..97132c6
--- /dev/null
+++ b/说明.txt
@@ -0,0 +1,3 @@
+修改nand-partition.xml
+运行命令
+找到nand-system-partition-ipq6018.bin
\ No newline at end of file