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 #ifndef _SEOS_H_
18 #define _SEOS_H_
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #include <plat/inc/taggedPtr.h>
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stdarg.h>
28 #include <stddef.h>
29 #include <eventQ.h>
30 #include <plat/inc/app.h>
31 #include <eventnums.h>
32 #include "toolchain.h"
33 
34 #include <nanohub/nanohub.h>
35 
36 //#define SEGMENT_CRC_SUPPORT
37 
38 #define MAX_TASKS                        16
39 #define MAX_EMBEDDED_EVT_SUBS             6 /* tradeoff, no wrong answer */
40 #define TASK_IDX_BITS                     8 /* should be big enough to hold MAX_TASKS, but still fit in TaskIndex */
41 
42 typedef uint8_t TaskIndex;
43 
44 struct AppFuncs { /* do not rearrange */
45     /* lifescycle */
46     bool (*init)(uint32_t yourTid);   //simple init only - no ints on at this time
47     void (*end)(void);                //die quickly please
48     /* events */
49     void (*handle)(uint32_t evtType, const void* evtData);
50 };
51 
52 /* NOTE: [TASK ID]
53  * TID is designed to be 16-bit; there is no reason for TID to become bigger than that on a system
54  * with typical RAM size of 64kB. However, in NO CASE TID values should overlap with TaggedPtr TAG mask,
55  * which is currently defined as 0x80000000.
56  */
57 
58 #define TASK_TID_BITS 16
59 
60 #define TASK_TID_MASK ((1 << TASK_TID_BITS) - 1)
61 #define TASK_TID_INCREMENT (1 << TASK_IDX_BITS)
62 #define TASK_TID_IDX_MASK ((1 << TASK_IDX_BITS) - 1)
63 #define TASK_TID_COUNTER_MASK ((1 << TASK_TID_BITS) - TASK_TID_INCREMENT)
64 
65 #if MAX_TASKS > TASK_TID_IDX_MASK
66 #error MAX_TASKS does not fit in TASK_TID_BITS
67 #endif
68 
69 #define OS_SYSTEM_TID                    0
70 #define OS_VER                           0x0000
71 
72 // FIXME: compatibility: keep key ID 1 until key update is functional
73 //#define ENCR_KEY_GOOGLE_PREPOPULATED     0x041F010000000001
74 #define ENCR_KEY_GOOGLE_PREPOPULATED     1 // our key ID is 1
75 
76 #define APP_HDR_MAGIC              NANOAPP_FW_MAGIC
77 #define APP_HDR_VER_CUR            0
78 
79 #define FL_APP_HDR_INTERNAL        0x0001 // to be able to fork behavior at run time for internal apps
80 #define FL_APP_HDR_APPLICATION     0x0002 // image has AppHdr; otherwise is has AppInfo header
81 #define FL_APP_HDR_SECURE          0x0004 // secure content, needs to be zero-filled when discarded
82 #define FL_APP_HDR_VOLATILE        0x0008 // volatile content, segment shall be deleted after operation is complete
83 #define FL_KEY_HDR_DELETE          0x8000 // key-specific flag: if set key id refers to existing key which has to be deleted
84 
85 /* app ids are split into vendor and app parts. vendor parts are assigned by google. App parts are free for each vendor to assign at will */
86 #define APP_ID_FIRST_USABLE        0x0100000000000000ULL //all app ids lower than this are reserved for google's internal use
87 #define APP_ID_GET_VENDOR(appid)   ((appid) >> 24)
88 #define APP_ID_GET_SEQ_ID(appid)   ((appid) & 0xFFFFFF)
89 #define APP_ID_MAKE(vendor, app)   ((((uint64_t)(vendor)) << 24) | ((app) & APP_SEQ_ID_ANY))
90 #define KEY_ID_MAKE(vendor, key)   ((((uint64_t)(vendor)) << 24) | ((key) & KEY_SEQ_ID_ANY))
91 #define APP_ID_VENDOR_GOOGLE       UINT64_C(0x476F6F676C) // "Googl"
92 #define APP_VENDOR_ANY             UINT64_C(0xFFFFFFFFFF)
93 #define APP_SEQ_ID_ANY             UINT64_C(0xFFFFFF)
94 #define KEY_SEQ_ID_ANY             UINT64_C(0xFFFFFF)
95 #define APP_ID_ANY                 UINT64_C(0xFFFFFFFFFFFFFFFF)
96 
97 #define APP_INFO_CMD_ADD_KEY 1
98 #define APP_INFO_CMD_REMOVE_KEY 2
99 #define APP_INFO_CMD_OS_UPDATE 3
100 
101 #define SEG_STATE_INVALID UINT32_C(0xFFFFFFFF)
102 #define SEG_SIZE_MAX      UINT32_C(0x00FFFFFF)
103 #define SEG_SIZE_INVALID  (-1)
104 #define SEG_ST(arg) (((arg) << 4) | (arg))
105 
106 #define SEG_ID_EMPTY    0xF
107 #define SEG_ID_RESERVED 0x7 // upload in progress
108 #define SEG_ID_VALID    0x3 // CRC-32 valid
109 #define SEG_ID_ERASED   0x0 // segment erased
110 
111 #define SEG_ST_EMPTY    SEG_ST(SEG_ID_EMPTY)
112 #define SEG_ST_RESERVED SEG_ST(SEG_ID_RESERVED)
113 #define SEG_ST_VALID    SEG_ST(SEG_ID_VALID)
114 #define SEG_ST_ERASED   SEG_ST(SEG_ID_ERASED)
115 
116 struct Segment {
117     uint8_t  state;   // 0xFF: empty; bit7=0: segment present; bit6=0: size valid; bit5=0: CRC-32 valid; bit4=0:segment erased;
118                       // bits 3-0 replicate bits7-4;
119     uint8_t  size[3]; // actual stored size in flash, initially filled with 0xFF
120                       // updated after flash operation is completed (successfully or not)
121 };
122 
123 struct AppEventFreeData { //goes with EVT_APP_FREE_EVT_DATA
124     uint32_t evtType;
125     void* evtData;
126 };
127 
128 typedef void (*OsDeferCbkF)(void *);
129 
130 typedef void (*EventFreeF)(void* event);
131 
132 SET_PACKED_STRUCT_MODE_ON
133 struct SeosEedataEncrKeyData {
134     uint64_t keyID;
135     uint8_t key[32];
136 } ATTRIBUTE_PACKED;
137 SET_PACKED_STRUCT_MODE_OFF
138 
139 /* ==== ABOUT THE "urgent" FLAG ====
140  *
141  * Do not set "urgent" unless you understand all the repercussions! What repercussions you might ask?
142  * Setting this flag will place your defer request at the front of the queue. This is useful for enqueueing work
143  * from interrupt context that needs to be done "very very soon"(tm). Doing this will delay all other work requests
144  * that have heretofore been peacefully queueing in full faith and with complete belief in fairness of our "FIFO"-ness.
145  * Please be appreciative of this fact and do not abuse this! Example: if you are setting "urgent" flag outside of interrupt
146  * context, you're very very likely wrong. That is not to say that being in interrupt context is a free pass to set this!
147  */
148 
149 // osMainInit is exposed for testing only, it must never be called for any reason at all by anyone
150 void osMainInit(void);
151 // osMainDequeueLoop is exposed for testing only, it must never be called for any reason at all by anyone
152 void osMainDequeueLoop(void);
153 void osMain(void);
154 
155 bool osEventSubscribe(uint32_t tid, uint32_t evtType); /* async */
156 bool osEventUnsubscribe(uint32_t tid, uint32_t evtType);  /* async */
157 
158 bool osEnqueuePrivateEvt(uint32_t evtType, void *evtData, EventFreeF evtFreeF, uint32_t toTid);
159 bool osEnqueuePrivateEvtAsApp(uint32_t evtType, void *evtData, uint32_t fromApp, uint32_t toTid);
160 
161 bool osEnqueueEvt(uint32_t evtType, void *evtData, EventFreeF evtFreeF);
162 bool osEnqueueEvtOrFree(uint32_t evtType, void *evtData, EventFreeF evtFreeF);
163 bool osEnqueueEvtAsApp(uint32_t evtType, void *evtData, uint32_t fromApp);
164 
165 bool osDefer(OsDeferCbkF callback, void *cookie, bool urgent);
166 
167 bool osTidById(uint64_t appId, uint32_t *tid);
168 bool osAppInfoById(uint64_t appId, uint32_t *appIdx, uint32_t *appVer, uint32_t *appSize);
169 bool osAppInfoByIndex(uint32_t appIdx, uint64_t *appId, uint32_t *appVer, uint32_t *appSize);
170 uint32_t osGetCurrentTid();
171 uint32_t osSetCurrentTid(uint32_t);
172 
173 struct AppHdr *osAppSegmentCreate(uint32_t size);
174 bool osAppSegmentClose(struct AppHdr *app, uint32_t segSize, uint32_t segState);
175 bool osAppSegmentSetState(const struct AppHdr *app, uint32_t segState);
176 bool osSegmentSetSize(struct Segment *seg, uint32_t size);
177 bool osAppWipeData(struct AppHdr *app);
178 struct Segment *osGetSegment(const struct AppHdr *app);
179 struct Segment *osSegmentGetEnd();
180 
osSegmentGetSize(const struct Segment * seg)181 static inline int32_t osSegmentGetSize(const struct Segment *seg)
182 {
183     return seg ? seg->size[0] | (seg->size[1] << 8) | (seg->size[2] << 16) : SEG_SIZE_INVALID;
184 }
185 
osSegmentGetState(const struct Segment * seg)186 static inline uint32_t osSegmentGetState(const struct Segment *seg)
187 {
188     return seg ? seg->state : SEG_STATE_INVALID;
189 }
190 
osSegmentGetData(const struct Segment * seg)191 static inline struct AppHdr *osSegmentGetData(const struct Segment *seg)
192 {
193     return (struct AppHdr*)(&seg[1]);
194 }
195 
196 #ifdef SEGMENT_CRC_SUPPORT
197 
198 struct SegmentFooter
199 {
200     uint32_t crc;
201 };
202 
203 #define FOOTER_SIZE sizeof(struct SegmentFooter)
204 #else
205 #define FOOTER_SIZE 0
206 #endif
207 
osSegmentSizeAlignedWithFooter(uint32_t size)208 static inline uint32_t osSegmentSizeAlignedWithFooter(uint32_t size)
209 {
210     return ((size + 3) & ~3) + FOOTER_SIZE;
211 }
212 
osSegmentSizeGetNext(const struct Segment * seg,uint32_t size)213 static inline const struct Segment *osSegmentSizeGetNext(const struct Segment *seg, uint32_t size)
214 {
215     struct Segment *next = (struct Segment *)(((uint8_t*)seg) +
216                                               osSegmentSizeAlignedWithFooter(size) +
217                                               sizeof(*seg)
218                                               );
219     return seg ? next : NULL;
220 }
221 
osSegmentGetNext(const struct Segment * seg)222 static inline const struct Segment *osSegmentGetNext(const struct Segment *seg)
223 {
224     return osSegmentSizeGetNext(seg, osSegmentGetSize(seg));
225 }
226 
osAppSegmentGetState(const struct AppHdr * app)227 static inline uint32_t osAppSegmentGetState(const struct AppHdr *app)
228 {
229     return osSegmentGetState(osGetSegment(app));
230 }
231 
232 struct SegmentIterator {
233     const struct Segment *shared;
234     const struct Segment *sharedEnd;
235     const struct Segment *seg;
236 };
237 
238 void osSegmentIteratorInit(struct SegmentIterator *it);
239 
osSegmentIteratorNext(struct SegmentIterator * it)240 static inline bool osSegmentIteratorNext(struct SegmentIterator *it)
241 {
242     const struct Segment *seg = it->shared;
243     const struct Segment *next = seg < it->sharedEnd ? osSegmentGetNext(seg) : it->sharedEnd;
244 
245     it->shared = next;
246     it->seg = seg;
247 
248     return seg < it->sharedEnd;
249 }
250 
251 bool osWriteShared(void *dest, const void *src, uint32_t len);
252 bool osEraseShared();
253 
254 //event retaining support
255 bool osRetainCurrentEvent(TaggedPtr *evtFreeingInfoP); //called from any apps' event handling to retain current event. Only valid for first app that tries. evtFreeingInfoP filled by call and used to free evt later
256 void osFreeRetainedEvent(uint32_t evtType, void *evtData, TaggedPtr *evtFreeingInfoP);
257 
258 uint32_t osExtAppStopApps(uint64_t appId);
259 uint32_t osExtAppEraseApps(uint64_t appId);
260 uint32_t osExtAppStartApps(uint64_t appId);
261 
262 /* Logging */
263 enum LogLevel {
264     LOG_ERROR = 'E',
265     LOG_WARN  = 'W',
266     LOG_INFO  = 'I',
267     LOG_DEBUG = 'D',
268 };
269 
270 void osLogv(enum LogLevel level, const char *str, va_list vl);
271 void osLog(enum LogLevel level, const char *str, ...) PRINTF_ATTRIBUTE;
272 
273 #ifndef INTERNAL_APP_INIT
274 #define INTERNAL_APP_INIT(_id, _ver, _init, _end, _event)                               \
275 SET_INTERNAL_LOCATION(location, ".internal_app_init")static const struct AppHdr         \
276 SET_INTERNAL_LOCATION_ATTRIBUTES(used, section (".internal_app_init")) mAppHdr = {      \
277     .hdr.magic   = APP_HDR_MAGIC,                                                       \
278     .hdr.fwVer   = APP_HDR_VER_CUR,                                                     \
279     .hdr.fwFlags = FL_APP_HDR_INTERNAL | FL_APP_HDR_APPLICATION,                        \
280     .hdr.appId   = (_id),                                                               \
281     .hdr.appVer  = (_ver),                                                              \
282     .hdr.payInfoType = LAYOUT_APP,                                                      \
283     .vec.init    = (uint32_t)(_init),                                                   \
284     .vec.end     = (uint32_t)(_end),                                                    \
285     .vec.handle  = (uint32_t)(_event)                                                   \
286 }
287 #endif
288 
289 #ifndef APP_INIT
290 #define APP_INIT(_ver, _init, _end, _event)                                             \
291 extern const struct AppFuncs _mAppFuncs;                                                \
292 const struct AppFuncs SET_EXTERNAL_APP_ATTRIBUTES(used, section (".app_init"),          \
293 visibility("default")) _mAppFuncs = {                                                   \
294     .init   = (_init),                                                                  \
295     .end    = (_end),                                                                   \
296     .handle = (_event)                                                                  \
297 };                                                                                      \
298 const uint32_t SET_EXTERNAL_APP_VERSION(used, section (".app_version"),                 \
299 visibility("default")) _mAppVer = _ver
300 #endif
301 
302 
303 #ifdef __cplusplus
304 }
305 #endif
306 
307 #endif
308