From 3b9ab66cf1f82a91cfef4ec56c11300eaa552a6b Mon Sep 17 00:00:00 2001 From: CTCaer Date: Sat, 6 Feb 2021 17:19:37 +0200 Subject: [PATCH] nyx: Add resized emuMMC creation --- bdk/utils/types.h | 3 +- nyx/nyx_gui/frontend/fe_emummc_tools.c | 373 ++++++++++++++++++++++-- nyx/nyx_gui/frontend/fe_emummc_tools.h | 2 +- nyx/nyx_gui/frontend/gui.c | 4 + nyx/nyx_gui/frontend/gui_emummc_tools.c | 42 ++- 5 files changed, 388 insertions(+), 36 deletions(-) diff --git a/bdk/utils/types.h b/bdk/utils/types.h index 5631068..8e476fd 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -93,7 +93,8 @@ typedef enum _nyx_ums_type typedef enum _nyx_sept_type { NYX_SEPT_DUMP = 0, - NYX_SEPT_CAL0 + NYX_SEPT_CAL0, + NYX_SEPT_EMUF } nyx_sept_type; typedef struct __attribute__((__packed__)) _boot_cfg_t diff --git a/nyx/nyx_gui/frontend/fe_emummc_tools.c b/nyx/nyx_gui/frontend/fe_emummc_tools.c index 3b1b389..1a09de0 100644 --- a/nyx/nyx_gui/frontend/fe_emummc_tools.c +++ b/nyx/nyx_gui/frontend/fe_emummc_tools.c @@ -23,13 +23,16 @@ #include "gui.h" #include "fe_emummc_tools.h" +#include "../hos/sept.h" #include "../config.h" #include +#include #include #include #include #include #include "../storage/nx_emmc.h" +#include "../storage/nx_emmc_bis.h" #include #include #include @@ -40,6 +43,7 @@ #define OUT_FILENAME_SZ 128 extern hekate_config h_cfg; +extern volatile boot_cfg_t *b_cfg; void load_emummc_cfg(emummc_cfg_t *emu_info) { @@ -492,9 +496,15 @@ out: sd_unmount(); } -static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, sdmmc_storage_t *storage, emmc_part_t *part) +static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, sdmmc_storage_t *storage, emmc_part_t *part, u32 resized_count) { - u32 totalSectors = part->lba_end - part->lba_start + 1; + u32 num = 0; + u32 pct = 0; + u32 prevPct = 200; + int retryCount = 0; + u32 sd_sector_off = sd_part_off + (0x2000 * active_part); + u32 lba_curr = part->lba_start; + u8 *buf = (u8 *)MIXD_BUF_ALIGNED; s_printf(gui->txt_buf, "\n\n\n"); lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf); @@ -509,24 +519,38 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); - u8 *buf = (u8 *)MIXD_BUF_ALIGNED; - u32 sd_sector_off = sd_part_off + (0x2000 * active_part); - u32 lba_curr = part->lba_start; - u32 prevPct = 200; - int retryCount = 0; - - u32 num = 0; - u32 pct = 0; - lv_obj_set_opa_scale(gui->bar, LV_OPA_COVER); lv_obj_set_opa_scale(gui->label_pct, LV_OPA_COVER); + u32 user_offset = 0; + + if (resized_count) + { + // Get USER partition info. + LIST_INIT(gpt); + nx_emmc_gpt_parse(&gpt, storage); + emmc_part_t *user_part = nx_emmc_part_find(&gpt, "USER"); + if (!user_part) + { + s_printf(gui->txt_buf, "\n#FFDD00 USER partition not found!#\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + + return 0; + } + + user_offset = user_part->lba_start; + part->lba_end = user_offset - 1; + nx_emmc_gpt_free(&gpt); + } + + u32 totalSectors = part->lba_end - part->lba_start + 1; while (totalSectors > 0) { // Check for cancellation combo. if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) { - s_printf(gui->txt_buf, "#FFDD00 The emuMMC was cancelled!#\n"); + s_printf(gui->txt_buf, "\n#FFDD00 The emuMMC was cancelled!#\n"); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); @@ -616,20 +640,319 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 100%"); manual_system_maintenance(true); - // Hide the partition. + // Set partition type to emuMMC (0xE0). if (active_part == 2) { - mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); - sdmmc_storage_read(&sd_storage, 0, 1, mbr); - mbr->partitions[part_idx].type = 0xE0; - sdmmc_storage_write(&sd_storage, 0, 1, mbr); - free(mbr); + mbr_t mbr; + sdmmc_storage_read(&sd_storage, 0, 1, &mbr); + mbr.partitions[part_idx].type = 0xE0; + sdmmc_storage_write(&sd_storage, 0, 1, &mbr); + } + + if (resized_count) + { + // Calculate USER size and set it for FatFS. + u32 user_sectors = resized_count - user_offset - 33; + disk_set_info(DRIVE_EMU, SET_SECTOR_COUNT, &user_sectors); + + // Initialize BIS for emuMMC. BIS keys should be already in place. + emmc_part_t user_part = {0}; + user_part.lba_start = user_offset; + user_part.lba_end = user_offset + user_sectors - 1; + strcpy(user_part.name, "USER"); + nx_emmc_bis_init(&user_part, true, sd_sector_off); + + s_printf(gui->txt_buf, "\nFormatting USER...\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + + // Format USER partition. + u8 *buf = malloc(0x400000); + int mkfs_error = f_mkfs("emu:", FM_FAT32 | FM_SFD | FM_PRF2, 16384, buf, 0x400000); + free(buf); + + // Mount sd card back. + sd_mount(); + + if (mkfs_error) + { + s_printf(gui->txt_buf, "#FF0000 USER format failed (%d)...#\nPlease try again...\n", mkfs_error); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + + return 0; + } + + // Flush BIS cache, deinit, clear BIS keys slots and reinstate SBK. + nx_emmc_bis_end(); + hos_bis_keys_clear(); + + s_printf(gui->txt_buf, "Writing new GPT...\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + + // Read MBR, GPT and backup GPT. + mbr_t mbr; + gpt_t gpt_main; + gpt_header_t gpt_hdr_backup; + sdmmc_storage_read(storage, 0, 1, &mbr); + sdmmc_storage_read(storage, 1, sizeof(gpt_t) >> 9, &gpt_main); + sdmmc_storage_read(storage, gpt_main.header.alt_lba, 1, &gpt_hdr_backup); + + // Find USER partition. + u32 gpt_entry_idx = 0; + for (gpt_entry_idx = 0; gpt_entry_idx < gpt_main.header.num_part_ents; gpt_entry_idx++) + if (!memcmp(gpt_main.entries[gpt_entry_idx].name, (char[]) { 'U', 0, 'S', 0, 'E', 0, 'R', 0 }, 8)) + break; + + if (gpt_entry_idx >= gpt_main.header.num_part_ents) + { + s_printf(gui->txt_buf, "#FF0000 No USER partition...#\nPlease try again...\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + + return 0; + } + + // Set new emuMMC size and USER size. + mbr.partitions[0].size_sct = resized_count; + gpt_main.entries[gpt_entry_idx].lba_end = user_offset + user_sectors - 1; + + // Update Main GPT. + gpt_main.header.alt_lba = resized_count - 1; + gpt_main.header.last_use_lba = resized_count - 34; + gpt_main.header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt_main.entries, sizeof(gpt_entry_t) * gpt_main.header.num_part_ents); + gpt_main.header.crc32 = 0; // Set to 0 for calculation. + gpt_main.header.crc32 = crc32_calc(0, (const u8 *)&gpt_main.header, gpt_main.header.size); + + // Update Backup GPT. + gpt_hdr_backup.my_lba = resized_count - 1; + gpt_hdr_backup.part_ent_lba = resized_count - 33; + gpt_hdr_backup.part_ents_crc32 = gpt_main.header.part_ents_crc32; + gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation. + gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); + + // Write main GPT. + sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_main.header.my_lba, sizeof(gpt_t) >> 9, &gpt_main); + + // Write backup GPT partition table. + sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt_main.entries); + + // Write backup GPT header. + sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); + + // Write MBR. + sdmmc_storage_write(&sd_storage, sd_sector_off, 1, &mbr); } return 1; } -void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start) +u32 kb = 0; +u8 *tsec_fw = NULL; +bool sept_error = false; + +static lv_res_t _emummc_raw_check_sept_action(lv_obj_t *btns, const char * txt) +{ + int btn_idx = lv_btnm_get_pressed(btns); + + mbox_action(btns, txt); + + if (btn_idx == 1 && !sept_error) + { + // Set boot cfg. + b_cfg->autoboot = 0; + b_cfg->autoboot_list = 0; + b_cfg->extra_cfg = EXTRA_CFG_NYX_SEPT; + b_cfg->sept = NYX_SEPT_EMUF; + + sd_mount(); + reboot_to_sept(tsec_fw, kb); + } + + return LV_RES_INV; +} + +static int _emummc_raw_check_sept(emmc_tool_gui_t *gui, u32 resized_count) +{ + if (!resized_count) + return 1; + + bool sept_needed = false; + sept_error = false; + tsec_fw = NULL; + + char *txt_buf = (char *)malloc(0x4000); + txt_buf[0] = 0; + + // Read package1. + static const u32 BOOTLOADER_SIZE = 0x40000; + static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000; + static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000; + static const u32 HOS_KEYBLOBS_OFFSET = 0x180000; + + u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET; + u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. + u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE); + + sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0); + +try_load: + sdmmc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1); + + char *build_date = malloc(32); + const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date); + + s_printf(txt_buf + strlen(txt_buf), "#00DDFF Found pkg1 ('%s')#\n", build_date); + free(build_date); + + if (!pkg1_id) + { + strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#\n"); + // Try backup bootloader. + if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET) + { + strcat(txt_buf, "Trying backup bootloader...\n"); + bootloader_offset = BOOTLOADER_BACKUP_OFFSET; + goto try_load; + } + + sept_error = true; + goto out; + } + + kb = pkg1_id->kb; + + // Skip if Mariko. + if (h_cfg.t210b01) + goto bis_derivation; + + tsec_ctxt_t tsec_ctxt; + tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off; + tsec_ctxt.pkg1 = pkg1; + tsec_ctxt.pkg11_off = pkg1_id->pkg11_off; + tsec_ctxt.secmon_base = pkg1_id->secmon_base; + + // Get keys. + hos_eks_get(); + if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run) + { + u32 key_idx = 0; + if (kb >= KB_FIRMWARE_VERSION_810) + key_idx = 1; + + if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb) + h_cfg.sept_run = true; + else + { + // Check that BCT is proper so sept can run. + u8 *bct_bldr = (u8 *)calloc(1, 512); + sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr); + u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144]; + free(bct_bldr); + if (bootloader_entrypoint > SEPT_PRI_ENTRY) + { + strcpy(txt_buf, "#FFDD00 Failed to run sept because main BCT is improper!#\n" + "#FFDD00 Run sept with proper BCT at least once to cache keys.#\n"); + sept_error = true; + goto out; + } + + // Set TSEC fw. + tsec_fw = (u8 *)tsec_ctxt.fw; + + sept_needed = true; + goto out; + } + } + +bis_derivation:; + // Read the correct keyblob. + u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1); + sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob); + + // Generate BIS keys + hos_bis_keygen(keyblob, kb, &tsec_ctxt); + + free(keyblob); + + u8 *cal0_buf = malloc(0x10000); + + // Read and decrypt CAL0 for validation of working BIS keys. + sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP); + LIST_INIT(gpt); + nx_emmc_gpt_parse(&gpt, &emmc_storage); + emmc_part_t *cal0_part = nx_emmc_part_find(&gpt, "PRODINFO"); // check if null + nx_emmc_bis_init(cal0_part, false, 0); + nx_emmc_bis_read(0, 0x40, cal0_buf); + nx_emmc_bis_end(); + nx_emmc_gpt_free(&gpt); + + nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf; + + // If successful, save BIS keys. + if (memcmp(&cal0->magic, "CAL0", 4)) + { + hos_bis_keys_clear(); + hos_eks_bis_clear(); + + strcpy(txt_buf, "#FFDD00 BIS keys validation failed!#\n"); + sept_error = true; + } + else + hos_eks_bis_save(); + free(cal0_buf); + +out: + // Check if sept is not needed. + if (!sept_needed) + free(pkg1); + + if (sept_needed || sept_error) + { + lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); + lv_obj_set_style(dark_bg, &mbox_darken); + lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES); + + static const char * mbox_btn_map[] = { "\211", "\222Launch", "\222Close", "\211", "" }; + static const char * mbox_btn_map2[] = { "\211", "\222Close", "\211", "" }; + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5); + + lv_mbox_set_text(mbox, "#C7EA46 BIS Keys Generation#"); + + lv_obj_t * lb_desc = lv_label_create(mbox, NULL); + lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK); + lv_label_set_recolor(lb_desc, true); + lv_label_set_style(lb_desc, &monospace_text); + lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4); + + if (sept_error) + { + lv_label_set_text(lb_desc, txt_buf); + lv_mbox_add_btns(mbox, mbox_btn_map2, _emummc_raw_check_sept_action); + free(pkg1); + } + else + { + lv_label_set_text(lb_desc, "Sept needs to launch in order to generate keys\nneeded for emuMMC resizing.\n" + "After that enter this menu again."); + lv_mbox_add_btns(mbox, mbox_btn_map, _emummc_raw_check_sept_action); + } + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); + + free(txt_buf); + + return 0; + } + + sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP); + + return 1; +} + +void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count) { int res = 0; u32 timer = 0; @@ -655,6 +978,14 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start) goto out; } + if (!_emummc_raw_check_sept(gui, resized_count)) + { + s_printf(gui->txt_buf, "#FFDD00 For formatting USER partition,#\n#FFDD00 BIS keys are needed!#\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + sdmmc_storage_end(&emmc_storage); + goto out; + } + int i = 0; char sdPath[OUT_FILENAME_SZ]; // Create Restore folders, if they do not exist. @@ -692,7 +1023,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start) sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1); strcat(sdPath, bootPart.name); - res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &emmc_storage, &bootPart); + res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &emmc_storage, &bootPart, 0); if (!res) { @@ -726,7 +1057,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start) lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); manual_system_maintenance(true); - res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &emmc_storage, &rawPart); + res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &emmc_storage, &rawPart, resized_count); if (!res) s_printf(txt_buf, "#FFDD00 Failed!#\n"); diff --git a/nyx/nyx_gui/frontend/fe_emummc_tools.h b/nyx/nyx_gui/frontend/fe_emummc_tools.h index 9b9213a..5564156 100644 --- a/nyx/nyx_gui/frontend/fe_emummc_tools.h +++ b/nyx/nyx_gui/frontend/fe_emummc_tools.h @@ -32,7 +32,7 @@ typedef struct _emummc_cfg_t void load_emummc_cfg(emummc_cfg_t *emu_info); void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path); void dump_emummc_file(emmc_tool_gui_t *gui); -void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start); +void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count); void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx); #endif diff --git a/nyx/nyx_gui/frontend/gui.c b/nyx/nyx_gui/frontend/gui.c index e5a9cad..f1a9d13 100644 --- a/nyx/nyx_gui/frontend/gui.c +++ b/nyx/nyx_gui/frontend/gui.c @@ -2221,6 +2221,10 @@ static void _nyx_main_menu(lv_theme_t * th) lv_task_t *task_run_cal0 = lv_task_create(sept_run_cal0, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL); lv_task_once(task_run_cal0); } + else if (type == NYX_SEPT_EMUF) + { + // TODO: Maybe automatically relaunch emuMMC creation in the future. + } } else if (nyx_str->cfg & NYX_CFG_UMS) { diff --git a/nyx/nyx_gui/frontend/gui_emummc_tools.c b/nyx/nyx_gui/frontend/gui_emummc_tools.c index 6c50354..4454268 100644 --- a/nyx/nyx_gui/frontend/gui_emummc_tools.c +++ b/nyx/nyx_gui/frontend/gui_emummc_tools.c @@ -38,6 +38,8 @@ typedef struct _mbr_ctxt_t { u32 available; u32 sector[3]; + u32 resized_cnt[3]; + int part_idx; u32 sector_start; } mbr_ctxt_t; @@ -142,7 +144,7 @@ static void _create_window_emummc() if (!mbr_ctx.part_idx) dump_emummc_file(&emmc_tool_gui_ctxt); else - dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start); + dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start, mbr_ctx.resized_cnt[mbr_ctx.part_idx - 1]); nyx_window_toggle_buttons(win, false); } @@ -239,10 +241,22 @@ static void _create_mbox_emummc_raw() // Skip Linux, GPT (Android) and SFD partitions. bool valid_part = (part_type != 0x83) && (part_type != 0xEE) && (part_type != 0xFF); - if ((part_size >= emmc_size_safe) && part_start > 0x8000 && valid_part) + // Check if at least 4GB and start above 16MB. + if ((part_size >= 0x80F000) && part_start > 0x8000 && valid_part) { - mbr_ctx.available |= (1 << (i - 1)); + mbr_ctx.available |= BIT(i - 1); mbr_ctx.sector[i - 1] = part_start; + + // Only allow up to 16GB resized emuMMC. + if (part_size <= 0x2010000) + mbr_ctx.resized_cnt[i - 1] = part_size - 0xC000; // Save sectors count without protective size and BOOT0/1. + else if (part_size >= emmc_size_safe) + mbr_ctx.resized_cnt[i - 1] = 0; + else + { + mbr_ctx.available &= ~BIT(i - 1); + mbr_ctx.sector[i - 1] = 0; + } } } @@ -260,19 +274,21 @@ static void _create_mbox_emummc_raw() "#C0C0C0 Part 0: Type: %02x, Start: %08x, Size: %08x#\n" "#%s Part 1: Type: %02x, Start: %08x, Size: %08x#\n" "#%s Part 2: Type: %02x, Start: %08x, Size: %08x#\n" - "#%s Part 3: Type: %02x, Start: %08x, Size: %08x#\n", + "#%s Part 3: Type: %02x, Start: %08x, Size: %08x#", mbr->partitions[0].type, mbr->partitions[0].start_sct, mbr->partitions[0].size_sct, - (mbr_ctx.available & 1) ? "C7EA46" : "C0C0C0", - mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct, - (mbr_ctx.available & 2) ? "C7EA46" : "C0C0C0", - mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct, - (mbr_ctx.available & 4) ? "C7EA46" : "C0C0C0", - mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct); + (mbr_ctx.available & BIT(0)) ? (mbr_ctx.resized_cnt[0] ? "FFDD00" : "C7EA46") : "C0C0C0", + mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct, + (mbr_ctx.available & BIT(1)) ? (mbr_ctx.resized_cnt[1] ? "FFDD00" : "C7EA46") : "C0C0C0", + mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct, + (mbr_ctx.available & BIT(2)) ? (mbr_ctx.resized_cnt[2] ? "FFDD00" : "C7EA46") : "C0C0C0", + mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct); + + if (mbr_ctx.resized_cnt[0] || mbr_ctx.resized_cnt[1] || mbr_ctx.resized_cnt[2]) + strcat(txt_buf, "\n\n#FFDD00 Note:# Yellow entries have USER partition resized."); if (!mbr_ctx.available) - strcat(txt_buf, - "\n#FF8000 Do you want to partition the SD card?#\n" - "#FF8000 (You will be asked on how to proceed)#"); + strcat(txt_buf, "\n#FF8000 Do you want to partition the SD card?#\n" + "#FF8000 (You will be asked on how to proceed)#"); lv_mbox_set_text(mbox, txt_buf); free(txt_buf);