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