00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <fcntl.h>
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include <unistd.h>
00023 #include <stdlib.h>
00024 #include <errno.h>
00025
00026 #include "elf_loader.h"
00027 #include "create.h"
00028 #include "spebase.h"
00029
00030 #ifndef SPE_EMULATED_LOADER_FILE
00031 #define SPE_EMULATED_LOADER_FILE "/usr/lib/spe/emulated-loader.bin"
00032 #endif
00033
00038 void _base_spe_program_load_complete(spe_context_ptr_t spectx)
00039 {
00040 int objfd, len;
00041 char buf[20];
00042 spe_program_handle_t *program;
00043
00044 program = spectx->base_private->loaded_program;
00045
00046 if (!program || !program->elf_image) {
00047 DEBUG_PRINTF("%s called, but no program loaded\n", __func__);
00048 return;
00049 }
00050
00051 objfd = openat(spectx->base_private->fd_spe_dir, "object-id", O_RDWR);
00052 if (objfd < 0)
00053 return;
00054
00055 len = sprintf(buf, "%p", program->elf_image);
00056 write(objfd, buf, len + 1);
00057 close(objfd);
00058
00059 __spe_context_update_event();
00060 }
00061
00073 static inline int __write_isolated_load_params(struct spe_context *spe,
00074 uint32_t addr_h, uint32_t addr_l, uint32_t size)
00075 {
00076 int fd = _base_spe_open_if_closed(spe, FD_WBOX, 0);
00077
00078 if (fd < 0) {
00079 DEBUG_PRINTF("%s: can't open wbox\n", __FUNCTION__);
00080 return -1;
00081 }
00082
00083 if ((write(fd, &addr_h, sizeof(uint32_t)) != sizeof(uint32_t)) ||
00084 (write(fd, &addr_l, sizeof(uint32_t)) != sizeof(uint32_t)) ||
00085 (write(fd, &size, sizeof(uint32_t)) != sizeof(uint32_t))) {
00086 DEBUG_PRINTF("%s: error writing to wbox\n", __FUNCTION__);
00087 return -1;
00088 }
00089
00090 return 0;
00091 }
00092
00102 static int spe_start_isolated_app(struct spe_context *spe,
00103 spe_program_handle_t *handle)
00104 {
00105 uint64_t addr;
00106 uint32_t size, addr_h, addr_l;
00107
00108 if (_base_spe_parse_isolated_elf(handle, &addr, &size)) {
00109 DEBUG_PRINTF("%s: invalid isolated image\n", __FUNCTION__);
00110 errno = ENOEXEC;
00111 return -errno;
00112 }
00113
00114 if (addr & 0xf) {
00115 DEBUG_PRINTF("%s: isolated image is incorrectly aligned\n",
00116 __FUNCTION__);
00117 errno = EINVAL;
00118 return -errno;
00119 }
00120
00121 addr_l = (uint32_t)(addr & 0xffffffff);
00122 addr_h = (uint32_t)(addr >> 32);
00123
00124 DEBUG_PRINTF("%s: Sending isolated app params: 0x%08x 0x%08x 0x%08x\n",
00125 __FUNCTION__, addr_h, addr_l, size);
00126
00127 if (__write_isolated_load_params(spe, addr_h, addr_l, size)) {
00128 errno = EIO;
00129 return -errno;
00130 }
00131
00132 return 0;
00133 }
00134
00141 static spe_program_handle_t *emulated_loader_program(void)
00142 {
00143 static spe_program_handle_t *loader = NULL;
00144
00145 if (!loader)
00146 loader = _base_spe_image_open(SPE_EMULATED_LOADER_FILE);
00147
00148 if (!loader)
00149 DEBUG_PRINTF("Can't load emulated loader '%s': %s\n",
00150 SPE_EMULATED_LOADER_FILE, strerror(errno));
00151
00152 return loader;
00153 }
00154
00159 int _base_spe_emulated_loader_present(void)
00160 {
00161 spe_program_handle_t *loader = emulated_loader_program();
00162
00163 if (!loader)
00164 return 0;
00165
00166 return !_base_spe_verify_spe_elf_image(loader);
00167 }
00168
00181 static int spe_start_emulated_isolated_app(struct spe_context *spe,
00182 spe_program_handle_t *handle, struct spe_ld_info *ld_info)
00183
00184 {
00185 int rc;
00186 spe_program_handle_t *loader;
00187
00188
00189 loader = emulated_loader_program();
00190
00191 if (!loader)
00192 return -1;
00193
00194 rc = _base_spe_load_spe_elf(loader, spe->base_private->mem_mmap_base, ld_info);
00195 if (rc != 0) {
00196 DEBUG_PRINTF("%s: No loader available\n", __FUNCTION__);
00197 return rc;
00198 }
00199
00200 return spe_start_isolated_app(spe, handle);
00201 }
00202
00203 int _base_spe_program_load(spe_context_ptr_t spe, spe_program_handle_t *program)
00204 {
00205 int rc = 0;
00206 struct spe_ld_info ld_info;
00207
00208 spe->base_private->loaded_program = program;
00209
00210 if (spe->base_private->flags & SPE_ISOLATE) {
00211 rc = spe_start_isolated_app(spe, program);
00212
00213 } else if (spe->base_private->flags & SPE_ISOLATE_EMULATE) {
00214 rc = spe_start_emulated_isolated_app(spe, program, &ld_info);
00215
00216 } else {
00217 rc = _base_spe_load_spe_elf(program,
00218 spe->base_private->mem_mmap_base, &ld_info);
00219 if (!rc)
00220 _base_spe_program_load_complete(spe);
00221 }
00222
00223 if (rc != 0) {
00224 DEBUG_PRINTF ("Load SPE ELF failed..\n");
00225 return -1;
00226 }
00227
00228 spe->base_private->entry = ld_info.entry;
00229 spe->base_private->emulated_entry = ld_info.entry;
00230
00231 return 0;
00232 }