Home | History | Annotate | Download | only in cortexm4
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <nanohub/appRelocFormat.h>
     18 
     19 #include <string.h>
     20 #include <stdint.h>
     21 #include <heap.h>
     22 #include <seos.h>
     23 #include <cpu.h>
     24 
     25 #include <plat/cmsis.h>
     26 
     27 //reloc types for this cpu type
     28 #define NANO_RELOC_TYPE_RAM	0
     29 #define NANO_RELOC_TYPE_FLASH	1
     30 
     31 #define APP_FLASH_RELOC(_base, _offset) ((uint32_t)(_base) + FLASH_RELOC_OFFSET + (_offset))
     32 #define APP_FLASH_RELOC_BASE(_base) APP_FLASH_RELOC(_base, 0)
     33 #define APP_VEC(_app) ((struct AppFuncs*)&((_app)->vec))
     34 
     35 static bool handleRelNumber(uint32_t *ofstP, uint32_t type, uint32_t flashAddr, uint32_t ramAddr, uint32_t *mem, uint32_t value)
     36 {
     37     uint32_t base, where;
     38 
     39     switch (type) {
     40 
     41     case NANO_RELOC_TYPE_RAM:
     42         base = ramAddr;
     43         break;
     44 
     45     case NANO_RELOC_TYPE_FLASH:
     46         base = flashAddr;
     47         break;
     48 
     49     default:
     50         return false;
     51     }
     52 
     53     where = *ofstP + value;
     54     *ofstP = where + 1;
     55 
     56     mem[where] += base;
     57 
     58     return true;
     59 }
     60 
     61 static bool handleRelocs(const uint8_t *relStart, const uint8_t *relEnd, uint32_t flashStart, uint32_t ramStart, void *mem)
     62 {
     63     uint32_t ofst = 0;
     64     uint32_t type = 0;
     65 
     66     while (relStart != relEnd) {
     67 
     68         uint32_t rel = *relStart++;
     69 
     70         if (rel <= MAX_8_BIT_NUM) {
     71 
     72             if (!handleRelNumber(&ofst, type, flashStart, ramStart, mem, rel))
     73                 return false;
     74         }
     75         else switch (rel) {
     76 
     77         case TOKEN_32BIT_OFST:
     78             if (relEnd - relStart < 4)
     79                 return false;
     80             rel = *(uint32_t*)relStart;
     81             relStart += sizeof(uint32_t);
     82             if (!handleRelNumber(&ofst, type, flashStart, ramStart, mem, rel))
     83                 return false;
     84             break;
     85 
     86         case TOKEN_24BIT_OFST:
     87             if (relEnd - relStart < 3)
     88                 return false;
     89             rel = *(uint16_t*)relStart;
     90             relStart += sizeof(uint16_t);
     91             rel += ((uint32_t)(*relStart++)) << 16;
     92             if (!handleRelNumber(&ofst, type, flashStart, ramStart, mem, rel + MAX_16_BIT_NUM))
     93                 return false;
     94             break;
     95 
     96         case TOKEN_16BIT_OFST:
     97             if (relEnd - relStart < 2)
     98                 return false;
     99             rel = *(uint16_t*)relStart;
    100             relStart += sizeof(uint16_t);
    101             if (!handleRelNumber(&ofst, type, flashStart, ramStart, mem, rel + MAX_8_BIT_NUM))
    102                 return false;
    103             break;
    104 
    105         case TOKEN_CONSECUTIVE:
    106             if (relEnd - relStart < 1)
    107                 return false;
    108             rel = *relStart++;
    109             rel += MIN_RUN_LEN;
    110             while (rel--)
    111                 if (!handleRelNumber(&ofst, type, flashStart, ramStart, mem, 0))
    112                     return false;
    113             break;
    114 
    115         case TOKEN_RELOC_TYPE_CHG:
    116             if (relEnd - relStart < 1)
    117                 return false;
    118             rel = *relStart++;
    119             rel++;
    120             type += rel;
    121             ofst = 0;
    122             break;
    123 
    124         case TOKEN_RELOC_TYPE_NEXT:
    125             type++;
    126             ofst = 0;
    127             break;
    128         }
    129     }
    130 
    131     return true;
    132 }
    133 
    134 bool cpuInternalAppLoad(const struct AppHdr *appHdr, struct PlatAppInfo *platInfo)
    135 {
    136     platInfo->data = 0x00000000;
    137 
    138     return true;
    139 }
    140 
    141 bool cpuAppLoad(const struct AppHdr *app, struct PlatAppInfo *platInfo)
    142 {
    143     const struct SectInfo *sect = &app->sect;
    144     const uint8_t *relocsStart = (const uint8_t*)APP_FLASH_RELOC(app, sect->rel_start);
    145     const uint8_t *relocsEnd = (const uint8_t*)APP_FLASH_RELOC(app, sect->rel_end);
    146     uint8_t *mem = heapAlloc(sect->bss_end);
    147 
    148     if (!mem)
    149         return false;
    150 
    151     //calculate and assign .DATA org (TODO: data_start must be always zero, exclude it form APP structures)
    152     platInfo->data = mem + sect->data_start;
    153 
    154     //clear .BSS
    155     memset(mem + sect->bss_start, 0, sect->bss_end - sect->bss_start);
    156 
    157     //copy initialized data and initialized .GOT
    158     memcpy(mem + sect->data_start, (uint8_t*)APP_FLASH_RELOC(app, sect->data_data), sect->got_end - sect->data_start);
    159 
    160     //perform relocs
    161     if (!handleRelocs(relocsStart, relocsEnd, (uintptr_t)APP_FLASH_RELOC_BASE(app), (uintptr_t)mem, (void*)mem)) {
    162         osLog(LOG_ERROR, "Relocs are invalid in this app. Aborting app load\n");
    163         heapFree(mem);
    164         return false;
    165     }
    166 
    167     return true;
    168 }
    169 
    170 void cpuAppUnload(const struct AppHdr *app, struct PlatAppInfo *platInfo)
    171 {
    172     if (platInfo->data)
    173         heapFree((uint8_t*)platInfo->data - app->sect.data_start);
    174 }
    175 
    176 static uintptr_t __attribute__((naked)) callWithR9(const void *base, uint32_t offset, void *data, uintptr_t arg1, uintptr_t arg2)
    177 {
    178     asm volatile (
    179         "add  r12, r0, r1  \n"
    180         "mov  r0,  r3      \n"
    181         "ldr  r1,  [sp]    \n"
    182         "push {r9, lr}     \n"
    183         "mov  r9, r2       \n"
    184         "blx  r12          \n"
    185         "pop  {r9, pc}     \n"
    186     );
    187 
    188     return 0; //dummy to fool gcc
    189 }
    190 
    191 bool cpuAppInit(const struct AppHdr *app, struct PlatAppInfo *platInfo, uint32_t tid)
    192 {
    193     if (platInfo->data)
    194         return callWithR9((const void*)APP_FLASH_RELOC_BASE(app), app->vec.init, platInfo->data, tid, 0);
    195     else
    196         return APP_VEC(app)->init(tid);
    197 }
    198 
    199 void cpuAppEnd(const struct AppHdr *app, struct PlatAppInfo *platInfo)
    200 {
    201     if (platInfo->data)
    202         (void)callWithR9((const void*)APP_FLASH_RELOC_BASE(app), app->vec.end, platInfo->data, 0, 0);
    203     else
    204         APP_VEC(app)->end();
    205     osLog(LOG_INFO, "App ID %016" PRIX64 "; TID=%04" PRIX32 " terminated\n", app->hdr.appId, osGetCurrentTid());
    206 }
    207 
    208 void cpuAppHandle(const struct AppHdr *app, struct PlatAppInfo *platInfo, uint32_t evtType, const void* evtData)
    209 {
    210     if (platInfo->data)
    211         (void)callWithR9((const void*)APP_FLASH_RELOC_BASE(app), app->vec.handle, platInfo->data, evtType, (uintptr_t)evtData);
    212     else
    213         APP_VEC(app)->handle(evtType, evtData);
    214 }
    215 
    216 void cpuAppInvoke(const struct AppHdr *app, struct PlatAppInfo *platInfo,
    217                   void (*method)(uintptr_t, uintptr_t),uintptr_t arg1, uintptr_t arg2)
    218 {
    219     if (platInfo->data) {
    220         uint32_t hasSvcAct = SCB->SHCSR & SCB_SHCSR_SVCALLACT_Msk;
    221 
    222         SCB->SHCSR &= ~SCB_SHCSR_SVCALLACT_Msk;
    223         (void)callWithR9(0, (uint32_t)method, platInfo->data, arg1, arg2);
    224         SCB->SHCSR |= hasSvcAct;
    225     } else {
    226         method(arg1, arg2);
    227     }
    228 }
    229