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