(* Aos, Copyright 2001, Pieter Muller, ETH Zurich *) MODULE BootConsole; (** AUTHOR "pjm"; PURPOSE "Boot console"; *) (* Config strings: BootVol# = prefix [hash] [cache] alias [volpar] ["|" fspar]. (* # is "1".."9" *) alias = gen gen . (* defines a volume and file system generator *) gen = mod "." cmd . Examples: BootVol1="AOS AosFS IDE0#2" BootVol2="RAM RamFS 2000 4096" AosFS="DiskVolumes.New DiskFS.NewFS" RamFS="RAMVolumes.New DiskFS.NewFS" RFS="RfsClientProxy.New RfsFS.NewFS" *) IMPORT Machine, Trace, KernelLog, Modules, Streams, Objects, Files, Commands; CONST ModuleName = "Console"; TraceBoot = FALSE; PROCEDURE BootCommand(CONST config: ARRAY OF CHAR; flags: SET); VAR i, j, res: LONGINT; par: ARRAY 32 OF CHAR; s: ARRAY 256 OF CHAR; BEGIN COPY(config, par); i := 0; j := 0; WHILE par[j] # 0X DO INC(j) END; LOOP Machine.GetConfig(par, s); IF s # "" THEN IF TraceBoot THEN Trace.String("Bootconsole:Commands.Call: "); Trace.String(s); Trace.Ln END; Commands.Call(s, flags, res, s); IF (res # Commands.Ok) THEN KernelLog.Enter; KernelLog.String(s); KernelLog.Exit END END; INC(i); IF i = 10 THEN EXIT END; par[j] := CHR(ORD("0") + i); par[j+1] := 0X END END BootCommand; PROCEDURE GetString(VAR i: LONGINT; CONST r : ARRAY OF CHAR; VAR s: ARRAY OF CHAR): BOOLEAN; VAR j: LONGINT; BEGIN WHILE r[i] = " " DO INC(i) END; j := 0; WHILE r[i] > " " DO s[j] := r[i]; INC(j); INC(i) END; s[j] := 0X; IF TraceBoot THEN Trace.String("GetString: "); Trace.String(s); Trace.Ln END; RETURN j # 0 END GetString; PROCEDURE Error(CONST config, val: ARRAY OF CHAR; i: LONGINT); VAR j: LONGINT; s: ARRAY 32 OF CHAR; BEGIN s := "BootConsole: Bad "; KernelLog.String(s); j := 0; WHILE s[j] # 0X DO INC(j) END; INC(i, j); KernelLog.String(config); j := 0; WHILE config[j] # 0X DO INC(j) END; INC(i, j); KernelLog.Char("="); KernelLog.Char(22X); INC(i, 2); KernelLog.String(val); KernelLog.Char(22X); KernelLog.Ln; WHILE i > 0 DO KernelLog.Char(" "); DEC(i) END; KernelLog.Char("^"); KernelLog.Ln END Error; PROCEDURE Generate(CONST name: ARRAY OF CHAR; par: Files.Parameters): BOOLEAN; VAR factory : Files.FileSystemFactory; res: WORD; msg: ARRAY 256 OF CHAR; moduleName, procedureName : Modules.Name; BEGIN Commands.Split(name, moduleName, procedureName, res, msg); IF (res = Commands.Ok) THEN GETPROCEDURE(moduleName, procedureName, factory); IF (factory # NIL) THEN factory(par); RETURN TRUE; ELSE KernelLog.String(ModuleName); KernelLog.String(": File system alias unknown"); KernelLog.Ln; END; ELSE KernelLog.String(ModuleName); KernelLog.String(": "); KernelLog.String(msg); KernelLog.Ln; END; RETURN FALSE; END Generate; PROCEDURE OpenVolume(CONST config: ARRAY OF CHAR); VAR i, j, k: LONGINT; parvol, parfs: Files.Parameters; volReady : BOOLEAN; prefix, alias: Files.Prefix; gen: ARRAY 64 OF CHAR; s: ARRAY 256 OF CHAR; argVol, argFs : Streams.StringReader; BEGIN Machine.GetConfig(config, s); (* s = prefix alias [volpar] ["|" fspar] . *) IF s = "" THEN RETURN END; i := 0; IF ~GetString(i, s, prefix) THEN Error(config, s, i); RETURN END; IF ~GetString(i, s, alias) THEN Error(config, s, i); RETURN END; (* generate volume generator parameter *) IF s[i] = " " THEN INC(i) END; j := 0; WHILE (s[i] # 0X) & (s[i] # "|") DO s[j] := s[i]; INC(i); INC(j) END; IF s[i] = "|" THEN INC(i) END; s[j] := 0X; NEW(argVol, j+1); argVol.SetRaw(s, 0, j+1); NEW(parvol, NIL, argVol, NIL, NIL, NIL); (* generate file system generator parameter *) j := 0; WHILE s[i] # 0X DO s[j] := s[i]; INC(i); INC(j) END; s[j] := 0X; NEW(argFs, j+1); argFs.SetRaw(s, 0, j+1); NEW(parfs, NIL, argFs, NIL, NIL, NIL); (* call volume generator *) Machine.GetConfig(alias, s); (* s = gen gen . ; gen = mod "." cmd . *) k := 0; IF ~GetString(k, s, gen) THEN Error(alias, s, k); RETURN END; (* call volume generator *) volReady := FALSE; IF gen = "NIL" THEN volReady := TRUE ELSE IF Generate(gen, parvol) & (parvol.vol # NIL) THEN INCL(parvol.vol.flags, Files.Boot); parfs.vol := parvol.vol; volReady := TRUE END END; IF volReady THEN COPY(prefix, parfs.prefix); (* call file system generator *) IF GetString(k, s, gen) THEN IF Generate(gen, parfs) THEN parvol.vol := NIL END ELSE Error(alias, s, k) END END; IF Files.This(prefix) = NIL THEN KernelLog.String("BootConsole: Mount failed on "); KernelLog.String(config); KernelLog.Ln; IF parvol.vol # NIL THEN parvol.vol.Finalize() (* unmount volume *) END END; parfs.out.Update; parfs.error.Update; parvol.out.Update; parvol.error.Update; END OpenVolume; PROCEDURE OpenVolumes; VAR config: ARRAY 16 OF CHAR; i: LONGINT; BEGIN config := "BootVol#"; FOR i := 1 TO 9 DO config[7] := CHR(ORD("0") + i); config[8] := 0X; OpenVolume(config) END END OpenVolumes; BEGIN OpenVolumes; BootCommand("Boot", {Commands.Wait}); BootCommand("BootSystem", {}); Objects.Terminate(); END BootConsole.