Compare commits

...

21 Commits

Author SHA1 Message Date
CTCaer
f085cbc4a4 Bump hekate to v5.2.1 and Nyx to v0.9.1 2020-05-05 20:40:22 +03:00
CTCaer
d8b6aa3831 nyx: Correct the error message for format 2020-05-05 19:28:34 +03:00
CTCaer
3e5ef39686 nyx: Fix emummc slider when there's not enough space 2020-05-05 19:28:15 +03:00
CTCaer
bc7c65447d nyx: Add start clearing for ext4 partitions 2020-05-05 19:27:45 +03:00
CTCaer
a91378b9c1 nyx: Allow always writeable emmc via config
The key is `umsemmcrw` and resides in nyx.ini
2020-05-05 19:26:10 +03:00
CTCaer
7543234401 emummc: Fix emupath folder and add more checks
The checks are checking if the emuMMC was found. If it didn't  and error will be show.
2020-05-05 19:23:31 +03:00
CTCaer
5b91c54936 fatfs: Backport some fixes 2020-05-05 19:21:07 +03:00
CTCaer
322280757f nyx: Fix time offset parsing 2020-05-05 19:20:04 +03:00
CTCaer
b1636fbb96 nyx: Add unsaved config changes pop up 2020-05-05 19:19:12 +03:00
CTCaer
cc18a7b146 nyx: Allow changing Date/Time via tickers 2020-05-05 19:17:29 +03:00
CTCaer
5fe84a78ac rtc: Remove custom encoding 2020-05-05 19:16:16 +03:00
CTCaer
822e0dcd98 Various small fixes 2020-05-05 19:11:39 +03:00
CTCaer
a6be3714a3 ums: Update Nyx status bar during UMS 2020-05-05 19:02:01 +03:00
CTCaer
f56d1bad04 nyx: Allow hue icons from section names 2020-05-05 19:01:08 +03:00
CTCaer
c7ab404fc1 exo: Fix prodinfo blanking overriding 2020-05-05 18:58:53 +03:00
CTCaer
e8f41a03f3 res: Fix name of colorized lakka icon 2020-05-03 02:52:51 +03:00
CTCaer
8edc9971f9 nyx: Refactor launch icon colorization
The Switch and Payload icons will be colorized by default, because they are system icons.

Users can still replace them with icons named `icon_switch_custom.bmp` and `icon_payload_custom.bmp` that do not get colorized.
2020-05-03 01:57:15 +03:00
CTCaer
54c36a7e46 Merge pull request #409 from NicholeMattera/master
Added support to have launch icons match theme color.
2020-05-03 01:16:59 +03:00
Nichole Mattera
afb820202d Small fix to make sure icon_path is long enough. 2020-05-02 16:34:06 -04:00
Nichole Mattera
0ce973966f Add support for launch icons changing color with theme. 2020-05-02 16:16:38 -04:00
CTCaer
da8c040c08 hos: Fix exosphere.ini parsing 2020-05-01 20:30:17 +03:00
39 changed files with 548 additions and 221 deletions

View File

@@ -67,6 +67,7 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
| timeoff=100 | Sets time offset in HEX. Must be in HOS epoch format |
| homescreen=0 | Sets home screen. 0: Home menu, 1: All configs (merges Launch and More configs), 2: Launch, 3: More Configs. |
| verification=1 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and mostly reliable), 2: Full (sha256 based, slow and 100% reliable). |
| umsemmcrw=1 | 1: eMMC/emuMMC UMS will be mounted as writable by default. |
### Boot entry key/value combinations:

View File

@@ -1,11 +1,11 @@
# IPL Version.
BLVERSION_MAJOR := 5
BLVERSION_MINOR := 2
BLVERSION_HOTFX := 0
BLVERSION_HOTFX := 1
BLVERSION_RSVD := 0
# Nyx Version.
NYXVERSION_MAJOR := 0
NYXVERSION_MINOR := 9
NYXVERSION_HOTFX := 0
NYXVERSION_HOTFX := 1
NYXVERSION_RSVD := 0

View File

@@ -39,6 +39,7 @@
#include "../soc/smmu.h"
#include "../soc/t210.h"
#include "../storage/emummc.h"
#include "../storage/mbr_gpt.h"
#include "../storage/nx_emmc.h"
#include "../storage/nx_sd.h"
#include "../storage/sdmmc.h"
@@ -51,8 +52,7 @@ extern hekate_config h_cfg;
#define DPRINTF(...)
#define EHPRINTFARGS(text, args...) \
({ display_backlight_brightness(h_cfg.backlight, 1000); \
gfx_con.mute = false; \
({ gfx_con.mute = false; \
gfx_printf("%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC); })
#define PKG2_LOAD_ADDR 0xA9800000
@@ -103,8 +103,6 @@ static void _hos_crit_error(const char *text)
{
gfx_con.mute = false;
gfx_printf("%k%s%k\n", 0xFFFF0000, text, 0xFFCCCCCC);
display_backlight_brightness(h_cfg.backlight, 1000);
}
static void _se_lock(bool lock_se)
@@ -183,15 +181,42 @@ void _sysctr0_reset()
SYSCTR0(SYSCTR0_COUNTERID11) = 0;
}
bool hos_eks_rw_try(u8 *buf, bool write)
{
mbr_t *mbr = (mbr_t *)buf;
for (u32 i = 0; i < 3; i++)
{
if (!write)
{
if (sdmmc_storage_read(&sd_storage, 0, 1, mbr))
{
if (mbr->partitions[0].status != 0xFF &&
mbr->partitions[0].start_sct &&
mbr->partitions[0].size_sct)
return true;
else
return false;
}
}
else
{
if (sdmmc_storage_write(&sd_storage, 0, 1, mbr))
return true;
}
}
return false;
}
void hos_eks_get()
{
// Check if EKS already found and parsed.
if (!h_cfg.eks)
{
u8 *mbr = calloc(512 , 1);
// Read EKS blob.
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
u8 *mbr = calloc(512 , 1);
if (!hos_eks_rw_try(mbr, false))
goto out;
// Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x10);
@@ -208,6 +233,7 @@ void hos_eks_get()
return;
}
out:
free(mbr);
}
}
@@ -221,12 +247,29 @@ void hos_eks_save(u32 kb)
if (key_idx > 5)
return;
bool new_eks = false;
if (!h_cfg.eks)
{
h_cfg.eks = calloc(512 , 1);
new_eks = true;
}
// If matching blob doesn't exist, create it.
if (!(h_cfg.eks->enabled & (1 << key_idx)))
{
// Read EKS blob.
u8 *mbr = calloc(512 , 1);
if (!hos_eks_rw_try(mbr, false))
{
if (new_eks)
{
free(h_cfg.eks);
h_cfg.eks = NULL;
}
goto out;
}
// Get keys.
u8 *keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10);
@@ -244,20 +287,21 @@ void hos_eks_save(u32 kb)
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].dkk, keys + 15 * 0x10, 0x10);
// Encrypt EKS.
// Encrypt EKS blob.
u8 *eks = calloc(512 , 1);
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS to SD.
u8 *mbr = calloc(512 , 1);
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
// Write EKS blob to SD.
memset(mbr, 0, 0x10);
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
hos_eks_rw_try(mbr, true);
free(eks);
free(mbr);
free(keys);
out:
free(mbr);
}
}
}
@@ -270,21 +314,25 @@ void hos_eks_clear(u32 kb)
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
if (h_cfg.eks->enabled & (1 << key_idx))
{
// Read EKS blob.
u8 *mbr = calloc(512 , 1);
if (!hos_eks_rw_try(mbr, false))
goto out;
// Disable current Master key version.
h_cfg.eks->enabled &= ~(1 << key_idx);
// Encrypt EKS.
// Encrypt EKS blob.
u8 *eks = calloc(512 , 1);
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS to SD.
u8 *mbr = calloc(512 , 1);
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
// Write EKS blob to SD.
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
hos_eks_rw_try(mbr, true);
free(eks);
out:
free(mbr);
}
}
@@ -477,8 +525,8 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
if (!ctxt->pkg1_id)
{
_hos_crit_error("Unknown pkg1 version.");
EHPRINTFARGS("%sNot yet supported HOS version!",
(emu_cfg.enabled && !h_cfg.emummc_force_disable) ? "Is emuMMC corrupt?\nOr " : "");
EHPRINTFARGS("HOS version not supported!%s",
(emu_cfg.enabled && !h_cfg.emummc_force_disable) ? "\nOr emuMMC corrupt!" : "");
goto out;
}
gfx_printf("Identified pkg1 and Keyblob %d\n\n", ctxt->pkg1_id->kb);
@@ -489,7 +537,7 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
res = 1;
out:;
out:
sdmmc_storage_end(&storage);
return res;
}
@@ -731,7 +779,10 @@ int hos_launch(ini_sec_t *cfg)
// Read package2.
u8 *bootConfigBuf = _read_emmc_pkg2(&ctxt);
if (!bootConfigBuf)
{
_hos_crit_error("Pkg2 read failed!");
return 0;
}
gfx_printf("Read pkg2\n");
@@ -839,9 +890,6 @@ int hos_launch(ini_sec_t *cfg)
gfx_printf("Rebuilt & loaded pkg2\n");
// Unmount SD card.
sd_unmount();
gfx_printf("\n%kBooting...%k\n", 0xFF96FF00, 0xFFCCCCCC);
// Clear pkg1/pkg2 keys.
@@ -896,6 +944,9 @@ int hos_launch(ini_sec_t *cfg)
if (ctxt.atmosphere && ctxt.secmon)
config_exosphere(&ctxt);
// Unmount SD card.
sd_unmount();
// Finalize MC carveout.
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_301)
mc_config_carveout();

View File

@@ -68,7 +68,7 @@ typedef struct _hos_eks_mbr_t
u32 rsvd2[3];
} hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) < 424, "HOS EKS storage bigger than MBR!");
static_assert(sizeof(hos_eks_mbr_t) == 416, "HOS EKS storage bigger than MBR!");
typedef struct _launch_ctxt_t
{

View File

@@ -223,7 +223,7 @@ static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
{
// Override key found.
ctxt->exo_cfg.cal0_blank = calloc(1, 1);
ctxt->exo_cfg.cal0_blank = calloc(sizeof(bool), 1);
if (*value == '1')
{
@@ -236,7 +236,7 @@ static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value)
{
// Override key found.
ctxt->exo_cfg.cal0_allow_writes_sys = calloc(1, 1);
ctxt->exo_cfg.cal0_allow_writes_sys = calloc(sizeof(bool), 1);
if (*value == '1')
{

View File

@@ -221,12 +221,12 @@ void config_exosphere(launch_ctxt_t *ctxt)
if (ctxt->exo_cfg.user_pmu)
exoFlags |= EXO_FLAG_USER_PMU;
// Check if exo ini value is overridden and enable prodinfo blanking.
// Enable prodinfo blanking. Check if exo ini value is overridden. If not, check if enabled in exo ini.
if ((ctxt->exo_cfg.cal0_blank && *ctxt->exo_cfg.cal0_blank)
|| (!ctxt->exo_cfg.cal0_blank && cal0_blanking))
exoFlags |= EXO_FLAG_CAL0_BLANKING;
// Check if exo ini value is overridden and allow prodinfo writes.
// Allow prodinfo writes. Check if exo ini value is overridden. If not, check if enabled in exo ini.
if ((ctxt->exo_cfg.cal0_allow_writes_sys && *ctxt->exo_cfg.cal0_allow_writes_sys)
|| (!ctxt->exo_cfg.cal0_allow_writes_sys && cal0_allow_writes_sys))
exoFlags |= EXO_FLAG_CAL0_WRITES_SYS;

View File

@@ -5630,7 +5630,7 @@ FRESULT f_mkfs (
UINT len /* Size of working buffer [byte] */
)
{
const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */
const UINT n_fats = 2; /* Number of FATs for FAT/FAT32 volume (1 or 2) */
const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */
static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */
static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */
@@ -5918,6 +5918,9 @@ FRESULT f_mkfs (
if (fmt == FS_FAT32) { /* FAT32: Move FAT base */
sz_rsv += n; b_fat += n;
} else { /* FAT: Expand FAT size */
if (n % n_fats) { /* Adjust fractional error if needed */
n--; sz_rsv++; b_fat++;
}
sz_fat += n / n_fats;
}

View File

@@ -465,8 +465,11 @@ void ini_list_launcher()
}
}
if (emummc_path)
emummc_set_path(emummc_path);
if (emummc_path && !emummc_set_path(emummc_path))
{
EPRINTF("emupath is wrong!");
goto wrong_emupath;
}
if (cfg_sec && !payload_path)
check_sept(cfg_sec);
@@ -497,15 +500,13 @@ void ini_list_launcher()
}
else if (!hos_launch(cfg_sec))
{
EPRINTF("Failed to launch firmware.");
wrong_emupath:
EPRINTF("Failed to launch HOS.");
if (emummc_path)
{
sd_mount();
emummc_load_cfg();
}
btn_wait();
}
out:
@@ -605,8 +606,11 @@ void launch_firmware()
}
}
if (emummc_path)
emummc_set_path(emummc_path);
if (emummc_path && !emummc_set_path(emummc_path))
{
EPRINTF("emupath is wrong!");
goto wrong_emupath;
}
if (cfg_sec && !payload_path)
check_sept(cfg_sec);
@@ -642,7 +646,8 @@ void launch_firmware()
}
else if (!hos_launch(cfg_sec))
{
EPRINTF("Failed to launch firmware.");
wrong_emupath:
EPRINTF("Failed to launch HOS.");
if (emummc_path)
{
sd_mount();
@@ -1034,8 +1039,13 @@ skip_list:
{
if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
emummc_set_path(b_cfg.emummc_path);
else if (emummc_path)
emummc_set_path(emummc_path);
else if (emummc_path && !emummc_set_path(emummc_path))
{
gfx_con.mute = false;
EPRINTF("emupath is wrong!");
goto wrong_emupath;
}
check_sept(cfg_sec);
hos_launch(cfg_sec);
@@ -1045,6 +1055,8 @@ skip_list:
emummc_load_cfg();
}
wrong_emupath:
display_backlight_brightness(h_cfg.backlight, 1000);
EPRINTF("\nFailed to launch HOS!");
gfx_printf("\nPress any key...\n");
msleep(500);
@@ -1432,7 +1444,7 @@ ment_t ment_top[] = {
MDEF_END()
};
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.2.0", 0, 0 };
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.2.1", 0, 0 };
extern void pivot_stack(u32 stack_top);

View File

@@ -136,7 +136,7 @@ void *malloc(u32 size)
void *calloc(u32 num, u32 size)
{
void *res = (void *)_heap_alloc(&_heap, num * size);
memset(res, 0, num * size);
memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
return res;
}
@@ -164,7 +164,7 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
count, node->used, (u32)node + sizeof(hnode_t), node->size);
count++;
if (node->next)
node = node->next;
else

View File

@@ -119,7 +119,7 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
time->weekday = 0; //! TODO.
}
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding)
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
{
u32 year, month, epoch;
@@ -128,39 +128,17 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding)
//Month of year
month = time->month;
if (!hos_encoding)
// Month/Year offset.
if(month < 3)
{
// Month/Year offset.
if(month < 3)
{
month += 12;
year--;
}
}
else
{
year -= 2000;
month++;
// Month/Year offset.
if(month < 3)
{
month += 9;
year--;
}
else
month -= 3;
month += 12;
year--;
}
epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days.
if (!hos_encoding)
{
epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
epoch -= 719561; // Epoch time is 1/1/1970.
}
else
epoch += (30 * month) + ((3 * month + 2) / 5) + 59 + time->day; // Months to days.
epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
epoch -= 719561; // Epoch time is 1/1/1970.
epoch *= 86400; // Days to seconds.
epoch += (3600 * time->hour) + (60 * time->min) + time->sec; // Add hours, minutes and seconds.

View File

@@ -72,6 +72,6 @@ typedef struct _rtc_time_t {
void max77620_rtc_get_time(rtc_time_t *time);
void max77620_rtc_stop_alarm();
void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time);
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding);
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time);
#endif /* _MFD_MAX77620_RTC_H_ */

View File

@@ -72,7 +72,7 @@ void emummc_load_cfg()
}
}
void emummc_set_path(char *path)
bool emummc_set_path(char *path)
{
FIL fp;
bool found = false;
@@ -105,8 +105,10 @@ void emummc_set_path(char *path)
emu_cfg.enabled = 1;
emu_cfg.id = 0;
strcpy(emu_cfg.nintendo_path, path);
strcpy(emu_cfg.nintendo_path, "/Nintendo");
strcat(emu_cfg.nintendo_path, "/Nintendo");
}
return found;
}
static int emummc_raw_get_part_off(int part_idx)

View File

@@ -50,7 +50,7 @@ typedef struct _emummc_cfg_t
emummc_cfg_t emu_cfg;
void emummc_load_cfg();
void emummc_set_path(char *path);
bool emummc_set_path(char *path);
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
int emummc_storage_end(sdmmc_storage_t *storage);
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);

View File

@@ -39,7 +39,7 @@ typedef struct _mbr_part_t
typedef struct _mbr_t
{
u8 bootstrap[0x1B8];
u8 bootstrap[440];
u32 signature;
u16 copy_protected;
mbr_part_t partitions[4];

View File

@@ -63,7 +63,7 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
lv_hal_disp.o lv_hal_indev.o lv_hal_tick.o \
interui_20.o interui_30.o ubuntu_mono.o hekate_symbol_20.o hekate_symbol_30.o hekate_symbol_120.o lv_font_builtin.o \
lv_anim.o lv_area.o lv_circ.o lv_color.o lv_font.o lv_ll.o lv_math.o lv_mem.o lv_task.o lv_txt.o lv_gc.o \
lv_bar.o lv_btn.o lv_btnm.o lv_cb.o lv_cont.o lv_ddlist.o lv_img.o lv_kb.o lv_label.o lv_line.o lv_list.o lv_lmeter.o lv_mbox.o \
lv_bar.o lv_btn.o lv_btnm.o lv_cb.o lv_cont.o lv_ddlist.o lv_img.o lv_label.o lv_line.o lv_list.o lv_lmeter.o lv_mbox.o \
lv_page.o lv_roller.o lv_slider.o lv_sw.o lv_tabview.o lv_ta.o lv_win.o lv_log.o lv_imgbtn.o \
lv_theme.o lv_theme_hekate.o \
)

View File

@@ -4,6 +4,10 @@ The background for Nyx, must be a 1280 x 720 32-bit BMP. Alpha blending is taken
The icons supported are 192 x 192 32-bit BMP. You can utilize transparency at will and make nice mixes with the button background.
Additionally, using the `icon={sd path}`, the icon will get colorized if the name ends in `_hue.bmp`. That only works nicely if the icon is a white layout with transparency.
The default system icons (`icon_switch.bmp` and `icon_payload.bmp`) can be replaced with white layouts that have transparency. They can also be replaced with normal icons if the following exist: `icon_switch_custom.bmp` or/and `icon_payload_custom.bmp`
## How to configure

View File

@@ -60,6 +60,7 @@ void set_nyx_default_configuration()
n_cfg.timeoff = 0;
n_cfg.home_screen = 0;
n_cfg.verification = 1;
n_cfg.ums_emmc_rw = 0;
}
int create_config_entry()
@@ -194,7 +195,7 @@ int create_nyx_config_entry()
itoa(n_cfg.themecolor, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\ntimeoff=", &fp);
itoa(n_cfg.timeoff, lbuf, 10);
itoa(n_cfg.timeoff, lbuf, 16);
f_puts(lbuf, &fp);
f_puts("\nhomescreen=", &fp);
itoa(n_cfg.home_screen, lbuf, 10);
@@ -202,6 +203,9 @@ int create_nyx_config_entry()
f_puts("\nverification=", &fp);
itoa(n_cfg.verification, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\numsemmcrw=", &fp);
itoa(n_cfg.ums_emmc_rw, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\n", &fp);
f_close(&fp);

View File

@@ -45,9 +45,10 @@ typedef struct _hekate_config
typedef struct _nyx_config
{
u32 themecolor;
s32 timeoff;
u32 timeoff;
u32 home_screen;
u32 verification;
u32 ums_emmc_rw;
} nyx_config;
void set_default_configuration();

View File

@@ -1145,7 +1145,7 @@ static void _update_status_bar(void *params)
max77620_rtc_get_time(&time);
if (n_cfg.timeoff)
{
u32 epoch = (u32)((s32)max77620_rtc_date_to_epoch(&time, true) + (s32)n_cfg.timeoff);
u32 epoch = max77620_rtc_date_to_epoch(&time) + (s32)n_cfg.timeoff;
max77620_rtc_epoch_to_date(epoch, &time);
}
soc_temp = tmp451_get_soc_temp(false);
@@ -1293,7 +1293,7 @@ static lv_res_t _win_launch_close_action(lv_obj_t * btn)
lv_img_dsc_t *src = (lv_img_dsc_t *)lv_img_get_src(img);
// Avoid freeing base icons.
if ((src != icon_switch) && (src != icon_payload) && (src != icon_lakka))
if ((src != icon_switch) && (src != icon_payload))
free(src);
}
}
@@ -1503,6 +1503,12 @@ static lv_res_t _create_window_home_launch(lv_obj_t *btn)
launch_ctxt[btn_idx + 1] = boot_entry_label;
}
// Create colorized icon style based on its parrent style.
static lv_style_t img_style;
lv_style_copy(&img_style, &lv_style_plain);
img_style.image.color = lv_color_hsv_to_rgb(n_cfg.themecolor, 100, 100);
img_style.image.intense = LV_OPA_COVER;
// Parse ini boot entries and set buttons/icons.
char *tmp_path = malloc(1024);
u32 curr_btn_idx = 0; // Active buttons.
@@ -1510,6 +1516,10 @@ static lv_res_t _create_window_home_launch(lv_obj_t *btn)
if (sd_mount())
{
// Check if we use custom system icons.
bool icon_sw_custom = !f_stat("bootloader/res/icon_switch_custom.bmp", NULL);
bool icon_pl_custom = !f_stat("bootloader/res/icon_payload_custom.bmp", NULL);
// Choose what to parse.
bool ini_parse_success = false;
if (!more_cfg)
@@ -1539,6 +1549,7 @@ ini_parsing:
icon_path = NULL;
u32 payload = 0;
bool img_colorize = false;
lv_img_dsc_t *bmp = NULL;
lv_obj_t *img = NULL;
@@ -1565,26 +1576,49 @@ ini_parsing:
bmp = bmp_to_lvimg_obj(tmp_path);
if (!bmp)
{
if (!strcmp(ini_sec->name, "Lakka"))
bmp = icon_lakka;
else if (payload)
bmp = icon_payload;
s_printf(tmp_path, "bootloader/res/%s_hue.bmp", ini_sec->name);
bmp = bmp_to_lvimg_obj(tmp_path);
if (bmp)
img_colorize = true;
}
if (!bmp && payload)
{
bmp = icon_payload;
if (!icon_pl_custom)
img_colorize = true;
}
}
else
{
bmp = bmp_to_lvimg_obj(icon_path);
// Check if colorization is enabled.
if (bmp && strlen(icon_path) > 8 && !memcmp(icon_path + strlen(icon_path) - 8, "_hue", 4))
img_colorize = true;
}
// Enable button.
lv_obj_set_opa_scale(launch_ctxt[curr_btn_idx], LV_OPA_COVER);
// Default to switch logo if no icon found at all.
if (!bmp)
{
bmp = icon_switch;
if (!icon_sw_custom)
img_colorize = true;
}
//Set icon.
if (bmp)
{
img = lv_img_create(launch_ctxt[curr_btn_idx], NULL);
if (img_colorize)
lv_img_set_style(img, &img_style);
lv_img_set_src(img, bmp);
}
@@ -1801,6 +1835,8 @@ static lv_res_t _save_options_action(lv_obj_t *btn)
lv_mbox_add_btns(mbox, mbox_btn_map, NULL);
lv_obj_set_top(mbox, true);
nyx_options_clear_ini_changes_made();
return LV_RES_OK;
}
@@ -1866,6 +1902,44 @@ static void _create_status_bar(lv_theme_t * th)
lv_btn_set_action(btn_mid, LV_BTN_ACTION_CLICK, _save_options_action);
}
static lv_res_t _create_mbox_save_changes_action(lv_obj_t *btns, const char * txt)
{
int btn_idx = lv_btnm_get_pressed(btns);
mbox_action(btns, txt);
if (!btn_idx)
_save_options_action(NULL);
return LV_RES_INV;
}
void nyx_check_ini_changes()
{
if (nyx_options_get_ini_changes_made())
{
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[] = { "\222Save", "\222Cancel", "" };
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true);
lv_mbox_set_text(mbox,
"#FF8000 Main configuration#\n\n"
"You changed your configuration!\n\n"
"Do you want to save it?");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_mbox_save_changes_action);
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_top(mbox, true);
nyx_options_clear_ini_changes_made();
}
}
static lv_res_t _show_hide_save_button(lv_obj_t *tv, uint16_t tab_idx)
{
if (tab_idx == 4) // Options.
@@ -1879,6 +1953,8 @@ static lv_res_t _show_hide_save_button(lv_obj_t *tv, uint16_t tab_idx)
lv_obj_set_click(status_bar.mid, false);
}
nyx_check_ini_changes();
return LV_RES_OK;
}

View File

@@ -49,15 +49,8 @@ extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_st
static lv_res_t _create_window_dump_done(int error, char *dump_filenames)
{
lv_style_t *darken;
darken = (lv_style_t *)malloc(sizeof(lv_style_t));
lv_style_copy(darken, &lv_style_plain);
darken->body.main_color = LV_COLOR_BLACK;
darken->body.grad_color = darken->body.main_color;
darken->body.opa = LV_OPA_30;
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, darken);
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", "\222OK", "\211", "" };
@@ -705,15 +698,8 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
sdmmc_storage_t emmc_storage;
sdmmc_storage_t *storage;
lv_style_t *darken;
darken = (lv_style_t *)malloc(sizeof(lv_style_t));
lv_style_copy(darken, &lv_style_plain);
darken->body.main_color = LV_COLOR_BLACK;
darken->body.grad_color = darken->body.main_color;
darken->body.opa = LV_OPA_30;
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, darken);
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", "\222OK", "\211", "" };
@@ -1134,7 +1120,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
lv_label_set_text(lb_desc4,
"#00DDFF SDMMC1 Error Counts:#\n"
"#00DDFF SDMMC1 Errors:#\n"
"Init fails:\n"
"Read/Write fails:\n"
"Read/Write errors:"

View File

@@ -23,6 +23,7 @@
#include "../input/joycon.h"
#include "../libs/lvgl/lvgl.h"
#include "../mem/heap.h"
#include "../rtc/max77620-rtc.h"
#include "../storage/nx_sd.h"
#include "../utils/list.h"
#include "../utils/sprintf.h"
@@ -34,9 +35,22 @@ extern nyx_config n_cfg;
static lv_obj_t *autoboot_btn;
static bool autoboot_first_time = true;
static bool ini_changes_made = false;
void nyx_options_clear_ini_changes_made()
{
ini_changes_made = false;
}
bool nyx_options_get_ini_changes_made()
{
return ini_changes_made;
}
static lv_res_t auto_hos_poweroff_toggle(lv_obj_t *btn)
{
h_cfg.autohosoff = !h_cfg.autohosoff;
ini_changes_made = true;
if (!h_cfg.autohosoff)
lv_btn_set_state(btn, LV_BTN_STATE_REL);
@@ -51,6 +65,7 @@ static lv_res_t auto_hos_poweroff_toggle(lv_obj_t *btn)
static lv_res_t auto_nogc_toggle(lv_obj_t *btn)
{
h_cfg.autonogc = !h_cfg.autonogc;
ini_changes_made = true;
if (!h_cfg.autonogc)
lv_btn_set_state(btn, LV_BTN_STATE_REL);
@@ -65,6 +80,7 @@ static lv_res_t auto_nogc_toggle(lv_obj_t *btn)
static lv_res_t _update_r2p_action(lv_obj_t *btn)
{
h_cfg.updater2p = !h_cfg.updater2p;
ini_changes_made = true;
if (!h_cfg.updater2p)
lv_btn_set_state(btn, LV_BTN_STATE_REL);
@@ -117,6 +133,7 @@ static lv_res_t _autoboot_disable_action(lv_obj_t *btn)
{
h_cfg.autoboot = 0;
h_cfg.autoboot_list = 0;
ini_changes_made = true;
lv_btn_set_state(autoboot_btn, LV_BTN_STATE_REL);
nyx_generic_onoff_toggle(autoboot_btn);
@@ -134,6 +151,7 @@ static lv_res_t _autoboot_enable_main_action(lv_obj_t *btn)
{
h_cfg.autoboot = lv_list_get_btn_index(auto_main_list, btn) + 1;
h_cfg.autoboot_list = 0;
ini_changes_made = true;
lv_btn_set_state(autoboot_btn, LV_BTN_STATE_TGL_REL);
nyx_generic_onoff_toggle(autoboot_btn);
@@ -150,6 +168,7 @@ static lv_res_t _autoboot_enable_more_action(lv_obj_t *btn)
{
h_cfg.autoboot = lv_list_get_btn_index(auto_more_list, btn) + 1;
h_cfg.autoboot_list = 1;
ini_changes_made = true;
lv_btn_set_state(autoboot_btn, LV_BTN_STATE_TGL_REL);
nyx_generic_onoff_toggle(autoboot_btn);
@@ -280,6 +299,7 @@ static lv_res_t _autoboot_hide_delay_action(lv_obj_t *btn)
static lv_res_t _autoboot_delay_action(lv_obj_t *ddlist)
{
h_cfg.bootwait = lv_ddlist_get_selected(ddlist);
ini_changes_made = true;
return LV_RES_OK;
}
@@ -288,6 +308,7 @@ static lv_res_t _slider_brightness_action(lv_obj_t * slider)
{
display_backlight_brightness(lv_slider_get_value(slider) - 20, 0);
h_cfg.backlight = lv_slider_get_value(slider);
ini_changes_made = true;
return LV_RES_OK;
}
@@ -516,13 +537,61 @@ static lv_res_t _create_window_nyx_colors(lv_obj_t *btn)
return LV_RES_OK;
}
lv_obj_t *epoch_ta;
static lv_res_t _create_mbox_clock_edit_action(lv_obj_t * btns, const char * txt)
typedef struct _time_edit_obj_t
{
lv_obj_t *year;
lv_obj_t *month;
lv_obj_t *day;
lv_obj_t *hour;
lv_obj_t *min;
} time_edit_obj_t;
time_edit_obj_t clock_ctxt;
static lv_res_t _action_clock_edit(lv_obj_t *btns, const char * txt)
{
int btn_idx = lv_btnm_get_pressed(btns);
if (btn_idx == 1)
n_cfg.timeoff = strtol(lv_ta_get_text(epoch_ta), NULL, 16);
{
rtc_time_t time;
max77620_rtc_get_time(&time);
u32 epoch = max77620_rtc_date_to_epoch(&time);
u32 year = lv_roller_get_selected(clock_ctxt.year);
u32 month = lv_roller_get_selected(clock_ctxt.month) + 1;
u32 day = lv_roller_get_selected(clock_ctxt.day) + 1;
u32 hour = lv_roller_get_selected(clock_ctxt.hour);
u32 min = lv_roller_get_selected(clock_ctxt.min);
switch (month)
{
case 2:
if (!(year % 4) && day > 29)
day = 29;
else if (day > 28)
day = 28;
break;
case 4:
case 6:
case 8:
case 10:
case 12:
if (day > 30)
day = 30;
break;
}
time.year = year + 2020;
time.month = month;
time.day = day;
time.hour = hour;
time.min = min;
u32 new_epoch = max77620_rtc_date_to_epoch(&time);
n_cfg.timeoff = new_epoch - epoch;
}
mbox_action(btns, txt);
@@ -531,15 +600,8 @@ static lv_res_t _create_mbox_clock_edit_action(lv_obj_t * btns, const char * txt
static lv_res_t _create_mbox_clock_edit(lv_obj_t *btn)
{
lv_style_t *darken;
darken = malloc(sizeof(lv_style_t));
lv_style_copy(darken, &lv_style_plain);
darken->body.main_color = LV_COLOR_BLACK;
darken->body.grad_color = darken->body.main_color;
darken->body.opa = LV_OPA_30;
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, darken);
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", "\222Done", "\222Cancel", "\211", "" };
@@ -547,28 +609,94 @@ static lv_res_t _create_mbox_clock_edit(lv_obj_t *btn)
lv_mbox_set_recolor_text(mbox, true);
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
lv_mbox_set_text(mbox, "Type the #C7EA46 epoch# offset in HEX s32:");
lv_mbox_set_text(mbox, "Enter #C7EA46 Date# and #C7EA46 Time#");
lv_obj_t *ta = lv_ta_create(mbox, NULL);
lv_obj_set_size(ta, LV_HOR_RES / 5, LV_VER_RES / 10);
lv_obj_align(ta, NULL, LV_ALIGN_IN_TOP_RIGHT, -LV_DPI / 10, LV_DPI / 10);
lv_ta_set_cursor_type(ta, LV_CURSOR_LINE);
lv_ta_set_one_line(ta, true);
epoch_ta = ta;
rtc_time_t time;
max77620_rtc_get_time(&time);
if (n_cfg.timeoff)
{
u32 epoch = max77620_rtc_date_to_epoch(&time) + (s32)n_cfg.timeoff;
max77620_rtc_epoch_to_date(epoch, &time);
}
if (time.year < 2020)
time.year = 2020;
else if (time.year > 2030)
time.year = 2030;
static char epoch_off[16];
s_printf(epoch_off, "%X", n_cfg.timeoff);
lv_ta_set_text(ta, epoch_off);
lv_ta_set_max_length(ta, 8);
time.year -= 2020;
lv_obj_t *kb = lv_kb_create(mbox, NULL);
lv_obj_set_size(kb, 2 * LV_HOR_RES / 3, LV_VER_RES / 3);
lv_obj_align(kb, ta, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, LV_DPI);
lv_kb_set_mode(kb, LV_KB_MODE_HEX);
lv_kb_set_ta(kb, ta);
lv_kb_set_cursor_manage(kb, true);
lv_obj_t *h1 = lv_cont_create(mbox, NULL);
lv_cont_set_fit(h1, true, true);
lv_mbox_add_btns(mbox, mbox_btn_map, _create_mbox_clock_edit_action); // Important. After set_text.
lv_obj_t *roller_year = lv_roller_create(h1, NULL);
lv_roller_set_options(roller_year,
"2020\n"
"2021\n"
"2022\n"
"2023\n"
"2024\n"
"2025\n"
"2026\n"
"2027\n"
"2028\n"
"2029\n"
"2030");
lv_roller_set_selected(roller_year, time.year, false);
lv_roller_set_visible_row_count(roller_year, 3);
clock_ctxt.year = roller_year;
lv_obj_t *roller_month = lv_roller_create(h1, roller_year);
lv_roller_set_options(roller_month,
"January\n"
"February\n"
"March\n"
"April\n"
"May\n"
"June\n"
"July\n"
"August\n"
"September\n"
"October\n"
"November\n"
"December");
lv_roller_set_selected(roller_month, time.month - 1, false);
lv_obj_align(roller_month, roller_year, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
clock_ctxt.month = roller_month;
static char days[256];
days[0] = 0;
for (u32 i = 1; i < 32; i++)
s_printf(days + strlen(days), " %d \n", i);
days[strlen(days) - 1] = 0;
lv_obj_t *roller_day = lv_roller_create(h1, roller_year);
lv_roller_set_options(roller_day, days);
lv_roller_set_selected(roller_day, time.day - 1, false);
lv_obj_align(roller_day, roller_month, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
clock_ctxt.day = roller_day;
static char hours[256];
hours[0] = 0;
for (u32 i = 0; i < 24; i++)
s_printf(hours + strlen(hours), " %d \n", i);
hours[strlen(hours) - 1] = 0;
lv_obj_t *roller_hour = lv_roller_create(h1, roller_year);
lv_roller_set_options(roller_hour, hours);
lv_roller_set_selected(roller_hour, time.hour, false);
lv_obj_align(roller_hour, roller_day, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
clock_ctxt.hour = roller_hour;
static char minutes[512];
minutes[0] = 0;
for (u32 i = 0; i < 60; i++)
s_printf(minutes + strlen(minutes), " %02d \n", i);
minutes[strlen(minutes) - 1] = 0;
lv_obj_t *roller_minute = lv_roller_create(h1, roller_year);
lv_roller_set_options(roller_minute, minutes);
lv_roller_set_selected(roller_minute, time.min, false);
lv_obj_align(roller_minute, roller_hour, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
clock_ctxt.min = roller_minute;
lv_mbox_add_btns(mbox, mbox_btn_map, _action_clock_edit); // Important. After set_text.
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_top(mbox, true);
@@ -626,15 +754,8 @@ static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
sd_unmount(false);
}
lv_style_t *darken;
darken = (lv_style_t *)malloc(sizeof(lv_style_t));
lv_style_copy(darken, &lv_style_plain);
darken->body.main_color = LV_COLOR_BLACK;
darken->body.grad_color = darken->body.main_color;
darken->body.opa = LV_OPA_30;
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, darken);
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", "\222OK", "\211", "" };
@@ -781,23 +902,16 @@ lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn)
lv_obj_t *btn2 = lv_btn_create(sw_h2, NULL);
lv_obj_t *label_btn2 = lv_label_create(btn2, NULL);
lv_btn_set_fit(btn2, true, true);
lv_label_set_static_text(label_btn2, SYMBOL_CLOCK" Clock (HOS)");
lv_label_set_static_text(label_btn2, SYMBOL_CLOCK" Clock (Offset)");
lv_obj_align(btn2, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
lv_btn_set_action(btn2, LV_BTN_ACTION_CLICK, _create_mbox_clock_edit); //TODO: Add support.
lv_btn_set_state(btn2, LV_BTN_STATE_INA); //TODO: Add support.
lv_obj_t *btn4 = lv_btn_create(sw_h2, btn2);
label_btn2 = lv_label_create(btn4, NULL);
lv_label_set_static_text(label_btn2, " "SYMBOL_EDIT" Manually ");
lv_obj_align(btn4, btn2, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 8, 0);
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, _create_mbox_clock_edit);
lv_btn_set_state(btn4, LV_BTN_STATE_REL);
lv_btn_set_action(btn2, LV_BTN_ACTION_CLICK, _create_mbox_clock_edit);
label_txt2 = lv_label_create(sw_h2, NULL);
lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2,
"#FF8000 Clock (HOS):# #C7EA46 Change clock offset based on what HOS uses.#\n"
"#FF8000 Manually:# #C7EA46 Edit the clock offset manually.#");
"Change clock offset manually.\n"
"#C7EA46 The entered Date and Time will be converted to an offset#\n"
"#C7EA46 automatically. This will be also used for FatFS operations.#");
lv_obj_set_style(label_txt2, &hint_small_style);
lv_obj_align(label_txt2, btn2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 4);

View File

@@ -19,6 +19,8 @@
#include "../libs/lvgl/lvgl.h"
void nyx_options_clear_ini_changes_made();
bool nyx_options_get_ini_changes_made();
lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn);
void create_tab_options(lv_theme_t *th, lv_obj_t *parent);

View File

@@ -46,6 +46,7 @@
extern volatile boot_cfg_t *b_cfg;
extern hekate_config h_cfg;
extern nyx_config n_cfg;
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
@@ -643,8 +644,6 @@ static lv_res_t _create_window_usb_tools(lv_obj_t *parent)
{
lv_obj_t *win = nyx_create_standard_window(SYMBOL_USB" USB Tools");
usb_msc_emmc_read_only = true;
static lv_style_t h_style;
lv_style_copy(&h_style, &lv_style_transp);
h_style.body.padding.inner = 0;
@@ -747,7 +746,8 @@ static lv_res_t _create_window_usb_tools(lv_obj_t *parent)
lv_obj_t *btn_write_access = lv_btn_create(h_write, NULL);
nyx_create_onoff_button(lv_theme_get_current(), h_write,
btn_write_access, SYMBOL_EDIT" Read-Only", _emmc_read_only_toggle, false);
lv_btn_set_state(btn_write_access, LV_BTN_STATE_TGL_REL);
if (!n_cfg.ums_emmc_rw)
lv_btn_set_state(btn_write_access, LV_BTN_STATE_TGL_REL);
_emmc_read_only_toggle(btn_write_access);
// Create USB Input Devices container.
@@ -1649,8 +1649,8 @@ void create_tab_tools(lv_theme_t *th, lv_obj_t *parent)
lv_tabview_set_sliding(tv, false);
lv_tabview_set_btns_pos(tv, LV_TABVIEW_BTNS_POS_BOTTOM);
lv_obj_t *tab1= lv_tabview_add_tab(tv, "eMMC "SYMBOL_DOT" Dump Pkg1/2 "SYMBOL_DOT" USB Tools");
lv_obj_t *tab2 = lv_tabview_add_tab(tv, "Archive bit "SYMBOL_DOT" AutoRCM "SYMBOL_DOT" Touch Tuning");
lv_obj_t *tab1= lv_tabview_add_tab(tv, "eMMC "SYMBOL_DOT" Pkg1/2 "SYMBOL_DOT" USB Tools");
lv_obj_t *tab2 = lv_tabview_add_tab(tv, "Arch bit "SYMBOL_DOT" RCM "SYMBOL_DOT" Touch "SYMBOL_DOT" Partitions");
lv_obj_t *line_sep = lv_line_create(tv, NULL);
static const lv_point_t line_pp[] = { {0, 0}, { 0, LV_DPI / 4} };

View File

@@ -223,6 +223,7 @@ static void _prepare_and_flash_mbr_gpt()
mbr.partitions[mbr_idx].type = 0x83; // Linux system partition.
mbr.partitions[mbr_idx].start_sct = 0x8000 + (part_info.hos_size << 11);
mbr.partitions[mbr_idx].size_sct = part_info.l4t_size << 11;
sdmmc_storage_write(&sd_storage, mbr.partitions[mbr_idx].start_sct, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
mbr_idx++;
}
@@ -301,6 +302,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.l4t_size << 11) - 1;
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'l', 0, '4', 0, 't', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += (part_info.l4t_size << 11);
gpt_idx++;
@@ -313,6 +315,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x200000 - 1; // 1GB.
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'v', 0, 'e', 0, 'n', 0, 'd', 0, 'o', 0, 'r', 0 }, 12);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += 0x200000;
gpt_idx++;
@@ -323,6 +326,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x400000 - 1; // 2GB.
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'A', 0, 'P', 0, 'P', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += 0x400000;
gpt_idx++;
@@ -333,6 +337,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x10000 - 1; // 32MB.
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += 0x10000;
gpt_idx++;
@@ -343,6 +348,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x20000 - 1; // 64MB.
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += 0x20000;
gpt_idx++;
@@ -353,6 +359,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x800 - 1; // 1MB.
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'D', 0, 'T', 0, 'B', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += 0x800;
gpt_idx++;
@@ -363,6 +370,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x8000 - 1; // 16MB.
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'M', 0, 'D', 0, 'A', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x8000, (void *)SDMMC_UPPER_BUFFER); // Clear 16MB.
curr_part_lba += 0x8000;
gpt_idx++;
@@ -373,6 +381,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x15E000 - 1; // 700MB.
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'C', 0, 'A', 0, 'C', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += 0x15E000;
gpt_idx++;
@@ -388,6 +397,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt.entries[gpt_idx].lba_start = curr_part_lba;
gpt.entries[gpt_idx].lba_end = curr_part_lba + user_size - 1;
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'U', 0, 'D', 0, 'A', 0 }, 6);
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
curr_part_lba += user_size;
gpt_idx++;
@@ -1325,12 +1335,14 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
if (f_mkfs("sd:", FM_FAT32, cluster_size, buf, 0x400000))
{
// Retry.
if (f_mkfs("sd:", FM_FAT32, cluster_size, buf, 0x400000))
u32 error = f_mkfs("sd:", FM_FAT32, cluster_size, buf, 0x400000);
if (error)
{
// Failed to format.
lv_label_set_text(lbl_status,
"#FFDD00 Error:# Failed to format disk!\n\n"
"Remove the SD card and check that is OK. If not, format it and press any key!");
s_printf((char *)buf, "#FFDD00 Error:# Failed to format disk (%d)!\n\n"
"Remove the SD card and check that is OK.\nIf not, format it, reinsert it and\npress #FF8000 POWER#!", error);
lv_label_set_text(lbl_status, (char *)buf);
lv_label_set_text(lbl_paths[0], " ");
manual_system_maintenance(true);
sd_unmount(true);
@@ -1569,7 +1581,23 @@ static lv_res_t _action_slider_emu(lv_obj_t *slider)
lv_label_set_text(part_info.lbl_emu, lbl_text);
}
else
lv_slider_set_value(slider, 0);
{
int new_slider_val;
switch (part_info.emu_size)
{
case 29856:
new_slider_val = 1;
break;
case 59712:
new_slider_val = 2;
break;
case 0:
default:
new_slider_val = 0;
break;
}
lv_slider_set_value(slider, new_slider_val);
}
_update_partition_bar();

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
#include "../soc/pmc.h"
#include "../soc/smmu.h"
#include "../soc/t210.h"
#include "../storage/mbr_gpt.h"
#include "../storage/nx_emmc.h"
#include "../storage/nx_sd.h"
#include "../storage/sdmmc.h"
@@ -90,15 +91,42 @@ static const u8 master_keyseed_620[0x10] =
static const u8 console_keyseed_4xx_5xx[0x10] =
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
bool hos_eks_rw_try(u8 *buf, bool write)
{
mbr_t *mbr = (mbr_t *)buf;
for (u32 i = 0; i < 3; i++)
{
if (!write)
{
if (sdmmc_storage_read(&sd_storage, 0, 1, mbr))
{
if (mbr->partitions[0].status != 0xFF &&
mbr->partitions[0].start_sct &&
mbr->partitions[0].size_sct)
return true;
else
return false;
}
}
else
{
if (sdmmc_storage_write(&sd_storage, 0, 1, mbr))
return true;
}
}
return false;
}
void hos_eks_get()
{
// Check if EKS already found and parsed.
if (!h_cfg.eks)
{
u8 *mbr = calloc(512 , 1);
// Read EKS blob.
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
u8 *mbr = calloc(512 , 1);
if (!hos_eks_rw_try(mbr, false))
goto out;
// Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x10);
@@ -115,6 +143,7 @@ void hos_eks_get()
return;
}
out:
free(mbr);
}
}
@@ -128,12 +157,29 @@ void hos_eks_save(u32 kb)
if (key_idx > 5)
return;
bool new_eks = false;
if (!h_cfg.eks)
{
h_cfg.eks = calloc(512 , 1);
new_eks = true;
}
// If matching blob doesn't exist, create it.
if (!(h_cfg.eks->enabled & (1 << key_idx)))
{
// Read EKS blob.
u8 *mbr = calloc(512 , 1);
if (!hos_eks_rw_try(mbr, false))
{
if (new_eks)
{
free(h_cfg.eks);
h_cfg.eks = NULL;
}
goto out;
}
// Get keys.
u8 *keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10);
@@ -151,20 +197,21 @@ void hos_eks_save(u32 kb)
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].dkk, keys + 15 * 0x10, 0x10);
// Encrypt EKS.
// Encrypt EKS blob.
u8 *eks = calloc(512 , 1);
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS to SD.
u8 *mbr = calloc(512 , 1);
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
// Write EKS blob to SD.
memset(mbr, 0, 0x10);
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
hos_eks_rw_try(mbr, true);
free(eks);
free(mbr);
free(keys);
out:
free(mbr);
}
}
}
@@ -177,25 +224,30 @@ void hos_eks_clear(u32 kb)
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
if (h_cfg.eks->enabled & (1 << key_idx))
{
// Read EKS blob.
u8 *mbr = calloc(512 , 1);
if (!hos_eks_rw_try(mbr, false))
goto out;
// Disable current Master key version.
h_cfg.eks->enabled &= ~(1 << key_idx);
// Encrypt EKS.
// Encrypt EKS blob.
u8 *eks = calloc(512 , 1);
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS to SD.
u8 *mbr = calloc(512 , 1);
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
// Write EKS blob to SD.
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
hos_eks_rw_try(mbr, true);
free(eks);
out:
free(mbr);
}
}
}
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
{
u8 tmp[0x20];

View File

@@ -68,7 +68,7 @@ typedef struct _hos_eks_mbr_t
u32 rsvd2[3];
} hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) < 424, "HOS EKS storage bigger than MBR!");
static_assert(sizeof(hos_eks_mbr_t) == 416, "HOS EKS storage bigger than MBR!");
typedef struct _launch_ctxt_t
{

View File

@@ -5842,7 +5842,7 @@ FRESULT f_mkfs (
UINT len /* Size of working buffer [byte] */
)
{
const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */
const UINT n_fats = 2; /* Number of FATs for FAT/FAT32 volume (1 or 2) */
const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */
static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */
static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */
@@ -6130,6 +6130,9 @@ FRESULT f_mkfs (
if (fmt == FS_FAT32) { /* FAT32: Move FAT base */
sz_rsv += n; b_fat += n;
} else { /* FAT: Expand FAT size */
if (n % n_fats) { /* Adjust fractional error if needed */
n--; sz_rsv++; b_fat++;
}
sz_fat += n / n_fats;
}

View File

@@ -54,7 +54,7 @@ DWORD get_fattime (
max77620_rtc_get_time(&time);
if (n_cfg.timeoff)
{
u32 epoch = (u32)((s32)max77620_rtc_date_to_epoch(&time, true) + (s32)n_cfg.timeoff);
u32 epoch = (u32)((s32)max77620_rtc_date_to_epoch(&time) + (s32)n_cfg.timeoff);
max77620_rtc_epoch_to_date(epoch, &time);
}

View File

@@ -336,7 +336,7 @@
#define USE_LV_BTNM 1
/*Keyboard (dependencies: lv_btnm)*/
#define USE_LV_KB 1
#define USE_LV_KB 0
/*Check box (dependencies: lv_btn, lv_label)*/
#define USE_LV_CB 1

View File

@@ -136,7 +136,7 @@ void *malloc(u32 size)
void *calloc(u32 num, u32 size)
{
void *res = (void *)_heap_alloc(&_heap, num * size);
memset(res, 0, num * size);
memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
return res;
}
@@ -164,7 +164,7 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
count, node->used, (u32)node + sizeof(hnode_t), node->size);
count++;
if (node->next)
node = node->next;
else

View File

@@ -270,6 +270,8 @@ void load_saved_configuration()
n_cfg.home_screen = atoi(kv->val);
else if (!strcmp("verification", kv->key))
n_cfg.verification = atoi(kv->val);
else if (!strcmp("umsemmcrw", kv->key))
n_cfg.ums_emmc_rw = atoi(kv->val) == 1;
}
break;
@@ -361,9 +363,19 @@ void nyx_init_load_res()
f_read(&fp, (void *)NYX_RES_ADDR, f_size(&fp), NULL);
f_close(&fp);
icon_switch = bmp_to_lvimg_obj("bootloader/res/icon_switch.bmp");
icon_payload = bmp_to_lvimg_obj("bootloader/res/icon_payload.bmp");
icon_lakka = bmp_to_lvimg_obj("bootloader/res/icon_lakka.bmp");
// If no custom switch icon exists, load normal.
if (f_stat("bootloader/res/icon_switch_custom.bmp", NULL))
icon_switch = bmp_to_lvimg_obj("bootloader/res/icon_switch.bmp");
else
icon_switch = bmp_to_lvimg_obj("bootloader/res/icon_switch_custom.bmp");
// If no custom payload icon exists, load normal.
if (f_stat("bootloader/res/icon_payload_custom.bmp", NULL))
icon_payload = bmp_to_lvimg_obj("bootloader/res/icon_payload.bmp");
else
icon_payload = bmp_to_lvimg_obj("bootloader/res/icon_payload_custom.bmp");
// Load background resource if any.
hekate_bg = bmp_to_lvimg_obj("bootloader/res/background.bmp");
sd_unmount(false);

View File

@@ -119,7 +119,7 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
time->weekday = 0; //! TODO.
}
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding)
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
{
u32 year, month, epoch;
@@ -128,39 +128,17 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding)
//Month of year
month = time->month;
if (!hos_encoding)
// Month/Year offset.
if(month < 3)
{
// Month/Year offset.
if(month < 3)
{
month += 12;
year--;
}
}
else
{
year -= 2000;
month++;
// Month/Year offset.
if(month < 3)
{
month += 9;
year--;
}
else
month -= 3;
month += 12;
year--;
}
epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days.
if (!hos_encoding)
{
epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
epoch -= 719561; // Epoch time is 1/1/1970.
}
else
epoch += (30 * month) + ((3 * month + 2) / 5) + 59 + time->day; // Months to days.
epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
epoch -= 719561; // Epoch time is 1/1/1970.
epoch *= 86400; // Days to seconds.
epoch += (3600 * time->hour) + (60 * time->min) + time->sec; // Add hours, minutes and seconds.

View File

@@ -72,6 +72,6 @@ typedef struct _rtc_time_t {
void max77620_rtc_get_time(rtc_time_t *time);
void max77620_rtc_stop_alarm();
void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time);
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding);
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time);
#endif /* _MFD_MAX77620_RTC_H_ */

View File

@@ -39,7 +39,7 @@ typedef struct _mbr_part_t
typedef struct _mbr_t
{
u8 bootstrap[0x1B8];
u8 bootstrap[440];
u32 signature;
u16 copy_protected;
mbr_part_t partitions[4];

View File

@@ -1740,6 +1740,25 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
}
}
static inline void _system_maintainance(usbd_gadget_ums_t *ums)
{
static u32 timer_dram = 0;
static u32 timer_status_bar = 0;
u32 time = get_tmr_ms();
if (timer_dram < time)
{
minerva_periodic_training();
timer_dram = get_tmr_ms() + 100;
}
else if (timer_status_bar < time)
{
ums->system_maintenance(true);
timer_status_bar = get_tmr_ms() + 30000;
}
}
int usb_device_gadget_ums(usb_ctxt_t *usbs)
{
int res = 0;
@@ -1818,7 +1837,8 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
do
{
minerva_periodic_training();
// Do DRAM training and update system tasks.
_system_maintainance(&ums);
// Check for force unmount button combo.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB