devkexec.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "kexec.h"
  16. enum
  17. {
  18. Maxkexecsize = 16300,
  19. };
  20. int kxdbg = 0;
  21. #define KXDBG if(!kxdbg) {} else print
  22. static Kexecgrp *kexecgrp(Chan *c);
  23. static int kexecwriteable(Chan *c);
  24. static Kexecgrp kgrp; /* global kexec group containing the kernel configuration */
  25. static Kvalue*
  26. kexeclookup(Kexecgrp *kg, uintptr_t addr, uint32_t qidpath)
  27. {
  28. Kvalue *e;
  29. int i;
  30. for(i=0; i<kg->nent; i++){
  31. e = kg->ent[i];
  32. if(e->qid.path == qidpath || e->addr==addr)
  33. return e;
  34. }
  35. return nil;
  36. }
  37. static int
  38. kexecgen(Chan *c, char *name, Dirtab* dir, int i, int s, Dir *dp)
  39. {
  40. Proc *up = externup();
  41. Kexecgrp *kg;
  42. Kvalue *e;
  43. uintptr_t addr;
  44. print("starting gen name %s\n", name);
  45. if(s == DEVDOTDOT){
  46. devdir(c, c->qid, "#§", 0, eve, DMDIR|0775, dp);
  47. return 1;
  48. }
  49. print("getting kg name %s\n", name);
  50. kg = kexecgrp(c);
  51. rlock(kg);
  52. e = 0;
  53. if(name) {
  54. addr = strtoull(name, nil, 0);
  55. print("got addr %p\n", addr);
  56. e = kexeclookup(kg, addr, -1);
  57. }else if(s < kg->nent)
  58. e = kg->ent[s];
  59. if(e == 0) {
  60. runlock(kg);
  61. return -1;
  62. }
  63. /* make sure name string continues to exist after we release lock */
  64. // how will we free this?
  65. snprint(up->genbuf, sizeof up->genbuf, "0x%p", addr);
  66. print("up->genbuf %s e 0x%p\n", up->genbuf, e);
  67. print("e qid %d e->addr 0x%p size %ld len %ld\n", e->qid, e->addr, e->size, e->len);
  68. devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp);
  69. runlock(kg);
  70. print("finished gen\n");
  71. return 1;
  72. }
  73. #define QPATH(p,d,t) ((p)<<16 | (d)<<8 | (t)<<0)
  74. static Chan*
  75. kexecattach(char *spec)
  76. {
  77. Chan *c;
  78. // Kexecgrp *kgrp = nil;
  79. // Qid qid;
  80. c = devattach(L'§', spec);
  81. c->aux = &kgrp;
  82. return c;
  83. }
  84. static Walkqid*
  85. kexecwalk(Chan *c, Chan *nc, char **name, int nname)
  86. {
  87. return devwalk(c, nc, name, nname, 0, 0, kexecgen);
  88. }
  89. static int32_t
  90. kexecstat(Chan *c, uint8_t *db, int32_t n)
  91. {
  92. int32_t nn;
  93. if(c->qid.type & QTDIR)
  94. c->qid.vers = kexecgrp(c)->vers;
  95. nn = devstat(c, db, n, 0, 0, kexecgen);
  96. return nn;
  97. }
  98. static Chan*
  99. kexecopen(Chan *c, int omode)
  100. {
  101. Kexecgrp *kg;
  102. Kvalue *e;
  103. int trunc;
  104. kg = kexecgrp(c);
  105. if(c->qid.type & QTDIR) {
  106. if(omode != OREAD)
  107. error(Eperm);
  108. }else {
  109. trunc = omode & OTRUNC;
  110. if(omode != OREAD && !kexecwriteable(c))
  111. error(Eperm);
  112. if(trunc)
  113. wlock(kg);
  114. else
  115. rlock(kg);
  116. e = kexeclookup(kg, 0, c->qid.path);
  117. if(e == 0) {
  118. if(trunc)
  119. wunlock(kg);
  120. else
  121. runlock(kg);
  122. error(Enonexist);
  123. }
  124. if(trunc && e->size) { // better validity check?
  125. e->qid.vers++;
  126. e->size = 0;
  127. e->len = 0;
  128. }
  129. if(trunc)
  130. wunlock(kg);
  131. else
  132. runlock(kg);
  133. }
  134. c->mode = openmode(omode);
  135. c->flag |= COPEN;
  136. c->offset = 0;
  137. return c;
  138. }
  139. static void
  140. kexeccreate(Chan *c, char *name, int omode, int i)
  141. {
  142. Proc *up = externup();
  143. Kexecgrp *kg;
  144. Kvalue *e;
  145. Kvalue **ent;
  146. uintptr_t addr;
  147. addr = strtoull(name, nil, 0);
  148. if(c->qid.type != QTDIR)
  149. error(Eperm);
  150. omode = openmode(omode);
  151. kg = kexecgrp(c);
  152. wlock(kg);
  153. if(waserror()) {
  154. wunlock(kg);
  155. nexterror();
  156. }
  157. if(kexeclookup(kg, addr, -1))
  158. error(Eexist);
  159. e = smalloc(sizeof(Kvalue));
  160. e->addr = addr;
  161. if(kg->nent == kg->ment){
  162. kg->ment += 32;
  163. ent = smalloc(sizeof(kg->ent[0])*kg->ment);
  164. if(kg->nent)
  165. memmove(ent, kg->ent, sizeof(kg->ent[0])*kg->nent);
  166. free(kg->ent);
  167. kg->ent = ent;
  168. }
  169. e->qid.path = ++kg->path;
  170. e->qid.vers = 0;
  171. kg->vers++;
  172. kg->ent[kg->nent++] = e;
  173. c->qid = e->qid;
  174. wunlock(kg);
  175. poperror();
  176. c->offset = 0;
  177. c->mode = omode;
  178. c->flag |= COPEN;
  179. }
  180. static void
  181. kexecremove(Chan *c)
  182. {
  183. int i;
  184. Kexecgrp *kg;
  185. Kvalue *e;
  186. if(c->qid.type & QTDIR)
  187. error(Eperm);
  188. kg = kexecgrp(c);
  189. wlock(kg);
  190. e = 0;
  191. for(i=0; i<kg->nent; i++){
  192. if(kg->ent[i]->qid.path == c->qid.path){
  193. e = kg->ent[i];
  194. kg->nent--;
  195. kg->ent[i] = kg->ent[kg->nent];
  196. kg->vers++;
  197. break;
  198. }
  199. }
  200. wunlock(kg);
  201. if(e == 0)
  202. error(Enonexist);
  203. free(e);
  204. }
  205. static void
  206. kexecclose(Chan *c)
  207. {
  208. /*
  209. * cclose can't fail, so errors from remove will be ignored.
  210. * since permissions aren't checked,
  211. * kexecremove can't not remove it if its there.
  212. */
  213. if(c->flag & CRCLOSE)
  214. kexecremove(c);
  215. }
  216. static int32_t
  217. kexecread(Chan *c, void *a, int32_t n, int64_t off)
  218. {
  219. Kexecgrp *kg;
  220. Kvalue *e;
  221. int32_t offset;
  222. if(c->qid.type & QTDIR)
  223. return devdirread(c, a, n, 0, 0, kexecgen);
  224. kg = kexecgrp(c);
  225. rlock(kg);
  226. e = kexeclookup(kg, 0, c->qid.path);
  227. if(e == 0) {
  228. runlock(kg);
  229. error(Enonexist);
  230. }
  231. offset = off;
  232. if(offset > e->len) /* protects against overflow converting int64_t to long */
  233. n = 0;
  234. else if(offset + n > e->len)
  235. n = e->len - offset;
  236. if(n <= 0)
  237. n = 0;
  238. // else
  239. // memmove(a, e->value+offset, n);
  240. runlock(kg);
  241. return n;
  242. }
  243. /*
  244. need to make slots. the slots themselves can be set somewhere else.
  245. need make the writes
  246. open will handle the parsing of the hex numbers.
  247. no, do it the other way around. just define the slots.
  248. can work on the interface later.
  249. kmap the space where the values need to stay safe.
  250. then when that is correct you can do it the other.
  251. kmap address range
  252. put it in
  253. write is going to be significantly different.
  254. the first thing to do is to make this just work.
  255. add to the kernel cfg.
  256. */
  257. static int32_t
  258. kexecwrite(Chan *c, void *a, int32_t n, int64_t off)
  259. {
  260. Kexecgrp *kg;
  261. Kvalue *e;
  262. int32_t offset;
  263. if(n <= 0)
  264. return 0;
  265. offset = off;
  266. if(offset > Maxkexecsize || n > (Maxkexecsize - offset))
  267. error(Etoobig);
  268. print("a: %s\n", a);
  269. kg = kexecgrp(c);
  270. wlock(kg);
  271. e = kexeclookup(kg, 0, c->qid.path);
  272. if(e == 0) {
  273. wunlock(kg);
  274. error(Enonexist);
  275. }
  276. // XXX: what to do with what is written?
  277. e->qid.vers++;
  278. kg->vers++;
  279. wunlock(kg);
  280. return n;
  281. }
  282. Dev kexecdevtab = {
  283. .dc = L'§',
  284. .name = "kexec",
  285. .reset = devreset,
  286. .init = devinit,
  287. .shutdown = devshutdown,
  288. .attach = kexecattach,
  289. .walk = kexecwalk,
  290. .stat = kexecstat,
  291. .open = kexecopen,
  292. .create = kexeccreate,
  293. .close = kexecclose,
  294. .read = kexecread,
  295. .bread = devbread,
  296. .write = kexecwrite,
  297. .bwrite = devbwrite,
  298. .remove = kexecremove,
  299. .wstat = devwstat,
  300. };
  301. void
  302. kexeccpy(Kexecgrp *to, Kexecgrp *from)
  303. {
  304. int i;
  305. Kvalue *ne, *e;
  306. rlock(from);
  307. to->ment = (from->nent+31)&~31;
  308. to->ent = smalloc(to->ment*sizeof(to->ent[0]));
  309. for(i=0; i<from->nent; i++){
  310. e = from->ent[i];
  311. ne = smalloc(sizeof(Kvalue));
  312. ne->addr = e->addr;
  313. ne->size = e->size;
  314. ne->qid.path = ++to->path;
  315. to->ent[i] = ne;
  316. }
  317. to->nent = from->nent;
  318. runlock(from);
  319. }
  320. void
  321. closekgrp(Kexecgrp *kg)
  322. {
  323. int i;
  324. Kvalue *e;
  325. if(decref(kg) == 0){
  326. for(i=0; i<kg->nent; i++){
  327. e = kg->ent[i];
  328. free(e);
  329. }
  330. free(kg->ent);
  331. free(kg);
  332. }
  333. }
  334. static Kexecgrp*
  335. kexecgrp(Chan *c)
  336. {
  337. if(c->aux == nil)
  338. return &kgrp;
  339. return c->aux;
  340. }
  341. static int
  342. kexecwriteable(Chan *c)
  343. {
  344. return iseve() || c->aux == nil;
  345. }