diff --git a/Makefile b/Makefile
index 2b83ea7..005c5ee 100755
--- a/Makefile
+++ b/Makefile
@@ -41,6 +41,7 @@ OBJS = $(addprefix $(BUILD)/$(TARGET)/, \
se.o \
tsec.o \
uart.o \
+ dirlist.o \
ini.o \
ianos.o \
)
diff --git a/bootloader/config/config.c b/bootloader/config/config.c
index 13cb9d1..3312028 100644
--- a/bootloader/config/config.c
+++ b/bootloader/config/config.c
@@ -39,6 +39,7 @@ extern int sd_unmount();
void set_default_configuration()
{
h_cfg.autoboot = 0;
+ h_cfg.autoboot_list = 0;
h_cfg.bootwait = 3;
h_cfg.customlogo = 0;
h_cfg.verification = 2;
@@ -56,7 +57,7 @@ int create_config_entry()
LIST_INIT(ini_sections);
- if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini"))
+ if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{
if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
return 0;
@@ -64,6 +65,9 @@ int create_config_entry()
f_puts("[config]\nautoboot=", &fp);
itoa(h_cfg.autoboot, lbuf, 10);
f_puts(lbuf, &fp);
+ f_puts("\nautoboot_list=", &fp);
+ itoa(h_cfg.autoboot_list, lbuf, 10);
+ f_puts(lbuf, &fp);
f_puts("\nbootwait=", &fp);
itoa(h_cfg.bootwait, lbuf, 10);
f_puts(lbuf, &fp);
@@ -123,7 +127,7 @@ int create_config_entry()
return 0;
}
-void config_autoboot()
+void _config_autoboot_list()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
@@ -143,7 +147,112 @@ void config_autoboot()
if (sd_mount())
{
- if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini"))
+ if (ini_parse(&ini_sections, "bootloader/ini", true))
+ {
+ // Build configuration menu.
+ ments[0].type = MENT_BACK;
+ ments[0].caption = "Back";
+
+ ments[1].type = MENT_CHGLINE;
+
+ u32 i = 2;
+ LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
+ {
+ // Skip other ini entries for autoboot.
+ if (ini_sec->type == INI_CHOICE)
+ {
+ if (!strcmp(ini_sec->name, "config"))
+ continue;
+
+ if (strlen(ini_sec->name) > 510)
+ ments[i].caption = ini_sec->name;
+ else
+ {
+ if (h_cfg.autoboot != (i - 1) || !h_cfg.autoboot_list)
+ boot_text[(i - 1) * 512] = ' ';
+
+ else
+ boot_text[(i - 1) * 512] = '*';
+ memcpy(boot_text + (i - 1) * 512 + 1, ini_sec->name, strlen(ini_sec->name));
+ boot_text[strlen(ini_sec->name) + (i - 1) * 512 + 1] = 0;
+ ments[i].caption = &boot_text[(i - 1) * 512];
+ }
+ ments[i].type = ini_sec->type;
+ ments[i].data = &boot_values[i - 1];
+ i++;
+
+ if ((i - 1) > max_entries)
+ break;
+ }
+ }
+ if (i < 3)
+ {
+ EPRINTF("No launch configurations found.");
+ goto out;
+ }
+
+ memset(&ments[i], 0, sizeof(ment_t));
+ menu_t menu = {ments, "Select a list entry to auto boot", 0, 0};
+ temp_autoboot = (u32 *)tui_do_menu(&gfx_con, &menu);
+ if (temp_autoboot != NULL)
+ {
+ gfx_clear_grey(&gfx_ctxt, 0x1B);
+ gfx_con_setpos(&gfx_con, 0, 0);
+
+ h_cfg.autoboot = *(u32 *)temp_autoboot;
+ h_cfg.autoboot_list = 1;
+ // Save choice to ini file.
+ if (!create_config_entry())
+ gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
+ else
+ EPRINTF("\nConfiguration saving failed!");
+ gfx_puts(&gfx_con, "\nPress any key...");
+ }
+ else
+ goto out2;
+ }
+ else
+ {
+ EPRINTF("Could not find or open 'hekate_ipl.ini'.\nMake sure it exists in SD Card!.");
+ goto out;
+ }
+ }
+
+out:;
+ btn_wait();
+out2:;
+ free(ments);
+ free(boot_values);
+ free(boot_text);
+ ini_free(&ini_sections);
+
+ sd_unmount();
+
+ if (temp_autoboot == NULL)
+ return;
+}
+
+void config_autoboot()
+{
+ gfx_clear_grey(&gfx_ctxt, 0x1B);
+ gfx_con_setpos(&gfx_con, 0, 0);
+
+ u32 *temp_autoboot = NULL;
+
+ LIST_INIT(ini_sections);
+
+ u8 max_entries = 30;
+
+ ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 5));
+ u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries);
+ char *boot_text = (char *)malloc(512 * max_entries);
+
+ for (u32 j = 0; j < max_entries; j++)
+ boot_values[j] = j;
+
+ if (sd_mount())
+ {
+ if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{
// Build configuration menu.
ments[0].type = MENT_BACK;
@@ -158,7 +267,17 @@ void config_autoboot()
ments[2].caption = " Disable";
ments[2].data = &boot_values[0];
- u32 i = 3;
+ ments[3].type = MENT_HANDLER;
+ if (h_cfg.autoboot_list)
+ ments[3].caption = "*More configs...";
+ else
+ ments[3].caption = " More configs...";
+ ments[3].handler = _config_autoboot_list;
+ ments[3].data = NULL;
+
+ ments[4].type = MENT_CHGLINE;
+
+ u32 i = 5;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
// Skip other ini entries for autoboot.
@@ -171,24 +290,24 @@ void config_autoboot()
ments[i].caption = ini_sec->name;
else
{
- if (h_cfg.autoboot != (i - 2))
- boot_text[(i - 2) * 512] = ' ';
+ if (h_cfg.autoboot != (i - 4) || h_cfg.autoboot_list)
+ boot_text[(i - 4) * 512] = ' ';
else
- boot_text[(i - 2) * 512] = '*';
- memcpy(boot_text + (i - 2) * 512 + 1, ini_sec->name, strlen(ini_sec->name));
- boot_text[strlen(ini_sec->name) + (i - 2) * 512 + 1] = 0;
- ments[i].caption = &boot_text[(i - 2) * 512];
+ boot_text[(i - 4) * 512] = '*';
+ memcpy(boot_text + (i - 4) * 512 + 1, ini_sec->name, strlen(ini_sec->name));
+ boot_text[strlen(ini_sec->name) + (i - 4) * 512 + 1] = 0;
+ ments[i].caption = &boot_text[(i - 4) * 512];
}
ments[i].type = ini_sec->type;
- ments[i].data = &boot_values[i - 2];
+ ments[i].data = &boot_values[i - 4];
i++;
- if (i > max_entries)
+ if ((i - 4) > max_entries)
break;
}
}
- if (i < 4)
+ if (i < 6 && !h_cfg.autoboot_list)
{
EPRINTF("No launch configurations found.");
goto out;
@@ -203,6 +322,7 @@ void config_autoboot()
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.autoboot = *(u32 *)temp_autoboot;
+ h_cfg.autoboot_list = 0;
// Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
diff --git a/bootloader/config/config.h b/bootloader/config/config.h
index a3bbd7b..a50132a 100644
--- a/bootloader/config/config.h
+++ b/bootloader/config/config.h
@@ -22,6 +22,7 @@
typedef struct _hekate_config
{
u32 autoboot;
+ u32 autoboot_list;
u32 bootwait;
u32 customlogo;
u32 verification;
diff --git a/bootloader/config/ini.c b/bootloader/config/ini.c
index 54b25b6..80e3acf 100644
--- a/bootloader/config/ini.c
+++ b/bootloader/config/ini.c
@@ -20,119 +20,162 @@
#include "ini.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
+#include "../utils/dirlist.h"
static char *_strdup(char *str)
{
- char *res = malloc(strlen(str) + 1);
+ char *res = (char *)malloc(strlen(str) + 1);
strcpy(res, str);
return res;
}
-int ini_parse(link_t *dst, char *ini_path)
+int ini_parse(link_t *dst, char *ini_path, bool is_dir)
{
u32 lblen;
+ u32 pathlen = strlen(ini_path);
+ u32 k = 0;
char lbuf[512];
+ char *filelist = NULL;
FIL fp;
ini_sec_t *csec = NULL;
- if (f_open(&fp, ini_path, FA_READ) != FR_OK)
- return 0;
+ char *filename = (char *)malloc(256);
+
+ memcpy(filename, ini_path, pathlen + 1);
+
+ if (is_dir)
+ {
+ filelist = dirlist(filename);
+ if (!filelist)
+ {
+ free(filename);
+ return 0;
+ }
+ memcpy(filename + pathlen, "/", 2);
+ pathlen++;
+ }
do
{
- // Fetch one line.
- lbuf[0] = 0;
- f_gets(lbuf, 512, &fp);
- lblen = strlen(lbuf);
-
- // Remove trailing newline.
- if (lbuf[lblen - 1] == '\n')
- lbuf[lblen - 1] = 0;
-
- if (lblen > 2 && lbuf[0] == '[') // Create new section.
+ if (is_dir)
{
- if (csec)
+ if (filelist[k * 256])
{
- list_append(dst, &csec->link);
- csec = NULL;
+ memcpy(filename + pathlen, &filelist[k * 256], strlen(&filelist[k * 256]) + 1);
+ k++;
}
-
- u32 i;
- for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != ']'; i++)
- ;
- lbuf[i] = 0;
-
- csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
- csec->name = _strdup(&lbuf[1]);
- csec->type = INI_CHOICE;
- list_init(&csec->kvs);
+ else
+ break;
}
- else if (lblen > 2 && lbuf[0] == '{') //Create new caption.
+
+ if (f_open(&fp, filename, FA_READ) != FR_OK)
{
- if (csec)
+ free(filelist);
+ free(filename);
+
+ return 0;
+ }
+
+ do
+ {
+ // Fetch one line.
+ lbuf[0] = 0;
+ f_gets(lbuf, 512, &fp);
+ lblen = strlen(lbuf);
+
+ // Remove trailing newline.
+ if (lbuf[lblen - 1] == '\n')
+ lbuf[lblen - 1] = 0;
+
+ if (lblen > 2 && lbuf[0] == '[') // Create new section.
{
- list_append(dst, &csec->link);
- csec = NULL;
+ if (csec)
+ {
+ list_append(dst, &csec->link);
+ csec = NULL;
+ }
+
+ u32 i;
+ for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != ']'; i++)
+ ;
+ lbuf[i] = 0;
+
+ csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
+ csec->name = _strdup(&lbuf[1]);
+ csec->type = INI_CHOICE;
+ list_init(&csec->kvs);
}
-
- u32 i;
- for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '}'; i++)
- ;
- lbuf[i] = 0;
-
- csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
- csec->name = _strdup(&lbuf[1]);
- csec->type = INI_CAPTION;
- csec->color = 0xFF0AB9E6;
- }
- else if (lblen > 2 && lbuf[0] == '#') //Create empty lines and comments.
- {
- if (csec)
+ else if (lblen > 2 && lbuf[0] == '{') //Create new caption.
{
- list_append(dst, &csec->link);
- csec = NULL;
+ if (csec)
+ {
+ list_append(dst, &csec->link);
+ csec = NULL;
+ }
+
+ u32 i;
+ for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '}'; i++)
+ ;
+ lbuf[i] = 0;
+
+ csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
+ csec->name = _strdup(&lbuf[1]);
+ csec->type = INI_CAPTION;
+ csec->color = 0xFF0AB9E6;
}
-
- u32 i;
- for (i = 0; i < lblen && lbuf[i] != '\n'; i++)
- ;
- lbuf[i] = 0;
-
- csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
- csec->name = _strdup(&lbuf[1]);
- csec->type = INI_COMMENT;
- }
- else if (lblen <= 1)
- {
- if (csec)
+ else if (lblen > 2 && lbuf[0] == '#') //Create empty lines and comments.
{
- list_append(dst, &csec->link);
- csec = NULL;
+ if (csec)
+ {
+ list_append(dst, &csec->link);
+ csec = NULL;
+ }
+
+ u32 i;
+ for (i = 0; i < lblen && lbuf[i] != '\n'; i++)
+ ;
+ lbuf[i] = 0;
+
+ csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
+ csec->name = _strdup(&lbuf[1]);
+ csec->type = INI_COMMENT;
}
+ else if (lblen < 2)
+ {
+ if (csec)
+ {
+ list_append(dst, &csec->link);
+ csec = NULL;
+ }
- csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
- csec->name = NULL;
- csec->type = INI_NEWLINE;
- }
- else if (csec->type == INI_CHOICE) //Extract key/value.
- {
- u32 i;
- for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '='; i++)
- ;
- lbuf[i] = 0;
+ csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
+ csec->name = NULL;
+ csec->type = INI_NEWLINE;
+ }
+ else if (csec->type == INI_CHOICE) //Extract key/value.
+ {
+ u32 i;
+ for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '='; i++)
+ ;
+ lbuf[i] = 0;
- ini_kv_t *kv = (ini_kv_t *)malloc(sizeof(ini_kv_t));
- kv->key = _strdup(&lbuf[0]);
- kv->val = _strdup(&lbuf[i + 1]);
- list_append(&csec->kvs, &kv->link);
- }
- } while (!f_eof(&fp));
+ ini_kv_t *kv = (ini_kv_t *)malloc(sizeof(ini_kv_t));
+ kv->key = _strdup(&lbuf[0]);
+ kv->val = _strdup(&lbuf[i + 1]);
+ list_append(&csec->kvs, &kv->link);
+ }
+ } while (!f_eof(&fp));
- f_close(&fp);
+ f_close(&fp);
+
+ } while (is_dir);
if (csec)
list_append(dst, &csec->link);
+ free(filename);
+ free(filelist);
+
return 1;
}
diff --git a/bootloader/config/ini.h b/bootloader/config/ini.h
index d993992..db08cd1 100644
--- a/bootloader/config/ini.h
+++ b/bootloader/config/ini.h
@@ -43,7 +43,7 @@ typedef struct _ini_sec_t
u32 color;
} ini_sec_t;
-int ini_parse(link_t *dst, char *ini_path);
+int ini_parse(link_t *dst, char *ini_path, bool is_dir);
void ini_free(link_t *dst);
ini_sec_t *ini_clone_section(ini_sec_t *cfg);
void ini_free_section(ini_sec_t *cfg);
diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c
index b216eb1..346b988 100644
--- a/bootloader/hos/hos.c
+++ b/bootloader/hos/hos.c
@@ -390,7 +390,7 @@ static int _config_kip1patch(launch_ctxt_t *ctxt, const char *value)
return 0;
int valueLen = strlen(value);
- if (valueLen == 0)
+ if (!valueLen)
return 0;
if (ctxt->kip1_patches == NULL)
@@ -435,10 +435,15 @@ static const cfg_handler_t _config_handlers[] = {
static int _config(launch_ctxt_t *ctxt, ini_sec_t *cfg)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
+ {
for(u32 i = 0; _config_handlers[i].key; i++)
- if (!strcmp(_config_handlers[i].key, kv->key) &&
- !_config_handlers[i].handler(ctxt, kv->val))
- return 0;
+ {
+ if (!strcmp(_config_handlers[i].key, kv->key))
+ if (!_config_handlers[i].handler(ctxt, kv->val))
+ return 0;
+ }
+ }
+
return 1;
}
@@ -667,7 +672,7 @@ int hos_launch(ini_sec_t *cfg)
// Wait for secmon to get ready.
cluster_boot_cpu0(ctxt.pkg1_id->secmon_base);
while (!*mb_out)
- ;
+ usleep(1); // This only works when in IRAM or with a trained DRAM.
//TODO: pkg1.1 locks PMC scratches, we can do that too at some point.
/*PMC(0x4) = 0x7FFFF3;
diff --git a/bootloader/main.c b/bootloader/main.c
index 5d88262..2459c8b 100644
--- a/bootloader/main.c
+++ b/bootloader/main.c
@@ -57,6 +57,7 @@
#include "power/bq24193.h"
#include "config/config.h"
#include "ianos/ianos.h"
+#include "utils/dirlist.h"
//TODO: ugly.
gfx_ctxt_t gfx_ctxt;
@@ -1720,6 +1721,102 @@ out:
btn_wait();
}
+void ini_list_launcher()
+{
+ u8 max_entries = 61;
+ char *payload_path = NULL;
+
+ ini_sec_t *cfg_sec = NULL;
+ LIST_INIT(ini_list_sections);
+
+ gfx_clear_grey(&gfx_ctxt, 0x1B);
+ gfx_con_setpos(&gfx_con, 0, 0);
+
+ if (sd_mount())
+ {
+ if (ini_parse(&ini_list_sections, "bootloader/ini", true))
+ {
+ // Build configuration menu.
+ ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
+ ments[0].type = MENT_BACK;
+ ments[0].caption = "Back";
+ ments[1].type = MENT_CHGLINE;
+
+ u32 i = 2;
+ LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_list_sections, link)
+ {
+ if (!strcmp(ini_sec->name, "config") ||
+ ini_sec->type == INI_COMMENT || ini_sec->type == INI_NEWLINE)
+ continue;
+ ments[i].type = ini_sec->type;
+ ments[i].caption = ini_sec->name;
+ ments[i].data = ini_sec;
+ if (ini_sec->type == MENT_CAPTION)
+ ments[i].color = ini_sec->color;
+ i++;
+
+ if ((i - 1) > max_entries)
+ break;
+ }
+ if (i > 2)
+ {
+ memset(&ments[i], 0, sizeof(ment_t));
+ menu_t menu = {
+ ments, "Launch ini configurations", 0, 0
+ };
+ cfg_sec = ini_clone_section((ini_sec_t *)tui_do_menu(&gfx_con, &menu));
+ if (!cfg_sec)
+ {
+ free(ments);
+ ini_free(&ini_list_sections);
+
+ return;
+ }
+ }
+ else
+ EPRINTF("No ini configurations found.");
+ free(ments);
+ //ini_free(&ini_list_sections); // This breaks hos_launch config parsing.
+ }
+ else
+ EPRINTF("Could not find any ini\nin bootloader/ini folder!");
+ }
+
+ if (!cfg_sec)
+ goto out;
+
+#ifdef MENU_LOGO_ENABLE
+ free(Kc_MENU_LOGO);
+#endif //MENU_LOGO_ENABLE
+
+ payload_path = ini_check_payload_section(cfg_sec);
+
+ if (payload_path)
+ {
+ ini_free_section(cfg_sec);
+ //if (launch_payload(payload_path, false))
+ //{
+ EPRINTF("Failed to launch payload.");
+ free(payload_path);
+ //}
+ }
+ else if (!hos_launch(cfg_sec))
+ {
+ EPRINTF("Failed to launch firmware.");
+ btn_wait();
+ }
+
+#ifdef MENU_LOGO_ENABLE
+ Kc_MENU_LOGO = (u8 *)malloc(0x6000);
+ blz_uncompress_srcdest(Kc_MENU_LOGO_blz, SZ_MENU_LOGO_BLZ, Kc_MENU_LOGO, SZ_MENU_LOGO);
+#endif //MENU_LOGO_ENABLE
+
+out:
+ ini_free_section(cfg_sec);
+
+ btn_wait();
+}
+
void launch_firmware()
{
u8 max_entries = 61;
@@ -1732,15 +1829,21 @@ void launch_firmware()
if (sd_mount())
{
- if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini"))
+ if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{
// Build configuration menu.
- ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
+ ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 5));
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
- u32 i = 2;
+ ments[2].type = MENT_HANDLER;
+ ments[2].caption = "More configs...";
+ ments[2].handler = ini_list_launcher;
+
+ ments[3].type = MENT_CHGLINE;
+
+ u32 i = 4;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
if (!strcmp(ini_sec->name, "config") ||
@@ -1753,10 +1856,10 @@ void launch_firmware()
ments[i].color = ini_sec->color;
i++;
- if (i > max_entries)
+ if ((i - 3) > max_entries)
break;
}
- if (i > 2)
+ if (i > 4)
{
memset(&ments[i], 0, sizeof(ment_t));
menu_t menu = {
@@ -1828,12 +1931,15 @@ void auto_launch_firmware()
ini_sec_t *cfg_sec = NULL;
LIST_INIT(ini_sections);
+ LIST_INIT(ini_list_sections);
gfx_con.mute = true;
if (sd_mount())
{
- if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini"))
+ auto_launch_update();
+
+ if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{
u32 configEntry = 0;
u32 boot_entry_id = 0;
@@ -1851,6 +1957,8 @@ void auto_launch_firmware()
{
if (!strcmp("autoboot", kv->key))
h_cfg.autoboot = atoi(kv->val);
+ else if (!strcmp("autoboot_list", kv->key))
+ h_cfg.autoboot_list = atoi(kv->val);
else if (!strcmp("bootwait", kv->key))
h_cfg.bootwait = atoi(kv->val);
else if (!strcmp("customlogo", kv->key))
@@ -1869,6 +1977,7 @@ void auto_launch_firmware()
{
if (!strcmp("logopath", kv->key))
bootlogoCustomEntry = kv->val;
+ gfx_printf(&gfx_con, "\n%s=%s\n\n", kv->key, kv->val);
}
break;
}
@@ -1876,6 +1985,43 @@ void auto_launch_firmware()
}
}
+ if (h_cfg.autoboot_list)
+ {
+ ini_free(&ini_sections);
+ list_init(&ini_sections);
+ ini_free_section(cfg_sec);
+ boot_entry_id = 1;
+ bootlogoCustomEntry = NULL;
+
+ if (ini_parse(&ini_list_sections, "bootloader/ini", true))
+ {
+ LIST_FOREACH_ENTRY(ini_sec_t, ini_sec_list, &ini_list_sections, link)
+ {
+ if (ini_sec_list->type == INI_CHOICE)
+ {
+ if (!strcmp(ini_sec_list->name, "config"))
+ continue;
+
+ if (h_cfg.autoboot == boot_entry_id)
+ {
+ cfg_sec = ini_clone_section(ini_sec_list);
+ LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
+ {
+ if (!strcmp("logopath", kv->key))
+ bootlogoCustomEntry = kv->val;
+ gfx_printf(&gfx_con, "\n%s=%s\n\n", kv->key, kv->val);
+ }
+ break;
+ }
+ boot_entry_id++;
+ }
+
+ }
+
+ }
+
+ }
+
// Add missing configuration entry.
if (!configEntry)
create_config_entry();
@@ -1969,6 +2115,8 @@ void auto_launch_firmware()
goto out;
ini_free(&ini_sections);
+ if (h_cfg.autoboot_list)
+ ini_free(&ini_list_sections);
#ifdef MENU_LOGO_ENABLE
free(Kc_MENU_LOGO);
@@ -1985,6 +2133,8 @@ void auto_launch_firmware()
out:
gfx_clear_grey(&gfx_ctxt, 0x1B);
ini_free(&ini_sections);
+ if (h_cfg.autoboot_list)
+ ini_free(&ini_list_sections);
ini_free_section(cfg_sec);
sd_unmount();
@@ -2581,7 +2731,7 @@ menu_t menu_tools = {
};
ment_t ment_top[] = {
- MDEF_HANDLER("Launch firmware", launch_firmware),
+ MDEF_HANDLER("Launch", launch_firmware),
MDEF_MENU("Launch options", &menu_options),
MDEF_CAPTION("---------------", 0xFF444444),
MDEF_MENU("Tools", &menu_tools),
diff --git a/bootloader/utils/dirlist.c b/bootloader/utils/dirlist.c
new file mode 100644
index 0000000..5c01cd9
--- /dev/null
+++ b/bootloader/utils/dirlist.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018 CTCaer
+ *
+ * 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 .
+ */
+
+#include
+#include
+
+#include "../libs/fatfs/ff.h"
+#include "../mem/heap.h"
+#include "../utils/types.h"
+
+char *dirlist(char *directory)
+{
+ u8 max_entries = 61;
+
+ int res = 0;
+ u32 i = 0, j = 0, k = 0;
+ DIR dir;
+ static FILINFO fno;
+
+ char *dir_entries = (char *)calloc(max_entries, 256);
+ char *temp = (char *)calloc(1, 256);
+
+ if (!f_opendir(&dir, directory))
+ {
+ for (;;)
+ {
+ res = f_readdir(&dir, &fno);
+ if (res || !fno.fname[0])
+ break;
+ if (!(fno.fattrib & AM_DIR))
+ {
+ memcpy(dir_entries + (k * 256), fno.fname, strlen(fno.fname) + 1);
+ k++;
+ if (k > (max_entries - 1))
+ break;
+ }
+ else
+ continue;
+ }
+ f_closedir(&dir);
+ }
+ else
+ return NULL;
+
+ for (i = 0; i < k - 1 ; i++)
+ {
+ for (j = i + 1; j < k; j++)
+ {
+ if (strcmp(&dir_entries[i * 256], &dir_entries[j * 256]) > 0)
+ {
+ memcpy(temp, &dir_entries[i * 256], strlen(&dir_entries[i * 256]) + 1);
+ memcpy(&dir_entries[i * 256], &dir_entries[j * 256], strlen(&dir_entries[j * 256]) + 1);
+ memcpy(&dir_entries[j * 256], temp, strlen(temp) + 1);
+ }
+ }
+ }
+
+ free(temp);
+
+ return dir_entries;
+}
diff --git a/bootloader/utils/dirlist.h b/bootloader/utils/dirlist.h
new file mode 100644
index 0000000..e1510e9
--- /dev/null
+++ b/bootloader/utils/dirlist.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018 CTCaer
+ *
+ * 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 .
+ */
+
+#include "../utils/types.h"
+
+char *dirlist(char *directory);