1 /*
2  * Copyright (C) 2017 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 /*******************************************************************************
18  *                          ~ ~ ~ W A R N I N G ~ ~ ~
19  *
20  * The following code is used to load a nanoapp into a Qualcomm implementation
21  * of the CHRE API that is based on Nanohub. This is not intended as a reference
22  * for future platforms and is provided for backwards compatibility with this
23  * implementation.
24  *
25  * You may find more suitable examples of app support libraries under the
26  * build/app_support directory for other variants. These files are typically
27  * designed to perform early initialization of the CHRE nanoapp and may be
28  * required by some platforms but not all.
29  *
30  ******************************************************************************/
31 
32 #include <chre.h>
33 #include <stdbool.h>
34 #include <stdint.h>
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 #define LEGACY_APP_HDR_MAGIC_ARRAY \
41     {'G', 'o', 'o', 'g', 'l', 'e', 'N', 'a', 'n', 'o', 'A', 'p', 'p'}
42 
43 #define APP_HDR_VER_CUR            0
44 #define APP_HDR_MARKER_INTERNAL    0xFF01
45 
46 #define EVT_APP_FROM_HOST                0x000000F8
47 #define EVT_APP_TIMER                    0x000000DF
48 
49 struct AppFuncs {
50     bool (*init)(uint32_t yourTid);
51     void (*end)(void);
52     void (*handle)(uint32_t evtType, const void *evtData);
53 };
54 
55 // This was the old "struct AppHdr" before the binary format was refactored as
56 // part of b/28265099. It's what Qualcomm's implementation currently expects as
57 // input when registering an app.
58 struct LegacyAppHdr {
59     char magic[13];
60     uint8_t fmtVer;  //app header format version
61     uint16_t marker;
62 
63     uint64_t appId;
64 
65     uint32_t data_start;
66     uint32_t data_end;
67     uint32_t data_data;
68 
69     uint32_t bss_start;
70     uint32_t bss_end;
71 
72     uint32_t got_start;
73     uint32_t got_end;
74     uint32_t rel_start;
75     uint32_t rel_end;
76 
77     uint32_t appVer;
78     uint32_t rfu;
79 
80     struct AppFuncs funcs;
81 };
82 
83 struct TimerEvent {
84     uint32_t timerId;
85     void *data;
86 };
87 
88 // These two functions are specific to Qualcomm's Nanohub platform
89 // implementation
90 extern void platSlpiAddInternalApp(const struct LegacyAppHdr *, bool);
91 extern void platSlpiRemoveInternalApp(const struct LegacyAppHdr *);
92 
93 static void __appInit(void) __attribute__((constructor));
94 static void __appEnd(void) __attribute__((destructor));
95 
96 static bool chreappStart(uint32_t tid);
97 static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData);
98 
99 #if !defined(NANOAPP_ID) || !defined(NANOAPP_VERSION)
100 #error NANOAPP_ID and NANOAPP_VERSION must be defined in the build environment
101 #endif
102 
103 static const struct LegacyAppHdr mAppHdr = {
104    .magic        = LEGACY_APP_HDR_MAGIC_ARRAY,
105    .fmtVer       = APP_HDR_VER_CUR,
106    .marker       = APP_HDR_MARKER_INTERNAL,
107    .appId        = NANOAPP_ID,
108    .appVer       = NANOAPP_VERSION,
109    .funcs.init   = chreappStart,
110    .funcs.end    = nanoappEnd,
111    .funcs.handle = chreappHandle,
112 };
113 
114 // Note: this runs when CHRE first loads the Nanoapp. We use it to register the
115 // app's entry points with the runtime environment.
__appInit(void)116 static void __appInit(void)
117 {
118    platSlpiAddInternalApp(&mAppHdr, false);
119 }
120 
__appEnd(void)121 static void __appEnd(void)
122 {
123    platSlpiRemoveInternalApp(&mAppHdr);
124 }
125 
chreappStart(uint32_t tid)126 static bool chreappStart(uint32_t tid)
127 {
128     return nanoappStart();
129 }
130 
chreappHandle(uint32_t eventTypeAndTid,const void * eventData)131 static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData)
132 {
133     uint16_t evt = eventTypeAndTid;
134     uint16_t srcTid = eventTypeAndTid >> 16;
135     const void *data = eventData;
136 
137     union EventLocalData {
138         struct chreMessageFromHostData msg;
139     } u;
140 
141     switch(evt) {
142     case EVT_APP_TIMER:
143         evt = CHRE_EVENT_TIMER;
144         data = ((struct TimerEvent *)eventData)->data;
145         break;
146     case EVT_APP_FROM_HOST:
147         evt = CHRE_EVENT_MESSAGE_FROM_HOST;
148         data = &u.msg;
149         u.msg.message = (uint8_t*)eventData + 1;
150         // TODO: fill messageType with the correct value once available.
151         u.msg.messageType = 0;
152         u.msg.messageSize = *(uint8_t*)eventData;
153         break;
154     }
155     nanoappHandleEvent(srcTid, evt, data);
156 }
157 
158 #ifdef __cplusplus
159 }
160 #endif
161