2 #include <aura/private.h>
3 #include <linux/easynmc.h>
12 #define MAGIC 0xbeefbabe
13 #define AURA_MAGIC_HDR 0xdeadf00d
14 #define AURA_OBJECT_EVENT 0xdeadc0de
15 #define AURA_OBJECT_METHOD 0xdeadbeaf
16 #define AURA_STRLEN 16
18 struct nmc_aura_object {
21 uint32_t name[AURA_STRLEN];
22 uint32_t argfmt[AURA_STRLEN];
23 uint32_t retfmt[AURA_STRLEN];
28 struct nmc_aura_header {
39 struct nmc_aura_syncbuffer {
42 uint32_t inbound_buffer_ptr;
43 uint32_t outbound_buffer_ptr;
46 struct nmc_export_table {
47 struct nmc_aura_header hdr;
48 struct nmc_aura_object objs[];
53 NMC_EVENT_TRANSPORT=1<<1
56 struct ion_buffer_descriptor {
60 ion_user_handle_t hndl;
66 struct easynmc_handle *h;
70 struct aura_node *node;
76 struct nmc_aura_syncbuffer *sbuf;
80 struct aura_export_table *etbl;
83 static char *nmc_fetch_str(
void *nmstr)
88 uint8_t *tmp = malloc(len);
89 char *ret = (
char *) tmp;
93 *tmp++ = (uint8_t) (*n++ & 0xff);
99 static int handle_aura_rpc_section(
struct easynmc_handle *h,
char* name, FILE *rfd, GElf_Shdr shdr)
101 struct nmc_private *pv = easynmc_userdata_get(h);
103 if (strcmp(name,
".aura_rpc_exports") == 0) {
104 uint32_t addr = shdr.sh_addr << 2;
105 uint32_t size = shdr.sh_size;
107 slog(4, SLOG_DEBUG,
"transport-nmc: Found RPC export section: %s at offset %u len %u",
111 slog(4, SLOG_ERROR,
"transport-nmc: RPC export section is empty!",
112 name, pv->eaddr, pv->esz);
120 if (strcmp(name,
".aura_rpc_syncbuf") == 0) {
121 uint32_t addr = shdr.sh_addr << 2;
122 uint32_t size = shdr.sh_size;
124 slog(4, SLOG_DEBUG,
"transport-nmc: Found sync buffer: %s at offset %u len %u",
127 slog(4, SLOG_ERROR,
"transport-nmc: RPC export section is empty!",
128 name, pv->eaddr, pv->esz);
132 pv->sbuf = (
struct nmc_aura_syncbuffer*) &pv->h->imem[addr];
138 static int parse_and_register_exports(
struct nmc_private *pv)
140 struct nmc_aura_object *cur;
141 struct nmc_export_table *tbl = (
struct nmc_export_table *) &pv->h->imem[pv->eaddr];
142 struct aura_export_table *etbl;
143 struct aura_node *node = pv->node;
148 if (tbl->hdr.magic != AURA_MAGIC_HDR) {
149 slog (0, SLOG_ERROR,
"transport-nmc: Bad rpc magic");
153 if (tbl->hdr.strlen != AURA_STRLEN) {
154 slog (0, SLOG_ERROR,
"transport-nmc: strlen mismatch: %d vs %d",
155 tbl->hdr.strlen, AURA_STRLEN);
159 slog(4, SLOG_DEBUG,
"transport-nmc: parsing objects");
162 while (cur->type != 0) {
163 if ((cur->type != AURA_OBJECT_METHOD) &&
164 (cur->type != AURA_OBJECT_EVENT))
170 etbl = aura_etable_create(node, count);
172 BUG(node,
"Failed to create etable");
175 while (cur->type != 0) {
177 if (cur->type == AURA_OBJECT_METHOD)
179 if (cur->type == AURA_OBJECT_EVENT)
182 slog(0, SLOG_WARN,
"transport-nmc: Bad data in object section, load stopped");
186 char *name = nmc_fetch_str(cur->name);
187 char *arg = nmc_fetch_str(cur->argfmt);
188 char *ret = nmc_fetch_str(cur->retfmt);
190 aura_etable_add(etbl, name, arg, ret);
192 slog(4, SLOG_DEBUG,
"transport-nmc: %s name %s (%s : %s)",
193 type, name, arg, ret);
201 for (i=0; i<etbl->next; i++) {
202 struct aura_object *o = &etbl->objects[i];
203 if (o->retlen > max_buf_sz)
204 max_buf_sz = o->retlen;
207 pv->inbufsize = max_buf_sz;
213 static struct easynmc_section_filter rpc_filter = {
214 .name =
"aura_rpc_exports",
215 .handle_section = handle_aura_rpc_section
218 static void nonblock(
int fd,
int state)
220 struct termios ttystate;
222 tcgetattr(fd, &ttystate);
225 ttystate.c_lflag &= ~(ICANON|ECHO);
226 ttystate.c_cc[VTIME] = 0;
227 ttystate.c_cc[VMIN] = 0;
232 ttystate.c_lflag |= ICANON | ECHO;
235 tcsetattr(fd, TCSANOW, &ttystate);
240 static int nmc_open(
struct aura_node *node,
const char *filepath)
243 struct easynmc_handle *h = easynmc_open(EASYNMC_CORE_ANY);
247 struct nmc_private *pv = calloc(1,
sizeof(*pv));
253 pv->ion_fd = ion_open();
255 if (pv->ion_fd < 0) {
256 slog(0, SLOG_ERROR,
"Failed to init ion");
261 BUG(node,
"Internal BUG: aura_buffer header must be 4-byte aligned")
266 easynmc_userdata_set(h, pv);
268 easynmc_register_section_filter(h, &rpc_filter);
270 ret = easynmc_load_abs(h, filepath, &pv->ep, ABSLOAD_FLAG_DEFAULT);
271 if ((ret != 0) || (!pv->eaddr)) {
272 slog(0, SLOG_ERROR,
"transport-nmc: abs file doesn't have a valid aura_rpc_exports section");
277 ret = parse_and_register_exports(pv);
283 nonblock(h->iofd, 1);
285 aura_add_pollfds(node, h->iofd, (EPOLLIN | EPOLLET));
286 aura_add_pollfds(node, h->memfd, (EPOLLPRI | EPOLLET));
288 easynmc_start_app(h, pv->ep);
298 static void fetch_stdout(
struct aura_node *node)
304 slog(4, SLOG_DEBUG,
"transport-nmc: We can read stdout!");
305 count = read(pv->h->iofd, tmp, 128);
308 fwrite(tmp, count, 1, stdout);
315 static void nmc_close(
struct aura_node *node)
323 aura_del_pollfds(node, pv->h->iofd);
324 aura_del_pollfds(node, pv->h->memfd);
325 easynmc_close(pv->h);
333 static uint32_t aura_buffer_to_nmc(
struct aura_buffer *buf)
335 struct aura_node *node = buf->
owner;
337 struct ion_buffer_descriptor *dsc = container_of(buf,
struct ion_buffer_descriptor, buf);
340 if (dsc->share_fd == -1) {
341 int ret = ion_share(pv->ion_fd, dsc->hndl, &dsc->share_fd);
343 BUG(node,
"ion_share() failed");
346 nmaddress = easynmc_ion2nmc(pv->h, dsc->share_fd);
348 BUG(node,
"Failed to obtain nm address handle");
353 static inline void do_issue_next_call(
struct aura_node *node)
357 struct aura_object *o;
366 BUG(node,
"Buffer allocation faield");
369 pv->current_out = out_buf;
370 pv->current_in = in_buf;
371 pv->sbuf->id = o->id;
373 pv->sbuf->outbound_buffer_ptr = aura_buffer_to_nmc(out_buf);
374 pv->sbuf->inbound_buffer_ptr = aura_buffer_to_nmc(in_buf);
375 pv->sbuf->state = SYNCBUF_ARGOUT;
378 static void nmc_loop(
struct aura_node *node,
const struct aura_pollfds *fd)
381 struct easynmc_handle *h = pv->h;
384 if (!pv->is_online && (easynmc_core_state(h) == EASYNMC_CORE_RUNNING)) {
385 aura_etable_activate(pv->etbl);
390 if (pv->is_online && (easynmc_core_state(h) != EASYNMC_CORE_RUNNING)) {
395 if (fd && (fd->fd == pv->h->iofd))
399 switch (pv->sbuf->state) {
401 slog(4, SLOG_DEBUG,
"transport-nmc: We can issue our call");
402 do_issue_next_call(node);
405 slog(4, SLOG_DEBUG,
"transport-nmc: NMC is still working");
410 pv->current_out = NULL;
411 pv->current_in = NULL;
412 pv->sbuf->state = SYNCBUF_IDLE;
413 slog(4, SLOG_DEBUG,
"transport-nmc: We got something from nmc");
416 BUG(node,
"Unexpected syncbuf state");
421 struct aura_buffer *ion_buffer_request(
struct aura_node *node,
int size)
425 ion_user_handle_t hndl;
428 struct ion_buffer_descriptor *dsc = malloc(
sizeof(*dsc));
430 BUG(node,
"malloc failed!");
432 ret = ion_alloc(pv->ion_fd, size, 0x10, 0xf, 0, &hndl);
434 BUG(node,
"ION allocation of %d bytes failed: %d", size, ret);
436 ret = ion_map(pv->ion_fd, hndl, size, (PROT_READ | PROT_WRITE),
437 MAP_SHARED, 0, (
void *) &dsc->buf.data, &map_fd);
439 BUG(node,
"ION mmap failed");
441 dsc->map_fd = map_fd;
448 static void ion_buffer_release(
struct aura_buffer *buf)
450 struct aura_node *node = buf->
owner;
452 struct ion_buffer_descriptor *dsc = container_of(buf,
struct ion_buffer_descriptor, buf);
455 munmap(dsc->buf.data, dsc->size);
457 ret = ion_free(pv->ion_fd, dsc->hndl);
459 BUG(node,
"Shit happened when doing ion_free(): %d", ret);
473 if (
sizeof(
void*) != 4)
474 BUG(dst->
owner,
"You know why we are screwed here, jerk!");
476 uint64_t buf_addrs = aura_buffer_to_nmc(buf);
477 buf_addrs |= (((uint64_t) (uintptr_t) buf) << 32);
479 slog(4, SLOG_DEBUG,
"nmc: serialized buf 0x%x to 0x%llx ", buf, buf_addrs);
486 slog(4, SLOG_DEBUG,
"nmc: deserialized buf 0x%x from 0x%llx ", buf, addrs);
497 .buffer_request = ion_buffer_request,
498 .buffer_release = ion_buffer_release,
499 .buffer_get = nmc_buffer_get,
500 .buffer_put = nmc_buffer_put,
void aura_set_status(struct aura_node *node, int status)
struct aura_buffer * aura_buffer_request(struct aura_node *nd, int size)
struct aura_buffer * aura_dequeue_buffer(struct list_head *head)
const char * name
Required.
static void aura_set_userdata(struct aura_node *node, void *udata)
void aura_buffer_put_u64(struct aura_buffer *buf, uint64_t value)
Put an unsigned 64 bit integer to aura buffer.
uint64_t aura_buffer_get_u64(struct aura_buffer *buf)
Get an unsigned 64 bit integer from aura buffer.
void aura_queue_buffer(struct list_head *list, struct aura_buffer *buf)
static void * aura_get_userdata(struct aura_node *node)
void aura_buffer_release(struct aura_buffer *buf)
struct aura_object * object