2
0

BIOS.BootShell.Mod 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. MODULE BootShell; (** AUTHOR "staubesv"; PURPOSE "Simple VGA text mode shell"; *)
  2. IMPORT
  3. SYSTEM, KernelLog, Machine, Modules, Streams, Commands, Inputs, Strings, Locks;
  4. CONST
  5. Version = "A2 Bootshell v1.0";
  6. LineWidth = 80; TraceHeight = 25;
  7. TraceBase = 0B8000H; (* default screen buffer *)
  8. BufferHeight = 2048; (* lines *)
  9. BufferSize = BufferHeight * LineWidth; (* characters *)
  10. TAB = 09X;
  11. CR = 0DX;
  12. LF = 0AX;
  13. SPACE = " ";
  14. Mode_Insert = 0;
  15. Mode_Overwrite = 1;
  16. Black = 0;
  17. Blue = 1;
  18. Green = 2;
  19. Cyan = 3;
  20. Red = 4;
  21. Magenta = 5;
  22. Brown = 6;
  23. White = 7;
  24. Gray = 8;
  25. LightBlue = 9;
  26. LightGreen = 10;
  27. LightCyan = 11;
  28. LightRed = 12;
  29. LightMagenta = 13;
  30. Yellow = 14;
  31. BrightWhite = 15;
  32. TYPE
  33. (* Copied from Shell.mod *)
  34. CommandsString = POINTER TO RECORD
  35. prev, next: CommandsString;
  36. string: Strings.String;
  37. END;
  38. CommandHistoryObject = OBJECT
  39. VAR
  40. first, current: CommandsString;
  41. PROCEDURE GetNextCommand() : Strings.String;
  42. VAR string : Strings.String;
  43. BEGIN
  44. IF first # NIL THEN
  45. IF current = NIL THEN current := first ELSE current := current.next END;
  46. string := current.string;
  47. ELSE
  48. string := NIL;
  49. END;
  50. RETURN string;
  51. END GetNextCommand;
  52. PROCEDURE GetPreviousCommand() : Strings.String;
  53. VAR string : Strings.String;
  54. BEGIN
  55. IF first # NIL THEN
  56. IF current = NIL THEN current := first.prev ELSE current := current.prev END;
  57. string := current.string;
  58. ELSE
  59. string := NIL;
  60. END;
  61. RETURN string;
  62. END GetPreviousCommand;
  63. PROCEDURE AddCommand(string : Strings.String);
  64. VAR command: CommandsString;
  65. BEGIN
  66. ASSERT((string # NIL) & (string^ # ""));
  67. command := first;
  68. IF command # NIL THEN
  69. WHILE (command.string^ # string^) & (command.next # first) DO command := command.next END;
  70. IF command.string^ # string^ THEN command := NIL END
  71. END;
  72. IF command # NIL THEN
  73. IF first = command THEN first := command.next END;
  74. command.prev.next := command.next;
  75. command.next.prev := command.prev;
  76. ELSE
  77. NEW (command);
  78. command.string := string;
  79. END;
  80. IF first = NIL THEN
  81. first := command; first.next := first; first.prev := first
  82. ELSE
  83. command.prev := first.prev; command.next := first;
  84. first.prev.next := command; first.prev := command;
  85. END;
  86. current := NIL;
  87. END AddCommand;
  88. PROCEDURE &Init*;
  89. BEGIN first := NIL; current := NIL;
  90. END Init;
  91. END CommandHistoryObject;
  92. TYPE
  93. Character = RECORD
  94. ch : CHAR;
  95. color : SHORTINT;
  96. END;
  97. Line = ARRAY LineWidth OF Character;
  98. TextBuffer = OBJECT
  99. VAR
  100. defaultColor : SHORTINT;
  101. currentColor : SHORTINT;
  102. (* ring buffer of lines *)
  103. lines : ARRAY BufferHeight OF Line;
  104. (* index of first line in ring buffer *)
  105. firstLine, lastLine : LONGINT;
  106. (* index of line currently shown on top of the display *)
  107. firstLineShown : LONGINT;
  108. (* start and end of currently edited text *)
  109. editStartPosition, editEndPosition : LONGINT;
  110. (* character position of cursor *)
  111. cursorPosition : LONGINT;
  112. mode : LONGINT;
  113. lock : Locks.RecursiveLock;
  114. PROCEDURE &Init*;
  115. BEGIN
  116. mode := Mode_Insert;
  117. NEW(lock);
  118. lock.Acquire;
  119. Clear;
  120. lock.Release;
  121. END Init;
  122. PROCEDURE Clear;
  123. VAR i : LONGINT;
  124. BEGIN
  125. ASSERT(lock.HasLock());
  126. firstLine := 0; lastLine := 0;
  127. firstLineShown := 0;
  128. cursorPosition := 0;
  129. editStartPosition := 0; editEndPosition := 0;
  130. SetColor(White, Black);
  131. defaultColor := White + 10H * Black;
  132. FOR i := 0 TO LEN(lines)-1 DO
  133. ClearLine(lines[i], 0, LineWidth-1, defaultColor);
  134. END;
  135. Invalidate(SELF);
  136. END Clear;
  137. PROCEDURE SetColor(foreground, background : SHORTINT);
  138. BEGIN
  139. currentColor := foreground + 10H * background;
  140. END SetColor;
  141. PROCEDURE SetEditStart;
  142. BEGIN
  143. editStartPosition := cursorPosition;
  144. editEndPosition := cursorPosition;
  145. END SetEditStart;
  146. PROCEDURE Send( CONST data: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  147. VAR i : LONGINT;
  148. BEGIN
  149. lock.Acquire;
  150. FOR i := ofs TO ofs + len - 1 DO
  151. CharInternal(data[i]);
  152. END;
  153. CheckVisibility;
  154. Invalidate(SELF);
  155. lock.Release;
  156. res := Streams.Ok;
  157. END Send;
  158. PROCEDURE String(CONST string : ARRAY OF CHAR);
  159. VAR i : LONGINT;
  160. BEGIN
  161. lock.Acquire;
  162. i := 0;
  163. WHILE (i < LEN(string)) & (string[i] # 0X) DO
  164. CharInternal(string[i]);
  165. INC(i);
  166. END;
  167. CheckVisibility;
  168. Invalidate(SELF);
  169. lock.Release;
  170. END String;
  171. PROCEDURE Char(ch : CHAR);
  172. BEGIN
  173. lock.Acquire;
  174. CharInternal(ch);
  175. CheckVisibility;
  176. Invalidate(SELF);
  177. lock.Release;
  178. END Char;
  179. PROCEDURE CheckVisibility;
  180. BEGIN
  181. ASSERT(lock.HasLock());
  182. IF (Difference(lastLine, firstLineShown, LEN(lines)) > TraceHeight - 1) THEN
  183. firstLineShown := Subtract(lastLine, TraceHeight - 1, LEN(lines));
  184. Invalidate(SELF);
  185. END;
  186. END CheckVisibility;
  187. PROCEDURE NextLine;
  188. BEGIN
  189. ASSERT(lock.HasLock());
  190. lastLine := Add(lastLine, 1, BufferHeight);
  191. ClearLine(lines[lastLine], 0, LineWidth-1, defaultColor);
  192. IF (lastLine = firstLine) THEN
  193. firstLine := Add(firstLine, 1, BufferHeight);
  194. IF (firstLineShown = lastLine) THEN
  195. firstLineShown := firstLine;
  196. END;
  197. END;
  198. END NextLine;
  199. PROCEDURE MoveCharactersToRight;
  200. VAR current, previous : LONGINT;
  201. BEGIN
  202. ASSERT(editStartPosition # editEndPosition);
  203. IF (editEndPosition = LineWidth-1) THEN (* reserve new line in advance *)
  204. NextLine;
  205. END;
  206. editEndPosition := Add(editEndPosition, 1, BufferSize);
  207. current := editEndPosition;
  208. WHILE (current # cursorPosition) DO
  209. previous := Subtract(current, 1, BufferSize);
  210. lines[current DIV LineWidth][current MOD LineWidth] := lines[previous DIV LineWidth][previous MOD LineWidth];
  211. current := previous;
  212. END;
  213. END MoveCharactersToRight;
  214. PROCEDURE MoveCharactersToLeft;
  215. VAR current, next : LONGINT;
  216. BEGIN
  217. ASSERT(editStartPosition # editEndPosition);
  218. IF (editEndPosition = 0) THEN (* line will be removed *)
  219. lastLine := Subtract(lastLine, 1, LEN(lines));
  220. END;
  221. current := cursorPosition;
  222. REPEAT
  223. next := Add(current, 1, BufferSize);
  224. lines[current DIV LineWidth][current MOD LineWidth] := lines[next DIV LineWidth][next MOD LineWidth];
  225. current := next;
  226. UNTIL (next = editEndPosition);
  227. editEndPosition := Subtract(editEndPosition, 1, BufferSize);
  228. END MoveCharactersToLeft;
  229. PROCEDURE CharInternal(ch : CHAR);
  230. VAR index : LONGINT;
  231. BEGIN
  232. ASSERT(lock.HasLock());
  233. IF (ch = CR) THEN (* ignore *)
  234. ELSIF (ch = LF) THEN
  235. ClearLine(lines[cursorPosition DIV LineWidth], cursorPosition MOD LineWidth, LineWidth-1, currentColor);
  236. NextLine;
  237. cursorPosition := Add(cursorPosition, LineWidth - (cursorPosition MOD LineWidth), BufferSize);
  238. editEndPosition := cursorPosition;
  239. ELSIF (SPACE <= ch) & (ORD(ch) < 128) THEN
  240. index := cursorPosition DIV LineWidth;
  241. IF (cursorPosition = editEndPosition) THEN (* append *)
  242. ASSERT(index = lastLine);
  243. lines[index][cursorPosition MOD LineWidth].ch := ch;
  244. lines[index][cursorPosition MOD LineWidth].color := currentColor;
  245. cursorPosition := Add(cursorPosition, 1, BufferSize);
  246. editEndPosition := cursorPosition;
  247. IF (cursorPosition DIV LineWidth # index) THEN
  248. NextLine;
  249. END;
  250. ELSE
  251. IF (mode # Mode_Overwrite) THEN
  252. MoveCharactersToRight;
  253. END;
  254. lines[index][cursorPosition MOD LineWidth].ch := ch;
  255. lines[index][cursorPosition MOD LineWidth].color := currentColor;
  256. cursorPosition := Add(cursorPosition, 1, BufferSize);
  257. END;
  258. END;
  259. END CharInternal;
  260. PROCEDURE DeleteCurrentLine;
  261. VAR i : LONGINT;
  262. BEGIN
  263. lock.Acquire;
  264. i := editStartPosition;
  265. LOOP
  266. lines[i DIV LineWidth][i MOD LineWidth].ch := SPACE;
  267. IF (i = editEndPosition) THEN EXIT; END;
  268. INC(i);
  269. END;
  270. cursorPosition := editStartPosition;
  271. editEndPosition := editStartPosition;
  272. lastLine := editStartPosition DIV LineWidth;
  273. lock.Release;
  274. END DeleteCurrentLine;
  275. PROCEDURE GetCurrentLine() : Strings.String;
  276. VAR string : Strings.String; i, length : LONGINT;
  277. BEGIN
  278. lock.Acquire;
  279. length := Difference(editEndPosition, editStartPosition, BufferSize);
  280. NEW(string, length + 1);
  281. i := 0;
  282. WHILE (i < length - 1) DO
  283. string[i] := lines[(editStartPosition + i) DIV LineWidth][(editStartPosition + i) MOD LineWidth].ch;
  284. INC(i);
  285. END;
  286. string[length-1] := 0X;
  287. lock.Release;
  288. RETURN string;
  289. END GetCurrentLine;
  290. PROCEDURE Home;
  291. BEGIN
  292. lock.Acquire;
  293. IF (cursorPosition # editStartPosition) THEN
  294. cursorPosition := editStartPosition;
  295. Invalidate(SELF);
  296. END;
  297. lock.Release;
  298. END Home;
  299. PROCEDURE End;
  300. BEGIN
  301. lock.Acquire;
  302. IF (cursorPosition # editEndPosition) THEN
  303. cursorPosition := editEndPosition;
  304. Invalidate(SELF);
  305. END;
  306. lock.Release;
  307. END End;
  308. PROCEDURE Backspace;
  309. BEGIN
  310. lock.Acquire;
  311. IF (cursorPosition # editStartPosition) THEN
  312. cursorPosition := Subtract(cursorPosition, 1, BufferSize);
  313. MoveCharactersToLeft;
  314. Invalidate(SELF);
  315. END;
  316. lock.Release;
  317. END Backspace;
  318. PROCEDURE Delete;
  319. BEGIN
  320. lock.Acquire;
  321. IF (cursorPosition # editEndPosition) THEN
  322. MoveCharactersToLeft;
  323. Invalidate(SELF);
  324. END;
  325. lock.Release;
  326. END Delete;
  327. PROCEDURE ScrollUp(nofLines : LONGINT);
  328. VAR d : LONGINT;
  329. BEGIN
  330. lock.Acquire;
  331. d := Difference(firstLineShown, firstLine, LEN(lines));
  332. nofLines := Min(nofLines, d - 1);
  333. IF (nofLines > 0) THEN
  334. firstLineShown := Subtract(firstLineShown, nofLines, LEN(lines));
  335. END;
  336. Invalidate(SELF);
  337. lock.Release;
  338. END ScrollUp;
  339. PROCEDURE ScrollDown(nofLines : LONGINT);
  340. VAR d : LONGINT;
  341. BEGIN
  342. lock.Acquire;
  343. d := Difference(lastLine, firstLineShown, LEN(lines));
  344. nofLines := Min(nofLines, d - 1);
  345. IF (nofLines > 0) THEN
  346. firstLineShown := Add(firstLineShown, nofLines, LEN(lines));
  347. END;
  348. Invalidate(SELF);
  349. lock.Release;
  350. END ScrollDown;
  351. PROCEDURE CursorLeft;
  352. VAR oldCursorPosition : LONGINT;
  353. BEGIN
  354. lock.Acquire;
  355. IF (cursorPosition # editStartPosition) THEN
  356. oldCursorPosition := cursorPosition;
  357. cursorPosition := Subtract(cursorPosition, 1, BufferSize);
  358. Invalidate(SELF);
  359. END;
  360. lock.Release;
  361. END CursorLeft;
  362. PROCEDURE CursorRight;
  363. VAR oldCursorPosition : LONGINT;
  364. BEGIN
  365. lock.Acquire;
  366. IF (cursorPosition # editEndPosition) THEN
  367. oldCursorPosition := cursorPosition;
  368. cursorPosition := Add(cursorPosition, 1, BufferSize);
  369. Invalidate(SELF);
  370. END;
  371. lock.Release;
  372. END CursorRight;
  373. PROCEDURE Dump(out : Streams.Writer);
  374. VAR i, j : LONGINT;
  375. BEGIN
  376. ASSERT(out # NIL);
  377. lock.Acquire;
  378. out.String("firstLine = "); out.Int(firstLine, 0); out.String(", lastLine = "); out.Int(lastLine, 0); out.Ln;
  379. out.String("firstLineShown = "); out.Int(firstLineShown, 0); out.Ln;
  380. out.String("cursorPosition = "); out.Int(cursorPosition, 0); out.Ln;
  381. out.String("editStartPosition = "); out.Int(editStartPosition, 0); out.String(", editEndPosition = "); out.Int(editEndPosition, 0); out.Ln;
  382. i := firstLine;
  383. LOOP
  384. FOR j := 0 TO LineWidth-1 DO
  385. out.Char(lines[i MOD LEN(lines)][j].ch);
  386. END;
  387. out.Ln;
  388. IF (i = lastLine) THEN EXIT; END;
  389. INC(i);
  390. END;
  391. out.Ln;
  392. lock.Release;
  393. END Dump;
  394. END TextBuffer;
  395. TYPE
  396. Shell = OBJECT(Inputs.Sink)
  397. VAR
  398. textBuffer : TextBuffer;
  399. history : CommandHistoryObject;
  400. PROCEDURE &Init;
  401. BEGIN
  402. NEW(textBuffer);
  403. textBuffer.lock.Acquire;
  404. textBuffer.SetColor(Yellow, Black);
  405. textBuffer.String(Version);
  406. textBuffer.Char(LF);
  407. Prompt;
  408. textBuffer.SetEditStart;
  409. textBuffer.lock.Release;
  410. NEW(history);
  411. Inputs.keyboard.Register(SELF);
  412. END Init;
  413. PROCEDURE Handle*(VAR msg: Inputs.Message);
  414. BEGIN
  415. IF (msg IS Inputs.KeyboardMsg) & (msg(Inputs.KeyboardMsg).flags * {Inputs.Release} = {}) THEN
  416. WITH msg:Inputs.KeyboardMsg DO
  417. IF (msg.keysym = Inputs.KsPageUp) THEN
  418. IF (msg.flags * Inputs.Shift # {}) THEN textBuffer.ScrollUp(1); ELSE textBuffer.ScrollUp(TraceHeight); END;
  419. ELSIF (msg.keysym = Inputs.KsPageDown) THEN
  420. IF (msg.flags * Inputs.Shift # {}) THEN textBuffer.ScrollDown(1); ELSE textBuffer.ScrollDown(TraceHeight); END;
  421. ELSIF (msg.keysym = Inputs.KsLeft) THEN
  422. textBuffer.CursorLeft;
  423. ELSIF (msg.keysym = Inputs.KsRight) THEN
  424. textBuffer.CursorRight;
  425. ELSIF (msg.keysym = Inputs.KsUp) THEN
  426. CommandHistory(FALSE);
  427. ELSIF (msg.keysym = Inputs.KsDown) THEN
  428. CommandHistory(TRUE);
  429. ELSIF (msg.keysym = Inputs.KsHome) THEN
  430. textBuffer.Home;
  431. ELSIF (msg.keysym = Inputs.KsEnd) THEN
  432. textBuffer.End;
  433. ELSIF (msg.keysym = Inputs.KsDelete) THEN
  434. textBuffer.Delete;
  435. ELSIF (msg.keysym = Inputs.KsBackSpace) THEN
  436. textBuffer.Backspace;
  437. ELSIF (msg.keysym = Inputs.KsReturn) THEN
  438. textBuffer.lock.Acquire;
  439. textBuffer.cursorPosition := textBuffer.editEndPosition;
  440. textBuffer.Char(LF);
  441. textBuffer.lock.Release;
  442. Execute;
  443. textBuffer.lock.Acquire;
  444. textBuffer.Char(LF);
  445. Prompt;
  446. textBuffer.SetEditStart;
  447. textBuffer.lock.Release;
  448. ELSIF (msg.ch = LF) OR ((SPACE <= msg.ch) & (ORD(msg.ch) < 128)) THEN
  449. textBuffer.Char(msg.ch);
  450. END;
  451. END;
  452. END;
  453. END Handle;
  454. PROCEDURE CommandHistory(next : BOOLEAN);
  455. VAR string : Strings.String;
  456. BEGIN
  457. textBuffer.lock.Acquire;
  458. IF next THEN
  459. string := history.GetNextCommand();
  460. ELSE
  461. string := history.GetPreviousCommand();
  462. END;
  463. IF (string # NIL) THEN
  464. textBuffer.DeleteCurrentLine;
  465. textBuffer.String(string^);
  466. END;
  467. textBuffer.lock.Release;
  468. END CommandHistory;
  469. PROCEDURE Prompt;
  470. BEGIN
  471. textBuffer.SetColor(LightBlue, Black);
  472. textBuffer.String("A2>");
  473. textBuffer.SetColor(White, Black);
  474. END Prompt;
  475. PROCEDURE Execute;
  476. VAR
  477. context : Commands.Context; writer : Streams.Writer; arg : Streams.StringReader;
  478. commandLine : Strings.String;
  479. nbr : ARRAY 8 OF CHAR;
  480. msg, command : ARRAY 128 OF CHAR;
  481. i, length, res : LONGINT;
  482. BEGIN
  483. commandLine := textBuffer.GetCurrentLine();
  484. Strings.TrimWS(commandLine^);
  485. IF (commandLine^ # "") THEN
  486. history.AddCommand(commandLine);
  487. END;
  488. length := Strings.Length(commandLine^);
  489. i := 0;
  490. WHILE (i < length) & ~IsWhitespace(commandLine[i]) & (i < LEN(command) - 1) DO
  491. command[i] := commandLine[i];
  492. INC(i);
  493. END;
  494. command[i] := 0X;
  495. IF (command = "exit") THEN
  496. Close;
  497. ELSIF (command = "clear") THEN
  498. textBuffer.lock.Acquire;
  499. textBuffer.Clear;
  500. textBuffer.lock.Release;
  501. ELSIF (command = "version") THEN
  502. textBuffer.lock.Acquire;
  503. textBuffer.String(Version);
  504. textBuffer.lock.Release;
  505. ELSIF (command = "") THEN
  506. (* ignore *)
  507. ELSE
  508. IF (i < length) THEN
  509. NEW(arg, length - i);
  510. arg.SetRaw(commandLine^, i, length - i);
  511. ELSE
  512. NEW(arg, 1); arg.Set("");
  513. END;
  514. NEW(writer, textBuffer.Send, 256);
  515. NEW(context, NIL, arg, writer, writer, SELF);
  516. Commands.Activate(command, context, {Commands.Wait}, res, msg);
  517. context.out.Update; context.error.Update;
  518. IF (res # Commands.Ok) THEN
  519. textBuffer.lock.Acquire;
  520. textBuffer.SetColor(Red, Black);
  521. textBuffer.String("Command execution error, res = ");
  522. Strings.IntToStr(res, nbr);
  523. textBuffer.String(nbr);
  524. textBuffer.String(" ("); textBuffer.String(msg); textBuffer.String(")");
  525. textBuffer.Char(LF);
  526. textBuffer.SetColor(White, Black);
  527. textBuffer.lock.Release;
  528. END;
  529. END;
  530. END Execute;
  531. PROCEDURE Quit;
  532. BEGIN
  533. Inputs.keyboard.Unregister(SELF);
  534. END Quit;
  535. END Shell;
  536. VAR
  537. shell : Shell;
  538. PROCEDURE Subtract(position, value, bufferSize : LONGINT) : LONGINT;
  539. VAR result : LONGINT;
  540. BEGIN
  541. ASSERT((0 <= position) & (position < bufferSize));
  542. value := value MOD bufferSize;
  543. IF (position - value >= 0) THEN result := position - value;
  544. ELSE result := bufferSize - 1 - (value - position);
  545. END;
  546. ASSERT((0 <= result) & (result < bufferSize));
  547. RETURN result;
  548. END Subtract;
  549. PROCEDURE Add(position, value, bufferSize : LONGINT) : LONGINT;
  550. VAR result : LONGINT;
  551. BEGIN
  552. ASSERT((0 <= position) & (position < bufferSize));
  553. result := (position + value) MOD bufferSize;
  554. ASSERT((0 <= result) & (result < bufferSize));
  555. RETURN result;
  556. END Add;
  557. PROCEDURE Difference(end, start, bufferSize : LONGINT) : LONGINT;
  558. VAR result : LONGINT;
  559. BEGIN
  560. IF (end >= start) THEN
  561. result := end - start + 1;
  562. ELSE
  563. result := (end + 1) + (bufferSize - start + 1);
  564. END;
  565. RETURN result;
  566. END Difference;
  567. PROCEDURE ClearLine(VAR line : Line; from, to : LONGINT; color : SHORTINT);
  568. VAR i : LONGINT;
  569. BEGIN
  570. ASSERT((0 <= from) & (from < LineWidth));
  571. ASSERT((0 <= to) & (to < LineWidth));
  572. FOR i := from TO to DO
  573. line[i].ch := SPACE;
  574. line[i].color := color;
  575. END;
  576. END ClearLine;
  577. PROCEDURE IsWhitespace(ch : CHAR) : BOOLEAN;
  578. BEGIN
  579. RETURN (ch = SPACE) OR (ch = TAB) OR (ch = CR) OR (ch = LF);
  580. END IsWhitespace;
  581. PROCEDURE Min(a, b : LONGINT) : LONGINT;
  582. BEGIN
  583. IF (a <= b) THEN RETURN a; ELSE RETURN b; END;
  584. END Min;
  585. PROCEDURE Invalidate(textBuffer : TextBuffer);
  586. VAR offset, index, i, nofLines : LONGINT; line : Line; character : Character; ch : CHAR;
  587. BEGIN
  588. ASSERT(textBuffer # NIL);
  589. ASSERT(textBuffer.lock.HasLock());
  590. offset := 0;
  591. nofLines := 1;
  592. index := textBuffer.firstLineShown;
  593. LOOP
  594. line := textBuffer.lines[index MOD LEN(textBuffer.lines)];
  595. FOR i := 0 TO LineWidth-1 DO
  596. character := line[i];
  597. IF (character.ch = TAB) THEN ch := SPACE; ELSE ch := character.ch; END;
  598. SYSTEM.PUT16(TraceBase + offset, ORD(ch) + 100H * character.color);
  599. INC(offset, 2);
  600. END;
  601. IF (index = textBuffer.lastLine) OR (nofLines = TraceHeight) THEN EXIT; END;
  602. INC(index);
  603. INC(nofLines);
  604. END;
  605. WHILE (nofLines < TraceHeight) DO
  606. FOR i := 0 TO LineWidth-1 DO
  607. SYSTEM.PUT16(TraceBase + offset, ORD(SPACE));
  608. INC(offset, 2);
  609. END;
  610. INC(nofLines);
  611. END;
  612. UpdateCursor(textBuffer);
  613. END Invalidate;
  614. PROCEDURE Open*;
  615. BEGIN {EXCLUSIVE}
  616. IF (shell = NIL) THEN
  617. KernelLog.String("BootShell: Starting shell..."); KernelLog.Ln;
  618. NEW(shell);
  619. END;
  620. END Open;
  621. PROCEDURE Close*;
  622. BEGIN {EXCLUSIVE}
  623. IF (shell # NIL) THEN
  624. shell.Quit;
  625. shell := NIL;
  626. END;
  627. END Close;
  628. PROCEDURE Dump*(context : Commands.Context);
  629. BEGIN {EXCLUSIVE}
  630. IF (shell # NIL) THEN
  631. shell.textBuffer.Dump(context.out);
  632. ELSE
  633. context.out.String("BootShell not started."); context.out.Ln;
  634. END;
  635. END Dump;
  636. PROCEDURE UpdateCursor(textBuffer : TextBuffer);
  637. VAR cursorLocation : LONGINT;
  638. BEGIN
  639. ASSERT(textBuffer # NIL);
  640. ASSERT(textBuffer.lock.HasLock());
  641. cursorLocation := Subtract(textBuffer.cursorPosition, textBuffer.firstLineShown * LineWidth, BufferSize);
  642. Machine.Portout8(3D4H, 0EX); (* Select cursor location high register *)
  643. Machine.Portout8(3D5H, CHR(cursorLocation DIV 100H));
  644. Machine.Portout8(3D4H, 0FX); (* Select cursor location low register *)
  645. Machine.Portout8(3D5H, CHR(cursorLocation MOD 100H));
  646. END UpdateCursor;
  647. PROCEDURE Cleanup;
  648. BEGIN
  649. Close;
  650. END Cleanup;
  651. PROCEDURE Init;
  652. VAR value : ARRAY 32 OF CHAR;
  653. BEGIN
  654. Machine.GetConfig("Diagnosis", value);
  655. Strings.TrimWS(value);
  656. IF (value = "1") THEN
  657. Open;
  658. BEGIN {EXCLUSIVE} AWAIT(shell = NIL); END;
  659. END;
  660. END Init;
  661. BEGIN
  662. Modules.InstallTermHandler(Cleanup);
  663. Init;
  664. END BootShell.
  665. SystemTools.DoCommands
  666. Linker.Link \P../Test/ \.Obx ../Test/IDE.Bin 0100000H 1000H Kernel Traps
  667. ATADisks DiskVolumes DiskFS Keyboard BootShell BootConsole ~
  668. VirtualDisks.Install VM0 E:/Private/A2/WinAos/VM/Old-f001.vmdk ~
  669. Partitions.UpdateBootFile VM0#1 ../Test/IDE.Bin ~
  670. VirtualDisks.Uninstall VM0 ~
  671. ~~~
  672. SystemTools.DoCommands
  673. FSTools.DeleteFiles BootShell.img ~
  674. VirtualDisks.Create BootShell.img 2048 512 ~
  675. VirtualDisks.Install -c=80 -h=2 -s=18 -b=512 VDISK0 BootShell.img ~
  676. Linker.Link \P../Test/ \.Obx ../Test/CD.Bin 0100000H 1000H Kernel Traps ProcessInfo SystemTools Keyboard BootShell BootConsole ~
  677. Partitions.Format VDISK0#0 AosFS 640 ../Test/CD.Bin ~
  678. Partitions.SetConfig VDISK0#0
  679. TraceMode="4" TracePort="1" TraceBPS="115200"
  680. ExtMemSize="64"
  681. MaxProcs="-1"
  682. Diagnosis="1"
  683. ~
  684. VirtualDisks.Uninstall VDISK0 ~
  685. IsoImages.Make A2Diagnosis.iso BootShell.img ~
  686. ~~