Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
F
firmware
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
External wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
fpletz
firmware
Commits
8ab8a96c
Commit
8ab8a96c
authored
5 years ago
by
Serge Bazanski
Browse files
Options
Downloads
Patches
Plain Diff
epicardium/l0der: move to epic_file API
parent
cbea5657
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
epicardium/l0der/l0der.c
+75
-98
75 additions, 98 deletions
epicardium/l0der/l0der.c
with
75 additions
and
98 deletions
epicardium/l0der/l0der.c
+
75
−
98
View file @
8ab8a96c
...
...
@@ -3,7 +3,6 @@
#include
<alloca.h>
#include
<stdio.h>
#include
<string.h>
#include
<ff.h>
#include
"epicardium.h"
#include
"l0der/elf.h"
...
...
@@ -56,46 +55,41 @@ struct _pie_load_info {
/*
* Read an ELF header, check E_IDENT.
*/
static
int
_read_elf_header
(
FIL
*
fp
,
Elf32_Ehdr
*
hdr
)
static
int
_read_elf_header
(
int
fd
,
Elf32_Ehdr
*
hdr
)
{
f_lseek
(
fp
,
0
)
;
int
res
;
unsigned
int
read
;
FRESULT
fres
=
f_read
(
fp
,
hdr
,
sizeof
(
Elf32_Ehdr
),
&
read
);
if
(
fres
!=
FR_OK
)
{
LOG_ERR
(
"l0der"
,
"_read_elf_header: f_read failed: %d"
,
fres
);
return
-
1
;
}
epic_file_seek
(
fd
,
0
,
SEEK_SET
);
if
(
read
!=
sizeof
(
Elf32_Ehdr
))
{
LOG_ERR
(
"l0der"
,
"_read_elf_header:
file truncated"
);
return
-
1
;
if
(
(
res
=
epic_file_read
(
fd
,
hdr
,
sizeof
(
Elf32_Ehdr
)))
!=
sizeof
(
Elf32_Ehdr
))
{
LOG_ERR
(
"l0der"
,
"_read_elf_header:
read failed: %d"
,
res
);
return
res
;
}
if
(
hdr
->
e_ident
[
0
]
!=
ELFMAG0
||
hdr
->
e_ident
[
1
]
!=
ELFMAG1
||
hdr
->
e_ident
[
2
]
!=
ELFMAG2
||
hdr
->
e_ident
[
3
]
!=
ELFMAG3
)
{
LOG_ERR
(
"l0der"
,
"_read_elf_header: not an ELF file"
);
return
-
1
;
return
-
ENOEXEC
;
}
if
(
hdr
->
e_ident
[
4
]
!=
ELFCLASS32
)
{
LOG_ERR
(
"l0der"
,
"_read_elf_header: not a 32-bit ELF"
);
return
-
1
;
return
-
ENOEXEC
;
}
if
(
hdr
->
e_ident
[
5
]
!=
ELFDATA2LSB
)
{
LOG_ERR
(
"l0der"
,
"_read_elf_header: not a little-endian ELF"
);
return
-
1
;
return
-
ENOEXEC
;
}
if
(
hdr
->
e_ident
[
6
]
!=
EV_CURRENT
)
{
LOG_ERR
(
"l0der"
,
"_read_elf_header: not a v1 ELF"
);
return
-
1
;
return
-
ENOEXEC
;
}
if
(
hdr
->
e_ehsize
<
sizeof
(
Elf32_Ehdr
))
{
LOG_ERR
(
"l0der"
,
"_raed_elf_header: header too small"
);
return
-
1
;
return
-
ENOEXEC
;
}
return
0
;
...
...
@@ -104,7 +98,7 @@ static int _read_elf_header(FIL *fp, Elf32_Ehdr *hdr)
/*
* Read bytes from file at a given offset.
*
* :param
FIL*
f
p
: file pointer to read from
* :param
int
f
d
: file pointer to read from
* :param uint32_t address: address from which to read
* :param void *data: buffer into which to read
* :param size_t count: amount of bytes to read
...
...
@@ -112,31 +106,21 @@ static int _read_elf_header(FIL *fp, Elf32_Ehdr *hdr)
*
* - ``-EIO``: Could not read from FAT - address out of bounds of not enough bytes available.
*/
static
int
_seek_and_read
(
FIL
*
fp
,
uint32_t
address
,
void
*
data
,
size_t
count
)
static
int
_seek_and_read
(
int
fd
,
uint32_t
address
,
void
*
data
,
size_t
count
)
{
FRESULT
f
res
;
int
res
;
if
((
f
res
=
f_l
seek
(
f
p
,
address
))
!=
FR_OK
)
{
if
((
res
=
epic_file_
seek
(
f
d
,
address
,
SEEK_SET
))
!=
0
)
{
LOG_ERR
(
"l0der"
,
"_seek_and_read: could not seek to 0x%lx: %d"
,
address
,
f
res
);
return
-
EIO
;
res
);
return
res
;
}
unsigned
int
read
;
if
((
fres
=
f_read
(
fp
,
data
,
count
,
&
read
))
!=
FR_OK
||
read
<
count
)
{
if
(
fres
==
FR_OK
)
{
LOG_ERR
(
"l0der"
,
"_seek_and_read: could not read: wanted %d bytes, got %d"
,
count
,
read
);
}
else
{
LOG_ERR
(
"l0der"
,
"_seek_and_read: could not read: %d"
,
fres
);
}
return
-
EIO
;
if
((
res
=
epic_file_read
(
fd
,
data
,
count
))
!=
count
)
{
LOG_ERR
(
"l0der"
,
"_seek_and_read: could not read: %d"
,
res
);
return
res
;
}
return
0
;
...
...
@@ -145,17 +129,17 @@ static int _seek_and_read(FIL *fp, uint32_t address, void *data, size_t count)
/*
* Read an ELF program header header.
*/
static
int
_read_program_header
(
FIL
*
fp
,
uint32_t
phdr_addr
,
Elf32_Phdr
*
phdr
)
static
int
_read_program_header
(
int
fd
,
uint32_t
phdr_addr
,
Elf32_Phdr
*
phdr
)
{
return
_seek_and_read
(
f
p
,
phdr_addr
,
phdr
,
sizeof
(
Elf32_Phdr
));
return
_seek_and_read
(
f
d
,
phdr_addr
,
phdr
,
sizeof
(
Elf32_Phdr
));
}
/*
* Read an ELF section header header.
*/
static
int
_read_section_header
(
FIL
*
fp
,
uint32_t
shdr_addr
,
Elf32_Shdr
*
shdr
)
static
int
_read_section_header
(
int
fd
,
uint32_t
shdr_addr
,
Elf32_Shdr
*
shdr
)
{
return
_seek_and_read
(
f
p
,
shdr_addr
,
shdr
,
sizeof
(
Elf32_Shdr
));
return
_seek_and_read
(
f
d
,
shdr_addr
,
shdr
,
sizeof
(
Elf32_Shdr
));
}
/*
...
...
@@ -164,10 +148,8 @@ static int _read_section_header(FIL *fp, uint32_t shdr_addr, Elf32_Shdr *shdr)
* This function ensures basic memory sanity of a program header / segment.
* It ensures that it points to a file region that is contained within the file fully.
*/
static
int
_check_program_header
(
FIL
*
fp
,
Elf32_Phdr
*
phdr
)
static
int
_check_program_header
(
int
fd
,
int
size
,
Elf32_Phdr
*
phdr
)
{
size_t
size
=
f_size
(
fp
);
// Check file size/offset.
uint32_t
file_start
=
phdr
->
p_offset
;
uint32_t
file_limit
=
phdr
->
p_offset
+
phdr
->
p_filesz
;
...
...
@@ -208,10 +190,8 @@ static int _check_program_header(FIL *fp, Elf32_Phdr *phdr)
* This function ensures basic memory sanity of a section header.
* It ensures that it points to a file region that is contained within the file fully.
*/
static
int
_check_section_header
(
FIL
*
fp
,
Elf32_Shdr
*
shdr
)
static
int
_check_section_header
(
int
fd
,
int
size
,
Elf32_Shdr
*
shdr
)
{
size_t
size
=
f_size
(
fp
);
// Check file size/offset.
uint32_t
file_start
=
shdr
->
sh_offset
;
uint32_t
file_limit
=
shdr
->
sh_offset
+
shdr
->
sh_size
;
...
...
@@ -236,15 +216,15 @@ static const char *_interpreter = "card10-l0dable";
/*
* Check that the given INTERP program header contains the correct interpreter string.
*/
static
int
_check_interp
(
FIL
*
fp
,
Elf32_Phdr
*
phdr
)
static
int
_check_interp
(
int
fd
,
Elf32_Phdr
*
phdr
)
{
int
res
;
uint32_t
buffer_size
=
strlen
(
_interpreter
)
+
1
;
char
*
interp
=
alloca
(
buffer_size
);
memset
(
interp
,
0
,
buffer_size
);
if
((
res
=
_seek_and_read
(
f
p
,
phdr
->
p_offset
,
interp
,
buffer_size
))
!=
FR_OK
)
{
if
((
res
=
_seek_and_read
(
f
d
,
phdr
->
p_offset
,
interp
,
buffer_size
))
!=
0
)
{
return
res
;
}
...
...
@@ -325,7 +305,7 @@ static int _get_load_addr(struct _pie_load_info *li)
*
* Segment must be a LOAD segment.
*/
static
int
_load_segment
(
FIL
*
fp
,
struct
_pie_load_info
*
li
,
Elf32_Phdr
*
phdr
)
static
int
_load_segment
(
int
fd
,
struct
_pie_load_info
*
li
,
Elf32_Phdr
*
phdr
)
{
uint32_t
segment_start
=
li
->
load_address
+
phdr
->
p_vaddr
;
uint32_t
segment_limit
=
segment_start
+
phdr
->
p_memsz
;
...
...
@@ -340,7 +320,7 @@ static int _load_segment(FIL *fp, struct _pie_load_info *li, Elf32_Phdr *phdr)
memset
((
void
*
)
segment_start
,
0
,
phdr
->
p_memsz
);
return
_seek_and_read
(
f
p
,
phdr
->
p_offset
,
(
void
*
)
segment_start
,
phdr
->
p_filesz
f
d
,
phdr
->
p_offset
,
(
void
*
)
segment_start
,
phdr
->
p_filesz
);
}
...
...
@@ -348,17 +328,16 @@ static int _load_segment(FIL *fp, struct _pie_load_info *li, Elf32_Phdr *phdr)
* Parse dynamic symbol sections.
*/
static
int
_parse_dynamic_symbols
(
FIL
*
fp
,
struct
_pie_load_info
*
li
,
Elf32_Ehdr
*
hdr
)
_parse_dynamic_symbols
(
int
fd
,
int
size
,
struct
_pie_load_info
*
li
,
Elf32_Ehdr
*
hdr
)
{
int
res
;
FRESULT
fres
;
Elf32_Shdr
shdr
;
Elf32_Sym
sym
;
// Go through all dynamic symbol sections.
for
(
int
i
=
0
;
i
<
hdr
->
e_shnum
;
i
++
)
{
uint32_t
shdr_addr
=
hdr
->
e_shoff
+
(
i
*
hdr
->
e_shentsize
);
if
((
res
=
_read_section_header
(
f
p
,
shdr_addr
,
&
shdr
))
!=
0
)
{
if
((
res
=
_read_section_header
(
f
d
,
shdr_addr
,
&
shdr
))
!=
0
)
{
return
res
;
}
...
...
@@ -366,7 +345,7 @@ _parse_dynamic_symbols(FIL *fp, struct _pie_load_info *li, Elf32_Ehdr *hdr)
continue
;
}
if
((
res
=
_check_section_header
(
f
p
,
&
shdr
))
!=
0
)
{
if
((
res
=
_check_section_header
(
f
d
,
size
,
&
shdr
))
!=
0
)
{
return
res
;
}
...
...
@@ -379,23 +358,21 @@ _parse_dynamic_symbols(FIL *fp, struct _pie_load_info *li, Elf32_Ehdr *hdr)
uint32_t
sym_count
=
shdr
.
sh_size
/
sizeof
(
Elf32_Sym
);
// Read symbols one by one.
if
((
f
res
=
f_l
seek
(
f
p
,
shdr
.
sh_offset
))
!=
FR_OK
)
{
if
((
res
=
epic_file_
seek
(
f
d
,
shdr
.
sh_offset
,
SEEK_SET
))
!=
0
)
{
LOG_ERR
(
"l0der"
,
"_parse_dynamic_symbols: seek to first relocation (at 0x%lx) failed"
,
shdr
.
sh_offset
);
return
-
EIO
;
return
res
;
}
for
(
int
j
=
0
;
j
<
sym_count
;
j
++
)
{
unsigned
int
read
;
if
((
fres
=
f_read
(
fp
,
&
sym
,
sizeof
(
Elf32_Sym
),
&
read
))
!=
FR_OK
||
read
!=
sizeof
(
Elf32_Sym
))
{
if
((
res
=
epic_file_read
(
fd
,
&
sym
,
sizeof
(
Elf32_Sym
)))
!=
sizeof
(
Elf32_Sym
))
{
LOG_ERR
(
"l0der"
,
"__parse_dynamic_symbols: symbol read failed: %d"
,
f
res
);
return
-
EIO
;
res
);
return
res
;
}
uint32_t
bind
=
ELF32_ST_BIND
(
sym
.
st_info
);
...
...
@@ -424,17 +401,16 @@ _parse_dynamic_symbols(FIL *fp, struct _pie_load_info *li, Elf32_Ehdr *hdr)
* the only one used when making 'standard' PIE binaries on RAM. However, other
* kinds might have to be implemented in the future.
*/
static
int
_run_relocations
(
FIL
*
fp
,
struct
_pie_load_info
*
li
,
Elf32_Ehdr
*
hdr
)
static
int
_run_relocations
(
int
fd
,
int
size
,
struct
_pie_load_info
*
li
,
Elf32_Ehdr
*
hdr
)
{
int
res
;
FRESULT
fres
;
Elf32_Shdr
shdr
;
Elf32_Rel
rel
;
// Go through all relocation sections.
for
(
int
i
=
0
;
i
<
hdr
->
e_shnum
;
i
++
)
{
uint32_t
shdr_addr
=
hdr
->
e_shoff
+
(
i
*
hdr
->
e_shentsize
);
if
((
res
=
_read_section_header
(
f
p
,
shdr_addr
,
&
shdr
))
!=
0
)
{
if
((
res
=
_read_section_header
(
f
d
,
shdr_addr
,
&
shdr
))
!=
0
)
{
return
res
;
}
...
...
@@ -449,7 +425,7 @@ static int _run_relocations(FIL *fp, struct _pie_load_info *li, Elf32_Ehdr *hdr)
continue
;
}
if
((
res
=
_check_section_header
(
f
p
,
&
shdr
))
!=
0
)
{
if
((
res
=
_check_section_header
(
f
d
,
size
,
&
shdr
))
!=
0
)
{
return
res
;
}
...
...
@@ -457,28 +433,26 @@ static int _run_relocations(FIL *fp, struct _pie_load_info *li, Elf32_Ehdr *hdr)
LOG_ERR
(
"l0der"
,
"_run_relocations: SHT_REL section with invalid size: %ld"
,
shdr
.
sh_size
);
return
-
E
IO
;
return
-
E
NOEXEC
;
}
uint32_t
reloc_count
=
shdr
.
sh_size
/
sizeof
(
Elf32_Rel
);
// Read relocations one by one.
if
((
f
res
=
f_l
seek
(
f
p
,
shdr
.
sh_offset
))
!=
FR_OK
)
{
if
((
res
=
epic_file_
seek
(
f
d
,
shdr
.
sh_offset
,
SEEK_SET
))
!=
0
)
{
LOG_ERR
(
"l0der"
,
"_run_relocations: seek to first relocation (at 0x%lx) failed"
,
shdr
.
sh_offset
);
return
-
EIO
;
return
res
;
}
for
(
int
j
=
0
;
j
<
reloc_count
;
j
++
)
{
unsigned
int
read
;
if
((
fres
=
f_read
(
fp
,
&
rel
,
sizeof
(
Elf32_Rel
),
&
read
))
!=
FR_OK
||
read
!=
sizeof
(
Elf32_Rel
))
{
if
((
res
=
epic_file_read
(
fd
,
&
rel
,
sizeof
(
Elf32_Rel
)))
!=
sizeof
(
Elf32_Rel
))
{
LOG_ERR
(
"l0der"
,
"_run_relocations: relocation read failed: %d"
,
f
res
);
return
-
EIO
;
res
);
return
res
;
}
uint32_t
sym
=
ELF32_R_SYM
(
rel
.
r_info
);
...
...
@@ -536,7 +510,7 @@ static int _run_relocations(FIL *fp, struct _pie_load_info *li, Elf32_Ehdr *hdr)
/*
* Load a l0dable PIE binary.
*/
static
int
_load_pie
(
FIL
*
fp
,
Elf32_Ehdr
*
hdr
,
struct
l0dable_info
*
info
)
static
int
_load_pie
(
int
fd
,
int
size
,
Elf32_Ehdr
*
hdr
,
struct
l0dable_info
*
info
)
{
int
res
;
struct
_pie_load_info
li
=
{
0
};
...
...
@@ -553,16 +527,16 @@ static int _load_pie(FIL *fp, Elf32_Ehdr *hdr, struct l0dable_info *info)
for
(
int
i
=
0
;
i
<
hdr
->
e_phnum
;
i
++
)
{
uint32_t
phdr_addr
=
hdr
->
e_phoff
+
(
i
*
hdr
->
e_phentsize
);
if
((
res
=
_read_program_header
(
f
p
,
phdr_addr
,
&
phdr
))
!=
0
)
{
if
((
res
=
_read_program_header
(
f
d
,
phdr_addr
,
&
phdr
))
!=
0
)
{
return
res
;
}
if
((
res
=
_check_program_header
(
f
p
,
&
phdr
))
!=
0
)
{
if
((
res
=
_check_program_header
(
f
d
,
size
,
&
phdr
))
!=
0
)
{
return
res
;
}
if
(
phdr
.
p_type
==
PT_INTERP
)
{
status_interp
=
_check_interp
(
f
p
,
&
phdr
);
status_interp
=
_check_interp
(
f
d
,
&
phdr
);
continue
;
}
...
...
@@ -620,7 +594,7 @@ static int _load_pie(FIL *fp, Elf32_Ehdr *hdr, struct l0dable_info *info)
for
(
int
i
=
0
;
i
<
hdr
->
e_phnum
;
i
++
)
{
uint32_t
phdr_addr
=
hdr
->
e_phoff
+
(
i
*
hdr
->
e_phentsize
);
if
((
res
=
_read_program_header
(
f
p
,
phdr_addr
,
&
phdr
))
!=
0
)
{
if
((
res
=
_read_program_header
(
f
d
,
phdr_addr
,
&
phdr
))
!=
0
)
{
return
res
;
}
...
...
@@ -628,18 +602,18 @@ static int _load_pie(FIL *fp, Elf32_Ehdr *hdr, struct l0dable_info *info)
continue
;
}
if
((
res
=
_load_segment
(
f
p
,
&
li
,
&
phdr
))
!=
0
)
{
if
((
res
=
_load_segment
(
f
d
,
&
li
,
&
phdr
))
!=
0
)
{
return
res
;
}
}
// Load dynamic symbols.
if
((
res
=
_parse_dynamic_symbols
(
f
p
,
&
li
,
hdr
))
!=
0
)
{
if
((
res
=
_parse_dynamic_symbols
(
f
d
,
size
,
&
li
,
hdr
))
!=
0
)
{
return
res
;
}
// Run relocations.
if
((
res
=
_run_relocations
(
f
p
,
&
li
,
hdr
))
!=
0
)
{
if
((
res
=
_run_relocations
(
f
d
,
size
,
&
li
,
hdr
))
!=
0
)
{
return
res
;
}
...
...
@@ -656,26 +630,29 @@ static int _load_pie(FIL *fp, Elf32_Ehdr *hdr, struct l0dable_info *info)
int
l0der_load_path
(
const
char
*
path
,
struct
l0dable_info
*
info
)
{
FIL
fh
;
FRESULT
fres
=
f_open
(
&
fh
,
path
,
FA_OPEN_EXISTING
|
FA_READ
);
if
(
fres
!=
FR_OK
)
{
int
fd
,
res
;
if
((
fd
=
epic_file_open
(
path
,
"rb"
))
<
0
)
{
LOG_ERR
(
"l0der"
,
"l0der_load_path: could not open ELF file %s: %d"
,
path
,
fres
);
return
-
ENOENT
;
fd
);
return
fd
;
}
if
((
res
=
epic_file_seek
(
fd
,
0
,
SEEK_END
))
!=
0
)
{
return
res
;
}
int
size
=
f_size
(
&
fh
);
int
size
=
epic_file_tell
(
fd
);
int
res
=
0
;
if
((
res
=
epic_file_seek
(
fd
,
0
,
SEEK_SET
))
!=
0
)
{
return
res
;
}
// Load ELF header and ensure it's somewhat sane.
Elf32_Ehdr
hdr
;
if
(
_read_elf_header
(
&
fh
,
&
hdr
)
!=
0
)
{
res
=
-
EINVAL
;
if
((
res
=
_read_elf_header
(
fd
,
&
hdr
))
!=
0
)
{
goto
done
;
}
...
...
@@ -728,7 +705,7 @@ int l0der_load_path(const char *path, struct l0dable_info *info)
if
(
hdr
.
e_type
==
ET_DYN
&&
hdr
.
e_machine
==
EM_ARM
&&
hdr
.
e_version
==
EV_CURRENT
)
{
LOG_INFO
(
"l0der"
,
"Loading PIE l0dable %s ..."
,
path
);
res
=
_load_pie
(
&
fh
,
&
hdr
,
info
);
res
=
_load_pie
(
fd
,
size
,
&
hdr
,
info
);
goto
done
;
}
else
{
LOG_ERR
(
"l0der"
,
...
...
@@ -739,6 +716,6 @@ int l0der_load_path(const char *path, struct l0dable_info *info)
}
done:
f
_close
(
&
fh
);
epic_file
_close
(
fd
);
return
res
;
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment