Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Stefan Haun
firmware
Commits
fe9c4218
Commit
fe9c4218
authored
Aug 28, 2019
by
Rahix
Browse files
Merge 'card10.cfg'
See merge request
card10/firmware!215
parents
956c9c91
f1d63669
Changes
7
Hide whitespace changes
Inline
Side-by-side
epicardium/main.c
View file @
fe9c4218
#include
"modules/modules.h"
#include
"modules/log.h"
#include
"modules/filesystem.h"
#include
"modules/config.h"
#include
"card10-version.h"
#include
"FreeRTOS.h"
...
...
@@ -20,6 +21,8 @@ int main(void)
LOG_DEBUG
(
"startup"
,
"Initializing hardware ..."
);
hardware_early_init
();
load_config
();
/*
* Version Splash
*/
...
...
epicardium/meson.build
View file @
fe9c4218
...
...
@@ -70,7 +70,7 @@ subdir('ble/')
subdir('l0der/')
epicardium_cargs = []
epicardium_cargs = [
'-D_POSIX_C_SOURCE=200809'
]
if get_option('jailbreak_card10')
epicardium_cargs += [
'-DJAILBREAK_CARD10=1',
...
...
epicardium/modules/config.c
0 → 100644
View file @
fe9c4218
#include
"modules/log.h"
#include
"modules/config.h"
#include
"modules/filesystem.h"
#include
<assert.h>
#include
<stdbool.h>
#include
<ctype.h>
#include
<string.h>
#include
<stdlib.h>
#include
<unistd.h>
#define CONFIG_MAX_LINE_LENGTH 80
enum
OptionType
{
OptionType_Boolean
,
OptionType_Int
,
OptionType_Float
,
OptionType_String
,
};
struct
config_option
{
const
char
*
name
;
enum
OptionType
type
;
union
{
bool
boolean
;
long
integer
;
double
floating_point
;
char
*
string
;
}
value
;
};
static
struct
config_option
s_options
[
_EpicOptionCount
]
=
{
/* clang-format off */
#define INIT_Boolean(v) { .boolean = (v) }
#define INIT_Int(v) { .integer = (v) }
#define INIT_Float(v) { .floating_point = (v) }
#define INIT_String(v) { .string = (v) }
#define INIT_(tp, v) INIT_ ## tp (v)
#define INIT(tp, v) INIT_ (tp, v)
#define CARD10_SETTING(identifier, spelling, tp, default_value) \
[Option ## identifier] = { .name = (spelling), \
.type = OptionType_ ## tp, \
.value = INIT(tp, (default_value)) },
#include
"modules/config.def"
/* clang-format on */
};
static
struct
config_option
*
findOption
(
const
char
*
key
)
{
for
(
int
i
=
0
;
i
<
_EpicOptionCount
;
++
i
)
{
if
(
!
strcmp
(
key
,
s_options
[
i
].
name
))
{
return
&
s_options
[
i
];
}
}
return
NULL
;
}
static
bool
set_bool
(
struct
config_option
*
opt
,
const
char
*
value
)
{
bool
val
;
if
(
!
strcmp
(
value
,
"1"
))
{
val
=
true
;
}
else
if
(
!
strcmp
(
value
,
"true"
))
{
val
=
true
;
}
else
if
(
!
strcmp
(
value
,
"0"
))
{
val
=
false
;
}
else
if
(
!
strcmp
(
value
,
"false"
))
{
val
=
false
;
}
else
{
return
false
;
}
opt
->
value
.
boolean
=
val
;
LOG_DEBUG
(
"card10.cfg"
,
"setting '%s' to %s"
,
opt
->
name
,
val
?
"true"
:
"false"
);
return
true
;
}
static
bool
set_int
(
struct
config_option
*
opt
,
const
char
*
value
)
{
char
*
endptr
;
size_t
len
=
strlen
(
value
);
int
v
=
strtol
(
value
,
&
endptr
,
0
);
if
(
endptr
!=
(
value
+
len
))
{
return
false
;
}
opt
->
value
.
integer
=
v
;
LOG_DEBUG
(
"card10.cfg"
,
"setting '%s' to %d (0x%08x)"
,
opt
->
name
,
v
,
v
);
return
true
;
}
static
bool
set_float
(
struct
config_option
*
opt
,
const
char
*
value
)
{
char
*
endptr
;
size_t
len
=
strlen
(
value
);
double
v
=
strtod
(
value
,
&
endptr
);
if
(
endptr
!=
(
value
+
len
))
{
return
false
;
}
opt
->
value
.
floating_point
=
v
;
LOG_DEBUG
(
"card10.cfg"
,
"setting '%s' to %f"
,
opt
->
name
,
v
);
return
true
;
}
const
char
*
elide
(
const
char
*
str
)
{
static
char
ret
[
21
];
size_t
len
=
strlen
(
str
);
if
(
len
<=
20
)
{
return
str
;
}
strncpy
(
ret
,
str
,
17
);
ret
[
17
]
=
'.'
;
ret
[
18
]
=
'.'
;
ret
[
19
]
=
'.'
;
ret
[
20
]
=
'\0'
;
return
ret
;
}
static
bool
set_string
(
struct
config_option
*
opt
,
const
char
*
value
)
{
//this leaks, but the lifetime of these ends when epicardium exits, so...
char
*
leaks
=
strdup
(
value
);
opt
->
value
.
string
=
leaks
;
LOG_DEBUG
(
"card10.cfg"
,
"setting '%s' to %s"
,
opt
->
name
,
elide
(
leaks
));
return
true
;
}
static
void
configure
(
const
char
*
key
,
const
char
*
value
,
int
lineNumber
)
{
struct
config_option
*
opt
=
findOption
(
key
);
if
(
!
opt
)
{
//invalid key
LOG_WARN
(
"card10.cfg"
,
"line %d: ignoring unknown option '%s'"
,
lineNumber
,
key
);
return
;
}
bool
ok
=
false
;
switch
(
opt
->
type
)
{
case
OptionType_Boolean
:
ok
=
set_bool
(
opt
,
value
);
break
;
case
OptionType_Int
:
ok
=
set_int
(
opt
,
value
);
break
;
case
OptionType_Float
:
ok
=
set_float
(
opt
,
value
);
break
;
case
OptionType_String
:
ok
=
set_string
(
opt
,
value
);
break
;
default:
assert
(
0
&&
"unreachable"
);
}
if
(
!
ok
)
{
LOG_WARN
(
"card10.cfg"
,
"line %d: ignoring invalid value '%s' for option '%s'"
,
lineNumber
,
value
,
key
);
}
}
static
void
doline
(
char
*
line
,
char
*
eol
,
int
lineNumber
)
{
//skip leading whitespace
while
(
*
line
&&
isspace
(
*
line
))
++
line
;
char
*
key
=
line
;
if
(
*
key
==
'#'
)
{
//skip comments
return
;
}
char
*
eq
=
strchr
(
line
,
'='
);
if
(
!
eq
)
{
if
(
*
key
)
{
LOG_WARN
(
"card10.cfg"
,
"line %d (%s): syntax error"
,
lineNumber
,
elide
(
line
)
);
}
return
;
}
char
*
e_key
=
eq
-
1
;
//skip trailing whitespace in key
while
(
e_key
>
key
&&
isspace
(
*
e_key
))
--
e_key
;
e_key
[
1
]
=
'\0'
;
if
(
*
key
==
'\0'
)
{
LOG_WARN
(
"card10.cfg"
,
"line %d: empty key"
,
lineNumber
);
return
;
}
char
*
value
=
eq
+
1
;
//skip leading whitespace
while
(
*
value
&&
isspace
(
*
value
))
++
value
;
char
*
e_val
=
eol
-
1
;
//skip trailing whitespace
while
(
e_val
>
value
&&
isspace
(
*
e_val
))
--
e_val
;
if
(
*
value
==
'\0'
)
{
LOG_WARN
(
"card10.cfg"
,
"line %d: empty value for option '%s'"
,
lineNumber
,
key
);
return
;
}
configure
(
key
,
value
,
lineNumber
);
}
bool
config_get_boolean
(
enum
EpicConfigOption
option
)
{
struct
config_option
*
opt
=
&
s_options
[
option
];
assert
(
opt
->
type
==
OptionType_Boolean
);
return
opt
->
value
.
boolean
;
}
long
config_get_integer
(
enum
EpicConfigOption
option
)
{
struct
config_option
*
opt
=
&
s_options
[
option
];
assert
(
opt
->
type
==
OptionType_Int
);
return
opt
->
value
.
integer
;
}
double
config_get_float
(
enum
EpicConfigOption
option
)
{
struct
config_option
*
opt
=
&
s_options
[
option
];
assert
(
opt
->
type
==
OptionType_Float
);
return
opt
->
value
.
floating_point
;
}
const
char
*
config_get_string
(
enum
EpicConfigOption
option
)
{
struct
config_option
*
opt
=
&
s_options
[
option
];
assert
(
opt
->
type
==
OptionType_String
);
return
opt
->
value
.
string
;
}
void
load_config
(
void
)
{
LOG_DEBUG
(
"card10.cfg"
,
"loading..."
);
int
fd
=
epic_file_open
(
"card10.cfg"
,
"r"
);
if
(
fd
<
0
)
{
LOG_DEBUG
(
"card10.cfg"
,
"loading failed: %s (%d)"
,
strerror
(
-
fd
),
fd
);
return
;
}
char
buf
[
CONFIG_MAX_LINE_LENGTH
];
int
lineNumber
=
0
;
int
nread
;
do
{
//zero-terminate in case file is empty
buf
[
0
]
=
'\0'
;
nread
=
epic_file_read
(
fd
,
buf
,
sizeof
(
buf
));
if
(
nread
<
sizeof
(
buf
))
{
//add fake EOL to ensure termination
buf
[
nread
]
=
'\n'
;
}
char
*
line
=
buf
;
char
*
eol
=
NULL
;
int
last_eol
=
0
;
while
(
line
)
{
//line points one character past the las (if any) '\n' hence '- 1'
last_eol
=
line
-
buf
-
1
;
eol
=
strchr
(
line
,
'\n'
);
++
lineNumber
;
if
(
eol
)
{
*
eol
=
'\0'
;
doline
(
line
,
eol
,
lineNumber
);
line
=
eol
+
1
;
}
else
{
if
(
line
==
buf
)
{
//line did not fit into buf
LOG_WARN
(
"card10.cfg"
,
"line:%d: too long - aborting"
,
lineNumber
);
return
;
}
else
{
int
seek_back
=
last_eol
-
nread
;
LOG_DEBUG
(
"card10.cfg"
,
"nread, last_eol, seek_back: %d,%d,%d"
,
nread
,
last_eol
,
seek_back
);
assert
(
seek_back
<=
0
);
if
(
seek_back
)
{
int
rc
=
epic_file_seek
(
fd
,
seek_back
,
SEEK_CUR
);
if
(
rc
<
0
)
{
LOG_ERR
(
"card10.cfg"
,
"seek failed, aborting"
);
return
;
}
char
newline
;
rc
=
epic_file_read
(
fd
,
&
newline
,
1
);
if
(
rc
<
0
||
newline
!=
'\n'
)
{
LOG_ERR
(
"card10.cfg"
,
"seek failed, aborting"
);
LOG_DEBUG
(
"card10.cfg"
,
"seek failed at read-back of newline: rc: %d read: %d"
,
rc
,
(
int
)
newline
);
return
;
}
}
break
;
}
}
}
}
while
(
nread
==
sizeof
(
buf
));
}
epicardium/modules/config.def
0 → 100644
View file @
fe9c4218
#ifndef CARD10_SETTING
# define CARD10_SETTING(identifier, spelling, type, default_value)
#endif
CARD10_SETTING(ExecuteElf, "execute_elf", Boolean, false)
//CARD10_SETTING(Nick, "nick", String, "an0n")
//CARD10_SETTING(Timeout, "timeout", Integer, 123)
//CARD10_SETTING(Dampening, "dampening", Float, 420)
#undef CARD10_SETTING
epicardium/modules/config.h
0 → 100644
View file @
fe9c4218
#ifndef EPICARDIUM_MODULES_CONFIG_H_INCLUDED
#define EPICARDIUM_MODULES_CONFIG_H_INCLUDED
#include
<stdbool.h>
enum
EpicConfigOption
{
#define CARD10_SETTING(identifier, spelling, type, default_value) Option ## identifier,
#include
"modules/config.def"
_EpicOptionCount
};
//initialize configuration values and load card10.cfg
void
load_config
(
void
);
bool
config_get_boolean
(
enum
EpicConfigOption
option
);
long
config_get_integer
(
enum
EpicConfigOption
option
);
double
config_get_float
(
enum
EpicConfigOption
option
);
const
char
*
config_get_string
(
enum
EpicConfigOption
option
);
#endif//EPICARDIUM_MODULES_CONFIG_H_INCLUDED
epicardium/modules/lifecycle.c
View file @
fe9c4218
#include
"epicardium.h"
#include
"modules/log.h"
#include
"modules/modules.h"
#include
"modules/config.h"
#include
"api/dispatcher.h"
#include
"api/interrupt-sender.h"
#include
"l0der/l0der.h"
...
...
@@ -49,6 +50,7 @@ static volatile struct load_info async_load = {
/* Whether to write the menu script before attempting to load. */
static
volatile
bool
write_menu
=
false
;
static
bool
execute_elfs
=
false
;
/* Helpers {{{ */
...
...
@@ -88,9 +90,7 @@ static int load_stat(char *name)
*/
static
int
do_load
(
struct
load_info
*
info
)
{
#if defined(JAILBREAK_CARD10) && (JAILBREAK_CARD10 == 1)
struct
l0dable_info
l0dable
;
#endif
int
res
;
if
(
*
info
->
name
==
'\0'
)
{
...
...
@@ -129,18 +129,22 @@ static int do_load(struct load_info *info)
case
PL_PYTHON_INTERP
:
core1_load
(
PYCARDIUM_IVT
,
info
->
name
);
break
;
#if defined(JAILBREAK_CARD10) && (JAILBREAK_CARD10 == 1)
case
PL_L0DABLE
:
res
=
l0der_load_path
(
info
->
name
,
&
l0dable
);
if
(
res
!=
0
)
{
LOG_ERR
(
"lifecycle"
,
"l0der failed: %d
\n
"
,
res
);
xSemaphoreGive
(
api_mutex
);
return
-
ENOEXEC
;
if
(
execute_elfs
)
{
res
=
l0der_load_path
(
info
->
name
,
&
l0dable
);
if
(
res
!=
0
)
{
LOG_ERR
(
"lifecycle"
,
"l0der failed: %d
\n
"
,
res
);
xSemaphoreGive
(
api_mutex
);
return
-
ENOEXEC
;
}
core1_load
(
l0dable
.
isr_vector
,
""
);
}
else
{
LOG_WARN
(
"lifecycle"
,
"Execution of .elf l0dables is disabled"
);
}
core1_load
(
l0dable
.
isr_vector
,
""
);
break
;
#endif
default:
LOG_ERR
(
"lifecyle"
,
"Attempted to load invalid payload (%s)"
,
...
...
@@ -379,6 +383,8 @@ void vLifecycleTask(void *pvParameters)
hardware_init
();
execute_elfs
=
config_get_boolean
(
OptionExecuteElf
);
/* When triggered, reset core 1 to menu */
while
(
1
)
{
ulTaskNotifyTake
(
pdTRUE
,
portMAX_DELAY
);
...
...
epicardium/modules/meson.build
View file @
fe9c4218
...
...
@@ -21,5 +21,6 @@ module_sources = files(
'trng.c',
'vibra.c',
'watchdog.c',
'usb.c'
'usb.c',
'config.c',
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment