1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 8 enum{ 9 Qdir, 10 Qboot, 11 Qmem, 12 Qkexec, 13 14 Maxkexec = 1536*1024, 15 }; 16 17 static 18 Dirtab bootdir[]={ 19 ".", {Qdir, 0, QTDIR}, 0, 0555, 20 "boot", {Qboot}, 0, 0220, 21 "mem", {Qmem}, 0, 0660, 22 "kexec", {Qkexec}, 0, 0220, 23 }; 24 25 static Chan* 26 bootattach(char *spec) 27 { 28 return devattach('B', spec); 29 } 30 31 static Walkqid* 32 bootwalk(Chan *c, Chan *nc, char **name, int nname) 33 { 34 return devwalk(c, nc, name, nname, bootdir, nelem(bootdir), devgen); 35 } 36 37 static int 38 bootstat(Chan *c, uchar *dp, int n) 39 { 40 return devstat(c, dp, n, bootdir, nelem(bootdir), devgen); 41 } 42 43 static Chan* 44 bootopen(Chan *c, int omode) 45 { 46 if (c->qid.path == Qkexec) { 47 c->aux = malloc(Maxkexec); 48 print("kexec buffer: %lux\n", c->aux); 49 } 50 return devopen(c, omode, bootdir, nelem(bootdir), devgen); 51 } 52 53 static void 54 bootclose(Chan *c) 55 { 56 if(c->qid.path == Qkexec && c->aux != nil){ 57 print("exec new kernel @%lux\n", (ulong)c->aux); 58 splhi(); 59 segflush(c->aux, 64*1024); 60 gotopc((ulong)c->aux); 61 } 62 } 63 64 static long 65 bootread(Chan *c, void *buf, long n, vlong offset) 66 { 67 switch((ulong)c->qid.path){ 68 69 case Qdir: 70 return devdirread(c, buf, n, bootdir, nelem(bootdir), devgen); 71 72 case Qmem: 73 /* kernel memory */ 74 if(offset>=KZERO && offset<KZERO+conf.npage*BY2PG){ 75 if(offset+n > KZERO+conf.npage*BY2PG) 76 n = KZERO+conf.npage*BY2PG - offset; 77 memmove(buf, (char*)offset, n); 78 return n; 79 } 80 error(Ebadarg); 81 } 82 83 error(Egreg); 84 return 0; /* not reached */ 85 } 86 87 static long 88 bootwrite(Chan *c, void *buf, long n, vlong offset) 89 { 90 ulong pc; 91 uchar *p; 92 93 switch((ulong)c->qid.path){ 94 case Qmem: 95 /* kernel memory */ 96 if(offset>=KZERO && offset<KZERO+conf.npage*BY2PG){ 97 if(offset+n > KZERO+conf.npage*BY2PG) 98 n = KZERO+conf.npage*BY2PG - offset; 99 memmove((char*)offset, buf, n); 100 segflush((void*)offset, n); 101 return n; 102 } 103 error(Ebadarg); 104 105 case Qboot: 106 p = (uchar*)buf; 107 pc = (((((p[0]<<8)|p[1])<<8)|p[2])<<8)|p[3]; 108 if(pc < KZERO || pc >= KZERO+conf.npage*BY2PG) 109 error(Ebadarg); 110 splhi(); 111 segflush((void*)pc, 64*1024); 112 gotopc(pc); 113 114 case Qkexec: 115 print("."); 116 if(c->aux != nil && offset <= Maxkexec){ 117 if(offset+n > Maxkexec) 118 n = Maxkexec - offset; 119 memmove((char*)c->aux+offset, buf, n); 120 segflush((char*)c->aux+offset, n); 121 return n; 122 } 123 free(c->aux); 124 c->aux = nil; 125 error(Ebadarg); 126 } 127 error(Ebadarg); 128 return 0; /* not reached */ 129 } 130 131 Dev bootdevtab = { 132 'B', 133 "boot", 134 135 devreset, 136 devinit, 137 devshutdown, 138 bootattach, 139 bootwalk, 140 bootstat, 141 bootopen, 142 devcreate, 143 bootclose, 144 bootread, 145 devbread, 146 bootwrite, 147 devbwrite, 148 devremove, 149 devwstat, 150 }; 151