devkexec.c 6.9 KB

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