From 980f754843fa31defbe537eff1865342296b0048 Mon Sep 17 00:00:00 2001 From: wrapper Date: Sun, 22 Mar 2026 11:47:18 +0700 Subject: [PATCH] reboot part 1 --- .gitignore | 5 +- .vscode/settings.json | 1 - crt.s | 86 +- dcc/bitutils.c | 2 +- dcc/bitutils.h | 2 +- dcc/dn_dcc_proto.c | 124 +- dcc/dn_dcc_proto.h | 29 +- dcc/pic.c | 8 +- dcc/plat.h | 16 +- devices/qcom/qsc6055_onenand.c | 8 + flash/cfi/cfi.c | 2 +- flash/mmap/mmap.c | 2 +- flash/nand/controller/emp/db3xxx.c | 182 +++ flash/nand/controller/qcom/qsc6270.c | 1 + flash/nand/controller/ste/nomadik.c | 180 +++ flash/nand/nand.c | 2 +- flash/onenand/controller/controller.h | 2 +- flash/onenand/controller/default.c | 8 +- flash/onenand/controller/qcom/msm7200.c | 8 +- flash/onenand/onenand.c | 10 +- flash/superand/superand.c | 2 +- .../MSM6050.has} | Bin .../MSM6100_CLK.has} | Bin .../msm6050_new/m6050_32mb_3ff.has | Bin 0 -> 624 bytes .../msm6050_new/old/m6050_32mb_3c4.has | Bin .../msm6050_new/old/m6050_32mb_3c5.has | Bin .../msm6050_new/old/m6050_32mb_3e8.has | Bin .../msm6050_new/old/m6050_32mb_3e9.has | Bin .../msm6050_new/old/m6050_32mb_3f0.has | Bin .../msm6050_new/old/m6050_32mb_3f1.has | Bin .../msm6100/msm6100_nor_rom1_cs1_gp2_cs3.has | Bin .../msm6100_nor_rom1_cs1_gp2_cs3_cp15.has | Bin .../msm6100_nor_rom1_cs1_gp2_cs3_cp15_clk.has | Bin 0 -> 300 bytes .../old/msm6100_nor_rom1_cs0_gp2_cs0.has | Bin .../old/msm6100_nor_rom1_cs0_gp2_cs0_cp15.has | Bin .../old/msm6100_nor_rom1_cs0_gp2_cs1.has | Bin .../old/msm6100_nor_rom1_cs0_gp2_cs1_cp15.has | Bin .../old/msm6100_nor_rom1_cs1_gp2_cs0.has | Bin .../old/msm6100_nor_rom1_cs1_gp2_cs0_cp15.has | Bin has/{ => old_versions}/old/msm6050_32mb.has | Bin has/{ => old_versions}/old/msm6050_8mb.has | Bin has/resurrectors/Alcatel_C131_init.has | Bin 0 -> 760 bytes has/resurrectors/Alcatel_OT255C_init.has | Bin 0 -> 640 bytes has/resurrectors/Anydata_ADU_555C_init.has | Bin 0 -> 2216 bytes has/resurrectors/ESC6XXX_L36_D08_init.has | Bin 0 -> 276 bytes has/resurrectors/ESM7XXX_L41_D04_init.has | Bin 0 -> 204 bytes has/resurrectors/HTC_Desire_init.has | Bin 0 -> 204 bytes has/resurrectors/HTC_DroidEris_init.has | Bin 0 -> 204 bytes has/resurrectors/Haier_C2010_init.has | Bin 0 -> 640 bytes has/resurrectors/Haier_C2040_init.has | Bin 0 -> 212 bytes has/resurrectors/Haier_C2076_init.has | Bin 0 -> 704 bytes has/resurrectors/Haier_C300_init.has | Bin 0 -> 212 bytes has/resurrectors/Haier_C3010_init.has | Bin 0 -> 212 bytes has/resurrectors/Haier_C301R_init.has | Bin 0 -> 212 bytes has/resurrectors/Haier_C5100_init.has | Bin 0 -> 212 bytes has/resurrectors/Haier_C6000_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2605_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2607_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2801_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2806M_init.has | Bin 0 -> 644 bytes has/resurrectors/Huawei_C2807_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2808_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2809_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2823_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2830_init.has | Bin 0 -> 640 bytes has/resurrectors/Huawei_C2856_init.has | Bin 0 -> 640 bytes has/resurrectors/Huawei_C2901M_init.has | Bin 0 -> 644 bytes has/resurrectors/Huawei_C2905_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C2906_init.has | Bin 0 -> 644 bytes has/resurrectors/Huawei_C3200_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C3500_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C5005_init.has | Bin 0 -> 772 bytes has/resurrectors/Huawei_C5100_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C5589_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_C8500_init.has | Bin 0 -> 972 bytes has/resurrectors/Huawei_EC1260_init.has | Bin 0 -> 2216 bytes has/resurrectors/Huawei_EC189_init.has | Bin 0 -> 2280 bytes has/resurrectors/Huawei_ETS2205_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_ETS2222_Plus_init.has | Bin 0 -> 212 bytes has/resurrectors/Huawei_ETS2225_init.has | Bin 0 -> 212 bytes has/resurrectors/Intex_In50_init.has | Bin 0 -> 212 bytes has/resurrectors/KDDI_Casio_W21CAII_init.has | Bin 0 -> 720 bytes has/resurrectors/KDDI_Hitachi_W52H_init.has | Bin 0 -> 72 bytes has/resurrectors/KDDI_Sanyio_SA002_init.has | Bin 0 -> 204 bytes has/resurrectors/KDDI_Sharp_W52SH_init.has | Bin 0 -> 36 bytes has/resurrectors/KDDI_Toshiba_W52T_init.has | Bin 0 -> 36 bytes has/resurrectors/LG_LS970_init.has | Bin 0 -> 420 bytes has/resurrectors/LG_LSP450T_init.has | Bin 0 -> 212 bytes has/resurrectors/LG_LU6200_init.has | Bin 0 -> 928 bytes has/resurrectors/LG_MX800_init.has | Bin 0 -> 1460 bytes has/resurrectors/LG_P999_CP_init.has | Bin 0 -> 48 bytes has/resurrectors/LG_RD3000_init.has | Bin 0 -> 644 bytes has/resurrectors/LG_RD3100_init.has | Bin 0 -> 644 bytes has/resurrectors/LG_RD3500_init.has | Bin 0 -> 644 bytes has/resurrectors/LG_RD3510_init.has | Bin 0 -> 644 bytes has/resurrectors/LG_RD3540_init.has | Bin 0 -> 644 bytes has/resurrectors/LG_RD3610_init.has | Bin 0 -> 644 bytes has/resurrectors/LG_RD3640_init.has | Bin 0 -> 212 bytes has/resurrectors/LG_RD6100_init.has | Bin 0 -> 644 bytes has/resurrectors/LG_SH860_init.has | Bin 0 -> 2372 bytes has/resurrectors/LG_SU630_init.has | Bin 0 -> 3232 bytes has/resurrectors/LG_TD636_init.has | Bin 0 -> 624 bytes has/resurrectors/LG_VM265_init.has | Bin 0 -> 2216 bytes has/resurrectors/MDM6600_init.has | Bin 0 -> 48 bytes has/resurrectors/MDM8200_init.has | Bin 0 -> 500 bytes has/resurrectors/MSM6550_w51h_init.has | Bin 0 -> 480 bytes has/resurrectors/MSM6XXX_L06_D02_init.has | Bin 0 -> 384 bytes has/resurrectors/MSM7225A_L52_D08_init.has | Bin 0 -> 336 bytes .../MSM7227_L41_D08_ONENAND_4K_init.has | Bin 0 -> 312 bytes .../MSM7227_L41_D08_ONENAND_init.has | Bin 0 -> 300 bytes has/resurrectors/MSM7XXX_L41_D04_init.has | Bin 0 -> 204 bytes has/resurrectors/MSM7XXX_L41_D08_init.has | Bin 0 -> 204 bytes has/resurrectors/Micromax_A87_init.has | Bin 0 -> 2384 bytes has/resurrectors/Micromax_C100_init.has | Bin 0 -> 640 bytes .../Micromax_C111_QSC1100_init.has | Bin 0 -> 640 bytes .../Micromax_C111_QSC6010_init.has | Bin 0 -> 212 bytes has/resurrectors/Motorola_W150i_init.has | Bin 0 -> 540 bytes has/resurrectors/Motorola_W200_init.has | Bin 0 -> 540 bytes has/resurrectors/Motorola_W210_init.has | Bin 0 -> 588 bytes has/resurrectors/Olive_C2110_init.has | Bin 0 -> 212 bytes has/resurrectors/PXA3XX_NAND_init.has | Bin 0 -> 1324 bytes has/resurrectors/Pantech_UM150_init.has | Bin 0 -> 1384 bytes has/resurrectors/Pantech_UM175_init.has | Bin 0 -> 1464 bytes has/resurrectors/QSC1100_X14_NOR_init.has | Bin 0 -> 640 bytes has/resurrectors/QSC60XX_L18_D08_NOR_init.has | Bin 0 -> 212 bytes has/resurrectors/QSC60XX_L20_D08_NOR_init.has | Bin 0 -> 212 bytes has/resurrectors/QSC60XX_L24_D08_NOR_init.has | Bin 0 -> 212 bytes .../QSC6XXX_L24_D08_ONENAND_init.has | Bin 0 -> 276 bytes .../QSC6XXX_L32_D08_BS0006_init.has | Bin 0 -> 276 bytes has/resurrectors/QSC6XXX_L32_D08_init.has | Bin 0 -> 276 bytes .../QSC6XXX_L36_D08_BS0006_init.has | Bin 0 -> 276 bytes has/resurrectors/QSC6XXX_L36_D08_init.has | Bin 0 -> 276 bytes has/resurrectors/QSD8XXX_L41_D04_init.has | Bin 0 -> 204 bytes .../Qualcomm_ThinkPadGobi2000_init.has | Bin 0 -> 1512 bytes .../Qualcomm_ThinkPadGobi3000_init.has | Bin 0 -> 48 bytes has/resurrectors/Samsung_A900_init.has | Bin 0 -> 1460 bytes has/resurrectors/Samsung_B119_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B139_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B159_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B209_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B219_init.has | Bin 0 -> 640 bytes has/resurrectors/Samsung_B259_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B2710_init.has | Bin 0 -> 1160 bytes has/resurrectors/Samsung_B309_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B319_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B339_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B379_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_B619_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_LC11_init.has | Bin 0 -> 400 bytes has/resurrectors/Samsung_M8800_init.has | Bin 0 -> 2024 bytes has/resurrectors/Samsung_S109_init.has | Bin 0 -> 564 bytes has/resurrectors/Samsung_S189_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_S239_init.has | Bin 0 -> 276 bytes has/resurrectors/Samsung_S359_init.has | Bin 0 -> 212 bytes has/resurrectors/Samsung_S3850_init.has | Bin 0 -> 288 bytes has/resurrectors/Samsung_S8000_init.has | Bin 0 -> 664 bytes has/resurrectors/Samsung_W299_init.has | Bin 0 -> 1632 bytes has/resurrectors/Samsung_W629_init.has | Bin 0 -> 1632 bytes has/resurrectors/Samsung_Z240_init.has | Bin 0 -> 2748 bytes has/resurrectors/Samsung_Z500_init.has | Bin 0 -> 3112 bytes has/resurrectors/Samsung_Z540_init.has | Bin 0 -> 2420 bytes has/resurrectors/Samsung_Z630_init.has | Bin 0 -> 1372 bytes has/resurrectors/Samsung_Z650i_init.has | Bin 0 -> 1372 bytes has/resurrectors/Samsung_Z710_init.has | Bin 0 -> 2748 bytes has/resurrectors/Samsung_ZV60_init.has | Bin 0 -> 1668 bytes has/resurrectors/Samsung_i450_PDA_init.has | Bin 0 -> 644 bytes has/resurrectors/Samsung_i740_MDM_init.has | Bin 0 -> 360 bytes has/resurrectors/Samsung_i740_PDA_init.has | Bin 0 -> 1324 bytes has/resurrectors/Samsung_i900_PDA_init.has | Bin 0 -> 864 bytes has/resurrectors/Sungil_SXC1080_init.has | Bin 0 -> 624 bytes has/resurrectors/Unicare_ChivaC2_init.has | Bin 0 -> 212 bytes has/resurrectors/Unicare_UN510BF_init.has | Bin 0 -> 212 bytes has/resurrectors/ZTEC_N600_init.has | Bin 0 -> 972 bytes has/resurrectors/ZTE_AC2746_init.has | Bin 0 -> 2216 bytes has/resurrectors/ZTE_AC2766_init.has | Bin 0 -> 2216 bytes has/resurrectors/ZTE_AC30_init.has | Bin 0 -> 204 bytes has/resurrectors/ZTE_C132_init.has | Bin 0 -> 760 bytes has/resurrectors/ZTE_C335_init.has | Bin 0 -> 212 bytes has/resurrectors/ZTE_C370_init.has | Bin 0 -> 212 bytes has/resurrectors/ZTE_D90_init.has | Bin 0 -> 1632 bytes has/resurrectors/ZTE_F160_init.has | Bin 0 -> 1160 bytes has/resurrectors/ZTE_F280_init.has | Bin 0 -> 212 bytes has/resurrectors/ZTE_F285_init.has | Bin 0 -> 644 bytes has/resurrectors/ZTE_FWPC26_init.has | Bin 0 -> 212 bytes has/resurrectors/ZTE_MF170_init.has | Bin 0 -> 1184 bytes has/resurrectors/ZTE_MF180S_init.has | Bin 0 -> 1644 bytes has/resurrectors/ZTE_MF627_init.has | Bin 0 -> 1380 bytes has/resurrectors/ZTE_R518_init.has | Bin 0 -> 2280 bytes has/resurrectors/ZTE_S100_init.has | Bin 0 -> 644 bytes has/resurrectors/ZTE_S1602_init.has | Bin 0 -> 640 bytes has/resurrectors/ZTE_S160_init.has | Bin 0 -> 640 bytes has/resurrectors/ZTE_S165_init.has | Bin 0 -> 640 bytes has/resurrectors/ZTE_S170_init.has | Bin 0 -> 640 bytes has/resurrectors/ZTE_S183_init.has | Bin 0 -> 760 bytes has/resurrectors/ZTE_S185_init.has | Bin 0 -> 640 bytes has/resurrectors/ZTE_Skate_init.has | Bin 0 -> 2276 bytes has/resurrectors/ZTE_T40_init.has | Bin 0 -> 392 bytes .../custom/LG_VM265_init_small_nand.has | Bin 0 -> 2216 bytes lwmem/lwmem.c | 1439 ----------------- lwmem/lwmem.h | 160 -- lwmem/lwmem_opt.h | 161 -- lwmem/lwmem_opts.h | 44 - main.c | 281 ++-- makefile | 29 +- plat/bcom/bcm2133.c | 21 + plat/default.c | 21 + plat/intel/pxa.c | 21 + plat/nxp/pcf5213.c | 21 + plat/nxp/pnx5230.c | 21 + plat/qcom/gpio/gpio_msm5xxx.c | 134 ++ plat/qcom/gpio/gpio_msm62xx.c | 216 +++ plat/qcom/gpio/gpio_msm6x50.c | 62 + plat/qcom/gpio/gpio_msm7xxx.c | 85 + plat/qcom/gpio/gpio_msm_common.c | 99 ++ plat/qcom/gpio/gpio_msm_common.h | 17 + plat/qcom/gpio/gpio_qsc6xxx.c | 139 ++ plat/qcom/msm3000.c | 156 ++ plat/qcom/msm3100.c | 6 + plat/qcom/msm5100.c | 2 + plat/qcom/msm5500.c | 2 + plat/qcom/msm6000.c | 6 + plat/qcom/msm6050.c | 25 + plat/qcom/msm6100.c | 6 + plat/qcom/msm6200.c | 21 + plat/qcom/msm6250.c | 28 + plat/qcom/msm6500.c | 6 + plat/qcom/msm6550.c | 5 + plat/qcom/msm6800.c | 2 + plat/qcom/msm7200.c | 2 + plat/qcom/qsc1100.c | 15 + plat/qcom/qsc6010.c | 5 + plat/qcom/qsc6055.c | 15 + plat/qcom/qsc6155.c | 9 + plat/qcom/qsc6270.c | 2 + plat/samsung/s3c24xx.c | 21 + plat/samsung/s3c6410.c | 21 + tools/dccdumper.py | 687 ++++++++ 237 files changed, 2574 insertions(+), 2119 deletions(-) create mode 100644 devices/qcom/qsc6055_onenand.c create mode 100644 flash/nand/controller/emp/db3xxx.c create mode 100644 flash/nand/controller/ste/nomadik.c rename has/{msm6050_new/m6050_32mb_3ff.has => generic/MSM6050.has} (100%) rename has/{msm6100/msm6100_nor_rom1_cs1_gp2_cs3_cp15_clk.has => generic/MSM6100_CLK.has} (100%) create mode 100644 has/old_versions/msm6050_new/m6050_32mb_3ff.has rename has/{ => old_versions}/msm6050_new/old/m6050_32mb_3c4.has (100%) rename has/{ => old_versions}/msm6050_new/old/m6050_32mb_3c5.has (100%) rename has/{ => old_versions}/msm6050_new/old/m6050_32mb_3e8.has (100%) rename has/{ => old_versions}/msm6050_new/old/m6050_32mb_3e9.has (100%) rename has/{ => old_versions}/msm6050_new/old/m6050_32mb_3f0.has (100%) rename has/{ => old_versions}/msm6050_new/old/m6050_32mb_3f1.has (100%) rename has/{ => old_versions}/msm6100/msm6100_nor_rom1_cs1_gp2_cs3.has (100%) rename has/{ => old_versions}/msm6100/msm6100_nor_rom1_cs1_gp2_cs3_cp15.has (100%) create mode 100644 has/old_versions/msm6100/msm6100_nor_rom1_cs1_gp2_cs3_cp15_clk.has rename has/{ => old_versions}/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0.has (100%) rename has/{ => old_versions}/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0_cp15.has (100%) rename has/{ => old_versions}/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1.has (100%) rename has/{ => old_versions}/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1_cp15.has (100%) rename has/{ => old_versions}/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0.has (100%) rename has/{ => old_versions}/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0_cp15.has (100%) rename has/{ => old_versions}/old/msm6050_32mb.has (100%) rename has/{ => old_versions}/old/msm6050_8mb.has (100%) create mode 100644 has/resurrectors/Alcatel_C131_init.has create mode 100644 has/resurrectors/Alcatel_OT255C_init.has create mode 100644 has/resurrectors/Anydata_ADU_555C_init.has create mode 100644 has/resurrectors/ESC6XXX_L36_D08_init.has create mode 100644 has/resurrectors/ESM7XXX_L41_D04_init.has create mode 100644 has/resurrectors/HTC_Desire_init.has create mode 100644 has/resurrectors/HTC_DroidEris_init.has create mode 100644 has/resurrectors/Haier_C2010_init.has create mode 100644 has/resurrectors/Haier_C2040_init.has create mode 100644 has/resurrectors/Haier_C2076_init.has create mode 100644 has/resurrectors/Haier_C300_init.has create mode 100644 has/resurrectors/Haier_C3010_init.has create mode 100644 has/resurrectors/Haier_C301R_init.has create mode 100644 has/resurrectors/Haier_C5100_init.has create mode 100644 has/resurrectors/Haier_C6000_init.has create mode 100644 has/resurrectors/Huawei_C2605_init.has create mode 100644 has/resurrectors/Huawei_C2607_init.has create mode 100644 has/resurrectors/Huawei_C2801_init.has create mode 100644 has/resurrectors/Huawei_C2806M_init.has create mode 100644 has/resurrectors/Huawei_C2807_init.has create mode 100644 has/resurrectors/Huawei_C2808_init.has create mode 100644 has/resurrectors/Huawei_C2809_init.has create mode 100644 has/resurrectors/Huawei_C2823_init.has create mode 100644 has/resurrectors/Huawei_C2830_init.has create mode 100644 has/resurrectors/Huawei_C2856_init.has create mode 100644 has/resurrectors/Huawei_C2901M_init.has create mode 100644 has/resurrectors/Huawei_C2905_init.has create mode 100644 has/resurrectors/Huawei_C2906_init.has create mode 100644 has/resurrectors/Huawei_C3200_init.has create mode 100644 has/resurrectors/Huawei_C3500_init.has create mode 100644 has/resurrectors/Huawei_C5005_init.has create mode 100644 has/resurrectors/Huawei_C5100_init.has create mode 100644 has/resurrectors/Huawei_C5589_init.has create mode 100644 has/resurrectors/Huawei_C8500_init.has create mode 100644 has/resurrectors/Huawei_EC1260_init.has create mode 100644 has/resurrectors/Huawei_EC189_init.has create mode 100644 has/resurrectors/Huawei_ETS2205_init.has create mode 100644 has/resurrectors/Huawei_ETS2222_Plus_init.has create mode 100644 has/resurrectors/Huawei_ETS2225_init.has create mode 100644 has/resurrectors/Intex_In50_init.has create mode 100644 has/resurrectors/KDDI_Casio_W21CAII_init.has create mode 100644 has/resurrectors/KDDI_Hitachi_W52H_init.has create mode 100644 has/resurrectors/KDDI_Sanyio_SA002_init.has create mode 100644 has/resurrectors/KDDI_Sharp_W52SH_init.has create mode 100644 has/resurrectors/KDDI_Toshiba_W52T_init.has create mode 100644 has/resurrectors/LG_LS970_init.has create mode 100644 has/resurrectors/LG_LSP450T_init.has create mode 100644 has/resurrectors/LG_LU6200_init.has create mode 100644 has/resurrectors/LG_MX800_init.has create mode 100644 has/resurrectors/LG_P999_CP_init.has create mode 100644 has/resurrectors/LG_RD3000_init.has create mode 100644 has/resurrectors/LG_RD3100_init.has create mode 100644 has/resurrectors/LG_RD3500_init.has create mode 100644 has/resurrectors/LG_RD3510_init.has create mode 100644 has/resurrectors/LG_RD3540_init.has create mode 100644 has/resurrectors/LG_RD3610_init.has create mode 100644 has/resurrectors/LG_RD3640_init.has create mode 100644 has/resurrectors/LG_RD6100_init.has create mode 100644 has/resurrectors/LG_SH860_init.has create mode 100644 has/resurrectors/LG_SU630_init.has create mode 100644 has/resurrectors/LG_TD636_init.has create mode 100644 has/resurrectors/LG_VM265_init.has create mode 100644 has/resurrectors/MDM6600_init.has create mode 100644 has/resurrectors/MDM8200_init.has create mode 100644 has/resurrectors/MSM6550_w51h_init.has create mode 100644 has/resurrectors/MSM6XXX_L06_D02_init.has create mode 100644 has/resurrectors/MSM7225A_L52_D08_init.has create mode 100644 has/resurrectors/MSM7227_L41_D08_ONENAND_4K_init.has create mode 100644 has/resurrectors/MSM7227_L41_D08_ONENAND_init.has create mode 100644 has/resurrectors/MSM7XXX_L41_D04_init.has create mode 100644 has/resurrectors/MSM7XXX_L41_D08_init.has create mode 100644 has/resurrectors/Micromax_A87_init.has create mode 100644 has/resurrectors/Micromax_C100_init.has create mode 100644 has/resurrectors/Micromax_C111_QSC1100_init.has create mode 100644 has/resurrectors/Micromax_C111_QSC6010_init.has create mode 100644 has/resurrectors/Motorola_W150i_init.has create mode 100644 has/resurrectors/Motorola_W200_init.has create mode 100644 has/resurrectors/Motorola_W210_init.has create mode 100644 has/resurrectors/Olive_C2110_init.has create mode 100644 has/resurrectors/PXA3XX_NAND_init.has create mode 100644 has/resurrectors/Pantech_UM150_init.has create mode 100644 has/resurrectors/Pantech_UM175_init.has create mode 100644 has/resurrectors/QSC1100_X14_NOR_init.has create mode 100644 has/resurrectors/QSC60XX_L18_D08_NOR_init.has create mode 100644 has/resurrectors/QSC60XX_L20_D08_NOR_init.has create mode 100644 has/resurrectors/QSC60XX_L24_D08_NOR_init.has create mode 100644 has/resurrectors/QSC6XXX_L24_D08_ONENAND_init.has create mode 100644 has/resurrectors/QSC6XXX_L32_D08_BS0006_init.has create mode 100644 has/resurrectors/QSC6XXX_L32_D08_init.has create mode 100644 has/resurrectors/QSC6XXX_L36_D08_BS0006_init.has create mode 100644 has/resurrectors/QSC6XXX_L36_D08_init.has create mode 100644 has/resurrectors/QSD8XXX_L41_D04_init.has create mode 100644 has/resurrectors/Qualcomm_ThinkPadGobi2000_init.has create mode 100644 has/resurrectors/Qualcomm_ThinkPadGobi3000_init.has create mode 100644 has/resurrectors/Samsung_A900_init.has create mode 100644 has/resurrectors/Samsung_B119_init.has create mode 100644 has/resurrectors/Samsung_B139_init.has create mode 100644 has/resurrectors/Samsung_B159_init.has create mode 100644 has/resurrectors/Samsung_B209_init.has create mode 100644 has/resurrectors/Samsung_B219_init.has create mode 100644 has/resurrectors/Samsung_B259_init.has create mode 100644 has/resurrectors/Samsung_B2710_init.has create mode 100644 has/resurrectors/Samsung_B309_init.has create mode 100644 has/resurrectors/Samsung_B319_init.has create mode 100644 has/resurrectors/Samsung_B339_init.has create mode 100644 has/resurrectors/Samsung_B379_init.has create mode 100644 has/resurrectors/Samsung_B619_init.has create mode 100644 has/resurrectors/Samsung_LC11_init.has create mode 100644 has/resurrectors/Samsung_M8800_init.has create mode 100644 has/resurrectors/Samsung_S109_init.has create mode 100644 has/resurrectors/Samsung_S189_init.has create mode 100644 has/resurrectors/Samsung_S239_init.has create mode 100644 has/resurrectors/Samsung_S359_init.has create mode 100644 has/resurrectors/Samsung_S3850_init.has create mode 100644 has/resurrectors/Samsung_S8000_init.has create mode 100644 has/resurrectors/Samsung_W299_init.has create mode 100644 has/resurrectors/Samsung_W629_init.has create mode 100644 has/resurrectors/Samsung_Z240_init.has create mode 100644 has/resurrectors/Samsung_Z500_init.has create mode 100644 has/resurrectors/Samsung_Z540_init.has create mode 100644 has/resurrectors/Samsung_Z630_init.has create mode 100644 has/resurrectors/Samsung_Z650i_init.has create mode 100644 has/resurrectors/Samsung_Z710_init.has create mode 100644 has/resurrectors/Samsung_ZV60_init.has create mode 100644 has/resurrectors/Samsung_i450_PDA_init.has create mode 100644 has/resurrectors/Samsung_i740_MDM_init.has create mode 100644 has/resurrectors/Samsung_i740_PDA_init.has create mode 100644 has/resurrectors/Samsung_i900_PDA_init.has create mode 100644 has/resurrectors/Sungil_SXC1080_init.has create mode 100644 has/resurrectors/Unicare_ChivaC2_init.has create mode 100644 has/resurrectors/Unicare_UN510BF_init.has create mode 100644 has/resurrectors/ZTEC_N600_init.has create mode 100644 has/resurrectors/ZTE_AC2746_init.has create mode 100644 has/resurrectors/ZTE_AC2766_init.has create mode 100644 has/resurrectors/ZTE_AC30_init.has create mode 100644 has/resurrectors/ZTE_C132_init.has create mode 100644 has/resurrectors/ZTE_C335_init.has create mode 100644 has/resurrectors/ZTE_C370_init.has create mode 100644 has/resurrectors/ZTE_D90_init.has create mode 100644 has/resurrectors/ZTE_F160_init.has create mode 100644 has/resurrectors/ZTE_F280_init.has create mode 100644 has/resurrectors/ZTE_F285_init.has create mode 100644 has/resurrectors/ZTE_FWPC26_init.has create mode 100644 has/resurrectors/ZTE_MF170_init.has create mode 100644 has/resurrectors/ZTE_MF180S_init.has create mode 100644 has/resurrectors/ZTE_MF627_init.has create mode 100644 has/resurrectors/ZTE_R518_init.has create mode 100644 has/resurrectors/ZTE_S100_init.has create mode 100644 has/resurrectors/ZTE_S1602_init.has create mode 100644 has/resurrectors/ZTE_S160_init.has create mode 100644 has/resurrectors/ZTE_S165_init.has create mode 100644 has/resurrectors/ZTE_S170_init.has create mode 100644 has/resurrectors/ZTE_S183_init.has create mode 100644 has/resurrectors/ZTE_S185_init.has create mode 100644 has/resurrectors/ZTE_Skate_init.has create mode 100644 has/resurrectors/ZTE_T40_init.has create mode 100644 has/resurrectors/custom/LG_VM265_init_small_nand.has delete mode 100644 lwmem/lwmem.c delete mode 100644 lwmem/lwmem.h delete mode 100644 lwmem/lwmem_opt.h delete mode 100644 lwmem/lwmem_opts.h create mode 100644 plat/qcom/gpio/gpio_msm5xxx.c create mode 100644 plat/qcom/gpio/gpio_msm62xx.c create mode 100644 plat/qcom/gpio/gpio_msm6x50.c create mode 100644 plat/qcom/gpio/gpio_msm7xxx.c create mode 100644 plat/qcom/gpio/gpio_msm_common.c create mode 100644 plat/qcom/gpio/gpio_msm_common.h create mode 100644 plat/qcom/gpio/gpio_qsc6xxx.c create mode 100644 plat/qcom/msm3100.c create mode 100644 plat/qcom/msm6000.c create mode 100644 plat/qcom/qsc1100.c create mode 100644 plat/qcom/qsc6055.c create mode 100644 tools/dccdumper.py diff --git a/.gitignore b/.gitignore index 661c2fe..d64e1bd 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,7 @@ compress_test.bat build/ dcc_test_* build_script/ -test_emu/ \ No newline at end of file +test_emu/ +*.pyc +dcc_test.py +old_stuff/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 1f2e64c..ecefa00 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -66,7 +66,6 @@ "C_Cpp_Runner.msvcSecureNoWarnings": false, "clangd.fallbackFlags": [ "-I${workspaceRoot}", - "-DDCC_TESTING=1", "-DDCC_BUFFER_SIZE=0x40000" ] } \ No newline at end of file diff --git a/crt.s b/crt.s index ea3f61f..46e7552 100644 --- a/crt.s +++ b/crt.s @@ -14,17 +14,17 @@ /* * Some defines for the program status registers */ - ARM_MODE_USER = 0x10 /* Normal User Mode */ - ARM_MODE_FIQ = 0x11 /* FIQ Fast Interrupts Mode */ - ARM_MODE_IRQ = 0x12 /* IRQ Standard Interrupts Mode */ - ARM_MODE_SVC = 0x13 /* Supervisor Interrupts Mode */ - ARM_MODE_ABORT = 0x17 /* Abort Processing memory Faults Mode */ - ARM_MODE_UNDEF = 0x1B /* Undefined Instructions Mode */ - ARM_MODE_SYS = 0x1F /* System Running in Privileged Operating Mode */ - ARM_MODE_MASK = 0x1F +ARM_MODE_USER = 0x10 /* Normal User Mode */ +ARM_MODE_FIQ = 0x11 /* FIQ Fast Interrupts Mode */ +ARM_MODE_IRQ = 0x12 /* IRQ Standard Interrupts Mode */ +ARM_MODE_SVC = 0x13 /* Supervisor Interrupts Mode */ +ARM_MODE_ABORT = 0x17 /* Abort Processing memory Faults Mode */ +ARM_MODE_UNDEF = 0x1B /* Undefined Instructions Mode */ +ARM_MODE_SYS = 0x1F /* System Running in Privileged Operating Mode */ +ARM_MODE_MASK = 0x1F - I_BIT = 0x80 /* disable IRQ when I bit is set */ - F_BIT = 0x40 /* disable IRQ when I bit is set */ +I_BIT = 0x80 /* disable IRQ when I bit is set */ +F_BIT = 0x40 /* disable IRQ when I bit is set */ /****************************************************************************/ /* Vector table and reset entry */ @@ -47,12 +47,12 @@ _vectors: .global ResetHandler .global ExitFunction - .extern pic_relocate - .global DN_Packet_DCC_WaitForBP #if USE_BREAKPOINTS + .global DN_Packet_DCC_WaitForBP .global DCC_PKT_RW_DATA .global DCC_PKT_RW_SIZE #endif + .extern pic_relocate .extern dcc_main .extern __stack_und_end @@ -60,12 +60,14 @@ _vectors: StartAddress: .word 0xffffffff FlashSize: .word 0x0 PageSize: .word 0xffffffff + /* Loader via H/W BP polling */ DCC_PKT_RW_SIZE: .word 0xffffffff DCC_PKT_RW_DATA: .word 0xffffffff DCC_PKT_HW_BP: .word DN_Packet_DCC_WaitForBP DCC_CANWRITE: .word 0x0 +/* Crash handlers */ UndefHandler: SWIHandler: PAbortHandler: @@ -76,21 +78,14 @@ CrashHandler: b CrashHandler .word CrashHandler +/* DCC info */ +.word __heap_start +.word __heap_end .word __heap_size -.word __stack_end + .asciz "A:DumpNow DCC Loader. (c) 2026 Wrapper.;Compile flags: " ADEFS ";Compile Date: " __DATE__ .align -/* LWMEM info */ -#if HAVE_LWMEM -lwmem_init: - .word __heap_start - .word __heap_size -lwmem_init_end: - .word 0x00000000 - .word 0x00000000 -#endif - /****************************************************************************/ /* Reset handler */ /****************************************************************************/ @@ -110,7 +105,7 @@ ResetHandler: mcr p15, 0, r0, cr1, cr0, 0 #endif - /* TODO: Why is this line necessary */ + /* Needed to flush DCC read buffer */ #if \ ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) \ || ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_7R__) ) @@ -121,6 +116,7 @@ ResetHandler: mrc p14, 0, r0, cr1, cr0, 0 #endif + /* 01 - Initialize stack section */ mov r0, #0 adr r0, _vectors @@ -129,6 +125,7 @@ ResetHandler: bl plat_init + /* 02 - Reset memory */ mov r0, #0 adr r0, _vectors @@ -146,7 +143,6 @@ bss_clear_loop: strne r3, [r1], #+4 bne bss_clear_loop -#if HAVE_LWMEM /* * Clear .heap section */ @@ -159,46 +155,16 @@ heap_clear_loop: cmp r1, r2 strne r3, [r1], #+4 bne heap_clear_loop -#endif - /* - * Jump to main - */ -#if HAVE_LWMEM - /* - * Setup lwmem memory manager - */ - mov r0, #0 - adr r0, lwmem_init - ldr r0, [r0] - - mov r1, #0 - adr r1, _vectors - - add r0, r1 - - mov r1, #0 - adr r1, lwmem_init - - str r0, [r1] - - mov r0, #0 - adr r0, lwmem_init - bl lwmem_assignmem -#endif - - /* - * Start - */ - - /* Setup PIC */ + /* 03 - Code initialize */ mov r0, #0 adr r0, _vectors + /* Setup PIC */ ldr r1, =_reloc_start - add r1, r0 - ldr r2, =_reloc_end + + add r1, r0 add r2, r0 ldr r3, =edata @@ -209,7 +175,7 @@ heap_clear_loop: ldr r9, =_sgot add r9, r0 - /* Jump to Main */ + /* 04 - Jump to Main */ mov r0, #0 adr r0, StartAddress ldr r0, [r0] diff --git a/dcc/bitutils.c b/dcc/bitutils.c index 661012d..40ebaae 100644 --- a/dcc/bitutils.c +++ b/dcc/bitutils.c @@ -1,4 +1,4 @@ -#include "dcc/plat.h" +#include "plat.h" #include "bitutils.h" /* diff --git a/dcc/bitutils.h b/dcc/bitutils.h index e1a0b41..f55cf11 100644 --- a/dcc/bitutils.h +++ b/dcc/bitutils.h @@ -2,7 +2,7 @@ #include #define BIT_SET(src, bm, value) (((src) & ~((bm).bit_mask << (bm).bit_pos)) | (((value) & (bm).bit_mask) << (bm).bit_pos)) -#define BIT_SET_VAR(src, bm, value) (src) = BIT_SET(src, bm, value); +#define BIT_SET_VAR(src, bm, value) (src) = BIT_SET(src, bm, value) typedef struct { uint32_t bit_pos; diff --git a/dcc/dn_dcc_proto.c b/dcc/dn_dcc_proto.c index 937a19f..2c8c4a1 100644 --- a/dcc/dn_dcc_proto.c +++ b/dcc/dn_dcc_proto.c @@ -92,7 +92,6 @@ void DN_RLE_FindMatch(uint8_t *src, uint32_t *RAW_Count, uint32_t *RLE_Count, ui uint32_t runCount = 1; uint32_t pReadSize = size < 0x7fff ? size : 0x7fff; uint32_t rawCount = 0; - while (pReadOffset < (pReadSize - 1)) { wdog_reset(); @@ -259,24 +258,13 @@ uint32_t DN_Packet_Compress3(uint8_t *src, uint32_t size, uint8_t *dest) } #endif -uint32_t DN_Packet_CompressNone(uint8_t *src, uint32_t size, uint8_t *dest) -{ - uint32_t MAGIC = CMD_WRITE_COMP_NONE; - uint32_t outOffset = 4; - - memcpy(dest, &MAGIC, 4); - memcpy(dest + 4, src, size); - outOffset += size; - - return ALIGN4(outOffset); -} - /* 03 - DCC Packets */ #ifdef DCC_TESTING uint32_t DN_Packet_DCC_Send(uint32_t data) { printf("DCC SEND: 0x%08X\n", data); return 1; }; + uint32_t DN_Packet_DCC_Read() { uint32_t count = 0; uint32_t dat_read; @@ -331,6 +319,7 @@ uint32_t DN_Packet_DCC_Read(void) { #define DCC_WRITE(x) asm volatile ("mcr p14, 0, %0, C1, C0" : : "r" (x)) #define DCC_READ(x) asm volatile ("mrc p14, 0, %0, C1, C0" : "=r" (x) :) #endif + uint32_t DN_Packet_DCC_Send(uint32_t data) { volatile uint32_t dcc_reg; @@ -394,6 +383,32 @@ void DN_Packet_Send_One(uint32_t data) { #endif } +void DN_Packet_Send_DirectUncompressed(uint8_t *src, uint32_t size) { + if (size & 3) return; // Must be dword aligned + uint32_t MAGIC = CMD_WRITE_COMP_NONE; + + uint32_t checksum = DN_Calculate_CRC32(0xffffffff, (uint8_t *)&MAGIC, 4); + checksum = DN_Calculate_CRC32(checksum, src, size); + +#if USE_BREAKPOINTS + DN_Packet_DCC_ResetBPP(cmdBuf); +#endif + + DN_Packet_DCC_Send((size >> 2) + 1); + DN_Packet_DCC_Send(CMD_WRITE_COMP_NONE); + + for (uint32_t src_offset = 0; src_offset < (size >> 2); src_offset++) { + wdog_reset(); + DN_Packet_DCC_Send(((uint32_t *)(src))[src_offset]); + } + + DN_Packet_DCC_Send(checksum); + +#if USE_BREAKPOINTS + cmdReadBuf = DN_Packet_DCC_WaitForBP(); +#endif +} + void DN_Packet_Read(uint8_t *dest, uint32_t size) { if (size & 3) return; // Must be dword aligned @@ -404,6 +419,61 @@ void DN_Packet_Read(uint8_t *dest, uint32_t size) { } /* 04 - DCC Buffer */ +static uint32_t dcc_temp_read; +static uint8_t dcc_buf_offset; + +void DN_Packet_DCC_Read_Buffer_Reset(void) { + dcc_temp_read = 0; + dcc_buf_offset = 0; +} + +static inline uint8_t DN_Packet_DCC_Read_Buffer8(void) { + if (!dcc_buf_offset) dcc_temp_read = DN_Packet_DCC_Read(); + uint8_t temp = dcc_temp_read & 0xff; + + dcc_temp_read >>= 8; + dcc_buf_offset = (dcc_buf_offset + 1) & 3; + return temp; +} + +static inline uint16_t DN_Packet_DCC_Read_Buffer16(void) { + return DN_Packet_DCC_Read_Buffer8() | DN_Packet_DCC_Read_Buffer8() << 8; +} + +static inline uint32_t DN_Packet_DCC_Read_Buffer32(void) { + return DN_Packet_DCC_Read_Buffer16() | DN_Packet_DCC_Read_Buffer16() << 16; +} + +void DN_Packet_DCC_ReadCompressed(uint8_t *dest, uint32_t size) { + uint32_t inOffset = 0; + uint32_t outOffset = 0; + + DN_Packet_DCC_Read_Buffer_Reset(); + + while (inOffset < size) { + uint16_t flag = DN_Packet_DCC_Read_Buffer16(); + uint16_t count = flag & 0x7fff; + + if (flag & 0x8000) { + inOffset += 3; + uint8_t data = DN_Packet_DCC_Read_Buffer8(); + + memset(dest + outOffset, data, count); + outOffset += count; + // do { + // dest[outOffset++] = data; + // } while (count--); + } else { + inOffset += 2 + count; + + do { + dest[outOffset++] = DN_Packet_DCC_Read_Buffer8(); + } while (--count); + } + } +} + +#if 0 static uint32_t temp_buf; static uint8_t temp_buf_offset; static uint32_t checksum; @@ -634,33 +704,7 @@ static inline uint16_t DN_Packet_DCC_Read_Buffer16(void) { static inline uint32_t DN_Packet_DCC_Read_Buffer32(void) { return DN_Packet_DCC_Read_Buffer16() | DN_Packet_DCC_Read_Buffer16() << 16; } - -void DN_Packet_DCC_ReadCompressed(uint8_t *dest, uint32_t size) { - uint32_t inOffset = 0; - uint32_t outOffset = 0; - - DN_Packet_DCC_Read_Buffer_Reset(); - - while (inOffset < size) { - uint16_t flag = DN_Packet_DCC_Read_Buffer16(); - uint16_t count = flag & 0x7fff; - - if (flag & 0x8000) { - inOffset += 3; - uint8_t data = DN_Packet_DCC_Read_Buffer8(); - - do { - dest[outOffset++] = data; - } while (count--); - } else { - inOffset += 2 + count; - - do { - dest[outOffset++] = DN_Packet_DCC_Read_Buffer8(); - } while (count--); - } - } -} +#endif /* 05 - Utilities */ uint32_t DN_Log2(uint32_t value) diff --git a/dcc/dn_dcc_proto.h b/dcc/dn_dcc_proto.h index e6f4616..1774ddf 100644 --- a/dcc/dn_dcc_proto.h +++ b/dcc/dn_dcc_proto.h @@ -35,7 +35,7 @@ typedef enum { } Configuration; typedef struct { - DCC_RETURN (*initialize)(DCCMemory *mem, uint32_t offset); + DCC_RETURN (*initialize)(DCCMemory *mem, uint32_t offset, uint32_t page_size); DCC_RETURN (*read)(DCCMemory *mem, uint32_t offset, uint32_t size, uint8_t *dest, uint32_t *dest_size); DCC_RETURN (*write)(DCCMemory *mem, uint32_t offset, uint8_t *src, uint32_t size); DCC_RETURN (*erase)(DCCMemory *mem, uint32_t offset, uint32_t size); @@ -123,8 +123,10 @@ typedef struct { #define DCC_FLASH_NOENT 0x37 // Flash with this ID is not probed/not found #define DCC_WPROT_ERROR 0x3C // Read-only memory or Write/Erase routines not implemented #define DCC_NOMEM_ERROR 0x3D // Not enough memory +#define DCC_E_INSUFF_DATA 0x3E // Insufficient data // Functions +// 01 - Compress uint32_t DN_Packet_Compress(uint8_t *src, uint32_t size, uint8_t *dest); #if HAVE_MINILZO uint32_t DN_Packet_Compress2(uint8_t *src, uint32_t size, uint8_t *dest); @@ -132,18 +134,31 @@ uint32_t DN_Packet_Compress2(uint8_t *src, uint32_t size, uint8_t *dest); #if HAVE_LZ4 uint32_t DN_Packet_Compress3(uint8_t *src, uint32_t size, uint8_t *dest); #endif -uint32_t DN_Packet_CompressNone(uint8_t *src, uint32_t size, uint8_t *dest); -uint32_t DN_Calculate_CRC32(uint32_t crc, uint8_t* data, uint32_t len); +// 02 - DCC main routines uint32_t DN_Packet_DCC_Send(uint32_t data); uint32_t DN_Packet_DCC_Read(void); +// 03 - DCC Write routines void DN_Packet_Send(uint8_t *src, uint32_t size); void DN_Packet_Send_One(uint32_t data); +void DN_Packet_Send_DirectUncompressed(uint8_t *src, uint32_t size); +// 04 - DCC Read routines void DN_Packet_Read(uint8_t *dest, uint32_t size); +void DN_Packet_DCC_ReadCompressed(uint8_t *dest, uint32_t size); +uint32_t DN_Calculate_CRC32(uint32_t crc, uint8_t* data, uint32_t len); +// 05 - Utilities uint32_t DN_Log2(uint32_t value); void DN_WaitUSec(uint32_t usec); -void DN_Packet_WriteDirectCompressed(uint8_t *src, uint32_t size); -void DN_Packet_WriteDirect(uint8_t *src, uint32_t size); -void DN_Packet_DCC_ReadCompressed(uint8_t *dest, uint32_t size); +// 06 - Unused +// void DN_Packet_WriteDirectCompressed(uint8_t *src, uint32_t size); +// void DN_Packet_WriteDirect(uint8_t *src, uint32_t size); +// void DN_Packet_DCC_ReadCompressed(uint8_t *dest, uint32_t size); // Watchdog -extern void wdog_reset(void); \ No newline at end of file +extern void wdog_reset(void); + +// GPIO +extern uint8_t plat_gpio_read(uint32_t pin); +extern void plat_gpio_write(uint32_t pin, uint8_t active); +extern void plat_gpio_set_dir(uint32_t pin, GPIODirection dir); +extern void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func); +extern void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull); \ No newline at end of file diff --git a/dcc/pic.c b/dcc/pic.c index 595ea10..f21de59 100644 --- a/dcc/pic.c +++ b/dcc/pic.c @@ -5,10 +5,10 @@ typedef struct { uint32_t type; } RELOC; -void pic_relocate(uint32_t base, uint32_t reloc_cur, uint32_t reloc_end, uint32_t data_offs) { +void pic_relocate(uint32_t base, RELOC *reloc_cur, RELOC *reloc_end, uint32_t data_end_offset) { while (reloc_cur < reloc_end) { - RELOC *rel = (RELOC *)(reloc_cur); - if (rel->type == 0x17 && rel->offset >= data_offs) *((uint32_t *)(base + rel->offset)) += base; - reloc_cur += sizeof(RELOC); + RELOC *rel = reloc_cur++; + if (rel->type == 0x17 && rel->offset >= data_end_offset) + *((uint32_t *)(base + rel->offset)) += base; } } \ No newline at end of file diff --git a/dcc/plat.h b/dcc/plat.h index 294f866..f7c5e98 100644 --- a/dcc/plat.h +++ b/dcc/plat.h @@ -2,6 +2,18 @@ #include #include #include +#include "bitutils.h" + +typedef enum { + GPIO_INPUT, + GPIO_OUTPUT +} GPIODirection; + +typedef enum { + GPIO_PULL_DISABLED, + GPIO_PULL_UP, + GPIO_PULL_DOWN +} GPIOPullType; #ifdef DCC_TESTING #include @@ -18,7 +30,9 @@ extern void *PLAT_MEMCPY(void *dest, const void *src, size_t n); #define INT_MEMCPY memcpy #define PLAT_SNPRINTF snprintf #else -#include "dcc/lwprintf.h" +#include "lwprintf.h" + +#define SET_BIT_BM_BP(val, bit_mask, bit_pos) (val) = ((val) & ~((bit_mask) << (bit_pos))) | (((val) & (bit_mask)) << (bit_pos)) #define WRITE_U8(_reg, _val) (*((volatile uint8_t *)(_reg)) = (_val)) #define WRITE_U16(_reg, _val) (*((volatile uint16_t *)(_reg)) = (_val)) diff --git a/devices/qcom/qsc6055_onenand.c b/devices/qcom/qsc6055_onenand.c new file mode 100644 index 0000000..0a5dd33 --- /dev/null +++ b/devices/qcom/qsc6055_onenand.c @@ -0,0 +1,8 @@ +#include "dcc/dn_dcc_proto.h" +#include "flash/onenand/onenand.h" + +Device devices[] = { + {&onenand_controller, 0x38000000}, + // {&nand_controller, 0x0}, + {0x0, 0x0} +}; \ No newline at end of file diff --git a/flash/cfi/cfi.c b/flash/cfi/cfi.c index c940ec3..aedbebb 100644 --- a/flash/cfi/cfi.c +++ b/flash/cfi/cfi.c @@ -51,7 +51,7 @@ DCC_RETURN CFI_Query(uint32_t offset, uint32_t type, CFIQuery *qry) { return DCC_OK; } -DCC_RETURN CFI_Probe(DCCMemory *mem, uint32_t offset) { +DCC_RETURN CFI_Probe(DCCMemory *mem, uint32_t offset, uint32_t page_size) { uint32_t CFI_Type; CFIQuery qry = { 0 }; DCC_RETURN ret_code; diff --git a/flash/mmap/mmap.c b/flash/mmap/mmap.c index 4cb5248..445b7c5 100644 --- a/flash/mmap/mmap.c +++ b/flash/mmap/mmap.c @@ -3,7 +3,7 @@ #include "mmap.h" #include "dcc/dn_dcc_proto.h" -DCC_RETURN Memdump_Probe(DCCMemory *mem, uint32_t offset) { +DCC_RETURN Memdump_Probe(DCCMemory *mem, uint32_t offset, uint32_t page_size) { mem->manufacturer = MEMDUMP_MFR; mem->device_id = MEMDUMP_DEVID; mem->bit_width = 16; diff --git a/flash/nand/controller/emp/db3xxx.c b/flash/nand/controller/emp/db3xxx.c new file mode 100644 index 0000000..9b810c8 --- /dev/null +++ b/flash/nand/controller/emp/db3xxx.c @@ -0,0 +1,182 @@ +/* Nand controller template */ +#include "../controller.h" +#include "dcc/dn_dcc_proto.h" +#include "dcc/plat.h" + +static uint8_t bits; + +void inline NAND_Ctrl_Command_Write(uint8_t cmd) { + // Write command routines + WRITE_U8(0x80010000, cmd); + wdog_reset(); +} + +void inline NAND_Ctrl_Address_Write(uint8_t addr) { + // Write address routines + WRITE_U8(0x80020000, addr); + wdog_reset(); +} + +uint16_t inline NAND_Ctrl_Data_Read() { + // Data read routines + wdog_reset(); + return bits == 16 ? READ_U16(0x80000000) : READ_U8(0x80000000); // TODO: 32-bit NAND data read +} + +void inline NAND_Ctrl_Wait_Ready() { + // Busy assert routines + do { wdog_reset(); } while (READ_U32(0x9F8000C8) & 2) ; +} + +uint32_t inline NAND_Ctrl_Check_Status() { + return 1; +} + +DCC_RETURN NAND_Ctrl_Probe(DCCMemory *mem) { + wdog_reset(); + mem->type = MEMTYPE_NONE; + + NAND_Ctrl_Command_Write(NAND_CMD_RESET); + NAND_Ctrl_Wait_Ready(); + + NAND_Ctrl_Command_Write(NAND_CMD_READID); + NAND_Ctrl_Address_Write(0x0); + NAND_Ctrl_Wait_Ready(); + + uint8_t mfr_id = (uint8_t)NAND_Ctrl_Data_Read(); + uint8_t dev_id = (uint8_t)NAND_Ctrl_Data_Read(); + + for (int i = 0; flash_ids[i].dev_id; i++) { + if (dev_id == (uint8_t)flash_ids[i].dev_id) { + mem->device_id = dev_id; + mem->manufacturer = mfr_id; + mem->bit_width = flash_ids[i].bits; + mem->block_size = flash_ids[i].block_size; + mem->page_size = flash_ids[i].page_size; + mem->size = flash_ids[i].chip_size; + mem->type = MEMTYPE_NAND; + break; + } + } + + if (mem->type != MEMTYPE_NAND) return DCC_PROBE_ERROR; + + if (mem->page_size == 0) { + NAND_Ctrl_Data_Read(); + uint8_t extra_id = (uint8_t)NAND_Ctrl_Data_Read(); + + mem->page_size = 1 << (10 + (extra_id & 3)); + + switch ((extra_id >> 4) & 3) { + case 0: + mem->block_size = 64 << 10; + break; + case 1: + mem->block_size = 128 << 10; + break; + case 2: + mem->block_size = 256 << 10; + break; + case 3: + mem->block_size = 512 << 10; + break; + } + + mem->device_id |= extra_id << 8; + } + + bits = mem->bit_width; + + NAND_Ctrl_Command_Write(NAND_CMD_RESET); + NAND_Ctrl_Wait_Ready(); + return DCC_OK; +} + +DCC_RETURN NAND_Ctrl_Read(DCCMemory *mem, uint8_t *page_buf, uint8_t *spare_buf, uint32_t page) { + wdog_reset(); + + if (mem->page_size <= 512) { + NAND_Ctrl_Command_Write(NAND_CMD_READ0); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x02000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < 0x100; i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(page_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + page_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + + if (mem->bit_width == 8) { + NAND_Ctrl_Command_Write(NAND_CMD_READ1); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x02000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < 0x100; i++) { + wdog_reset(); + page_buf[i + 0x100] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + + NAND_Ctrl_Command_Write(NAND_CMD_READOOB); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x02000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < (0x10 >> (mem->bit_width >> 4)); i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(spare_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + spare_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + } else { + NAND_Ctrl_Command_Write(NAND_CMD_READ0); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x08000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Command_Write(NAND_CMD_READSTART); + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < (mem->page_size >> (mem->bit_width >> 4)); i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(page_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + page_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + + for (int i = 0; i < ((mem->page_size >> 5) >> (mem->bit_width >> 4)); i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(spare_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + spare_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + } + + return DCC_OK; +} \ No newline at end of file diff --git a/flash/nand/controller/qcom/qsc6270.c b/flash/nand/controller/qcom/qsc6270.c index f0b73c3..a620f5a 100644 --- a/flash/nand/controller/qcom/qsc6270.c +++ b/flash/nand/controller/qcom/qsc6270.c @@ -2,5 +2,6 @@ #define REGS_INIT1 0xaad4001a #define REGS_INIT2 0x44747e // OneNAND is handled by default onenand controller at 0x38000000 (Must not set NAND_BUS_ENA at EBI2_CFG; 0x80028000, Corresponds to EBI2_CS0_N) +// for NAND, EBI2_CS1_N is always connected and NAND_BUS_ENA is set (by default, this is on) #include "msm7200.c" \ No newline at end of file diff --git a/flash/nand/controller/ste/nomadik.c b/flash/nand/controller/ste/nomadik.c new file mode 100644 index 0000000..55c1530 --- /dev/null +++ b/flash/nand/controller/ste/nomadik.c @@ -0,0 +1,180 @@ +/* Nand controller template */ +#include "../controller.h" +#include "dcc/plat.h" + +#define NAND_BASE 0x40000000 +static uint8_t counter; + +void inline NAND_Ctrl_Command_Write(uint8_t cmd) { + // Write command routines + WRITE_U8(NAND_BASE | 0x1000000, cmd); + wdog_reset(); +} + +void inline NAND_Ctrl_Address_Write(uint8_t addr) { + // Write address routines + WRITE_U8(NAND_BASE | ((counter++ >= 4) ? 0x9000000 : 0x800000), addr); + wdog_reset(); +} + +uint16_t inline NAND_Ctrl_Data_Read() { + // Data read routines + wdog_reset(); + return READ_U8(NAND_BASE); +} + +void inline NAND_Ctrl_Wait_Ready() { + // Busy assert routines + wdog_reset(); +} + +uint32_t inline NAND_Ctrl_Check_Status() { + return 1; +} + +DCC_RETURN NAND_Ctrl_Probe(DCCMemory *mem) { + wdog_reset(); + mem->type = MEMTYPE_NONE; + + NAND_Ctrl_Command_Write(NAND_CMD_RESET); + NAND_Ctrl_Wait_Ready(); + + NAND_Ctrl_Command_Write(NAND_CMD_READID); + NAND_Ctrl_Address_Write(0x0); + NAND_Ctrl_Wait_Ready(); + + uint8_t mfr_id = (uint8_t)NAND_Ctrl_Data_Read(); + uint8_t dev_id = (uint8_t)NAND_Ctrl_Data_Read(); + + for (int i = 0; flash_ids[i].dev_id; i++) { + if (dev_id == (uint8_t)flash_ids[i].dev_id) { + mem->device_id = dev_id; + mem->manufacturer = mfr_id; + mem->bit_width = flash_ids[i].bits; + mem->block_size = flash_ids[i].block_size; + mem->page_size = flash_ids[i].page_size; + mem->size = flash_ids[i].chip_size; + mem->type = MEMTYPE_NAND; + break; + } + } + + if (mem->type != MEMTYPE_NAND) return DCC_PROBE_ERROR; + + if (mem->page_size == 0) { + NAND_Ctrl_Data_Read(); + uint8_t extra_id = (uint8_t)NAND_Ctrl_Data_Read(); + + mem->page_size = 1 << (10 + (extra_id & 3)); + + switch ((extra_id >> 4) & 3) { + case 0: + mem->block_size = 64 << 10; + break; + case 1: + mem->block_size = 128 << 10; + break; + case 2: + mem->block_size = 256 << 10; + break; + case 3: + mem->block_size = 512 << 10; + break; + } + + mem->device_id |= extra_id << 8; + } + + NAND_Ctrl_Command_Write(NAND_CMD_RESET); + NAND_Ctrl_Wait_Ready(); + return DCC_OK; +} + +DCC_RETURN NAND_Ctrl_Read(DCCMemory *mem, uint8_t *page_buf, uint8_t *spare_buf, uint32_t page) { + wdog_reset(); + + if (mem->page_size <= 512) { + NAND_Ctrl_Command_Write(NAND_CMD_READ0); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x02000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < 0x100; i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(page_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + page_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + + if (mem->bit_width == 8) { + NAND_Ctrl_Command_Write(NAND_CMD_READ1); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x02000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < 0x100; i++) { + wdog_reset(); + page_buf[i + 0x100] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + + NAND_Ctrl_Command_Write(NAND_CMD_READOOB); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x02000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < (0x10 >> (mem->bit_width >> 4)); i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(spare_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + spare_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + } else { + NAND_Ctrl_Command_Write(NAND_CMD_READ0); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(0); + NAND_Ctrl_Address_Write(page); + NAND_Ctrl_Address_Write(page >> 8); + if (mem->size > 0x08000000) NAND_Ctrl_Address_Write(page >> 16); + + NAND_Ctrl_Command_Write(NAND_CMD_READSTART); + NAND_Ctrl_Wait_Ready(); + if (!NAND_Ctrl_Check_Status()) return DCC_READ_ERROR; + + for (int i = 0; i < (mem->page_size >> (mem->bit_width >> 4)); i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(page_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + page_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + + for (int i = 0; i < ((mem->page_size >> 5) >> (mem->bit_width >> 4)); i++) { + wdog_reset(); + if (mem->bit_width == 16) { + ((uint16_t *)(spare_buf))[i] = NAND_Ctrl_Data_Read(); + } else { + spare_buf[i] = (uint8_t)NAND_Ctrl_Data_Read(); + } + } + } + + return DCC_OK; +} \ No newline at end of file diff --git a/flash/nand/nand.c b/flash/nand/nand.c index 717e62b..aaee10d 100644 --- a/flash/nand/nand.c +++ b/flash/nand/nand.c @@ -60,7 +60,7 @@ const nand_info flash_ids[] = { {0, 0, 0, 0, 0} }; -DCC_RETURN NAND_Probe(DCCMemory *mem, uint32_t offset) { +DCC_RETURN NAND_Probe(DCCMemory *mem, uint32_t offset, uint32_t page_size) { return NAND_Ctrl_Probe(mem); } diff --git a/flash/onenand/controller/controller.h b/flash/onenand/controller/controller.h index 2b7fad9..cf33e5f 100644 --- a/flash/onenand/controller/controller.h +++ b/flash/onenand/controller/controller.h @@ -61,7 +61,7 @@ // Single register R/W int OneNAND_Ctrl_Wait_Ready(DCCMemory *mem, uint16_t flag); -void OneNAND_Pre_Initialize(DCCMemory *mem, uint32_t offset); +void OneNAND_Pre_Initialize(DCCMemory *mem, uint32_t offset, uint32_t page_size); void OneNAND_Ctrl_Reg_Write(DCCMemory *mem, uint16_t reg, uint16_t data, uint8_t wait_interrupt); uint16_t OneNAND_Ctrl_Reg_Read(DCCMemory *mem, uint16_t reg); void OneNAND_Ctrl_Get_Data(DCCMemory *mem, uint8_t *page_buf, uint8_t *spare_buf, uint32_t page_size, uint32_t spare_size); diff --git a/flash/onenand/controller/default.c b/flash/onenand/controller/default.c index d88acb9..385b1a4 100644 --- a/flash/onenand/controller/default.c +++ b/flash/onenand/controller/default.c @@ -5,10 +5,14 @@ #include #include "dcc/dn_dcc_proto.h" -void OneNAND_Pre_Initialize(DCCMemory *mem, uint32_t offset) { +void OneNAND_Pre_Initialize(DCCMemory *mem, uint32_t offset, uint32_t page_size) { // Initialize routines mem->base_offset = offset; - mem->page_size = 0x800; + if (page_size != 0x800 && page_size != 0x1000) { + page_size = 0x800; + } + + mem->page_size = page_size; OneNAND_Ctrl_Reg_Write(mem, O1N_REG_SYS_CFG1, 0x40c0, 0); diff --git a/flash/onenand/controller/qcom/msm7200.c b/flash/onenand/controller/qcom/msm7200.c index af59da0..d4cd73b 100644 --- a/flash/onenand/controller/qcom/msm7200.c +++ b/flash/onenand/controller/qcom/msm7200.c @@ -48,10 +48,14 @@ int OneNAND_Ctrl_Wait_Ready(DCCMemory *mem, uint16_t flag) { return 1; } -void OneNAND_Pre_Initialize(DCCMemory *mem, uint32_t offset) { +void OneNAND_Pre_Initialize(DCCMemory *mem, uint32_t offset, uint32_t page_size) { // Initialize routines mem->base_offset = offset; - mem->page_size = 0x800; + if (page_size != 0x800 && page_size != 0x1000) { + page_size = 0x800; + } + + mem->page_size = page_size; WRITE_U32(REGS_START + MSM7200_REG_DEV0_CFG0, 0xaad4001a); WRITE_U32(REGS_START + MSM7200_REG_DEV0_CFG1, 0x2101bd); diff --git a/flash/onenand/onenand.c b/flash/onenand/onenand.c index c4ffed7..b6ac0fa 100644 --- a/flash/onenand/onenand.c +++ b/flash/onenand/onenand.c @@ -2,9 +2,9 @@ #include "dcc/dn_dcc_proto.h" #include "controller/controller.h" -uint32_t OneNAND_Probe(DCCMemory *mem, uint32_t offset) { +uint32_t OneNAND_Probe(DCCMemory *mem, uint32_t offset, uint32_t page_size) { wdog_reset(); - OneNAND_Pre_Initialize(mem, offset); + OneNAND_Pre_Initialize(mem, offset, page_size); if (!OneNAND_Ctrl_Wait_Ready(mem, 0x8000)) return DCC_PROBE_ERROR; @@ -28,9 +28,9 @@ uint32_t OneNAND_Read_Upper(DCCMemory *mem, uint8_t *page_buf, uint8_t *spare_bu wdog_reset(); OneNAND_Ctrl_Reg_Write(mem, O1N_REG_ECC_STATUS, 0x0, 0); - uint32_t density = 2 << ((mem->page_size == 4096 ? 4 : 3) + ((mem->device_id >> 4) & 0xf)); - uint32_t addr1_mask = ((mem->device_id & 8) ? (density << 2) : (density << 3)) - 1; - uint32_t ddp_access = (mem->device_id & 8) && ((page >> 6) >= (density << 2)); + uint32_t density_n = 2 << (3 + ((mem->device_id >> 4) & 0xf)); + uint32_t addr1_mask = ((mem->device_id & 8) ? (density_n << 2) : (density_n << 3)) - 1; + uint32_t ddp_access = (mem->device_id & 8) && ((page >> 6) >= (density_n << 2)); OneNAND_Ctrl_Reg_Write_Queue(mem, O1N_REG_START_ADDRESS8, (page & 63) << 2); OneNAND_Ctrl_Reg_Write_Queue(mem, O1N_REG_START_ADDRESS1, (ddp_access ? 0x8000 : 0) | ((page >> 6) & addr1_mask)); diff --git a/flash/superand/superand.c b/flash/superand/superand.c index ee2e17f..384be7f 100644 --- a/flash/superand/superand.c +++ b/flash/superand/superand.c @@ -22,7 +22,7 @@ const superand_info flash_ids[] = { {0x5b, 0x200, 0x04000000, 0x4000, 16}, }; -DCC_RETURN SuperAND_Probe(DCCMemory *mem, uint32_t offset) { +DCC_RETURN SuperAND_Probe(DCCMemory *mem, uint32_t offset, uint32_t page_size) { return SuperAND_Ctrl_Probe(mem); } diff --git a/has/msm6050_new/m6050_32mb_3ff.has b/has/generic/MSM6050.has similarity index 100% rename from has/msm6050_new/m6050_32mb_3ff.has rename to has/generic/MSM6050.has diff --git a/has/msm6100/msm6100_nor_rom1_cs1_gp2_cs3_cp15_clk.has b/has/generic/MSM6100_CLK.has similarity index 100% rename from has/msm6100/msm6100_nor_rom1_cs1_gp2_cs3_cp15_clk.has rename to has/generic/MSM6100_CLK.has diff --git a/has/old_versions/msm6050_new/m6050_32mb_3ff.has b/has/old_versions/msm6050_new/m6050_32mb_3ff.has new file mode 100644 index 0000000000000000000000000000000000000000..0979b54d2b849cb84fad47a110e5fcde90238d38 GIT binary patch literal 624 zcmYk)p-uxq5XSMj>%lEeNUk11Nd*FlsHmtS2n2#R!1e)9T+<*bDhWZ7P*I6M;0SNf z1Ox(6f#?H}P&a(v?2y}<{<8Vs-t4xjs>Qanh9Uy0z^_`9X4Sf+*&wmzL8SffMdEql zC43;AjL&|+-KRBdob#+~ zWie*t(YQGJ5Dk8D>yK#P m|CndThfN>OuVddw^Y|Y7LDKJ`*gcus+p==c(n+-`^0f)FEk~lk(dL@6TRRD1`L_#Pzj14!aWki<_QiJw6dUjSqu IU|YZd0F(WHSO5S3 literal 0 HcmV?d00001 diff --git a/has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0.has b/has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0.has similarity index 100% rename from has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0.has rename to has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0.has diff --git a/has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0_cp15.has b/has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0_cp15.has similarity index 100% rename from has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0_cp15.has rename to has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs0_cp15.has diff --git a/has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1.has b/has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1.has similarity index 100% rename from has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1.has rename to has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1.has diff --git a/has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1_cp15.has b/has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1_cp15.has similarity index 100% rename from has/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1_cp15.has rename to has/old_versions/msm6100/old/msm6100_nor_rom1_cs0_gp2_cs1_cp15.has diff --git a/has/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0.has b/has/old_versions/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0.has similarity index 100% rename from has/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0.has rename to has/old_versions/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0.has diff --git a/has/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0_cp15.has b/has/old_versions/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0_cp15.has similarity index 100% rename from has/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0_cp15.has rename to has/old_versions/msm6100/old/msm6100_nor_rom1_cs1_gp2_cs0_cp15.has diff --git a/has/old/msm6050_32mb.has b/has/old_versions/old/msm6050_32mb.has similarity index 100% rename from has/old/msm6050_32mb.has rename to has/old_versions/old/msm6050_32mb.has diff --git a/has/old/msm6050_8mb.has b/has/old_versions/old/msm6050_8mb.has similarity index 100% rename from has/old/msm6050_8mb.has rename to has/old_versions/old/msm6050_8mb.has diff --git a/has/resurrectors/Alcatel_C131_init.has b/has/resurrectors/Alcatel_C131_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a344435b4c926679e3249f44f1fcfccb0f0ee769 GIT binary patch literal 760 zcmZ{gKW@S>6vn?0C{RTrl`=3!NFa6V5UJ3nfA+2%AV?elsY^F3)Fbo&3>~W8qBrO< zIwHZ)PUf@Y$d5`MlKlM3_nx19&{`uJ-~}BJb@~{q2(XMVsBXhC6w&$~Idhx{pOTx} zq3{`bbCK6Q$t_o#=TJ+>pg$A-Cw4Q?n;HH%TN_aNnG1rMm2~oNzqY@8mg`j1KCFPM z?`ye*?Q>Q6vlW6t<~9SfSG#6|dMYxd;GW1QBEMbu{s+My3%qg!JHtD@ZO+$@+}!&c zGgNklbPILw@)?=eU~7%P3-~hNZv*}&;Aa6p4fyMTAN}*cJRB8vd<=h{1K)zjj^`bM fWAlBQ`23~trVrcbq-rS?QGGw;0yUT92xEN&%VAS` literal 0 HcmV?d00001 diff --git a/has/resurrectors/Alcatel_OT255C_init.has b/has/resurrectors/Alcatel_OT255C_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/Anydata_ADU_555C_init.has b/has/resurrectors/Anydata_ADU_555C_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8a42799e2760ca5d75fb73c0168980094bf38dc GIT binary patch literal 2216 zcmdUwJ!=$E6o$`?LtJzvY3JRSz5^AQ$Re9)Z_R=9>4xZRZREX9$j5&N_1eA9dV7UwB%l z3HJU=_?gSM!a8HlZ2f+~0>+3D=S%_~1kNzvM&L99-dLH|f4(B?zSk4vD1DvvpCZR) zp4=$$Tt#f>2MdN~zAw{tyJuul+`Cy%HO)sCbFZqo~!r3(EmmALfwvMLrc%Ml)GxHMJ;k^`a%sSi1 z4xI#l;QXKJPvpvUem)$|e>wle1ncvc^)b!#{c-!Q?;AhB5$*-^x0icIxbNimVD3u~ ztn!S{{1`I&kn&u&7H68{C17c{C@Y6{_b_a zH(IA!oGk9epBsDfbHq1cHmk0NF708-Qv=pyFGQ%u#4yNRVQn-R)p0J7PT*z8cY2+&?ZD4Pe!mVvTC?t$r5U|6u=7Q>ZQ UAor*M*)=6DV0+g9*}OpY0BE^g^Z)<= literal 0 HcmV?d00001 diff --git a/has/resurrectors/HTC_Desire_init.has b/has/resurrectors/HTC_Desire_init.has new file mode 100644 index 0000000000000000000000000000000000000000..7a01c544b4d2a434d2d401bed1778684d3516924 GIT binary patch literal 204 zcmezJ|NnmmMt+70237_j^S=N?!U_f;0I^vZ9xMQ|8bE9Y=7beYP;mhuo5290Mg+)i zaAkz32eKWZYB)e@pllu>n-R)p0J7PT*z8cY2+&?ZD4Pe!mVvTC?t$r5U|6u=7Q>ZQ UAor*M*)=6DV0+g9*}OpY0BE^g^Z)<= literal 0 HcmV?d00001 diff --git a/has/resurrectors/HTC_DroidEris_init.has b/has/resurrectors/HTC_DroidEris_init.has new file mode 100644 index 0000000000000000000000000000000000000000..7a01c544b4d2a434d2d401bed1778684d3516924 GIT binary patch literal 204 zcmezJ|NnmmMt+70237_j^S=N?!U_f;0I^vZ9xMQ|8bE9Y=7beYP;mhuo5290Mg+)i zaAkz32eKWZYB)e@pllu>n-R)p0J7PT*z8cY2+&?ZD4Pe!mVvTC?t$r5U|6u=7Q>ZQ UAor*M*)=6DV0+g9*}OpY0BE^g^Z)<= literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C2010_init.has b/has/resurrectors/Haier_C2010_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C2040_init.has b/has/resurrectors/Haier_C2040_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C2076_init.has b/has/resurrectors/Haier_C2076_init.has new file mode 100644 index 0000000000000000000000000000000000000000..67cbea6aded20cfcdf8e9fe3862527827ceb1a1e GIT binary patch literal 704 zcmZXSElvbM6og+-8g@d4Fq;r86M{e>R;(Zdfj}S;9AHT10Ej(6ixndfgseay5D4T7 z4uIew2m~aE6(r!As{UDCLYw~jrCxRQkN4h7E4^R69rT8r|^UN!8oH?EpKY+1S$o!~ysx%|_cdoJGUTF?c zkM7V)rYM@=U&h|xU&-^?$K-IG8Lp9GfW639iP;P5cIU>1 zx9-#*m;^S#^OU?DGmOC{eE8P?^!6guFQLJimm2=DtY1~kJPY`&VP+Og%X_klv0teF E0<}y-lK=n! literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C300_init.has b/has/resurrectors/Haier_C300_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C3010_init.has b/has/resurrectors/Haier_C3010_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C301R_init.has b/has/resurrectors/Haier_C301R_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C5100_init.has b/has/resurrectors/Haier_C5100_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Haier_C6000_init.has b/has/resurrectors/Haier_C6000_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2605_init.has b/has/resurrectors/Huawei_C2605_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2607_init.has b/has/resurrectors/Huawei_C2607_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2801_init.has b/has/resurrectors/Huawei_C2801_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2806M_init.has b/has/resurrectors/Huawei_C2806M_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2807_init.has b/has/resurrectors/Huawei_C2807_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2808_init.has b/has/resurrectors/Huawei_C2808_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2809_init.has b/has/resurrectors/Huawei_C2809_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2823_init.has b/has/resurrectors/Huawei_C2823_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2830_init.has b/has/resurrectors/Huawei_C2830_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2856_init.has b/has/resurrectors/Huawei_C2856_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2901M_init.has b/has/resurrectors/Huawei_C2901M_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2905_init.has b/has/resurrectors/Huawei_C2905_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C2906_init.has b/has/resurrectors/Huawei_C2906_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C3200_init.has b/has/resurrectors/Huawei_C3200_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C3500_init.has b/has/resurrectors/Huawei_C3500_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C5005_init.has b/has/resurrectors/Huawei_C5005_init.has new file mode 100644 index 0000000000000000000000000000000000000000..337de0f958f0f0de95f5ccf5bf260b3b7608f8b3 GIT binary patch literal 772 zcmZXStxm*16oqd~_a|ft-Grb>Xc`1^Nh%0gfk3QW!2>Lz4}jPQ7=frj5V8WX0)arT z-~kXk2m%2KkQF50hI6Jf%ODoO@GitxXT5ibMoxWm61LzQKz~CK;G@BQojx zdIk;lPV>_F)juhIQ@m9CsrcD5{TDqkT>0HAz6Ikcm*GzFxzY@bR6$cHu9RjU_1fLq zA$Z+;&Xni1;<@4*#ReRFGUPu#dQ7R9{bE&yqniP8F(mr&PO8nd!GU7iPz6?H)KelX|={q-vvVw zF>_BI#;?ud#>8Q9A|eRAUJXV73q rjfOo2eOoc}Ea9_?^#g0y&y{`gLjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C5589_init.has b/has/resurrectors/Huawei_C5589_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_C8500_init.has b/has/resurrectors/Huawei_C8500_init.has new file mode 100644 index 0000000000000000000000000000000000000000..64b429dbd3c4b2ae86bff4237229e4f2e0febd65 GIT binary patch literal 972 zcmbW#El&eM5C-6Bfs*hMDvBW_oT#X%xM27Qq9G?LDhR1SAR2;1AlhIWasp9-z>pvi zC!3}Mc@n`7K%5{1!9M_jU*6fBfe|R0G6H&N(+r?-`LxLAO2A8c@M*&o z1$W?duH@@`@Rnp+oDnB*Nz8pJVxlO|Rze@H&r5wB)>%!M;*g19ofW|i$=5j}ZooQ= z`}{SF>pH7Oz45B7y@Kg5%vyqXq+W%!C&A8bT=G3s%fEAL#!Y0>wa|ws9%l=|efUDo z8^IH)w_)crALVo!+(P|fF*t!if6oW-?MZMK9!dQOPWMCo7#`qOc%SDmBHm}Po_z>c zZbJPL-j&QVoFt)M7{3_58Gpjs|BLI=$Ij(5YNi8kO6JMbdu&|vhwhm#9p8AsE5m+# zMr`|En?Co(Q{xfbm9=-qcwj&E+?ex)$*Vc9=DeEUGoGry=l{&YQook>rsi2{o~3TV Zxx9^tvh0Z9u#`ORI literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_EC1260_init.has b/has/resurrectors/Huawei_EC1260_init.has new file mode 100644 index 0000000000000000000000000000000000000000..91e6f436bf80988c0849ee7811107e398179b083 GIT binary patch literal 2216 zcmdUwJ!=$E6o$`?LtJzv}t?eB5yZec@@H zCfNJ0;Abx14(p6Lv-Nuc3m79toHGfyA2@@68-dddcync1|HX=I_+C$uqx22de}){F zd2*w~a}8rVKUgp{^8=Z#+kGQrBfFZff}byaTB7ri`P%Lp`4L!3*&!RtC3z#@Cyu`& z$6N-NLtJBe+&{l|S#CM-=xhH1p64-Y_&vM}?l@-|?45gHU-vfH?_r+9!3XTk-0x?C z`irg(_tV!2eeSv6+i=fAhjsir71r58FQ0FN>*}Ay2b?Xe&v(k_ycgrEGuyWr-0SPJ zug~lH!Zly2y$kG{=JCc!SEmh59H*PpI&E;6U-SM<-up?Om10IX*eh2~^jW$=e#vq| zXHnTcZx1ZPk>4GmhmT_!M8EO55zMH25$8#2NI*g2*E94_*BfEp^ z%|m-3PhZEscRv4t^T9gZnqEFQ@jjDqX67ZbqkAdfn00oL z9XSd9!1+JbpUBne{Cqf^|8o9`3D)N?>tmYf`{VXq-#31MBisw-Z?6=`xbNimVD3u+ zR(Zx}egYYNatlm<1U6uvejU8Cj)rvlH8nM#*qX|v^#?V+=FV4ke!IqJ{-AqVfA>1z zo2@e~&X$3T1=~w%?q%MRG~)cf`aivX5YN*Y;(I_B7|$H8!vOhkuCnU}?qZ!dLyv4M cFPmwe<9F=5yn9IppN}7}j?~`*pTfOA05CdYL;wH) literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_EC189_init.has b/has/resurrectors/Huawei_EC189_init.has new file mode 100644 index 0000000000000000000000000000000000000000..7d70ea615e34326c5fdb4c1c895c47db66ff6cc6 GIT binary patch literal 2280 zcmdUwy^9l36vgk%4r|ar#uzb3gken~vdEw*QUo0#0Sgg}EiAMDfr5pF#oHx?g{94Q zDMhwW*wSJm`v+K9SgvfdogdwTyW=@`-rIQu;|JLIV3^;Wciz4Cy*rs47DW+@m?PW; z!`_WZEj)zQ3B-K2b9{!y92fgX^y0CIvn3N)mYJASmQ(mb%NZD`{vmktY@*x)x2)dx zJOi+c$vDf_lO$rMjWP~(m#c;vu||$jPaVvg!`rd*J7CW9?&i~RRbS6z0mB;5 zA9>vOJOhtwo~Q2dbiIoIa$P1UMfd+4Izr!K{1?!1YmjR>_MC<4se=W@Q$LXEOdlE< z8`)F+F?ehAWkk;t>Kl6-<%=u6?l z8m(oF8eM7SM6H%)x}8?u=VpDV2`=h@4fF~ zoR;Ttaki1m={sPj`)e8hytfunc@90WWJA^OC`T(A zXC@|zOHUVk*|Lm7WAZ@bNA%lz+VD8;cpPVekqfDOW^H6Uc-|bE3wrz}{JrPvA9y~M zp6-HNPG?^7JCTUBsm>1{uH>GUru8^K6~AWcIkc0tG+@kocA=ekB0S*wpW@HtdR0F+ zhwER~KQrF>{AGMpQ@ua7@A|%R0>keG_4n7(CH9^C5zM}%U^UPAsh@^MKe-8}e+V{U zUhW*6XA=qO=`V<>`mBtpoR|K=0>A3kuWbFT1%B#}x>xmouMNK4JlAAx9dNo*=8^?# zsW&AKSpTnnr#BD620aLjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_ETS2222_Plus_init.has b/has/resurrectors/Huawei_ETS2222_Plus_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Huawei_ETS2225_init.has b/has/resurrectors/Huawei_ETS2225_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Intex_In50_init.has b/has/resurrectors/Intex_In50_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/KDDI_Casio_W21CAII_init.has b/has/resurrectors/KDDI_Casio_W21CAII_init.has new file mode 100644 index 0000000000000000000000000000000000000000..9a88b05dcd976adb5f2d28d21cbd40153de4958d GIT binary patch literal 720 zcmZ{hJ!->17(_qWapT%=HGgB{->r0^kJ>L58lPLMiB$YBCb zVc5*9R%8liLFn-`JNu(=@4Y2sJKD&A9qmHhsKcj$+9-2W|kYVO3dfE#@18E8N7i;)$=6LOzv!0fTaUOxwA;5tJm zHbK7-c4lilU0yiHx^MpU#XRrrAesE!WCNLCHVcp~0A-6Hv4KJfUQ7%O0A9%) AJ^%m! literal 0 HcmV?d00001 diff --git a/has/resurrectors/KDDI_Sanyio_SA002_init.has b/has/resurrectors/KDDI_Sanyio_SA002_init.has new file mode 100644 index 0000000000000000000000000000000000000000..13dae88a9f05dcd4f203e15cdbb751cc37e03111 GIT binary patch literal 204 zcmYk$EfPRb6vgr5TVTAPXo4UpqHZA;AxPFDVk}3p4*fardf~O-ocYh4`)aM>6<82~ z)GAa*1&B+U6vNp6ojR_AY3D3WOGEwcjH6!mhHhx>?(m9y8_wg>lV O{%q)V9_9W;=j=Z}Yg*v| literal 0 HcmV?d00001 diff --git a/has/resurrectors/KDDI_Sharp_W52SH_init.has b/has/resurrectors/KDDI_Sharp_W52SH_init.has new file mode 100644 index 0000000000000000000000000000000000000000..e9c2a0646b25e55125cceeb335e80de7f25eb805 GIT binary patch literal 36 ncmezJ|NnmmMt+70237_j^FIRvL&76w1~6NJnIWOMLxBMRHlhz| literal 0 HcmV?d00001 diff --git a/has/resurrectors/KDDI_Toshiba_W52T_init.has b/has/resurrectors/KDDI_Toshiba_W52T_init.has new file mode 100644 index 0000000000000000000000000000000000000000..e9c2a0646b25e55125cceeb335e80de7f25eb805 GIT binary patch literal 36 ncmezJ|NnmmMt+70237_j^FIRvL&76w1~6NJnIWOMLxBMRHlhz| literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_LS970_init.has b/has/resurrectors/LG_LS970_init.has new file mode 100644 index 0000000000000000000000000000000000000000..27b684b3f8a869018046b094b835ddcca5ccdecc GIT binary patch literal 420 zcmaKnu?@m76htpUAOsXqTAEM*qG19GMo2+HnE@y~f(r)72$YNw#0=0v!2m3P%pFOT zUm+KM-~ayoa|j_+g#!@bLq5z(B&@{MqT{FGo#B(=Y}x6HdB@IpCaaR0YX59q^NqVE zeD`C(v!{BLjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_LU6200_init.has b/has/resurrectors/LG_LU6200_init.has new file mode 100644 index 0000000000000000000000000000000000000000..aed306656541bc07f33e5fd2b09d7ac189b8b5d6 GIT binary patch literal 928 zcmaKrF;2rk5JkrZ5(E@cprcu&073{PdL&$=NI~Hu1*HoL3JTu<7ono@5mHd(7(tu? zT2iE-L2v=G{J-826A6*Xnzu9G-?QVj_ufy7QbZB~`s}O*OW>SbH9Q1A^zP*anm*XC zi0nZ3iuHhN-ww6Q$Vv2|Uuw8zxDBSCbG2N6JGefvzB#PX4LfRns|X9^3*-?(JVuVs zR_zBEEd||m)G<=`ZFKaX^#1lABagCYRDac4|Hr6fRDadc|NUgypM7zkGvx2U+ql@f z>gdfGQ8PCh_N^NF4i1)mbuJn5D0@crR;}&3A9ak>(O-4s+r3)&4#-nzlxK#AhR22- zX07^S|CdYS**R+Zr@uRGn0wwrzS;~&EzDpYYmfh%tc5k}=gF=-r}HqkppSi$1^3cZ z!0dsuRe!R5u4UDHL9_ACeXQ$w9wm7f(h4bGf-`9qTDSYsob82so!}mx2mL0l=vStW QewE~1gzzp$V91_+06iImLjV8( literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_MX800_init.has b/has/resurrectors/LG_MX800_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a407ad841a0fc431028be67dd89773bc5e89f906 GIT binary patch literal 1460 zcma)+y-EX75QQf{YLK9v2nw!}!onhjg++=KDIy43Scq6Gm>2K~vW2BD;hWjnrV!Mi zUeCEZvpHCqX1_B#Gk5N}H=9yQc4U>|2TXloTU*7u!hLef^CjLhoA$jA9t{`hdFk;1 zxa-XLp~O+2XF%_A+%7VA!C0z}TXi4Y10$T{C;!MPkl*(Ffz%!g55e1>b1Hl$JQ5xY zPlTu71MhPod?kD>`8UGWTJ5V49t)SkU2vyU`!Eom2+y29dDd9#J3q~+>En-R`t${j zmic}5>LaCd-w!1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_RD3100_init.has b/has/resurrectors/LG_RD3100_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_RD3500_init.has b/has/resurrectors/LG_RD3500_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_RD3510_init.has b/has/resurrectors/LG_RD3510_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_RD3540_init.has b/has/resurrectors/LG_RD3540_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_RD3610_init.has b/has/resurrectors/LG_RD3610_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_RD3640_init.has b/has/resurrectors/LG_RD3640_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_RD6100_init.has b/has/resurrectors/LG_RD6100_init.has new file mode 100644 index 0000000000000000000000000000000000000000..906d48cafb062ebec0dba04c163ba297f7f9dcef GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2SFea6@*k&AdrYYKuPWa5Pg6Vh!Y4z1p1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/LG_SH860_init.has b/has/resurrectors/LG_SH860_init.has new file mode 100644 index 0000000000000000000000000000000000000000..886912ae6d48949f9c4af975e365a41dd38cb21c GIT binary patch literal 2372 zcmeH|zityj5XQ&8GhD2ba+X}UxZ*%AEJSgI3m29!$^j09KShd^c?9SvPYMNvixdvwfxPn&(khLatqCwz8f zSh`#Pva{vHaB7%-?fJSdbv5p~dOm;$x2uZrKT^ksTt`xOQ51OvzCIYZI#0on+kJtf zC~Nm+^fRNM8+{GdI2T42aPfY!V6K~B=KTrQJTWw_y+9B4eEu;w_DsDB=ywA8-GF{C zpf3aZen7t;&>sZ!gMj`ppg#)ekN==cw(Vg8hQ+S^O9&M!%yvg6orVmLLN86FxQ8O{we z{J?_<0~`1GUF>VzB1#J+cVgAy@;h<6ThZ@&HOs_>&UM;R@Nlwi@yK= zbNAPC*JbY(|1ftY?hu{RDOk_i46NsO4(|EcT!5cRr(oU+Tm z?v^E3bMao%T)*E-s>kpQeVmE$L#pw0eW0#&dfm+yb)79SH9Q6H!1x1u5!?&h6FD}_ zdsX$+aAtUDn0K%GbI<&H63Hr9ul19a`wnAw!1_f*Cq=DEKNJB4iM8 zsNj(CRUMRe$Yuxs0EdF$Vn!FSgWwW)e!utKn|tya6>RB)XFs0%JwNWry(jsZrl}Mr zWK%{3m_`NZ6htiVNIj9+j71ic5oa%fFFKA&(cV?Z6>#iWzyb%xEGrhoEc7O;HdiDa z$gQTLcuny;FtvOR6eG``_pLL&i?gHbO~oz6NZQvw1ET}BhIPb2nla{jVeM&wysP*X zc_PyvWcDI8CF!B=A>3c%k8`$(Zc@_3w*a?|?ed6}|0POeO05cCYYhcE-b%Om}imp=; zG@i9D<8Qn8+PF=->OVm-_{qh?*`X9F6zTKyWBaqOPK!)IO4 zYu|b3!yOEo^<2#1vo7e*BW9R&CJD1H)KJgW%%1QaoOMB;uQ|**lNk8%v(TE;#y{&m zx3FK7Y3po)mmKdZP84?(Q}5>(^`5EsOuc8`-^wX+`8t`)Gjn-nF3$%14F`_>ui|&< b7dd)O=5OMyjX7(73%&ve+Ix>B=I^NAO3qmo<_X3g@{5_za0##BA$*_5Jx|JJ z=hMVziH{Qpcr3YnufX}GQ49DR^SS?keTd%`a3`aq=H8Il4l6e9rJH+RY&QE~#CE9s zERCM??^>~8KXLQ<2<9iBU&FQcGjI6r^Td0YiNx;bz|HeFK8O7+jf}Z9+4}u}1&k3R&Y1)}2%KTSjlgLJyszPhtYegu|Mw#mkFNnQ{5iQ})x zF_*#R0N0ov_s_3gmRk-y`r5w-&+`~H{2tx~cbu~X_Rc-9uX`Kp_b|`l-~;w%?)Ni6 z{RLNt`|0b1KKI=3ZMf&5!#e(*3hQj5m(RDrb@fl<1I`xK=R4(d-iz_oneE#Q?)CNA z*XMP8;hHbi?m6~N^LYKZtJ4N2j?;~4oi;ekuX=wb@BbvvN--lG?3F7g`YhcbzhpU~ zv!HCBw-1(Lr1>r7l+`Cy%HO)sCbFZqo~!r3(EmmALfj*h1Dc%Ml)GxHMJ;k^`a%sSi1 z4xI#l;QXKJPvpvUem)$|e>wle1ncvc^)b!#{c-!Q?;AhB5$*-^x0icIxbNimVD3u~ ztn!S{{1`I&kn&u&7H68{C17c{6Y7c{_b_a zH(RG#oGkkxtDoM(uni_>i_imemqa7!1sVIFrGPFhavJ}uCnU}?qZ!dL!WFc cFPUkc<9F<=yn9IppN}7}jMU!*pTNC805IcXLjV8( literal 0 HcmV?d00001 diff --git a/has/resurrectors/MDM6600_init.has b/has/resurrectors/MDM6600_init.has new file mode 100644 index 0000000000000000000000000000000000000000..8a98188e16ac2966380f52f9e3d9dd5572ba8325 GIT binary patch literal 48 vcmezJ|NnmmMt+70237_j^S=TEL%}VEE2}_k6(GBzA2FT`RU|;|MO@|gt literal 0 HcmV?d00001 diff --git a/has/resurrectors/MDM8200_init.has b/has/resurrectors/MDM8200_init.has new file mode 100644 index 0000000000000000000000000000000000000000..346e0b496dafc8bccdfe2921e2f3258d83b12450 GIT binary patch literal 500 zcmYk%p>6^}5C-7?pm4M)aN;Bafj}T|wKU-Ycmzmz0#boMT!P>Q5Qr5gDq4a#aiW69 zsA^xK5=8>bKg)JAXYSkCnc10>wH8quOVmKx#v{z%?|CbJrq_$vM4SL70$fhl`@(qR z6^3UQ9|4~m?=hWuvo?6BJg81TnBr=ObXJR;dn(?i!@G3f=XdCea$Pz0PI2#lm0f7r zL;k#m%$|5l9CYj9=|!9*Fp?uqmFLO@E%)-3$~*4&U&|)Jx$?U*hY2|c`rgsnLb+7_ fQa(DzZWq28X6_=-fAGDRUOjsCHg>xl=q3|yA~gF< literal 0 HcmV?d00001 diff --git a/has/resurrectors/MSM6550_w51h_init.has b/has/resurrectors/MSM6550_w51h_init.has new file mode 100644 index 0000000000000000000000000000000000000000..208192329578e7402da1b9794efd2ba1ae6e1195 GIT binary patch literal 480 zcmYk2tq#IK5QOL211d-m*e3i0K?tIv0)Zf;q6)(cAb12s1tArE1RfQC%$B{fqRE%d z*O|$ELI`j(G#G&x0JQvi_J)zleV2&i$xfZU;o6yh4QGb)wp2#drTSQy9_YW%By}wBJ$+ z!T~RAKr8?jp334FN#~cSj*x>nSI2X3cO7TPUHm&Bx163`(K7F@cT$#6_Zi4rb4KUf z$Udhznz=Jydz&+pv(0s9F=ov|tX;ZuoBKV_3C|;g^dI>4A9v(rcYE^Va}sq1$9ckg HZw`!CI?R?N literal 0 HcmV?d00001 diff --git a/has/resurrectors/MSM7225A_L52_D08_init.has b/has/resurrectors/MSM7225A_L52_D08_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a717396302eca9ca7ab00398945b5572a7059783 GIT binary patch literal 336 zcmYk$p$)=77{&3|Qs78RsHnkJbN~iGAW*1=3Caotfj~5YV6Y5OSqKAk5P|^107w)G zIo{V^!?|BB|9f|Dtu>qh)@Xy&s)zFR_#DMPy2j~NvBme*a literal 0 HcmV?d00001 diff --git a/has/resurrectors/MSM7227_L41_D08_ONENAND_4K_init.has b/has/resurrectors/MSM7227_L41_D08_ONENAND_4K_init.has new file mode 100644 index 0000000000000000000000000000000000000000..1ba335de33aba4afc1ccd37cfd4cc039f01da421 GIT binary patch literal 312 zcmYk$Jqp4=5Cz~_*PjRxS4d^Gf?(?bY%C<#$Pp|oQV4Eg5j&5tSOu}LuoY6|2p%AZ zuoTue*%h4XV|c^7w{wofm~!e7=oDooVc1=2EM(Xuv$7NR3Z|vcB(T{CpNH2W6LBUu zhD9*J{XY+a6a1Y7$M7nc`}}S{2QsAmUrp9d>2>99bNDG{ZHF5?3bzfskV>X_7S+aAujP9-Xye}R@-WyogmlONQu5`^VysIw=ww)sY literal 0 HcmV?d00001 diff --git a/has/resurrectors/MSM7227_L41_D08_ONENAND_init.has b/has/resurrectors/MSM7227_L41_D08_ONENAND_init.has new file mode 100644 index 0000000000000000000000000000000000000000..00a989a4b9399615d73543d286abf0971d29fee0 GIT binary patch literal 300 zcmYk$Jqp4=5QgDd*PjRxBc!rgL9q1zHWrd=?(Aj>A5`<~1bnATmB!gi;+9^Oh5aU+gl zB_??I=aD$Y-kCUtH)6i$_t%hfb9&$So+bQJi+1lFo=D%oE1ei__OQ)t#y-GKUo^Xb bee`I3n-R)p0J7PT*z8cY2+&?ZD4Pe!mVvTC?t$r5U|6u=7Q>ZQ UAor*M*)=6DV0+g9*}OpY0BE^g^Z)<= literal 0 HcmV?d00001 diff --git a/has/resurrectors/MSM7XXX_L41_D08_init.has b/has/resurrectors/MSM7XXX_L41_D08_init.has new file mode 100644 index 0000000000000000000000000000000000000000..200e675fe22e42c8f4876db325b002d5e4339949 GIT binary patch literal 204 zcmezJ|NnmmMt+70237_j^S=N?!U_f;0I^vZ9xMQ|8bE9Y=7beYP;mhuo5290Mg+)i zaAkz32eKWZYB)e@pllu>n-R)p0J7PT*z8cY2+&?ZD4Pe!wt=!i?t$r5U|6u=7Q>ZQ UAor*M*)=6DV0+g9*}OpY0B<>76aWAK literal 0 HcmV?d00001 diff --git a/has/resurrectors/Micromax_A87_init.has b/has/resurrectors/Micromax_A87_init.has new file mode 100644 index 0000000000000000000000000000000000000000..03d254f79adf2e1e55b3b263e7a2609ee43ee12a GIT binary patch literal 2384 zcmchYF=!M)6o%h;EJ#3IFli3Chx z5hS9;mX{!6k>b)_k;2jT0_#F+S8u+*bm z0!PXM76dUS@3FwMvQ-St*g)zCH!&rT$2@)uW-PB2kCA7|jScCqJ~N&^=kdJ9NZO8n z22K)N!#I49ri-~2jGko3iyprsAGh%#;aB{=I=`Q%g$c_?C{( z+Tp^rXZ%h4`g1Y9(Dw4bo{H!D;V$}YY91|9&fw48>Mw9ms!lv6rgyn!j?CV@7;Fua z*}G`AY5K+9$(pQDXYZsT?cO=Y?jWgFd`tOegDpbf0?8dM;+e_Fg#vmOiuG$q@Ky?-MS2 zav6NZz6MDJ%x{o-73}s|k#arOeMdY!06WhT*m>r_=hY|A807-k`P1i+>S_Nj)l1l~ zi@R{dv*C!X)0`7GEEk{;X?y@~=K@!^d+u>w0nQtQm^t$7A)5#McNTHcN&6_$S9_y5 zCc#rW|1$U|K2mxOfZhJhImnpRE6@WhG-ImZQ9X->!5dRn9|3=RZuvGis#?AScDW|N zuDtu;Tk10nK7~Vq{tfUYox*#tt7qNgj~;*VxaILCcy!r%j%VPbo*{S(jbyH|l-|O| zP2I1PJ#jS;fiI}fnx}_kcyd25W4Tbc`yO(n^)xZczW==EGY1~gm_?8AQnvNF$BbY1 z;vF;IG2pF literal 0 HcmV?d00001 diff --git a/has/resurrectors/Micromax_C100_init.has b/has/resurrectors/Micromax_C100_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/Micromax_C111_QSC1100_init.has b/has/resurrectors/Micromax_C111_QSC1100_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/Micromax_C111_QSC6010_init.has b/has/resurrectors/Micromax_C111_QSC6010_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Motorola_W150i_init.has b/has/resurrectors/Motorola_W150i_init.has new file mode 100644 index 0000000000000000000000000000000000000000..845d2fae4efafdcffab3d074d5861289c2e71c47 GIT binary patch literal 540 zcmYk&FBidJ6bA4++x#gwM_J_f2#O#GjwFhLAPAxlu&}To2!bGpqOc$cg5U!Pg6KQY z=DB;f^FB+zbI-G9clVd3X&|8|cz*DP9KyY(nMdlX@ewZN`5onBxPvC`+0*<0w|q0- z!riiQSQZzRSw4cLZ5*o|kuQ1#d0kHJQRk#0Za6mi5sXOIGt8~|fotbW%FHP<6LImW ztUsukyuSOP%+#^-q-5Rqtyg5x{qud+aB-^z`QEUZ2l))^U+WDM@{=+z@|%1jU*MwW TO1_bgxwAXh?HzX5Q*ZJI^0?iL literal 0 HcmV?d00001 diff --git a/has/resurrectors/Motorola_W200_init.has b/has/resurrectors/Motorola_W200_init.has new file mode 100644 index 0000000000000000000000000000000000000000..845d2fae4efafdcffab3d074d5861289c2e71c47 GIT binary patch literal 540 zcmYk&FBidJ6bA4++x#gwM_J_f2#O#GjwFhLAPAxlu&}To2!bGpqOc$cg5U!Pg6KQY z=DB;f^FB+zbI-G9clVd3X&|8|cz*DP9KyY(nMdlX@ewZN`5onBxPvC`+0*<0w|q0- z!riiQSQZzRSw4cLZ5*o|kuQ1#d0kHJQRk#0Za6mi5sXOIGt8~|fotbW%FHP<6LImW ztUsukyuSOP%+#^-q-5Rqtyg5x{qud+aB-^z`QEUZ2l))^U+WDM@{=+z@|%1jU*MwW TO1_bgxwAXh?HzX5Q*ZJI^0?iL literal 0 HcmV?d00001 diff --git a/has/resurrectors/Motorola_W210_init.has b/has/resurrectors/Motorola_W210_init.has new file mode 100644 index 0000000000000000000000000000000000000000..bfa22c3e690cca5314635a556a5f7506ab6708c8 GIT binary patch literal 588 zcmYk&uM$B~5C-t&`dbK!8HMozW)wjXj3kPJAPAxdxIqvEK@bE{6a+yK1P>qxqIaNO z-`=x#&Ue#qcD}QBcYje7RVB;_z8}0Mhj6>@>PvOO`2goEzoq;NZlII)*-?EDSF*0Y zftz@&nJ_0o&H5~1v45@9DUmNSg1io=&QQ-`UV?Do`t)H$;+{RT=DUHf&nPpY%vdDA zuj2mIqRZ>s4`oIvUq7e4J6Z2JS#*AzX91_pQ}Vs+GY|3!)~)qEXY!LWFY=pwBwyg9 i&y{>5AI$NcOa2a9%&9lQ2vN)KpiXvCC%dTEw(lRgm+xNy literal 0 HcmV?d00001 diff --git a/has/resurrectors/Olive_C2110_init.has b/has/resurrectors/Olive_C2110_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/PXA3XX_NAND_init.has b/has/resurrectors/PXA3XX_NAND_init.has new file mode 100644 index 0000000000000000000000000000000000000000..7a675ee1b4b27dbf0c2cb65e8e2d07d79945af25 GIT binary patch literal 1324 zcmZ9~F-u!v6o>JXkeWzRyh5xI6aqRpIN0joVBv}mL2&Ef&>@r#X>o9HD4n_#96Ds| z=!bA{aA-TV&@bV)aM9~|&OL!YW_f=+_r34ENlsN&Rljvt9t_ML-9KM#m%db2zM6mV z^qI%mFTGD>&nGu$uz$94Kl|ooANT09xPBqmKa0OU-)nZ#OLA-@s@a3yf1z){wO{ZUx>|i4?3^w_ctp>CvE!`zpZ;c|BKSSV^-3~ z?&hLR@x*Pm9RI~Pceh)gGmUP)*<+1j^xq?!&a0 zv22+3*RR=9eIBNjer?t;EoM9SVcO7F=AC!Jw3xGOm=^Pv4bx)ovSHe(ue0+oZ7dDb zCeko1<}%O2w3yFqm=<%I4bx&?vte4yZ8l7c`OSuDF~`|3?abHN_rSE6>)eN*02R@I AWdHyG literal 0 HcmV?d00001 diff --git a/has/resurrectors/Pantech_UM150_init.has b/has/resurrectors/Pantech_UM150_init.has new file mode 100644 index 0000000000000000000000000000000000000000..fc3995cc09f871bea69e9d9c485086a42e86fc86 GIT binary patch literal 1384 zcmZ{kze)o^5Qpb-r>>gf0s&K`I3CvQ0M8KRBC(D#=I^O~VZ6*RIj_Zn{ zGCV~_u_@LXuHR71_3JLL>$7jn@l>o0xK3<2woH|B-!v%MD6T5zeBkOgSCEg2p4-gM zXCY-3$B*ERS{(AeGq7>~$@-f0&tPc#?l0g68jU#rs{EVEzbj9cw=0~Fz|vb=G0)_{ z)#q8EWxE&qp2r`0{E^2WdwlBgCmw(5@n;_2_xN*db8{0_XFfnBi7yaSdqum@grHM@#?VEG+W<@;b+d!=}w^4E$J@EC=-Pv%fq_1S`# zK6U@>o36L0hP7dNX4akOv$QIikZu;h-`LB5m%#kF#ltQ4t{ zpJVtR_Oqb)CbIuk`woBB82Um^X2^BSa88|1SI<+&42|vM9`}ySVgjac-}))I>-NpS iYmPZDd+XV;mv^gT)>1PC%kRf`jb#4cHR1_*J_o-y11#+T literal 0 HcmV?d00001 diff --git a/has/resurrectors/Pantech_UM175_init.has b/has/resurrectors/Pantech_UM175_init.has new file mode 100644 index 0000000000000000000000000000000000000000..0f9e9ee7772d26089bcc2fc99fb1369e3b719cc5 GIT binary patch literal 1464 zcmZ{kKQ9D97>8$X*IA-)iG*T{BS$WxxI&@0;>0?K^QTZKl?sJILZR4%gvb?FC=?2X z!iQ1#BEkp2`u%3-y?Z5QlgU2&>^twgGqbaKp679Dt|yE!z}zUVj+t!U`5G8#V5v>n;US8!!DO&Rw_kBgjzCX?}c;JHdA zr0;`KhV6T={Dbn3;2U#(&iE(gpH=*e@|ZYsF4|fnFxQHGG4}y;PuHC1o<@%8Q;%Qw z__oJycznm>H$8sK+w4tzw7aP|9CSwT*DZQ5WBWje3L6ElASD^K*b*_u7aTq;At0s3YNZSV99x*{3ZQ$U~@8$?1f$j`caoN!MaJ#4p{br|FH!Z!~fV9 jX26>HA1epn#5@5q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/QSC60XX_L18_D08_NOR_init.has b/has/resurrectors/QSC60XX_L18_D08_NOR_init.has new file mode 100644 index 0000000000000000000000000000000000000000..c3769a531ae4c1391dbd5ab41f884921bcdb2ef8 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcRBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE)3Rz3g# literal 0 HcmV?d00001 diff --git a/has/resurrectors/QSC60XX_L20_D08_NOR_init.has b/has/resurrectors/QSC60XX_L20_D08_NOR_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/QSC60XX_L24_D08_NOR_init.has b/has/resurrectors/QSC60XX_L24_D08_NOR_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/QSC6XXX_L24_D08_ONENAND_init.has b/has/resurrectors/QSC6XXX_L24_D08_ONENAND_init.has new file mode 100644 index 0000000000000000000000000000000000000000..2c500ce4e59c64e3b0ddb68ee99fcb776719957d GIT binary patch literal 276 zcmezJ|NnmmMt+7023CfjK(+t_L&IN?7!W||1_lNWCXk#ABSXU^+RGV7+UA IY#yL`035b?L;wH) literal 0 HcmV?d00001 diff --git a/has/resurrectors/QSC6XXX_L32_D08_BS0006_init.has b/has/resurrectors/QSC6XXX_L32_D08_BS0006_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a3f61f4351fb00c4929e1c546ea2e45920ae4aef GIT binary patch literal 276 zcmezJ|NnmmMt+7023CfjK(+t_L&IN?7!W||1_lNWCXk#ABSXUcHmk0NF708-QwLpyFGQ%u#4yNRVQcHmk0NF708-QwLpyFGQ%u#4yNRVQ9epBsDfbHq1cHmk0NF708-Qv=pyFGQ%u#4yNRVQ9epBsDfbHq1cHmk0NF708-Qv=pyFGQ%u#4yNRVQn-R)p0J7PT*z8cY2+&?ZD4Pe!mVvTC?t$r5U|6u=7Q>ZQ UAor*M*)=6DV0+g9*}OpY0BE^g^Z)<= literal 0 HcmV?d00001 diff --git a/has/resurrectors/Qualcomm_ThinkPadGobi2000_init.has b/has/resurrectors/Qualcomm_ThinkPadGobi2000_init.has new file mode 100644 index 0000000000000000000000000000000000000000..790c6e0badceb624641ec99ad2b537d0cdfe4020 GIT binary patch literal 1512 zcmZ{ky=xRv6vgi(*<{s7CUF}@aD)XTq!?}dz+#XoA_NJdU}3RE3JVL1h!zs3*dj%W zAQmZ7JPTnHEG(jIVX=jOK!g+`7HO@th@CK=^WJ^C7tw)PejLs{_r8zWqq?ponUQDG z5MZ4q(oaM@ccs&ln}J1^dt<7n6Y0)r3GmQQ_v9`m$n$tDGu*>Puw=o%1g;v1?|TD$MdvT*Q7*yp zT$nSdx=7Y{Is^47)z5^k@ z=rs-fn(8UrwFz2H2*qmy5lylyAY>w#uFel#IzvmgujdEuH zmxE%SBkyxvpIalRW21d*8D4;=IureQ&*^$sCGS1ec{1>>>Wkob_qcXh3AF`uxgEF! zpU~Ns!EfFN{Vw>m&VL_V={NfT{Of!0JO;--c?6DU_Z)l*7oTexfUj%*KDaD{eqi{E z;cte2f@A&>bHQWVn zVy~Eg2p%A(z?)vc4<7ErI`m3;%P>Boq24#l^NN1fqSWWGHZp4?vo^AyNB=W9e?x0I jKbOvVIDh1ih6`|0??xuheU*b<`rF{O)lzGnJBge>CN#qN literal 0 HcmV?d00001 diff --git a/has/resurrectors/Qualcomm_ThinkPadGobi3000_init.has b/has/resurrectors/Qualcomm_ThinkPadGobi3000_init.has new file mode 100644 index 0000000000000000000000000000000000000000..8a98188e16ac2966380f52f9e3d9dd5572ba8325 GIT binary patch literal 48 vcmezJ|NnmmMt+70237_j^S=TEL%}VEE2}_k6(GBzA2FT`RU|;|MO@|gt literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_A900_init.has b/has/resurrectors/Samsung_A900_init.has new file mode 100644 index 0000000000000000000000000000000000000000..cfb2732385afe07d65064a2ca3c76cdc9f95052a GIT binary patch literal 1460 zcma)+y-EW?6oqeo4HC4IfB{!YVPTQN!Xm{MDG~^nB1I63K=J}ULAJ2;C44hG+Z2Kt z)bX6j+|9vCLH0X$@6XJc$%YVuU07lG1BSM+HTLnkaGP97`4VrLjqo4);8Ajhp0_F9 z1J@HXelGE{wqlFCn#DeKFh-@G#nQQD#S-Bdzxqc`hWx6}lG;n*KKMB0Tnpa_4}^2! zq3{TNmikPDr@}MIp9@=MzpqR<7hVY0!L{1Xho10Ic$N5*XN_6k@o7d)AAdyCr!Q!< zjPHBU_7TE3?S~$@kMzjTk{&fv4n1}~qj%gZ^J3i}O%L@weN@f*fPkTa*Q;i|YSydfS+8HPkCRLjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B139_init.has b/has/resurrectors/Samsung_B139_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B159_init.has b/has/resurrectors/Samsung_B159_init.has new file mode 100644 index 0000000000000000000000000000000000000000..c3769a531ae4c1391dbd5ab41f884921bcdb2ef8 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcRBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE)3Rz3g# literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B209_init.has b/has/resurrectors/Samsung_B209_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B219_init.has b/has/resurrectors/Samsung_B219_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B259_init.has b/has/resurrectors/Samsung_B259_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B2710_init.has b/has/resurrectors/Samsung_B2710_init.has new file mode 100644 index 0000000000000000000000000000000000000000..58e6b5ade4927b7d12d07a9c03ed752045149ce7 GIT binary patch literal 1160 zcmb`FPb&ps6voe7<8R5h$X#4D>M9HBCJT$Zm|NFE`4HE_-hxu3mn0v7Zy-s0gSoP_ zP^_%j*Prv_FMx8p6OFi+@-kN^CUEHNMH@+Sj>%Q7x$V{AZEjkQDV#Bu=Bui z4F0;S)N1!wRxHheG2W*JPP!8Nj_ji)kte(p#Aqfo@{jvwUK+T%q9iafn#~{vN9P3> zcl@IGA>#`5c<4jE5D9sgi*q12i(^!@HL2oDaIO#Wf%BjGmdv#M**DH#{w<^G`9%*G z*Y7a;9g&HEy_dkTbPSTq;O2Oy;XKpcY6s&2E=uI|oaff#=>X&IU+pFG2B!WM?;d~0 z_noPuCg$j!iLe`aP2gdl8|yfH*DBL_t@Ywikv`vRy`IWytwP`DeaJ;H|5F2Oz&v`6 z)a)Qe&pEKP6sH;2RNOJ*?3uH$Fh}~2GvF>kn(x>(INzBFA2_-ew|ic{Vx(!p`;c|5 wf)5v-=gI4gZ{Kf|H^Gw16&cNuQ}V9jeZ?{OPHvB>sem_E8?Lq!a6j(-1dylxrvLx| literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B309_init.has b/has/resurrectors/Samsung_B309_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B319_init.has b/has/resurrectors/Samsung_B319_init.has new file mode 100644 index 0000000000000000000000000000000000000000..c3769a531ae4c1391dbd5ab41f884921bcdb2ef8 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcRBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE)3Rz3g# literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B339_init.has b/has/resurrectors/Samsung_B339_init.has new file mode 100644 index 0000000000000000000000000000000000000000..c3769a531ae4c1391dbd5ab41f884921bcdb2ef8 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcRBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE)3Rz3g# literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B379_init.has b/has/resurrectors/Samsung_B379_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_B619_init.has b/has/resurrectors/Samsung_B619_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_LC11_init.has b/has/resurrectors/Samsung_LC11_init.has new file mode 100644 index 0000000000000000000000000000000000000000..59fbdb167e2e5afff19f248e54fb46371da0328c GIT binary patch literal 400 zcmYk&Ar8Vo5CzcR00{yDf&;AJ7$hJnI0#2TATX6AfI=V;h>C_(R8$}kI5+?xP&h0C zOO`(^B!804zMY+!P4?}*N6^9qHIN=~3!G1Vb5&dyH^e0;9G|2PmEWt;fpwT4!*gra^_hW zJ|9cpby;SUo2 ze!@RU_``&MnDCDh{_z!Fs?8pjV1)RyZP1TP6w0%mnHcNm@Y*8_@U=L12_8q@1CJuN zhC8sH-O9ut8h&E|peZX0uPahONI>*Gz%Q^feb zYl<+6IL5WOFZj#P;q&}igLOpDnlvWlEyEfmcPPwthD*Z}!pc=3gG zGQTqOD>J_`^D8sIGV?1lKRMjNvEK_PVJzb~iDMPVoj6Y8SYu>Of_>5R|KE3}?~bnM zyR%ID&cDmsf9boU(06luyR=Ui;7RPkrSW@Uy~{25xnvE`4DZptIT$iB^XR>{cZ&Xc z%vqan+6r7o&+nm&{P*`z{mjH5w8zgsJH6Hxz3(S_?I$toJ_BzdkTw5!DGX`JKglTQ EH()|ie*gdg literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_S109_init.has b/has/resurrectors/Samsung_S109_init.has new file mode 100644 index 0000000000000000000000000000000000000000..efae6112c98c09ea0281df5e59a05213d2e573bb GIT binary patch literal 564 zcmYk&FB1V_5C-r)cm9nT%qSPhq9O6~cW}2P{n)1_Jt6PbHuH$>5Pi@?$n!#MPjybqRI#QV!WeDgrORK7KA=B|8#`LFqgsq#Z* cp2{!fqw*R4_gs{(%859?bKTw{#-4nWA5N3!m;e9( literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_S189_init.has b/has/resurrectors/Samsung_S189_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8f2aa7a188c594788f185cb8b06b6aa36a2e527 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcNBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE=*Rz?5- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_S239_init.has b/has/resurrectors/Samsung_S239_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5841858efb3218401b25fbd6aba4d2b5e21ec1f GIT binary patch literal 276 zcmezJ|NnmmMt+7023CfjK(+t_L&IN?7!W||1_lNWCXk#ABSXULjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_S3850_init.has b/has/resurrectors/Samsung_S3850_init.has new file mode 100644 index 0000000000000000000000000000000000000000..bd6fb772cacb9553f0e64ce7f3f4382cd9e817c3 GIT binary patch literal 288 zcmezW|Nnm$1}6??1_lNo6U+uO89o5nj6nJ)kmdl%b29KRIKT*2!vo|CsX){V0NK3e zN+KY=B1q<_0NEgOK;kVxHWQTn1<0PH0x?Ge$d-nRgV+*4Hq2g-z8Ij`f2e!~kPT#l z&65GLL2d)7Q9xqr0NK?*01`JqVut|P8+e#d%ywZA0h@Sr?3>pkT9ssf| Bch3L- literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_S8000_init.has b/has/resurrectors/Samsung_S8000_init.has new file mode 100644 index 0000000000000000000000000000000000000000..e961b22cc57f4272ab294c71fddf7bb36ba97b94 GIT binary patch literal 664 zcmZ|NJ5Izf5C-7i#DV}3YuFS4rHBv(1;rLAD7FX^1qB5S64#)h_3la>fCF$GE`Y>A zcr>g8gn#VW;08;HKab`SCHd(49%h6e?(b?ifb7x1gG*eZxs_d3iOJxX1!mV=-;84k z-!XsXIsK(^jCkNB^>~HnJ=iAB>G2M*WKKg%wYiIV1&q933186|F- zxy-NW4UP=G-r#49@fc@1c&m1FzNYo`y2dNosB4-jp|+u=FWdD;^rrfl&eSLLGm9l> zlEmA@r-`TZs(+XGoZi)*7l{jczdP)t|0R949cN(={`1O&xmJ9m9{+vEocTZza-w5x kv`ylvw}yC&d@xWac8SY>d@#gYRKYepkNzjLyhC~Kzos20kN^Mx literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_W299_init.has b/has/resurrectors/Samsung_W299_init.has new file mode 100644 index 0000000000000000000000000000000000000000..350d18a71765c951b966016abb50b7884cd0d52a GIT binary patch literal 1632 zcmb`Izityj5XQ%U5}(isC?b@?5(jbwMG6-bDN(;iTx-%2fr#lpM;NukA+*| z6X8?v+mdG?ycAxE|Anv(p89HpTj90v7(5!~In0Dlgf9!<;vO0Hy7yl*YR>UNH0N{& zjg-Fbv${#?tn|Yf#T+@KI7`lGxA<^I!JJVrXB6kh8HJrQ3g(Q0Iiv9BjL58+HEvLJ z2ZL(fTk5EpbzVciC~;wDFZAQ=*em@!?jOw=>N@ABn(+w+LxPA`&3M&}SIx8D{6rsb zay-vlHP2i%&s{a+f1!SUH{74`su{1E@v8edBHr)7RsP+_r|$X6oU!bh`=#_3cc|+3 zQ_cNUb3fH_w=|#kv;S1TYUWeTe4){9THvjUySN0$`>_K5z$Wy$0B;L_0e`bWL;D)s zoNe5PdE(Bsc+b91b1dz6+S~`vTK^8!yVkud_BnW`@HPB_?*AJcc9{Cu>Bug(TUL+~ W`7;{e_sIVU_znHr6rKv#g&zT4Hu)g{ literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_W629_init.has b/has/resurrectors/Samsung_W629_init.has new file mode 100644 index 0000000000000000000000000000000000000000..350d18a71765c951b966016abb50b7884cd0d52a GIT binary patch literal 1632 zcmb`Izityj5XQ%U5}(isC?b@?5(jbwMG6-bDN(;iTx-%2fr#lpM;NukA+*| z6X8?v+mdG?ycAxE|Anv(p89HpTj90v7(5!~In0Dlgf9!<;vO0Hy7yl*YR>UNH0N{& zjg-Fbv${#?tn|Yf#T+@KI7`lGxA<^I!JJVrXB6kh8HJrQ3g(Q0Iiv9BjL58+HEvLJ z2ZL(fTk5EpbzVciC~;wDFZAQ=*em@!?jOw=>N@ABn(+w+LxPA`&3M&}SIx8D{6rsb zay-vlHP2i%&s{a+f1!SUH{74`su{1E@v8edBHr)7RsP+_r|$X6oU!bh`=#_3cc|+3 zQ_cNUb3fH_w=|#kv;S1TYUWeTe4){9THvjUySN0$`>_K5z$Wy$0B;L_0e`bWL;D)s zoNe5PdE(Bsc+b91b1dz6+S~`vTK^8!yVkud_BnW`@HPB_?*AJcc9{Cu>Bug(TUL+~ W`7;{e_sIVU_znHr6rKv#g&zT4Hu)g{ literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_Z240_init.has b/has/resurrectors/Samsung_Z240_init.has new file mode 100644 index 0000000000000000000000000000000000000000..ad02d5198800e43f416c447c6dcd93fb9762f123 GIT binary patch literal 2748 zcmeH}p>GsX5XNV(2VF=5*HS?+EX|1%hyo{?P|<`FM^aJIG{{R@5(EO0iV8xPqzRP> z1hNu=Kp+r^6BQK*1b+a61O$N!k`_`}zHfHsZthYNia@bR^L{h$dvo*Vz1eP26opL6 z1_ph`DzYIR5gKR7S;=*gP9Y^@Xs5;)d;A=l@$p30z68ru$=$#^#(RkWf{cg!D)4sT z*T&3ei(DylSWS={9{Sh7_l@s?i}R&F51OY~o0#TV;5@|N47>&IRx-^kt`*6bJx&Tn zNXS)g!m;PMWQO9+D&LX*7xOVd)dyvf7w5hp@Kics3&Wd-6bM*79JdW1i{EeXb-*;u5 z2JRy3^M`%see^ed=WE$_&i|_KcrU!KxOcaEeFulnYag23>$}B%UuhqjedNBYdEez_ zU!fL!zwi$8_m9$d?4#*3_emd-0J5Z$xUd|@3oWU8Sq_6GV&}qyI%0Mq54tN zXZRn-rlh|PzI+JhSPQpmHW(i-o>JfM%_s2leMmpQwZy)){5y(%{q8cqe^b%lRsAJh zyG^z@JHa2nwcf*jMQW=581$dOYBiZxh N`)A5>&Jd>!{sr%S;^hDU literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_Z500_init.has b/has/resurrectors/Samsung_Z500_init.has new file mode 100644 index 0000000000000000000000000000000000000000..efb3aa2000cb99dcb595c7597151ca3c9d8a12b7 GIT binary patch literal 3112 zcmeH}v1=4j5XNWkPP2xfmzcsraMctkEFxZ!B1OP}C!`1%)bbz^EG!gKScq96pnrgc zrKN?1g@uJhiWDgtgZ`IkWy_a-$y4N`|rFqW?DduJavmb)xo{67vMPO^@o2nRxfJm^ zIO45QF5UCo7C8L5@Cf*@$BYZNg$r=hnE*$fN#QdR-w~b?o&`spIdIhJ3eQXYqVR%n z4;*!t!BOYB@C}Jy5x(jC2^zj}oii4|#XG;(YtjE#+7{3mpE|`)h~|^RQ{W>W(-EE) zo)MlEo)hkZv1HP_=7kr87bX6xuw{Gt6vDH@J>eF(+4Ok{&j~L(e}z`m$9v9bbN&5D zeoHoW+J%jh$xd4BRMjD$4>bxMsZq=Q)F^kRMhBg#Q7|=%Z$^#6PmLm%8U<6Mh^Izm zj+tXz#h}rT`)n=vMj0wVD4O^PpZymjRpk`keV{_jN>mS_7N?d+uwZ;rHQG-*rcL zdLQ3kRohrodH?-t^Zjb`{c6WrvOKn+FzzT#xXP2rCDhw z&tJRGJ%h|#+Kjn?UtMc&ZLtUVjDC(O>ZJAJ{z-}XzfaUUX)kDRQODoy6Vdm7vQI=V z_le+twNG$eM4xl+VYAQGW}mCw;<|@}3pDc8X1?0YSDSstzAqQ|`dn@HncD0#wVA)K z?+0w=>vQI-&7Mg6E#{y0gLW2o-zUo2#zyeB_X+m>)KQ$txC!`m0Qa=!;E&$zfb(zd zVfv@Rw=65jGvMN4#p$IwL!MjU48cu={t_|3#A~dB4VHec@z|>#!5_?Xs`)uJ&Y+A> zXIA&ed6fS36n{3=+#vhAu>GP=?bmbaJNVC8JH>yH_>bUG_iu@RSN!--?AQMy{vC;L tA!evCmg?sc|4`;gj&V|l(>~?`b-K>hwB?AI$63GSesX-5IwMT#o|ITFi*oM2&Lks^hd6$1Ka zq!dY!!ong&3X2pL7XATtRvJ4K(5&CLJ99U8AgG{~f$)B_@0)qM-_C@@7^BR~9v<-= zzcZE0(idTT&Ekd#HBFIzl+1_V+1VnkzXr?A%*T#T9KRxK?vdj+j^8@oCs*>fwhP&_ z+#T=}t@9WhuV+ngnit5es^$P(CU6+XXVr1n>3fdX9QVOiX8^W34;(*q z`fbOLlt076_v(4U0{G#R-oDdy^3S|&z-L^$_ST*UzPCMdpI;D9Yo4w1EY#7vv9nIZd>al)|Uva19u>M#KJ)f+x z{?BLjX{=}I&o9oW&D)>Mr{!`!jsMkrvM+4@cy^12^N9s}pXOC#o6pc2%^&C0;@_Un mdXeX}Ug&&=97`zw%6wL3V7=eP|4jC`mP`*gH;d4$BlrQaP-n9M literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_Z630_init.has b/has/resurrectors/Samsung_Z630_init.has new file mode 100644 index 0000000000000000000000000000000000000000..c4f0b789638d4bb6e477b604de3c95bea158801b GIT binary patch literal 1372 zcmZ{ju}%U(5QgWtQ&)3|P-$UtF~k@`K|w)542h?nib?`86c!d1z5$KJC6Y*CL1AHG zVPWB8_%;^4gX=$gyWE7h6!7ugzq7M*ci&oTBFeS?0cl+wQ64}rw^EumEVscx;}tlz zOoCex0-mk3aQz9Lw~!+~>K+_dWi?<1an_>L0%^ z<}YX7f_KkA8|>!U0V`XlE7tbF?!KhLXW$i^?+YG)U7Zow?KK83?kV^YfB0U@-V*rG z`np&vGwk>5zEKT%G{l94kf$=kN n&*pRRmSxVbT9*B>U$Z{Ov+inUU^f?jpIv78eRiIZ=Xw1Bo_0tA literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_Z650i_init.has b/has/resurrectors/Samsung_Z650i_init.has new file mode 100644 index 0000000000000000000000000000000000000000..c4f0b789638d4bb6e477b604de3c95bea158801b GIT binary patch literal 1372 zcmZ{ju}%U(5QgWtQ&)3|P-$UtF~k@`K|w)542h?nib?`86c!d1z5$KJC6Y*CL1AHG zVPWB8_%;^4gX=$gyWE7h6!7ugzq7M*ci&oTBFeS?0cl+wQ64}rw^EumEVscx;}tlz zOoCex0-mk3aQz9Lw~!+~>K+_dWi?<1an_>L0%^ z<}YX7f_KkA8|>!U0V`XlE7tbF?!KhLXW$i^?+YG)U7Zow?KK83?kV^YfB0U@-V*rG z`np&vGwk>5zEKT%G{l94kf$=kN n&*pRRmSxVbT9*B>U$Z{Ov+inUU^f?jpIv78eRiIZ=Xw1Bo_0tA literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_Z710_init.has b/has/resurrectors/Samsung_Z710_init.has new file mode 100644 index 0000000000000000000000000000000000000000..ad02d5198800e43f416c447c6dcd93fb9762f123 GIT binary patch literal 2748 zcmeH}p>GsX5XNV(2VF=5*HS?+EX|1%hyo{?P|<`FM^aJIG{{R@5(EO0iV8xPqzRP> z1hNu=Kp+r^6BQK*1b+a61O$N!k`_`}zHfHsZthYNia@bR^L{h$dvo*Vz1eP26opL6 z1_ph`DzYIR5gKR7S;=*gP9Y^@Xs5;)d;A=l@$p30z68ru$=$#^#(RkWf{cg!D)4sT z*T&3ei(DylSWS={9{Sh7_l@s?i}R&F51OY~o0#TV;5@|N47>&IRx-^kt`*6bJx&Tn zNXS)g!m;PMWQO9+D&LX*7xOVd)dyvf7w5hp@Kics3&Wd-6bM*79JdW1i{EeXb-*;u5 z2JRy3^M`%see^ed=WE$_&i|_KcrU!KxOcaEeFulnYag23>$}B%UuhqjedNBYdEez_ zU!fL!zwi$8_m9$d?4#*3_emd-0J5Z$xUd|@3oWU8Sq_6GV&}qyI%0Mq54tN zXZRn-rlh|PzI+JhSPQpmHW(i-o>JfM%_s2leMmpQwZy)){5y(%{q8cqe^b%lRsAJh zyG^z@JHa2nwcf*jMQW=581$dOYBiZxh N`)A5>&Jd>!{sr%S;^hDU literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_ZV60_init.has b/has/resurrectors/Samsung_ZV60_init.has new file mode 100644 index 0000000000000000000000000000000000000000..238d5f9fe557b6cc188cba0cd6f900355d40e712 GIT binary patch literal 1668 zcmZ{kKWkG_7{=e5dt$FrFrgq08KM*kMKD8#41v~q)mZDFp-4wZ2L}fS2f+)r(4j+y z4jDRh$k3sKAHfgc;D-<_)WHuR-ahYp&Pg7`6A1a`m*>3qJ@36aKkK>{k*cmQKy}^P zkt%~w?w7K+7I**#nlHf1frYs5q>7mVv4Bx7)0)n6t~{j7h`8_>%P&*@q`9a+BR*}) zytgyrFO)e1>oxT?FgNyU% zVy+KDU#nmjSbdrB4-@`T!aq*^pQ;jKOiHdd}Pl`G3!u=mnV@A=3fJ`wCUz qZF^VW44L4qXZ7(u3H9&;JlzyKL(a+nBK}Pr&Pl8J=My>-*|-E256JNV literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_i450_PDA_init.has b/has/resurrectors/Samsung_i450_PDA_init.has new file mode 100644 index 0000000000000000000000000000000000000000..829ca310b6d225a1b4d478ee60196bf8248f8d36 GIT binary patch literal 644 zcmZwFu}T9$5C-5`Pvl5pqS&O$`34g50EZmG?Tv-iMG?{n0Snte#5WK`EG#VKDhr=L zEbMG7wDBbj2x46Se{Tmi;5GN<-?`b@+|8VGk~9T3_eq>iiByOP|xa7p?z8>@(!uP+!8Ur}eXRBX|_$wC4A)&iM-KJWud>akbBx ypJ6@Y8;q^|Y_!fs>uj+fkT1-363rIuXN%kj&bb$w@_lqR#U|Ky4)-$SzlT4x10JFP literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_i740_MDM_init.has b/has/resurrectors/Samsung_i740_MDM_init.has new file mode 100644 index 0000000000000000000000000000000000000000..dd14ff64de99eded0777a55c677c34a7fd3f6de4 GIT binary patch literal 360 zcmYk$u?oU45XSLq%}{But^Nd}=4{5CGYq*oXQEpW~Q+*HjCBM0Ve}Ao1 z?^M5mPxvJ5yiK06ckmtiyfG*8?)l%}yTh8B0&|SNcPnKJhY*(Ot{Kqe(!=xfm3!D< Rcy3{HJXkeWzRyh5xI6aqRpIN0joVBv}mL2&Ef&>@r#X>o9HD4n_#96Ds| z=!bA{aA-TV&@bV)aM9~|&OL!YW_f=+_r34ENlsN&Rljvt9t_ML-9KM#m%db2zM6mV z^qI%mFTGD>&nGu$uz$94Kl|ooANT09xPBqmKa0OU-)nZ#OLA-@s@a3yf1z){wO{ZUx>|i4?3^w_ctp>CvE!`zpZ;c|BKSSV^-3~ z?&hLR@x*Pm9RI~Pceh)gGmUP)*<+1j^xq?!&a0 zv22+3*RR=9eIBNjer?t;EoM9SVcO7F=AC!Jw3xGOm=^Pv4bx)ovSHe(ue0+oZ7dDb zCeko1<}%O2w3yFqm=<%I4bx&?vte4yZ8l7c`OSuDF~`|3?abHN_rSE6>)eN*02R@I AWdHyG literal 0 HcmV?d00001 diff --git a/has/resurrectors/Samsung_i900_PDA_init.has b/has/resurrectors/Samsung_i900_PDA_init.has new file mode 100644 index 0000000000000000000000000000000000000000..09ce089b5fbc067345f4286667043d755020c4f2 GIT binary patch literal 864 zcmZ9~ze>YU6bA4wA(}`cO(AFsEfm_JLx*ZRbWljCLlN8@92|l;L~(HFQ7TT!)Fk31lc$rt35oRROz zU2>m1A|H`2$=BpN@|+BeCf-4HejuEkx%epGt+->pMIs&oiPlrGT}Q6Y#K3;}Egr?b zU#*jub$n_DRyeylwzkxv*mXOxIwHs9Cb>=Sl6&Mn*+DpMwd&=00`V7~oN`}ax@+#D T|Jr!FI_FYsoBBfB_#Wa9FkXbc literal 0 HcmV?d00001 diff --git a/has/resurrectors/Sungil_SXC1080_init.has b/has/resurrectors/Sungil_SXC1080_init.has new file mode 100644 index 0000000000000000000000000000000000000000..afa7ee5d756d6e1e3147d29d5e9608c086acd903 GIT binary patch literal 624 zcmYk)p-uxq5XSMjqmo<_X3g@{5_za0##BA$*_5Jx|JJ z=hMVziH{Qpcr3YnufX}GQ49DR^SS?keTd%`a3`aq=H8Il4l6e9rJH+RY&QE~#CE9s zERCM??^>~8KXLQ<2<9iBU&FQcGjI6r^Td0YiNx;bz|HeFK8O7+jfLjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/Unicare_UN510BF_init.has b/has/resurrectors/Unicare_UN510BF_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTEC_N600_init.has b/has/resurrectors/ZTEC_N600_init.has new file mode 100644 index 0000000000000000000000000000000000000000..64b429dbd3c4b2ae86bff4237229e4f2e0febd65 GIT binary patch literal 972 zcmbW#El&eM5C-6Bfs*hMDvBW_oT#X%xM27Qq9G?LDhR1SAR2;1AlhIWasp9-z>pvi zC!3}Mc@n`7K%5{1!9M_jU*6fBfe|R0G6H&N(+r?-`LxLAO2A8c@M*&o z1$W?duH@@`@Rnp+oDnB*Nz8pJVxlO|Rze@H&r5wB)>%!M;*g19ofW|i$=5j}ZooQ= z`}{SF>pH7Oz45B7y@Kg5%vyqXq+W%!C&A8bT=G3s%fEAL#!Y0>wa|ws9%l=|efUDo z8^IH)w_)crALVo!+(P|fF*t!if6oW-?MZMK9!dQOPWMCo7#`qOc%SDmBHm}Po_z>c zZbJPL-j&QVoFt)M7{3_58Gpjs|BLI=$Ij(5YNi8kO6JMbdu&|vhwhm#9p8AsE5m+# zMr`|En?Co(Q{xfbm9=-qcwj&E+?ex)$*Vc9=DeEUGoGry=l{&YQook>rsi2{o~3TV Zxx9^tvh0Z9u#`ORI literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_AC2746_init.has b/has/resurrectors/ZTE_AC2746_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a8a42799e2760ca5d75fb73c0168980094bf38dc GIT binary patch literal 2216 zcmdUwJ!=$E6o$`?LtJzvY3JRSz5^AQ$Re9)Z_R=9>4xZRZREX9$j5&N_1eA9dV7UwB%l z3HJU=_?gSM!a8HlZ2f+~0>+3D=S%_~1kNzvM&L99-dLH|f4(B?zSk4vD1DvvpCZR) zp4=$$Tt#f>2MdN~zAw{tyJuul+`Cy%HO)sCbFZqo~!r3(EmmALfwvMLrc%Ml)GxHMJ;k^`a%sSi1 z4xI#l;QXKJPvpvUem)$|e>wle1ncvc^)b!#{c-!Q?;AhB5$*-^x0icIxbNimVD3u~ ztn!S{{1`I&kn&u&7H68{C17c{C@Y6{_b_a zH(IA!oGkY3JRSz5^AQ$Re9)Z_R=9>4xZRZREX9$j5&N_1eA9dV7UwB%l z3HJU=_?gSM!a8HlZ2f+~0>+3D=S%_~1kNzvM&L99-dLH|f4(B?zSk4vD1DvvpCZR) zp4=$$Tt#f>2MdN~zAw{tyJuul+`Cy%HO)sCbFZqo~!r3(EmmALfwvMLrc%Ml)GxHMJ;k^`a%sSi1 z4xI#l;QXKJPvpvUem)$|e>wle1ncvc^)b!#{c-!Q?;AhB5$*-^x0icIxbNimVD3u~ ztn!S{{1`I&kn&u&7H68{C17c{C@Y6{_b_a zH(IA!oGkn-R)p0J7PT*z8cY2+&?ZD4Pe!mVvTC?t$r5U|6u=7Q>ZQ UAor*M*)=6DV0+g9*}OpY0BE^g^Z)<= literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_C132_init.has b/has/resurrectors/ZTE_C132_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a344435b4c926679e3249f44f1fcfccb0f0ee769 GIT binary patch literal 760 zcmZ{gKW@S>6vn?0C{RTrl`=3!NFa6V5UJ3nfA+2%AV?elsY^F3)Fbo&3>~W8qBrO< zIwHZ)PUf@Y$d5`MlKlM3_nx19&{`uJ-~}BJb@~{q2(XMVsBXhC6w&$~Idhx{pOTx} zq3{`bbCK6Q$t_o#=TJ+>pg$A-Cw4Q?n;HH%TN_aNnG1rMm2~oNzqY@8mg`j1KCFPM z?`ye*?Q>Q6vlW6t<~9SfSG#6|dMYxd;GW1QBEMbu{s+My3%qg!JHtD@ZO+$@+}!&c zGgNklbPILw@)?=eU~7%P3-~hNZv*}&;Aa6p4fyMTAN}*cJRB8vd<=h{1K)zjj^`bM fWAlBQ`23~trVrcbq-rS?QGGw;0yUT92xEN&%VAS` literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_C335_init.has b/has/resurrectors/ZTE_C335_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_C370_init.has b/has/resurrectors/ZTE_C370_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_D90_init.has b/has/resurrectors/ZTE_D90_init.has new file mode 100644 index 0000000000000000000000000000000000000000..350d18a71765c951b966016abb50b7884cd0d52a GIT binary patch literal 1632 zcmb`Izityj5XQ%U5}(isC?b@?5(jbwMG6-bDN(;iTx-%2fr#lpM;NukA+*| z6X8?v+mdG?ycAxE|Anv(p89HpTj90v7(5!~In0Dlgf9!<;vO0Hy7yl*YR>UNH0N{& zjg-Fbv${#?tn|Yf#T+@KI7`lGxA<^I!JJVrXB6kh8HJrQ3g(Q0Iiv9BjL58+HEvLJ z2ZL(fTk5EpbzVciC~;wDFZAQ=*em@!?jOw=>N@ABn(+w+LxPA`&3M&}SIx8D{6rsb zay-vlHP2i%&s{a+f1!SUH{74`su{1E@v8edBHr)7RsP+_r|$X6oU!bh`=#_3cc|+3 zQ_cNUb3fH_w=|#kv;S1TYUWeTe4){9THvjUySN0$`>_K5z$Wy$0B;L_0e`bWL;D)s zoNe5PdE(Bsc+b91b1dz6+S~`vTK^8!yVkud_BnW`@HPB_?*AJcc9{Cu>Bug(TUL+~ W`7;{e_sIVU_znHr6rKv#g&zT4Hu)g{ literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_F160_init.has b/has/resurrectors/ZTE_F160_init.has new file mode 100644 index 0000000000000000000000000000000000000000..58e6b5ade4927b7d12d07a9c03ed752045149ce7 GIT binary patch literal 1160 zcmb`FPb&ps6voe7<8R5h$X#4D>M9HBCJT$Zm|NFE`4HE_-hxu3mn0v7Zy-s0gSoP_ zP^_%j*Prv_FMx8p6OFi+@-kN^CUEHNMH@+Sj>%Q7x$V{AZEjkQDV#Bu=Bui z4F0;S)N1!wRxHheG2W*JPP!8Nj_ji)kte(p#Aqfo@{jvwUK+T%q9iafn#~{vN9P3> zcl@IGA>#`5c<4jE5D9sgi*q12i(^!@HL2oDaIO#Wf%BjGmdv#M**DH#{w<^G`9%*G z*Y7a;9g&HEy_dkTbPSTq;O2Oy;XKpcY6s&2E=uI|oaff#=>X&IU+pFG2B!WM?;d~0 z_noPuCg$j!iLe`aP2gdl8|yfH*DBL_t@Ywikv`vRy`IWytwP`DeaJ;H|5F2Oz&v`6 z)a)Qe&pEKP6sH;2RNOJ*?3uH$Fh}~2GvF>kn(x>(INzBFA2_-ew|ic{Vx(!p`;c|5 wf)5v-=gI4gZ{Kf|H^Gw16&cNuQ}V9jeZ?{OPHvB>sem_E8?Lq!a6j(-1dylxrvLx| literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_F280_init.has b/has/resurrectors/ZTE_F280_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_F285_init.has b/has/resurrectors/ZTE_F285_init.has new file mode 100644 index 0000000000000000000000000000000000000000..12fb1d7c75bba4f01c66eb6facd8d95b46aede78 GIT binary patch literal 644 zcmZwEp-uxq5C-7c%|aVe!jTXx2Z02Ms34@G0)edH0ZMWYfan8^K%77zDi8<+0$ITW zAb1c20un?83Ap8--97RP&g^${|IO^}#TcV(iwZ6vQCsbLB0sP$#>*? zvcg@T8v8##eF=8IpT1?&n-9&ElW%xSWNK$<^?}nyR>H2iGMD;@>SOa>&I_!XJ@?vl zeFEy<*QsaU@**zvm*>gH>}1{M-e7JI56sua_KzC+zq4eQ`ka|}@~k1;$GiXL!$qoJ cB6C0)PhKV49+sH9h80W1@^>DAjCra43$@xS0RR91 literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_FWPC26_init.has b/has/resurrectors/ZTE_FWPC26_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a5ae6280a9e024dbde752d2e6390ff07f2976f74 GIT binary patch literal 212 zcmezJ|NnmmMt+70237_j^S=i>LjyYl1DMSq#?Sy{g4qHN3>}P6wgONbBmq*Nf~2Md z%w~j`17gcV)R+L-97yV!plq;umPD}n0-zcdBsFYEY><0C0PW&}iUFwvm|Iwo*g!kL F;sE^HR!RT> literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_MF170_init.has b/has/resurrectors/ZTE_MF170_init.has new file mode 100644 index 0000000000000000000000000000000000000000..df0553f0a8eed10013f6ef4203265f64e05f506a GIT binary patch literal 1184 zcmb`Gy-EW?6ov1`^%ul7MobZ5g$Nc3K`c_FSRodI4-pId6bgbtMiKE5^bJHr^bIy* zX%W!MDt2}%2x1Dyb7qIl5Tca}!+v}A%$YlPXSLQ^L==VqwePUhxsjuiNZw6tmwP_B$=} z9`~LHhcYlpE`V!uiHH4+M@s|L1)P<@_}S0>m#Yct=35;{@&%^<6Za9jM(;UXMNORJ zp2Gm=Ev*ThvvWgNNA6B>DXn!iJC$WlZ>_Dxq}CGrV>XAJ1@k*q!3xab_K}`LXv{2w zrRi{-aK+ILL+75^3ypA0@7n{OC0Nrl)&i$zCcp!RTZ=h+)*s@(d6LHq)>Q;IwyP%R I5t z3l}L|q)6c+1qF}51Ek19ASF^LcmT-po7tV*6l^3bpFaO~c6RQ(msM2}QF&8c{{>d< z36%*1b6(KlgTMnYP`m@T0+Zo9qf#>i!vsdTgllG=Q|6(`j0`)Uk$lVKPn&i9h2gU% z-S+m)@OP7$f_YE=n+b2oS&otC39z3t-}8Lp^U^2IbbGGMu)8DP@!B=R)Tr~Lq~^@9 zGt7CNc|WChM-AV@L&NM>j92c$r)ZFS$idXgg$ITgD^wOmCjK1Ud0Z5nzYy=aOsPb9 z$xOlbI~_Uu3=A#)*!a2eC*Uu%x5qV4jbDJ%v@L7Tj3?$F{Y}o}jI!?ySog``bRIp- z^-0)&9h?PbUqt-Vh~J9%XAwV+`0a>)9`P?CekbBzM*ORYfBhd%?Rtg|jEFpk9^SPf z8s*vdO~(2hUf+cQSZ6*2yHIBYUJCrkZ~@k5H#U9;tZUyGo|ybw!#(f;3UQyzsj}&R z9bWsi{j=9+ly&$W^mPdQbyC+nK>zaI%@Y5gNbVfo4`0dNevK3UV1D}_!FNOE6Bt`a zW*4mU+6P06{|qj10q}Xaj`q#0bF^n*zZ}+D-^Ka0<{0ckhVPm8f%%^KQ~AC4o>@xd tYOe^q8Zuq5_6b$u)8O9NH$x_P>6yJgSHix^Kf&`&KesF6e;NKA_#Y+7!=nHI literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_MF627_init.has b/has/resurrectors/ZTE_MF627_init.has new file mode 100644 index 0000000000000000000000000000000000000000..65a81f83741d41ce5936525486601ba9ef787388 GIT binary patch literal 1380 zcmZ{kuTBF&5Qpb_M_CG@H3U)7kctXKMMXsglmiNsKcWJOA_xS6qzJ?%C4mq`1)>6h zsNgYp00a+#Kp=Pk;P}nnPHqG%ntu5*J2N}Gw`rQDCZ=mcM8K3Z6D82rM~cmy^@ih@ z6jLFO?*utVij8894_y96NXK`Dtk#NR_9f+otMH*)+XT}>)Ard?JS|ZY$C34~;L2JY zbI)(qXPktTAia&b2QODDA;*lt(AGaFKT-Y>d_%(_$3H1Q1&3kTu6jHt z-CwZOiQr@&HOzJ0)vtpi$LwQ|-|+ZNkKgk6p2u%{{Eo-(dVJsG_dI^z;}8DvRL*B; zzzDJDP{UnoqfwrHL&a#{gqOR}0?W+XVEH~e;G)a9syGJA+4Yp~gJtcZ;(>}kQd|R% zkcj(a4uw_!b$IDh_s?F=D5~%s%<>TUc97>Bp?`bt#zFQ^6i7XpSGLC3K2FuQe+Hg+ z`#%SxgpIiX%e*eZlIIGX-~r(LoJaa*mO1J@u%C4~wXb6TlCuXkE{5Nk6UY3{e5YA0 yerJlo50^~|yy#-8VCfSo!LPtE>}Onz^R{R9a;}8B!tdZoH=Ems@}G*o9RC3*U_0ah literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_R518_init.has b/has/resurrectors/ZTE_R518_init.has new file mode 100644 index 0000000000000000000000000000000000000000..81f0ef9e122ab75dd99888cf8308d65353383a4d GIT binary patch literal 2280 zcmdUwKWh|07{=e-TjHT7S+`%jb2|jjKVaj+W`B9+nP=X4ckb?>EX!=%up(k` z>ot$RkjtKkjUDG;pz0&=`YEH_2X~x42s}e@NJ~{ploPt^FAs7!U(u}ER$Y?kZ^+>W9a+&6hX?Aa1@2wxOfMJd3 zPXZnUo?*bvz|#tNYo*SAz9Ji_L-)T49nm+K{}ehN^W4$p>QfHhM0XCp!WqRZi#@HxhSouB82=Yw;@a}#=) z(+NC2XB%sIeFyCIa4z%D1aq;huElfdbw10Gy71bs<)?GpS8C#o z6E3F%P8_FObxsEy>Q}x0h~EE+o)uz8xVV;4PIQmmK)+ORLeHXd)rUS<@{#Jdl#>gZ zGZAa>;Uss#7ahwuwzh~=Pw02`EWqPA3pmXqD`$IhfE+`17yHdi*MgqDihu9<@&}%e zm8UynEwAgo;CU^Qur}5CMTFbj(bBXY@23*hOuc|Mol66*qn=%8Q%{0_aQ{#F6S-2? z&&}cfm-SC<(4W7|M>X~NaqnHv8wYTO?}GZ9%e@BQJNZ4B@1+M;^ASJwHz8JVh2s!Zjg@(*YDRd;@6=kLt$Q-9FCroVd&;G6B!ZPu27&G~9A znK74oThfU2|LSvkeLtS3C&%}IHW+&j`!Ix_&y`i*z+Lo-HT220;$>Uw2ESt;1yxF~%snqJj&I)mT~w|H2C=)4I4uMvFgsId7Ra z@)vnY{wBW{+pNVv)KbZN2BY3OyoKw#`@;&*1 ztZ>(-#{MT~ufgsQ(^{iBBd?=0D+KIi7WJZlK|@$SF*aGB~? d$lz?Nj3=*?Z4XP#-N1?^Vp)BUK*qdO{{yf_D)0aR literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_S1602_init.has b/has/resurrectors/ZTE_S1602_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_S160_init.has b/has/resurrectors/ZTE_S160_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_S165_init.has b/has/resurrectors/ZTE_S165_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_S170_init.has b/has/resurrectors/ZTE_S170_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_S183_init.has b/has/resurrectors/ZTE_S183_init.has new file mode 100644 index 0000000000000000000000000000000000000000..a344435b4c926679e3249f44f1fcfccb0f0ee769 GIT binary patch literal 760 zcmZ{gKW@S>6vn?0C{RTrl`=3!NFa6V5UJ3nfA+2%AV?elsY^F3)Fbo&3>~W8qBrO< zIwHZ)PUf@Y$d5`MlKlM3_nx19&{`uJ-~}BJb@~{q2(XMVsBXhC6w&$~Idhx{pOTx} zq3{`bbCK6Q$t_o#=TJ+>pg$A-Cw4Q?n;HH%TN_aNnG1rMm2~oNzqY@8mg`j1KCFPM z?`ye*?Q>Q6vlW6t<~9SfSG#6|dMYxd;GW1QBEMbu{s+My3%qg!JHtD@ZO+$@+}!&c zGgNklbPILw@)?=eU~7%P3-~hNZv*}&;Aa6p4fyMTAN}*cJRB8vd<=h{1K)zjj^`bM fWAlBQ`23~trVrcbq-rS?QGGw;0yUT92xEN&%VAS` literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_S185_init.has b/has/resurrectors/ZTE_S185_init.has new file mode 100644 index 0000000000000000000000000000000000000000..d2ce276db09e81bf241da10752d93afa5d492312 GIT binary patch literal 640 zcmZ{gI|{-;6h*JbF9?Z{!ZNr53&CIfEG2>q5Nzxm#3i@@3k$d5ZY%|Dtj0T&33&?B zgfnN}=VsnoYg9t)Q3p{+t3Xu%%eX@|3l5-&*0;#99m9;!aqIbCkvUb_a6?V=bEB|dM7-X&q z&8}L`2K89fq=H+bz9Z@{>vH~E@NJC~BiIaAdOMt-C%Jg{Gi#`9hUfydaP={n&tQ9v YpL=}j@iUK~di=!W#~wfO`2L^&0uCf0VgLXD literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_Skate_init.has b/has/resurrectors/ZTE_Skate_init.has new file mode 100644 index 0000000000000000000000000000000000000000..f9f89de2a1af88beb1d0f2f3ed8432af4c8426f4 GIT binary patch literal 2276 zcmchXziSg=7{{M9sYZ?Tf*D#}ZcssRh`Kn4W{9+v2t_+M2nKO<$Pj6VA~!V9!BIrf z;l{M|4@kER85|ulh&W`_p%^fOOM8C5@B6&*CnF*U;7zHwCGYV)F&dGT_6#)C=fJ0wgIut^pj-k+$^sTRP@nfWCxaN)=m+fI z4iCAEc=kG{z72`vXfaykS`!>+<1Bd{yjR>Sk~e5?#Vv9K4!dEOyy@|lGIRaXToTw^ zvwXnr-}`tswWRFyAF6-Wx(nw;{X;zcUQArrCdI#>(sQQnVw{oY(K6*S7LTgGK&Mol zcumaga)TV1vwOEZTqbjNQEOo4#o0+udbD$P(v|V-9CLPL_IM{<1HKPl$63QQCPXd% z&H7Eh`9Yq{e&0{(w>y2mmyqhOXa1jSm`~R*&CCmf!W47(NX<0+e&(2F&U$WU>*N2+ z5?IP+yOSC?x|=ck(U_5Klr&^nyxbY&ndE+X>*n~lbv{$;Axy%v&fK?<~b~0 za5cWqX~zaL<_7q}Ys+1*+xJgkS5M#L&mMpEc-U6?x=B>y0_{R2*$JF;dy<_SfQ}392hofp{ r`!BiRYJ6FnW9D+qT#hT?dHps*{Oi9+e}{W|5&W`QHF0*qXW{T0A(5zI literal 0 HcmV?d00001 diff --git a/has/resurrectors/ZTE_T40_init.has b/has/resurrectors/ZTE_T40_init.has new file mode 100644 index 0000000000000000000000000000000000000000..0abe0b7e9bbe3ed635800486a88653506e891562 GIT binary patch literal 392 zcmYk&F$%&!6a>(T2D3=O71G#y0Pz@B9$`xlA($eFpoN8ng$GD_iySKlP}cd$SAVsS zVKRIYV~jpQn*eyz6+#VXya5Y3JRSz5^AQ$Re9)Z_R=9>4xZRZREX9$j5&N_1eA9dV7UwB%l z3HJU=_?gSM!a8HlZ2f+~0>+3D=S%_~1kNzvM&L99-dLH|f4(B?zSk4vD1DvvpCZR) zp4=$$Tt#f>2MdN~zAw{tyJuul+`Cy%HO)sCbFZqo~!r3(EmmALfwvMLrc%Ml)GxHMJ;k^`a%sSi1 z4xI#l;QXKJPvr7+em)$|e>wle1ncvc^)b!#{c-!Q?;AhB5$*-^x0iZHxbNimVD3u~ ztn!S{{1`I&kn&u&7H68{C17c{C@YU{_b_a zH(IA!oGk - * Version: v2.2.1 - */ -#include "lwmem.h" -#include -#include "dcc/plat.h" -#include - -#if LWMEM_CFG_OS -#include "system/lwmem_sys.h" -#endif /* LWMEM_CFG_OS */ - -#if LWMEM_CFG_OS -#define LWMEM_PROTECT(lwobj) lwmem_sys_mutex_wait(&((lwobj)->mutex)) -#define LWMEM_UNPROTECT(lwobj) lwmem_sys_mutex_release(&((lwobj)->mutex)) -#else /* LWMEM_CFG_OS */ -#define LWMEM_PROTECT(lwobj) -#define LWMEM_UNPROTECT(lwobj) -#endif /* !LWMEM_CFG_OS */ - -/* Statistics part */ -#if LWMEM_CFG_ENABLE_STATS -#define LWMEM_INC_STATS(field) (++(field)) -#define LWMEM_UPDATE_MIN_FREE(lwobj) \ - do { \ - if ((lwobj)->mem_available_bytes < (lwobj)->stats.minimum_ever_mem_available_bytes) { \ - (lwobj)->stats.minimum_ever_mem_available_bytes = (lwobj)->mem_available_bytes; \ - } \ - } while (0) -#else -#define LWMEM_INC_STATS(field) -#define LWMEM_UPDATE_MIN_FREE(lwobj) -#endif /* LWMEM_CFG_ENABLE_STATS */ - -/* Verify alignment */ -#if (LWMEM_CFG_ALIGN_NUM & (LWMEM_CFG_ALIGN_NUM - 1) > 0) -#error "LWMEM_ALIGN_BITS must be power of 2" -#endif - -/** - * \brief LwMEM default structure used by application - */ -static lwmem_t lwmem_default; - -/** - * \brief Get LwMEM instance based on user input - * \param[in] in_lwobj: LwMEM instance. Set to `NULL` for default instance - */ -#define LWMEM_GET_LWOBJ(in_lwobj) ((in_lwobj) != NULL ? (in_lwobj) : (&lwmem_default)) - -/** - * \brief Transform alignment number (power of `2`) to bits - */ -#define LWMEM_ALIGN_BITS ((size_t)(((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) - -/** - * \brief Aligns input value to next alignment bits - * - * As an example, when \ref LWMEM_CFG_ALIGN_NUM is set to `4`: - * - * - Input: `0`; Output: `0` - * - Input: `1`; Output: `4` - * - Input: `2`; Output: `4` - * - Input: `3`; Output: `4` - * - Input: `4`; Output: `4` - * - Input: `5`; Output: `8` - * - Input: `6`; Output: `8` - * - Input: `7`; Output: `8` - * - Input: `8`; Output: `8` - */ -#define LWMEM_ALIGN(x) (((x) + (LWMEM_ALIGN_BITS)) & ~(LWMEM_ALIGN_BITS)) - -/** - * \brief Cast input pointer to byte - * \param[in] p: Input pointer to cast to byte pointer - */ -#define LWMEM_TO_BYTE_PTR(p) ((uint8_t*)(p)) - -#if LWMEM_CFG_FULL - -/** - * \brief Size of metadata header for block information - */ -#define LWMEM_BLOCK_META_SIZE LWMEM_ALIGN(sizeof(lwmem_block_t)) - -/** - * \brief Bit indicating memory block is allocated - */ -#define LWMEM_ALLOC_BIT ((size_t)((size_t)1 << (sizeof(size_t) * CHAR_BIT - 1))) - -/** - * \brief Mark written in `next` field when block is allocated - */ -#define LWMEM_BLOCK_ALLOC_MARK (0xDEADBEEF) - -/** - * \brief Check if input block is properly allocated and valid - * \param[in] block: Block to check if properly set as allocated - */ -#define LWMEM_BLOCK_IS_ALLOC(block) \ - ((block) != NULL && ((block)->size & LWMEM_ALLOC_BIT) \ - && (block)->next == (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK)) - -/** - * \brief Get block handle from application pointer - * \param[in] ptr: Input pointer to get block from - */ -#define LWMEM_GET_BLOCK_FROM_PTR(ptr) (void*)((ptr) != NULL ? ((LWMEM_TO_BYTE_PTR(ptr)) - LWMEM_BLOCK_META_SIZE) : NULL) - -/** - * \brief Get block handle from application pointer - * \param[in] block: Input pointer to get block from - */ -#define LWMEM_GET_PTR_FROM_BLOCK(block) \ - (void*)((block) != NULL ? ((LWMEM_TO_BYTE_PTR(block)) + LWMEM_BLOCK_META_SIZE) : NULL) - -/** - * \brief Minimum amount of memory required to make new empty block - * - * Default size is size of meta block - */ -#define LWMEM_BLOCK_MIN_SIZE (LWMEM_BLOCK_META_SIZE) - -/** - * \brief Gets block before input block (marked as prev) and its previous free block - * \param[in] in_lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] in_b: Input block to find previous and its previous - * \param[in] in_pp: Previous previous of input block. Finding will be stored here - * \param[in] in_p: Previous of input block. Finding will be stored here - */ -static void -prv_get_prev_curr_of_block(lwmem_t* in_lwobj, const lwmem_block_t* in_b, lwmem_block_t** in_pp, lwmem_block_t** in_p) { - for (*in_pp = NULL, *in_p = &((in_lwobj)->start_block); *in_p != NULL && (*in_p)->next < in_b; - *in_pp = (*in_p), *in_p = (*in_p)->next) {} -} - -/** - * \brief Set block as allocated - * \param[in] block: Block to set as allocated - */ -static void -prv_block_set_alloc(lwmem_block_t* block) { - if (block != NULL) { - block->size |= LWMEM_ALLOC_BIT; - block->next = (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK); - } -} - -/** - * \brief Get region aligned start address and aligned size - * \param[in] region: Region to check for size and address - * \param[out] msa: Memory start address output variable - * \param[out] msz: Memory size output variable - * \return `1` if region valid, `0` otherwise - */ -static uint8_t -prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* msz) { - size_t mem_size = 0; - uint8_t* mem_start_addr = NULL; - - if (region == NULL || msa == NULL || msz == NULL) { - return 0; - } - *msa = NULL; - *msz = 0; - - /* - * Start address must be aligned to configuration - * Increase start address and decrease effective region size - */ - mem_start_addr = region->start_addr; - mem_size = region->size; - if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { /* Check alignment boundary */ - mem_start_addr += ((size_t)LWMEM_CFG_ALIGN_NUM) - ((size_t)mem_start_addr & LWMEM_ALIGN_BITS); - mem_size -= (size_t)(mem_start_addr - LWMEM_TO_BYTE_PTR(region->start_addr)); - } - - /* Check region size and align it to config bits */ - mem_size &= ~LWMEM_ALIGN_BITS; /* Align the size to lower bits */ - if (mem_size < (2 * LWMEM_BLOCK_MIN_SIZE)) { - return 0; - } - - /* Check final memory size */ - if (mem_size >= (2 * LWMEM_BLOCK_MIN_SIZE)) { - *msa = mem_start_addr; - *msz = mem_size; - - return 1; - } - return 0; -} - -/** - * \brief Insert free block to linked list of free blocks - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] nblk: New free block to insert into linked list - */ -static void -prv_insert_free_block(lwmem_t* const lwobj, lwmem_block_t* nblk) { - lwmem_block_t* prev; - - /* Check valid inputs */ - if (nblk == NULL) { - return; - } - - /* - * Try to find position to put new block in-between - * Search until all free block addresses are lower than entry block - */ - for (prev = &(lwobj->start_block); prev != NULL && prev->next < nblk; prev = prev->next) {} - - /* This is hard error with wrong memory usage */ - if (prev == NULL) { - return; - } - - /* - * At this point we have valid previous block - * Previous block is last free block before input block - */ - -#if LWMEM_CFG_CLEAN_MEMORY - /* - * Reset user memory. This is to reset memory - * after it has been freed by the application. - * - * By doing this, we protect data left by app - * and we make sure new allocations cannot see old information - */ - if (nblk != NULL) { - void* ptr = LWMEM_GET_PTR_FROM_BLOCK(nblk); - if (ptr != NULL) { - LWMEM_MEMSET(ptr, 0x00, nblk->size - LWMEM_BLOCK_META_SIZE); - } - } -#endif /* LWMEM_CFG_RESET_MEMORY */ - - /* - * Check if previous block and input block together create one big contiguous block - * If this is the case, merge blocks together and increase previous block by input block size - */ - if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(nblk)) { - prev->size += nblk->size; /* Increase current block by size of new block */ - nblk = prev; /* New block and current are now the same thing */ - /* - * It is important to set new block as current one - * as this allows merging previous and next blocks together with new block - * at the same time; follow next steps - */ - } - - /* - * Check if new block and next of previous create big contiguous block - * Do not merge with "end of region" indication (commented part of if statement) - */ - if (prev->next != NULL && prev->next->size > 0 /* Do not remove "end of region" indicator in each region */ - && (LWMEM_TO_BYTE_PTR(nblk) + nblk->size) == LWMEM_TO_BYTE_PTR(prev->next)) { - if (prev->next == lwobj->end_block) { /* Does it points to the end? */ - nblk->next = lwobj->end_block; /* Set end block pointer */ - } else { - /* Expand of current block for size of next free block which is right behind new block */ - nblk->size += prev->next->size; - nblk->next = prev->next->next; /* Next free is pointed to the next one of previous next */ - } - } else { - nblk->next = prev->next; /* Set next of input block as next of current one */ - } - - /* - * If new block has not been set as current (and expanded), - * then link them together, otherwise ignore as it would point to itself - */ - if (prev != nblk) { - prev->next = nblk; - } -} - -/** - * \brief Split too big block and add it to list of free blocks - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] block: Pointer to block with size already set - * \param[in] new_block_size: New block size to be set - * \return `1` if block splitted, `0` otherwise - */ -static uint8_t -prv_split_too_big_block(lwmem_t* const lwobj, lwmem_block_t* block, size_t new_block_size) { - lwmem_block_t* next; - size_t block_size, is_alloc_bit; - uint8_t success = 0; - - is_alloc_bit = block->size & LWMEM_ALLOC_BIT; /* Check if allocation bit is set */ - block_size = block->size & ~LWMEM_ALLOC_BIT; /* Use size without allocated bit */ - - /* - * If current block size is greater than requested size, - * it is possible to create empty block at the end of existing one - * and add it back to list of empty blocks - */ - if ((block_size - new_block_size) >= LWMEM_BLOCK_MIN_SIZE) { - next = (void*)(LWMEM_TO_BYTE_PTR(block) + new_block_size); /* Put next block after size of current allocation */ - next->size = block_size - new_block_size; /* Modify block data */ - block->size = new_block_size; /* Current size is now smaller */ - - lwobj->mem_available_bytes += next->size; /* Increase available bytes by new block size */ - prv_insert_free_block(lwobj, next); /* Add new block to the free list */ - - success = 1; - } else { - /* TODO: If next of current is free, check if we can increase next by at least some bytes */ - /* This can only happen during reallocation process when allocated block is reallocated to previous one */ - /* Very rare case, but may happen! */ - } - - /* If allocation bit was set before, set it now again */ - if (is_alloc_bit) { - prv_block_set_alloc(block); - } - return success; -} - -/** - * \brief Private allocation function - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] region: Pointer to region to allocate from. - * Set to `NULL` for any region - * \param[in] size: Application wanted size, excluding size of meta header - * \return Pointer to allocated memory, `NULL` otherwise - */ -static void* -prv_alloc(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) { - lwmem_block_t *prev, *curr; - void* retval = NULL; - - /* Calculate final size including meta data size */ - const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; - - /* Check if initialized and if size is in the limits */ - if (lwobj->end_block == NULL || final_size == LWMEM_BLOCK_META_SIZE || (final_size & LWMEM_ALLOC_BIT) > 0) { - return NULL; - } - - /* Set default values */ - prev = &(lwobj->start_block); /* Use pointer from custom lwmem block */ - curr = prev->next; /* Curr represents first actual free block */ - - /* - * If region is not set to NULL, - * request for memory allocation came from specific region: - * - * - Start at the beginning like normal (from very first region) - * - Loop until free block is between region start addr and its size - */ - if (region != NULL) { - uint8_t* region_start_addr; - size_t region_size; - - /* Get data about region */ - if (!prv_get_region_addr_size(region, ®ion_start_addr, ®ion_size)) { - return NULL; - } - - /* - * Scan all regions from lwmem and find first available block - * which is within address of region and is big enough - */ - for (; curr != NULL; prev = curr, curr = curr->next) { - /* Check bounds */ - if (curr->next == NULL || curr == lwobj->end_block) { - return NULL; - } - if ((uint8_t*)curr < (uint8_t*)region_start_addr) { /* Check if we reached region */ - continue; - } - if ((uint8_t*)curr >= (uint8_t*)(region_start_addr + region_size)) { /* Check if we are out already */ - return NULL; - } - if (curr->size >= final_size) { - break; /* Free block identified */ - } - } - } else { - /* - * Try to find first block with at least `size` bytes of available memory - * Loop until size of current block is smaller than requested final size - */ - for (; curr != NULL && curr->size < final_size; prev = curr, curr = curr->next) { - if (curr->next == NULL || curr == lwobj->end_block) { /* If no more blocks available */ - return NULL; /* No sufficient memory available to allocate block of memory */ - } - } - } - - /* Check curr pointer. During normal use, this should be always false */ - if (curr == NULL) { - return NULL; - } - - /* There is a valid block available */ - retval = LWMEM_GET_PTR_FROM_BLOCK(curr); /* Return pointer does not include meta part */ - prev->next = curr->next; /* Remove this block from linked list by setting next of previous to next of current */ - - /* curr block is now removed from linked list */ - - lwobj->mem_available_bytes -= curr->size; /* Decrease available bytes by allocated block size */ - prv_split_too_big_block(lwobj, curr, final_size); /* Split block if it is too big */ - prv_block_set_alloc(curr); /* Set block as allocated */ - - LWMEM_UPDATE_MIN_FREE(lwobj); - LWMEM_INC_STATS(lwobj->stats.nr_alloc); - - return retval; -} - -/** - * \brief Free input pointer - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] ptr: Input pointer to free - */ -static void -prv_free(lwmem_t* const lwobj, void* const ptr) { - lwmem_block_t* const block = LWMEM_GET_BLOCK_FROM_PTR(ptr); - if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */ - block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */ - - lwobj->mem_available_bytes += block->size; /* Increase available bytes */ - prv_insert_free_block(lwobj, block); /* Put block back to list of free block */ - - LWMEM_INC_STATS(lwobj->stats.nr_free); - } -} - -/** - * \brief Reallocates already allocated memory with new size - * - * Function behaves differently, depends on input parameter of `ptr` and `size`: - * - * - `ptr == NULL; size == 0`: Function returns `NULL`, no memory is allocated or freed - * - `ptr == NULL; size > 0`: Function tries to allocate new block of memory with `size` length, equivalent to `malloc(size)` - * - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)` - * - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success - * - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] region: Pointer to region to allocate from. - * Set to `NULL` for any region - * \param[in] ptr: Memory block previously allocated with one of allocation functions. - * It may be set to `NULL` to create new clean allocation - * \param[in] size: Size of new memory to reallocate - * \return Pointer to allocated memory on success, `NULL` otherwise - */ -static void* -prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) { - lwmem_block_t *block = NULL, *prevprev = NULL, *prev = NULL; - size_t block_size; /* Holds size of input block (ptr), including metadata size */ - const size_t final_size = - LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; /* Holds size of new requested block size, including metadata size */ - void* retval; /* Return pointer, used with LWMEM_RETURN macro */ - - /* Check optional input parameters */ - if (size == 0) { - if (ptr != NULL) { - prv_free(lwobj, ptr); - } - return NULL; - } - if (ptr == NULL) { - return prv_alloc(lwobj, region, size); - } - - /* Try to reallocate existing pointer */ - if ((size & LWMEM_ALLOC_BIT) || (final_size & LWMEM_ALLOC_BIT)) { - return NULL; - } - - /* Process existing block */ - block = LWMEM_GET_BLOCK_FROM_PTR(ptr); - if (!LWMEM_BLOCK_IS_ALLOC(block)) { - - /* Hard error. Input pointer is not NULL and block is not considered allocated */ - return NULL; - } - block_size = block->size & ~LWMEM_ALLOC_BIT; /* Get actual block size, without memory allocation bit */ - - /* Check current block size is the same as new requested size */ - if (block_size == final_size) { - return ptr; /* Just return pointer, nothing to do */ - } - - /* - * Abbreviations - * - * - "Current block" or "Input block" is allocated block from input variable "ptr" - * - "Next free block" is next free block, on address space after input block - * - "Prev free block" is last free block, on address space before input block - * - "PrevPrev free block" is previous free block of "Prev free block" - */ - - /* - * When new requested size is smaller than existing one, - * it is enough to modify size of current block only. - * - * If new requested size is much smaller than existing one, - * check if it is possible to create new empty block and add it to list of empty blocks - * - * Application returns same pointer - */ - if (final_size < block_size) { - if ((block_size - final_size) >= LWMEM_BLOCK_MIN_SIZE) { - prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ - } else { - /* - * It is not possible to create new empty block at the end of input block - * - * But if next free block is just after input block, - * it is possible to find this block and increase it by "block_size - final_size" bytes - */ - - /* Find free blocks before input block */ - prv_get_prev_curr_of_block(lwobj, block, &prevprev, &prev); - - /* Check if current block and next free are connected */ - if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) - && prev->next->size > 0) { /* Must not be end of region indicator */ - /* Make temporary variables as prev->next will point to different location */ - const size_t tmp_size = prev->next->size; - void* const tmp_next = prev->next->next; - - /* Shift block up, effectively increase its size */ - prev->next = (void*)(LWMEM_TO_BYTE_PTR(prev->next) - (block_size - final_size)); - prev->next->size = tmp_size + (block_size - final_size); - prev->next->next = tmp_next; - - /* Increase available bytes by increase of free block */ - lwobj->mem_available_bytes += block_size - final_size; - - block->size = final_size; /* Block size is requested size */ - } - } - prv_block_set_alloc(block); /* Set block as allocated */ - return ptr; /* Return existing pointer */ - } - - /* New requested size is bigger than current block size is */ - - /* Find last free (and its previous) block, located just before input block */ - prv_get_prev_curr_of_block(lwobj, block, &prevprev, &prev); - - /* If entry could not be found, there is a hard error */ - if (prev == NULL) { - return NULL; - } - - /* Order of variables is: | prevprev ---> prev --->--->--->--->--->--->--->--->--->---> prev->next | */ - /* | (input_block, which is not on a list) | */ - /* Input block points to address somewhere between "prev" and "prev->next" pointers */ - - /* Check if "block" and next free "prev->next" create contiguous memory with size of at least new requested size */ - if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) - && (block_size + prev->next->size) >= final_size) { - - /* - * Merge blocks together by increasing current block with size of next free one - * and remove next free from list of free blocks - */ - lwobj->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */ - LWMEM_UPDATE_MIN_FREE(lwobj); - block->size = block_size + prev->next->size; /* Increase effective size of new block */ - prev->next = prev->next->next; /* Set next to next's next, - effectively remove expanded block from free list */ - - prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ - prv_block_set_alloc(block); /* Set block as allocated */ - return ptr; /* Return existing pointer */ - } - - /* - * Check if "block" and last free before "prev" create contiguous memory with size of at least new requested size. - * - * It is necessary to make a memory move and shift content up as new return pointer is now upper on address space - */ - if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) && (prev->size + block_size) >= final_size) { - /* Move memory from block to block previous to current */ - void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); - void* const new_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(prev); - - /* - * If memmove overwrites metadata of current block (when shifting content up), - * it is not an issue as we know its size (block_size) and next is already NULL. - * - * Memmove must be used to guarantee move of data as addresses + their sizes may overlap - * - * Metadata of "prev" are not modified during memmove - */ - LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); - - lwobj->mem_available_bytes -= prev->size; /* For now decrease effective available bytes */ - LWMEM_UPDATE_MIN_FREE(lwobj); - prev->size += block_size; /* Increase size of input block size */ - prevprev->next = prev->next; /* Remove prev from free list as it is now being used - for allocation together with existing block */ - block = prev; /* Move block pointer to previous one */ - - prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ - prv_block_set_alloc(block); /* Set block as allocated */ - return new_data_ptr; /* Return new data ptr */ - } - - /* - * At this point, it was not possible to expand existing block with free before or free after due to: - * - Input block & next free block do not create contiguous block or its new size is too small - * - Previous free block & input block do not create contiguous block or its new size is too small - * - * Last option is to check if previous free block "prev", input block "block" and next free block "prev->next" create contiguous block - * and size of new block (from 3 contiguous blocks) together is big enough - */ - if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) - && (LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) - && (prev->size + block_size + prev->next->size) >= final_size) { - - /* Move memory from block to block previous to current */ - void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); - void* const new_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(prev); - - /* - * If memmove overwrites metadata of current block (when shifting content up), - * it is not an issue as we know its size (block_size) and next is already NULL. - * - * Memmove must be used to guarantee move of data as addresses and their sizes may overlap - * - * Metadata of "prev" are not modified during memmove - */ - LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); - - /* Decrease effective available bytes for free blocks before and after input block */ - lwobj->mem_available_bytes -= prev->size + prev->next->size; - LWMEM_UPDATE_MIN_FREE(lwobj); - prev->size += block_size + prev->next->size; /* Increase size of new block by size of 2 free blocks */ - - /* Remove free block before current one and block after current one from linked list (remove 2) */ - prevprev->next = prev->next->next; - block = prev; /* Previous block is now current */ - - prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ - prv_block_set_alloc(block); /* Set block as allocated */ - return new_data_ptr; /* Return new data ptr */ - } - - /* - * If application reaches this point, it means: - * - New requested size is greater than input block size - * - Input block & next free block do not create contiguous block or its new size is too small - * - Last free block & input block do not create contiguous block or its new size is too small - * - Last free block & input block & next free block do not create contiguous block or its size is too small - * - * Final solution is to find completely new empty block of sufficient size and copy content from old one to new one - */ - retval = prv_alloc(lwobj, region, size); /* Try to allocate new block */ - if (retval != NULL) { - /* Get application size from input pointer, then copy content to new block */ - block_size = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; - LWMEM_MEMCPY(retval, ptr, size > block_size ? block_size : size); - prv_free(lwobj, ptr); /* Free old block */ - } - return retval; -} - -/** - * \brief Assign the memory structure for advanced memory allocation system - * - * \param lwobj - * \param regions - * \return size_t - */ -static size_t -prv_assignmem(lwmem_t* lwobj, const lwmem_region_t* regions) { - uint8_t* mem_start_addr = NULL; - size_t mem_size = 0; - lwmem_block_t *first_block = NULL, *prev_end_block = NULL; - - for (size_t idx = 0; regions->size > 0 && regions->start_addr != NULL; ++idx, ++regions) { - /* Get region start address and size, stop on failure */ - if (!prv_get_region_addr_size(regions, &mem_start_addr, &mem_size)) { - continue; - } - - /* - * If end_block == NULL, this indicates first iteration. - * In first indication application shall set start_block and never again - * end_block value holds - */ - if (lwobj->end_block == NULL) { - /* - * Next entry of start block is first region - * It points to beginning of region data - * In the later step(s) first block is manually set on top of memory region - */ - lwobj->start_block.next = (void*)mem_start_addr; - lwobj->start_block.size = 0; /* Size of dummy start block is zero */ - } - - /* Save current end block status as it is used later for linked list insertion */ - prev_end_block = lwobj->end_block; - - /* Put end block to the end of the region with size = 0 */ - lwobj->end_block = (void*)(mem_start_addr + mem_size - LWMEM_BLOCK_META_SIZE); - lwobj->end_block->next = NULL; /* End block in region does not have next entry */ - lwobj->end_block->size = 0; /* Size of end block is zero */ - - /* - * Create memory region first block. - * - * First block meta size includes size of metadata too - * Subtract MEM_BLOCK_META_SIZE as there is one more block (end_block) at the end of region - * - * Actual maximal available size for application in the region is mem_size - 2 * MEM_BLOCK_META_SIZE - */ - first_block = (void*)mem_start_addr; - first_block->next = lwobj->end_block; /* Next block of first is last block */ - first_block->size = mem_size - LWMEM_BLOCK_META_SIZE; - - /* Check if previous regions exist by checking previous end block state */ - if (prev_end_block != NULL) { - prev_end_block->next = first_block; /* End block of previous region now points to start of current region */ - } - - lwobj->mem_available_bytes += first_block->size; /* Increase number of available bytes */ - ++lwobj->mem_regions_count; /* Increase number of used regions */ - } - -#if defined(LWMEM_DEV) - /* Copy default state of start block */ - LWMEM_MEMCPY(&lwmem_default.start_block_first_use, &lwmem_default.start_block, sizeof(lwmem_default.start_block)); -#endif /* defined(LWMEM_DEV) */ -#if LWMEM_CFG_ENABLE_STATS - lwobj->stats.mem_size_bytes = lwobj->mem_available_bytes; - lwobj->stats.minimum_ever_mem_available_bytes = lwobj->mem_available_bytes; -#endif - - return lwobj->mem_regions_count; /* Return number of regions used by manager */ -} - -#else /* LWMEM_CFG_FULL */ - -/** - * \brief Assign the regions for simple algorithm - * - * At this point, regions check has been performed, so we assume - * everything is ready to proceed - * - * \param lwobj: LwMEM object - * \param regions: List of regions to assign - * \return Number of regions used - */ -static size_t -prv_assignmem_simple(lwmem_t* const lwobj, const lwmem_region_t* regions) { - uint8_t* mem_start_addr = regions[0].start_addr; - size_t mem_size = regions[0].size; - - /* Adjust alignment data */ - if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { - mem_start_addr += ((size_t)LWMEM_CFG_ALIGN_NUM) - ((size_t)mem_start_addr & LWMEM_ALIGN_BITS); - mem_size -= (size_t)(mem_start_addr - LWMEM_TO_BYTE_PTR(regions[0].start_addr)); - } - - /* Align mem to alignment*/ - mem_size = mem_size & ~LWMEM_ALIGN_BITS; - - /* Store the available information */ - lwobj->mem_available_bytes = mem_size; - lwobj->mem_next_available_ptr = mem_start_addr; - lwobj->is_initialized = 1; - return 1; /* One region is being used only for now */ -} - -/** - * \brief Simple allocation algorithm, that can only allocate memory, - * but it does not support free. - * - * It uses simple first-in-first-serve concept, - * where memory grows upward gradually, up until it reaches the end - * of memory area - * - * \param lwobj: LwMEM object - * \param region: Selected region. Not used in the current revision, - * but footprint remains the same if one day library will support it - * \param size: Requested allocation size - * \return `NULL` on failure, or pointer to allocated memory - */ -static void* -prv_alloc_simple(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) { - void* retval = NULL; - const size_t alloc_size = LWMEM_ALIGN(size); - - if (alloc_size <= lwobj->mem_available_bytes) { - retval = lwobj->mem_next_available_ptr; - - /* Get ready for next iteration */ - lwobj->mem_next_available_ptr += alloc_size; - lwobj->mem_available_bytes -= alloc_size; - } - (void)region; - return retval; -} - -#endif /* LWMEM_CFG_FULL */ - -/** - * \brief Initializes and assigns user regions for memory used by allocator algorithm - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] regions: Pointer to array of regions with address and respective size. - * Regions must be in increasing order (start address) and must not overlap in-between. - * Last region entry must have address `NULL` and size set to `0` - * \code{.c} -//Example definition -lwmem_region_t regions[] = { - { (void *)0x10000000, 0x1000 }, //Region starts at address 0x10000000 and is 0x1000 bytes long - { (void *)0x20000000, 0x2000 }, //Region starts at address 0x20000000 and is 0x2000 bytes long - { (void *)0x30000000, 0x3000 }, //Region starts at address 0x30000000 and is 0x3000 bytes long - { NULL, 0 } //Array termination indicator -} -\endcode - * \return `0` on failure, number of final regions used for memory manager on success - * \note This function is not thread safe when used with operating system. - * It must be called only once to setup memory regions - */ -size_t -lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) { - uint8_t* mem_start_addr = NULL; - size_t mem_size = 0, len = 0; - - lwobj = LWMEM_GET_LWOBJ(lwobj); - - /* Check first things first */ - if (regions == NULL -#if LWMEM_CFG_FULL - || lwobj->end_block != NULL /* Init function may only be called once per lwmem instance */ -#else - || lwobj->is_initialized /* Already initialized? */ -#endif /* LWMEM_CFG_FULL */ - ) { - return 0; - } - - /* Check values entered by application */ - mem_start_addr = (void*)0; - mem_size = 0; - for (size_t idx = 0;; ++idx) { - /* - * Check for valid entry or end of array descriptor - * Invalid entry is considered as "end-of-region" indicator - */ - if (regions[idx].size == 0 && regions[idx].start_addr == NULL) { - len = idx; - if (len == 0) { - return 0; - } - break; - } - -#if !LWMEM_CFG_FULL - /* - * In case of simple allocation algorithm, we (for now!) only allow one region. - * Return zero value if user passed more than one region in a sequence. - */ - else if (idx > 0) { - return 0; - } -#endif /* LWMEM_CFG_FULL */ - - /* New region(s) must be higher (in address space) than previous one */ - if ((mem_start_addr + mem_size) > LWMEM_TO_BYTE_PTR(regions[idx].start_addr)) { - return 0; - } - - /* Save new values for next round */ - mem_start_addr = regions[idx].start_addr; - mem_size = regions[idx].size; - } - - /* Final init and check before initializing the regions */ - if (len == 0 -#if LWMEM_CFG_OS - || lwmem_sys_mutex_isvalid(&(lwobj->mutex)) /* Check if mutex valid already = must not be */ - || !lwmem_sys_mutex_create(&(lwobj->mutex)) /* Final step = try to create mutex for new instance */ -#endif /* LWMEM_CFG_OS */ - ) { - return 0; - } - -#if LWMEM_CFG_FULL - return prv_assignmem(lwobj, regions); -#else /* LWMEM_CFG_FULL */ - return prv_assignmem_simple(lwobj, regions); -#endif /* LWMEM_CFG_FULL */ -} - -/** - * \brief Allocate memory of requested size in specific lwmem instance and optional region. - * \note This is an extended malloc version function declaration to support advanced features - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] region: Optional region instance within LwMEM instance to force allocation from. - * Set to `NULL` to use any region within LwMEM instance - * \param[in] size: Number of bytes to allocate - * \return Pointer to allocated memory on success, `NULL` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void* -lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size) { - void* ptr = NULL; - - lwobj = LWMEM_GET_LWOBJ(lwobj); - - LWMEM_PROTECT(lwobj); -#if LWMEM_CFG_FULL - ptr = prv_alloc(lwobj, region, size); -#else /* LWMEM_CFG_FULL */ - ptr = prv_alloc_simple(lwobj, region, size); -#endif /* LWMEM_CFG_FULL */ - LWMEM_UNPROTECT(lwobj); - return ptr; -} - -/** - * \brief Allocate contiguous block of memory for requested number of items and its size - * in specific lwmem instance and region. - * - * It resets allocated block of memory to zero if allocation is successful - * - * \note This is an extended calloc version function declaration to support advanced features - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] region: Optional region instance within LwMEM instance to force allocation from. - * Set to `NULL` to use any region within LwMEM instance - * \param[in] nitems: Number of elements to be allocated - * \param[in] size: Size of each element, in units of bytes - * \return Pointer to allocated memory on success, `NULL` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void* -lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size) { - void* ptr = NULL; - const size_t alloc_size = size * nitems; - - lwobj = LWMEM_GET_LWOBJ(lwobj); - - LWMEM_PROTECT(lwobj); -#if LWMEM_CFG_FULL - ptr = prv_alloc(lwobj, region, alloc_size); -#else /* LWMEM_CFG_FULL */ - ptr = prv_alloc_simple(lwobj, region, alloc_size); -#endif /* LWMEM_CFG_FULL */ - LWMEM_UNPROTECT(lwobj); - - if (ptr != NULL) { - LWMEM_MEMSET(ptr, 0x00, alloc_size); - } - return ptr; -} - -#if LWMEM_CFG_FULL || __DOXYGEN__ - -/** - * \brief Reallocates already allocated memory with new size in specific lwmem instance and region. - * - * \note This function may only be used with allocations returned by any of `_from` API functions - * - * Function behaves differently, depends on input parameter of `ptr` and `size`: - * - * - `ptr == NULL; size == 0`: Function returns `NULL`, no memory is allocated or freed - * - `ptr == NULL; size > 0`: Function tries to allocate new block of memory with `size` length, equivalent to `malloc(region, size)` - * - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)` - * - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success - * - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] region: Pointer to region to allocate from. - * Set to `NULL` to use any region within LwMEM instance. - * Instance must be the same as used during allocation procedure - * \param[in] ptr: Memory block previously allocated with one of allocation functions. - * It may be set to `NULL` to create new clean allocation - * \param[in] size: Size of new memory to reallocate - * \return Pointer to allocated memory on success, `NULL` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void* -lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) { - void* p; - lwobj = LWMEM_GET_LWOBJ(lwobj); - LWMEM_PROTECT(lwobj); - p = prv_realloc(lwobj, region, ptr, size); - LWMEM_UNPROTECT(lwobj); - return p; -} - -/** - * \brief Safe version of realloc_ex function. - * - * After memory is reallocated, input pointer automatically points to new memory - * to prevent use of dangling pointers. When reallocation is not successful, - * original pointer is not modified and application still has control of it. - * - * It is advised to use this function when reallocating memory. - * - * Function behaves differently, depends on input parameter of `ptr` and `size`: - * - * - `ptr == NULL`: Invalid input, function returns `0` - * - `*ptr == NULL; size == 0`: Function returns `0`, no memory is allocated or freed - * - `*ptr == NULL; size > 0`: Function tries to allocate new block of memory with `size` length, equivalent to `malloc(size)` - * - `*ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)`, sets input pointer pointing to `NULL` - * - `*ptr != NULL; size > 0`: Function tries to reallocate existing pointer with new size and copy content to new block - * - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance - * \param[in] region: Pointer to region to allocate from. - * Set to `NULL` to use any region within LwMEM instance. - * Instance must be the same as used during allocation procedure - * \param[in] ptr: Pointer to pointer to allocated memory. Must not be set to `NULL`. - * If reallocation is successful, it modifies pointer's pointing address, - * or sets it to `NULL` in case of `free` operation - * \param[in] size: New requested size in bytes - * \return `1` if successfully reallocated, `0` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -int -lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size) { - void* new_ptr; - - /* - * Input pointer must not be NULL otherwise, - * in case of successful allocation, we have memory leakage - * aka. allocated memory where noone is pointing to it - */ - if (ptr == NULL) { - return 0; - } - - new_ptr = lwmem_realloc_ex(lwobj, region, *ptr, size); /* Try to reallocate existing pointer */ - if (new_ptr != NULL) { - *ptr = new_ptr; - } else if (size == 0) { /* size == 0 means free input memory */ - *ptr = NULL; - return 1; - } - return new_ptr != NULL; -} - -/** - * \brief Free previously allocated memory using one of allocation functions - * in specific lwmem instance. - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. - * Instance must be the same as used during allocation procedure - * \note This is an extended free version function declaration to support advanced features - * \param[in] ptr: Memory to free. `NULL` pointer is valid input - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void -lwmem_free_ex(lwmem_t* lwobj, void* const ptr) { - lwobj = LWMEM_GET_LWOBJ(lwobj); - LWMEM_PROTECT(lwobj); - prv_free(lwobj, ptr); - LWMEM_UNPROTECT(lwobj); -} - -/** - * \brief Safe version of free function - * - * After memory is freed, input pointer is safely set to `NULL` - * to prevent use of dangling pointers. - * - * It is advised to use this function when freeing memory. - * - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. - * Instance must be the same as used during allocation procedure - * \param[in] ptr: Pointer to pointer to allocated memory. - * When set to non `NULL`, pointer is freed and set to `NULL` - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void -lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr) { - if (ptr != NULL && *ptr != NULL) { - lwobj = LWMEM_GET_LWOBJ(lwobj); - LWMEM_PROTECT(lwobj); - prv_free(lwobj, *ptr); - LWMEM_UNPROTECT(lwobj); - *ptr = NULL; - } -} - -/** - * \brief Get user size of allocated memory - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. - * Instance must be the same as used during allocation procedure - * \param[in] ptr: Pointer to allocated memory - * \return Block size for user in units of bytes - */ -size_t -lwmem_get_size_ex(lwmem_t* lwobj, void* ptr) { - lwmem_block_t* block; - uint32_t len = 0; - - if (ptr != NULL) { - lwobj = LWMEM_GET_LWOBJ(lwobj); - LWMEM_PROTECT(lwobj); - block = LWMEM_GET_BLOCK_FROM_PTR(ptr); - if (LWMEM_BLOCK_IS_ALLOC(block)) { - len = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; - } - LWMEM_UNPROTECT(lwobj); - } - return len; -} - -#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ - -#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ - -/** - * \brief Get statistics of a LwMEM instance - * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. - * Instance must be the same as used during allocation procedure - * \param[in,out] stats: Pointer to \ref lwmem_stats_t to store result - */ -void -lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats) { - if (stats != NULL) { - lwobj = LWMEM_GET_LWOBJ(lwobj); - LWMEM_PROTECT(lwobj); - *stats = lwobj->stats; - stats->mem_available_bytes = lwobj->mem_available_bytes; - LWMEM_UNPROTECT(lwobj); - } -} - -/** - * \brief Get statistics of a default LwMEM instance - * \param[in,out] stats: Pointer to \ref lwmem_stats_t to store result - */ -size_t -lwmem_get_size(lwmem_stats_t* stats) { - lwmem_get_stats_ex(NULL, stats); -} - -#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ - -/** - * \note This is a wrapper for \ref lwmem_assignmem_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] regions: Pointer to array of regions with address and respective size. - * Regions must be in increasing order (start address) and must not overlap in-between. - * Last region entry must have address `NULL` and size set to `0` - * \code{.c} -//Example definition -lwmem_region_t regions[] = { - { (void *)0x10000000, 0x1000 }, //Region starts at address 0x10000000 and is 0x1000 bytes long - { (void *)0x20000000, 0x2000 }, //Region starts at address 0x20000000 and is 0x2000 bytes long - { (void *)0x30000000, 0x3000 }, //Region starts at address 0x30000000 and is 0x3000 bytes long - { NULL, 0 } //Array termination indicator -} -\endcode - * \return `0` on failure, number of final regions used for memory manager on success - */ -size_t -lwmem_assignmem(const lwmem_region_t* regions) { - return lwmem_assignmem_ex(NULL, regions); -} - -/** - * \note This is a wrapper for \ref lwmem_malloc_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] size: Size to allocate in units of bytes - * \return Pointer to allocated memory on success, `NULL` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void* -lwmem_malloc(size_t size) { - return lwmem_malloc_ex(NULL, NULL, size); -} - -/** - * \note This is a wrapper for \ref lwmem_calloc_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] nitems: Number of elements to be allocated - * \param[in] size: Size of each element, in units of bytes - * \return Pointer to allocated memory on success, `NULL` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void* -lwmem_calloc(size_t nitems, size_t size) { - return lwmem_calloc_ex(NULL, NULL, nitems, size); -} - -#if LWMEM_CFG_FULL || __DOXYGEN__ - -/** - * \note This is a wrapper for \ref lwmem_realloc_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] ptr: Memory block previously allocated with one of allocation functions. - * It may be set to `NULL` to create new clean allocation - * \param[in] size: Size of new memory to reallocate - * \return Pointer to allocated memory on success, `NULL` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void* -lwmem_realloc(void* ptr, size_t size) { - return lwmem_realloc_ex(NULL, NULL, ptr, size); -} - -/** - * \note This is a wrapper for \ref lwmem_realloc_s_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] ptr2ptr: Pointer to pointer to allocated memory. Must not be set to `NULL`. - * If reallocation is successful, it modifies pointer's pointing address, - * or sets it to `NULL` in case of `free` operation - * \param[in] size: New requested size in bytes - * \return `1` if successfully reallocated, `0` otherwise - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -int -lwmem_realloc_s(void** ptr2ptr, size_t size) { - return lwmem_realloc_s_ex(NULL, NULL, ptr2ptr, size); -} - -/** - * \note This is a wrapper for \ref lwmem_free_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] ptr: Memory to free. `NULL` pointer is valid input - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void -lwmem_free(void* ptr) { - lwmem_free_ex(NULL, (ptr)); -} - -/** - * \note This is a wrapper for \ref lwmem_free_s_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] ptr2ptr: Pointer to pointer to allocated memory. - * When set to non `NULL`, pointer is freed and set to `NULL` - * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled - */ -void -lwmem_free_s(void** ptr2ptr) { - lwmem_free_s_ex(NULL, (ptr2ptr)); -} - -/** - * \note This is a wrapper for \ref lwmem_get_size_ex function. - * It operates in default LwMEM instance and uses first available region for memory operations - * \param[in] ptr: Pointer to allocated memory - * \return Block size for user in units of bytes - */ -size_t -lwmem_get_size(void* ptr) { - return lwmem_get_size_ex(NULL, ptr); -} - -#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ - -/* Part of library used ONLY for LWMEM_DEV purposes */ -/* To validate and test library */ - -#if defined(LWMEM_DEV) && LWMEM_CFG_FULL && !__DOXYGEN__ - -#include -#include - -/* Temporary variable for lwmem save */ -static lwmem_t lwmem_temp; -static lwmem_region_t* regions_orig; -static lwmem_region_t* regions_temp; -static size_t regions_count; - -static lwmem_region_t* -create_regions(size_t count, size_t size) { - lwmem_region_t* regions; - lwmem_region_t tmp; - - /* - * Allocate pointer structure - * - * Length 1 entry more, to set default values for NULL entry - */ - regions = calloc(count + 1, sizeof(*regions)); - if (regions == NULL) { - return NULL; - } - - /* Allocate memory for regions */ - for (size_t i = 0; i < count; ++i) { - regions[i].size = size; - regions[i].start_addr = malloc(regions[i].size); - if (regions[i].start_addr == NULL) { - return NULL; - } - } - regions[count].size = 0; - regions[count].start_addr = NULL; - - /* Sort regions, make sure they grow linearly */ - for (size_t x = 0; x < count; ++x) { - for (size_t y = 0; y < count; ++y) { - if (regions[x].start_addr < regions[y].start_addr) { - memcpy(&tmp, ®ions[x], sizeof(regions[x])); - memcpy(®ions[x], ®ions[y], sizeof(regions[x])); - memcpy(®ions[y], &tmp, sizeof(regions[x])); - } - } - } - - return regions; -} - -static void -print_block(size_t i, lwmem_block_t* block) { - size_t is_free, block_size; - - is_free = (block->size & LWMEM_ALLOC_BIT) == 0 && block != &lwmem_default.start_block_first_use && block->size > 0; - block_size = block->size & ~LWMEM_ALLOC_BIT; - - printf("| %5d | %16p | %6d | %4d | %16d |", (int)i, (void*)block, (int)is_free, (int)block_size, - (int)(is_free ? (block_size - LWMEM_BLOCK_META_SIZE) : 0)); - if (block == &lwmem_default.start_block_first_use) { - printf(" Start block "); - } else if (block_size == 0) { - printf(" End of region "); - } else if (is_free) { - printf(" Free block "); - } else if (!is_free) { - printf(" Allocated block "); - } else { - printf(" "); - } - printf("|\r\n"); -} - -void -lwmem_debug_print(uint8_t print_alloc, uint8_t print_free) { - size_t block_size; - lwmem_block_t* block; - - (void)print_alloc; - (void)print_free; - - printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); - printf("| Block | Address | IsFree | Size | MaxUserAllocSize | Meta |\r\n"); - printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); - - block = &lwmem_default.start_block_first_use; - print_block(0, &lwmem_default.start_block_first_use); - printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); - for (size_t i = 0, j = 1; i < regions_count; ++i) { - block = regions_orig[i].start_addr; - - /* Print all blocks */ - for (;; ++j) { - block_size = block->size & ~LWMEM_ALLOC_BIT; - - print_block(j, block); - - /* Get next block */ - block = (void*)(LWMEM_TO_BYTE_PTR(block) + block_size); - if (block_size == 0) { - break; - } - } - printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); - } -} - -uint8_t -lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size) { - regions_orig = create_regions(count, size); - regions_temp = create_regions(count, size); - - if (regions_orig == NULL || regions_temp == NULL) { - return 0; - } - regions_count = count; - *regs_out = regions_orig; - - return 1; -} - -void -lwmem_debug_save_state(void) { - memcpy(&lwmem_temp, &lwmem_default, sizeof(lwmem_temp)); - for (size_t i = 0; i < regions_count; ++i) { - memcpy(regions_temp[i].start_addr, regions_orig[i].start_addr, regions_temp[i].size); - } - printf(" -- > Current state saved!\r\n"); -} - -void -lwmem_debug_restore_to_saved(void) { - memcpy(&lwmem_default, &lwmem_temp, sizeof(lwmem_temp)); - for (size_t i = 0; i < regions_count; ++i) { - memcpy(regions_orig[i].start_addr, regions_temp[i].start_addr, regions_temp[i].size); - } - printf(" -- > State restored to last saved!\r\n"); -} - -void -lwmem_debug_test_region(void* region_start, size_t region_size, uint8_t** region_start_calc, size_t* region_size_calc) { - lwmem_region_t region = { - .start_addr = region_start, - .size = region_size, - }; - prv_get_region_addr_size(®ion, region_start_calc, region_size_calc); -} - -#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ diff --git a/lwmem/lwmem.h b/lwmem/lwmem.h deleted file mode 100644 index bde8add..0000000 --- a/lwmem/lwmem.h +++ /dev/null @@ -1,160 +0,0 @@ -/** - * \file lwmem.h - * \brief Lightweight dynamic memory manager - */ - -/* - * Copyright (c) 2024 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of LwMEM - Lightweight dynamic memory manager library. - * - * Author: Tilen MAJERLE - * Version: v2.2.1 - */ -#ifndef LWMEM_HDR_H -#define LWMEM_HDR_H - -#include -#include "dcc/plat.h" -#include -#include "lwmem_opt.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * \defgroup LWMEM Lightweight dynamic memory manager - * \brief Lightweight dynamic memory manager - * \{ - */ - -/** - * \brief Get size of statically allocated array - * \param[in] x: Object to get array size of - * \return Number of elements in array - */ -#define LWMEM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) - -/** - * \brief Memory block structure - */ -typedef struct lwmem_block { - struct lwmem_block* next; /*!< Next free memory block on linked list. - Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */ - size_t size; /*!< Size of block, including metadata part. - MSB bit is set to `1` when block is allocated and in use, - or `0` when block is considered free */ -} lwmem_block_t; - -/** - * \brief Statistics structure - */ -typedef struct { - uint32_t mem_size_bytes; /*!< Total memory size of all regions combined */ - uint32_t mem_available_bytes; /*!< Free memory available for allocation */ - uint32_t minimum_ever_mem_available_bytes; /*!< Minimum amount of total free memory there has been - in the heap since the system booted. */ - uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */ - uint32_t nr_free; /*!< Number of frees in the LwMEM instance */ -} lwmem_stats_t; - -/** - * \brief LwMEM main structure - */ -typedef struct lwmem { - size_t mem_available_bytes; /*!< Memory size available for allocation */ -#if LWMEM_CFG_FULL - lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */ - lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */ - size_t mem_regions_count; /*!< Number of regions used for allocation */ -#else - uint8_t* mem_next_available_ptr; /*!< Pointer for next allocation */ - uint8_t is_initialized; /*!< Set to `1` when initialized */ -#endif - -#if LWMEM_CFG_OS || __DOXYGEN__ - LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */ -#endif /* LWMEM_CFG_OS || __DOXYGEN__ */ -#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ - lwmem_stats_t stats; /*!< Statistics */ -#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ -#if defined(LWMEM_DEV) && !__DOXYGEN__ - lwmem_block_t start_block_first_use; /*!< Value of start block for very first time. - This is used only during validation process and is removed in final use */ -#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ -} lwmem_t; - -/** - * \brief Memory region descriptor - */ -typedef struct { - void* start_addr; /*!< Region start address */ - size_t size; /*!< Size of region in units of bytes */ -} lwmem_region_t; - -size_t lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions); -void* lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size); -void* lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size); -#if LWMEM_CFG_FULL || __DOXYGEN__ -void* lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size); -int lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size); -void lwmem_free_ex(lwmem_t* lwobj, void* const ptr); -void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr); -size_t lwmem_get_size_ex(lwmem_t* lwobj, void* ptr); -#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ -#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ -void lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats); -void lwmem_get_size(lwmem_stats_t* stats); -#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ - -size_t lwmem_assignmem(const lwmem_region_t* regions); -void* lwmem_malloc(size_t size); -void* lwmem_calloc(size_t nitems, size_t size); - -#if LWMEM_CFG_FULL || __DOXYGEN__ -void* lwmem_realloc(void* ptr, size_t size); -int lwmem_realloc_s(void** ptr2ptr, size_t size); -void lwmem_free(void* ptr); -void lwmem_free_s(void** ptr2ptr); -size_t lwmem_get_size(void* ptr); -#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ - -#if defined(LWMEM_DEV) && !__DOXYGEN__ -unsigned char lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size); -void lwmem_debug_save_state(void); -void lwmem_debug_restore_to_saved(void); -void lwmem_debug_print(unsigned char print_alloc, unsigned char print_free); -void lwmem_debug_test_region(void* region_start, size_t region_size, uint8_t** region_start_calc, - size_t* region_size_calc); -#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* LWMEM_HDR_H */ diff --git a/lwmem/lwmem_opt.h b/lwmem/lwmem_opt.h deleted file mode 100644 index bc14c9b..0000000 --- a/lwmem/lwmem_opt.h +++ /dev/null @@ -1,161 +0,0 @@ -/** - * \file lwmem_opt.h - * \brief LwMEM options - */ - -/* - * Copyright (c) 2024 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of LwMEM - Lightweight dynamic memory manager library. - * - * Author: Tilen MAJERLE - * Version: v2.2.1 - */ -#ifndef LWMEM_OPT_HDR_H -#define LWMEM_OPT_HDR_H - -/* Uncomment to ignore user options (or set macro in compiler flags) */ -/* #define LWMEM_IGNORE_USER_OPTS */ - -/* Include application options */ -#ifndef LWMEM_IGNORE_USER_OPTS -#include "lwmem_opts.h" -#endif /* LWMEM_IGNORE_USER_OPTS */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * \defgroup LWMEM_OPT Configuration - * \brief LwMEM options - * \{ - */ - -/** - * \brief Enables `1` or disables `0` operating system support in the library - * - * \note When `LWMEM_CFG_OS` is enabled, user must implement functions in \ref LWMEM_SYS group. - */ -#ifndef LWMEM_CFG_OS -#define LWMEM_CFG_OS 0 -#endif - -/** - * \brief Mutex handle type - * - * \note This value must be set in case \ref LWMEM_CFG_OS is set to `1`. - * If data type is not known to compiler, include header file with - * definition before you define handle type - */ -#ifndef LWMEM_CFG_OS_MUTEX_HANDLE -#define LWMEM_CFG_OS_MUTEX_HANDLE void* -#endif - -/** - * \brief Number of bits to align memory address and memory size - * - * Some CPUs do not offer unaligned memory access (Cortex-M0 as an example) - * therefore it is important to have alignment of data addresses and potentialy length of data - * - * \note This value must be a power of `2` for number of bytes. - * Usually alignment of `4` bytes fits to all processors. - */ -#ifndef LWMEM_CFG_ALIGN_NUM -#define LWMEM_CFG_ALIGN_NUM 4 -#endif - -/** - * \brief Enables `1` or disables `0` full memory management support. - * - * When enabled (default config), library supports allocation, reallocation and freeing of the memory. - * - Memory [c]allocation - * - Memory reallocation - * - Memory allocation in user defined memory regions - * - Memory freeing - * - * When disabled, library only supports allocation and does not provide any other service. - * - Its purpose is for memory allocation at the start of firmware initialization only - * - * \note When disabled, statistics functionaltiy is not available - * and only one region is supported (for now, may be updated later). - * API to allocate memory remains the same as for full configuration. - */ -#ifndef LWMEM_CFG_FULL -#define LWMEM_CFG_FULL 1 -#endif - -/** - * \brief Enables `1` or disables `0` memory cleanup on free operation (or realloc). - * - * It resets unused memory to `0x00` and prevents other applications seeing old data. - * It is disabled by default since it has performance penalties. - */ -#ifndef LWMEM_CFG_CLEAN_MEMORY -#define LWMEM_CFG_CLEAN_MEMORY 0 -#endif - -/** - * \brief Enables `1` or disables `0` statistics in the library - * - */ -#ifndef LWMEM_CFG_ENABLE_STATS -#define LWMEM_CFG_ENABLE_STATS 0 -#endif - -/** - * \brief Memory set function - * - * \note Function footprint is the same as \ref memset - */ -#ifndef LWMEM_MEMSET -#define LWMEM_MEMSET(dst, val, len) memset((dst), (val), (len)) -#endif - -/** - * \brief Memory copy function - * - * \note Function footprint is the same as \ref memcpy - */ -#ifndef LWMEM_MEMCPY -#define LWMEM_MEMCPY(dst, src, len) memcpy((dst), (src), (len)) -#endif - -/** - * \brief Memory move function - * - * \note Function footprint is the same as \ref memmove - */ -#ifndef LWMEM_MEMMOVE -#define LWMEM_MEMMOVE(dst, src, len) memmove((dst), (src), (len)) -#endif - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* LWMEM_OPT_HDR_H */ diff --git a/lwmem/lwmem_opts.h b/lwmem/lwmem_opts.h deleted file mode 100644 index cfd5d39..0000000 --- a/lwmem/lwmem_opts.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * \file lwmem_opts_template.h - * \brief Template config file - */ - -/* - * Copyright (c) 2024 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of LwMEM - Lightweight dynamic memory manager library. - * - * Author: Tilen MAJERLE - * Version: v2.2.1 - */ -#ifndef LWMEM_OPTS_HDR_H -#define LWMEM_OPTS_HDR_H - -/* Rename this file to "lwmem_opts.h" for your application */ - -/* - * Open "include/lwmem/lwmem_opt.h" and - * copy & replace here settings you want to change values - */ - -#endif /* LWMEM_OPTS_HDR_H */ diff --git a/main.c b/main.c index 9993b4a..4c1e8fb 100644 --- a/main.c +++ b/main.c @@ -6,9 +6,9 @@ const char CFLAGS[] = "C:DumpNow DCC Loader. (c) 2026 Wrapper.;Compile flags: " CDEFS ";Compile Date: " __DATE__; #endif -static uint8_t rawBuf[DCC_BUFFER_SIZE + 0x2000]; -#if HAVE_LZ4 || HAVE_MINILZO || USE_OLD_DCC_IO -static uint8_t compBuf[DCC_BUFFER_SIZE + 0x4000]; +#if !USE_BREAKPOINTS && !DISABLE_COMPRESS +static uint8_t read_buffer[DCC_BUFFER_SIZE + 0x2000]; +static uint8_t compress_buffer[DCC_BUFFER_SIZE + 0x4000]; #endif #ifdef DCC_TESTING @@ -17,13 +17,50 @@ extern void DCC_COMPRESS_MEMCPY(uint32_t algo, uint32_t src_offset, uint32_t siz size_t strlen(const char *str); +static inline uint8_t dcc_send_data(uint8_t *data, uint32_t size, uint8_t algo) { + uint32_t dcc_comp_packet_size; + + switch (algo) { + case CMD_READ_COMP_RLE: + #if !USE_BREAKPOINTS && !DISABLE_COMPRESS + dcc_comp_packet_size = DN_Packet_Compress(data, size, compress_buffer); + DN_Packet_Send(compress_buffer, dcc_comp_packet_size); + break; + #endif + + case CMD_READ_COMP_NONE: + DN_Packet_Send_DirectUncompressed(data, size); + break; + + #if HAVE_MINILZO && !USE_BREAKPOINTS && !DISABLE_COMPRESS + case CMD_READ_COMP_LZO: + dcc_comp_packet_size = DN_Packet_Compress2(data, size, compress_buffer); + DN_Packet_Send(compress_buffer, dcc_comp_packet_size); + break; + #endif + + #if HAVE_LZ4 && !USE_BREAKPOINTS && !DISABLE_COMPRESS + case CMD_READ_COMP_LZ4: + dcc_comp_packet_size = DN_Packet_Compress3(data, size, compress_buffer); + DN_Packet_Send(compress_buffer, dcc_comp_packet_size); + break; + #endif + + default: + DN_Packet_Send_One(CMD_READ_RESP_FAIL(DCC_INVALID_ARGS)); + return 0; + } + + return 1; +} + // dcc code void dcc_main(uint32_t StartAddress, uint32_t PageSize) { - DCCMemory mem[16] = { 0 }; - uint8_t mem_has_spare[16] = { 0 }; - uint32_t BUF_INIT[2048]; + DCCMemory dev_mem[16] = { 0 }; + uint8_t mem_has_oob[16] = { 0 }; + uint32_t dcc_init_buf[2048]; uint32_t dcc_init_offset = 0; - uint32_t ext_mem; + uint32_t temp_ext_mem; DCC_RETURN res; /* 01 - Probe flash devices */ @@ -31,49 +68,51 @@ void dcc_main(uint32_t StartAddress, uint32_t PageSize) { if (!devices[i].driver) break; // Break when reaching the end of list /* Probe device */ - res = devices[i].driver->initialize(&mem[i], devices[i].base_offset); - if (res != DCC_OK) mem[i].type = MEMTYPE_NONE; + res = devices[i].driver->initialize(&dev_mem[i], devices[i].base_offset, PageSize); + if (res != DCC_OK) + dev_mem[i].type = MEMTYPE_NONE; /* Print appropriate value */ - switch (mem[i].type) { + switch (dev_mem[i].type) { /* Anything without spare */ case MEMTYPE_NOR: case MEMTYPE_SUPERAND: - ext_mem = DCC_MEM_EXTENDED(1, mem[i].page_size, mem[i].block_size, mem[i].size >> 20); - mem_has_spare[i] = 0; + temp_ext_mem = DCC_MEM_EXTENDED(1, dev_mem[i].page_size, dev_mem[i].block_size, dev_mem[i].size >> 20); + mem_has_oob[i] = 0; + /* Extended memory logic */ WRITE_EXTMEM: /* Set name flag if memory name is defined */ - if (strlen(mem[i].name)) ext_mem |= 0x80; + if (strlen(dev_mem[i].name)) temp_ext_mem |= 0x80; /* First device info */ - BUF_INIT[dcc_init_offset++] = DCC_MEM_OK | (ext_mem << 16); - BUF_INIT[dcc_init_offset++] = mem[i].manufacturer | (mem[i].device_id << 16); + dcc_init_buf[dcc_init_offset++] = DCC_MEM_OK | (temp_ext_mem << 16); + dcc_init_buf[dcc_init_offset++] = dev_mem[i].manufacturer | (dev_mem[i].device_id << 16); /* Print additional information */ - if (strlen(mem[i].name)) { - int sLen = strlen(mem[i].name); - uint8_t *bufCast = (uint8_t *)BUF_INIT; + if (strlen(dev_mem[i].name)) { + int sLen = strlen(dev_mem[i].name); + uint8_t *dcc_init_buf_uint8 = (uint8_t *)dcc_init_buf; /* 8-bit length then name (WORD aligned) */ - BUF_INIT[dcc_init_offset] = sLen; - INT_MEMCPY((bufCast + (dcc_init_offset << 2) + 1), mem[i].name, sLen); + dcc_init_buf[dcc_init_offset] = sLen; + INT_MEMCPY((dcc_init_buf_uint8 + (dcc_init_offset << 2) + 1), dev_mem[i].name, sLen); dcc_init_offset += ALIGN4(1 + sLen) >> 2; } /* Second device info */ - BUF_INIT[dcc_init_offset++] = ext_mem; + dcc_init_buf[dcc_init_offset++] = temp_ext_mem; break; /* Regular NAND */ case MEMTYPE_NAND: - if (strlen(mem[i].name)) goto NAND_EXTMEM; // Extended device info if we have additional information + if (strlen(dev_mem[i].name)) goto NAND_EXTMEM; // Extended device info if we have additional information /* Device info */ - BUF_INIT[dcc_init_offset++] = DCC_MEM_OK | (mem[i].page_size << 16); - BUF_INIT[dcc_init_offset++] = mem[i].manufacturer | (mem[i].device_id << 16); - mem_has_spare[i] = 1; + dcc_init_buf[dcc_init_offset++] = DCC_MEM_OK | (dev_mem[i].page_size << 16); + dcc_init_buf[dcc_init_offset++] = dev_mem[i].manufacturer | (dev_mem[i].device_id << 16); + mem_has_oob[i] = 1; break; /* Anything with spare */ @@ -81,32 +120,29 @@ void dcc_main(uint32_t StartAddress, uint32_t PageSize) { case MEMTYPE_AND: case MEMTYPE_AG_AND: NAND_EXTMEM: - ext_mem = DCC_MEM_EXTENDED(0, mem[i].page_size, mem[i].block_size, mem[i].size >> 20); - mem_has_spare[i] = 1; + temp_ext_mem = DCC_MEM_EXTENDED(0, dev_mem[i].page_size, dev_mem[i].block_size, dev_mem[i].size >> 20); + mem_has_oob[i] = 1; goto WRITE_EXTMEM; /* When device probe fails, it goes here */ default: - BUF_INIT[dcc_init_offset++] = DCC_MEM_OK | (DCC_MEM_NONE << 16); - BUF_INIT[dcc_init_offset++] = mem[i].probe_error_code; - mem_has_spare[i] = 0; + dcc_init_buf[dcc_init_offset++] = DCC_MEM_OK | (DCC_MEM_NONE << 16); + dcc_init_buf[dcc_init_offset++] = dev_mem[i].probe_error_code; + mem_has_oob[i] = 0; } } /* 02 - Print buffer size */ - BUF_INIT[dcc_init_offset++] = DCC_MEM_OK | (DCC_MEM_BUFFER(0) << 16); - BUF_INIT[dcc_init_offset++] = DCC_BUFFER_SIZE; + dcc_init_buf[dcc_init_offset++] = DCC_MEM_OK | (DCC_MEM_BUFFER(0) << 16); + dcc_init_buf[dcc_init_offset++] = DCC_BUFFER_SIZE; - DN_Packet_Send((uint8_t *)BUF_INIT, dcc_init_offset << 2); + DN_Packet_Send((uint8_t *)dcc_init_buf, dcc_init_offset << 2); - #if HAVE_LZ4 || HAVE_MINILZO || USE_OLD_DCC_IO - uint32_t dcc_comp_packet_size; - #endif - uint32_t flashIndex; - uint32_t srcOffset; - uint32_t srcSize; - uint32_t destSize; + uint32_t fbFlashIndex; + uint32_t fbStartOffset; + uint32_t fbReadSize; + uint32_t readDestSize; /* 03 - The loop */ while (1) { @@ -124,149 +160,68 @@ void dcc_main(uint32_t StartAddress, uint32_t PageSize) { /* Get devices information */ case CMD_GETINFO: - DN_Packet_Send((uint8_t *)BUF_INIT, dcc_init_offset << 2); + DN_Packet_Send((uint8_t *)dcc_init_buf, dcc_init_offset << 2); break; /* Get memory size */ case CMD_GETMEMSIZE: - flashIndex = (cmd >> 8) & 0xff; - if (flashIndex == 0) { + fbFlashIndex = (cmd >> 8) & 0xff; + if (fbFlashIndex == 0) { DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(0x21, 0)); - } else if (flashIndex < 0x11 && mem[flashIndex - 1].type != MEMTYPE_NONE) { - DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(0x21, mem[flashIndex - 1].size >> 20)); + } else if (fbFlashIndex < 0x11 && dev_mem[fbFlashIndex - 1].type != MEMTYPE_NONE) { + DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(0x21, dev_mem[fbFlashIndex - 1].size >> 20)); } else { - DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_FLASH_NOENT, flashIndex)); + DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_FLASH_NOENT, fbFlashIndex)); } break; /* Flash read */ case CMD_READ: - srcOffset = DN_Packet_DCC_Read(); - srcSize = DN_Packet_DCC_Read(); - flashIndex = (cmd >> 8) & 0xff; - uint8_t algo = (cmd >> 24) & 0xff; + fbStartOffset = DN_Packet_DCC_Read(); + fbReadSize = DN_Packet_DCC_Read(); + fbFlashIndex = (cmd >> 8) & 0xff; + uint8_t compAlgo = (cmd >> 24) & 0xff; /* Check for read size not exceeding buffer */ - if (srcSize > DCC_BUFFER_SIZE) { + if (fbReadSize > DCC_BUFFER_SIZE) { DN_Packet_Send_One(CMD_READ_RESP_FAIL(DCC_INVALID_ARGS)); continue; } - if (flashIndex == 0) { // Direct read + if (fbFlashIndex == 0) { // Direct read Jump_Read_NOR: #ifndef DCC_TESTING - switch (algo) { - #if USE_OLD_DCC_IO - case CMD_READ_COMP_RLE: - #if !USE_BREAKPOINTS && !DISABLE_COMPRESS - dcc_comp_packet_size = DN_Packet_Compress((uint8_t *)srcOffset, srcSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #endif - case CMD_READ_COMP_NONE: - dcc_comp_packet_size = DN_Packet_CompressNone((uint8_t *)srcOffset, srcSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #else - case CMD_READ_COMP_RLE: - #if !USE_BREAKPOINTS && !DISABLE_COMPRESS - DN_Packet_WriteDirectCompressed((uint8_t *)srcOffset, srcSize); - break; - #endif - case CMD_READ_COMP_NONE: - DN_Packet_WriteDirect((uint8_t *)srcOffset, srcSize); - break; - #endif - - #if HAVE_MINILZO - case CMD_READ_COMP_LZO: - dcc_comp_packet_size = DN_Packet_Compress2((uint8_t *)srcOffset, srcSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #endif - - #if HAVE_LZ4 - case CMD_READ_COMP_LZ4: - dcc_comp_packet_size = DN_Packet_Compress3((uint8_t *)srcOffset, srcSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #endif - - default: - DN_Packet_Send_One(CMD_READ_RESP_FAIL(DCC_INVALID_ARGS)); - continue; - } + if (!dcc_send_data((uint8_t *)(fbStartOffset), fbReadSize, compAlgo)) + continue; #else - DCC_COMPRESS_MEMCPY(algo, srcOffset, srcSize); + DCC_COMPRESS_MEMCPY(compAlgo, fbStartOffset, fbReadSize); #endif // DN_Packet_Send(compBuf, dcc_comp_packet_size); - } else if (flashIndex < 0x11 && mem[flashIndex - 1].type != MEMTYPE_NONE) { - switch (mem[flashIndex - 1].type) { + } else if (fbFlashIndex < 0x11 && dev_mem[fbFlashIndex - 1].type != MEMTYPE_NONE) { + switch (dev_mem[fbFlashIndex - 1].type) { case MEMTYPE_NAND: case MEMTYPE_ONENAND: case MEMTYPE_SUPERAND: case MEMTYPE_AND: case MEMTYPE_AG_AND: /* Get driver routines */ - res = devices[flashIndex - 1].driver->read(&mem[flashIndex - 1], srcOffset, srcSize, rawBuf, &destSize); + res = devices[fbFlashIndex - 1].driver->read(&dev_mem[fbFlashIndex - 1], fbStartOffset, fbReadSize, read_buffer, &readDestSize); if (res != DCC_OK) { // Check if error DN_Packet_Send_One(CMD_READ_RESP_FAIL(res)); continue; } /* Compression */ - switch (algo) { - #if USE_OLD_DCC_IO - case CMD_READ_COMP_RLE: - #if !USE_BREAKPOINTS && !DISABLE_COMPRESS - dcc_comp_packet_size = DN_Packet_Compress(rawBuf, destSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #endif - case CMD_READ_COMP_NONE: - dcc_comp_packet_size = DN_Packet_CompressNone(rawBuf, destSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #else - case CMD_READ_COMP_RLE: - #if !USE_BREAKPOINTS && !DISABLE_COMPRESS - DN_Packet_WriteDirectCompressed(rawBuf, destSize); - //dcc_comp_packet_size = DN_Packet_Compress(rawBuf, destSize, compBuf); - break; - #endif - case CMD_READ_COMP_NONE: - DN_Packet_WriteDirect(rawBuf, destSize); - //dcc_comp_packet_size = DN_Packet_CompressNone(rawBuf, destSize, compBuf); - break; - #endif + if (!dcc_send_data((uint8_t *)(read_buffer), readDestSize, compAlgo)) + continue; - #if HAVE_MINILZO - case CMD_READ_COMP_LZO: - dcc_comp_packet_size = DN_Packet_Compress2(rawBuf, destSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #endif - - #if HAVE_LZ4 - case CMD_READ_COMP_LZ4: - dcc_comp_packet_size = DN_Packet_Compress3(rawBuf, destSize, compBuf); - DN_Packet_Send(compBuf, dcc_comp_packet_size); - break; - #endif - - default: - DN_Packet_Send_One(CMD_READ_RESP_FAIL(DCC_INVALID_ARGS)); - continue; - } - - // DN_Packet_Send(compBuf, dcc_comp_packet_size); break; case MEMTYPE_NOR: default: /* NOR reads directly */ - srcOffset &= (mem[flashIndex - 1].size - 1); - srcOffset += mem[flashIndex - 1].base_offset; + fbStartOffset &= (dev_mem[fbFlashIndex - 1].size - 1); + fbStartOffset += dev_mem[fbFlashIndex - 1].base_offset; goto Jump_Read_NOR; } } else { @@ -278,23 +233,23 @@ void dcc_main(uint32_t StartAddress, uint32_t PageSize) { /* Flash erase */ case CMD_ERASE: - srcOffset = DN_Packet_DCC_Read(); - srcSize = DN_Packet_DCC_Read(); - flashIndex = (cmd >> 8) & 0xff; + fbStartOffset = DN_Packet_DCC_Read(); + fbReadSize = DN_Packet_DCC_Read(); + fbFlashIndex = (cmd >> 8) & 0xff; - if (flashIndex == 0) flashIndex = 1; + if (fbFlashIndex == 0) fbFlashIndex = 1; - if (flashIndex < 0x11 && mem[flashIndex - 1].type != MEMTYPE_NONE) { + if (fbFlashIndex < 0x11 && dev_mem[fbFlashIndex - 1].type != MEMTYPE_NONE) { // TODO: Erasing - DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_WPROT_ERROR, flashIndex)); + DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_WPROT_ERROR, fbFlashIndex)); } else { - DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_FLASH_NOENT, flashIndex)); + DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_FLASH_NOENT, fbFlashIndex)); } break; /* Flash write */ case CMD_WRITE: - flashIndex = (cmd >> 16) & 0xff; + fbFlashIndex = (cmd >> 16) & 0xff; uint32_t pAddrStart = DN_Packet_DCC_Read(); uint32_t dataPackN = DN_Packet_DCC_Read(); @@ -302,33 +257,33 @@ void dcc_main(uint32_t StartAddress, uint32_t PageSize) { uint8_t useECC = (cmd >> 8) & 0x80; uint32_t checksum_comp = 0xffffffff; - if (flashIndex == 0) flashIndex = 1; + if (fbFlashIndex == 0) fbFlashIndex = 1; - if (flashIndex < 0x11 && mem[flashIndex - 1].type != MEMTYPE_NONE) { + if (fbFlashIndex < 0x11 && dev_mem[fbFlashIndex - 1].type != MEMTYPE_NONE) { if (dataPackN == CMD_WRITE_COMP_NONE) { if (progType & 2) { - DN_Packet_Read(rawBuf, mem[flashIndex - 1].block_size); - checksum_comp = DN_Calculate_CRC32(checksum_comp, rawBuf, mem[flashIndex - 1].block_size); + DN_Packet_Read(read_buffer, dev_mem[fbFlashIndex - 1].block_size); + checksum_comp = DN_Calculate_CRC32(checksum_comp, read_buffer, dev_mem[fbFlashIndex - 1].block_size); } - if ((progType & 1) && mem_has_spare[flashIndex - 1]) { - DN_Packet_Read(rawBuf + ((progType & 2) ? mem[flashIndex - 1].block_size : 0), mem[flashIndex - 1].block_size >> 5); - checksum_comp = DN_Calculate_CRC32(checksum_comp, rawBuf + ((progType & 2) ? mem[flashIndex - 1].block_size : 0), mem[flashIndex - 1].block_size >> 5); + if ((progType & 1) && mem_has_oob[fbFlashIndex - 1]) { + DN_Packet_Read(read_buffer + ((progType & 2) ? dev_mem[fbFlashIndex - 1].block_size : 0), dev_mem[fbFlashIndex - 1].block_size >> 5); + checksum_comp = DN_Calculate_CRC32(checksum_comp, read_buffer + ((progType & 2) ? dev_mem[fbFlashIndex - 1].block_size : 0), dev_mem[fbFlashIndex - 1].block_size >> 5); } } else { uint32_t comp_len = DN_Packet_DCC_Read(); - DN_Packet_DCC_ReadCompressed(rawBuf, comp_len); - checksum_comp = DN_Calculate_CRC32(checksum_comp, rawBuf, comp_len); + DN_Packet_DCC_ReadCompressed(read_buffer, comp_len); + checksum_comp = DN_Calculate_CRC32(checksum_comp, read_buffer, comp_len); } uint32_t checksum = DN_Packet_DCC_Read(); if (checksum != checksum_comp) { - DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_CHECKSUM_ERROR, flashIndex)); + DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_CHECKSUM_ERROR, fbFlashIndex)); continue; } // TODO: Writing - DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_WPROT_ERROR, flashIndex)); + DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_WPROT_ERROR, fbFlashIndex)); } else { - DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_FLASH_NOENT, flashIndex)); + DN_Packet_Send_One(CMD_WRITE_ERASE_STATUS(DCC_FLASH_NOENT, fbFlashIndex)); } break; diff --git a/makefile b/makefile index cd5089a..9e58a9e 100644 --- a/makefile +++ b/makefile @@ -48,7 +48,6 @@ UDEFS = UADEFS = # List C source files here -# SRC = main.c dcc/dn_dcc_proto.c minilzo/minilzo.c lwmem/lwmem.c flash/cfi/cfi.c DEVICES = flash/mmap/mmap.c CONTROLLERS = ADD_DEPS = @@ -70,15 +69,6 @@ else DDEFS += -DHAVE_LZ4=0 endif -ifeq ($(LWMEM), 1) -ADD_DEPS += lwmem/lwmem.c -DDEFS += -DHAVE_LWMEM=1 -DADEFS += -DHAVE_LWMEM=1 -else -DDEFS += -DHAVE_LWMEM=0 -DADEFS += -DHAVE_LWMEM=0 -endif - # Devices ifeq ($(CFI), 1) DEVICES += flash/cfi/cfi.c @@ -99,6 +89,7 @@ DEVICES += flash/superand/superand.c CONTROLLERS += flash/superand/controller/$(SUPERAND_CONTROLLER).c endif +# Configuration ifeq ($(MCU), xscale) DDEFS += -DCPU_XSCALE DADEFS += -DCPU_XSCALE @@ -106,29 +97,24 @@ endif ifeq ($(ICACHE), 1) DADEFS += -DUSE_ICACHE=1 -else -DADEFS += -DUSE_ICACHE=0 endif ifeq ($(BP_LOADER), 1) DADEFS += -DUSE_BREAKPOINTS=1 DDEFS += -DUSE_BREAKPOINTS=1 -else -DADEFS += -DUSE_BREAKPOINTS=0 -DDEFS += -DUSE_BREAKPOINTS=0 endif ifdef BUFFER_SIZE DDEFS += -DDCC_BUFFER_SIZE=${BUFFER_SIZE} else -DDEFS += -DDCC_BUFFER_SIZE=0x40000 +DDEFS += -DDCC_BUFFER_SIZE=0x4000 endif -ifeq ($(NEW_IO), 1) -DDEFS += -DUSE_OLD_DCC_IO=0 -else -DDEFS += -DUSE_OLD_DCC_IO=1 -endif +# ifeq ($(NEW_IO), 1) +# DDEFS += -DUSE_OLD_DCC_IO=0 +# else +# DDEFS += -DUSE_OLD_DCC_IO=1 +# endif ifeq ($(NO_COMPRESS), 1) DDEFS += -DDISABLE_COMPRESS=1 @@ -228,7 +214,6 @@ endif $(info Optional libraries:) $(info $(NULL) LZO=1 = Enable LZO Compression) $(info $(NULL) LZ4=1 = Enable LZ4 Compression) - $(info $(NULL) LWMEM=1 = Enable LWMEM memory management) $(info Target configuration:) $(info $(NULL) PLATFORM=(name) Select chipset platform) $(info $(NULL) MCU=(MCU) = Select CPU architecture) diff --git a/plat/bcom/bcm2133.c b/plat/bcom/bcm2133.c index b0e0b7b..2ab98eb 100644 --- a/plat/bcom/bcm2133.c +++ b/plat/bcom/bcm2133.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) WRITE_U16(0x088a0000, 0x0); // Shut up watchdog diff --git a/plat/default.c b/plat/default.c index adf995e..8eea4b1 100644 --- a/plat/default.c +++ b/plat/default.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) } diff --git a/plat/intel/pxa.c b/plat/intel/pxa.c index dee7ebc..67dd526 100644 --- a/plat/intel/pxa.c +++ b/plat/intel/pxa.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) WRITE_U16(0x40A00018, 0x0); // Shut up watchdog diff --git a/plat/nxp/pcf5213.c b/plat/nxp/pcf5213.c index fc212d8..80a3ac2 100644 --- a/plat/nxp/pcf5213.c +++ b/plat/nxp/pcf5213.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) WRITE_U32(0x30503000, 0x0); // Shut up watchdog diff --git a/plat/nxp/pnx5230.c b/plat/nxp/pnx5230.c index 2a69581..78e94ce 100644 --- a/plat/nxp/pnx5230.c +++ b/plat/nxp/pnx5230.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) WRITE_U32(0x50503000, 0x0); // Shut up watchdog diff --git a/plat/qcom/gpio/gpio_msm5xxx.c b/plat/qcom/gpio/gpio_msm5xxx.c new file mode 100644 index 0000000..52d7808 --- /dev/null +++ b/plat/qcom/gpio/gpio_msm5xxx.c @@ -0,0 +1,134 @@ +#include "dcc/plat.h" + +#define GPIO_IN 0x03000720 +#define GPIO_TSEN 0x0300072c +#define GPIO_FUNC 0x03000738 + +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + uint8_t gpio_page_offset = (pin >> 4) << 2; + uint8_t gpio_pin_bit_pos = pin & 0xf; + + return (READ_U16(GPIO_IN + gpio_page_offset) >> gpio_pin_bit_pos) & 1; +} + +static uint16_t gpio_buffers[5]; +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write + uint8_t gpio_page_offset = (pin >> 4) << 2; + uint8_t gpio_pin_bit_pos = pin & 0xf; + bitmask gpio_write_bm = {gpio_pin_bit_pos, 1}; + + BIT_SET_VAR(gpio_buffers[pin >> 4], gpio_write_bm, active); + WRITE_U16(GPIO_IN + gpio_page_offset, gpio_buffers[pin >> 4]); +} + +static uint16_t gpio_dir_buffers[5]; +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) + // GPIO pin write + uint8_t gpio_page_offset = (pin >> 4) << 2; + uint8_t gpio_pin_bit_pos = pin & 0xf; + bitmask gpio_write_bm = {gpio_pin_bit_pos, 1}; + + BIT_SET_VAR(gpio_dir_buffers[pin >> 4], gpio_write_bm, dir == GPIO_INPUT ? 0 : 1); + WRITE_U16(GPIO_TSEN + gpio_page_offset, gpio_dir_buffers[pin >> 4]); +} + +static uint16_t gpio_func_sel_buffers[5]; +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function + uint8_t func_sel_offset = 0; + uint8_t func_sel_bit_mask = 1; + uint8_t func_sel_bit_pos = 0; + + switch (pin) { + /* GPIO select 1*/ + case 37: + func_sel_bit_pos = 4; + break; + + case 38: + func_sel_bit_pos = 3; + break; + + case 39: + func_sel_bit_pos = 2; + break; + + case 40: + func_sel_bit_pos = 1; + break; + + case 41: + func_sel_bit_pos = 0; + break; + + case 42: + func_sel_bit_pos = 5; + break; + + case 43: + func_sel_bit_pos = 6; + break; + + case 44: + func_sel_bit_pos = 7; + break; + + case 45: + func_sel_bit_pos = 8; + break; + + case 46: + func_sel_bit_pos = 9; + break; + + case 47: + func_sel_bit_pos = 10; + break; + + /* GPIO select 2 */ + case 1: + func_sel_bit_pos = 6; + func_sel_offset = 1; + break; + + case 13: + func_sel_bit_pos = 2; + func_sel_offset = 1; + break; + + case 18: + case 19: + case 20: + case 21: + func_sel_bit_pos = 0; + func_sel_offset = 1; + break; + + case 29: + func_sel_bit_pos = 1; + func_sel_offset = 1; + break; + + case 30: + func_sel_bit_pos = 3; + func_sel_offset = 1; + func_sel_bit_mask = 0x7; + break; + + default: + return; + } + + uint8_t gpio_page_offset = func_sel_offset << 2; + bitmask gpio_write_bm = {func_sel_bit_pos, func_sel_bit_mask}; + + BIT_SET_VAR(gpio_func_sel_buffers[func_sel_offset], gpio_write_bm, alt_func); + WRITE_U16(GPIO_FUNC + gpio_page_offset, gpio_func_sel_buffers[func_sel_offset]); +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} \ No newline at end of file diff --git a/plat/qcom/gpio/gpio_msm62xx.c b/plat/qcom/gpio/gpio_msm62xx.c new file mode 100644 index 0000000..8d3ee12 --- /dev/null +++ b/plat/qcom/gpio/gpio_msm62xx.c @@ -0,0 +1,216 @@ +#include "gpio_msm_common.h" + +#ifndef GPIO1_OFFSET +#define GPIO1_OFFSET 0x80000900 +#endif + +#ifndef GPIO2_OFFSET +#define GPIO2_OFFSET 0x80004400 +#endif + +// GPIO1 Registers +#if MSM6100 || MSM6500 +#define REG_GPIO_OUT_0 0x0000 +#define REG_GPIO_OUT_1 0x0004 +#define REG_GPIO_OUT_4 0x0008 +#define REG_GPIO_OE_0 0x000c +#define REG_GPIO_OE_1 0x0010 +#define REG_GPIO_OE_4 0x0014 +#define REG_GPIO_PAGE 0x0020 +#define REG_GPIO_CFG 0x0024 +#define REG_GPIO_IN_0 0x0034 +#define REG_GPIO_IN_1 0x0038 +#define REG_GPIO_IN_4 0x003c +#elif QSC60x0 +#define REG_GPIO_OUT_0 0x0000 +#define REG_GPIO_IN_0 0x0004 +#define REG_GPIO_OE_0 0x0008 +#define REG_GPIO_PAGE 0x000C +#define REG_GPIO_CFG 0x0010 +#else +#define REG_GPIO_OUT_0 0x0000 +#define REG_GPIO_OUT_1 0x0004 +#define REG_GPIO_OUT_4 0x0008 +#define REG_GPIO_OUT_5 0x000c +#define REG_GPIO_OE_0 0x0010 +#define REG_GPIO_OE_1 0x0014 +#define REG_GPIO_OE_4 0x0018 +#define REG_GPIO_OE_5 0x001c +#define REG_GPIO_PAGE 0x0020 +#define REG_GPIO_CFG 0x0024 +#define REG_GPIO_IN_0 0x0034 +#define REG_GPIO_IN_1 0x0038 +#define REG_GPIO_IN_4 0x003c +#define REG_GPIO_IN_5 0x0040 +#endif + +// GPIO2 Registers +#if MSM6100 +#define REG_GPIO2_OE_2 0x0000 +#define REG_GPIO2_OE_3 0x0004 +#define REG_GPIO2_OUT_2 0x0008 +#define REG_GPIO2_OUT_3 0x000c +#define REG_GPIO2_PAGE 0x0040 +#define REG_GPIO2_CFG 0x0044 +#define REG_GPIO2_IN_2 0x0060 +#define REG_GPIO2_IN_3 0x0064 +#elif QSC60x0 +#define REG_GPIO2_OUT_2 0x0000 +#define REG_GPIO2_OUT_3 0x0004 +#define REG_GPIO2_IN_2 0x0008 +#define REG_GPIO2_IN_3 0x000c +#define REG_GPIO2_OE_2 0x0010 +#define REG_GPIO2_OE_3 0x0014 +#define REG_GPIO2_PAGE 0x0018 +#define REG_GPIO2_CFG 0x001c +#else +#define REG_GPIO2_OE_2 0x0000 +#define REG_GPIO2_OE_3 0x0004 +#define REG_GPIO2_OUT_2 0x0008 +#define REG_GPIO2_OUT_3 0x000c +#define REG_GPIO2_PAGE 0x0030 +#define REG_GPIO2_CFG 0x0034 +#define REG_GPIO2_IN_2 0x0040 +#define REG_GPIO2_IN_3 0x0044 +#endif + +// GPIOs +#if (MSM6100 || MSM6500) +const GPIOData gpios[5] = { + { + .no_pins = 32, + .pin_start_offset = 0, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_0, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_0, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_0, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 7, + .pin_start_offset = 32, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_1, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_1, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_1, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 16, + .pin_start_offset = 39, + .gpio_out = GPIO2_OFFSET + REG_GPIO2_OUT_2, + .gpio_in = GPIO2_OFFSET + REG_GPIO2_IN_2, + .gpio_oe = GPIO2_OFFSET + REG_GPIO2_OE_2, + .gpio_page = GPIO2_OFFSET + REG_GPIO2_PAGE, + .gpio_cfg = GPIO2_OFFSET + REG_GPIO2_CFG + }, + { + .no_pins = 12, + .pin_start_offset = 55, + .gpio_out = GPIO2_OFFSET + REG_GPIO2_OUT_3, + .gpio_in = GPIO2_OFFSET + REG_GPIO2_IN_3, + .gpio_oe = GPIO2_OFFSET + REG_GPIO2_OE_3, + .gpio_page = GPIO2_OFFSET + REG_GPIO2_PAGE, + .gpio_cfg = GPIO2_OFFSET + REG_GPIO2_CFG + }, + { + .no_pins = 32, + .pin_start_offset = 67, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_4, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_4, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_4, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, +}; +#elif QSC60x0 +const GPIOData gpios[3] = { + { + .no_pins = 21, + .pin_start_offset = 0, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_0, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_0, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_0, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 32, + .pin_start_offset = 21, + .gpio_out = GPIO2_OFFSET + REG_GPIO2_OUT_2, + .gpio_in = GPIO2_OFFSET + REG_GPIO2_IN_2, + .gpio_oe = GPIO2_OFFSET + REG_GPIO2_OE_2, + .gpio_page = GPIO2_OFFSET + REG_GPIO2_PAGE, + .gpio_cfg = GPIO2_OFFSET + REG_GPIO2_CFG + }, + { + .no_pins = 4, + .pin_start_offset = 53, + .gpio_out = GPIO2_OFFSET + REG_GPIO2_OUT_3, + .gpio_in = GPIO2_OFFSET + REG_GPIO2_IN_3, + .gpio_oe = GPIO2_OFFSET + REG_GPIO2_OE_3, + .gpio_page = GPIO2_OFFSET + REG_GPIO2_PAGE, + .gpio_cfg = GPIO2_OFFSET + REG_GPIO2_CFG + } +}; +#else +const GPIOData gpios[6] = { + { + .no_pins = 32, + .pin_start_offset = 0, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_0, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_0, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_0, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 7, + .pin_start_offset = 32, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_1, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_1, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_1, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 16, + .pin_start_offset = 39, + .gpio_out = GPIO2_OFFSET + REG_GPIO2_OUT_2, + .gpio_in = GPIO2_OFFSET + REG_GPIO2_IN_2, + .gpio_oe = GPIO2_OFFSET + REG_GPIO2_OE_2, + .gpio_page = GPIO2_OFFSET + REG_GPIO2_PAGE, + .gpio_cfg = GPIO2_OFFSET + REG_GPIO2_CFG + }, + { + .no_pins = 12, + .pin_start_offset = 55, + .gpio_out = GPIO2_OFFSET + REG_GPIO2_OUT_3, + .gpio_in = GPIO2_OFFSET + REG_GPIO2_IN_3, + .gpio_oe = GPIO2_OFFSET + REG_GPIO2_OE_3, + .gpio_page = GPIO2_OFFSET + REG_GPIO2_PAGE, + .gpio_cfg = GPIO2_OFFSET + REG_GPIO2_CFG + }, + { + .no_pins = 32, + .pin_start_offset = 67, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_4, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_4, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_4, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 16, + .pin_start_offset = 99, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_5, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_5, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_5, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, +}; +#endif + +#define GPIO_TOTAL_LEN (sizeof(gpios) / sizeof(GPIOData)) +#include "gpio_msm_common.c" \ No newline at end of file diff --git a/plat/qcom/gpio/gpio_msm6x50.c b/plat/qcom/gpio/gpio_msm6x50.c new file mode 100644 index 0000000..cf285db --- /dev/null +++ b/plat/qcom/gpio/gpio_msm6x50.c @@ -0,0 +1,62 @@ +#include "dcc/plat.h" + +extern const uint32_t gpio_read_table[]; +extern const uint32_t gpio_write_table[]; +extern const uint32_t gpio_oe_table[]; +extern const uint32_t gpio_func_sel_table[]; + +void plat_gpio_get_reg_offset(uint32_t pin, uint8_t *reg_index, uint8_t *reg_bit_offset); + +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + uint8_t reg_index; + uint8_t pin_bit_offset; + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + + return (READ_U32(gpio_read_table[reg_index]) >> pin_bit_offset) & 1; +} + +static uint32_t gpio_buffers[8]; +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write + uint8_t reg_index; + uint8_t pin_bit_offset; + + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + bitmask gpio_write_bm = {pin_bit_offset, 1}; + + BIT_SET_VAR(gpio_buffers[reg_index], gpio_write_bm, active); + WRITE_U32(gpio_write_table[reg_index], gpio_buffers[reg_index]); +} + +static uint32_t gpio_dir_buffers[8]; +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) + uint8_t reg_index; + uint8_t pin_bit_offset; + + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + bitmask gpio_write_bm = {pin_bit_offset, 1}; + + BIT_SET_VAR(gpio_dir_buffers[reg_index], gpio_write_bm, dir == GPIO_INPUT ? 0 : 1); + WRITE_U32(gpio_oe_table[reg_index], gpio_dir_buffers[reg_index]); +} + +static uint32_t gpio_func_sel_buffers[8]; +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function + uint8_t reg_index; + uint8_t pin_bit_offset; + + if (FUNC_SEL_CONDITION) { + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + bitmask gpio_write_bm = {pin_bit_offset, 1}; + + BIT_SET_VAR(gpio_func_sel_buffers[reg_index], gpio_write_bm, alt_func); + WRITE_U32(gpio_func_sel_table[reg_index], gpio_func_sel_buffers[reg_index]); + } +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} \ No newline at end of file diff --git a/plat/qcom/gpio/gpio_msm7xxx.c b/plat/qcom/gpio/gpio_msm7xxx.c new file mode 100644 index 0000000..ff12fe5 --- /dev/null +++ b/plat/qcom/gpio/gpio_msm7xxx.c @@ -0,0 +1,85 @@ +#include "dcc/plat.h" +#include "gpio_msm_common.h" + +#ifndef GPIO1_OFFSET +#define GPIO1_OFFSET 0xA9000000 +#endif + +#ifndef GPIO2_OFFSET +#define GPIO2_OFFSET 0xA9100400 +#endif + +// GPIO1 Registers +#define REG_GPIO_OUT_0 0x0000 +#define REG_GPIO_OUT_2 0x0004 +#define REG_GPIO_OUT_3 0x0008 +#define REG_GPIO_OUT_4 0x000c +#define REG_GPIO_OE_0 0x0010 +#define REG_GPIO_OE_2 0x0014 +#define REG_GPIO_OE_3 0x0018 +#define REG_GPIO_OE_4 0x001c +#define REG_GPIO_PAGE 0x0020 +#define REG_GPIO_CFG 0x0024 +#define REG_GPIO_IN_0 0x0034 +#define REG_GPIO_IN_2 0x0038 +#define REG_GPIO_IN_3 0x003c +#define REG_GPIO_IN_4 0x0040 + +// GPIO2 Registers +#define REG_GPIO2_OUT_1 0x0000 +#define REG_GPIO2_OE_1 0x0008 +#define REG_GPIO2_PAGE 0x0010 +#define REG_GPIO2_CFG 0x0014 +#define REG_GPIO2_IN_1 0x0020 + +// GPIOs +const GPIOData gpios[5] = { + { + .no_pins = 16, + .pin_start_offset = 0, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_0, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_0, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_0, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 27, + .pin_start_offset = 16, + .gpio_out = GPIO2_OFFSET + REG_GPIO2_OUT_1, + .gpio_in = GPIO2_OFFSET + REG_GPIO2_IN_1, + .gpio_oe = GPIO2_OFFSET + REG_GPIO2_OE_1, + .gpio_page = GPIO2_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO2_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 25, + .pin_start_offset = 43, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_2, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_2, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_2, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 27, + .pin_start_offset = 68, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_3, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_3, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_3, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + }, + { + .no_pins = 24, + .pin_start_offset = 95, + .gpio_out = GPIO1_OFFSET + REG_GPIO_OUT_4, + .gpio_in = GPIO1_OFFSET + REG_GPIO_IN_4, + .gpio_oe = GPIO1_OFFSET + REG_GPIO_OE_4, + .gpio_page = GPIO1_OFFSET + REG_GPIO_PAGE, + .gpio_cfg = GPIO1_OFFSET + REG_GPIO_CFG + } +}; + +#define GPIO_TOTAL_LEN (sizeof(gpios) / sizeof(GPIOData)) +#include "gpio_msm_common.c" \ No newline at end of file diff --git a/plat/qcom/gpio/gpio_msm_common.c b/plat/qcom/gpio/gpio_msm_common.c new file mode 100644 index 0000000..791b9fb --- /dev/null +++ b/plat/qcom/gpio/gpio_msm_common.c @@ -0,0 +1,99 @@ +#include "gpio_msm_common.h" + +#ifndef GPIO_TOTAL_LEN +#define GPIO_TOTAL_LEN 6 +#endif + +extern const GPIOData gpios[]; + +void plat_gpio_get_reg_offset(uint32_t pin, uint8_t *reg_index, uint8_t *reg_bits) { + for (int i = 0; i < GPIO_TOTAL_LEN; i++) { + if (pin >= gpios[i].pin_start_offset && pin < (gpios[i].pin_start_offset + gpios[i].no_pins)) { + *reg_index = i; + *reg_bits = pin - gpios[i].pin_start_offset; + return; + } + } + + *reg_index = 0; + *reg_bits = 0; +} + +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + uint8_t reg_index; + uint8_t pin_bit_offset; + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + + return (READ_U32(gpios[reg_index].gpio_in) >> pin_bit_offset) & 1; +} + +static uint32_t gpio_buffers[8]; +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write + uint8_t reg_index; + uint8_t pin_bit_offset; + + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + bitmask gpio_write_bm = {pin_bit_offset, 1}; + + BIT_SET_VAR(gpio_buffers[reg_index], gpio_write_bm, active); + WRITE_U32(gpios[reg_index].gpio_out, gpio_buffers[reg_index]); +} + +static uint32_t gpio_dir_buffers[8]; +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) + uint8_t reg_index; + uint8_t pin_bit_offset; + + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + bitmask gpio_write_bm = {pin_bit_offset, 1}; + + BIT_SET_VAR(gpio_dir_buffers[reg_index], gpio_write_bm, dir == GPIO_INPUT ? 0 : 1); + WRITE_U32(gpios[reg_index].gpio_oe, gpio_dir_buffers[reg_index]); +} + +static uint32_t gpio_cfg_buffers[128]; +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function + uint8_t reg_index; + uint8_t pin_bit_offset; + + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_ALT_FUNC, alt_func); + + WRITE_U32(gpios[reg_index].gpio_page, pin); + WRITE_U32(gpios[reg_index].gpio_cfg, gpio_cfg_buffers[pin]); +} + +// The keeper keeps the output level the same even if you turn the driver off. +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) + uint8_t reg_index; + uint8_t pin_bit_offset; + + plat_gpio_get_reg_offset(pin, ®_index, &pin_bit_offset); + + switch (pull) { + case GPIO_PULL_DISABLED: + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_PULL_TYPE, 0b00); + break; + + case GPIO_PULL_UP: + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_PULL_TYPE, 0b11); + break; + + case GPIO_PULL_DOWN: + #if GPIO_NO_KEEPER + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_PULL_TYPE, 0b10); + #else + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_PULL_TYPE, 0b01); + #endif + break; + } + + WRITE_U32(gpios[reg_index].gpio_page, pin); + WRITE_U32(gpios[reg_index].gpio_cfg, gpio_cfg_buffers[pin]); +} \ No newline at end of file diff --git a/plat/qcom/gpio/gpio_msm_common.h b/plat/qcom/gpio/gpio_msm_common.h new file mode 100644 index 0000000..339a808 --- /dev/null +++ b/plat/qcom/gpio/gpio_msm_common.h @@ -0,0 +1,17 @@ +#pragma once +#include "dcc/plat.h" + +// GPIO Bitmask +const bitmask GPIO_CFG_ALT_FUNC = {2, 0xf}; +const bitmask GPIO_CFG_PULL_TYPE = {0, 0x3}; + +// GPIO data struct +typedef struct { + uint32_t no_pins; + uint32_t pin_start_offset; + uint32_t gpio_out; + uint32_t gpio_in; + uint32_t gpio_oe; + uint32_t gpio_page; + uint32_t gpio_cfg; +} GPIOData; \ No newline at end of file diff --git a/plat/qcom/gpio/gpio_qsc6xxx.c b/plat/qcom/gpio/gpio_qsc6xxx.c new file mode 100644 index 0000000..ba28dbc --- /dev/null +++ b/plat/qcom/gpio/gpio_qsc6xxx.c @@ -0,0 +1,139 @@ +#include "dcc/plat.h" +#include "gpio_msm_common.h" + +#ifndef GPIO1_OFFSET +#define GPIO1_OFFSET 0x8000A000 +#endif + +#ifndef GPIO2_OFFSET +#define GPIO2_OFFSET 0x84022000 +#endif + +// GPIO Registers +#if QSC60X5 | QSC11XX +#define REG_GPIO_OUT 0x0000 +#define REG_GPIO_OE 0x0008 +#define REG_GPIO_PAGE 0x0010 +#define REG_GPIO_CFG 0x0014 +#define REG_GPIO_IN 0x0018 +#elif QSC61X5 +#define REG_GPIO_OUT 0x0000 +#define REG_GPIO_OE 0x0010 +#define REG_GPIO_PAGE 0x0020 +#define REG_GPIO_CFG 0x0024 +#define REG_GPIO_IN 0x0028 +#else +#define REG_GPIO_OUT 0x0000 +#define REG_GPIO_OE 0x000c +#define REG_GPIO_PAGE 0x0018 +#define REG_GPIO_CFG 0x001c +#define REG_GPIO_IN 0x0020 +#endif + +// GPIO masks +// #define GPIO_MASK_01 0x1f801fe +// #define GPIO_MASK_02 0xffffe1c0 +// #define GPIO_MASK_03 0x3fff +#if QSC60X5 +const uint32_t gpio_mask_index[2] = {0x7c0037fe, 0x3fdc009}; +#elif QSC11XX +const uint32_t gpio_mask_index[2] = {0x7fffd000, 0x7fa003fc}; +#elif QSC61X5 +const uint32_t gpio_mask_index[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; +#else +const uint32_t gpio_mask_index[3] = {0x1f801fe, 0xffffe1c0, 0x3fff}; +#endif + +inline void plat_gpio_get_base(uint32_t pin, uint32_t reg_offset, uint32_t *reg_conv_offset, uint32_t *reg_mask) { + uint32_t pin_bit_offset = pin & 0x1f; + uint32_t mask_index = pin >> 5; + uint32_t base_offset = (gpio_mask_index[mask_index] & (1 << pin_bit_offset)) ? GPIO1_OFFSET : GPIO2_OFFSET; // 1 - GPIO1, 0 - GPIO2 + + *reg_conv_offset = base_offset + (mask_index << 2) + reg_offset; + *reg_mask = (gpio_mask_index[mask_index] & (1 << pin_bit_offset)) ? gpio_mask_index[mask_index] : ~(gpio_mask_index[mask_index]); +} + +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + uint32_t gpio_reg_offset; + uint32_t gpio_reg_mask; + uint8_t pin_bit_offset = pin & 0x1f; + + plat_gpio_get_base(pin, REG_GPIO_IN, &gpio_reg_offset, &gpio_reg_mask); + + return (READ_U32(gpio_reg_offset) >> pin_bit_offset) & 1; +} + +static uint32_t gpio_buffers[4]; +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write + uint32_t gpio_reg_offset; + uint32_t gpio_reg_mask; + uint8_t pin_bit_offset = pin & 0x1f; + uint32_t mask_index = pin >> 5; + + plat_gpio_get_base(pin, REG_GPIO_OUT, &gpio_reg_offset, &gpio_reg_mask); + bitmask gpio_write_bm = {pin_bit_offset, 1}; + + BIT_SET_VAR(gpio_buffers[mask_index], gpio_write_bm, active); + WRITE_U32(gpio_reg_offset, gpio_buffers[mask_index] & gpio_reg_mask); +} + +static uint32_t gpio_dir_buffers[4]; +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) + uint32_t gpio_reg_offset; + uint32_t gpio_reg_mask; + uint8_t pin_bit_offset = pin & 0x1f; + uint32_t mask_index = pin >> 5; + + plat_gpio_get_base(pin, REG_GPIO_OE, &gpio_reg_offset, &gpio_reg_mask); + bitmask gpio_write_bm = {pin_bit_offset, 1}; + + BIT_SET_VAR(gpio_dir_buffers[mask_index], gpio_write_bm, dir == GPIO_INPUT ? 0 : 1); + WRITE_U32(gpio_reg_offset, gpio_dir_buffers[mask_index] & gpio_reg_mask); +} + +static uint32_t gpio_cfg_buffers[128]; +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function + uint32_t gpio_reg_offset_page; + uint32_t gpio_reg_offset_cfg; + uint32_t gpio_reg_mask; + + plat_gpio_get_base(pin, REG_GPIO_PAGE, &gpio_reg_offset_page, &gpio_reg_mask); + plat_gpio_get_base(pin, REG_GPIO_CFG, &gpio_reg_offset_cfg, &gpio_reg_mask); + + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_ALT_FUNC, alt_func); + + WRITE_U32(gpio_reg_offset_page, pin); + WRITE_U32(gpio_reg_offset_cfg, gpio_cfg_buffers[pin]); +} + +// The keeper keeps the output level the same even if you turn the driver off. +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) + uint32_t gpio_reg_offset_page; + uint32_t gpio_reg_offset_cfg; + uint32_t gpio_reg_mask; + + plat_gpio_get_base(pin, REG_GPIO_PAGE, &gpio_reg_offset_page, &gpio_reg_mask); + plat_gpio_get_base(pin, REG_GPIO_CFG, &gpio_reg_offset_cfg, &gpio_reg_mask); + + switch (pull) { + case GPIO_PULL_DISABLED: + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_PULL_TYPE, 0b00); + break; + + case GPIO_PULL_UP: + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_PULL_TYPE, 0b11); + break; + + case GPIO_PULL_DOWN: + BIT_SET_VAR(gpio_cfg_buffers[pin], GPIO_CFG_PULL_TYPE, 0b01); + break; + } + + WRITE_U32(gpio_reg_offset_page, pin); + WRITE_U32(gpio_reg_offset_cfg, gpio_cfg_buffers[pin]); +} \ No newline at end of file diff --git a/plat/qcom/msm3000.c b/plat/qcom/msm3000.c index a33a64c..dc0598f 100644 --- a/plat/qcom/msm3000.c +++ b/plat/qcom/msm3000.c @@ -1,5 +1,161 @@ #include "dcc/plat.h" +#ifndef GPIO_IN +#define GPIO_IN 0x3000660 +#endif + +#ifndef GPIO_TSEN +#define GPIO_TSEN 0x3000674 +#endif + +#ifndef GPIO_FUNC +#define GPIO_FUNC 0x3000690 +#endif + +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + uint8_t gpio_page_offset = (pin >> 4) << 2; + uint8_t gpio_pin_bit_pos = pin & 0xf; + + return (READ_U16(GPIO_IN + gpio_page_offset) >> gpio_pin_bit_pos) & 1; +} + +static uint16_t gpio_buffers[5]; +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write + uint8_t gpio_page_offset = (pin >> 4) << 2; + uint8_t gpio_pin_bit_pos = pin & 0xf; + bitmask gpio_write_bm = {gpio_pin_bit_pos, 1}; + + BIT_SET_VAR(gpio_buffers[pin >> 4], gpio_write_bm, active); + WRITE_U16(GPIO_IN + gpio_page_offset, gpio_buffers[pin >> 4]); +} + +static uint16_t gpio_dir_buffers[5]; +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) + // GPIO pin write + uint8_t gpio_page_offset = (pin >> 4) << 2; + uint8_t gpio_pin_bit_pos = pin & 0xf; + bitmask gpio_write_bm = {gpio_pin_bit_pos, 1}; + + BIT_SET_VAR(gpio_dir_buffers[pin >> 4], gpio_write_bm, dir == GPIO_INPUT ? 0 : 1); + WRITE_U16(GPIO_TSEN + gpio_page_offset, gpio_dir_buffers[pin >> 4]); +} + +static uint16_t gpio_func_sel_buffers[5]; +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function + uint8_t func_sel_offset = 0; + uint8_t func_sel_bit_mask = 1; + uint8_t func_sel_bit_pos = 0; + +#if IS_MSM3100 || IS_MSM6000 + switch (pin) { + /* GPIO select 1*/ + case 37: + func_sel_bit_pos = 4; + break; + + case 38: + func_sel_bit_pos = 3; + break; + + case 39: + func_sel_bit_pos = 2; + break; + + case 40: + func_sel_bit_pos = 1; + break; + + case 41: + func_sel_bit_pos = 0; + break; + + #if IS_MSM6000 + case 42: + func_sel_bit_pos = 5; + func_sel_bit_mask = 0x3; + break; + #endif + + #if IS_MSM3100 + case 45: + func_sel_bit_pos = 8; + break; + + case 46: + func_sel_bit_pos = 9; + break; + + case 47: + func_sel_bit_pos = 10; + break; + #endif + + /* GPIO select 2 */ + + case 12: + func_sel_bit_pos = 13; + func_sel_offset = 1; + break; + + #if IS_MSM3100 + case 13: + func_sel_bit_pos = 2; + func_sel_offset = 1; + break; + #endif + + case 18: + case 19: + case 20: + case 21: + func_sel_bit_pos = 0; + func_sel_offset = 1; + break; + + case 30: + func_sel_bit_pos = 3; + func_sel_offset = 1; + func_sel_bit_mask = 0x7; + break; + + default: + return; + } +#else + switch (pin) { + case 26: + func_sel_bit_pos = 5; + break; + + case 29: + func_sel_bit_pos = 0; + break; + + case 30: + func_sel_bit_pos = 1; + func_sel_bit_mask = 0x7; + break; + + default: + return; + } +#endif + + uint8_t gpio_page_offset = func_sel_offset << 2; + bitmask gpio_write_bm = {func_sel_bit_pos, func_sel_bit_mask}; + + BIT_SET_VAR(gpio_func_sel_buffers[func_sel_offset], gpio_write_bm, alt_func); + WRITE_U16(GPIO_FUNC + gpio_page_offset, gpio_func_sel_buffers[func_sel_offset]); +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm3100.c b/plat/qcom/msm3100.c new file mode 100644 index 0000000..eb1edb1 --- /dev/null +++ b/plat/qcom/msm3100.c @@ -0,0 +1,6 @@ +#define GPIO_IN 0x3000660 +#define GPIO_TSEN 0x300066C +#define GPIO_FUNC 0x3000678 +#define IS_MSM3100 1 + +#include "msm3000.c" diff --git a/plat/qcom/msm5100.c b/plat/qcom/msm5100.c index ebf7523..32dbc30 100644 --- a/plat/qcom/msm5100.c +++ b/plat/qcom/msm5100.c @@ -1,5 +1,7 @@ #include "dcc/plat.h" +#include "gpio/gpio_msm5xxx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm5500.c b/plat/qcom/msm5500.c index ed640b6..9cd2327 100644 --- a/plat/qcom/msm5500.c +++ b/plat/qcom/msm5500.c @@ -1,5 +1,7 @@ #include "dcc/plat.h" +#include "gpio/gpio_msm5xxx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm6000.c b/plat/qcom/msm6000.c new file mode 100644 index 0000000..9cc7b27 --- /dev/null +++ b/plat/qcom/msm6000.c @@ -0,0 +1,6 @@ +#define GPIO_IN 0x3000660 +#define GPIO_TSEN 0x3000670 +#define GPIO_FUNC 0x3000680 +#define IS_MSM6000 1 + +#include "msm3000.c" diff --git a/plat/qcom/msm6050.c b/plat/qcom/msm6050.c index 23d3118..2c5fb74 100644 --- a/plat/qcom/msm6050.c +++ b/plat/qcom/msm6050.c @@ -1,5 +1,30 @@ #include "dcc/plat.h" +const uint32_t gpio_read_table[4] = {0x03000720, 0x03000724, 0x09000060, 0x09000064}; +const uint32_t gpio_write_table[4] = {0x030006e8, 0x030006ec, 0x09000008, 0x0900000c}; +const uint32_t gpio_oe_table[4] = {0x030006f4, 0x030006f8, 0x09000000, 0x09000004}; +const uint32_t gpio_func_sel_table[4] = {0x03000700, 0x03000704, 0x0, 0x0}; + +void plat_gpio_get_reg_offset(uint32_t pin, uint8_t *reg_index, uint8_t *reg_bit_offset) { + if (pin < 32) { + *reg_index = 0; + } else if (pin < 43) { + *reg_index = 1; + pin -= 32; + } else if (pin < 59) { + *reg_index = 2; + pin -= 43; + } else { + *reg_index = 3; + pin -= 59; + } + + *reg_bit_offset = pin; +} + +#define FUNC_SEL_CONDITION (pin < 43) +#include "gpio/gpio_msm6x50.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm6100.c b/plat/qcom/msm6100.c index 46b8b53..ac73af8 100644 --- a/plat/qcom/msm6100.c +++ b/plat/qcom/msm6100.c @@ -1,5 +1,11 @@ #include "dcc/plat.h" +#define GPIO1_OFFSET 0x80001200 +#define GPIO2_OFFSET 0x58000000 +#define MSM6100 1 +#define GPIO_NO_KEEPER 1 +#include "gpio/gpio_msm62xx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm6200.c b/plat/qcom/msm6200.c index df27a5c..a90580e 100644 --- a/plat/qcom/msm6200.c +++ b/plat/qcom/msm6200.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm6250.c b/plat/qcom/msm6250.c index e166c4c..d405eef 100644 --- a/plat/qcom/msm6250.c +++ b/plat/qcom/msm6250.c @@ -1,5 +1,33 @@ #include "dcc/plat.h" +const uint32_t gpio_read_table[5] = {0x84000168, 0x8400016c, 0x48000060, 0x48000064, 0x84000170}; +const uint32_t gpio_write_table[5] = {0x8400015c, 0x84000160, 0x48000008, 0x4800000c, 0x84000164}; +const uint32_t gpio_oe_table[5] = {0x84000150, 0x84000154, 0x48000000, 0x48000004, 0x84000158}; +const uint32_t gpio_func_sel_table[5] = {0x84000174, 0x84000178, 0x0, 0x0, 0x8400017c}; + +void plat_gpio_get_reg_offset(uint32_t pin, uint8_t *reg_index, uint8_t *reg_bit_offset) { + if (pin < 32) { + *reg_index = 0; + } else if (pin < 39) { + *reg_index = 1; + pin -= 32; + } else if (pin < 55) { + *reg_index = 2; + pin -= 39; + } else if (pin < 67) { + *reg_index = 3; + pin -= 55; + } else { + *reg_index = 4; + pin -= 67; + } + + *reg_bit_offset = pin; +} + +#define FUNC_SEL_CONDITION (pin < 39 || pin >= 67) +#include "gpio/gpio_msm6x50.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm6500.c b/plat/qcom/msm6500.c index 52ae8fc..1e0c986 100644 --- a/plat/qcom/msm6500.c +++ b/plat/qcom/msm6500.c @@ -1,5 +1,11 @@ #include "dcc/plat.h" +#define GPIO1_OFFSET 0x80002200 +#define GPIO2_OFFSET 0x48000000 +#define MSM6500 1 +#define GPIO_NO_KEEPER 1 +#include "gpio/gpio_msm62xx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm6550.c b/plat/qcom/msm6550.c index cfb3357..5e2bb6b 100644 --- a/plat/qcom/msm6550.c +++ b/plat/qcom/msm6550.c @@ -1,5 +1,10 @@ #include "dcc/plat.h" +#define GPIO1_OFFSET 0x80000400 +#define GPIO2_OFFSET 0x84005700 +#define GPIO_NO_KEEPER 1 +#include "gpio/gpio_msm62xx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm6800.c b/plat/qcom/msm6800.c index 6a7cb1d..c351c6e 100644 --- a/plat/qcom/msm6800.c +++ b/plat/qcom/msm6800.c @@ -1,5 +1,7 @@ #include "dcc/plat.h" +#include "gpio/gpio_msm62xx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/msm7200.c b/plat/qcom/msm7200.c index 41b9abc..33a1dfd 100644 --- a/plat/qcom/msm7200.c +++ b/plat/qcom/msm7200.c @@ -1,5 +1,7 @@ #include "dcc/plat.h" +#include "gpio/gpio_msm7xxx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/qsc1100.c b/plat/qcom/qsc1100.c new file mode 100644 index 0000000..6fb8173 --- /dev/null +++ b/plat/qcom/qsc1100.c @@ -0,0 +1,15 @@ +#include "dcc/plat.h" + +#define QSC11XX 1 +#include "gpio/gpio_qsc6xxx.c" + +void plat_init(void) { + // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) + // Can alternatively be turned off + // WRITE_U32(0x80034010, 1); +} + +void wdog_reset(void) { + WRITE_U32(0x8003400c, 1); + // Reset watchdog (or else, system restarts) +} \ No newline at end of file diff --git a/plat/qcom/qsc6010.c b/plat/qcom/qsc6010.c index e080b84..31e7ea5 100644 --- a/plat/qcom/qsc6010.c +++ b/plat/qcom/qsc6010.c @@ -1,5 +1,10 @@ #include "dcc/plat.h" +#define GPIO1_OFFSET 0x88006000 +#define GPIO2_OFFSET 0x88008000 +#define QSC60x0 1 +#include "gpio/gpio_msm62xx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/qsc6055.c b/plat/qcom/qsc6055.c new file mode 100644 index 0000000..aa4db27 --- /dev/null +++ b/plat/qcom/qsc6055.c @@ -0,0 +1,15 @@ +#include "dcc/plat.h" + +#define QSC60X5 1 +#include "gpio/gpio_qsc6xxx.c" + +void plat_init(void) { + // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) + // Can alternatively be turned off + // WRITE_U32(0x80034010, 1); +} + +void wdog_reset(void) { + WRITE_U32(0x8003400c, 1); + // Reset watchdog (or else, system restarts) +} \ No newline at end of file diff --git a/plat/qcom/qsc6155.c b/plat/qcom/qsc6155.c index e869282..3d29d4e 100644 --- a/plat/qcom/qsc6155.c +++ b/plat/qcom/qsc6155.c @@ -1,5 +1,14 @@ #include "dcc/plat.h" +// 80008000 = GPIO_OUT +// 80008010 = GPIO_OE +// 80008020 = GPIO_PAGE +// 80008024 = GPIO_CFG +// 80008028 = GPIO_IN + +#define QSC61X5 1 +#include "gpio/gpio_qsc6xxx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/qcom/qsc6270.c b/plat/qcom/qsc6270.c index 407f88e..bb6c0ac 100644 --- a/plat/qcom/qsc6270.c +++ b/plat/qcom/qsc6270.c @@ -1,5 +1,7 @@ #include "dcc/plat.h" +#include "gpio/gpio_qsc6xxx.c" + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) // Can alternatively be turned off diff --git a/plat/samsung/s3c24xx.c b/plat/samsung/s3c24xx.c index 8f961e8..6ba39f2 100644 --- a/plat/samsung/s3c24xx.c +++ b/plat/samsung/s3c24xx.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) WRITE_U32(0x53000000, 0x0); diff --git a/plat/samsung/s3c6410.c b/plat/samsung/s3c6410.c index 7ef73cc..5e141ff 100644 --- a/plat/samsung/s3c6410.c +++ b/plat/samsung/s3c6410.c @@ -1,5 +1,26 @@ #include "dcc/plat.h" +uint8_t plat_gpio_read(uint32_t pin) { + // GPIO pin read + return 0; +} + +void plat_gpio_write(uint32_t pin, uint8_t active) { + // GPIO pin write +} + +void plat_gpio_set_dir(uint32_t pin, GPIODirection dir) { + // GPIO set output direction (oe: 0 = input, 1 = output) +} + +void plat_gpio_set_alt_func(uint32_t pin, uint32_t alt_func) { + // GPIO set alt function +} + +void plat_gpio_set_pull(uint32_t pin, GPIOPullType pull) { + // GPIO set pull (0 = Pull disabled, 1 = Pull up, 2 = Pull down) +} + void plat_init(void) { // Initialize platform (after CMM, H/W init script, TCL, etc, and Uploading) WRITE_U32(0x7e004000, 0x0); diff --git a/tools/dccdumper.py b/tools/dccdumper.py new file mode 100644 index 0000000..1373a2c --- /dev/null +++ b/tools/dccdumper.py @@ -0,0 +1,687 @@ +# pyright: reportUnknownMemberType=false, reportOptionalMemberAccess=false, reportPrivateUsage=false, reportUnknownVariableType=false, reportUninitializedInstanceVariable=false + +from ctypes import * +from pylink import JLink +import crcmod +from enum import IntEnum +import struct +import random +import traceback +import sys +import time + +from logging import Logger, getLogger, basicConfig +from dataclasses import dataclass +from typing_extensions import override +from construct import * +from construct_typed import DataclassMixin, DataclassStruct, csfield +from typing import IO, Any, Literal, Self +from tap import Tap + +class _EnhancedDataclassMixin(DataclassMixin): + @classmethod + def format(cls): + return DataclassStruct(cls) + + @classmethod + def build(cls, obj: Self, **kw: Any): # pyright: ignore[reportExplicitAny, reportAny] + return cls.format().build(obj, **kw) + + @classmethod + def parse(cls, data: bytes|bytearray, **kw: Any):# pyright: ignore[reportExplicitAny, reportAny] + return cls.format().parse(data, **kw) + + @classmethod + def parse_file(cls, file: str, **kw: Any):# pyright: ignore[reportExplicitAny, reportAny] + return cls.format().parse_file(file, **kw) + + @classmethod + def parse_stream(cls, stream: IO[bytes], **kw: Any):# pyright: ignore[reportExplicitAny, reportAny] + return cls.format().parse_stream(stream, **kw) + +class ArmRegs(IntEnum): + ARM_REG_R0 = 0 + ARM_REG_R1 = 1 + ARM_REG_R2 = 2 + ARM_REG_R3 = 3 + ARM_REG_R4 = 4 + ARM_REG_R5 = 5 + ARM_REG_R6 = 6 + ARM_REG_R7 = 7 + ARM_REG_CPSR = 8 + ARM_REG_R15 = 9 + ARM_REG_R8_USR = 10 + ARM_REG_R9_USR = 11 + ARM_REG_R10_USR = 12 + ARM_REG_R11_USR = 13 + ARM_REG_R12_USR = 14 + ARM_REG_R13_USR = 15 + ARM_REG_R14_USR = 16 + ARM_REG_SPSR_FIQ = 17 + ARM_REG_R8_FIQ = 18 + ARM_REG_R9_FIQ = 19 + ARM_REG_R10_FIQ = 20 + ARM_REG_R11_FIQ = 21 + ARM_REG_R12_FIQ = 22 + ARM_REG_R13_FIQ = 23 + ARM_REG_R14_FIQ = 24 + ARM_REG_SPSR_SVC = 25 + ARM_REG_R13_SVC = 26 + ARM_REG_R14_SVC = 27 + ARM_REG_SPSR_ABT = 28 + ARM_REG_R13_ABT = 29 + ARM_REG_R14_ABT = 30 + ARM_REG_SPSR_IRQ = 31 + ARM_REG_R13_IRQ = 32 + ARM_REG_R14_IRQ = 33 + ARM_REG_SPSR_UND = 34 + ARM_REG_R13_UND = 35 + ARM_REG_R14_UND = 36 + ARM_REG_FPSID = 37 + ARM_REG_FPSCR = 38 + ARM_REG_FPEXC = 39 + ARM_REG_FPS0 = 40 + ARM_REG_FPS1 = 41 + ARM_REG_FPS2 = 42 + ARM_REG_FPS3 = 43 + ARM_REG_FPS4 = 44 + ARM_REG_FPS5 = 45 + ARM_REG_FPS6 = 46 + ARM_REG_FPS7 = 47 + ARM_REG_FPS8 = 48 + ARM_REG_FPS9 = 49 + ARM_REG_FPS10 = 50 + ARM_REG_FPS11 = 51 + ARM_REG_FPS12 = 52 + ARM_REG_FPS13 = 53 + ARM_REG_FPS14 = 54 + ARM_REG_FPS15 = 55 + ARM_REG_FPS16 = 56 + ARM_REG_FPS17 = 57 + ARM_REG_FPS18 = 58 + ARM_REG_FPS19 = 59 + ARM_REG_FPS20 = 60 + ARM_REG_FPS21 = 61 + ARM_REG_FPS22 = 62 + ARM_REG_FPS23 = 63 + ARM_REG_FPS24 = 64 + ARM_REG_FPS25 = 65 + ARM_REG_FPS26 = 66 + ARM_REG_FPS27 = 67 + ARM_REG_FPS28 = 68 + ARM_REG_FPS29 = 69 + ARM_REG_FPS30 = 70 + ARM_REG_FPS31 = 71 + ARM_REG_R8 = 72 + ARM_REG_R9 = 73 + ARM_REG_R10 = 74 + ARM_REG_R11 = 75 + ARM_REG_R12 = 76 + ARM_REG_R13 = 77 + ARM_REG_R14 = 78 + ARM_REG_SPSR = 79 + +class ResetType(IntEnum): + ARM_RESET_TYPE_NORMAL = 0 + ARM_RESET_TYPE_BP0 = 1 + ARM_RESET_TYPE_ADI = 2 + ARM_RESET_TYPE_NO_RESET = 3 + ARM_RESET_TYPE_HALT_WP = 4 + ARM_RESET_TYPE_HALT_DBGRQ = 5 + ARM_RESET_TYPE_SOFT = 6 + ARM_RESET_TYPE_HALT_DURING = 7 + ARM_RESET_TYPE_SAM7 = 8 + ARM_RESET_TYPE_LPC = 9 + RESET_TYPE_CORE = 100 + RESET_TYPE_RESET_PIN = 101 + +@dataclass +class NANDDeviceInfo: + page_size: int + flash_size: int + block_size: int + bits: int + +_NAND_DEV_IDS = { + 0x6e: NANDDeviceInfo(0x100, 0x100000, 0x800, 8), + 0x64: NANDDeviceInfo(0x100, 0x200000, 0x800, 8), + 0xe8: NANDDeviceInfo(0x100, 0x100000, 0x800, 8), + 0xec: NANDDeviceInfo(0x100, 0x100000, 0x800, 8), + 0xea: NANDDeviceInfo(0x100, 0x200000, 0x800, 8), + 0x6b: NANDDeviceInfo(0x200, 0x400000, 0x2000, 8), + 0xe3: NANDDeviceInfo(0x200, 0x400000, 0x2000, 8), + 0xe5: NANDDeviceInfo(0x200, 0x400000, 0x2000, 8), + 0xd6: NANDDeviceInfo(0x200, 0x800000, 0x2000, 8), + 0x39: NANDDeviceInfo(0x200, 0x8000000, 0x4000, 8), + 0xe6: NANDDeviceInfo(0x200, 0x800000, 0x2000, 8), + 0x49: NANDDeviceInfo(0x200, 0x8000000, 0x4000, 16), + 0x59: NANDDeviceInfo(0x200, 0x8000000, 0x4000, 16), + 0x33: NANDDeviceInfo(0x200, 0x1000000, 0x4000, 8), + 0x73: NANDDeviceInfo(0x200, 0x1000000, 0x4000, 8), + 0x43: NANDDeviceInfo(0x200, 0x1000000, 0x4000, 16), + 0x53: NANDDeviceInfo(0x200, 0x1000000, 0x4000, 16), + 0x35: NANDDeviceInfo(0x200, 0x2000000, 0x4000, 8), + 0x75: NANDDeviceInfo(0x200, 0x2000000, 0x4000, 8), + 0x45: NANDDeviceInfo(0x200, 0x2000000, 0x4000, 16), + 0x55: NANDDeviceInfo(0x200, 0x2000000, 0x4000, 16), + 0x36: NANDDeviceInfo(0x200, 0x4000000, 0x4000, 8), + 0x76: NANDDeviceInfo(0x200, 0x4000000, 0x4000, 8), + 0x46: NANDDeviceInfo(0x200, 0x4000000, 0x4000, 16), + 0x56: NANDDeviceInfo(0x200, 0x4000000, 0x4000, 16), + 0x78: NANDDeviceInfo(0x200, 0x8000000, 0x4000, 8), + 0x79: NANDDeviceInfo(0x200, 0x8000000, 0x4000, 8), + 0x72: NANDDeviceInfo(0x200, 0x8000000, 0x4000, 16), + 0x74: NANDDeviceInfo(0x200, 0x8000000, 0x4000, 16), + 0x71: NANDDeviceInfo(0x200, 0x10000000, 0x4000, 8), + 0xa2: NANDDeviceInfo(0x00, 0x4000000, 0x00, 8), + 0xb2: NANDDeviceInfo(0x00, 0x4000000, 0x00, 16), + 0xc2: NANDDeviceInfo(0x00, 0x4000000, 0x00, 16), + 0xf2: NANDDeviceInfo(0x00, 0x4000000, 0x00, 8), + 0xa1: NANDDeviceInfo(0x00, 0x8000000, 0x00, 8), + 0xb1: NANDDeviceInfo(0x00, 0x8000000, 0x00, 16), + 0xc1: NANDDeviceInfo(0x00, 0x8000000, 0x00, 16), + 0xf1: NANDDeviceInfo(0x00, 0x8000000, 0x00, 8), + 0xaa: NANDDeviceInfo(0x00, 0x10000000, 0x00, 8), + 0xba: NANDDeviceInfo(0x00, 0x10000000, 0x00, 16), + 0xca: NANDDeviceInfo(0x00, 0x10000000, 0x00, 16), + 0xda: NANDDeviceInfo(0x00, 0x10000000, 0x00, 8), + 0xac: NANDDeviceInfo(0x00, 0x20000000, 0x00, 8), + 0xbc: NANDDeviceInfo(0x00, 0x20000000, 0x00, 16), + 0xcc: NANDDeviceInfo(0x00, 0x20000000, 0x00, 16), + 0xdc: NANDDeviceInfo(0x00, 0x20000000, 0x00, 8), + 0xa3: NANDDeviceInfo(0x00, 0x40000000, 0x00, 8), + 0xb3: NANDDeviceInfo(0x00, 0x40000000, 0x00, 16), + 0xc3: NANDDeviceInfo(0x00, 0x40000000, 0x00, 16), + 0xd3: NANDDeviceInfo(0x00, 0x40000000, 0x00, 8), + 0xa5: NANDDeviceInfo(0x00, 0x80000000, 0x00, 8), + 0xb5: NANDDeviceInfo(0x00, 0x80000000, 0x00, 16), + 0xc5: NANDDeviceInfo(0x00, 0x80000000, 0x00, 16), + 0xd5: NANDDeviceInfo(0x00, 0x80000000, 0x00, 8) +} + +@dataclass +class DCCLoaderInfoPacket(_EnhancedDataclassMixin): + @dataclass + class Error(_EnhancedDataclassMixin): + error_code: int = csfield(Hex(Int32ul)) + + @dataclass + class BufferInfo(_EnhancedDataclassMixin): + read_buffer_size: int = csfield(Int32ul) + write_buffer_size: int = csfield(IfThenElse(this._.dev_type & 0x100, Int32ul, Computed(this.read_buffer_size))) + + @dataclass + class MemoryInfo(_EnhancedDataclassMixin): + @dataclass + class ExtendParams(_EnhancedDataclassMixin): + emmc_no_sectors: int | None = csfield(If(this._._dev_type & 0x10, Int32ul)) + name: str | None = csfield(If(this._._dev_type & 0x80, Aligned(4, PascalString(Int8ul, "ascii")))) + extend_flags: int = csfield(Hex(Rebuild(Int8ul, this._._dev_type & 0xff))) + page_size_log2: int = csfield(Hex(Int8ul)) + block_size_log2: int = csfield(Hex(Int8ul)) + size_mb_log2: int = csfield(Hex(Int8ul)) + + _dev_type: int = csfield(Computed(this._.dev_type)) # pyright: ignore[reportAny] + manufacturer_id: int = csfield(Hex(Int16ul)) + device_id: int = csfield(Hex(Int16ul)) + extend_params: ExtendParams | None = csfield(If((this._dev_type & 3) == 3, ExtendParams.format())) + have_oob: bool = csfield(Computed(lambda x: (x._dev_type & 0xb) in [0x0, 0x3])) # pyright: ignore[reportAny] + + dev_magic: bytes = csfield(Const(b"OK")) + dev_type: int = csfield(Hex(Int16ul)) + data: Error | BufferInfo | MemoryInfo = csfield(IfThenElse(this.dev_type == 0xffff, Error.format(), IfThenElse(this.dev_type & 4, BufferInfo.format(), MemoryInfo.format()))) + +@dataclass +class DCCMemDevice: + manufacturer_id: int + device_id: int + page_size: int # 1 << n + block_size: int # 1 << n + flash_size: int # (1 << n) << 20 + have_oob: bool + +class DumpDCC(): + def __init__(self, jlink: JLink, bp_loader: bool=False, logger: Logger | None=None): + self.jlink: JLink = jlink # JLink context + self.__is_bp_loader: bool = bp_loader # Breakpoint loader + + # Variables + self.__is_loaded: bool = False + self.__start_offset: int = 0 + self.flash_devices: list[DCCMemDevice | None] = [] + self.__logger: Logger | None = logger + self.__read_buf_size: int = 0 + self.__write_buf_size: int = 0 + self.__bp_loader_breakpoint_pc: int = 0 + self.__bp_loader_read_data: list[int] = [] + self.__bp_loader_data_fetched: bool = False + + def load(self, binary: bytes|bytearray|str, start_offset: int): + if isinstance(binary, str): + binary = open(binary, "rb").read() + + assert (start_offset % 4) == 0, "Invalid destination offset" + + # 00 - Reset variables + self.__is_loaded = False + self.__start_offset = start_offset + self.flash_devices.clear() + self.__read_buf_size = 0 + self.__write_buf_size = 0 + self.__bp_loader_breakpoint_pc = 0 + self.jlink.breakpoint_clear_all() + self.__bp_loader_read_data.clear() + self.__bp_loader_data_fetched = False + + # 01 - Ram self test + if self.__logger is not None: + self.__logger.debug("Running RAM self test for 0x%08x", start_offset) + + ram_selftest_data = random.randbytes(0x800) + self.jlink.memory_write8(start_offset, [x for x in ram_selftest_data]) + + ram_selftest_read = bytes(self.jlink.memory_read8(start_offset, 0x800)) + assert ram_selftest_read == ram_selftest_data, "Upload test failed" + + # 02 - Upload and restart + if self.__logger is not None: + self.__logger.debug("Uploading loader to 0x%08x", start_offset) + + self.jlink.memory_write8(start_offset, [x for x in binary]) + + if self.__is_bp_loader: + #bp_loader_breakpoint = int.from_bytes(binary[0x34:0x38], "little") + bp_loader_breakpoint: int = self.jlink.memory_read32(start_offset + 0x34, 1)[0] + if self.__logger is not None: + self.__logger.debug("Setting loader breakpoint at 0x%08x", bp_loader_breakpoint) + + self.__bp_loader_breakpoint_pc = bp_loader_breakpoint + self.jlink.hardware_breakpoint_set(bp_loader_breakpoint, arm=True) + + self.jlink.register_write(ArmRegs.ARM_REG_CPSR, 0xd3) # Disable all interrupts and go to supervisor mode + self.jlink.register_write(ArmRegs.ARM_REG_R15, start_offset) + + self.jlink.restart() + + # 03 - DCC Load start + if self.__logger is not None: + self.__logger.debug("Began flash device probing") + + dcc_init_data = GreedyRange(DCCLoaderInfoPacket.format()).parse(self.__dcc_read_data()) + + for flash_n, f in enumerate(dcc_init_data, start=1): + if isinstance(f.data, DCCLoaderInfoPacket.Error): + if self.__logger is not None: + self.__logger.warning("Probe failed for dev id %d (code 0x%02x)", flash_n, f.data.error_code) + + self.flash_devices.append(None) + + elif isinstance(f.data, DCCLoaderInfoPacket.BufferInfo): + if self.__logger is not None: + self.__logger.debug("read buffer size: 0x%08x, write buffer size: 0x%08x", f.data.read_buffer_size, f.data.write_buffer_size) + + self.__read_buf_size = f.data.read_buffer_size + self.__write_buf_size = f.data.write_buffer_size + + else: + if f.data.extend_params is None: + device_id = f.data.device_id & 0xff + is_nor = (f.dev_type & 0x3) == 1 + + block_size = (1 << (f.dev_type >> 8)) if is_nor else _NAND_DEV_IDS[device_id].block_size + page_size = 0x200 if is_nor else _NAND_DEV_IDS[device_id].page_size + + if not page_size: + device_id_high = f.data.device_id >> 8 + page_size_bits = device_id_high & 3 + block_size_bits = (device_id_high >> 4) & 3 + + page_size = 1 << (10 + page_size_bits) + block_size = (1 << (6 + block_size_bits)) << 10 + + self.flash_devices.append(DCCMemDevice(f.data.manufacturer_id, f.data.device_id, page_size, block_size, _NAND_DEV_IDS[device_id].flash_size, f.data.have_oob)) + + else: + self.flash_devices.append(DCCMemDevice(f.data.manufacturer_id, f.data.device_id, 1 << f.data.extend_params.page_size_log2, 1 << f.data.extend_params.block_size_log2, (1 << f.data.extend_params.size_mb_log2) << 20, f.data.have_oob)) + + if self.__logger is not None: + self.__logger.debug("flash devices:") + for id, fd in enumerate(self.flash_devices, start=1): + self.__logger.debug("id %d: %s", id, fd) + + self.__is_loaded = True + + def __dcc_do_read(self, length: int) -> list[int]: + if self.__is_bp_loader: + if not self.__bp_loader_data_fetched: + # 01 - Watit for breakpoint + while True: + time.sleep(0.01) + if self.jlink.halted(): + break + + # 02 - Check breakpoint PC + pc = self.jlink.register_read(ArmRegs.ARM_REG_R15) + assert pc == self.__bp_loader_breakpoint_pc, "Something is wrong with the breakpoint" + + # 03 - Read breakpoint data + bp_loader_ptr: int = self.jlink.memory_read32(self.__start_offset + 0x30, 1)[0] + bp_loader_size: int = self.jlink.memory_read32(self.__start_offset + 0x2c, 1)[0] + + self.__bp_loader_read_data = list[int](self.jlink.memory_read32(bp_loader_ptr, bp_loader_size >> 2)) # pyright: ignore[reportUnknownArgumentType] + assert len(self.__bp_loader_read_data) == (bp_loader_size >> 2), f"dcc read error ({len(self.__bp_loader_read_data)} != {bp_loader_size >> 2})" + + # 04 - Mark as fetched + self.__bp_loader_data_fetched = True + + if self.__logger is not None: + self.__logger.debug("bp loader read buffer: %s, read length: %d", self.__bp_loader_read_data[:16], length) + + temp = self.__bp_loader_read_data[:length] + self.__bp_loader_read_data = self.__bp_loader_read_data[length:] + + return temp + + else: + dcc_read_data = (c_uint32 * length)() + dcc_read_num: int = self.jlink._dll.JLINKARM_ReadDCC(dcc_read_data, length, 2500) + + assert dcc_read_num == length, f"dcc read error ({dcc_read_num} != {length})" + + return list[int](dcc_read_data) + + def __dcc_do_write(self, values: list[int]): + if self.__is_bp_loader: + self.__bp_loader_read_data.clear() + self.__bp_loader_data_fetched = False + + bp_loader_ptr: int = self.jlink.memory_read32(self.__start_offset + 0x30, 1)[0] + + write_no_values = self.jlink.memory_write32(bp_loader_ptr, values) + write_len = self.jlink.memory_write32(self.__start_offset + 0x2c, [len(values) << 2]) + + assert write_no_values == len(values), f"dcc write error ({write_no_values} != {len(values)})" + assert write_len == 1, f"dcc write error (len) ({write_len} != 1)" + + else: + dcc_write_data = (c_uint32 * len(values))(*values) + dcc_write_num: int = self.jlink._dll.JLINKARM_WriteDCC(dcc_write_data, len(values), 2500) + + assert dcc_write_num == len(values), f"dcc write error ({dcc_write_num} != {len(values)})" + + def __dcc_read_data(self) -> bytes: + # 01 - Get Length + dcc_data_len: int = self.__dcc_do_read(1)[0] + + # 02 - Read Data + len_data_plus_crc: int = dcc_data_len + 1 + dcc_read_data: list[int] = self.__dcc_do_read(len_data_plus_crc) + + dcc_data: list[int] = dcc_read_data[:dcc_data_len] + dcc_crc32_expect: int = dcc_read_data[dcc_data_len] + dcc_data_bytes: bytes = b"".join(x.to_bytes(4, "little") for x in dcc_data) + + # 03 - Verify data + dcc_crc32_hash = crcmod.mkCrcFun(0x104c11db7, 0xffffffff, False, 0) + + dcc_crc_computed = dcc_crc32_hash(dcc_data_bytes) + assert dcc_crc_computed == dcc_crc32_expect, f"dcc data checksum mismatch (0x{dcc_crc_computed:08x} != 0x{dcc_crc32_expect:08x})" + + return dcc_data_bytes + + @staticmethod + def __decompress(data: bytes) -> bytes: + o = 0 + buf = bytearray() + + while o < len(data): + c = int.from_bytes(data[o:o + 2], "little") + + if c & 0x8000: + c &= 0x7fff + #print("rle", hex(c[0])) + buf += data[o + 2:o + 3] * c + o += 3 + + else: + #print("raw", hex(c)) + buf += data[o + 2:(o + 2) + c] + o += 2 + c + + return bytes(buf) + + def read_flash(self, offset: int, length: int, flash_id: int=1) -> tuple[bytes, bytes]: + # 01 - Check parameters + assert self.__is_loaded, "Please load the DCC loader code first" + + if flash_id == 0: # MCU + assert (offset % 4) == 0, "read offset must be dword aligned" + assert (length % 4) == 0, "read size must be dword aligned" + + else: # Flash + read_flash_id = flash_id - 1 + assert read_flash_id < len(self.flash_devices) and self.flash_devices[read_flash_id] is not None, "Invalid flash ID" + assert (offset % self.flash_devices[read_flash_id].page_size) == 0, "read offset must be page aligned" + assert (length % self.flash_devices[read_flash_id].page_size) == 0, "read size must be page aligned" + + # 02 - Initialize variables + outp_data = bytearray() + outp_oob = bytearray() + + read_n = 0 + + # 03 - Main read + while length > 0: + read_len = min(self.__read_buf_size, length) + + # 04 - Send read command + if self.__logger is not None: + self.__logger.debug("sending read command: id %d, offset: 0x%08x, size: 0x%08x", flash_id, offset + read_n, read_len) + + self.__dcc_do_write([0x52 | (flash_id << 8), offset + read_n, read_len]) + data = self.__dcc_read_data() + + # 05 - Handle response + if self.__logger is not None: + self.__logger.debug("got read response: %s", data[:16]) + + match data[0]: + case 0xff: + raise Exception(f"read flash error, code: 0x{data[1]:02x}") + + case 0x00: + outp_data += data[4:4+read_len] + outp_oob += data[4+read_len:] + + case 0x01: + rle_read_size = int.from_bytes(data[4:8], "little") - 4 + rle_decomp = self.__decompress(data[8:8+rle_read_size]) + + outp_data += rle_decomp[:read_len] + outp_oob += rle_decomp[read_len:] + + case _: + raise Exception(f"not implemented: 0x{data[0]:02x}") + + read_n += read_len + length -= read_len + + return bytes(outp_data), bytes(outp_oob) + +def runHAS(j: JLink, has: str): + myHAS = open(has, "rb") + while True: + fp = myHAS.read(4) + if len(fp) < 4: break + + cmd = int.from_bytes(fp, "little", signed=True) + if cmd == -1: + offset, data = struct.unpack(" None: + self.add_argument("loader") + self.add_argument("output") + self.add_argument("load_offset", type=self.intorhex) + self.add_argument("read_start_offset", type=self.intorhex) + self.add_argument("read_size", type=self.intorhex) + self.add_argument("--read_block_size", type=self.intorhex) + +if __name__ == "__main__": + basicConfig(level="INFO", format="[%(levelname)s] (%(name)s) %(message)s") + logger = getLogger("DCC Dumper") + + args = Args().parse_args() + speed = "adaptive" if args.speed == -2 else ("auto" if args.speed == -1 else args.speed) + logger.info("Loader: %s", args.loader) + logger.info("Output: %s", args.output) + logger.info("Load offset: 0x%08x", args.load_offset) + logger.info("Read start offset: 0x%08x", args.read_start_offset) + logger.info("Read size: 0x%08x", args.read_size) + logger.info("Speed (kHZ): %s", speed) + logger.info("Family: %s", args.family) + logger.info("Script: %s", args.script if args.script else "(none)") + logger.info("Target Flash ID: %d", args.flash_id) + logger.info("Breakpoint loader: %s", args.breakpoint_loader) + logger.info("Read block size: 0x%08x", args.read_block_size) + + myJLink: JLink = JLink() + myJLink.disable_dialog_boxes() + myJLink.exec_command("SuppressEmuUSBDialog") + + logger.info("Connecting to JLink") + myJLink.open() + + logger.info("Connecting to target") + myJLink.connect(args.family, speed=speed) # pyright: ignore[reportArgumentType] + + logger.info("Halting target") + myJLink.halt() + + assert myJLink.halted(), "Target cannot be halted" # Cannot halt the target + + logger.info("Resetting target") + match args.reset_strategy: + case "halt_reset": + myJLink.set_reset_strategy(ResetType.ARM_RESET_TYPE_NORMAL) + + case "halt_bp": + myJLink.set_reset_strategy(ResetType.ARM_RESET_TYPE_BP0) + + case "halt_wp": + myJLink.set_reset_strategy(ResetType.ARM_RESET_TYPE_HALT_WP) + + case "halt_dbgrq": + myJLink.set_reset_strategy(ResetType.ARM_RESET_TYPE_HALT_DBGRQ) + + case "software": + myJLink.set_reset_strategy(ResetType.ARM_RESET_TYPE_SOFT) + + myJLink.reset() + assert myJLink.halted(), "Target not halted after reset" # Cannot halt the target after reset + + if args.script: + logger.info("Executing HAS script") + runHAS(myJLink, args.script) + + logger.info("Uploading loader to target") + loader = DumpDCC(myJLink, args.breakpoint_loader, logger) + loader.load(args.loader, args.load_offset) + + logger.info("Available flash devices:") + for id, flash in enumerate(filter(lambda x: x is not None, loader.flash_devices), start=1): + logger.info("CHIP%d: ID 0x%02X/0x%02X (%dMB)", id, flash.manufacturer_id, flash.device_id, flash.flash_size >> 20) + + dump_oob = bytearray() + + with open(args.output, "wb") as dumpOut: + try: + cur_offset = args.read_start_offset + END_OFFSET = args.read_start_offset + args.read_size + + while cur_offset < END_OFFSET: + read_size = min(args.read_block_size, END_OFFSET - cur_offset) + logger.debug("Reading %d bytes command to loader at 0x%08x", read_size, cur_offset) + + blk_dump_data, blk_dump_oob = loader.read_flash(cur_offset, read_size, args.flash_id) + + dumpOut.write(blk_dump_data) + dump_oob += blk_dump_oob + + cur_offset += read_size + + dumpOut.write(dump_oob) + + except Exception as e: + print(f"ERROR: {e}", file=sys.stderr) + traceback.print_exc() + + try: + myJLink.halt() + assert myJLink.halted(), "cannot halt" + + print("registers:") + + regs = myJLink.register_list() + vals = myJLink.register_read_multiple(regs) + + for reg, val in zip(regs, vals): + name = myJLink.register_name(reg) + print(f"{name} = 0x{val:08x}") + + print("stack (r13; sp:sp+0x40):") + sp = myJLink.register_read(ArmRegs.ARM_REG_R13_SVC) + for e, i in enumerate(myJLink.memory_read32(sp, 16)): + print(f"0x{sp + (4 * e):08x} = 0x{i:08x}") + + print("stack (r13; sp-0x40:sp):") + for e, i in enumerate(myJLink.memory_read32(sp - 0x40, 16)): + print(f"0x{(sp - 0x40) + (4 * e):08x} = 0x{i:08x}") + + except Exception as e: + print(f"cannot get arm state dump:", file=sys.stderr) + traceback.print_exc() + + myJLink.close()