2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Amiga bootloader -- config file routines
9 #include <exec/types.h>
10 #include <exec/lists.h>
11 #include <exec/nodes.h>
12 #include <exec/memory.h>
14 #include <dos/rdargs.h>
19 #include <proto/exec.h>
20 #include <proto/alib.h>
21 #include <proto/dos.h>
27 #define D(x) if (debug) x
31 * Maximum config file length. Is actually 100, but we add 2 for the newline
32 * character and the \0 character. Add another character for the V36/V37 FGets
33 * bug. All of this still implies a maximum line length of 100 to the user.
35 #define MAX_LINE_LEN 103
37 char txt_module
[] = "MODULE";
38 char args_module
[] = "MODULE/K/A";
39 #define ARG_MOD_MODULE 0
41 LONG vec_module
[ARG_MOD_END
];
43 char txt_function
[] = "FUNCTION";
44 char args_function
[] = "FUNCTION/N/K/A,MODULE/A,ON/S,OFF/S";
45 #define ARG_FUNC_FUNCTION 0
46 #define ARG_FUNC_MODULE 1
48 #define ARG_FUNC_OFF 3
49 #define ARG_FUNC_END 4
50 LONG vec_function
[ARG_FUNC_END
];
52 BOOL
isconfigline(char *, char *);
53 struct Node
*FindNameNC(struct List
*, UBYTE
*);
55 struct BootConfig
*ReadConfig(char *file
)
60 struct RDArgs
*rdargs
;
61 struct BootConfig
*config
;
62 struct ModNode
*modnode
;
63 struct FuncNode
*funcnode
;
66 D(bug("Processing config file\n"));
68 D(bug("Allocating Config..."));
69 if( (config
= AllocVec(sizeof(*config
), MEMF_CLEAR
)))
72 NewList(&config
->bc_Modules
);
75 D(bug("Allocating RDArgs..."));
76 if( (rdargs
= AllocDosObject(DOS_RDARGS
, NULL
)))
79 D(bug("Allocating linebuffer..."));
80 if( (linebuffer
= AllocMem(MAX_LINE_LEN
, MEMF_CLEAR
)))
84 D(bug("Opening config file \"%s\"", (ULONG
)file
));
85 if( (fh
= Open(file
, MODE_OLDFILE
)))
91 /* MAX_LINE_LEN-1 because of V36/V37 bug */
92 if( (FGets(fh
, linebuffer
, MAX_LINE_LEN
-1)))
94 rdargs
->RDA_Source
.CS_Buffer
= linebuffer
;
95 rdargs
->RDA_Source
.CS_Length
= MAX_LINE_LEN
;
96 rdargs
->RDA_Source
.CS_CurChr
= 0;
97 rdargs
->RDA_Buffer
= NULL
;
99 if( (isconfigline(linebuffer
, txt_module
)))
101 vec_module
[0] = NULL
;
103 D(bug("About to ReadArgs()..."));
104 if( (ReadArgs(args_module
, vec_module
, rdargs
)))
108 D(bug("Found module: \"%s\"\n", vec_module
[ARG_MOD_MODULE
]));
110 D(bug("Looking if module already included..."));
111 if(!(FindNameNC(&config
->bc_Modules
,
112 (STRPTR
)vec_module
[ARG_MOD_MODULE
])))
116 D(bug("Allocating module node..."));
117 if( (modnode
= AllocVec(sizeof(*modnode
), MEMF_CLEAR
)))
121 NewList(&modnode
->mn_FuncList
);
123 D(bug("Allocating space for module name..."));
124 if( (modnode
->mn_Node
.ln_Name
=
125 AllocVec(strlen((char *)vec_module
[ARG_MOD_MODULE
])+1,
130 strcpy(modnode
->mn_Node
.ln_Name
, (char *)vec_module
[ARG_MOD_MODULE
]);
131 D(bug("Copied name \"%s\"\n", (ULONG
)modnode
->mn_Node
.ln_Name
));
133 D(bug("Adding node to list\n"));
134 AddTail(&config
->bc_Modules
, &modnode
->mn_Node
);
140 ioerr
= ERROR_NO_FREE_STORE
;
146 ioerr
= ERROR_NO_FREE_STORE
;
154 Printf("Module \"%s\" declared twice. Ignored second occurence.\n",
155 (ULONG
)vec_module
[ARG_MOD_MODULE
]
164 D(bug(" fail or incomplete parameters\n"));
167 else if( (isconfigline(linebuffer
, txt_function
)))
169 vec_module
[ARG_FUNC_FUNCTION
] =
170 vec_module
[ARG_FUNC_MODULE
] =
171 vec_module
[ARG_FUNC_OFF
] = 0;
172 vec_module
[ARG_FUNC_ON
] = 1;
174 D(bug("About to ReadArgs()..."));
175 if( (ReadArgs(args_function
, vec_function
, rdargs
)))
179 /* ON has precedence */
180 if(vec_function
[ARG_FUNC_ON
] & vec_function
[ARG_FUNC_OFF
])
181 vec_function
[ARG_FUNC_OFF
] = 0;
183 /* Both flags off: ON is default */
184 if(!vec_function
[ARG_FUNC_ON
] & !vec_function
[ARG_FUNC_OFF
])
185 vec_function
[ARG_FUNC_ON
] = 1;
187 D(bug("Found function: \"%ld\" in \"%s\" status \"%s\"\n",
188 *(LONG
*)vec_function
[ARG_FUNC_FUNCTION
],
189 vec_function
[ARG_FUNC_MODULE
],
190 vec_function
[ARG_FUNC_ON
] ? (ULONG
)"on" : (ULONG
)"off"
193 if( *(LONG
*)vec_function
[ARG_FUNC_FUNCTION
] % 6 )
196 Printf("Function offset %ld is not a multiple of -6! Ignoring this function line.\n",
197 *(LONG
*)vec_function
[ARG_FUNC_FUNCTION
]
202 D(bug("Finding correct module..."));
203 if( (modnode
= (struct ModNode
*)FindNameNC(&config
->bc_Modules
,
204 (STRPTR
)vec_function
[ARG_FUNC_MODULE
])))
208 D(bug("Allocating function node..."));
209 if( (funcnode
= AllocVec(sizeof(*funcnode
), MEMF_CLEAR
)))
213 D(bug("Setting function status in function node..."));
214 funcnode
->fn_Slot
= *(LONG
*)vec_function
[ARG_FUNC_FUNCTION
] / -6;
215 funcnode
->fn_Status
=
216 vec_function
[ARG_FUNC_ON
] ? 1 : 0;
219 D(bug("Adding function node to list..."));
220 AddTail(&modnode
->mn_FuncList
, &funcnode
->fn_Node
);
225 ioerr
= ERROR_NO_FREE_STORE
;
232 Printf("Function %ld \"%s\" not in any known module. Ignored.\n",
233 *(LONG
*)vec_function
[ARG_FUNC_FUNCTION
],
234 vec_function
[ARG_FUNC_MODULE
]
244 D(bug(" fail or incomplete parameters\n"));
250 ioerr
= IoErr(); /* will be 0 in case of EOF */
255 D(bug("Closing file \"%s\"...", (ULONG
)file
));
272 D(bug("Freeing linebuffer..."));
273 FreeMem(linebuffer
, MAX_LINE_LEN
);
278 ioerr
= ERROR_NO_FREE_STORE
;
282 D(bug("Freeing RDArgs..."));
283 FreeDosObject(DOS_RDARGS
, rdargs
);
289 ioerr
= ERROR_NO_FREE_STORE
;
295 ioerr
= ERROR_NO_FREE_STORE
;
301 if(!quiet
) PrintFault(ioerr
, "arosboot");
306 if(config
->bc_Modules
.lh_TailPred
== (struct Node
*)&config
->bc_Modules
)
308 /* empty list: no modules */
309 if(!quiet
) Printf("No modules found in config file\n");
314 D(bug("End of config file processing\n"));
318 void FreeConfig(struct BootConfig
*config
)
320 struct ModNode
*modnode
, *modnext
;
321 struct FuncNode
*funcnode
, *funcnext
;
323 D(bug("FreeConfig...\n"));
327 for(modnode
= (struct ModNode
*)config
->bc_Modules
.lh_Head
;
328 modnode
->mn_Node
.ln_Succ
;
331 /* Get the next node here, because after the Remove() it is undefined. */
332 modnext
= (struct ModNode
*)modnode
->mn_Node
.ln_Succ
;
334 for(funcnode
= (struct FuncNode
*)modnode
->mn_FuncList
.lh_Head
;
335 funcnode
->fn_Node
.ln_Succ
;
338 funcnext
= (struct FuncNode
*)funcnode
->fn_Node
.ln_Succ
;
339 D(bug(" Free funcnode\n"));
343 Remove(&modnode
->mn_Node
);
344 if(modnode
->mn_Node
.ln_Name
)
346 D(bug(" Free modname\n"));
347 FreeVec(modnode
->mn_Node
.ln_Name
);
349 D(bug(" Free modnode\n"));
352 D(bug(" Free config\n"));
357 BOOL
isconfigline(char *buffer
, char *keyword
)
359 /* account for indented lines */
360 while(isspace(*buffer
) && *buffer
!= '\n') buffer
++;
363 if(*buffer
== ';') return FALSE
;
365 while(*keyword
&& *buffer
)
367 if(*keyword
!= toupper(*buffer
)) return FALSE
;
375 /* FindName case-insensitive */
376 struct Node
*FindNameNC(struct List
*list
, UBYTE
*name
)
380 /* Look through the list */
381 for (node
=GetHead(list
); node
; node
=GetSucc(node
))
383 /* Only compare the names if this node has one. */
386 /* Check the node. If we found it, stop. */
387 if (!strcasecmp (node
->ln_Name
, name
))
392 * If we found a node, this will contain the pointer to it. If we
393 * didn't, this will be NULL (either because the list was
394 * empty or because we tried all nodes in the list)