1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
46:
47: 48: 49: 50: 51: 52:
53:
54: #include <basic.h>
55: #include <errno.h>
56: #include <sys/debug.h>
57: #include <tk/tkernel.h>
58: #include <t2ex/load.h>
59: #include "service.h"
60: #include "pminfo.h"
61: #include "source.h"
62: #include "elf.h"
63:
64: IMPORT ER elf_load( ProgInfo *pg, LoadSource *ldr, UINT attr, Elf32_Ehdr *hdr );
65: IMPORT ER pmCallStartup( INT ac, UB *av[], FP entry );
66:
67: 68: 69:
70: LOCAL ER pmOpenSource( LoadSource* source, const struct pm* prog )
71: {
72: switch (prog->pmtype) {
73: #if USE_FILELOADER
74: case PM_FILE:
75: return openFileSource(source, prog);
76: #endif
77: #if USE_MEMLOADER
78: case PM_PTR:
79: return openMemSource(source, prog);
80: #endif
81: default:
82: return EX_INVAL;
83: }
84: }
85:
86:
87: 88: 89:
90: typedef struct {
91: Elf32_Ehdr elf;
92: } ObjectHeader;
93:
94:
95: 96: 97:
98: LOCAL ID pmLoadProg( const struct pm* prog, UINT attr, FP* entry )
99: {
100: LoadSource source;
101: ProgInfo *pginfo;
102: ObjectHeader hdr;
103: ER er;
104:
105:
106: pginfo = pmAllocInfo();
107: if ( pginfo == NULL ) { er = E_LIMIT; goto err_ret0; }
108: pginfo->attr = attr;
109:
110:
111: er = pmOpenSource(&source, prog);
112: if ( er < E_OK ) goto err_ret1;
113:
114:
115: er = source.read(&source, 0, &hdr, sizeof(ObjectHeader));
116: if ( er < E_OK ) goto err_ret2;
117: if ( er < sizeof(ObjectHeader) ) { er = EX_NOEXEC; goto err_ret2; }
118:
119:
120: if ( hdr.elf.e_ident[EI_MAG0] == ELFMAG0
121: && hdr.elf.e_ident[EI_MAG1] == ELFMAG1
122: && hdr.elf.e_ident[EI_MAG2] == ELFMAG2
123: && hdr.elf.e_ident[EI_MAG3] == ELFMAG3 ) {
124:
125: er = elf_load(pginfo, &source, attr, &(hdr.elf));
126: }
127: else {
128:
129: er = EX_NOEXEC;
130: goto err_ret2;
131: }
132: if ( er < E_OK ) goto err_ret2;
133:
134: source.close(&source);
135:
136:
137: *entry = pginfo->entry;
138: er = pginfo->pmid;
139:
140: return er;
141:
142: err_ret2:
143: source.close(&source);
144: err_ret1:
145: pmFreeInfo(pginfo);
146: err_ret0:
147: TM_DEBUG_PRINT(("_pm_load ercd = %d\n", er));
148: return er;
149: }
150:
151:
152: 153: 154:
155: Inline ER pmUnloadProg( ProgInfo* pginfo )
156: {
157: ER er;
158:
159: er = tk_rel_smb(pginfo->loadadr);
160: pmFreeInfo(pginfo);
161:
162: return er;
163: }
164:
165:
166: 167: 168:
169: EXPORT ID _pm_load( const struct pm* prog, UINT attr, pm_entry_t** entry )
170: {
171: ER er;
172: ID pmid;
173: FP realEntry;
174: ProgInfo* pginfo;
175:
176:
177: er = ChkSpaceR(prog, sizeof(*prog));
178: if ( er < E_OK ) goto err_ret0;
179:
180: if ( entry ) {
181: er = ChkSpaceR(entry, sizeof(*entry));
182: if ( er < E_OK ) goto err_ret0;
183: }
184:
185: LockPM();
186:
187:
188: er = pmLoadProg(prog, attr, &realEntry);
189: if ( er < E_OK ) goto err_ret1;
190: pmid = er;
191: pginfo = pmGetInfo(pmid);
192:
193:
194: er = pmCallStartup(0, (UB**)&(pginfo->modentry), realEntry);
195: if ( er < E_OK ) goto err_ret2;
196: if ( !pginfo->modentry ) { er = EX_INVAL; goto err_ret2; }
197:
198:
199: if ( entry ) {
200: *entry = (pm_entry_t*)pginfo->modentry;
201: }
202:
203: UnlockPM();
204:
205: return pmid;
206:
207: err_ret2:
208: pmUnloadProg(pginfo);
209: err_ret1:
210: UnlockPM();
211: err_ret0:
212: TM_DEBUG_PRINT(("_pm_load ercd = %d\n", er));
213: return er;
214: }
215:
216:
217: 218: 219:
220: EXPORT ID _pm_loadspg( const struct pm* prog, INT ac, UB* av[] )
221: {
222: ER er;
223: ID pmid;
224: int i;
225: FP entry = NULL;
226:
227:
228: er = ChkSpaceR(prog, sizeof(*prog));
229: if ( er < E_OK ) goto err_ret0;
230:
231: if ( ac < 0 ) goto err_ret0;
232:
233: er = ChkSpaceR(av, ac * sizeof(UB*));
234: if ( er < E_OK ) goto err_ret0;
235:
236: for ( i = 0; i < ac; i++ ) {
237: er = ChkSpaceR(av[i], 0);
238: if ( er < E_OK ) goto err_ret0;
239: }
240:
241: LockPM();
242:
243:
244: er = pmLoadProg(prog, TA_RNG0, &entry);
245: if ( er < E_OK ) goto err_ret1;
246: pmid = er;
247:
248:
249: er = pmCallStartup(ac, av, entry);
250: if ( er < E_OK ) goto err_ret2;
251:
252: UnlockPM();
253:
254: return pmid;
255:
256: err_ret2:
257: pmUnloadProg(pmGetInfo(pmid));
258: err_ret1:
259: UnlockPM();
260: err_ret0:
261: TM_DEBUG_PRINT(("_pm_loadspg ercd = %d\n", er));
262: return er;
263: }
264:
265:
266: 267: 268:
269: EXPORT ER _pm_unload( ID progid )
270: {
271: ProgInfo* pginfo;
272: ER er;
273:
274: LockPM();
275:
276:
277: pginfo = pmGetInfo(progid);
278: if ( !pginfo || !pginfo->used ) {
279: er = E_ID;
280: goto err_ret;
281: }
282:
283:
284: er = pmCallStartup(-1, NULL, pginfo->entry);
285:
286:
287: pmUnloadProg(pginfo);
288:
289: UnlockPM();
290:
291: return er;
292:
293: err_ret:
294: UnlockPM();
295: TM_DEBUG_PRINT(("_pm_unload ercd = %d\n", er));
296: return er;
297: }
298:
299:
300: 301: 302:
303: EXPORT ER _pm_status( ID progid, struct pm_stat* status )
304: {
305: ER er;
306: ProgInfo* pginfo;
307:
308:
309: er = ChkSpaceR(status, sizeof(*status));
310: if ( er < E_OK ) goto err_ret0;
311:
312: LockPM();
313:
314:
315: pginfo = pmGetInfo(progid);
316: if ( !pginfo || !pginfo->used ) {
317: er = E_ID;
318: goto err_ret1;
319: }
320:
321:
322: status->sysprg = ( pginfo->modentry )? FALSE: TRUE;
323: status->attr = pginfo->attr;
324: status->entry = ( pginfo->modentry )? pginfo->modentry: pginfo->entry;
325: status->start = pginfo->loadadr;
326: status->end = (void*)((B*)pginfo->loadadr + pginfo->loadsz);
327:
328: UnlockPM();
329:
330: return E_OK;
331:
332: err_ret1:
333: UnlockPM();
334: err_ret0:
335: TM_DEBUG_PRINT(("_pm_status ercd = %d\n", er));
336: return er;
337: }