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 platSlpiAddInternalApp(&mAppHdr, false);
118 }
119
__appEnd(void)120 static void __appEnd(void) {
121 platSlpiRemoveInternalApp(&mAppHdr);
122 }
123
chreappStart(uint32_t tid)124 static bool chreappStart(uint32_t tid) {
125 return nanoappStart();
126 }
127
chreappHandle(uint32_t eventTypeAndTid,const void * eventData)128 static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData) {
129 uint16_t evt = eventTypeAndTid;
130 uint16_t srcTid = eventTypeAndTid >> 16;
131 const void *data = eventData;
132
133 union EventLocalData {
134 struct chreMessageFromHostData msg;
135 } u;
136
137 switch (evt) {
138 case EVT_APP_TIMER:
139 evt = CHRE_EVENT_TIMER;
140 data = ((struct TimerEvent *)eventData)->data;
141 break;
142 case EVT_APP_FROM_HOST:
143 evt = CHRE_EVENT_MESSAGE_FROM_HOST;
144 data = &u.msg;
145 u.msg.message = (uint8_t *)eventData + 1;
146 // TODO: fill messageType with the correct value once available.
147 u.msg.messageType = 0;
148 u.msg.messageSize = *(uint8_t *)eventData;
149 break;
150 }
151 nanoappHandleEvent(srcTid, evt, data);
152 }
153
154 #ifdef __cplusplus
155 }
156 #endif
157