[INI] Fix memory leaks + other fixes (#38)

* [INI] Fix memory leaks + other fixes

* Add ini_free
* check and return if NULL pointer in free()
* Add button check with timeout
* Fix a bug in menu rendering that tries to parse a string without existing
* Change initial cnt value to max (fixes menus with first entry not a selectable entry)
* Some & ? clarifications

* [INI] Add get selected boot cfg

- This allows to free ini as we launch the firmware and have the lowest mem leak

* [INI] Rename ini section clone/free functions
This commit is contained in:
Kostas Missos 2018-06-13 02:34:32 +03:00 committed by nwert
parent 62a8618606
commit b2dd070d10
12 changed files with 124 additions and 47 deletions

View file

@ -18,6 +18,7 @@
#include "i2c.h" #include "i2c.h"
#include "gpio.h" #include "gpio.h"
#include "t210.h" #include "t210.h"
#include "util.h"
u32 btn_read() u32 btn_read()
{ {
@ -53,5 +54,22 @@ u32 btn_wait()
else if (pwr) else if (pwr)
res &= 0xFFFFFFFE; res &= 0xFFFFFFFE;
} while (btn == res); } while (btn == res);
return res;
}
u32 btn_wait_timeout(u32 time_ms)
{
u32 timeout = get_tmr() + (time_ms * 1000);
u32 res = btn_read();
u32 btn = res;
do
{
//Keep the new value until timeout is reached
if (btn == res)
res = btn_read();
} while (get_tmr() < timeout);
return res; return res;
} }

View file

@ -25,5 +25,6 @@
u32 btn_read(); u32 btn_read();
u32 btn_wait(); u32 btn_wait();
u32 btn_wait_timeout(u32 time_ms);
#endif #endif

View file

@ -90,5 +90,5 @@ void gpio_write(u32 port, u32 pins, int high)
int gpio_read(u32 port, u32 pins) int gpio_read(u32 port, u32 pins)
{ {
return GPIO(_gpio_in[port]) & pins ? 1 : 0; return (GPIO(_gpio_in[port]) & pins) ? 1 : 0;
} }

View file

@ -97,6 +97,7 @@ static void _heap_free(heap_t *heap, u32 addr)
while (node) while (node)
{ {
if (!node->used) if (!node->used)
{
if (node->prev && !node->prev->used) if (node->prev && !node->prev->used)
{ {
node->prev->size += node->size + sizeof(hnode_t); node->prev->size += node->size + sizeof(hnode_t);
@ -104,6 +105,7 @@ static void _heap_free(heap_t *heap, u32 addr)
if (node->next) if (node->next)
node->next->prev = node->prev; node->next->prev = node->prev;
} }
}
node = node->next; node = node->next;
} }
} }
@ -129,5 +131,6 @@ void *calloc(u32 num, u32 size)
void free(void *buf) void free(void *buf)
{ {
_heap_free(&_heap, (u32)buf); if (buf != NULL)
_heap_free(&_heap, (u32)buf);
} }

View file

@ -109,7 +109,7 @@ u32 crc32c(const u8 *buf, u32 len)
{ {
crc ^= *buf++; crc ^= *buf++;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
crc = crc & 1 ? (crc >> 1) ^ CRC32C_POLY : crc >> 1; crc = (crc & 1) ? (crc >> 1) ^ CRC32C_POLY : crc >> 1;
} }
return ~crc; return ~crc;
} }

View file

@ -91,3 +91,51 @@ int ini_parse(link_t *dst, char *ini_path)
return 1; return 1;
} }
void ini_free(link_t *dst)
{
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, dst, link)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
free(kv->key);
free(kv->val);
free(kv);
}
free(ini_sec->name);
free(ini_sec);
}
}
ini_sec_t *ini_clone_section(ini_sec_t *cfg)
{
if (cfg == NULL)
return NULL;
ini_sec_t *csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
list_init(&csec->kvs);
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
{
ini_kv_t *kvcfg = (ini_kv_t *)malloc(sizeof(ini_kv_t));
kvcfg->key = _strdup(kv->key);
kvcfg->val = _strdup(kv->val);
list_append(&csec->kvs, &kvcfg->link);
}
return csec;
}
void ini_free_section(ini_sec_t *cfg)
{
if (cfg == NULL)
return;
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
{
free(kv->key);
free(kv->val);
free(kv);
}
free(cfg);
}

View file

@ -35,5 +35,8 @@ typedef struct _ini_sec_t
} ini_sec_t; } ini_sec_t;
int ini_parse(link_t *dst, char *ini_path); int ini_parse(link_t *dst, char *ini_path);
void ini_free(link_t *dst);
ini_sec_t *ini_clone_section(ini_sec_t *cfg);
void ini_free_section(ini_sec_t *cfg);
#endif #endif

View file

@ -870,7 +870,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
// Verify part // Verify part
if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part)) if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part))
{ {
EPRINTF("\nPress any key and try again.\n"); EPRINTF("\nPress any key and try again...\n");
free(buf); free(buf);
return 0; return 0;
@ -938,7 +938,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
{ {
EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X from eMMC. Aborting..\n", EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X from eMMC. Aborting..\n",
num, lba_curr); num, lba_curr);
EPRINTF("\nPress any key and try again.\n"); EPRINTF("\nPress any key and try again...\n");
free(buf); free(buf);
f_close(&fp); f_close(&fp);
@ -949,7 +949,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
if (res) if (res)
{ {
EPRINTFARGS("\nFatal error (%d) when writing to SD Card", res); EPRINTFARGS("\nFatal error (%d) when writing to SD Card", res);
EPRINTF("\nPress any key and try again.\n"); EPRINTF("\nPress any key and try again...\n");
free(buf); free(buf);
f_close(&fp); f_close(&fp);
@ -982,7 +982,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
// Verify last part or single file backup // Verify last part or single file backup
if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part)) if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part))
{ {
EPRINTF("\nPress any key and try again.\n"); EPRINTF("\nPress any key and try again...\n");
free(buf); free(buf);
return 0; return 0;
@ -1099,7 +1099,7 @@ static void dump_emmc_selected(dumpType_t dumpType)
gfx_printf(&gfx_con, "Time taken: %d seconds.\n", (get_tmr() - timer) / 1000000); gfx_printf(&gfx_con, "Time taken: %d seconds.\n", (get_tmr() - timer) / 1000000);
sdmmc_storage_end(&storage); sdmmc_storage_end(&storage);
if (res) if (res)
gfx_printf(&gfx_con, "\n%kFinished and verified!%k\nPress any key.\n",0xFF00FF96, 0xFFCCCCCC); gfx_printf(&gfx_con, "\n%kFinished and verified!%k\nPress any key...\n",0xFF00FF96, 0xFFCCCCCC);
out:; out:;
btn_wait(); btn_wait();
@ -1112,15 +1112,10 @@ void dump_emmc_rawnand() { dump_emmc_selected(DUMP_RAW); }
void dump_package1() void dump_package1()
{ {
u8 *pkg1 = (u8 *)malloc(0x40000); u8 *pkg1 = (u8 *)calloc(1, 0x40000);
u8 *warmboot = (u8 *)malloc(0x40000); u8 *warmboot = (u8 *)calloc(1, 0x40000);
u8 *secmon = (u8 *)malloc(0x40000); u8 *secmon = (u8 *)calloc(1, 0x40000);
u8 *loader = (u8 *)malloc(0x40000); u8 *loader = (u8 *)calloc(1, 0x40000);
memset(pkg1, 0, 0x40000);
memset(warmboot, 0, 0x40000);
memset(secmon, 0, 0x40000);
memset(loader, 0, 0x40000);
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
@ -1137,7 +1132,7 @@ void dump_package1()
} }
sdmmc_storage_set_mmc_partition(&storage, 1); sdmmc_storage_set_mmc_partition(&storage, 1);
//Read package1. // Read package1.
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1); sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1); const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20); const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
@ -1151,13 +1146,13 @@ void dump_package1()
u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE); u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob); sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob);
// decrypt // Decrypt
keygen(keyblob, pkg1_id->kb, (u8 *)pkg1 + pkg1_id->tsec_off); keygen(keyblob, pkg1_id->kb, (u8 *)pkg1 + pkg1_id->tsec_off);
pkg1_decrypt(pkg1_id, pkg1); pkg1_decrypt(pkg1_id, pkg1);
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1); pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1);
// display info // Display info
gfx_printf(&gfx_con, "%kNX Bootloader size: %k0x%05X\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->ldr_size); gfx_printf(&gfx_con, "%kNX Bootloader size: %k0x%05X\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->ldr_size);
gfx_printf(&gfx_con, "%kNX Bootloader ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->ldr_off); gfx_printf(&gfx_con, "%kNX Bootloader ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->ldr_off);
@ -1169,28 +1164,28 @@ void dump_package1()
gfx_printf(&gfx_con, "%kWarmboot size: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->wb_size); gfx_printf(&gfx_con, "%kWarmboot size: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->wb_size);
gfx_printf(&gfx_con, "%kWarmboot ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->wb_off); gfx_printf(&gfx_con, "%kWarmboot ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->wb_off);
// dump package1 // Dump package1
if (sd_save_to_file(pkg1, 0x40000, "pkg1_decr.bin")) { if (sd_save_to_file(pkg1, 0x40000, "pkg1_decr.bin")) {
EPRINTF("\nFailed to create pkg1_decr.bin"); EPRINTF("\nFailed to create pkg1_decr.bin");
goto out; goto out;
} }
gfx_puts(&gfx_con, "\npackage1 dumped to pkg1_decr.bin\n"); gfx_puts(&gfx_con, "\npackage1 dumped to pkg1_decr.bin\n");
// dump nxbootloader // Dump nxbootloader
if (sd_save_to_file(loader, hdr->ldr_size, "nxloader.bin")) { if (sd_save_to_file(loader, hdr->ldr_size, "nxloader.bin")) {
EPRINTF("\nFailed to create nxloader.bin"); EPRINTF("\nFailed to create nxloader.bin");
goto out; goto out;
} }
gfx_puts(&gfx_con, "NX Bootloader dumped to nxloader.bin\n"); gfx_puts(&gfx_con, "NX Bootloader dumped to nxloader.bin\n");
// dump secmon // Dump secmon
if (sd_save_to_file(secmon, hdr->sm_size, "secmon.bin")) { if (sd_save_to_file(secmon, hdr->sm_size, "secmon.bin")) {
EPRINTF("\nFailed to create secmon.bin"); EPRINTF("\nFailed to create secmon.bin");
goto out; goto out;
} }
gfx_puts(&gfx_con, "Secure Monitor dumped to secmon.bin\n"); gfx_puts(&gfx_con, "Secure Monitor dumped to secmon.bin\n");
// dump warmboot // Dump warmboot
if (sd_save_to_file(warmboot, hdr->wb_size, "warmboot.bin")) { if (sd_save_to_file(warmboot, hdr->wb_size, "warmboot.bin")) {
EPRINTF("\nFailed to create warmboot.bin"); EPRINTF("\nFailed to create warmboot.bin");
goto out; goto out;
@ -1199,7 +1194,7 @@ void dump_package1()
sdmmc_storage_end(&storage); sdmmc_storage_end(&storage);
gfx_puts(&gfx_con, "\nDone. Press any key.\n"); gfx_puts(&gfx_con, "\nDone. Press any key...\n");
out:; out:;
free(pkg1); free(pkg1);
@ -1212,6 +1207,8 @@ out:;
void launch_firmware() void launch_firmware()
{ {
u8 max_entries = 16;
ini_sec_t *cfg_sec = NULL; ini_sec_t *cfg_sec = NULL;
LIST_INIT(ini_sections); LIST_INIT(ini_sections);
@ -1222,8 +1219,8 @@ void launch_firmware()
{ {
if (ini_parse(&ini_sections, "hekate_ipl.ini")) if (ini_parse(&ini_sections, "hekate_ipl.ini"))
{ {
//Build configuration menu. // Build configuration menu.
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 16); ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * max_entries);
ments[0].type = MENT_BACK; ments[0].type = MENT_BACK;
ments[0].caption = "Back"; ments[0].caption = "Back";
u32 i = 1; u32 i = 1;
@ -1235,6 +1232,9 @@ void launch_firmware()
ments[i].caption = ini_sec->name; ments[i].caption = ini_sec->name;
ments[i].data = ini_sec; ments[i].data = ini_sec;
i++; i++;
if (i > max_entries)
break;
} }
if (i > 1) if (i > 1)
{ {
@ -1242,13 +1242,18 @@ void launch_firmware()
menu_t menu = { menu_t menu = {
ments, "Launch configurations", 0, 0 ments, "Launch configurations", 0, 0
}; };
cfg_sec = (ini_sec_t *)tui_do_menu(&gfx_con, &menu); cfg_sec = ini_clone_section((ini_sec_t *)tui_do_menu(&gfx_con, &menu));
if (!cfg_sec) if (!cfg_sec)
{
free(ments);
ini_free(&ini_sections);
return; return;
}
} }
else else
EPRINTF("No launch configurations found."); EPRINTF("No launch configurations found.");
free(ments); free(ments);
ini_free(&ini_sections);
} }
else else
EPRINTF("Could not find or open 'hekate_ipl.ini'.\nMake sure it exists in SD Card!."); EPRINTF("Could not find or open 'hekate_ipl.ini'.\nMake sure it exists in SD Card!.");
@ -1263,7 +1268,7 @@ void launch_firmware()
if (!hos_launch(cfg_sec)) if (!hos_launch(cfg_sec))
EPRINTF("Failed to launch firmware."); EPRINTF("Failed to launch firmware.");
//TODO: free ini. ini_free_section(cfg_sec);
btn_wait(); btn_wait();
} }
@ -1310,19 +1315,19 @@ int fix_attributes(char *path, u32 *total)
u32 k = 0; u32 k = 0;
static FILINFO fno; static FILINFO fno;
/* Open directory */ // Open directory
res = f_opendir(&dir, path); res = f_opendir(&dir, path);
if (res == FR_OK) if (res == FR_OK)
{ {
for (;;) for (;;)
{ {
//Read a directory item. // Read a directory item.
res = f_readdir(&dir, &fno); res = f_readdir(&dir, &fno);
//Break on error or end of dir. // Break on error or end of dir.
if (res != FR_OK || fno.fname[0] == 0) if (res != FR_OK || fno.fname[0] == 0)
break; break;
//Set new directory // Set new directory
i = strlen(path); i = strlen(path);
memcpy(&path[i], "/", 1); memcpy(&path[i], "/", 1);
for (k = 0; k < 256; k++) for (k = 0; k < 256; k++)
@ -1333,23 +1338,23 @@ int fix_attributes(char *path, u32 *total)
memcpy(&path[i+1], fno.fname, k + 1); memcpy(&path[i+1], fno.fname, k + 1);
path[i + k + 2] = 0; path[i + k + 2] = 0;
//Check if archive bit is set // Check if archive bit is set
if (fno.fattrib & AM_ARC) if (fno.fattrib & AM_ARC)
{ {
*(u32 *)total = *(u32 *)total + 1; *(u32 *)total = *(u32 *)total + 1;
f_chmod(path, 0, AM_ARC); f_chmod(path, 0, AM_ARC);
} }
/* Is it a directory? */ // Is it a directory?
if (fno.fattrib & AM_DIR) if (fno.fattrib & AM_DIR)
{ {
//Enter the directory. // Enter the directory.
res = fix_attributes(path, total); res = fix_attributes(path, total);
if (res != FR_OK) if (res != FR_OK)
break; break;
} }
//Clear file or folder path. // Clear file or folder path.
path[i] = 0; path[i] = 0;
} }
f_closedir(&dir); f_closedir(&dir);
@ -1515,7 +1520,7 @@ void ipl_main()
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_init(&gfx_con, &gfx_ctxt); gfx_con_init(&gfx_con, &gfx_ctxt);
//Enable backlight after initializing gfx // Enable backlight after initializing gfx
display_backlight(1); display_backlight(1);
while (1) while (1)

View file

@ -73,8 +73,8 @@ int max77620_regulator_get_status(u32 id)
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
if (reg->type == REGULATOR_SD) if (reg->type == REGULATOR_SD)
return i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask ? 0 : 1; return (i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1;
return i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8 ? 1 : 0; return (i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8) ? 1 : 0;
} }
int max77620_regulator_config_fps(u32 id) int max77620_regulator_config_fps(u32 id)

View file

@ -55,7 +55,7 @@ PATCHSET_DEF(_secmon_4_patchset,
{ 0x2300 + 0x5D80, _NOP() }, //package2 structure. { 0x2300 + 0x5D80, _NOP() }, //package2 structure.
{ 0x2300 + 0x5D8C, _NOP() }, //Version. { 0x2300 + 0x5D8C, _NOP() }, //Version.
{ 0x2300 + 0x5EFC, _NOP() }, //Header signature. { 0x2300 + 0x5EFC, _NOP() }, //Header signature.
{ 0xAC8 + 0xA2C, _NOP() } //Sections SHA2. { 0xAC8 + 0xA2C, _NOP() } //Sections SHA2.
); );
PATCHSET_DEF(_secmon_5_patchset, PATCHSET_DEF(_secmon_5_patchset,

View file

@ -849,7 +849,7 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20]; raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16]; raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
storage->ssr.bus_width = unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4 ? 4 : 1; storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
switch(unstuff_bits(raw_ssr1, 440 - 384, 8)) switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
{ {
case 0: case 0:

View file

@ -40,8 +40,7 @@ void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol)
void *tui_do_menu(gfx_con_t *con, menu_t *menu) void *tui_do_menu(gfx_con_t *con, menu_t *menu)
{ {
int idx = 0, cnt = 0; int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF;
int prev_idx = 0;
gfx_clear_grey(con->gfx_ctxt, 0x1B); gfx_clear_grey(con->gfx_ctxt, 0x1B);
@ -56,7 +55,7 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
menu->ents[idx].type == MENT_CHGLINE) menu->ents[idx].type == MENT_CHGLINE)
{ {
if (prev_idx <= idx || (!idx && prev_idx == cnt - 1)) if (prev_idx <= idx || (!idx && prev_idx == cnt - 1))
{ {
idx++; idx++;
if (idx > (cnt - 1)) if (idx > (cnt - 1))
{ {
@ -83,9 +82,9 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
gfx_con_setcol(con, 0xFF1B1B1B, 1, 0xFFCCCCCC); gfx_con_setcol(con, 0xFF1B1B1B, 1, 0xFFCCCCCC);
else else
gfx_con_setcol(con, 0xFFCCCCCC, 1, 0xFF1B1B1B); gfx_con_setcol(con, 0xFFCCCCCC, 1, 0xFF1B1B1B);
if (cnt != idx && menu->ents[cnt].type == MENT_CAPTION) if (menu->ents[cnt].type == MENT_CAPTION)
gfx_printf(con, "%k %s", menu->ents[cnt].color, menu->ents[cnt].caption); gfx_printf(con, "%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);
else else if (menu->ents[cnt].type != MENT_CHGLINE)
gfx_printf(con, " %s", menu->ents[cnt].caption); gfx_printf(con, " %s", menu->ents[cnt].caption);
if(menu->ents[cnt].type == MENT_MENU) if(menu->ents[cnt].type == MENT_MENU)
gfx_printf(con, "%k...", 0xFFEE9900); gfx_printf(con, "%k...", 0xFFEE9900);