libspe2 0.9a
|
00001 /* 00002 * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS 00003 * Copyright (C) 2005 IBM Corp. 00004 * 00005 * This library is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 2.1 of the License, 00008 * or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, but 00011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this library; if not, write to the Free Software Foundation, 00017 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 /* load emulated loader from the filesystem */ 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 }