diff --git a/bootloader/hos/fss.c b/bootloader/hos/fss.c index 891656a..14e50ac 100644 --- a/bootloader/hos/fss.c +++ b/bootloader/hos/fss.c @@ -164,7 +164,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt) if (mariko_not_supported) { - EPRINTF("Mariko not supported on < 0.17.0!"); + EPRINTF("\nMariko not supported on < 0.17.0!"); goto fail; } diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 3f1898a..8a5bb5e 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -756,22 +756,20 @@ int hos_launch(ini_sec_t *cfg) // Check if fuses lower than 4.0.0 or 9.0.0 or 11.0.0 and if yes apply NO Gamecard patch. // Additionally check if running emuMMC and disable GC if v3/v4 fuses are burnt and HOS is <= 8.1.0 or != 11.0.0. - //TODO: Add better checks for 11.0.0 in case mkey doesn't change. if (!ctxt.stock) { u32 fuses = fuse_read_odm(7); - bool is_hos_11000 = !memcmp(ctxt.pkg1_id->id, "20201030110855", 8); if ((h_cfg.autonogc && ( - (!(fuses & ~0xF) && (kb >= KB_FIRMWARE_VERSION_400)) || // LAFW v2. - (!(fuses & ~0x3FF) && (kb >= KB_FIRMWARE_VERSION_900)) || // LAFW v3. - (!(fuses & ~0x1FFF) && is_hos_11000) // LAFW v4. + (!(fuses & ~0xF) && (ctxt.pkg1_id->fuses >= 5)) || // LAFW v2, 4.0.0+ + (!(fuses & ~0x3FF) && (ctxt.pkg1_id->fuses >= 11)) || // LAFW v3, 9.0.0+ + (!(fuses & ~0x1FFF) && (ctxt.pkg1_id->fuses >= 14)) // LAFW v4, 11.0.0+ ) ) || ((emummc_enabled) && ( - ((fuses & 0x400) && (kb <= KB_FIRMWARE_VERSION_810)) || // HOS 9.0.0 fuses burnt. - ((fuses & 0x2000) && !is_hos_11000) // HOS 11.0.0 fuses burnt. + ((fuses & 0x400) && (ctxt.pkg1_id->fuses <= 10)) || // HOS 9.0.0+ fuses burnt. + ((fuses & 0x2000) && (ctxt.pkg1_id->fuses <= 13)) // HOS 11.0.0+ fuses burnt. ) )) config_kip1patch(&ctxt, "nogc"); @@ -845,7 +843,7 @@ int hos_launch(ini_sec_t *cfg) } // Configure and manage Warmboot binary. - pkg1_warmboot_config(&ctxt, kb, warmboot_base); + pkg1_warmboot_config(&ctxt, warmboot_base); // Replace 'warmboot.bin' if requested. if (ctxt.warmboot) diff --git a/bootloader/hos/pkg1.c b/bootloader/hos/pkg1.c index b432a24..e6fe6b6 100644 --- a/bootloader/hos/pkg1.c +++ b/bootloader/hos/pkg1.c @@ -77,7 +77,7 @@ PATCHSET_DEF(_secmon_6_patchset, // { 0x1A68 + 0x3A6C, _NOP() } // warmboot UARTA cfg. ); -PATCHSET_DEF(_secmon_620_patchset, +PATCHSET_DEF(_secmon_62_patchset, // Patch package2 signature/hash checks. { 0xDC8 + 0xC74, _NOP() } // Fix sleep mode for debug. @@ -153,23 +153,24 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM }; static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB }; + // ID (Timestamp), KB, Fuses, TSEC, PK11, SECMON, Warmboot. static const pkg1_id_t _pkg1_ids[] = { - { "20161121183008", 0, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset, _warmboot_1_patchset }, // 1.0.0 (Patched relocator). - { "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset, _warmboot_2_patchset }, // 2.0.0 - 2.3.0. - { "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.0. - { "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.1 - 3.0.2. - { "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_4_patchset, _warmboot_4_patchset }, // 4.0.0 - 4.1.0. - { "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_5_patchset, _warmboot_4_patchset }, // 5.0.0 - 5.1.0. - { "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800, _secmon_6_patchset, _warmboot_4_patchset }, // 6.0.0 - 6.1.0. - { "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800, _secmon_620_patchset, _warmboot_4_patchset }, // 6.2.0. - { "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.0. - { "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.1. - { "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.0.0 - 8.0.1. - { "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.1.0. - { "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.0.0 - 9.0.1. - { "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.1.0. - { "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 10.0.0. - { "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 11.0.0. + { "20161121183008", 0, 1, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset, _warmboot_1_patchset }, // 1.0.0 (Patched relocator). + { "20170210155124", 0, 2, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset, _warmboot_2_patchset }, // 2.0.0 - 2.3.0. + { "20170519101410", 1, 3, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.0. + { "20170710161758", 2, 4, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.1 - 3.0.2. + { "20170921172629", 3, 5, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_4_patchset, _warmboot_4_patchset }, // 4.0.0 - 4.1.0. + { "20180220163747", 4, 6, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_5_patchset, _warmboot_4_patchset }, // 5.0.0 - 5.1.0. + { "20180802162753", 5, 7, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800, _secmon_6_patchset, _warmboot_4_patchset }, // 6.0.0 - 6.1.0. + { "20181107105733", 6, 8, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800, _secmon_62_patchset, _warmboot_4_patchset }, // 6.2.0. + { "20181218175730", 7, 9, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.0. + { "20190208150037", 7, 9, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.1. + { "20190314172056", 7, 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.0.0 - 8.0.1. + { "20190531152432", 8, 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.1.0 - 8.1.1. + { "20190809135709", 9, 11, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.0.0 - 9.0.1. + { "20191021113848", 10, 12, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.1.0 - 9.2.0. + { "20200303104606", 10, 13, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 10.0.0 - 10.2.0. + { "20201030110855", 10, 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 11.0.0+ { NULL } // End. }; @@ -227,11 +228,11 @@ const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, con //u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off }; // Get correct header mapping. - if (id->kb == KB_FIRMWARE_VERSION_100_200 && !strcmp(id->id, "20161121183008")) + if (id->fuses == 1) // 1.0.0. sec_map = sec_map_100; - else if (id->kb >= KB_FIRMWARE_VERSION_100_200 && id->kb <= KB_FIRMWARE_VERSION_301) + else if (id->fuses >= 2 && id->fuses <= 4) // 2.0.0 - 3.0.2. sec_map = sec_map_2xx; - else + else // 4.0.0+ sec_map = sec_map_4xx; // Copy secmon, warmboot and nx bootloader payloads. @@ -329,9 +330,10 @@ static void _warmboot_filename(char *out, u32 fuses) strcat(out, ".bin"); } -void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base) +void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base) { launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt; + u32 kb = ctxt->pkg1_id->kb; // Set warmboot address in PMC if required. if (kb <= KB_FIRMWARE_VERSION_301) @@ -340,17 +342,10 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base) if (h_cfg.t210b01) { u32 pa_id; - u32 fuses_fw = kb + 2; u32 fuses_max = 32; // Current ODM7 max. + u32 fuses_fw = ctxt->pkg1_id->fuses; u8 burnt_fuses = fuse_count_burnt(fuse_read_odm(7)); - // Add one more fuse for high versions. - //TODO: Add better checks for 10.0.0 and up in case mkey doesn't change. - if (kb > KB_FIRMWARE_VERSION_910 || !memcmp(ctxt->pkg1_id->id, "20200303104606", 8)) // 10.0.0. - fuses_fw++; - if (!memcmp(ctxt->pkg1_id->id, "20201030110855", 8)) // 11.0.0. - fuses_fw += 2; - // Save current warmboot in storage cache and check if another one is needed. if (!ctxt->warmboot) { diff --git a/bootloader/hos/pkg1.h b/bootloader/hos/pkg1.h index c1861a7..d427617 100644 --- a/bootloader/hos/pkg1.h +++ b/bootloader/hos/pkg1.h @@ -53,9 +53,10 @@ typedef struct _bl_hdr_t210b01_t typedef struct _pkg1_id_t { const char *id; - u32 kb; - u32 tsec_off; - u32 pkg11_off; + u16 kb; + u16 fuses; + u16 tsec_off; + u16 pkg11_off; u32 secmon_base; u32 warmboot_base; patch_t *secmon_patchset; @@ -80,6 +81,6 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1); void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01); void pkg1_warmboot_patch(void *hos_ctxt); -void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base); +void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base); #endif diff --git a/bootloader/hos/secmon_exo.c b/bootloader/hos/secmon_exo.c index f365fa6..3b12510 100644 --- a/bootloader/hos/secmon_exo.c +++ b/bootloader/hos/secmon_exo.c @@ -150,9 +150,8 @@ typedef struct _atm_fatal_error_ctx void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new) { - u32 exoFwNo = 0; - u32 exoFlags = 0; - u32 kb = ctxt->pkg1_id->kb; + u32 exo_fw_no = 0; + u32 exo_flags = 0; bool user_debug = false; bool cal0_blanking = false; bool cal0_allow_writes_sys = false; @@ -161,71 +160,56 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new) volatile exo_cfg_t *exo_cfg = (exo_cfg_t *)EXO_CFG_ADDR; - // Old exosphere target versioning. - switch (kb) - { - case KB_FIRMWARE_VERSION_100_200: - if (!memcmp(ctxt->pkg1_id->id, "20161121183008", 8)) - exoFwNo = 1; - else - exoFwNo = 2; - break; - case KB_FIRMWARE_VERSION_300: - exoFwNo = 3; - break; - default: - exoFwNo = kb + 1; - if (!memcmp(ctxt->pkg1_id->id, "20190314172056", 8) || (kb >= KB_FIRMWARE_VERSION_810)) - exoFwNo++; // ATM_TARGET_FW_800 and up. - if (!memcmp(ctxt->pkg1_id->id, "20200303104606", 8)) - exoFwNo++; // ATM_TARGET_FW_1000. - else if (!memcmp(ctxt->pkg1_id->id, "20201030110855", 8)) //TODO: Add better checks in case mkey doesn't change. - exoFwNo += 2; // ATM_TARGET_FW_1100. - break; - } + // Old exosphere target versioning. Use fuses for a simpler encoding. + if (ctxt->pkg1_id->fuses <= 3 || ctxt->pkg1_id->fuses >= 10) // 1.0.0 - 3.0.0, 8.1.0+. + exo_fw_no = ctxt->pkg1_id->fuses; + else + exo_fw_no = ctxt->pkg1_id->fuses - 1; // 3.0.1 - 7.0.1, 8.0.0 - 8.0.1. - // New exosphere target versioning. + if (!memcmp(ctxt->pkg1_id->id, "20190314172056", 8)) // 8.0.0 - 8.0.1. + exo_fw_no++; + + // Feed old exosphere target versioning to new. if (exo_new) { - // Feed old versioning. - switch (exoFwNo) + switch (exo_fw_no) { case 1: case 2: case 3: case 4: case 6: - exoFwNo = EXO_FW_VER(exoFwNo, 0, 0); + exo_fw_no = EXO_FW_VER(exo_fw_no, 0, 0); break; case 5: if (!ctxt->exo_ctx.fs_is_510) - exoFwNo = EXO_FW_VER(5, 0, 0); + exo_fw_no = EXO_FW_VER(5, 0, 0); else - exoFwNo = EXO_FW_VER(5, 1, 0); + exo_fw_no = EXO_FW_VER(5, 1, 0); break; case 7: - exoFwNo = EXO_FW_VER(6, 2, 0); + exo_fw_no = EXO_FW_VER(6, 2, 0); break; case 8: - exoFwNo = EXO_FW_VER(7, 0, 0); + exo_fw_no = EXO_FW_VER(7, 0, 0); break; case 9: - exoFwNo = EXO_FW_VER(8, 0, 0); + exo_fw_no = EXO_FW_VER(8, 0, 0); break; case 10: - exoFwNo = EXO_FW_VER(8, 1, 0); + exo_fw_no = EXO_FW_VER(8, 1, 0); break; case 11: - exoFwNo = EXO_FW_VER(9, 0, 0); + exo_fw_no = EXO_FW_VER(9, 0, 0); break; case 12: - exoFwNo = EXO_FW_VER(9, 1, 0); + exo_fw_no = EXO_FW_VER(9, 1, 0); break; case 13: - exoFwNo = EXO_FW_VER(10, 0, 0); + exo_fw_no = EXO_FW_VER(10, 0, 0); break; case 14: - exoFwNo = EXO_FW_VER(11, 0, 0); + exo_fw_no = EXO_FW_VER(11, 0, 0); break; } } @@ -272,41 +256,41 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new) // To avoid problems, make private debug mode always on if not semi-stock. if (!ctxt->stock || (emu_cfg.enabled && !h_cfg.emummc_force_disable)) - exoFlags |= EXO_FLAG_DBG_PRIV; + exo_flags |= EXO_FLAG_DBG_PRIV; // Enable user debug. if (user_debug) - exoFlags |= EXO_FLAG_DBG_USER; + exo_flags |= EXO_FLAG_DBG_USER; // Disable proper failure handling. if (ctxt->exo_ctx.no_user_exceptions) - exoFlags |= EXO_FLAG_NO_USER_EXC; + exo_flags |= EXO_FLAG_NO_USER_EXC; // Enable user access to PMU. if (ctxt->exo_ctx.user_pmu) - exoFlags |= EXO_FLAG_USER_PMU; + exo_flags |= EXO_FLAG_USER_PMU; // Enable prodinfo blanking. Check if exo ini value is overridden. If not, check if enabled in exo ini. if ((ctxt->exo_ctx.cal0_blank && *ctxt->exo_ctx.cal0_blank) || (!ctxt->exo_ctx.cal0_blank && cal0_blanking)) - exoFlags |= EXO_FLAG_CAL0_BLANKING; + exo_flags |= EXO_FLAG_CAL0_BLANKING; // Allow prodinfo writes. Check if exo ini value is overridden. If not, check if enabled in exo ini. if ((ctxt->exo_ctx.cal0_allow_writes_sys && *ctxt->exo_ctx.cal0_allow_writes_sys) || (!ctxt->exo_ctx.cal0_allow_writes_sys && cal0_allow_writes_sys)) - exoFlags |= EXO_FLAG_CAL0_WRITES_SYS; + exo_flags |= EXO_FLAG_CAL0_WRITES_SYS; // Set mailbox values. exo_cfg->magic = EXO_MAGIC_VAL; - exo_cfg->fwno = exoFwNo; - exo_cfg->flags[0] = exoFlags; + exo_cfg->fwno = exo_fw_no; + exo_cfg->flags[0] = exo_flags; // If warmboot is lp0fw, add in RSA modulus. volatile wb_cfg_t *wb_cfg = (wb_cfg_t *)(warmboot_base + ATM_WB_HEADER_OFF); if (wb_cfg->magic == ATM_WB_MAGIC) { - wb_cfg->fwno = exoFwNo; + wb_cfg->fwno = exo_fw_no; // Set warmboot binary rsa modulus. u8 *rsa_mod = (u8 *)malloc(512); diff --git a/nyx/nyx_gui/frontend/gui_tools.c b/nyx/nyx_gui/frontend/gui_tools.c index e038f7d..d2bd51b 100644 --- a/nyx/nyx_gui/frontend/gui_tools.c +++ b/nyx/nyx_gui/frontend/gui_tools.c @@ -1186,6 +1186,8 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) if (!pkg1_decrypt(pkg1_id, pkg1)) { strcat(txt_buf, "#FFDD00 Pkg1 decryption failed!#\n"); + if (h_cfg.t210b01) + strcat(txt_buf, "#FFDD00 Is BEK missing?#\n"); lv_label_set_text(lb_desc, txt_buf); goto out_free; } diff --git a/nyx/nyx_gui/hos/pkg1.c b/nyx/nyx_gui/hos/pkg1.c index 260106c..be231d3 100644 --- a/nyx/nyx_gui/hos/pkg1.c +++ b/nyx/nyx_gui/hos/pkg1.c @@ -42,22 +42,22 @@ static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTIO static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB }; static const pkg1_id_t _pkg1_ids[] = { - { "20161121183008", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0. - { "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0. - { "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.0. - { "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.1 - 3.0.2. - { "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000 }, // 4.0.0 - 4.1.0. - { "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000 }, // 5.0.0 - 5.1.0. - { "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800 }, // 6.0.0 - 6.1.0. - { "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800 }, // 6.2.0. - { "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.0. - { "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.1. - { "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.0.0 - 8.0.1. - { "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.1.0. - { "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.0.0 - 9.0.1. - { "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.1.0. - { "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 10.0.0. - { "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 11.0.0. + { "20161121183008", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0. + { "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0. + { "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.0. + { "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.1 - 3.0.2. + { "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000 }, // 4.0.0 - 4.1.0. + { "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000 }, // 5.0.0 - 5.1.0. + { "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800 }, // 6.0.0 - 6.1.0. + { "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800 }, // 6.2.0. + { "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.0. + { "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.1. + { "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.0.0 - 8.0.1. + { "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.1.0 - 8.1.1. + { "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.0.0 - 9.0.1. + { "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.1.0 - 9.2.0. + { "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 10.0.0 - 10.2.0. + { "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 11.0.0+ { NULL } //End. };