2020-04-30 13:12:55 +00:00
/*
2022-01-20 11:15:04 +00:00
* Copyright ( c ) 2019 - 2022 CTCaer
2020-04-30 13:12:55 +00:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <stdlib.h>
2022-01-15 22:04:34 +00:00
# include <bdk.h>
2020-04-30 13:12:55 +00:00
# include "gui.h"
# include "gui_tools.h"
# include "gui_tools_partition_manager.h"
2020-06-14 13:45:45 +00:00
# include <libs/fatfs/diskio.h>
# include <libs/lvgl/lvgl.h>
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
# define AU_ALIGN_SECTORS 0x8000 // 16MB.
# define AU_ALIGN_BYTES (AU_ALIGN_SECTORS * SD_BLOCKSIZE)
# define SECTORS_PER_GB 0x200000
# define HOS_MIN_SIZE_MB 2048
# define ANDROID_SYSTEM_SIZE_MB 4096 // 4 GB which is > 3888 MB of the actual size.
2020-04-30 13:12:55 +00:00
extern volatile boot_cfg_t * b_cfg ;
extern volatile nyx_storage_t * nyx_str ;
typedef struct _partition_ctxt_t
{
u32 total_sct ;
2021-05-11 06:57:29 +00:00
u32 alignment ;
2020-04-30 13:12:55 +00:00
int backup_possible ;
s32 hos_size ;
u32 emu_size ;
u32 l4t_size ;
u32 and_size ;
2021-02-06 02:10:02 +00:00
bool emu_double ;
2022-01-20 12:11:36 +00:00
bool emmc_is_64gb ;
2021-02-06 02:10:02 +00:00
2021-03-17 07:08:34 +00:00
mbr_t mbr_old ;
2020-12-28 03:34:01 +00:00
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_hos ;
lv_obj_t * bar_emu ;
lv_obj_t * bar_l4t ;
lv_obj_t * bar_and ;
lv_obj_t * sep_emu ;
lv_obj_t * sep_l4t ;
lv_obj_t * sep_and ;
lv_obj_t * slider_bar_hos ;
lv_obj_t * slider_emu ;
lv_obj_t * slider_l4t ;
lv_obj_t * slider_and ;
lv_obj_t * lbl_hos ;
lv_obj_t * lbl_emu ;
lv_obj_t * lbl_l4t ;
lv_obj_t * lbl_and ;
} partition_ctxt_t ;
typedef struct _l4t_flasher_ctxt_t
{
u32 offset_sct ;
u32 image_size_sct ;
} l4t_flasher_ctxt_t ;
partition_ctxt_t part_info ;
l4t_flasher_ctxt_t l4t_flash_ctxt ;
2021-01-03 12:51:48 +00:00
lv_obj_t * btn_flash_l4t ;
lv_obj_t * btn_flash_android ;
2020-04-30 13:12:55 +00:00
static int _backup_and_restore_files ( char * path , u32 * total_files , u32 * total_size , const char * dst , const char * src , lv_obj_t * * labels )
{
FRESULT res ;
FIL fp_src ;
FIL fp_dst ;
DIR dir ;
u32 dirLength = 0 ;
static FILINFO fno ;
if ( src )
f_chdrive ( src ) ;
// Open directory.
res = f_opendir ( & dir , path ) ;
if ( res ! = FR_OK )
return res ;
if ( labels )
lv_label_set_text ( labels [ 0 ] , path ) ;
dirLength = strlen ( path ) ;
2022-05-08 02:57:59 +00:00
// Hard limit path to 1024 characters. Do not result to error.
if ( dirLength > 1024 )
goto out ;
2020-04-30 13:12:55 +00:00
for ( ; ; )
{
// Clear file path.
path [ dirLength ] = 0 ;
// Read a directory item.
res = f_readdir ( & dir , & fno ) ;
// Break on error or end of dir.
if ( res ! = FR_OK | | fno . fname [ 0 ] = = 0 )
break ;
// Set new directory or file.
memcpy ( & path [ dirLength ] , " / " , 1 ) ;
strcpy ( & path [ dirLength + 1 ] , fno . fname ) ;
if ( labels )
{
lv_label_set_text ( labels [ 1 ] , fno . fname ) ;
manual_system_maintenance ( true ) ;
}
// Copy file to destination disk.
if ( ! ( fno . fattrib & AM_DIR ) )
{
u32 file_size = fno . fsize > RAMDISK_CLUSTER_SZ ? fno . fsize : RAMDISK_CLUSTER_SZ ; // Ramdisk cluster size.
2020-06-15 12:05:47 +00:00
// Check for overflow.
if ( ( file_size + * total_size ) < * total_size )
2021-01-10 00:09:03 +00:00
{
// Set size to > 1GB, skip next folders and return.
2021-10-01 12:45:25 +00:00
* total_size = SZ_2G ;
2021-01-10 00:09:03 +00:00
res = - 1 ;
2020-06-15 12:05:47 +00:00
break ;
2021-01-10 00:09:03 +00:00
}
2020-06-15 12:05:47 +00:00
2020-04-30 13:12:55 +00:00
* total_size + = file_size ;
* total_files + = 1 ;
if ( src & & dst )
{
u32 file_size = fno . fsize ;
// Open file for writing.
f_chdrive ( dst ) ;
f_open ( & fp_dst , path , FA_CREATE_ALWAYS | FA_WRITE ) ;
f_lseek ( & fp_dst , fno . fsize ) ;
f_lseek ( & fp_dst , 0 ) ;
// Open file for reading.
f_chdrive ( src ) ;
f_open ( & fp_src , path , FA_READ ) ;
while ( file_size )
{
2021-10-01 12:45:25 +00:00
u32 chunk_size = MIN ( file_size , SZ_4M ) ; // 4MB chunks.
2020-04-30 13:12:55 +00:00
file_size - = chunk_size ;
// Copy file to buffer.
f_read ( & fp_src , ( void * ) SDXC_BUF_ALIGNED , chunk_size , NULL ) ;
manual_system_maintenance ( true ) ;
// Write file to disk.
f_write ( & fp_dst , ( void * ) SDXC_BUF_ALIGNED , chunk_size , NULL ) ;
}
f_close ( & fp_src ) ;
// Finalize copied file.
f_close ( & fp_dst ) ;
f_chdrive ( dst ) ;
f_chmod ( path , fno . fattrib , 0xFF ) ;
f_chdrive ( src ) ;
}
// If total is > 1GB exit.
2021-10-01 12:45:25 +00:00
if ( * total_size > ( RAM_DISK_SZ - SZ_16M ) ) // 0x2400000.
2021-01-10 00:09:03 +00:00
{
// Skip next folders and return.
res = - 1 ;
2020-04-30 13:12:55 +00:00
break ;
2021-01-10 00:09:03 +00:00
}
2020-04-30 13:12:55 +00:00
}
else // It's a directory.
{
if ( ! memcmp ( " System Volume Information " , fno . fname , 25 ) )
continue ;
// Create folder to destination.
if ( dst )
{
f_chdrive ( dst ) ;
f_mkdir ( path ) ;
2022-01-15 23:38:47 +00:00
f_chmod ( path , fno . fattrib , 0xFF ) ;
2020-04-30 13:12:55 +00:00
}
// Enter the directory.
res = _backup_and_restore_files ( path , total_files , total_size , dst , src , labels ) ;
if ( res ! = FR_OK )
break ;
if ( labels )
{
// Clear folder path.
path [ dirLength ] = 0 ;
lv_label_set_text ( labels [ 0 ] , path ) ;
}
}
}
2022-05-08 02:57:59 +00:00
out :
2020-04-30 13:12:55 +00:00
f_closedir ( & dir ) ;
return res ;
}
2022-05-16 10:28:38 +00:00
static void _create_gpt_partition ( gpt_t * gpt , u8 * gpt_idx , u32 * curr_part_lba , u32 size_lba , char * name , int name_size )
{
const u8 linux_part_guid [ ] = { 0xAF , 0x3D , 0xC6 , 0x0F , 0x83 , 0x84 , 0x72 , 0x47 , 0x8E , 0x79 , 0x3D , 0x69 , 0xD8 , 0x47 , 0x7D , 0xE4 } ;
u8 random_number [ 16 ] ;
// Create GPT partition.
memcpy ( gpt - > entries [ * gpt_idx ] . type_guid , linux_part_guid , 16 ) ;
// Set randomly created GUID
se_gen_prng128 ( random_number ) ;
memcpy ( gpt - > entries [ * gpt_idx ] . part_guid , random_number , 16 ) ;
// Set partition start and end.
gpt - > entries [ * gpt_idx ] . lba_start = * curr_part_lba ;
gpt - > entries [ * gpt_idx ] . lba_end = * curr_part_lba + size_lba - 1 ;
// Set name.
memcpy ( gpt - > entries [ * gpt_idx ] . name , name , name_size ) ;
// Wipe the first 1MB to sanitize it as raw-empty partition.
sdmmc_storage_write ( & sd_storage , * curr_part_lba , 0x800 , ( void * ) SDMMC_UPPER_BUFFER ) ;
// Prepare for next.
( * curr_part_lba ) + = size_lba ;
( * gpt_idx ) + + ;
}
2020-04-30 13:12:55 +00:00
static void _prepare_and_flash_mbr_gpt ( )
{
mbr_t mbr ;
2021-03-17 07:08:34 +00:00
u8 random_number [ 16 ] ;
2020-04-30 13:12:55 +00:00
// Read current MBR.
sdmmc_storage_read ( & sd_storage , 0 , 1 , & mbr ) ;
2020-12-28 03:34:01 +00:00
// Copy over metadata if they exist.
2021-03-17 07:08:34 +00:00
if ( * ( u32 * ) & part_info . mbr_old . bootstrap [ 0x80 ] )
memcpy ( & mbr . bootstrap [ 0x80 ] , & part_info . mbr_old . bootstrap [ 0x80 ] , 304 ) ;
2020-12-28 03:34:01 +00:00
2020-04-30 13:12:55 +00:00
// Clear the first 16MB.
2022-05-16 10:28:38 +00:00
memset ( ( void * ) SDMMC_UPPER_BUFFER , 0 , AU_ALIGN_BYTES ) ;
sdmmc_storage_write ( & sd_storage , 0 , AU_ALIGN_SECTORS , ( void * ) SDMMC_UPPER_BUFFER ) ;
2020-04-30 13:12:55 +00:00
u8 mbr_idx = 1 ;
se_gen_prng128 ( random_number ) ;
memcpy ( & mbr . signature , random_number , 4 ) ;
// Apply L4T Linux second to MBR if no Android.
if ( part_info . l4t_size & & ! part_info . and_size )
{
mbr . partitions [ mbr_idx ] . type = 0x83 ; // Linux system partition.
2022-05-16 10:28:38 +00:00
mbr . partitions [ mbr_idx ] . start_sct = AU_ALIGN_SECTORS + ( ( u32 ) part_info . hos_size < < 11 ) ;
2020-04-30 13:12:55 +00:00
mbr . partitions [ mbr_idx ] . size_sct = part_info . l4t_size < < 11 ;
2020-05-05 16:27:45 +00:00
sdmmc_storage_write ( & sd_storage , mbr . partitions [ mbr_idx ] . start_sct , 0x800 , ( void * ) SDMMC_UPPER_BUFFER ) ; // Clear the first 1MB.
2020-04-30 13:12:55 +00:00
mbr_idx + + ;
}
// emuMMC goes second or third. Next to L4T if no Android.
if ( part_info . emu_size )
{
mbr . partitions [ mbr_idx ] . type = 0xE0 ; // emuMMC partition.
2022-05-16 10:28:38 +00:00
mbr . partitions [ mbr_idx ] . start_sct = AU_ALIGN_SECTORS + ( ( u32 ) part_info . hos_size < < 11 ) + ( part_info . l4t_size < < 11 ) + ( part_info . and_size < < 11 ) ;
2020-04-30 13:12:55 +00:00
2021-02-06 02:10:02 +00:00
if ( ! part_info . emu_double )
mbr . partitions [ mbr_idx ] . size_sct = ( part_info . emu_size < < 11 ) - 0x800 ; // Reserve 1MB.
2020-04-30 13:12:55 +00:00
else
{
mbr . partitions [ mbr_idx ] . size_sct = part_info . emu_size < < 10 ;
mbr_idx + + ;
// 2nd emuMMC.
2021-05-11 06:57:29 +00:00
mbr . partitions [ mbr_idx ] . type = 0xE0 ; // emuMMC partition.
2020-04-30 13:12:55 +00:00
mbr . partitions [ mbr_idx ] . start_sct = mbr . partitions [ mbr_idx - 1 ] . start_sct + ( part_info . emu_size < < 10 ) ;
2021-02-06 02:10:02 +00:00
mbr . partitions [ mbr_idx ] . size_sct = ( part_info . emu_size < < 10 ) - 0x800 ; // Reserve 1MB.
2020-04-30 13:12:55 +00:00
}
mbr_idx + + ;
}
if ( part_info . and_size )
{
2021-03-17 07:08:34 +00:00
gpt_t * gpt = calloc ( 1 , sizeof ( gpt_t ) ) ;
gpt_header_t gpt_hdr_backup = { 0 } ;
2022-05-16 10:28:38 +00:00
// Set GPT protective partition in MBR.
mbr . partitions [ mbr_idx ] . type = 0xEE ;
2020-04-30 13:12:55 +00:00
mbr . partitions [ mbr_idx ] . start_sct = 1 ;
2020-06-14 10:06:43 +00:00
mbr . partitions [ mbr_idx ] . size_sct = sd_storage . sec_cnt - 1 ;
2020-04-30 13:12:55 +00:00
mbr_idx + + ;
// Set GPT header.
2021-03-17 07:08:34 +00:00
memcpy ( & gpt - > header . signature , " EFI PART " , 8 ) ;
gpt - > header . revision = 0x10000 ;
gpt - > header . size = 92 ;
gpt - > header . my_lba = 1 ;
gpt - > header . alt_lba = sd_storage . sec_cnt - 1 ;
gpt - > header . first_use_lba = ( sizeof ( mbr_t ) + sizeof ( gpt_t ) ) > > 9 ;
gpt - > header . last_use_lba = sd_storage . sec_cnt - 0x800 - 1 ; // sd_storage.sec_cnt - 33 is start of backup gpt partition entries.
2020-04-30 13:12:55 +00:00
se_gen_prng128 ( random_number ) ;
2021-03-17 07:08:34 +00:00
memcpy ( gpt - > header . disk_guid , random_number , 10 ) ;
memcpy ( gpt - > header . disk_guid + 10 , " NYXGPT " , 6 ) ;
gpt - > header . part_ent_lba = 2 ;
gpt - > header . part_ent_size = 128 ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Set FAT GPT partition manually.
const u8 basic_part_guid [ ] = { 0xA2 , 0xA0 , 0xD0 , 0xEB , 0xE5 , 0xB9 , 0x33 , 0x44 , 0x87 , 0xC0 , 0x68 , 0xB6 , 0xB7 , 0x26 , 0x99 , 0xC7 } ;
2021-03-17 07:08:34 +00:00
memcpy ( gpt - > entries [ 0 ] . type_guid , basic_part_guid , 16 ) ;
2020-04-30 13:12:55 +00:00
se_gen_prng128 ( random_number ) ;
2021-03-17 07:08:34 +00:00
memcpy ( gpt - > entries [ 0 ] . part_guid , random_number , 16 ) ;
2020-04-30 13:12:55 +00:00
// Clear non-standard Windows MBR attributes. bit4: Read only, bit5: Shadow copy, bit6: Hidden, bit7: No drive letter.
2021-03-17 07:08:34 +00:00
gpt - > entries [ 0 ] . part_guid [ 7 ] = 0 ;
2020-04-30 13:12:55 +00:00
2021-03-17 07:08:34 +00:00
gpt - > entries [ 0 ] . lba_start = mbr . partitions [ 0 ] . start_sct ;
gpt - > entries [ 0 ] . lba_end = mbr . partitions [ 0 ] . start_sct + mbr . partitions [ 0 ] . size_sct - 1 ;
memcpy ( gpt - > entries [ 0 ] . name , ( char [ ] ) { ' h ' , 0 , ' o ' , 0 , ' s ' , 0 , ' _ ' , 0 , ' d ' , 0 , ' a ' , 0 , ' t ' , 0 , ' a ' , 0 } , 16 ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Set the rest of GPT partitions.
u8 gpt_idx = 1 ;
u32 curr_part_lba = AU_ALIGN_SECTORS + ( ( u32 ) part_info . hos_size < < 11 ) ;
// L4T partition.
2020-04-30 13:12:55 +00:00
if ( part_info . l4t_size )
2022-05-16 10:28:38 +00:00
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , part_info . l4t_size < < 11 , ( char [ ] ) { ' l ' , 0 , ' 4 ' , 0 , ' t ' , 0 } , 6 ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Android Vendor partition. 1GB
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x200000 , ( char [ ] ) { ' v ' , 0 , ' e ' , 0 , ' n ' , 0 , ' d ' , 0 , ' o ' , 0 , ' r ' , 0 } , 12 ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Android System partition. 2GB.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x400000 , ( char [ ] ) { ' A ' , 0 , ' P ' , 0 , ' P ' , 0 } , 6 ) ;
// Android Linux Kernel partition. 32MB.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x10000 , ( char [ ] ) { ' L ' , 0 , ' N ' , 0 , ' X ' , 0 } , 6 ) ;
// Android Recovery partition. 64MB.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x20000 , ( char [ ] ) { ' S ' , 0 , ' O ' , 0 , ' S ' , 0 } , 6 ) ;
// Android Device Tree Reference partition. 1MB.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x800 , ( char [ ] ) { ' D ' , 0 , ' T ' , 0 , ' B ' , 0 } , 6 ) ;
// Android Encryption partition. 16MB.
// Note: 16MB size is for aligning UDA. If any other tiny partition must be added, it should split the MDA one.
sdmmc_storage_write ( & sd_storage , curr_part_lba , 0x8000 , ( void * ) SDMMC_UPPER_BUFFER ) ; // Clear the whole of it.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x8000 , ( char [ ] ) { ' M ' , 0 , ' D ' , 0 , ' A ' , 0 } , 6 ) ;
// Android Cache partition. 700MB.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x15E000 , ( char [ ] ) { ' C ' , 0 , ' A ' , 0 , ' C ' , 0 } , 6 ) ;
// Android Misc partition. 3MB.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , 0x1800 , ( char [ ] ) { ' M ' , 0 , ' S ' , 0 , ' C ' , 0 } , 6 ) ;
2021-01-03 12:52:13 +00:00
2020-04-30 13:12:55 +00:00
// Android Userdata partition.
2022-05-16 10:28:38 +00:00
u32 uda_size = ( part_info . and_size < < 11 ) - 0x798000 ; // Subtract the other partitions (3888MB).
2020-04-30 13:12:55 +00:00
if ( ! part_info . emu_size )
2022-05-16 10:28:38 +00:00
uda_size - = 0x800 ; // Reserve 1MB.
_create_gpt_partition ( gpt , & gpt_idx , & curr_part_lba , uda_size , ( char [ ] ) { ' U ' , 0 , ' D ' , 0 , ' A ' , 0 } , 6 ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Handle emuMMC partitions manually.
2020-04-30 13:12:55 +00:00
if ( part_info . emu_size )
{
2022-05-16 10:28:38 +00:00
// Set 1st emuMMC.
2020-04-30 13:12:55 +00:00
u8 emu_part_guid [ ] = { 0x00 , 0x7E , 0xCA , 0x11 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , ' e ' , ' m ' , ' u ' , ' M ' , ' M ' , ' C ' } ;
2021-03-17 07:08:34 +00:00
memcpy ( gpt - > entries [ gpt_idx ] . type_guid , emu_part_guid , 16 ) ;
2020-04-30 13:12:55 +00:00
se_gen_prng128 ( random_number ) ;
2021-03-17 07:08:34 +00:00
memcpy ( gpt - > entries [ gpt_idx ] . part_guid , random_number , 16 ) ;
gpt - > entries [ gpt_idx ] . lba_start = curr_part_lba ;
2021-02-06 02:10:02 +00:00
if ( ! part_info . emu_double )
2021-03-17 07:08:34 +00:00
gpt - > entries [ gpt_idx ] . lba_end = curr_part_lba + ( part_info . emu_size < < 11 ) - 0x800 - 1 ; // Reserve 1MB.
2020-04-30 13:12:55 +00:00
else
2021-03-17 07:08:34 +00:00
gpt - > entries [ gpt_idx ] . lba_end = curr_part_lba + ( part_info . emu_size < < 10 ) - 1 ;
memcpy ( gpt - > entries [ gpt_idx ] . name , ( char [ ] ) { ' e ' , 0 , ' m ' , 0 , ' u ' , 0 , ' m ' , 0 , ' m ' , 0 , ' c ' , 0 } , 12 ) ;
2020-04-30 13:12:55 +00:00
gpt_idx + + ;
2022-05-16 10:28:38 +00:00
// Set 2nd emuMMC.
2021-02-06 02:10:02 +00:00
if ( part_info . emu_double )
2020-04-30 13:12:55 +00:00
{
curr_part_lba + = ( part_info . emu_size < < 10 ) ;
2021-03-17 07:08:34 +00:00
memcpy ( gpt - > entries [ gpt_idx ] . type_guid , emu_part_guid , 16 ) ;
2020-04-30 13:12:55 +00:00
se_gen_prng128 ( random_number ) ;
2021-03-17 07:08:34 +00:00
memcpy ( gpt - > entries [ gpt_idx ] . part_guid , random_number , 16 ) ;
gpt - > entries [ gpt_idx ] . lba_start = curr_part_lba ;
gpt - > entries [ gpt_idx ] . lba_end = curr_part_lba + ( part_info . emu_size < < 10 ) - 0x800 - 1 ; // Reserve 1MB.
memcpy ( gpt - > entries [ gpt_idx ] . name , ( char [ ] ) { ' e ' , 0 , ' m ' , 0 , ' u ' , 0 , ' m ' , 0 , ' m ' , 0 , ' c ' , 0 , ' 2 ' , 0 } , 14 ) ;
2020-04-30 13:12:55 +00:00
gpt_idx + + ;
}
}
// Set final GPT header parameters.
2022-05-08 02:59:57 +00:00
gpt - > header . num_part_ents = gpt_idx ;
gpt - > header . part_ents_crc32 = crc32_calc ( 0 , ( const u8 * ) gpt - > entries , sizeof ( gpt_entry_t ) * gpt - > header . num_part_ents ) ;
2021-03-17 07:08:34 +00:00
gpt - > header . crc32 = 0 ; // Set to 0 for calculation.
gpt - > header . crc32 = crc32_calc ( 0 , ( const u8 * ) & gpt - > header , gpt - > header . size ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Set final backup GPT header parameters.
2021-03-17 07:08:34 +00:00
memcpy ( & gpt_hdr_backup , & gpt - > header , sizeof ( gpt_header_t ) ) ;
2020-06-14 10:06:43 +00:00
gpt_hdr_backup . my_lba = sd_storage . sec_cnt - 1 ;
2020-04-30 13:12:55 +00:00
gpt_hdr_backup . alt_lba = 1 ;
2020-06-14 10:06:43 +00:00
gpt_hdr_backup . part_ent_lba = sd_storage . sec_cnt - 33 ;
2020-04-30 13:12:55 +00:00
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 ) ;
2021-05-11 06:57:29 +00:00
// Write main GPT.
2021-03-17 07:08:34 +00:00
sdmmc_storage_write ( & sd_storage , gpt - > header . my_lba , sizeof ( gpt_t ) > > 9 , gpt ) ;
2020-04-30 13:12:55 +00:00
// Write backup GPT partition table.
2021-03-17 07:08:34 +00:00
sdmmc_storage_write ( & sd_storage , gpt_hdr_backup . part_ent_lba , ( ( sizeof ( gpt_entry_t ) * 128 ) > > 9 ) , gpt - > entries ) ;
2020-04-30 13:12:55 +00:00
// Write backup GPT header.
sdmmc_storage_write ( & sd_storage , gpt_hdr_backup . my_lba , 1 , & gpt_hdr_backup ) ;
2021-03-17 07:08:34 +00:00
free ( gpt ) ;
2020-04-30 13:12:55 +00:00
}
// Write MBR.
sdmmc_storage_write ( & sd_storage , 0 , 1 , & mbr ) ;
}
static lv_res_t _action_part_manager_ums_sd ( lv_obj_t * btn )
{
action_ums_sd ( btn ) ;
2021-09-26 09:16:04 +00:00
// Close and reopen partition manager.
lv_action_t close_btn_action = lv_btn_get_action ( close_btn , LV_BTN_ACTION_CLICK ) ;
close_btn_action ( close_btn ) ;
lv_obj_del ( ums_mbox ) ;
create_window_partition_manager ( NULL ) ;
2020-04-30 13:12:55 +00:00
2021-09-26 09:16:04 +00:00
return LV_RES_INV ;
2020-04-30 13:12:55 +00:00
}
static lv_res_t _action_delete_linux_installer_files ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
// Delete parent mbox.
mbox_action ( btns , txt ) ;
// Flash Linux.
if ( ! btn_idx )
{
char path [ 128 ] ;
sd_mount ( ) ;
strcpy ( path , " switchroot/install/l4t. " ) ;
// Delete all l4t.xx files.
u32 idx = 0 ;
while ( true )
{
if ( idx < 10 )
{
path [ 23 ] = ' 0 ' ;
itoa ( idx , & path [ 23 + 1 ] , 10 ) ;
}
else
itoa ( idx , & path [ 23 ] , 10 ) ;
if ( ! f_stat ( path , NULL ) )
{
f_unlink ( path ) ;
}
else
break ;
idx + + ;
}
2020-06-13 15:32:40 +00:00
sd_unmount ( ) ;
2020-04-30 13:12:55 +00:00
}
return LV_RES_INV ;
}
static lv_res_t _action_flash_linux_data ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
// Delete parent mbox.
mbox_action ( btns , txt ) ;
bool succeeded = false ;
2022-01-28 23:23:40 +00:00
if ( btn_idx )
return LV_RES_INV ;
2020-04-30 13:12:55 +00:00
// Flash Linux.
2022-01-28 23:23:40 +00:00
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 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
static const char * mbox_btn_map [ ] = { " \211 " , " \222 OK " , " \211 " , " " } ;
static const char * mbox_btn_map2 [ ] = { " \223 Delete Installation Files " , " \221 OK " , " " } ;
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 / 10 * 5 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_mbox_set_text ( mbox , " #FF8000 Linux Flasher# " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_obj_t * lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
lv_label_set_text ( lbl_status , " #C7EA46 Status:# Flashing Linux... " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
// Create container to keep content inside.
lv_obj_t * h1 = lv_cont_create ( mbox , NULL ) ;
lv_cont_set_fit ( h1 , true , true ) ;
lv_cont_set_style ( h1 , & lv_style_transp_tight ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_obj_t * bar = lv_bar_create ( h1 , NULL ) ;
lv_obj_set_size ( bar , LV_DPI * 30 / 10 , LV_DPI / 5 ) ;
lv_bar_set_range ( bar , 0 , 100 ) ;
lv_bar_set_value ( bar , 0 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_obj_t * label_pct = lv_label_create ( h1 , NULL ) ;
lv_label_set_recolor ( label_pct , true ) ;
lv_label_set_text ( label_pct , " " SYMBOL_DOT " 0% " ) ;
lv_label_set_style ( label_pct , lv_theme_get_current ( ) - > label . prim ) ;
lv_obj_align ( label_pct , bar , LV_ALIGN_OUT_RIGHT_MID , LV_DPI / 20 , 0 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
sd_mount ( ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
int res = 0 ;
char * path = malloc ( 1024 ) ;
char * txt_buf = malloc ( SZ_4K ) ;
strcpy ( path , " switchroot/install/l4t.00 " ) ;
u32 path_len = strlen ( path ) - 2 ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
FIL fp ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
res = f_open ( & fp , path , FA_READ ) ;
if ( res )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Failed to open 1st part! " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
goto exit ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
u64 fileSize = ( u64 ) f_size ( & fp ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
u32 num = 0 ;
u32 pct = 0 ;
u32 lba_curr = 0 ;
u32 bytesWritten = 0 ;
u32 currPartIdx = 0 ;
u32 prevPct = 200 ;
int retryCount = 0 ;
u32 total_size_sct = l4t_flash_ctxt . image_size_sct ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
u8 * buf = ( u8 * ) MIXD_BUF_ALIGNED ;
DWORD * clmt = f_expand_cltbl ( & fp , SZ_4M , 0 ) ;
2022-05-16 10:28:38 +00:00
// Start flashing L4T.
2022-01-28 23:23:40 +00:00
while ( total_size_sct > 0 )
{
// If we have more than one part, check the size for the split parts and make sure that the bytes written is not more than that.
if ( bytesWritten > = fileSize )
{
// If we have more bytes written then close the file pointer and increase the part index we are using
f_close ( & fp ) ;
free ( clmt ) ;
memset ( & fp , 0 , sizeof ( fp ) ) ;
currPartIdx + + ;
if ( currPartIdx < 10 )
{
path [ path_len ] = ' 0 ' ;
itoa ( currPartIdx , & path [ path_len + 1 ] , 10 ) ;
}
else
itoa ( currPartIdx , & path [ path_len ] , 10 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
// Try to open the next file part
res = f_open ( & fp , path , FA_READ ) ;
2020-04-30 13:12:55 +00:00
if ( res )
{
2022-01-28 23:23:40 +00:00
s_printf ( txt_buf , " #FFDD00 Error:# Failed to open part %d# " , currPartIdx ) ;
lv_label_set_text ( lbl_status , txt_buf ) ;
2020-04-30 13:12:55 +00:00
manual_system_maintenance ( true ) ;
goto exit ;
}
2022-01-28 23:23:40 +00:00
fileSize = ( u64 ) f_size ( & fp ) ;
bytesWritten = 0 ;
clmt = f_expand_cltbl ( & fp , SZ_4M , 0 ) ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
retryCount = 0 ;
num = MIN ( total_size_sct , 8192 ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Read next data block from SD.
2022-01-28 23:23:40 +00:00
res = f_read_fast ( & fp , buf , num < < 9 ) ;
manual_system_maintenance ( false ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
if ( res )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Reading from SD! " ) ;
manual_system_maintenance ( true ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
f_close ( & fp ) ;
free ( clmt ) ;
goto exit ;
}
2022-05-16 10:28:38 +00:00
// Write data block to L4T partition.
2022-01-28 23:23:40 +00:00
res = ! sdmmc_storage_write ( & sd_storage , lba_curr + l4t_flash_ctxt . offset_sct , num , buf ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
manual_system_maintenance ( false ) ;
2022-05-16 10:28:38 +00:00
// If failed, retry 3 more times.
2022-01-28 23:23:40 +00:00
while ( res )
{
msleep ( 150 ) ;
manual_system_maintenance ( true ) ;
if ( retryCount > = 3 )
2020-04-30 13:12:55 +00:00
{
2022-01-28 23:23:40 +00:00
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Writing to SD! " ) ;
2020-04-30 13:12:55 +00:00
manual_system_maintenance ( true ) ;
2022-01-28 23:23:40 +00:00
f_close ( & fp ) ;
free ( clmt ) ;
goto exit ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
res = ! sdmmc_storage_write ( & sd_storage , lba_curr + l4t_flash_ctxt . offset_sct , num , buf ) ;
manual_system_maintenance ( false ) ;
}
2022-05-16 10:28:38 +00:00
// Update completion percentage.
2022-01-28 23:23:40 +00:00
pct = ( u64 ) ( ( u64 ) lba_curr * 100u ) / ( u64 ) l4t_flash_ctxt . image_size_sct ;
if ( pct ! = prevPct )
{
lv_bar_set_value ( bar , pct ) ;
s_printf ( txt_buf , " #DDDDDD " SYMBOL_DOT " # %d%% " , pct ) ;
lv_label_set_text ( label_pct , txt_buf ) ;
manual_system_maintenance ( true ) ;
prevPct = pct ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
lba_curr + = num ;
total_size_sct - = num ;
bytesWritten + = num * EMMC_BLOCKSIZE ;
}
lv_bar_set_value ( bar , 100 ) ;
lv_label_set_text ( label_pct , " " SYMBOL_DOT " 100% " ) ;
manual_system_maintenance ( true ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
// Restore operation ended successfully.
f_close ( & fp ) ;
free ( clmt ) ;
succeeded = true ;
2020-04-30 13:12:55 +00:00
exit :
2022-01-28 23:23:40 +00:00
free ( path ) ;
free ( txt_buf ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
if ( ! succeeded )
lv_mbox_add_btns ( mbox , mbox_btn_map , mbox_action ) ;
else
lv_mbox_add_btns ( mbox , mbox_btn_map2 , _action_delete_linux_installer_files ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
sd_unmount ( ) ;
2020-04-30 13:12:55 +00:00
return LV_RES_INV ;
}
2021-01-03 12:51:48 +00:00
static u32 _get_available_l4t_partition ( )
2020-04-30 13:12:55 +00:00
{
mbr_t mbr = { 0 } ;
2021-03-17 07:08:34 +00:00
gpt_t * gpt = calloc ( 1 , sizeof ( gpt_t ) ) ;
2020-04-30 13:12:55 +00:00
memset ( & l4t_flash_ctxt , 0 , sizeof ( l4t_flasher_ctxt_t ) ) ;
// Read MBR.
sdmmc_storage_read ( & sd_storage , 0 , 1 , & mbr ) ;
// Read main GPT.
2021-03-17 07:08:34 +00:00
sdmmc_storage_read ( & sd_storage , 1 , sizeof ( gpt_t ) > > 9 , gpt ) ;
2020-04-30 13:12:55 +00:00
// Search for a suitable partition.
u32 size_sct = 0 ;
2021-03-17 07:14:50 +00:00
if ( ! memcmp ( & gpt - > header . signature , " EFI PART " , 8 ) | | gpt - > header . num_part_ents > 128 )
2020-04-30 13:12:55 +00:00
{
2021-03-17 07:08:34 +00:00
for ( u32 i = 0 ; i < gpt - > header . num_part_ents ; i + + )
2020-04-30 13:12:55 +00:00
{
2021-03-17 07:08:34 +00:00
if ( ! memcmp ( gpt - > entries [ i ] . name , ( char [ ] ) { ' l ' , 0 , ' 4 ' , 0 , ' t ' , 0 } , 6 ) )
2020-04-30 13:12:55 +00:00
{
2021-03-17 07:08:34 +00:00
l4t_flash_ctxt . offset_sct = gpt - > entries [ i ] . lba_start ;
size_sct = ( gpt - > entries [ i ] . lba_end + 1 ) - gpt - > entries [ i ] . lba_start ;
2020-04-30 13:12:55 +00:00
break ;
}
if ( i > 126 )
break ;
}
}
else
{
for ( u32 i = 1 ; i < 4 ; i + + )
{
if ( mbr . partitions [ i ] . type = = 0x83 )
{
l4t_flash_ctxt . offset_sct = mbr . partitions [ i ] . start_sct ;
size_sct = mbr . partitions [ i ] . size_sct ;
break ;
}
}
}
2021-03-17 07:08:34 +00:00
free ( gpt ) ;
2021-01-03 12:51:48 +00:00
return size_sct ;
}
static bool _get_available_android_partition ( )
{
2021-03-17 07:08:34 +00:00
gpt_t * gpt = calloc ( 1 , sizeof ( gpt_t ) ) ;
2021-01-03 12:51:48 +00:00
// Read main GPT.
2021-03-17 07:08:34 +00:00
sdmmc_storage_read ( & sd_storage , 1 , sizeof ( gpt_t ) > > 9 , gpt ) ;
2021-01-03 12:51:48 +00:00
// Check if GPT.
2021-03-17 07:14:50 +00:00
if ( memcmp ( & gpt - > header . signature , " EFI PART " , 8 ) | | gpt - > header . num_part_ents > 128 )
2021-03-17 07:08:34 +00:00
goto out ;
2021-01-03 12:51:48 +00:00
// Find kernel partition.
2021-03-17 07:08:34 +00:00
for ( u32 i = 0 ; i < gpt - > header . num_part_ents ; i + + )
2021-01-03 12:51:48 +00:00
{
2021-03-17 07:08:34 +00:00
if ( gpt - > entries [ i ] . lba_start & & ! memcmp ( gpt - > entries [ i ] . name , ( char [ ] ) { ' L ' , 0 , ' N ' , 0 , ' X ' , 0 } , 6 ) )
{
free ( gpt ) ;
2021-01-03 12:51:48 +00:00
return true ;
2021-03-17 07:08:34 +00:00
}
2021-01-03 12:51:48 +00:00
if ( i > 126 )
break ;
}
2021-03-17 07:08:34 +00:00
out :
free ( gpt ) ;
2021-01-03 12:51:48 +00:00
return false ;
}
static lv_res_t _action_check_flash_linux ( lv_obj_t * btn )
{
FILINFO fno ;
char path [ 128 ] ;
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 " , " \222 OK " , " \211 " , " " } ;
static const char * mbox_btn_map2 [ ] = { " \222 Continue " , " \222 Cancel " , " " } ;
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 * 6 ) ;
lv_mbox_set_text ( mbox , " #FF8000 Linux Flasher# " ) ;
lv_obj_t * lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
lv_label_set_text ( lbl_status , " #C7EA46 Status:# Searching for files and partitions... " ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
manual_system_maintenance ( true ) ;
sd_mount ( ) ;
2022-05-16 10:28:38 +00:00
// Check if L4T image exists.
2021-01-03 12:51:48 +00:00
strcpy ( path , " switchroot/install/l4t.00 " ) ;
if ( f_stat ( path , NULL ) )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Installation files not found! " ) ;
goto error ;
}
2022-05-16 10:28:38 +00:00
// Find an applicable partition for L4T.
2021-01-03 12:51:48 +00:00
u32 size_sct = _get_available_l4t_partition ( ) ;
if ( ! l4t_flash_ctxt . offset_sct | | ! size_sct | | size_sct < 0x800000 )
2020-04-30 13:12:55 +00:00
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# No partition found! " ) ;
goto error ;
}
u32 idx = 0 ;
path [ 23 ] = 0 ;
2022-05-16 10:28:38 +00:00
// Validate L4T images and consolidate their info.
2020-04-30 13:12:55 +00:00
while ( true )
{
if ( idx < 10 )
{
path [ 23 ] = ' 0 ' ;
itoa ( idx , & path [ 23 + 1 ] , 10 ) ;
}
else
itoa ( idx , & path [ 23 ] , 10 ) ;
// Check for alignment.
2022-01-28 23:23:40 +00:00
if ( f_stat ( path , & fno ) )
break ;
if ( ( u64 ) fno . fsize % SZ_4M )
2020-04-30 13:12:55 +00:00
{
2022-01-28 23:23:40 +00:00
// Check if last part.
idx + + ;
if ( idx < 10 )
2020-04-30 13:12:55 +00:00
{
2022-01-28 23:23:40 +00:00
path [ 23 ] = ' 0 ' ;
itoa ( idx , & path [ 23 + 1 ] , 10 ) ;
}
else
itoa ( idx , & path [ 23 ] , 10 ) ;
2020-09-02 10:11:03 +00:00
2022-01-28 23:23:40 +00:00
// If not the last part, unaligned size is not permitted.
if ( ! f_stat ( path , NULL ) ) // NULL: Don't override current part fs info.
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# The image is not aligned to 4 MiB! " ) ;
goto error ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
// Last part. Align size to LBA (512 bytes).
fno . fsize = ALIGN ( ( u64 ) fno . fsize , 512 ) ;
idx - - ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
l4t_flash_ctxt . image_size_sct + = ( u64 ) fno . fsize > > 9 ;
2020-04-30 13:12:55 +00:00
idx + + ;
}
2022-05-16 10:28:38 +00:00
// Check if image size is bigger than the partition available.
2020-04-30 13:12:55 +00:00
if ( l4t_flash_ctxt . image_size_sct > size_sct )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# The image is bigger than the partition! " ) ;
goto error ;
}
2021-10-01 12:45:25 +00:00
char * txt_buf = malloc ( SZ_4K ) ;
2020-04-30 13:12:55 +00:00
s_printf ( txt_buf ,
" #C7EA46 Status:# Found installation files and partition. \n "
" #00DDFF Offset:# %08x, #00DDFF Size:# %X, #00DDFF Image size:# %d MiB \n "
" \n Do you want to continue? " , l4t_flash_ctxt . offset_sct , size_sct , l4t_flash_ctxt . image_size_sct > > 11 ) ;
lv_label_set_text ( lbl_status , txt_buf ) ;
free ( txt_buf ) ;
lv_mbox_add_btns ( mbox , mbox_btn_map2 , _action_flash_linux_data ) ;
goto exit ;
error :
lv_mbox_add_btns ( mbox , mbox_btn_map , mbox_action ) ;
exit :
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
2020-06-13 15:32:40 +00:00
sd_unmount ( ) ;
2020-04-30 13:12:55 +00:00
return LV_RES_OK ;
}
static lv_res_t _action_reboot_twrp ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
// Delete parent mbox.
mbox_action ( btns , txt ) ;
if ( ! btn_idx )
{
2022-05-16 10:28:38 +00:00
// Set custom reboot type to Android Recovery.
2020-04-30 13:12:55 +00:00
PMC ( APBDEV_PMC_SCRATCH0 ) | = PMC_SCRATCH0_MODE_RECOVERY ;
2022-05-16 10:28:38 +00:00
// Enable hekate boot configuration.
2020-04-30 13:12:55 +00:00
b_cfg - > boot_cfg = BOOT_CFG_FROM_ID | BOOT_CFG_AUTOBOOT_EN ;
2022-05-16 10:28:38 +00:00
// Set id to Android.
2020-04-30 13:12:55 +00:00
strcpy ( ( char * ) b_cfg - > id , " SWANDR " ) ;
void ( * main_ptr ) ( ) = ( void * ) nyx_str - > hekate ;
2022-05-16 10:28:38 +00:00
// Deinit hardware.
2020-06-13 15:32:40 +00:00
sd_end ( ) ;
2020-07-17 15:08:27 +00:00
hw_reinit_workaround ( false , 0 ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Chainload to hekate main.
2020-04-30 13:12:55 +00:00
( * main_ptr ) ( ) ;
}
return LV_RES_INV ;
}
static lv_res_t _action_flash_android_data ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
2022-05-16 10:28:38 +00:00
bool boot_twrp = false ;
2020-04-30 13:12:55 +00:00
// Delete parent mbox.
mbox_action ( btns , txt ) ;
2022-01-28 23:23:40 +00:00
if ( btn_idx )
return LV_RES_INV ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
// Flash Android components.
char path [ 128 ] ;
gpt_t * gpt = calloc ( 1 , sizeof ( gpt_t ) ) ;
char * txt_buf = malloc ( SZ_4K ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
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 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
static const char * mbox_btn_map [ ] = { " \211 " , " \222 OK " , " \211 " , " " } ;
static const char * mbox_btn_map2 [ ] = { " \222 Continue " , " \222 No " , " " } ;
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 * 6 ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_mbox_set_text ( mbox , " #FF8000 Android Flasher# " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_obj_t * lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
lv_label_set_text ( lbl_status , " #C7EA46 Status:# Searching for files and partitions... " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
manual_system_maintenance ( true ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
sd_mount ( ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
// Read main GPT.
sdmmc_storage_read ( & sd_storage , 1 , sizeof ( gpt_t ) > > 9 , gpt ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Validate GPT header.
2022-01-28 23:23:40 +00:00
if ( memcmp ( & gpt - > header . signature , " EFI PART " , 8 ) | | gpt - > header . num_part_ents > 128 )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# No Android GPT was found! " ) ;
goto error ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
u32 offset_sct = 0 ;
u32 size_sct = 0 ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Check if Kernel image should be flashed.
2022-01-28 23:23:40 +00:00
strcpy ( path , " switchroot/install/boot.img " ) ;
if ( f_stat ( path , NULL ) )
{
s_printf ( txt_buf , " #FF8000 Warning:# Kernel image not found! \n " ) ;
goto boot_img_not_found ;
}
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Find Kernel partition.
2022-01-28 23:23:40 +00:00
for ( u32 i = 0 ; i < gpt - > header . num_part_ents ; i + + )
{
if ( ! memcmp ( gpt - > entries [ i ] . name , ( char [ ] ) { ' L ' , 0 , ' N ' , 0 , ' X ' , 0 } , 6 ) )
{
offset_sct = gpt - > entries [ i ] . lba_start ;
size_sct = ( gpt - > entries [ i ] . lba_end + 1 ) - gpt - > entries [ i ] . lba_start ;
break ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
if ( i > 126 )
break ;
}
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Flash Kernel.
2022-01-28 23:23:40 +00:00
if ( offset_sct & & size_sct )
{
u32 file_size = 0 ;
u8 * buf = sd_file_read ( path , & file_size ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
if ( file_size % 0x200 )
{
file_size = ALIGN ( file_size , 0x200 ) ;
u8 * buf_tmp = calloc ( file_size , 1 ) ;
memcpy ( buf_tmp , buf , file_size ) ;
free ( buf ) ;
buf = buf_tmp ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
if ( ( file_size > > 9 ) > size_sct )
s_printf ( txt_buf , " #FF8000 Warning:# Kernel image too big! \n " ) ;
else
2020-04-30 13:12:55 +00:00
{
2022-01-28 23:23:40 +00:00
sdmmc_storage_write ( & sd_storage , offset_sct , file_size > > 9 , buf ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
s_printf ( txt_buf , " #C7EA46 Success:# Kernel image flashed! \n " ) ;
f_unlink ( path ) ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
free ( buf ) ;
}
else
s_printf ( txt_buf , " #FF8000 Warning:# Kernel partition not found! \n " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
boot_img_not_found :
lv_label_set_text ( lbl_status , txt_buf ) ;
manual_system_maintenance ( true ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Check if TWRP should be flashed.
2022-01-28 23:23:40 +00:00
strcpy ( path , " switchroot/install/twrp.img " ) ;
if ( f_stat ( path , NULL ) )
{
strcat ( txt_buf , " #FF8000 Warning:# TWRP image not found! \n " ) ;
goto twrp_not_found ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
offset_sct = 0 ;
size_sct = 0 ;
2022-05-16 10:28:38 +00:00
// Find TWRP partition.
2022-01-28 23:23:40 +00:00
for ( u32 i = 0 ; i < gpt - > header . num_part_ents ; i + + )
{
if ( ! memcmp ( gpt - > entries [ i ] . name , ( char [ ] ) { ' S ' , 0 , ' O ' , 0 , ' S ' , 0 } , 6 ) )
{
offset_sct = gpt - > entries [ i ] . lba_start ;
size_sct = ( gpt - > entries [ i ] . lba_end + 1 ) - gpt - > entries [ i ] . lba_start ;
break ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
if ( i > 126 )
break ;
}
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Flash TWRP.
2022-01-28 23:23:40 +00:00
if ( offset_sct & & size_sct )
{
u32 file_size = 0 ;
u8 * buf = sd_file_read ( path , & file_size ) ;
if ( file_size % 0x200 )
2020-04-30 13:12:55 +00:00
{
2022-01-28 23:23:40 +00:00
file_size = ALIGN ( file_size , 0x200 ) ;
u8 * buf_tmp = calloc ( file_size , 1 ) ;
memcpy ( buf_tmp , buf , file_size ) ;
free ( buf ) ;
buf = buf_tmp ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
if ( ( file_size > > 9 ) > size_sct )
strcat ( txt_buf , " #FF8000 Warning:# TWRP image too big! \n " ) ;
else
{
sdmmc_storage_write ( & sd_storage , offset_sct , file_size > > 9 , buf ) ;
strcat ( txt_buf , " #C7EA46 Success:# TWRP image flashed! \n " ) ;
f_unlink ( path ) ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
free ( buf ) ;
}
else
strcat ( txt_buf , " #FF8000 Warning:# TWRP partition not found! \n " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
twrp_not_found :
lv_label_set_text ( lbl_status , txt_buf ) ;
manual_system_maintenance ( true ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Check if Device Tree should be flashed.
2022-01-28 23:23:40 +00:00
strcpy ( path , " switchroot/install/tegra210-icosa.dtb " ) ;
if ( f_stat ( path , NULL ) )
{
strcat ( txt_buf , " #FF8000 Warning:# DTB image not found! " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
goto dtb_not_found ;
}
offset_sct = 0 ;
size_sct = 0 ;
2022-05-16 10:28:38 +00:00
// Find Device Tree partition.
2022-01-28 23:23:40 +00:00
for ( u32 i = 0 ; i < gpt - > header . num_part_ents ; i + + )
{
if ( ! memcmp ( gpt - > entries [ i ] . name , ( char [ ] ) { ' D ' , 0 , ' T ' , 0 , ' B ' , 0 } , 6 ) )
{
offset_sct = gpt - > entries [ i ] . lba_start ;
size_sct = ( gpt - > entries [ i ] . lba_end + 1 ) - gpt - > entries [ i ] . lba_start ;
break ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
if ( i > 126 )
break ;
}
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Flash Device Tree.
2022-01-28 23:23:40 +00:00
if ( offset_sct & & size_sct )
{
u32 file_size = 0 ;
u8 * buf = sd_file_read ( path , & file_size ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
if ( file_size % 0x200 )
{
file_size = ALIGN ( file_size , 0x200 ) ;
u8 * buf_tmp = calloc ( file_size , 1 ) ;
memcpy ( buf_tmp , buf , file_size ) ;
free ( buf ) ;
buf = buf_tmp ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
if ( ( file_size > > 9 ) > size_sct )
strcat ( txt_buf , " #FF8000 Warning:# DTB image too big! " ) ;
else
2020-04-30 13:12:55 +00:00
{
2022-01-28 23:23:40 +00:00
sdmmc_storage_write ( & sd_storage , offset_sct , file_size > > 9 , buf ) ;
strcat ( txt_buf , " #C7EA46 Success:# DTB image flashed! " ) ;
f_unlink ( path ) ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
free ( buf ) ;
}
else
strcat ( txt_buf , " #FF8000 Warning:# DTB partition not found! " ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
dtb_not_found :
lv_label_set_text ( lbl_status , txt_buf ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
// Check if TWRP is flashed unconditionally.
for ( u32 i = 0 ; i < gpt - > header . num_part_ents ; i + + )
{
if ( ! memcmp ( gpt - > entries [ i ] . name , ( char [ ] ) { ' S ' , 0 , ' O ' , 0 , ' S ' , 0 } , 6 ) )
{
u8 * buf = malloc ( 512 ) ;
sdmmc_storage_read ( & sd_storage , gpt - > entries [ i ] . lba_start , 1 , buf ) ;
if ( ! memcmp ( buf , " ANDROID " , 7 ) )
boot_twrp = true ;
free ( buf ) ;
break ;
}
if ( i > 126 )
break ;
}
error :
if ( boot_twrp )
{
2022-05-16 10:28:38 +00:00
// If a TWRP partition was found, ask user if rebooting into it is wanted.
2022-01-28 23:23:40 +00:00
strcat ( txt_buf , " \n \n Do you want to reboot into TWRP \n to finish Android installation? " ) ;
lv_label_set_text ( lbl_status , txt_buf ) ;
lv_mbox_add_btns ( mbox , mbox_btn_map2 , _action_reboot_twrp ) ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
else
lv_mbox_add_btns ( mbox , mbox_btn_map , mbox_action ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
free ( txt_buf ) ;
free ( gpt ) ;
sd_unmount ( ) ;
2020-04-30 13:12:55 +00:00
return LV_RES_INV ;
}
static lv_res_t _action_flash_android ( lv_obj_t * btn )
{
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 [ ] = { " \222 Continue " , " \222 Cancel " , " " } ;
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 * 6 ) ;
lv_mbox_set_text ( mbox , " #FF8000 Android Flasher# " ) ;
lv_obj_t * lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
lv_label_set_text ( lbl_status ,
" This will flash #C7EA46 Kernel#, #C7EA46 DTB# and #C7EA46 TWRP# if found. \n "
" Do you want to continue? " ) ;
lv_mbox_add_btns ( mbox , mbox_btn_map , _action_flash_android_data ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
return LV_RES_OK ;
}
static lv_res_t _action_part_manager_flash_options0 ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
switch ( btn_idx )
{
case 0 :
action_ums_sd ( btns ) ;
lv_obj_del ( ums_mbox ) ;
break ;
case 1 :
_action_check_flash_linux ( btns ) ;
break ;
case 2 :
_action_flash_android ( btns ) ;
break ;
case 3 :
mbox_action ( btns , txt ) ;
return LV_RES_INV ;
}
return LV_RES_OK ;
}
static lv_res_t _action_part_manager_flash_options1 ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
switch ( btn_idx )
{
case 0 :
action_ums_sd ( btns ) ;
lv_obj_del ( ums_mbox ) ;
break ;
case 1 :
mbox_action ( btns , txt ) ;
_action_check_flash_linux ( NULL ) ;
return LV_RES_INV ;
case 2 :
mbox_action ( btns , txt ) ;
return LV_RES_INV ;
}
return LV_RES_OK ;
}
static lv_res_t _action_part_manager_flash_options2 ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
switch ( btn_idx )
{
case 0 :
action_ums_sd ( btns ) ;
lv_obj_del ( ums_mbox ) ;
break ;
case 1 :
mbox_action ( btns , txt ) ;
_action_flash_android ( NULL ) ;
return LV_RES_INV ;
case 2 :
mbox_action ( btns , txt ) ;
return LV_RES_INV ;
}
return LV_RES_OK ;
}
static lv_res_t _create_mbox_start_partitioning ( lv_obj_t * btn )
{
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 ) ;
2021-02-06 02:10:02 +00:00
static const char * mbox_btn_map [ ] = { " \211 " , " \222 OK " , " \211 " , " " } ;
2020-04-30 13:12:55 +00:00
static const char * mbox_btn_map1 [ ] = { " \222 SD UMS " , " \222 Flash Linux " , " \222 Flash Android " , " \221 OK " , " " } ;
static const char * mbox_btn_map2 [ ] = { " \222 SD UMS " , " \222 Flash Linux " , " \221 OK " , " " } ;
static const char * mbox_btn_map3 [ ] = { " \222 SD UMS " , " \222 Flash Android " , " \221 OK " , " " } ;
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 * 6 ) ;
lv_mbox_set_text ( mbox , " #FF8000 Partition Manager# " ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
bool buttons_set = false ;
2022-05-16 10:28:38 +00:00
// Use safety wait if backup is not possible.
2020-04-30 13:12:55 +00:00
if ( ! part_info . backup_possible )
{
2021-10-01 12:45:25 +00:00
char * txt_buf = malloc ( SZ_4K ) ;
2020-04-30 13:12:55 +00:00
strcpy ( txt_buf , " #FF8000 Partition Manager# \n \n Safety wait ends in " ) ;
lv_mbox_set_text ( mbox , txt_buf ) ;
u32 seconds = 5 ;
u32 text_idx = strlen ( txt_buf ) ;
while ( seconds )
{
s_printf ( txt_buf + text_idx , " %d seconds... " , seconds ) ;
lv_mbox_set_text ( mbox , txt_buf ) ;
manual_system_maintenance ( true ) ;
msleep ( 1000 ) ;
seconds - - ;
}
lv_mbox_set_text ( mbox ,
" #FF8000 Partition Manager# \n \n "
" #FFDD00 Warning: Do you really want to continue?!# \n \n "
" Press #FF8000 POWER# to Continue. \n Press #FF8000 VOL# to abort. " ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
manual_system_maintenance ( true ) ;
free ( txt_buf ) ;
if ( ! ( btn_wait ( ) & BTN_POWER ) )
goto exit ;
}
lv_mbox_set_text ( mbox , " #FF8000 Partition Manager# " ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
manual_system_maintenance ( true ) ;
lv_obj_t * lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
lv_obj_t * lbl_paths [ 2 ] ;
2022-05-16 10:28:38 +00:00
// Create backup/restore paths labels.
2020-04-30 13:12:55 +00:00
lbl_paths [ 0 ] = lv_label_create ( mbox , NULL ) ;
lv_label_set_text ( lbl_paths [ 0 ] , " / " ) ;
lv_label_set_long_mode ( lbl_paths [ 0 ] , LV_LABEL_LONG_DOT ) ;
lv_cont_set_fit ( lbl_paths [ 0 ] , false , true ) ;
lv_obj_set_width ( lbl_paths [ 0 ] , ( LV_HOR_RES / 9 * 6 ) - LV_DPI / 2 ) ;
lv_label_set_align ( lbl_paths [ 0 ] , LV_LABEL_ALIGN_CENTER ) ;
lbl_paths [ 1 ] = lv_label_create ( mbox , NULL ) ;
lv_label_set_text ( lbl_paths [ 1 ] , " " ) ;
lv_label_set_long_mode ( lbl_paths [ 1 ] , LV_LABEL_LONG_DOT ) ;
lv_cont_set_fit ( lbl_paths [ 1 ] , false , true ) ;
lv_obj_set_width ( lbl_paths [ 1 ] , ( LV_HOR_RES / 9 * 6 ) - LV_DPI / 2 ) ;
lv_label_set_align ( lbl_paths [ 1 ] , LV_LABEL_ALIGN_CENTER ) ;
sd_mount ( ) ;
FATFS ram_fs ;
2022-05-08 02:57:59 +00:00
char * path = malloc ( 0x1000 ) ;
2020-04-30 13:12:55 +00:00
u32 total_files = 0 ;
u32 total_size = 0 ;
2020-12-28 03:34:01 +00:00
// Read current MBR.
2021-03-17 07:08:34 +00:00
sdmmc_storage_read ( & sd_storage , 0 , 1 , & part_info . mbr_old ) ;
2020-12-28 03:34:01 +00:00
2020-04-30 13:12:55 +00:00
lv_label_set_text ( lbl_status , " #00DDFF Status:# Initializing Ramdisk... " ) ;
lv_label_set_text ( lbl_paths [ 0 ] , " Please wait... " ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
manual_system_maintenance ( true ) ;
2022-05-16 10:28:38 +00:00
// Initialize RAM disk.
2021-02-06 02:15:19 +00:00
if ( ram_disk_init ( & ram_fs , RAM_DISK_SZ ) )
2020-04-30 13:12:55 +00:00
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Failed to initialize Ramdisk! " ) ;
goto error ;
}
if ( ! part_info . backup_possible )
{
strcpy ( path , " bootloader " ) ;
f_chdrive ( " ram: " ) ;
f_mkdir ( path ) ;
}
else
path [ 0 ] = 0 ;
lv_label_set_text ( lbl_status , " #00DDFF Status:# Backing up files... " ) ;
manual_system_maintenance ( true ) ;
2022-05-16 10:28:38 +00:00
// Do full or hekate/Nyx backup.
2020-04-30 13:12:55 +00:00
if ( _backup_and_restore_files ( path , & total_files , & total_size , " ram: " , " sd: " , lbl_paths ) )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Failed to back up files! " ) ;
goto error ;
}
total_files = 0 ;
total_size = 0 ;
if ( ! part_info . backup_possible )
strcpy ( path , " bootloader " ) ;
else
path [ 0 ] = 0 ;
f_mount ( NULL , " sd: " , 1 ) ; // Unmount SD card.
lv_label_set_text ( lbl_status , " #00DDFF Status:# Formatting FAT32 partition... " ) ;
lv_label_set_text ( lbl_paths [ 0 ] , " Please wait... " ) ;
lv_label_set_text ( lbl_paths [ 1 ] , " " ) ;
manual_system_maintenance ( true ) ;
// Set reserved size.
u32 part_rsvd_size = ( part_info . emu_size < < 11 ) + ( part_info . l4t_size < < 11 ) + ( part_info . and_size < < 11 ) ;
2022-03-22 22:24:51 +00:00
part_rsvd_size + = part_rsvd_size ? part_info . alignment : 0 ; // Do not reserve alignment space if no extra partitions.
2020-04-30 13:12:55 +00:00
disk_set_info ( DRIVE_SD , SET_SECTOR_COUNT , & part_rsvd_size ) ;
2021-10-01 12:45:25 +00:00
u8 * buf = malloc ( SZ_4M ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Set cluster size to 64KB and try to format.
2020-06-14 10:07:42 +00:00
u32 cluster_size = 65536 ;
2021-10-01 12:45:25 +00:00
u32 mkfs_error = f_mkfs ( " sd: " , FM_FAT32 , cluster_size , buf , SZ_4M ) ;
2022-01-28 23:23:40 +00:00
if ( ! mkfs_error )
goto mkfs_no_error ;
2022-05-16 10:28:38 +00:00
// Retry formatting by halving cluster size, until one succeeds.
2022-01-28 23:23:40 +00:00
while ( cluster_size > 4096 )
2020-04-30 13:12:55 +00:00
{
2022-01-28 23:23:40 +00:00
cluster_size / = 2 ;
mkfs_error = f_mkfs ( " sd: " , FM_FAT32 , cluster_size , buf , SZ_4M ) ;
2020-06-14 10:07:42 +00:00
2022-01-28 23:23:40 +00:00
if ( ! mkfs_error )
break ;
}
2020-06-14 10:07:42 +00:00
2022-01-28 23:23:40 +00:00
if ( mkfs_error )
{
// Failed to format.
s_printf ( ( char * ) buf , " #FFDD00 Error:# Failed to format disk (%d)! \n \n "
" Remove the SD card and check that is OK. \n If not, format it, reinsert it and \n press #FF8000 POWER#! " , mkfs_error ) ;
2020-06-14 10:07:42 +00:00
2022-01-28 23:23:40 +00:00
lv_label_set_text ( lbl_status , ( char * ) buf ) ;
lv_label_set_text ( lbl_paths [ 0 ] , " " ) ;
manual_system_maintenance ( true ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
sd_end ( ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
while ( ! ( btn_wait ( ) & BTN_POWER ) ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
sd_mount ( ) ;
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
if ( ! part_info . backup_possible )
{
f_chdrive ( " sd: " ) ;
f_mkdir ( path ) ;
}
2020-04-30 13:12:55 +00:00
2022-01-28 23:23:40 +00:00
lv_label_set_text ( lbl_status , " #00DDFF Status:# Restoring files... " ) ;
manual_system_maintenance ( true ) ;
if ( _backup_and_restore_files ( path , & total_files , & total_size , " sd: " , " ram: " , NULL ) )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Failed to restore files! " ) ;
2020-04-30 13:12:55 +00:00
free ( buf ) ;
goto error ;
}
2022-01-28 23:23:40 +00:00
lv_label_set_text ( lbl_status , " #00DDFF Status:# Restored files but the operation failed! " ) ;
f_mount ( NULL , " ram: " , 1 ) ; // Unmount ramdisk.
free ( buf ) ;
goto error ;
2020-04-30 13:12:55 +00:00
}
2022-01-28 23:23:40 +00:00
mkfs_no_error :
2020-04-30 13:12:55 +00:00
free ( buf ) ;
2022-05-16 10:28:38 +00:00
// Remount sd card as it was unmounted from formatting it.
2020-04-30 13:12:55 +00:00
f_mount ( & sd_fs , " sd: " , 1 ) ; // Mount SD card.
if ( ! part_info . backup_possible )
{
f_chdrive ( " sd: " ) ;
f_mkdir ( path ) ;
}
lv_label_set_text ( lbl_status , " #00DDFF Status:# Restoring files... " ) ;
manual_system_maintenance ( true ) ;
2022-05-16 10:28:38 +00:00
// Restore backed up files back to SD.
2020-04-30 13:12:55 +00:00
if ( _backup_and_restore_files ( path , & total_files , & total_size , " sd: " , " ram: " , lbl_paths ) )
{
2022-05-16 10:28:38 +00:00
// Failed to restore files.
2020-04-30 13:12:55 +00:00
total_files = 0 ;
total_size = 0 ;
if ( ! part_info . backup_possible )
{
strcpy ( path , " bootloader " ) ;
f_chdrive ( " sd: " ) ;
f_mkdir ( path ) ;
}
else
path [ 0 ] = 0 ;
2022-05-16 10:28:38 +00:00
// Try again once more.
2020-04-30 13:12:55 +00:00
if ( _backup_and_restore_files ( path , & total_files , & total_size , " sd: " , " ram: " , NULL ) )
{
lv_label_set_text ( lbl_status , " #FFDD00 Error:# Failed to restore files! " ) ;
goto error ;
}
}
f_mount ( NULL , " ram: " , 1 ) ; // Unmount ramdisk.
f_chdrive ( " sd: " ) ;
// Set Volume label.
f_setlabel ( " 0:SWITCH SD " ) ;
lv_label_set_text ( lbl_status , " #00DDFF Status:# Flashing partition table... " ) ;
lv_label_set_text ( lbl_paths [ 0 ] , " Please wait... " ) ;
lv_label_set_text ( lbl_paths [ 1 ] , " " ) ;
manual_system_maintenance ( true ) ;
2022-05-16 10:28:38 +00:00
// Prepare MBR and GPT header and partition entries and flash them.
2020-04-30 13:12:55 +00:00
_prepare_and_flash_mbr_gpt ( ) ;
2021-01-03 12:51:48 +00:00
// Enable/Disable buttons depending on partition layout.
if ( part_info . l4t_size )
{
lv_obj_set_click ( btn_flash_l4t , true ) ;
lv_btn_set_state ( btn_flash_l4t , LV_BTN_STATE_REL ) ;
}
else
{
lv_obj_set_click ( btn_flash_l4t , false ) ;
lv_btn_set_state ( btn_flash_l4t , LV_BTN_STATE_INA ) ;
}
// Enable/Disable buttons depending on partition layout.
if ( part_info . and_size )
{
lv_obj_set_click ( btn_flash_android , true ) ;
lv_btn_set_state ( btn_flash_android , LV_BTN_STATE_REL ) ;
}
else
{
lv_obj_set_click ( btn_flash_android , false ) ;
lv_btn_set_state ( btn_flash_android , LV_BTN_STATE_INA ) ;
}
2020-06-13 15:32:40 +00:00
sd_unmount ( ) ;
2020-04-30 13:12:55 +00:00
lv_label_set_text ( lbl_status , " #00DDFF Status:# Done! " ) ;
manual_system_maintenance ( true ) ;
2022-05-16 10:28:38 +00:00
// Set buttons depending on what user chose to create.
2020-04-30 13:12:55 +00:00
if ( part_info . l4t_size & & part_info . and_size )
lv_mbox_add_btns ( mbox , mbox_btn_map1 , _action_part_manager_flash_options0 ) ;
else if ( part_info . l4t_size )
lv_mbox_add_btns ( mbox , mbox_btn_map2 , _action_part_manager_flash_options1 ) ;
else if ( part_info . and_size )
lv_mbox_add_btns ( mbox , mbox_btn_map3 , _action_part_manager_flash_options2 ) ;
if ( part_info . l4t_size | | part_info . and_size )
buttons_set = true ;
goto out ;
error :
f_chdrive ( " sd: " ) ;
free ( path ) ;
out :
lv_obj_del ( lbl_paths [ 0 ] ) ;
lv_obj_del ( lbl_paths [ 1 ] ) ;
exit :
if ( ! buttons_set )
lv_mbox_add_btns ( mbox , mbox_btn_map , mbox_action ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
// Disable partitioning button.
if ( btn )
lv_btn_set_state ( btn , LV_BTN_STATE_INA ) ;
return LV_RES_OK ;
}
static lv_res_t _create_mbox_partitioning_option0 ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
switch ( btn_idx )
{
case 0 :
action_ums_sd ( btns ) ;
return LV_RES_OK ;
case 1 :
mbox_action ( btns , txt ) ;
_create_mbox_start_partitioning ( NULL ) ;
break ;
case 2 :
mbox_action ( btns , txt ) ;
break ;
}
return LV_RES_INV ;
}
static lv_res_t _create_mbox_partitioning_option1 ( lv_obj_t * btns , const char * txt )
{
int btn_idx = lv_btnm_get_pressed ( btns ) ;
mbox_action ( btns , txt ) ;
if ( ! btn_idx )
{
mbox_action ( btns , txt ) ;
_create_mbox_start_partitioning ( NULL ) ;
return LV_RES_INV ;
}
return LV_RES_OK ;
}
static lv_res_t _create_mbox_partitioning_next ( lv_obj_t * btn )
{
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 [ ] = { " \222 SD UMS " , " \222 Start " , " \222 Cancel " , " " } ;
static const char * mbox_btn_map2 [ ] = { " \222 Start " , " \222 Cancel " , " " } ;
lv_obj_t * mbox = lv_mbox_create ( dark_bg , NULL ) ;
lv_mbox_set_recolor_text ( mbox , true ) ;
2021-10-01 12:45:25 +00:00
char * txt_buf = malloc ( SZ_4K ) ;
2020-04-30 13:12:55 +00:00
lv_obj_set_width ( mbox , LV_HOR_RES / 9 * 6 ) ;
lv_mbox_set_text ( mbox , " #FF8000 Partition Manager# " ) ;
lv_obj_t * lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
2021-01-11 19:39:44 +00:00
s_printf ( txt_buf , " #FFDD00 Warning: This will partition the SD Card!# \n \n " ) ;
2020-04-30 13:12:55 +00:00
if ( part_info . backup_possible )
2021-02-08 01:52:23 +00:00
{
strcat ( txt_buf , " #C7EA46 Your files will be backed up and restored!# \n "
" #FFDD00 Any other partition will be wiped!# " ) ;
}
2020-04-30 13:12:55 +00:00
else
2021-02-08 01:52:23 +00:00
{
strcat ( txt_buf , " #FFDD00 Your files will be wiped!# \n "
" #FFDD00 Any other partition will be also wiped!# \n "
" #FFDD00 Use USB UMS to copy them over!# " ) ;
}
2020-04-30 13:12:55 +00:00
lv_label_set_text ( lbl_status , txt_buf ) ;
if ( part_info . backup_possible )
lv_mbox_add_btns ( mbox , mbox_btn_map2 , _create_mbox_partitioning_option1 ) ;
else
lv_mbox_add_btns ( mbox , mbox_btn_map , _create_mbox_partitioning_option0 ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
free ( txt_buf ) ;
return LV_RES_OK ;
}
static void _update_partition_bar ( )
{
lv_obj_t * h1 = lv_obj_get_parent ( part_info . bar_hos ) ;
2022-05-16 10:28:38 +00:00
// Set widths based on max bar width.
u32 total_size = ( part_info . total_sct - AU_ALIGN_SECTORS ) / SECTORS_PER_GB ;
2020-04-30 13:12:55 +00:00
u32 bar_hos_size = lv_obj_get_width ( h1 ) * ( part_info . hos_size > > 10 ) / total_size ;
u32 bar_emu_size = lv_obj_get_width ( h1 ) * ( part_info . emu_size > > 10 ) / total_size ;
u32 bar_l4t_size = lv_obj_get_width ( h1 ) * ( part_info . l4t_size > > 10 ) / total_size ;
u32 bar_and_size = lv_obj_get_width ( h1 ) * ( part_info . and_size > > 10 ) / total_size ;
2022-05-16 10:28:38 +00:00
// Update bar widths.
2020-04-30 13:12:55 +00:00
lv_obj_set_size ( part_info . bar_hos , bar_hos_size , LV_DPI / 2 ) ;
lv_obj_set_size ( part_info . bar_emu , bar_emu_size , LV_DPI / 2 ) ;
lv_obj_set_size ( part_info . bar_l4t , bar_l4t_size , LV_DPI / 2 ) ;
lv_obj_set_size ( part_info . bar_and , bar_and_size , LV_DPI / 2 ) ;
2022-05-16 10:28:38 +00:00
// Re-align bars.
2020-04-30 13:12:55 +00:00
lv_obj_align ( part_info . bar_emu , part_info . bar_hos , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
lv_obj_align ( part_info . bar_l4t , part_info . bar_emu , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
lv_obj_align ( part_info . bar_and , part_info . bar_l4t , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
2022-05-16 10:28:38 +00:00
// Set emuMMC blending separator sizes and realign.
2020-04-30 13:12:55 +00:00
lv_obj_set_size ( part_info . sep_emu , bar_emu_size ? 8 : 0 , LV_DPI / 2 ) ;
lv_obj_align ( part_info . sep_emu , part_info . bar_hos , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
2022-05-16 10:28:38 +00:00
// Set L4T blending separator sizes and realign.
2020-04-30 13:12:55 +00:00
lv_obj_set_size ( part_info . sep_l4t , bar_l4t_size ? 8 : 0 , LV_DPI / 2 ) ;
lv_obj_align ( part_info . sep_l4t , part_info . bar_emu , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
2022-05-16 10:28:38 +00:00
// Set Android blending separator sizes and realign.
2020-04-30 13:12:55 +00:00
lv_obj_set_size ( part_info . sep_and , bar_and_size ? 8 : 0 , LV_DPI / 2 ) ;
lv_obj_align ( part_info . sep_and , part_info . bar_l4t , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
}
static lv_res_t _action_slider_emu ( lv_obj_t * slider )
{
2022-01-28 23:39:01 +00:00
# define EMUMMC_32GB_FULL 29856
# define EMUMMC_64GB_FULL (59664 + 1) // 1MB extra for backup GPT.
2022-01-20 12:11:36 +00:00
const u32 rsvd_mb = 4 + 4 + 16 + 8 ; // BOOT0 + BOOT1 + 16MB offset + 8MB alignment.
2021-02-06 02:10:02 +00:00
u32 size ;
2020-04-30 13:12:55 +00:00
char lbl_text [ 64 ] ;
2021-02-06 02:10:02 +00:00
bool prev_emu_double = part_info . emu_double ;
2020-04-30 13:12:55 +00:00
int slide_val = lv_slider_get_value ( slider ) ;
2022-01-28 23:39:01 +00:00
u32 max_emmc_size = ! part_info . emmc_is_64gb ? EMUMMC_32GB_FULL : EMUMMC_64GB_FULL ;
2021-02-06 02:10:02 +00:00
part_info . emu_double = false ;
2020-04-30 13:12:55 +00:00
2021-02-06 15:12:09 +00:00
size = ( slide_val > 10 ? ( slide_val - 10 ) : slide_val ) + 3 ; // Min 4GB.
size * = 1024 ; // Convert to GB.
size + = rsvd_mb ; // Add reserved size.
2021-02-06 02:10:02 +00:00
if ( ! slide_val )
size = 0 ; // Reset if 0.
else if ( slide_val > = 11 )
{
size * = 2 ;
part_info . emu_double = true ;
}
2022-01-20 12:11:36 +00:00
// Handle special cases. 2nd value is for 64GB Aula.
2021-02-06 02:10:02 +00:00
if ( slide_val = = 10 )
2022-01-28 23:39:01 +00:00
size = max_emmc_size ;
2021-02-06 02:10:02 +00:00
else if ( slide_val = = 20 )
2022-01-28 23:39:01 +00:00
size = 2 * max_emmc_size ;
2021-02-06 02:10:02 +00:00
2022-05-16 10:28:38 +00:00
// Sanitize sizes based on new HOS size.
2021-02-06 02:10:02 +00:00
s32 hos_size = ( part_info . total_sct > > 11 ) - 16 - size - part_info . l4t_size - part_info . and_size ;
2022-05-16 10:28:38 +00:00
if ( hos_size > HOS_MIN_SIZE_MB )
2020-04-30 13:12:55 +00:00
{
part_info . emu_size = size ;
part_info . hos_size = hos_size ;
s_printf ( lbl_text , " #96FF00 %d GiB# " , hos_size > > 10 ) ;
lv_label_set_text ( part_info . lbl_hos , lbl_text ) ;
lv_bar_set_value ( part_info . slider_bar_hos , hos_size > > 10 ) ;
2021-02-06 02:10:02 +00:00
if ( ! part_info . emu_double )
2021-02-06 15:12:09 +00:00
{
if ( slide_val ! = 10 )
s_printf ( lbl_text , " #FF3C28 %d GiB# " , size > > 10 ) ;
else
s_printf ( lbl_text , " #FF3C28 %d FULL# " , size > > 10 ) ;
}
2020-04-30 13:12:55 +00:00
else
2021-02-06 15:12:09 +00:00
s_printf ( lbl_text , " #FFDD00 2x##FF3C28 %d# " , size > > 11 ) ;
2020-04-30 13:12:55 +00:00
lv_label_set_text ( part_info . lbl_emu , lbl_text ) ;
}
else
2020-05-05 16:28:15 +00:00
{
2021-02-06 02:10:02 +00:00
u32 emu_size = part_info . emu_size ;
2022-01-28 23:39:01 +00:00
if ( emu_size = = max_emmc_size )
2021-02-06 02:10:02 +00:00
emu_size = 10 ;
2022-01-28 23:39:01 +00:00
else if ( emu_size = = 2 * max_emmc_size )
2021-02-06 02:10:02 +00:00
emu_size = 20 ;
else if ( emu_size )
2020-05-05 16:28:15 +00:00
{
2021-02-06 02:10:02 +00:00
if ( prev_emu_double )
emu_size / = 2 ;
emu_size - = rsvd_mb ;
emu_size / = 1024 ;
emu_size - = 3 ;
if ( prev_emu_double )
emu_size + = 11 ;
2020-05-05 16:28:15 +00:00
}
2021-02-06 02:10:02 +00:00
int new_slider_val = emu_size ;
part_info . emu_double = prev_emu_double ? true : false ;
2020-05-05 16:28:15 +00:00
lv_slider_set_value ( slider , new_slider_val ) ;
}
2020-04-30 13:12:55 +00:00
_update_partition_bar ( ) ;
return LV_RES_OK ;
}
static lv_res_t _action_slider_l4t ( lv_obj_t * slider )
{
char lbl_text [ 64 ] ;
u32 size = ( u32 ) lv_slider_get_value ( slider ) < < 10 ;
if ( size < 4096 )
size = 0 ;
else if ( size < 8192 )
size = 8192 ;
s32 hos_size = ( part_info . total_sct > > 11 ) - 16 - part_info . emu_size - size - part_info . and_size ;
2022-05-16 10:28:38 +00:00
// Sanitize sizes based on new HOS size.
if ( hos_size > HOS_MIN_SIZE_MB )
2020-04-30 13:12:55 +00:00
{
if ( size < = 8192 )
lv_slider_set_value ( slider , size > > 10 ) ;
}
else
{
size = ( part_info . total_sct > > 11 ) - 16 - part_info . emu_size - part_info . and_size - 2048 ;
hos_size = ( part_info . total_sct > > 11 ) - 16 - part_info . emu_size - part_info . and_size - size ;
2022-05-16 10:28:38 +00:00
if ( hos_size < HOS_MIN_SIZE_MB | | size < 8192 )
2020-04-30 13:12:55 +00:00
{
lv_slider_set_value ( slider , part_info . l4t_size > > 10 ) ;
goto out ;
}
lv_slider_set_value ( slider , size > > 10 ) ;
}
part_info . l4t_size = size ;
part_info . hos_size = hos_size ;
s_printf ( lbl_text , " #96FF00 %d GiB# " , hos_size > > 10 ) ;
lv_label_set_text ( part_info . lbl_hos , lbl_text ) ;
lv_bar_set_value ( part_info . slider_bar_hos , hos_size > > 10 ) ;
s_printf ( lbl_text , " #00DDFF %d GiB# " , size > > 10 ) ;
lv_label_set_text ( part_info . lbl_l4t , lbl_text ) ;
_update_partition_bar ( ) ;
out :
return LV_RES_OK ;
}
static lv_res_t _action_slider_and ( lv_obj_t * slider )
{
char lbl_text [ 64 ] ;
u32 user_size = ( u32 ) lv_slider_get_value ( slider ) < < 10 ;
if ( user_size < 2048 )
user_size = 0 ;
else if ( user_size < 4096 )
user_size = 4096 ;
2022-05-16 10:28:38 +00:00
u32 and_size = user_size ? ( user_size + ANDROID_SYSTEM_SIZE_MB ) : 0 ;
2020-04-30 13:12:55 +00:00
s32 hos_size = ( part_info . total_sct > > 11 ) - 16 - part_info . emu_size - part_info . l4t_size - and_size ;
2022-05-16 10:28:38 +00:00
// Sanitize sizes based on new HOS size.
if ( hos_size > HOS_MIN_SIZE_MB )
2020-04-30 13:12:55 +00:00
{
if ( user_size < = 4096 )
lv_slider_set_value ( slider , user_size > > 10 ) ;
}
else
{
and_size = ( part_info . total_sct > > 11 ) - 16 - part_info . emu_size - part_info . l4t_size - 2048 ;
hos_size = ( part_info . total_sct > > 11 ) - 16 - part_info . emu_size - part_info . l4t_size - and_size ;
2022-05-16 10:28:38 +00:00
if ( hos_size < HOS_MIN_SIZE_MB | | and_size < 8192 )
2020-04-30 13:12:55 +00:00
{
lv_slider_set_value ( slider , part_info . and_size > > 10 ) ;
goto out ;
}
2022-05-16 10:28:38 +00:00
user_size = and_size - ANDROID_SYSTEM_SIZE_MB ;
2020-04-30 13:12:55 +00:00
lv_slider_set_value ( slider , user_size > > 10 ) ;
}
part_info . and_size = and_size ;
part_info . hos_size = hos_size ;
s_printf ( lbl_text , " #96FF00 %d GiB# " , hos_size > > 10 ) ;
lv_label_set_text ( part_info . lbl_hos , lbl_text ) ;
lv_bar_set_value ( part_info . slider_bar_hos , hos_size > > 10 ) ;
s_printf ( lbl_text , " #FF8000 %d GiB# " , user_size > > 10 ) ;
lv_label_set_text ( part_info . lbl_and , lbl_text ) ;
_update_partition_bar ( ) ;
out :
return LV_RES_OK ;
}
static void create_mbox_check_files_total_size ( )
{
static lv_style_t bar_hos_ind , bar_emu_ind , bar_l4t_ind , bar_and_ind ;
static lv_style_t sep_emu_bg , sep_l4t_bg , sep_and_bg ;
2022-05-16 10:28:38 +00:00
// Set HOS bar style.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_hos_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_hos_ind . body . main_color = LV_COLOR_HEX ( 0x96FF00 ) ;
bar_hos_ind . body . grad_color = bar_hos_ind . body . main_color ;
2022-05-16 10:28:38 +00:00
// Set emuMMC bar style.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_emu_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_emu_ind . body . main_color = LV_COLOR_HEX ( 0xFF3C28 ) ;
bar_emu_ind . body . grad_color = bar_emu_ind . body . main_color ;
2022-05-16 10:28:38 +00:00
// Set L4T bar style.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_l4t_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_l4t_ind . body . main_color = LV_COLOR_HEX ( 0x00DDFF ) ;
bar_l4t_ind . body . grad_color = bar_l4t_ind . body . main_color ;
2022-05-16 10:28:38 +00:00
// Set Android bar style.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_and_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_and_ind . body . main_color = LV_COLOR_HEX ( 0xFF8000 ) ;
bar_and_ind . body . grad_color = bar_and_ind . body . main_color ;
2022-05-16 10:28:38 +00:00
// Set separator styles.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & sep_emu_bg , lv_theme_get_current ( ) - > cont ) ;
sep_emu_bg . body . main_color = LV_COLOR_HEX ( 0xFF3C28 ) ;
sep_emu_bg . body . grad_color = sep_emu_bg . body . main_color ;
sep_emu_bg . body . radius = 0 ;
lv_style_copy ( & sep_l4t_bg , & sep_emu_bg ) ;
sep_l4t_bg . body . main_color = LV_COLOR_HEX ( 0x00DDFF ) ;
sep_l4t_bg . body . grad_color = sep_l4t_bg . body . main_color ;
lv_style_copy ( & sep_and_bg , & sep_emu_bg ) ;
sep_and_bg . body . main_color = LV_COLOR_HEX ( 0xFF8000 ) ;
sep_and_bg . body . grad_color = sep_and_bg . body . main_color ;
2021-10-01 12:45:25 +00:00
char * txt_buf = malloc ( SZ_8K ) ;
2020-04-30 13:12:55 +00:00
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 " , " \222 OK " , " \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 * 6 ) ;
lv_mbox_set_text ( mbox , " Analyzing SD card usage. This might take a while... " ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
manual_system_maintenance ( true ) ;
2022-05-08 02:57:59 +00:00
char * path = malloc ( 0x1000 ) ;
2020-04-30 13:12:55 +00:00
u32 total_files = 0 ;
u32 total_size = 0 ;
path [ 0 ] = 0 ;
// Check total size of files.
2021-01-11 19:32:35 +00:00
int res = _backup_and_restore_files ( path , & total_files , & total_size , NULL , NULL , NULL ) ;
2020-04-30 13:12:55 +00:00
// Not more than 1.0GB.
2021-10-01 12:45:25 +00:00
part_info . backup_possible = ! res & & ! ( total_size > ( RAM_DISK_SZ - SZ_16M ) ) ; // 0x2400000
2020-04-30 13:12:55 +00:00
if ( part_info . backup_possible )
{
s_printf ( txt_buf ,
2021-01-11 19:39:44 +00:00
" #96FF00 The SD Card files will be backed up automatically!# \n "
2020-12-28 03:34:01 +00:00
" #FFDD00 Any other partition will be wiped!# \n "
2020-04-30 13:12:55 +00:00
" #00DDFF Total files:# %d, #00DDFF Total size:# %d MiB " , total_files , total_size > > 20 ) ;
lv_mbox_set_text ( mbox , txt_buf ) ;
}
else
{
lv_mbox_set_text ( mbox ,
2021-02-08 01:52:23 +00:00
" #FFDD00 The SD Card cannot be backed up!# \n "
" #FFDD00 Any other partition will be also wiped!# \n \n "
2020-04-30 13:12:55 +00:00
" You will be asked to back up your files later via UMS. " ) ;
}
// Create container to keep content inside.
lv_obj_t * h1 = lv_cont_create ( mbox , NULL ) ;
lv_cont_set_fit ( h1 , false , true ) ;
lv_cont_set_style ( h1 , & lv_style_transp_tight ) ;
lv_obj_set_width ( h1 , lv_obj_get_width ( mbox ) - LV_DPI * 3 ) ;
lv_obj_t * lbl_part = lv_label_create ( h1 , NULL ) ;
lv_label_set_recolor ( lbl_part , true ) ;
2021-03-17 07:14:50 +00:00
lv_label_set_text ( lbl_part , " #00DDFF Current MBR partition layout:# " ) ;
2020-04-30 13:12:55 +00:00
// Read current MBR.
mbr_t mbr = { 0 } ;
sdmmc_storage_read ( & sd_storage , 0 , 1 , & mbr ) ;
2022-05-16 10:28:38 +00:00
// Calculate MBR partitions size.
total_size = ( sd_storage . sec_cnt - AU_ALIGN_SECTORS ) / SECTORS_PER_GB ;
u32 bar_hos_size = lv_obj_get_width ( h1 ) * ( mbr . partitions [ 0 ] . size_sct / SECTORS_PER_GB ) / total_size ;
2020-04-30 13:12:55 +00:00
u32 bar_emu_size = 0 ;
for ( u32 i = 1 ; i < 4 ; i + + )
if ( mbr . partitions [ i ] . type = = 0xE0 )
bar_emu_size + = mbr . partitions [ i ] . size_sct ;
2022-05-16 10:28:38 +00:00
bar_emu_size = lv_obj_get_width ( h1 ) * ( bar_emu_size / SECTORS_PER_GB ) / total_size ;
2020-04-30 13:12:55 +00:00
u32 bar_l4t_size = 0 ;
for ( u32 i = 1 ; i < 4 ; i + + )
if ( mbr . partitions [ i ] . type = = 0x83 )
bar_l4t_size + = mbr . partitions [ i ] . size_sct ;
2022-05-16 10:28:38 +00:00
bar_l4t_size = lv_obj_get_width ( h1 ) * ( bar_l4t_size / SECTORS_PER_GB ) / total_size ;
2020-04-30 13:12:55 +00:00
u32 bar_and_size = lv_obj_get_width ( h1 ) - bar_hos_size - bar_emu_size - bar_l4t_size ;
2022-05-16 10:28:38 +00:00
// Create HOS bar.
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_mbr_hos = lv_bar_create ( h1 , NULL ) ;
lv_obj_set_size ( bar_mbr_hos , bar_hos_size , LV_DPI / 3 ) ;
lv_bar_set_range ( bar_mbr_hos , 0 , 1 ) ;
lv_bar_set_value ( bar_mbr_hos , 1 ) ;
lv_bar_set_style ( bar_mbr_hos , LV_BAR_STYLE_INDIC , & bar_hos_ind ) ;
lv_obj_align ( bar_mbr_hos , lbl_part , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 6 ) ;
2022-05-16 10:28:38 +00:00
// Create emuMMC bar.
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_mbr_emu = lv_bar_create ( h1 , bar_mbr_hos ) ;
lv_obj_set_size ( bar_mbr_emu , bar_emu_size , LV_DPI / 3 ) ;
lv_bar_set_style ( bar_mbr_emu , LV_BAR_STYLE_INDIC , & bar_emu_ind ) ;
lv_obj_align ( bar_mbr_emu , bar_mbr_hos , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
2022-05-16 10:28:38 +00:00
// Create L4T bar.
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_mbr_l4t = lv_bar_create ( h1 , bar_mbr_hos ) ;
lv_obj_set_size ( bar_mbr_l4t , bar_l4t_size , LV_DPI / 3 ) ;
lv_bar_set_style ( bar_mbr_l4t , LV_BAR_STYLE_INDIC , & bar_l4t_ind ) ;
lv_obj_align ( bar_mbr_l4t , bar_mbr_emu , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
2022-05-16 10:28:38 +00:00
// Create GPT bar.
lv_obj_t * bar_mbr_gpt = lv_bar_create ( h1 , bar_mbr_hos ) ;
lv_obj_set_size ( bar_mbr_gpt , bar_and_size > 1 ? bar_and_size : 0 , LV_DPI / 3 ) ;
lv_bar_set_style ( bar_mbr_gpt , LV_BAR_STYLE_INDIC , & bar_and_ind ) ;
lv_obj_align ( bar_mbr_gpt , bar_mbr_l4t , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Create emuMMC separator.
2020-04-30 13:12:55 +00:00
lv_obj_t * sep_mbr_emu = lv_cont_create ( h1 , NULL ) ;
lv_obj_set_size ( sep_mbr_emu , bar_emu_size ? 8 : 0 , LV_DPI / 3 ) ;
lv_obj_set_style ( sep_mbr_emu , & sep_emu_bg ) ;
lv_obj_align ( sep_mbr_emu , bar_mbr_hos , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
2022-05-16 10:28:38 +00:00
// Create L4T separator.
2020-04-30 13:12:55 +00:00
lv_obj_t * sep_mbr_l4t = lv_cont_create ( h1 , sep_mbr_emu ) ;
lv_obj_set_size ( sep_mbr_l4t , bar_l4t_size ? 8 : 0 , LV_DPI / 3 ) ;
lv_obj_set_style ( sep_mbr_l4t , & sep_l4t_bg ) ;
lv_obj_align ( sep_mbr_l4t , bar_mbr_emu , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
2022-05-16 10:28:38 +00:00
// Create GPT separator.
lv_obj_t * sep_mbr_gpt = lv_cont_create ( h1 , sep_mbr_emu ) ;
lv_obj_set_size ( sep_mbr_gpt , bar_and_size ? ( bar_and_size > 1 ? 8 : 0 ) : 0 , LV_DPI / 3 ) ;
lv_obj_set_style ( sep_mbr_gpt , & sep_and_bg ) ;
lv_obj_align ( sep_mbr_gpt , bar_mbr_l4t , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
2020-04-30 13:12:55 +00:00
// Print partition table info.
s_printf ( txt_buf ,
" Partition 0 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 1 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 2 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 3 - Type: %02x, Start: %08x, Size: %08x " ,
mbr . partitions [ 0 ] . type , mbr . partitions [ 0 ] . start_sct , mbr . partitions [ 0 ] . size_sct ,
mbr . partitions [ 1 ] . type , mbr . partitions [ 1 ] . start_sct , mbr . partitions [ 1 ] . size_sct ,
mbr . partitions [ 2 ] . type , mbr . partitions [ 2 ] . start_sct , mbr . partitions [ 2 ] . size_sct ,
mbr . partitions [ 3 ] . type , mbr . partitions [ 3 ] . start_sct , mbr . partitions [ 3 ] . size_sct ) ;
lv_obj_t * lbl_table = lv_label_create ( h1 , NULL ) ;
lv_label_set_style ( lbl_table , & monospace_text ) ;
lv_label_set_text ( lbl_table , txt_buf ) ;
lv_obj_align ( lbl_table , h1 , LV_ALIGN_IN_TOP_MID , 0 , LV_DPI ) ;
lv_mbox_add_btns ( mbox , mbox_btn_map , mbox_action ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
free ( txt_buf ) ;
free ( path ) ;
}
static lv_res_t _action_fix_mbr ( lv_obj_t * btn )
{
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 " , " \222 OK " , " \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 * 6 ) ;
lv_mbox_set_text ( mbox , " #FF8000 Fix Hybrid MBR# " ) ;
lv_obj_t * lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
2021-02-06 02:10:50 +00:00
// Try to init sd card. No need for valid MBR.
if ( ! sd_mount ( ) & & ! sd_get_card_initialized ( ) )
2020-04-30 13:12:55 +00:00
{
lv_label_set_text ( lbl_status , " #FFDD00 Failed to init SD!# " ) ;
goto out ;
}
mbr_t mbr [ 2 ] = { 0 } ;
2021-03-17 07:08:34 +00:00
gpt_t * gpt = calloc ( 1 , sizeof ( gpt_t ) ) ;
2022-05-08 02:59:32 +00:00
gpt_header_t gpt_hdr_backup = { 0 } ;
2020-04-30 13:12:55 +00:00
sdmmc_storage_read ( & sd_storage , 0 , 1 , & mbr [ 0 ] ) ;
2021-03-17 07:08:34 +00:00
sdmmc_storage_read ( & sd_storage , 1 , sizeof ( gpt_t ) > > 9 , gpt ) ;
2020-04-30 13:12:55 +00:00
memcpy ( & mbr [ 1 ] , & mbr [ 0 ] , sizeof ( mbr_t ) ) ;
2020-06-13 15:32:40 +00:00
sd_unmount ( ) ;
2020-04-30 13:12:55 +00:00
2021-03-17 07:14:50 +00:00
if ( memcmp ( & gpt - > header . signature , " EFI PART " , 8 ) | | gpt - > header . num_part_ents > 128 )
2020-04-30 13:12:55 +00:00
{
2021-03-17 07:14:50 +00:00
lv_label_set_text ( lbl_status , " #FFDD00 Warning:# No valid GPT was found! " ) ;
2022-05-08 02:59:32 +00:00
free ( gpt ) ;
2020-04-30 13:12:55 +00:00
goto out ;
}
2022-05-08 02:59:32 +00:00
sdmmc_storage_read ( & sd_storage , gpt - > header . alt_lba , 1 , & gpt_hdr_backup ) ;
2020-04-30 13:12:55 +00:00
// Parse GPT.
LIST_INIT ( gpt_parsed ) ;
2021-03-17 07:08:34 +00:00
for ( u32 i = 0 ; i < gpt - > header . num_part_ents ; i + + )
2020-04-30 13:12:55 +00:00
{
emmc_part_t * part = ( emmc_part_t * ) calloc ( sizeof ( emmc_part_t ) , 1 ) ;
2021-03-17 07:08:34 +00:00
if ( gpt - > entries [ i ] . lba_start < gpt - > header . first_use_lba )
2020-04-30 13:12:55 +00:00
continue ;
part - > index = i ;
2021-03-17 07:08:34 +00:00
part - > lba_start = gpt - > entries [ i ] . lba_start ;
part - > lba_end = gpt - > entries [ i ] . lba_end ;
2020-04-30 13:12:55 +00:00
// ASCII conversion. Copy only the LSByte of the UTF-16LE name.
for ( u32 j = 0 ; j < 36 ; j + + )
2021-03-17 07:08:34 +00:00
part - > name [ j ] = gpt - > entries [ i ] . name [ j ] ;
2020-04-30 13:12:55 +00:00
part - > name [ 35 ] = 0 ;
list_append ( & gpt_parsed , & part - > link ) ;
}
2021-03-17 07:20:01 +00:00
// Set FAT and emuMMC partitions.
u32 mbr_idx = 1 ;
bool found_hos_data = false ;
2020-04-30 13:12:55 +00:00
LIST_FOREACH_ENTRY ( emmc_part_t , part , & gpt_parsed , link )
{
2021-03-17 07:20:01 +00:00
// FatFS simple GPT found a fat partition, set it.
if ( sd_fs . part_type & & ! part - > index )
2020-04-30 13:12:55 +00:00
{
2021-03-17 07:20:01 +00:00
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 ] . size_sct = ( part - > lba_end - part - > lba_start + 1 ) ;
2020-04-30 13:12:55 +00:00
}
2021-03-17 07:20:01 +00:00
// FatFS simple GPT didn't find a fat partition as the first one.
if ( ! sd_fs . part_type & & ! found_hos_data & & ! strcmp ( part - > name , " hos_data " ) )
{
mbr [ 1 ] . partitions [ 0 ] . type = 0xC ;
mbr [ 1 ] . partitions [ 0 ] . start_sct = part - > lba_start ;
mbr [ 1 ] . partitions [ 0 ] . size_sct = ( part - > lba_end - part - > lba_start + 1 ) ;
found_hos_data = true ;
}
// Set up to max 2 emuMMC partitions.
2020-04-30 13:12:55 +00:00
if ( ! strcmp ( part - > name , " emummc " ) | | ! strcmp ( part - > name , " emummc2 " ) )
{
mbr [ 1 ] . partitions [ mbr_idx ] . type = 0xE0 ;
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_idx + + ;
}
2021-03-17 07:20:01 +00:00
// Total reached last slot.
if ( mbr_idx > = 3 )
2020-04-30 13:12:55 +00:00
break ;
}
2022-01-20 11:15:04 +00:00
emmc_gpt_free ( & gpt_parsed ) ;
2021-03-17 07:14:50 +00:00
// Set GPT protective partition.
mbr [ 1 ] . partitions [ mbr_idx ] . type = 0xEE ;
2020-04-30 13:12:55 +00:00
mbr [ 1 ] . partitions [ mbr_idx ] . start_sct = 1 ;
mbr [ 1 ] . partitions [ mbr_idx ] . size_sct = sd_storage . sec_cnt - 1 ;
// Check for differences.
2022-05-08 02:59:32 +00:00
bool hybrid_mbr_changed = false ;
2020-04-30 13:12:55 +00:00
for ( u32 i = 1 ; i < 4 ; i + + )
{
if ( ( mbr [ 0 ] . partitions [ i ] . type ! = mbr [ 1 ] . partitions [ i ] . type ) | |
( mbr [ 0 ] . partitions [ i ] . start_sct ! = mbr [ 1 ] . partitions [ i ] . start_sct ) | |
( mbr [ 0 ] . partitions [ i ] . size_sct ! = mbr [ 1 ] . partitions [ i ] . size_sct ) )
{
2022-05-08 02:59:32 +00:00
hybrid_mbr_changed = true ;
2020-04-30 13:12:55 +00:00
break ;
}
}
2022-05-08 02:59:32 +00:00
// Check for secret MBR attributes.
bool has_mbr_attributes = false ;
if ( gpt - > entries [ 0 ] . part_guid [ 7 ] )
has_mbr_attributes = true ;
if ( ! hybrid_mbr_changed & & ! has_mbr_attributes )
2020-04-30 13:12:55 +00:00
{
lv_label_set_text ( lbl_status , " #96FF00 Warning:# The Hybrid MBR needs no change!# " ) ;
2022-05-08 02:59:32 +00:00
free ( gpt ) ;
2020-04-30 13:12:55 +00:00
goto out ;
}
2021-10-01 12:45:25 +00:00
char * txt_buf = malloc ( SZ_16K ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Current MBR info.
2020-04-30 13:12:55 +00:00
s_printf ( txt_buf , " #00DDFF Current MBR Layout:# \n " ) ;
s_printf ( txt_buf + strlen ( txt_buf ) ,
" Partition 0 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 1 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 2 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 3 - Type: %02x, Start: %08x, Size: %08x \n \n " ,
mbr [ 0 ] . partitions [ 0 ] . type , mbr [ 0 ] . partitions [ 0 ] . start_sct , mbr [ 0 ] . partitions [ 0 ] . size_sct ,
mbr [ 0 ] . partitions [ 1 ] . type , mbr [ 0 ] . partitions [ 1 ] . start_sct , mbr [ 0 ] . partitions [ 1 ] . size_sct ,
mbr [ 0 ] . partitions [ 2 ] . type , mbr [ 0 ] . partitions [ 2 ] . start_sct , mbr [ 0 ] . partitions [ 2 ] . size_sct ,
mbr [ 0 ] . partitions [ 3 ] . type , mbr [ 0 ] . partitions [ 3 ] . start_sct , mbr [ 0 ] . partitions [ 3 ] . size_sct ) ;
2022-05-16 10:28:38 +00:00
// New MBR info.
2020-04-30 13:12:55 +00:00
s_printf ( txt_buf + strlen ( txt_buf ) , " #00DDFF New MBR Layout:# \n " ) ;
s_printf ( txt_buf + strlen ( txt_buf ) ,
" Partition 0 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 1 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 2 - Type: %02x, Start: %08x, Size: %08x \n "
" Partition 3 - Type: %02x, Start: %08x, Size: %08x " ,
mbr [ 1 ] . partitions [ 0 ] . type , mbr [ 1 ] . partitions [ 0 ] . start_sct , mbr [ 1 ] . partitions [ 0 ] . 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 [ 3 ] . type , mbr [ 1 ] . partitions [ 3 ] . start_sct , mbr [ 1 ] . partitions [ 3 ] . size_sct ) ;
lv_label_set_text ( lbl_status , txt_buf ) ;
lv_label_set_style ( lbl_status , & monospace_text ) ;
free ( txt_buf ) ;
lbl_status = lv_label_create ( mbox , NULL ) ;
lv_label_set_recolor ( lbl_status , true ) ;
lv_label_set_align ( lbl_status , LV_LABEL_ALIGN_CENTER ) ;
lv_label_set_text ( lbl_status ,
" #FF8000 Warning: Do you really want to continue?!# \n \n "
" Press #FF8000 POWER# to Continue. \n Press #FF8000 VOL# to abort. " ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
manual_system_maintenance ( true ) ;
if ( btn_wait ( ) & BTN_POWER )
{
sd_mount ( ) ;
2022-05-08 02:59:32 +00:00
// Write MBR.
if ( hybrid_mbr_changed )
sdmmc_storage_write ( & sd_storage , 0 , 1 , & mbr [ 1 ] ) ;
// Fix MBR secret attributes.
if ( has_mbr_attributes )
{
2022-05-16 10:28:38 +00:00
// Clear secret attributes.
2022-05-08 02:59:32 +00:00
gpt - > entries [ 0 ] . part_guid [ 7 ] = 0 ;
2022-05-16 10:28:38 +00:00
// Fix CRC32s.
2022-05-08 02:59:32 +00:00
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 . crc32 = 0 ; // Set to 0 for calculation.
gpt - > header . crc32 = crc32_calc ( 0 , ( const u8 * ) & gpt - > header , gpt - > header . size ) ;
gpt_hdr_backup . part_ents_crc32 = gpt - > 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.
u32 aligned_entries_size = ALIGN ( entries_size , 512 ) ;
sdmmc_storage_write ( & sd_storage , gpt - > header . my_lba , ( sizeof ( gpt_header_t ) + aligned_entries_size ) > > 9 , gpt ) ;
// Write backup GPT partition table.
sdmmc_storage_write ( & sd_storage , gpt_hdr_backup . part_ent_lba , aligned_entries_size > > 9 , gpt - > entries ) ;
// Write backup GPT header.
sdmmc_storage_write ( & sd_storage , gpt_hdr_backup . my_lba , 1 , & gpt_hdr_backup ) ;
}
2020-06-13 15:32:40 +00:00
sd_unmount ( ) ;
2022-05-08 02:59:32 +00:00
2020-04-30 13:12:55 +00:00
lv_label_set_text ( lbl_status , " #96FF00 The new Hybrid MBR was written successfully!# " ) ;
}
else
lv_label_set_text ( lbl_status , " #FFDD00 Warning: The Hybrid MBR Fix was canceled!# " ) ;
2022-05-08 02:59:32 +00:00
free ( gpt ) ;
2020-04-30 13:12:55 +00:00
out :
lv_mbox_add_btns ( mbox , mbox_btn_map , mbox_action ) ;
lv_obj_align ( mbox , NULL , LV_ALIGN_CENTER , 0 , 0 ) ;
lv_obj_set_top ( mbox , true ) ;
return LV_RES_OK ;
}
lv_res_t create_window_partition_manager ( lv_obj_t * btn )
{
lv_obj_t * win = nyx_create_standard_window ( SYMBOL_SD " Partition Manager " ) ;
lv_win_add_btn ( win , NULL , SYMBOL_MODULES_ALT " Fix Hybrid MBR " , _action_fix_mbr ) ;
static lv_style_t bar_hos_bg , bar_emu_bg , bar_l4t_bg , bar_and_bg ;
static lv_style_t bar_hos_ind , bar_emu_ind , bar_l4t_ind , bar_and_ind ;
static lv_style_t bar_hos_btn , bar_emu_btn , bar_l4t_btn , bar_and_btn ;
static lv_style_t sep_emu_bg , sep_l4t_bg , sep_and_bg ;
2022-05-16 10:28:38 +00:00
// Set HOS bar styles.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_hos_bg , lv_theme_get_current ( ) - > bar . bg ) ;
bar_hos_bg . body . main_color = LV_COLOR_HEX ( 0x4A8000 ) ;
bar_hos_bg . body . grad_color = bar_hos_bg . body . main_color ;
lv_style_copy ( & bar_hos_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_hos_ind . body . main_color = LV_COLOR_HEX ( 0x96FF00 ) ;
bar_hos_ind . body . grad_color = bar_hos_ind . body . main_color ;
lv_style_copy ( & bar_hos_btn , lv_theme_get_current ( ) - > slider . knob ) ;
bar_hos_btn . body . main_color = LV_COLOR_HEX ( 0x77CC00 ) ;
bar_hos_btn . body . grad_color = bar_hos_btn . body . main_color ;
2022-05-16 10:28:38 +00:00
// Set eMUMMC bar styles.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_emu_bg , lv_theme_get_current ( ) - > bar . bg ) ;
bar_emu_bg . body . main_color = LV_COLOR_HEX ( 0x940F00 ) ;
bar_emu_bg . body . grad_color = bar_emu_bg . body . main_color ;
lv_style_copy ( & bar_emu_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_emu_ind . body . main_color = LV_COLOR_HEX ( 0xFF3C28 ) ;
bar_emu_ind . body . grad_color = bar_emu_ind . body . main_color ;
lv_style_copy ( & bar_emu_btn , lv_theme_get_current ( ) - > slider . knob ) ;
bar_emu_btn . body . main_color = LV_COLOR_HEX ( 0xB31200 ) ;
bar_emu_btn . body . grad_color = bar_emu_btn . body . main_color ;
lv_style_copy ( & sep_emu_bg , lv_theme_get_current ( ) - > cont ) ;
sep_emu_bg . body . main_color = LV_COLOR_HEX ( 0xFF3C28 ) ;
sep_emu_bg . body . grad_color = sep_emu_bg . body . main_color ;
sep_emu_bg . body . radius = 0 ;
2022-05-16 10:28:38 +00:00
// Set L4T bar styles.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_l4t_bg , lv_theme_get_current ( ) - > bar . bg ) ;
bar_l4t_bg . body . main_color = LV_COLOR_HEX ( 0x006E80 ) ;
bar_l4t_bg . body . grad_color = bar_l4t_bg . body . main_color ;
lv_style_copy ( & bar_l4t_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_l4t_ind . body . main_color = LV_COLOR_HEX ( 0x00DDFF ) ;
bar_l4t_ind . body . grad_color = bar_l4t_ind . body . main_color ;
lv_style_copy ( & bar_l4t_btn , lv_theme_get_current ( ) - > slider . knob ) ;
bar_l4t_btn . body . main_color = LV_COLOR_HEX ( 0x00B1CC ) ;
bar_l4t_btn . body . grad_color = bar_l4t_btn . body . main_color ;
lv_style_copy ( & sep_l4t_bg , & sep_emu_bg ) ;
sep_l4t_bg . body . main_color = LV_COLOR_HEX ( 0x00DDFF ) ;
sep_l4t_bg . body . grad_color = sep_l4t_bg . body . main_color ;
2022-05-16 10:28:38 +00:00
// Set Android bar styles.
2020-04-30 13:12:55 +00:00
lv_style_copy ( & bar_and_bg , lv_theme_get_current ( ) - > bar . bg ) ;
bar_and_bg . body . main_color = LV_COLOR_HEX ( 0x804000 ) ;
bar_and_bg . body . grad_color = bar_and_bg . body . main_color ;
lv_style_copy ( & bar_and_ind , lv_theme_get_current ( ) - > bar . indic ) ;
bar_and_ind . body . main_color = LV_COLOR_HEX ( 0xFF8000 ) ;
bar_and_ind . body . grad_color = bar_and_ind . body . main_color ;
lv_style_copy ( & bar_and_btn , lv_theme_get_current ( ) - > slider . knob ) ;
bar_and_btn . body . main_color = LV_COLOR_HEX ( 0xCC6600 ) ;
bar_and_btn . body . grad_color = bar_and_btn . body . main_color ;
lv_style_copy ( & sep_and_bg , & sep_emu_bg ) ;
sep_and_bg . body . main_color = LV_COLOR_HEX ( 0xFF8000 ) ;
sep_and_bg . body . grad_color = sep_and_bg . body . main_color ;
lv_obj_t * sep = lv_label_create ( win , NULL ) ;
lv_label_set_static_text ( sep , " " ) ;
lv_obj_align ( sep , NULL , LV_ALIGN_IN_TOP_MID , 0 , 0 ) ;
// Create container to keep content inside.
lv_obj_t * h1 = lv_cont_create ( win , NULL ) ;
lv_obj_set_size ( h1 , LV_HOR_RES - ( LV_DPI * 8 / 10 ) , LV_VER_RES - LV_DPI ) ;
if ( ! sd_mount ( ) )
{
lv_obj_t * lbl = lv_label_create ( h1 , NULL ) ;
lv_label_set_text ( lbl , " #FFDD00 Failed to init SD!# " ) ;
return LV_RES_OK ;
}
memset ( & part_info , 0 , sizeof ( partition_ctxt_t ) ) ;
create_mbox_check_files_total_size ( ) ;
2021-10-01 12:45:25 +00:00
char * txt_buf = malloc ( SZ_8K ) ;
2020-04-30 13:12:55 +00:00
part_info . total_sct = sd_storage . sec_cnt ;
2021-05-11 06:57:29 +00:00
// Align down total size to ensure alignment of all partitions after HOS one.
2022-05-16 10:28:38 +00:00
part_info . alignment = part_info . total_sct - ALIGN_DOWN ( part_info . total_sct , AU_ALIGN_SECTORS ) ;
2021-05-11 06:57:29 +00:00
part_info . total_sct - = part_info . alignment ;
2022-05-16 10:28:38 +00:00
u32 extra_sct = AU_ALIGN_SECTORS + 0x400000 ; // Reserved 16MB alignment for FAT partition + 2GB.
2020-04-30 13:12:55 +00:00
2020-06-14 10:07:21 +00:00
// Set initial HOS partition size, so the correct cluster size can be selected.
part_info . hos_size = ( part_info . total_sct > > 11 ) - 16 ; // Important if there's no slider change.
2022-01-20 12:11:36 +00:00
// Check if eMMC should be 64GB (Aula).
part_info . emmc_is_64gb = fuse_read_hw_type ( ) = = FUSE_NX_HW_TYPE_AULA ;
2020-04-30 13:12:55 +00:00
// Read current MBR.
mbr_t mbr = { 0 } ;
sdmmc_storage_read ( & sd_storage , 0 , 1 , & mbr ) ;
u32 bar_hos_size = lv_obj_get_width ( h1 ) ;
u32 bar_emu_size = 0 ;
u32 bar_l4t_size = 0 ;
u32 bar_and_size = 0 ;
lv_obj_t * lbl = lv_label_create ( h1 , NULL ) ;
2021-09-26 09:16:04 +00:00
lv_label_set_recolor ( lbl , true ) ;
lv_label_set_text ( lbl , " Choose #FFDD00 new# partition layout: " ) ;
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Create disk layout blocks.
// HOS partition block.
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_hos = lv_bar_create ( h1 , NULL ) ;
lv_obj_set_size ( bar_hos , bar_hos_size , LV_DPI / 2 ) ;
lv_bar_set_range ( bar_hos , 0 , 1 ) ;
lv_bar_set_value ( bar_hos , 1 ) ;
lv_bar_set_style ( bar_hos , LV_BAR_STYLE_INDIC , & bar_hos_ind ) ;
lv_obj_align ( bar_hos , lbl , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 6 ) ;
part_info . bar_hos = bar_hos ;
2022-05-16 10:28:38 +00:00
// emuMMC partition block.
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_emu = lv_bar_create ( h1 , bar_hos ) ;
lv_obj_set_size ( bar_emu , bar_emu_size , LV_DPI / 2 ) ;
lv_bar_set_style ( bar_emu , LV_BAR_STYLE_INDIC , & bar_emu_ind ) ;
lv_obj_align ( bar_emu , bar_hos , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
part_info . bar_emu = bar_emu ;
2022-05-16 10:28:38 +00:00
// L4T partition block.
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_l4t = lv_bar_create ( h1 , bar_hos ) ;
lv_obj_set_size ( bar_l4t , bar_l4t_size , LV_DPI / 2 ) ;
lv_bar_set_style ( bar_l4t , LV_BAR_STYLE_INDIC , & bar_l4t_ind ) ;
lv_obj_align ( bar_l4t , bar_emu , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
part_info . bar_l4t = bar_l4t ;
2022-05-16 10:28:38 +00:00
// Android partition block.
2020-04-30 13:12:55 +00:00
lv_obj_t * bar_and = lv_bar_create ( h1 , bar_hos ) ;
lv_obj_set_size ( bar_and , bar_and_size , LV_DPI / 2 ) ;
lv_bar_set_style ( bar_and , LV_BAR_STYLE_INDIC , & bar_and_ind ) ;
lv_obj_align ( bar_and , bar_l4t , LV_ALIGN_OUT_RIGHT_MID , 0 , 0 ) ;
part_info . bar_and = bar_and ;
2022-05-16 10:28:38 +00:00
// HOS partition block.
2020-04-30 13:12:55 +00:00
lv_obj_t * sep_emu = lv_cont_create ( h1 , NULL ) ;
lv_cont_set_fit ( sep_emu , false , false ) ;
lv_obj_set_size ( sep_emu , 0 , LV_DPI / 2 ) ; // 8.
lv_obj_set_style ( sep_emu , & sep_emu_bg ) ;
lv_obj_align ( sep_emu , bar_hos , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
part_info . sep_emu = sep_emu ;
2022-05-16 10:28:38 +00:00
// Create disk layout blending separators.
2020-04-30 13:12:55 +00:00
lv_obj_t * sep_l4t = lv_cont_create ( h1 , sep_emu ) ;
lv_obj_set_style ( sep_l4t , & sep_l4t_bg ) ;
lv_obj_align ( sep_l4t , bar_emu , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
part_info . sep_l4t = sep_l4t ;
lv_obj_t * sep_and = lv_cont_create ( h1 , sep_emu ) ;
lv_obj_set_style ( sep_and , & sep_and_bg ) ;
lv_obj_align ( sep_and , bar_l4t , LV_ALIGN_OUT_RIGHT_MID , - 4 , 0 ) ;
part_info . sep_and = sep_and ;
2022-05-16 10:28:38 +00:00
// Create slider type labels.
2020-04-30 13:12:55 +00:00
lv_obj_t * lbl_hos = lv_label_create ( h1 , NULL ) ;
lv_label_set_recolor ( lbl_hos , true ) ;
lv_label_set_static_text ( lbl_hos , " #96FF00 " SYMBOL_DOT " HOS (FAT32):# " ) ;
lv_obj_align ( lbl_hos , bar_hos , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 2 ) ;
lv_obj_t * lbl_emu = lv_label_create ( h1 , lbl_hos ) ;
lv_label_set_static_text ( lbl_emu , " #FF3C28 " SYMBOL_DOT " emuMMC (RAW):# " ) ;
lv_obj_align ( lbl_emu , lbl_hos , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 ) ;
lv_obj_t * lbl_l4t = lv_label_create ( h1 , lbl_hos ) ;
lv_label_set_static_text ( lbl_l4t , " #00DDFF " SYMBOL_DOT " Linux (EXT4):# " ) ;
lv_obj_align ( lbl_l4t , lbl_emu , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 ) ;
lv_obj_t * lbl_and = lv_label_create ( h1 , lbl_hos ) ;
lv_label_set_static_text ( lbl_and , " #FF8000 " SYMBOL_DOT " Android (USER):# " ) ;
lv_obj_align ( lbl_and , lbl_l4t , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 ) ;
2022-05-16 10:28:38 +00:00
// Create HOS size slider. Non-interactive.
2020-04-30 13:12:55 +00:00
lv_obj_t * slider_bar_hos = lv_bar_create ( h1 , NULL ) ;
lv_obj_set_size ( slider_bar_hos , LV_DPI * 7 , LV_DPI * 3 / 17 ) ;
2022-05-16 10:28:38 +00:00
lv_bar_set_range ( slider_bar_hos , 0 , ( part_info . total_sct - AU_ALIGN_SECTORS ) / SECTORS_PER_GB ) ;
lv_bar_set_value ( slider_bar_hos , ( part_info . total_sct - AU_ALIGN_SECTORS ) / SECTORS_PER_GB ) ;
2020-04-30 13:12:55 +00:00
lv_bar_set_style ( slider_bar_hos , LV_SLIDER_STYLE_BG , & bar_hos_bg ) ;
lv_bar_set_style ( slider_bar_hos , LV_SLIDER_STYLE_INDIC , & bar_hos_ind ) ;
lv_obj_align ( slider_bar_hos , lbl_hos , LV_ALIGN_OUT_RIGHT_MID , LV_DPI * 6 / 4 , 0 ) ;
part_info . slider_bar_hos = slider_bar_hos ;
2022-05-16 10:28:38 +00:00
// Create emuMMC size slider.
2020-04-30 13:12:55 +00:00
lv_obj_t * slider_emu = lv_slider_create ( h1 , NULL ) ;
lv_obj_set_size ( slider_emu , LV_DPI * 7 , LV_DPI / 3 ) ;
2021-02-06 02:10:02 +00:00
lv_slider_set_range ( slider_emu , 0 , 20 ) ;
2020-04-30 13:12:55 +00:00
lv_slider_set_value ( slider_emu , 0 ) ;
lv_slider_set_style ( slider_emu , LV_SLIDER_STYLE_BG , & bar_emu_bg ) ;
lv_slider_set_style ( slider_emu , LV_SLIDER_STYLE_INDIC , & bar_emu_ind ) ;
lv_slider_set_style ( slider_emu , LV_SLIDER_STYLE_KNOB , & bar_emu_btn ) ;
lv_obj_align ( slider_emu , slider_bar_hos , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 + 5 ) ;
lv_slider_set_action ( slider_emu , _action_slider_emu ) ;
part_info . slider_emu = slider_bar_hos ;
2022-05-16 10:28:38 +00:00
// Create L4T size slider.
2020-04-30 13:12:55 +00:00
lv_obj_t * slider_l4t = lv_slider_create ( h1 , NULL ) ;
lv_obj_set_size ( slider_l4t , LV_DPI * 7 , LV_DPI / 3 ) ;
2022-05-16 10:28:38 +00:00
lv_slider_set_range ( slider_l4t , 0 , ( part_info . total_sct - extra_sct ) / SECTORS_PER_GB ) ;
2020-04-30 13:12:55 +00:00
lv_slider_set_value ( slider_l4t , 0 ) ;
lv_slider_set_style ( slider_l4t , LV_SLIDER_STYLE_BG , & bar_l4t_bg ) ;
lv_slider_set_style ( slider_l4t , LV_SLIDER_STYLE_INDIC , & bar_l4t_ind ) ;
lv_slider_set_style ( slider_l4t , LV_SLIDER_STYLE_KNOB , & bar_l4t_btn ) ;
lv_obj_align ( slider_l4t , slider_emu , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 - 3 ) ;
lv_slider_set_action ( slider_l4t , _action_slider_l4t ) ;
part_info . slider_l4t = slider_l4t ;
2022-05-16 10:28:38 +00:00
// Create Android size slider.
2020-04-30 13:12:55 +00:00
lv_obj_t * slider_and = lv_slider_create ( h1 , NULL ) ;
lv_obj_set_size ( slider_and , LV_DPI * 7 , LV_DPI / 3 ) ;
2022-05-16 10:28:38 +00:00
lv_slider_set_range ( slider_and , 0 , ( part_info . total_sct - extra_sct ) / SECTORS_PER_GB - 4 ) ; // Subtract android reserved size.
2020-04-30 13:12:55 +00:00
lv_slider_set_value ( slider_and , 0 ) ;
lv_slider_set_style ( slider_and , LV_SLIDER_STYLE_BG , & bar_and_bg ) ;
lv_slider_set_style ( slider_and , LV_SLIDER_STYLE_INDIC , & bar_and_ind ) ;
lv_slider_set_style ( slider_and , LV_SLIDER_STYLE_KNOB , & bar_and_btn ) ;
lv_obj_align ( slider_and , slider_l4t , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 - 3 ) ;
lv_slider_set_action ( slider_and , _action_slider_and ) ;
part_info . slider_and = slider_and ;
2022-05-16 10:28:38 +00:00
// Create HOS size label.
2020-04-30 13:12:55 +00:00
lv_obj_t * lbl_sl_hos = lv_label_create ( h1 , NULL ) ;
lv_label_set_recolor ( lbl_sl_hos , true ) ;
2022-05-16 10:28:38 +00:00
s_printf ( txt_buf , " #96FF00 %d GiB# " , ( part_info . total_sct - AU_ALIGN_SECTORS ) > > 11 > > 10 ) ;
2020-04-30 13:12:55 +00:00
lv_label_set_text ( lbl_sl_hos , txt_buf ) ;
lv_obj_align ( lbl_sl_hos , slider_bar_hos , LV_ALIGN_OUT_RIGHT_MID , LV_DPI * 4 / 7 , 0 ) ;
part_info . lbl_hos = lbl_sl_hos ;
2022-05-16 10:28:38 +00:00
// Create emuMMC size label.
2020-04-30 13:12:55 +00:00
lv_obj_t * lbl_sl_emu = lv_label_create ( h1 , lbl_sl_hos ) ;
lv_label_set_text ( lbl_sl_emu , " #FF3C28 0 GiB# " ) ;
lv_obj_align ( lbl_sl_emu , lbl_sl_hos , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 ) ;
part_info . lbl_emu = lbl_sl_emu ;
2022-05-16 10:28:38 +00:00
// Create L4T size label.
2020-04-30 13:12:55 +00:00
lv_obj_t * lbl_sl_l4t = lv_label_create ( h1 , lbl_sl_hos ) ;
lv_label_set_text ( lbl_sl_l4t , " #00DDFF 0 GiB# " ) ;
lv_obj_align ( lbl_sl_l4t , lbl_sl_emu , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 ) ;
part_info . lbl_l4t = lbl_sl_l4t ;
2022-05-16 10:28:38 +00:00
// Create Android size label.
2020-04-30 13:12:55 +00:00
lv_obj_t * lbl_sl_and = lv_label_create ( h1 , lbl_sl_hos ) ;
lv_label_set_text ( lbl_sl_and , " #FF8000 0 GiB# " ) ;
lv_obj_align ( lbl_sl_and , lbl_sl_l4t , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 3 ) ;
part_info . lbl_and = lbl_sl_and ;
2022-05-16 10:28:38 +00:00
// Set partition manager notes.
2020-04-30 13:12:55 +00:00
lv_obj_t * lbl_notes = lv_label_create ( h1 , NULL ) ;
lv_label_set_recolor ( lbl_notes , true ) ;
lv_label_set_static_text ( lbl_notes ,
" Note 1: Only up to #C7EA46 1GB# can be backed up. If more, you will be asked to back them manually at the next step. \n "
2021-02-06 02:10:02 +00:00
" Note 2: Resized emuMMC formats the USER partition. A save data manager can be used to move them over. \n "
" Note 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found. \n "
" Note 4: The installation folder is #C7EA46 switchroot/install#. Linux uses #C7EA46 l4t.XX# and Android uses #C7EA46 twrp.img# and #C7EA46 tegra210-icosa.dtb#. " ) ;
2020-04-30 13:12:55 +00:00
lv_label_set_style ( lbl_notes , & hint_small_style ) ;
lv_obj_align ( lbl_notes , lbl_and , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , LV_DPI / 5 ) ;
2022-05-16 10:28:38 +00:00
// Create UMS button.
2020-04-30 13:12:55 +00:00
lv_obj_t * btn1 = lv_btn_create ( h1 , NULL ) ;
lv_obj_t * label_btn = lv_label_create ( btn1 , NULL ) ;
lv_btn_set_fit ( btn1 , true , true ) ;
lv_label_set_static_text ( label_btn , SYMBOL_USB " SD UMS " ) ;
lv_obj_align ( btn1 , h1 , LV_ALIGN_IN_TOP_LEFT , 0 , LV_DPI * 5 ) ;
lv_btn_set_action ( btn1 , LV_BTN_ACTION_CLICK , _action_part_manager_ums_sd ) ;
2022-05-16 10:28:38 +00:00
// Create Flash Linux button.
2021-01-06 19:29:18 +00:00
btn_flash_l4t = lv_btn_create ( h1 , NULL ) ;
2021-01-03 12:51:48 +00:00
lv_obj_t * label_btn2 = lv_label_create ( btn_flash_l4t , NULL ) ;
lv_btn_set_fit ( btn_flash_l4t , true , true ) ;
2020-04-30 13:12:55 +00:00
lv_label_set_static_text ( label_btn2 , SYMBOL_DOWNLOAD " Flash Linux " ) ;
2021-01-03 12:51:48 +00:00
lv_obj_align ( btn_flash_l4t , btn1 , LV_ALIGN_OUT_RIGHT_MID , LV_DPI / 3 , 0 ) ;
lv_btn_set_action ( btn_flash_l4t , LV_BTN_ACTION_CLICK , _action_check_flash_linux ) ;
2020-04-30 13:12:55 +00:00
2021-01-03 12:51:48 +00:00
// Disable Flash Linux button if partition not found.
u32 size_sct = _get_available_l4t_partition ( ) ;
if ( ! l4t_flash_ctxt . offset_sct | | ! size_sct | | size_sct < 0x800000 )
{
lv_obj_set_click ( btn_flash_l4t , false ) ;
lv_btn_set_state ( btn_flash_l4t , LV_BTN_STATE_INA ) ;
}
2022-05-16 10:28:38 +00:00
// Create Flash Android button.
2021-01-03 12:51:48 +00:00
btn_flash_android = lv_btn_create ( h1 , NULL ) ;
label_btn = lv_label_create ( btn_flash_android , NULL ) ;
lv_btn_set_fit ( btn_flash_android , true , true ) ;
2020-04-30 13:12:55 +00:00
lv_label_set_static_text ( label_btn , SYMBOL_DOWNLOAD " Flash Android " ) ;
2021-01-03 12:51:48 +00:00
lv_obj_align ( btn_flash_android , btn_flash_l4t , LV_ALIGN_OUT_RIGHT_MID , LV_DPI / 3 , 0 ) ;
lv_btn_set_action ( btn_flash_android , LV_BTN_ACTION_CLICK , _action_flash_android ) ;
// Disable Flash Android button if partition not found.
if ( ! _get_available_android_partition ( ) )
{
lv_obj_set_click ( btn_flash_android , false ) ;
lv_btn_set_state ( btn_flash_android , LV_BTN_STATE_INA ) ;
}
2020-04-30 13:12:55 +00:00
2022-05-16 10:28:38 +00:00
// Create next step button.
2020-04-30 13:12:55 +00:00
btn1 = lv_btn_create ( h1 , NULL ) ;
label_btn = lv_label_create ( btn1 , NULL ) ;
lv_btn_set_fit ( btn1 , true , true ) ;
lv_label_set_static_text ( label_btn , SYMBOL_SD " Next Step " ) ;
lv_obj_align ( btn1 , h1 , LV_ALIGN_IN_TOP_RIGHT , 0 , LV_DPI * 5 ) ;
lv_btn_set_action ( btn1 , LV_BTN_ACTION_CLICK , _create_mbox_partitioning_next ) ;
free ( txt_buf ) ;
2020-06-13 15:32:40 +00:00
sd_unmount ( ) ;
2020-04-30 13:12:55 +00:00
return LV_RES_OK ;
}