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
37extern "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
49struct 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.
58struct 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
83struct TimerEvent {
84    uint32_t timerId;
85    void *data;
86};
87
88// These two functions are specific to Qualcomm's Nanohub platform
89// implementation
90extern void platSlpiAddInternalApp(const struct LegacyAppHdr *, bool);
91extern void platSlpiRemoveInternalApp(const struct LegacyAppHdr *);
92
93static void __appInit(void) __attribute__((constructor));
94static void __appEnd(void) __attribute__((destructor));
95
96static bool chreappStart(uint32_t tid);
97static 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
103static 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.
116static void __appInit(void)
117{
118   platSlpiAddInternalApp(&mAppHdr, false);
119}
120
121static void __appEnd(void)
122{
123   platSlpiRemoveInternalApp(&mAppHdr);
124}
125
126static bool chreappStart(uint32_t tid)
127{
128    return nanoappStart();
129}
130
131static 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