- Removed unnecessary casts.
[AROS.git] / arch / all-native / econsole / econsole.c
blob817ede735e5efdc301dbc8aded20b2d636530fd9
1 /*
2 Copyright 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Emergency console launcher for AROS
6 Lang: english
7 */
9 #include <aros/debug.h>
11 #include <aros/asmcall.h>
12 #include <dos/dosextens.h>
13 #include <dos/stdio.h>
15 #include <exec/resident.h>
16 #include <graphics/modeid.h>
17 #include <utility/tagitem.h>
18 #include <libraries/expansion.h>
20 #include <proto/exec.h>
21 #include <proto/dos.h>
22 #include <proto/graphics.h>
23 #include <proto/alib.h>
24 #include <proto/expansion.h>
26 #include LC_LIBDEFS_FILE
28 /********* ECON: DOS Handler
30 * ECON: - interactive file, accesing the Exec/Raw* functions
31 * ECON:AROS.boot - synthetic file, to allow AROS to boot from ECON:
32 * as a last resort.
34 static void replyPkt(struct DosPacket *dp)
36 struct MsgPort *mp;
37 struct Message *mn;
39 mp = dp->dp_Port;
40 mn = dp->dp_Link;
41 mn->mn_Node.ln_Name = (char*)dp;
42 dp->dp_Port = &((struct Process*)FindTask(NULL))->pr_MsgPort;
43 PutMsg(mp, mn);
46 struct econsole_file {
47 CONST_STRPTR ef_Name;
48 BOOL ef_Interactive;
49 SIPTR (*ef_Read)(APTR buff, SIPTR len, SIPTR *actual);
50 SIPTR (*ef_Write)(CONST_APTR buff, SIPTR len, SIPTR *actual);
51 SIPTR (*ef_ExamineFH)(struct FileInfoBlock *fib, SIPTR *actual);
54 SIPTR Raw_Read(APTR buff, SIPTR len, SIPTR *err)
56 SIPTR actual = 0;
57 UBYTE *cp = buff;
59 D(bug("%s: buff=%p, len=%d\n", __func__, buff, len));
60 while (actual < len) {
61 LONG c = RawMayGetChar();
62 if (c < 0) {
63 Reschedule();
64 continue;
67 /* Trivial line editing */
68 switch (c) {
69 case '\b': /* Backspace */
70 if ((APTR)cp > buff) {
71 actual--;
72 cp--;
74 RawPutChar('\b');
75 RawPutChar(' ');
76 RawPutChar('\b');
77 break;
78 case '\r':
79 case '\n': /* Done */
80 *(cp++) = '\n';
81 len = (++actual);
82 RawPutChar('\n');
83 break;
84 default:
85 *(cp++) = (UBYTE)c;
86 actual++;
87 RawPutChar(c);
88 break;
92 *err = 0;
93 return actual;
96 SIPTR Raw_Write(CONST_APTR buff, SIPTR len, SIPTR *err)
98 SIPTR actual;
99 CONST UBYTE *cp = buff;
101 D(bug("%s: buff=%p, len=%d\n", __func__, buff, len));
102 for (actual = 0; actual < len; actual++, cp++) {
103 RawPutChar(*cp);
106 *err = 0;
107 return actual;
110 SIPTR Raw_ExamineFH(struct FileInfoBlock *fib, SIPTR *errcode)
112 memset(fib, 0, sizeof(fib));
113 fib->fib_Protection = FIBF_WRITE | FIBF_READ;
115 *errcode = 0;
116 return DOSTRUE;
119 CONST UBYTE CONST Boot_Data[] = AROS_CPU;
121 SIPTR Boot_Read(APTR buff, SIPTR len, SIPTR *err)
123 SIPTR actual;
124 UBYTE *cp = buff;
126 D(bug("%s: len=%d \"%s\"\n", __func__, len, Boot_Data));
127 for (actual = 0; actual < len; actual++, cp++) {
128 if (Boot_Data[actual] == 0)
129 break;
130 *cp = Boot_Data[actual];
133 *err = 0;
134 return actual;
137 SIPTR Boot_Write(CONST_APTR buff, SIPTR len, SIPTR *err)
139 *err = ERROR_WRITE_PROTECTED;
140 return (SIPTR)-1;
143 SIPTR Boot_ExamineFH(struct FileInfoBlock *fib, SIPTR *errcode)
145 memset(fib, 0, sizeof(fib));
146 fib->fib_FileName[0] = strlen("AROS.boot");
147 CopyMem("AROS.boot", &fib->fib_FileName[1], fib->fib_FileName[0] + 1);
148 fib->fib_Protection = FIBF_READ;
149 fib->fib_Size = sizeof(Boot_Data) - 1;
151 *errcode = 0;
152 return DOSTRUE;
155 const struct econsole_file econsole_files[] = {
156 { .ef_Name = "", .ef_Interactive = TRUE,
157 .ef_Read = Raw_Read, .ef_Write = Raw_Write,
158 .ef_ExamineFH = Raw_ExamineFH
160 { .ef_Name = "AROS.boot", .ef_Interactive = FALSE,
161 .ef_Read = Boot_Read, .ef_Write = Boot_Write,
162 .ef_ExamineFH = Boot_ExamineFH
166 #ifndef ARRAY_SIZE
167 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
168 #endif
170 const struct econsole_file *econsole_file_of(BSTR bname, SIPTR *errcode)
172 STRPTR name, file;
173 int i;
174 int blen = AROS_BSTR_strlen(bname);
176 name = AllocMem(blen + 1, MEMF_ANY);
177 CopyMem(AROS_BSTR_ADDR(bname), name, blen);
178 name[blen] = 0;
180 file = strchr(name, ':');
181 if (file == NULL)
182 file = name;
183 else
184 file++;
186 D(bug("%s: bname=%b, name=%s, file=%s\n", __func__, bname, name, file));
187 for (i = 0; i < ARRAY_SIZE(econsole_files); i++) {
188 if (strcmp(econsole_files[i].ef_Name, file) == 0) {
189 FreeMem(name, blen + 1);
190 *errcode = 0;
191 return &econsole_files[i];
195 FreeMem(name, blen + 1);
196 *errcode = ERROR_OBJECT_NOT_FOUND;
197 return NULL;
200 LONG econ_handler(struct ExecBase *SysBase)
202 struct DosPacket *dp;
203 struct MsgPort *mp;
204 BOOL dead = FALSE;
205 struct FileHandle *fh;
206 const struct econsole_file *efile;
207 struct DeviceNode *dn;
209 mp = &((struct Process *)FindTask(NULL))->pr_MsgPort;
211 WaitPort(mp);
213 dp = (struct DosPacket *)(GetMsg(mp)->mn_Node.ln_Name);
215 dn = ((struct DeviceNode *)BADDR(dp->dp_Arg3));
216 dn->dn_Task = mp;
218 dp->dp_Res2 = 0;
219 dp->dp_Res1 = DOSTRUE;
221 RawIOInit();
223 D(bug("%s: started\n", __func__));
224 do {
225 replyPkt(dp);
226 WaitPort(mp);
227 dp = (struct DosPacket *)(GetMsg(mp)->mn_Node.ln_Name);
228 D(bug("%s: type=%d\n", __func__, dp->dp_Type));
230 switch (dp->dp_Type) {
231 case ACTION_LOCATE_OBJECT:
232 if ((efile = econsole_file_of((BSTR)dp->dp_Arg2, &dp->dp_Res2))) {
233 D(bug("%s: efile=%p (%s)\n", __func__, efile, efile->ef_Name));
234 struct FileLock *fl = AllocMem(sizeof(*fl), MEMF_PUBLIC | MEMF_CLEAR);
235 fl->fl_Link = BNULL;
236 fl->fl_Key = (IPTR)efile;
237 fl->fl_Access = dp->dp_Arg3;
238 fl->fl_Task = mp;
239 fl->fl_Volume = MKBADDR(dn);
240 dp->dp_Res1 = (SIPTR)MKBADDR(fl);
241 } else {
242 dp->dp_Res1 = DOSFALSE;
244 break;
245 case ACTION_FH_FROM_LOCK:
246 if (dp->dp_Arg2) {
247 struct FileLock *fl = BADDR(dp->dp_Arg2);
248 efile = (const struct econsole_file *)fl->fl_Key;
249 D(bug("%s: efile=%p (%s)\n", __func__, efile, efile->ef_Name));
250 fh = BADDR(dp->dp_Arg1);
251 fh->fh_Arg1 = (SIPTR)efile;
252 fh->fh_Type = mp;
253 fh->fh_Interactive = efile->ef_Interactive;
254 FreeMem(fl, sizeof(*fl));
255 dp->dp_Res2 = 0;
256 } else {
257 dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
259 dp->dp_Res1 = dp->dp_Res2 ? DOSFALSE : DOSTRUE;
260 break;
261 case ACTION_COPY_DIR_FH:
262 if (dp->dp_Arg1) {
263 struct FileLock *fl = AllocMem(sizeof(*fl), MEMF_PUBLIC | MEMF_CLEAR);
264 efile = (const struct econsole_file *)dp->dp_Arg1;
265 D(bug("%s: efile=%p (%s)\n", __func__, efile, efile->ef_Name));
266 fl->fl_Link = BNULL;
267 fl->fl_Key = (SIPTR)efile;
268 fl->fl_Access = dp->dp_Arg3;
269 fl->fl_Task = mp;
270 fl->fl_Volume = MKBADDR(dn);
271 dp->dp_Res1 = (SIPTR)MKBADDR(fl);
272 dp->dp_Res2 = 0;
273 } else {
274 dp->dp_Res1 = DOSFALSE;
275 dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
277 break;
278 case ACTION_FREE_LOCK:
279 if (dp->dp_Arg1) {
280 struct FileLock *fl = BADDR(dp->dp_Arg1);
281 FreeMem(fl, sizeof(*fl));
283 dp->dp_Res1 = DOSTRUE;
284 dp->dp_Res2 = 0;
285 break;
286 case ACTION_FINDINPUT:
287 case ACTION_FINDOUTPUT:
288 case ACTION_FINDUPDATE:
289 if ((efile = econsole_file_of((BSTR)dp->dp_Arg3, &dp->dp_Res2))) {
290 D(bug("%s: efile=%p (%s)\n", __func__, efile, efile->ef_Name));
291 fh = BADDR(dp->dp_Arg1);
292 fh->fh_Arg1 = (SIPTR)efile;
293 fh->fh_Type = mp;
294 fh->fh_Interactive = efile->ef_Interactive;
296 dp->dp_Res1 = efile ? DOSTRUE : DOSFALSE;
297 break;
298 case ACTION_READ:
299 if ((efile = (const struct econsole_file *)dp->dp_Arg1)) {
300 D(bug("%s: efile=%p (%s)\n", __func__, efile, efile->ef_Name));
301 dp->dp_Res1 = efile->ef_Read((APTR)dp->dp_Arg2, dp->dp_Arg3, &dp->dp_Res2);
302 } else {
303 dp->dp_Res1 = DOSFALSE;
304 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
306 break;
307 case ACTION_WRITE:
308 if ((efile = (const struct econsole_file *)dp->dp_Arg1)) {
309 D(bug("%s: efile=%p (%s)\n", __func__, efile, efile->ef_Name));
310 dp->dp_Res1 = efile->ef_Write((CONST_APTR)dp->dp_Arg2, dp->dp_Arg3, &dp->dp_Res2);
311 } else {
312 dp->dp_Res1 = DOSFALSE;
313 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
315 break;
316 case ACTION_EXAMINE_FH:
317 if ((efile = (const struct econsole_file *)dp->dp_Arg1)) {
318 dp->dp_Res1 = efile->ef_ExamineFH((struct FileInfoBlock *)BADDR(dp->dp_Arg2), &dp->dp_Res2);
319 } else {
320 dp->dp_Res1 = DOSFALSE;
321 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
323 break;
324 case ACTION_END:
325 dp->dp_Res1 = DOSTRUE;
326 dp->dp_Res2 = 0;
327 break;
328 case ACTION_DIE:
329 dp->dp_Res1 = DOSTRUE;
330 dp->dp_Res2 = 0;
331 dead = TRUE;
332 break;
333 default:
334 dp->dp_Res1 = DOSFALSE;
335 dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
336 break;
338 D(bug("%s: Type %d, Res1=%p, Res2=%p\n", __func__, dp->dp_Type, dp->dp_Res1, dp->dp_Res2));
339 } while (!dead);
341 /* ACTION_DIE ends up here... */
342 D(bug("%s: Exiting\n", __func__));
344 replyPkt(dp);
346 return RETURN_OK;