nyx: part: extend Fix Hybrid MBR/GPT functionality

- Allow invalid/out-of-bounds and empty partitions to be removed from GPT
- Add fix for wrong emuMMC offset because of older bugged Android Dynamic scheme
This commit is contained in:
CTCaer
2025-11-10 15:28:41 +02:00
parent b461bfc846
commit 453ec18048

View File

@@ -2616,7 +2616,7 @@ static void _create_mbox_check_files_total_size()
free(path); free(path);
} }
static lv_res_t _action_fix_mbr(lv_obj_t *btn) static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn)
{ {
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, &mbox_darken); lv_obj_set_style(dark_bg, &mbox_darken);
@@ -2639,6 +2639,8 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
bool has_mbr_attributes = false; bool has_mbr_attributes = false;
bool hybrid_mbr_changed = false; bool hybrid_mbr_changed = false;
bool gpt_partition_exists = false; bool gpt_partition_exists = false;
int gpt_oob_empty_part_no = 0;
int gpt_emummc_migrate_no = 0;
// Try to init sd card. No need for valid MBR. // Try to init sd card. No need for valid MBR.
if (!sd_mount() && !sd_get_card_initialized()) if (!sd_mount() && !sd_get_card_initialized())
@@ -2684,10 +2686,16 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
LIST_INIT(gpt_parsed); LIST_INIT(gpt_parsed);
for (u32 i = 0; i < gpt->header.num_part_ents; i++) for (u32 i = 0; i < gpt->header.num_part_ents; i++)
{ {
emmc_part_t *part = (emmc_part_t *)zalloc(sizeof(emmc_part_t)); // Check if partition is out of bounds or empty.
if ( gpt->entries[i].lba_start < gpt->header.first_use_lba ||
if (gpt->entries[i].lba_start < gpt->header.first_use_lba) gpt->entries[i].lba_start >= gpt->entries[i].lba_end ||
!gpt->entries[i].lba_end)
{
gpt_oob_empty_part_no++;
continue; continue;
}
emmc_part_t *part = (emmc_part_t *)zalloc(sizeof(emmc_part_t));
part->index = i; part->index = i;
part->lba_start = gpt->entries[i].lba_start; part->lba_start = gpt->entries[i].lba_start;
@@ -2704,6 +2712,7 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
// Set FAT and emuMMC partitions. // Set FAT and emuMMC partitions.
u32 mbr_idx = 1; u32 mbr_idx = 1;
bool found_hos_data = false; bool found_hos_data = false;
u32 emummc_mbr_part_idx[2] = {0};
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt_parsed, link) LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt_parsed, link)
{ {
// FatFS simple GPT found a fat partition, set it. // FatFS simple GPT found a fat partition, set it.
@@ -2711,7 +2720,7 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
{ {
mbr[1].partitions[0].type = sd_fs.fs_type == FS_EXFAT ? 0x7 : 0xC; mbr[1].partitions[0].type = sd_fs.fs_type == FS_EXFAT ? 0x7 : 0xC;
mbr[1].partitions[0].start_sct = part->lba_start; mbr[1].partitions[0].start_sct = part->lba_start;
mbr[1].partitions[0].size_sct = (part->lba_end - part->lba_start + 1); mbr[1].partitions[0].size_sct = part->lba_end - part->lba_start + 1;
} }
// FatFS simple GPT didn't find a fat partition as the first one. // FatFS simple GPT didn't find a fat partition as the first one.
@@ -2719,7 +2728,7 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
{ {
mbr[1].partitions[0].type = 0xC; mbr[1].partitions[0].type = 0xC;
mbr[1].partitions[0].start_sct = part->lba_start; mbr[1].partitions[0].start_sct = part->lba_start;
mbr[1].partitions[0].size_sct = (part->lba_end - part->lba_start + 1); mbr[1].partitions[0].size_sct = part->lba_end - part->lba_start + 1;
found_hos_data = true; found_hos_data = true;
} }
@@ -2728,7 +2737,11 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
{ {
mbr[1].partitions[mbr_idx].type = 0xE0; mbr[1].partitions[mbr_idx].type = 0xE0;
mbr[1].partitions[mbr_idx].start_sct = part->lba_start; mbr[1].partitions[mbr_idx].start_sct = part->lba_start;
mbr[1].partitions[mbr_idx].size_sct = (part->lba_end - part->lba_start + 1); mbr[1].partitions[mbr_idx].size_sct = part->lba_end - part->lba_start + 1;
if (!strcmp(part->name, "emummc"))
emummc_mbr_part_idx[0] = mbr_idx;
else
emummc_mbr_part_idx[1] = mbr_idx;
mbr_idx++; mbr_idx++;
} }
@@ -2751,13 +2764,21 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
(mbr[0].partitions[i].start_sct != mbr[1].partitions[i].start_sct) || (mbr[0].partitions[i].start_sct != mbr[1].partitions[i].start_sct) ||
(mbr[0].partitions[i].size_sct != mbr[1].partitions[i].size_sct)) (mbr[0].partitions[i].size_sct != mbr[1].partitions[i].size_sct))
{ {
// Check if original MBR already has an emuMMC and use it as source of truth.
if (mbr[0].partitions[i].type == 0xE0)
{
memcpy(&mbr[1].partitions[i], &mbr[0].partitions[i], sizeof(mbr_part_t));
gpt_emummc_migrate_no++;
continue;
}
else
hybrid_mbr_changed = true; hybrid_mbr_changed = true;
break; break;
} }
} }
check_changes: check_changes:
if (!hybrid_mbr_changed && !has_mbr_attributes) if (!hybrid_mbr_changed && !has_mbr_attributes && !gpt_emummc_migrate_no)
{ {
lv_label_set_text(lbl_status, "#96FF00 Warning:# The Hybrid MBR needs no change!#"); lv_label_set_text(lbl_status, "#96FF00 Warning:# The Hybrid MBR needs no change!#");
goto out; goto out;
@@ -2765,6 +2786,8 @@ check_changes:
char *txt_buf = malloc(SZ_16K); char *txt_buf = malloc(SZ_16K);
if (hybrid_mbr_changed)
{
// Current MBR info. // Current MBR info.
s_printf(txt_buf, "#00DDFF Current MBR Layout:#\n"); s_printf(txt_buf, "#00DDFF Current MBR Layout:#\n");
s_printf(txt_buf + strlen(txt_buf), s_printf(txt_buf + strlen(txt_buf),
@@ -2788,6 +2811,17 @@ check_changes:
mbr[1].partitions[1].type, mbr[1].partitions[1].start_sct, mbr[1].partitions[1].size_sct, mbr[1].partitions[1].type, mbr[1].partitions[1].start_sct, mbr[1].partitions[1].size_sct,
mbr[1].partitions[2].type, mbr[1].partitions[2].start_sct, mbr[1].partitions[2].size_sct, mbr[1].partitions[2].type, mbr[1].partitions[2].start_sct, mbr[1].partitions[2].size_sct,
mbr[1].partitions[3].type, mbr[1].partitions[3].start_sct, mbr[1].partitions[3].size_sct); mbr[1].partitions[3].type, mbr[1].partitions[3].start_sct, mbr[1].partitions[3].size_sct);
}
else if (has_mbr_attributes || gpt_emummc_migrate_no || gpt_oob_empty_part_no)
{
s_printf(txt_buf, "#00DDFF The following need to be corrected:#\n");
if (has_mbr_attributes)
s_printf(txt_buf + strlen(txt_buf), "- MBR attributes\n");
if (gpt_emummc_migrate_no)
s_printf(txt_buf + strlen(txt_buf), "- emuMMC GPT Partition address and size\n");
if (gpt_oob_empty_part_no)
s_printf(txt_buf + strlen(txt_buf), "- GPT OOB/Empty Partitions (removal)\n");
}
lv_label_set_text(lbl_status, txt_buf); lv_label_set_text(lbl_status, txt_buf);
lv_label_set_style(lbl_status, &monospace_text); lv_label_set_style(lbl_status, &monospace_text);
@@ -2809,6 +2843,8 @@ check_changes:
if (btn_wait() & BTN_POWER) if (btn_wait() & BTN_POWER)
{ {
bool has_gpt_changes = false;
sd_mount(); sd_mount();
// Write MBR. // Write MBR.
@@ -2820,10 +2856,59 @@ check_changes:
{ {
// Clear secret attributes. // Clear secret attributes.
gpt->entries[0].part_guid[7] = 0; gpt->entries[0].part_guid[7] = 0;
has_gpt_changes = gpt_partition_exists;
if (gpt_partition_exists) if (!has_gpt_changes)
{ {
// Fix CRC32s. // Only write the relevant sector if the only change is MBR attributes.
sdmmc_storage_write(&sd_storage, 2, 1, &gpt->entries[0]);
}
}
if (gpt_emummc_migrate_no)
{
u32 emu_idx = 0;
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
{
if (!memcmp(gpt->entries[i].name, (u16[]) { 'e', 'm', 'u', 'm', 'm', 'c' }, 12))
{
u32 idx = emummc_mbr_part_idx[emu_idx];
gpt->entries[i].lba_start = mbr[0].partitions[idx].start_sct;
gpt->entries[i].lba_end = mbr[0].partitions[idx].start_sct + mbr[0].partitions[idx].size_sct - 1;
gpt_emummc_migrate_no--;
emu_idx++;
has_gpt_changes = true;
}
if (i > 126 || !gpt_emummc_migrate_no)
break;
}
}
if (gpt_oob_empty_part_no)
{
u32 part_idx = 0;
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
{
if ( gpt->entries[i].lba_start < gpt->header.first_use_lba ||
gpt->entries[i].lba_start >= gpt->entries[i].lba_end ||
!gpt->entries[i].lba_end)
{
continue;
}
if (part_idx != i)
memcpy(&gpt->entries[part_idx], &gpt->entries[i], sizeof(gpt_entry_t));
part_idx++;
}
gpt->header.num_part_ents -= gpt_oob_empty_part_no;
has_gpt_changes = true;
}
if (has_gpt_changes)
{
// Fix GPT CRC32s.
u32 entries_size = sizeof(gpt_entry_t) * gpt->header.num_part_ents; u32 entries_size = sizeof(gpt_entry_t) * gpt->header.num_part_ents;
gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, entries_size); gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, entries_size);
gpt->header.crc32 = 0; // Set to 0 for calculation. gpt->header.crc32 = 0; // Set to 0 for calculation.
@@ -2843,12 +2928,6 @@ check_changes:
// Write backup GPT header. // Write backup GPT header.
sdmmc_storage_write(&sd_storage, gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); sdmmc_storage_write(&sd_storage, gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup);
} }
else
{
// Only write the relevant sector if the only change is MBR attributes.
sdmmc_storage_write(&sd_storage, 2, 1, &gpt->entries[0]);
}
}
sd_unmount(); sd_unmount();
@@ -2875,7 +2954,7 @@ lv_res_t create_window_partition_manager(bool emmc)
if (!emmc) if (!emmc)
{ {
win = nyx_create_standard_window(SYMBOL_SD" SD Partition Manager"); win = nyx_create_standard_window(SYMBOL_SD" SD Partition Manager");
lv_win_add_btn(win, NULL, SYMBOL_MODULES_ALT" Fix Hybrid MBR", _action_fix_mbr); lv_win_add_btn(win, NULL, SYMBOL_MODULES_ALT" Fix Hybrid MBR/GPT", _action_fix_mbr_gpt);
} }
else else
win = nyx_create_standard_window(SYMBOL_CHIP" eMMC Partition Manager"); win = nyx_create_standard_window(SYMBOL_CHIP" eMMC Partition Manager");