libspe2 0.9a
load.c
Go to the documentation of this file.
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 }