diff options
Diffstat (limited to 'firmware/load_code.c')
-rw-r--r-- | firmware/load_code.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/firmware/load_code.c b/firmware/load_code.c index 75bac8b2ac..5b5307e622 100644 --- a/firmware/load_code.c +++ b/firmware/load_code.c | |||
@@ -26,37 +26,77 @@ | |||
26 | #include "load_code.h" | 26 | #include "load_code.h" |
27 | 27 | ||
28 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 28 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
29 | |||
29 | /* load binary blob from disk to memory, returning a handle */ | 30 | /* load binary blob from disk to memory, returning a handle */ |
30 | void * lc_open(const char *filename, char *buf, size_t buf_size) | 31 | void * lc_open(const char *filename, unsigned char *buf, size_t buf_size) |
31 | { | 32 | { |
32 | int fd = open(filename, O_RDONLY); | 33 | int fd = open(filename, O_RDONLY); |
33 | ssize_t read_size; | 34 | ssize_t read_size; |
35 | struct lc_header hdr; | ||
36 | unsigned char *buf_end = buf+buf_size; | ||
37 | off_t copy_size; | ||
34 | 38 | ||
35 | if (fd < 0) | 39 | if (fd < 0) |
36 | { | 40 | { |
37 | DEBUGF("Could not open file"); | 41 | DEBUGF("Could not open file"); |
38 | return NULL; | 42 | goto error; |
39 | } | 43 | } |
40 | 44 | ||
41 | #if NUM_CORES > 1 | 45 | #if NUM_CORES > 1 |
42 | /* Make sure COP cache is flushed and invalidated before loading */ | 46 | /* Make sure COP cache is flushed and invalidated before loading */ |
43 | { | 47 | { |
44 | int my_core = switch_core(CURRENT_CORE ^ 1); | 48 | int my_core = switch_core(CURRENT_CORE ^ 1); |
45 | cpucache_invalidate(); | 49 | cpucache_commit_discard(); |
46 | switch_core(my_core); | 50 | switch_core(my_core); |
47 | } | 51 | } |
48 | #endif | 52 | #endif |
49 | 53 | ||
50 | read_size = read(fd, buf, buf_size); | 54 | /* read the header to obtain the load address */ |
55 | read_size = read(fd, &hdr, sizeof(hdr)); | ||
56 | |||
57 | if (read_size < 0) | ||
58 | { | ||
59 | DEBUGF("Could not read from file"); | ||
60 | goto error_fd; | ||
61 | } | ||
62 | |||
63 | /* hdr.end_addr points to the end of the bss section, | ||
64 | * but there might be idata/icode behind that so the bytes to copy | ||
65 | * can be larger */ | ||
66 | copy_size = MAX(filesize(fd), hdr.end_addr - hdr.load_addr); | ||
67 | |||
68 | if (hdr.load_addr < buf || (hdr.load_addr+copy_size) > buf_end) | ||
69 | { | ||
70 | DEBUGF("Binary doesn't fit into memory"); | ||
71 | goto error_fd; | ||
72 | } | ||
73 | |||
74 | /* go back to beginning to load the whole thing (incl. header) */ | ||
75 | if (lseek(fd, 0, SEEK_SET) < 0) | ||
76 | { | ||
77 | DEBUGF("lseek failed"); | ||
78 | goto error_fd; | ||
79 | } | ||
80 | |||
81 | /* the header has the addresses where the code is linked at */ | ||
82 | read_size = read(fd, hdr.load_addr, copy_size); | ||
51 | close(fd); | 83 | close(fd); |
52 | cpucache_invalidate(); | ||
53 | 84 | ||
54 | if (read_size < 0) | 85 | if (read_size < 0) |
55 | { | 86 | { |
56 | DEBUGF("Could not read from file"); | 87 | DEBUGF("Could not read from file"); |
57 | return NULL; | 88 | goto error; |
58 | } | 89 | } |
59 | return buf; | 90 | |
91 | /* commit dcache and discard icache */ | ||
92 | cpucache_commit_discard(); | ||
93 | /* return a pointer the header, reused by lc_get_header() */ | ||
94 | return hdr.load_addr; | ||
95 | |||
96 | error_fd: | ||
97 | close(fd); | ||
98 | error: | ||
99 | return NULL; | ||
60 | } | 100 | } |
61 | 101 | ||
62 | #elif (CONFIG_PLATFORM & PLATFORM_HOSTED) | 102 | #elif (CONFIG_PLATFORM & PLATFORM_HOSTED) |
@@ -85,12 +125,11 @@ static inline char *_dlerror(void) | |||
85 | #include "rbpaths.h" | 125 | #include "rbpaths.h" |
86 | #include "general.h" | 126 | #include "general.h" |
87 | 127 | ||
88 | void * _lc_open(const _lc_open_char *filename, char *buf, size_t buf_size) | 128 | void * _lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size) |
89 | { | 129 | { |
90 | (void)buf; | 130 | (void)buf; |
91 | (void)buf_size; | 131 | (void)buf_size; |
92 | void* dl_handle = dlopen(filename, RTLD_NOW); | 132 | return dlopen(filename, RTLD_NOW); |
93 | return dl_handle; | ||
94 | } | 133 | } |
95 | 134 | ||
96 | void *lc_open_from_mem(void *addr, size_t blob_size) | 135 | void *lc_open_from_mem(void *addr, size_t blob_size) |