|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.2 root 7: // LUNA88K の ROM エミュレーション
8:
9: // IODevice
10: // |
1.1.1.5 root 11: // +----------+---------------------+
12: // v v
13: // ROMDevice LunaPROMEmuDeivce (ROM エミュレーションの共通部分)
14: // | |
15: // | +------------+----------------+
16: // v v v
17: // PROMDevice Luna1PROMEmuDevice Luna88kPROMEmuDevice
18: // (実ROM) (LUNA-I エミュレーション) (LUNA88K エミュレーション)
1.1.1.2 root 19:
20: #include "romemu_luna88k.h"
1.1.1.5 root 21: #include "iodevstream.h"
1.1.1.7 ! root 22: #include "lunafb.h"
1.1 root 23: #include "mainapp.h"
24: #include "memorystream.h"
1.1.1.7 ! root 25: #include "mk48t02.h"
1.1.1.5 root 26: #include "pio.h"
1.1 root 27: #include "ram.h"
1.1.1.5 root 28: #include "sysctlr.h"
1.1 root 29:
30: // コンストラクタ
31: Luna88kPROMEmuDevice::Luna88kPROMEmuDevice()
32: {
33: devaddr = baseaddr;
1.1.1.5 root 34:
35: // ROM の特定アドレスを読み出す人がいるかも知れないので、
36: // サイズは実 ROM と同じにしておく。LUNA-I からの類推。
1.1.1.2 root 37: devlen = 256 * 1024;
1.1.1.5 root 38: romdata.reset(new uint8 [devlen]);
1.1.1.2 root 39:
1.1.1.5 root 40: // プロンプトを初期化。
1.1.1.7 ! root 41: prompt = default_prompt;
1.1 root 42: }
43:
44: // デストラクタ
45: Luna88kPROMEmuDevice::~Luna88kPROMEmuDevice()
46: {
47: }
48:
49: bool
50: Luna88kPROMEmuDevice::Init()
51: {
1.1.1.5 root 52: // 親クラス
53: if (inherited::Init() == false) {
54: return false;
55: }
56:
1.1.1.2 root 57: MemoryStreamBE ms(romdata.get());
1.1 root 58:
1.1.1.6 root 59: // リセット時のブートページには ROM (これ) が見えている。
60: // ROMIO_INIT へのアクセスでブートページを RAM に切り替えて、同時に RAM の
61: // 0番地付近のベクタも作り直す。そのため、ここのベクタ1 以降 ($41000008〜)
62: // をベクタとして参照することはないので、ベクタ0 の命令列がそのまま使い潰
63: // してよい。というか2ワードでは 0番地から ROM まで飛べないので使わないと
64: // 面倒くさい。一体どういう設計してんだ…。
65:
66: // ; _ROM_START へジャンプ (ここは0番地)
67: ms.Write32(0x5cc04100); // or.u r6, r0, #0x4100
68: ms.Write32(0x58c6000c); // or r6, r6, #0x000c
69: ms.Write32(0xf400c006); // jmp r6
1.1.1.5 root 70:
1.1.1.6 root 71: // _ROM_START: (ここは ROM)
1.1.1.5 root 72: // ; 元の PSR を r10 に保存しつつ
73: // ; 割り込み許可
74: ms.Write32(0x81404020); // ldcr r10, psr
75: ms.Write32(0xf04a8040); // clr r2, r10, 2<1> ; IND,SFRZ
76: ms.Write32(0x80028022); // stcr r2, psr
77: // ; r3 <- ROMIO_BASE
78: ms.Write32(0x5c600000 | // or.u r3, r0, #ROMIO_BASE.Hi
79: (ROMIO_BASE >> 16)); //
80: ms.Write32(0x58630000 | // or r3, r0, #ROMIO_BASE.Lo
81: (ROMIO_BASE & 0xffff)); //
82: // ; ROMIO_INIT を読み出す
83: ms.Write32(0x14430000); // ld r2, r3, #+INIT
84: // ; 起動先があれば GO
85: ms.Write32(0xe9a20005); // bcnd ne0, r2, _go
86: // _prompt:
87: // ; 疑似 STOP でキー入力を待つ
88: ms.Write32(0xc8000001); // bsr _stop
89: // ; この時点で r1 = _stop
90: // _stop:
91: ms.Write32(0xf400c001); // jmp r1
92: // _back:
93: ms.Write32(0x14430000 | // ld r2, r3, #+ENTRY
94: (ROMIO_ENTRY - ROMIO_BASE));//
95: // ; 起動先がなければループ
96: ms.Write32(0xe842fffd); // bcnd eq0, r2, _prompt
97: // ; 起動先があれば後始末して
98: ms.Write32(0x14030000 | // _go:
99: (ROMIO_CLOSE - ROMIO_BASE));// ld r0, r3, #+CLOSE
100: // ; 割り込み禁止に戻す
101: ms.Write32(0x800a802a); // stcr r10, psr
102: // ; ジャンプ
103: ms.Write32(0xf400c002); // jmp r2
104:
105: // ここから割り込みハンドラ。割り込みは SIO のみ許可にしてある。
106: // キーボード割り込みが上がったら KEYIN をコールして _back に戻る。
107: ms.SetPtr(&romdata[0x200]);
108: ms.Write32(0x14030000 | // ld r0, r3, #+KEYIN
109: (ROMIO_KEYIN - ROMIO_BASE));//
110: // ; 戻ったところの jmp を抜ける
111: ms.Write32(0x60210004); // addu r1, r1, #4
112: ms.Write32(0xf400fc00); // rte
1.1 root 113:
114: return true;
115: }
116:
1.1.1.6 root 117: void
118: Luna88kPROMEmuDevice::ResetHard()
119: {
120: inherited::ResetHard();
121:
122: b_entrypoint = 0;
123: }
124:
1.1.1.5 root 125: // 起動時の処理を行う。
126: // 次段実行ファイルの読み込みに成功すればそのエントリポイントを返す。
127: // そうでなければ 0 を返すので、プロンプトに処理を移すこと。
128: uint32
129: Luna88kPROMEmuDevice::ROM_Init()
1.1 root 130: {
1.1.1.5 root 131: IODeviceStream rs(gRAM.get());
132: uint32 entry;
1.1 root 133:
1.1.1.5 root 134: // デバイスの初期化 (親クラス)
135: InitDevice();
1.1.1.6 root 136:
1.1.1.5 root 137: // 割り込みマスクで SIO だけ許可
138: gInterrupt->Write32(0x65000000, 0x40000000);
1.1 root 139:
1.1.1.5 root 140: rs.SetAddr(0);
141: // ベクタテーブルを rte で埋めておく
142: for (int i = 0; i < 512 * 2; i++) {
143: rs.Write32(0xf400fc00 /* rte */);
144: }
145: // +$08: 割り込みベクタ
146: rs.Write32(8, 0xc00003fe); // br $00001000
147:
148: // 割り込みトランポリン (0x1000)
149: // ベクタテーブルは各2ワードしかないのに、0 番地付近にあるベクタテーブル
150: // から2ワードでは ROM まで飛べない。一体どういう設計してんだ…。
151: rs.SetAddr(0x1000);
152: rs.Write32(0x5cc04100); // or.u r6, r0, #0x4100
153: rs.Write32(0x58c60200); // or r6, r6, #0x0200
154: rs.Write32(0xf400c006); // jmp r6
1.1.1.2 root 155:
1.1.1.5 root 156: // ROM の機能テーブル
157: // 0x00001100 からあるようだ
158: // 0x0000110c GETC()
159: // 0x00001110 PUTC(c)
160: // 0x00001114 ビットマッププレーンの有効状態が入っている。
161: // bit0: plane0 有効
162: // bit1..7: plane1..7 有効
163: rs.SetAddr(0x110c);
164: rs.Write32(0x00001300);
165: rs.Write32(0x00001400);
166: rs.Write32(0x00000001);
167:
168: // ROM GETC エミュレータ
169: rs.SetAddr(0x1300);
170: rs.Write32(0xfc000c00); // internal inst getc
171: rs.Write32(0xf400c001); // jmp r1
1.1.1.2 root 172:
1.1.1.5 root 173: // ROM PUTC エミュレータ
174: rs.SetAddr(0x1400);
175: rs.Write32(0xfc001000); // internal inst putc
176: rs.Write32(0xf400c001); // jmp r1
177:
178: // スクリーンを初期化
179: InitScreen("LUNA88K");
180:
181: entry = 0;
182:
183: // 表示環境が整ったところで NVRAM を照合
184: if (VerifyNVRAM() == false) {
1.1.1.7 ! root 185: // PROM 1.20 は初期化するかどうか確認してくるけど、とりあえず。
1.1.1.5 root 186: InitNVRAM();
187: text.Print("** NVRAM Initialized.\n");
188: text.Print("\n");
189: // NVRAM をクリアしたら DIPSW によらずプロンプトに降りる
190: goto done;
191: }
192:
193: // DIPSW#1-1 が UP なら自動起動、DOWN なら ROM モニタ起動なので、
194: // これを真似する。
195: if ((gPIO0->GetDIPSW1() & 1)) {
196: if (gMainApp.host_file) {
197: // ホストのファイルを読み込んでエントリポイントアドレスを
198: // この Read アクセスの読み出し値として返す。
199: // エラーがあればエラーメッセージは呼び出し先側で表示してある。
200: entry = LoadHostFile();
201: } else {
202: // NVRAM の設定に従ってブート先を探す。
203: errmsg.clear();
204:
205: bootinfo_t bootinfo;
206: GetNVRAM(bootinfo);
207: entry = LoadGuestFile(bootinfo);
208: if (entry == 0) {
209: text.Print("** %s\n", errmsg.c_str());
210: }
211: }
212: }
213:
214: // ここまでタイトルなどを Print してはいるが、実際の画面更新は
215: // ConsoleUpdate() を呼ぶまで行われないことを利用(悪用?)して、
216: // ここでエラーなくブートプログラムに制御を渡せる場合には何も表示せずに
217: // ゲストに処理を移す。意図して或いは意図せずプロンプトに降りる場合だけ
218: // ConsoleUpdate を呼ぶことでタイトルを含めて画面を表示する。
219: done:
220: if (entry == 0) {
1.1.1.7 ! root 221: ClearPrompt();
1.1.1.5 root 222: ConsoleUpdate();
223: }
224:
225: return entry;
226: }
227:
228: // ROM 処理。エントリポイントを返す。
229: uint32
230: Luna88kPROMEmuDevice::ROM_Entry()
231: {
232: if (b_entrypoint != 0) {
233: return b_entrypoint;
1.1.1.2 root 234: } else {
1.1.1.5 root 235: return 0;
1.1.1.2 root 236: }
237: }
238:
1.1.1.7 ! root 239: void
! 240: Luna88kPROMEmuDevice::GetChar(char asciicode)
! 241: {
! 242: if (prompt_idx == 0) {
! 243: // 行入力モード (画面更新もしてある)
! 244: inherited::GetChar(asciicode);
! 245: } else {
! 246: // 0 以外ならノンブロッキングモード
! 247:
! 248: // 入力されたキーを表示
! 249: text.SetAttr(TA::Normal);
! 250: if (' ' <= asciicode && asciicode < 0x7f) {
! 251: text.Putc(asciicode);
! 252: }
! 253:
! 254: switch (prompt_idx) {
! 255: case PROMPT_NVRAM_UPDATE:
! 256: CommandNvramUpdate2(asciicode);
! 257: break;
! 258:
! 259: case PROMPT_NVRAM_NEW:
! 260: CommandNvramNew2(asciicode);
! 261: break;
! 262:
! 263: case PROMPT_NVRAM_INIT:
! 264: CommandNvramInit2(asciicode);
! 265: break;
! 266: }
! 267:
! 268: // プロンプトを戻す
! 269: prompt = default_prompt;
! 270: prompt_idx = 0;
! 271: prompt_y = text.GetY();
! 272:
! 273: // こっちは画面更新をする必要がある
! 274: ConsoleUpdate();
! 275: }
! 276: }
! 277:
1.1.1.5 root 278: // 入力コマンド処理 (入力行が揃ったところで呼ばれる)。
279: //
280: // b 現在のパラメータで起動
281: // b ... パラメータを指定して起動
282: // nvram 全パラメータを表示
283: // nvram [<name>] name のみ表示?
284: // nvram <name> <val> 値を設定
285: // nvram - <name> 削除
286: // nvram-- NVRAM 初期化
287:
288: void
289: Luna88kPROMEmuDevice::Command()
1.1.1.2 root 290: {
1.1.1.5 root 291: std::vector<char> buf(inputbuf.length() + 1);
292: std::vector<std::string> arg;
1.1.1.2 root 293:
1.1.1.5 root 294: // 1ワードごとに分解
295: strcpy(&buf[0], inputbuf.c_str());
296: char *p = &buf[0];
1.1.1.6 root 297: for (char *ap; (ap = strsep(&p, " ")) != NULL; ) {
298: if (*ap != '\0') {
299: arg.push_back(std::string(ap));
1.1.1.5 root 300: }
301: }
302: if (loglevel >= 1) {
303: for (int i = 0; i < arg.size(); i++) {
304: putmsgn("arg[%d]=|%s|", i, arg[i].c_str());
305: }
306: }
1.1.1.2 root 307:
1.1.1.5 root 308: // 空行
309: if (arg.size() == 0) {
310: return;
311: }
312:
313: // 1ワード目がコマンド
314: if (arg[0] == "h") {
1.1.1.7 ! root 315: CommandH(arg);
1.1.1.5 root 316: return;
317: }
318: if (arg[0] == "b") {
319: CommandB(arg);
320: return;
321: }
322: if (arg[0] == "nvram") {
323: CommandNvram(arg);
324: return;
1.1.1.2 root 325: }
1.1.1.5 root 326:
327: text.Print("** Unknown command: %s\n", arg[0].c_str());
1.1.1.2 root 328: }
329:
1.1.1.7 ! root 330: // "h" コマンド
! 331: // 引数なしなら、全体のヘルプメッセージ。
! 332: // 引数ありなら、個別のヘルプメッセージ。
! 333: void
! 334: Luna88kPROMEmuDevice::CommandH(const std::vector<std::string>& arg)
! 335: {
! 336: if (arg.size() < 2) {
! 337: // ヘルプメッセージ
! 338: mainhelp:
! 339: text.Print(
! 340: " *** Help Message ***\n"
! 341: " b : load and execute program\n"
! 342: " h : show this message\n"
! 343: " nvram : show/set nvram parameters\n"
! 344: );
! 345: return;
! 346: }
! 347:
! 348: const std::string& key = arg[1];
! 349: if (key == "nvram") {
! 350: text.Print(
! 351: " *** Help Message ***\n"
! 352: " nvram [<symbol>] : show\n"
! 353: " nvram <symbol> <value> : set\n"
! 354: " nvram - <symbol> : delete\n"
! 355: " nvram -- : initialize\n"
! 356: );
! 357: return;
! 358: } else {
! 359: goto mainhelp;
! 360: }
! 361: }
! 362:
1.1.1.5 root 363: // "b" コマンド
364: // 引数なしなら NVRAM の情報に従ってプログラムをロードして実行。
365: // 引数ありのほうは未実装。
366: void
367: Luna88kPROMEmuDevice::CommandB(const std::vector<std::string>& arg)
1.1 root 368: {
1.1.1.5 root 369: errmsg.clear();
1.1 root 370:
1.1.1.5 root 371: // XXX とりあえず boot を起動するだけ
372: bootinfo_t bootinfo;
373: GetNVRAM(bootinfo);
374: b_entrypoint = LoadGuestFile(bootinfo);
375: if (b_entrypoint == 0) {
376: text.Print("** %s\n", errmsg.c_str());
1.1 root 377: }
1.1.1.5 root 378: }
1.1 root 379:
1.1.1.5 root 380: // "bh" コマンド (勝手に拡張)
381: // -A オプションで指定されたホストプログラムをロードして実行。
382: void
383: Luna88kPROMEmuDevice::CommandBH()
384: {
385: // 指定されてたら読み込む
386: if (gMainApp.host_file == NULL) {
387: text.Print("** Cannot loaded; host program is not specified.\n");
388: return;
1.1.1.2 root 389: }
1.1.1.5 root 390: b_entrypoint = LoadHostFile();
1.1.1.2 root 391: }
392:
1.1.1.7 ! root 393: // "nvram" コマンド
! 394: // nvram .. 全表示
! 395: // nvram <key> .. 表示
! 396: // nvram <key> <val> .. 追加/更新
! 397: // nvram - <key> .. 削除
! 398: // nvram -- .. 初期化
1.1.1.5 root 399: void
400: Luna88kPROMEmuDevice::CommandNvram(const std::vector<std::string>& arg)
1.1.1.2 root 401: {
1.1.1.7 ! root 402: switch (arg.size()) {
! 403: case 1:
! 404: // 引数なし
! 405: CommandNvramShowAll();
! 406: break;
! 407: case 2:
! 408: // 引数1つ
! 409: if (arg[1] == "--") {
! 410: CommandNvramInit();
! 411: } else {
! 412: CommandNvramShow(arg);
! 413: }
! 414: break;
! 415: case 3:
! 416: // 引数2つ
! 417: if (arg[1] == "-") {
! 418: CommandNvramDelete(arg);
! 419: } else {
! 420: CommandNvramUpdate(arg);
! 421: }
! 422: break;
! 423: default:
! 424: text.Print("** Syntax error\n");
! 425: }
! 426: }
! 427:
! 428: // NVRAM は 32バイトを1エントリとする。
! 429: // [0] はヘッダに相当し、フォーマットは別記。
! 430: // [1] 以降が key (16バイト)、val(16バイト) の並び。こんな感じ。
! 431: //
! 432: // 00000020 62 6f 6f 74 5f 64 65 76 69 63 65 00 00 00 00 00 |boot_device.....|
! 433: // 00000030 73 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |sd..............|
! 434: //
! 435: // key, val とも '\0' で終端もしくは16文字で終端のようだ。
! 436: // val に17文字を設定しようとすると怒られる。
! 437: // key が "" ならこのエントリは空きで val は無視、
! 438: // 空きエントリは無視して次へ (FAT のディレクトリエントリみたいな感じ)。
! 439: // val が "" は有効。
! 440: //
! 441: // オフセット 0x540 から始まるエントリが最後で、これ以上追加しようとすると
! 442: // "nvram set error: no area" (PROM 1.20) と言われる。
! 443: // LUNA88K にはないが LUNA-I では 0x560 にぽつんと ENADDR があったので、
! 444: // その辺りとの互換性だろうか。
! 445:
! 446: // NVRAM 全項目表示
! 447: void
! 448: Luna88kPROMEmuDevice::CommandNvramShowAll()
! 449: {
! 450: putmsg(1, "nvram ShowAll");
! 451: for (uint32 offset = 0x20; offset < 0x560; offset += 0x20) {
! 452: std::string key = nvram->PeekString(offset);
! 453: if (key.empty()) {
! 454: continue;
! 455: }
! 456: std::string val = nvram->PeekString(offset + 16);
! 457: text.Print("%-15s : %s\n", key.c_str(), val.c_str());
! 458: }
! 459: }
! 460:
! 461: // NVRAM 指定項目を表示
! 462: void
! 463: Luna88kPROMEmuDevice::CommandNvramShow(const std::vector<std::string>& arg)
! 464: {
! 465: assert(arg.size() >= 2);
! 466: const std::string& key = arg[1];
! 467:
! 468: putmsg(1, "nvram Show |%s|", key.c_str());
! 469: uint32 offset = FindNVRAM(key);
! 470: if (offset > 0) {
! 471: std::string val = nvram->PeekString(offset + 16);
! 472: text.Print("%-15s : %s\n", key.c_str(), val.c_str());
! 473: } else {
! 474: text.Print("** Not found\n");
! 475: }
! 476: }
! 477:
! 478: // NVRAM 項目を追加/更新
! 479: void
! 480: Luna88kPROMEmuDevice::CommandNvramUpdate(const std::vector<std::string>& arg)
! 481: {
! 482: // キーがあれば更新、なければ追加。
! 483: // いずれも事前にプロンプトで確認する。
! 484:
! 485: assert(arg.size() >= 3);
! 486: nvram_key = arg[1];
! 487: nvram_val = arg[2];
! 488: putmsg(1, "nvram Update |%s|%s|", nvram_key.c_str(), nvram_val.c_str());
! 489:
! 490: if (nvram_key.size() > 16) {
! 491: text.Print("** Key too long\n");
! 492: return;
! 493: }
! 494: if (nvram_val.size() > 16) {
! 495: text.Print("** Val too long\n");
! 496: return;
! 497: }
! 498:
! 499: nvram_offset = FindNVRAM(nvram_key);
! 500: if (nvram_offset > 0) {
! 501: // キーがすでにあれば更新。
! 502: // Update2() に申し送りするのは nvram_offset と nvram_val のみでいい。
! 503:
! 504: std::string oldval = nvram->PeekString(nvram_offset + 16);
! 505: prompt = string_format("Update %s : \"%s\" -> \"%s\" (Y/[N]):",
! 506: nvram_key.c_str(), oldval.c_str(), nvram_val.c_str());
! 507: prompt_idx = PROMPT_NVRAM_UPDATE;
! 508: } else {
! 509: // キーがなければ追加
! 510: // New2() に申し送りするのは nvram_offset, nvram_key, nvram_val の3つ。
! 511:
! 512: // 先に空き領域をチェックしている
! 513: nvram_offset = FindNVRAM("");
! 514: if (nvram_offset == 0) {
! 515: text.Print("** No area available\n");
! 516: return;
! 517: }
! 518:
! 519: prompt = string_format("Set new %s : \"%s\" (Y/[N]):",
! 520: nvram_key.c_str(), nvram_val.c_str());
! 521: prompt_idx = PROMPT_NVRAM_NEW;
! 522: }
! 523:
! 524: // 入力待ちの状態で戻る
! 525: // (prompt_idx != 0 なのでキー入力後に指定の関数へ飛んで続きを実行する)
! 526: }
! 527:
! 528: // NVRAM 項目を更新 (キー入力後)
! 529: void
! 530: Luna88kPROMEmuDevice::CommandNvramUpdate2(char asciicode)
! 531: {
! 532: assert(prompt_idx == PROMPT_NVRAM_UPDATE);
! 533: assert(nvram_offset > 0);
! 534: assert(nvram_val.size() <= 16);
! 535:
! 536: text.CRLF();
! 537:
! 538: if (asciicode != 'y' && asciicode != 'Y') {
! 539: text.Print("** Not updated\n");
! 540: return;
! 541: }
! 542:
! 543: if (nvram->WriteString(nvram_offset + 16, nvram_val) == false) {
! 544: text.Print("** Write error\n");
! 545: return;
! 546: }
! 547: WriteNVRAMCsum();
! 548:
! 549: text.Print("Updated\n");
! 550: }
! 551:
! 552: // NVRAM 項目を追加 (キー入力後)
! 553: void
! 554: Luna88kPROMEmuDevice::CommandNvramNew2(char asciicode)
! 555: {
! 556: assert(prompt_idx == PROMPT_NVRAM_NEW);
! 557: assert(nvram_offset > 0);
! 558: assert(!nvram_key.empty());
! 559: assert(nvram_key.size() <= 16);
! 560: assert(nvram_val.size() <= 16);
! 561:
! 562: text.CRLF();
! 563:
! 564: if (asciicode != 'y' && asciicode != 'Y') {
! 565: text.Print("** Not added\n");
! 566: return;
! 567: }
! 568:
! 569: if (nvram->WriteString(nvram_offset, nvram_key) == false
! 570: || nvram->WriteString(nvram_offset + 16, nvram_val) == false) {
! 571: text.Print("** Write error\n");
! 572: return;
! 573: }
! 574: WriteNVRAMCsum();
! 575:
! 576: text.Print("Added\n");
1.1.1.2 root 577: }
578:
1.1.1.7 ! root 579: // NVRAM 項目削除
! 580: //
! 581: // 削除する時は確認がないらしい… (PROM 1.20)
! 582: // 成功しても何も言わないらしい… (PROM 1.20)
! 583: // 追加削除に比べてなんか雑じゃない?
! 584: void
! 585: Luna88kPROMEmuDevice::CommandNvramDelete(const std::vector<std::string>& arg)
! 586: {
! 587: assert(arg.size() >= 3);
! 588: assert(arg[1] == "-");
! 589: const std::string& key = arg[2];
! 590: putmsg(1, "nvram Delete |%s|", key.c_str());
! 591:
! 592: if (key.size() > 16) {
! 593: text.Print("** key too long\n");
! 594: return;
! 595: }
! 596:
! 597: uint32 offset = FindNVRAM(key);
! 598: if (offset == 0) {
! 599: text.Print("** Not found\n");
! 600: return;
! 601: }
! 602:
! 603: // キーを消せば削除になる (値のほうは消してないようだ)
! 604: nvram->WriteString(offset, "");
! 605: WriteNVRAMCsum();
! 606: }
! 607:
! 608: // NVRAM から key を探してそのエントリのオフセットを返す。
! 609: // key == "" なら空きエントリを探す。
! 610: // 見付からなければ 0 を返す (オフセット 0 はパラメータには使わないため)
! 611: uint32
! 612: Luna88kPROMEmuDevice::FindNVRAM(const std::string& key) const
1.1.1.2 root 613: {
1.1.1.7 ! root 614: for (uint32 offset = 0x20; offset < 0x560; offset += 0x20) {
! 615: std::string k = nvram->PeekString(offset);
! 616: if (k == key) {
! 617: return offset;
! 618: }
! 619: // XXX 同じキーが複数あったらどうなるか
! 620: }
1.1.1.2 root 621: return 0;
622: }
623:
1.1.1.7 ! root 624: // NVRAM 初期化
1.1.1.5 root 625: void
1.1.1.7 ! root 626: Luna88kPROMEmuDevice::CommandNvramInit()
1.1.1.2 root 627: {
1.1.1.7 ! root 628: putmsg(1, "nvram Init");
! 629:
! 630: prompt = "Initialize (Y/[N]):";
! 631: prompt_idx = PROMPT_NVRAM_INIT;
! 632:
! 633: // 入力待ちの状態で戻る
1.1.1.2 root 634: }
635:
1.1.1.7 ! root 636: // NVRAM 初期化 (キー入力後)
! 637: void
! 638: Luna88kPROMEmuDevice::CommandNvramInit2(char asciicode)
1.1.1.2 root 639: {
1.1.1.7 ! root 640: assert(prompt_idx == PROMPT_NVRAM_INIT);
! 641:
! 642: text.CRLF();
! 643:
! 644: if (asciicode != 'y' && asciicode != 'Y') {
! 645: text.Print("** Not initialized\n");
! 646: return;
! 647: }
! 648:
! 649: InitNVRAM();
! 650: text.Print("** Initialized\n");
1.1 root 651: }
652:
1.1.1.5 root 653: // NVRAM を初期化する
654: bool
655: Luna88kPROMEmuDevice::InitNVRAM()
1.1 root 656: {
1.1.1.7 ! root 657: nvram->ClearAll();
! 658:
! 659: nvram->WriteString(0x0004, "<nv>");
! 660: nvram->WriteString(0x0020, "boot_device");
! 661: nvram->WriteString(0x0030, "sd");
! 662: nvram->WriteString(0x0040, "boot_spec");
! 663: nvram->WriteString(0x0050, "0");
! 664: nvram->WriteString(0x0060, "boot_unit");
! 665: nvram->WriteString(0x0070, "0");
! 666: nvram->WriteString(0x0080, "boot_partition");
! 667: nvram->WriteString(0x0090, "0");
! 668: nvram->WriteString(0x00a0, "boot_filename");
! 669: nvram->WriteString(0x00b0, "vmunix");
! 670: nvram->WriteString(0x00c0, "main_mem_check");
! 671: nvram->WriteString(0x00d0, "1");
! 672: nvram->WriteString(0x00e0, "3port_mem_check");
! 673: nvram->WriteString(0x00f0, "1");
! 674:
! 675: // チェックサム再計算
! 676: WriteNVRAMCsum();
! 677:
! 678: return true;
1.1.1.5 root 679: }
1.1 root 680:
1.1.1.5 root 681: // NVRAM のブート設定を bootinfo に取得する。
682: void
683: Luna88kPROMEmuDevice::GetNVRAM(bootinfo_t& bootinfo)
684: {
1.1.1.7 ! root 685: // dkunit (装置番号) はたぶん boot_unit (0..)
! 686: // dkpart (パーティション) は boot_partition (0..)
! 687: // dkfile (ファイル名) は boot_filename
! 688: // sd 以外のデバイスは未対応
! 689: bootinfo.dkunit = nvram->Peek(0x0070) - '0';
! 690: bootinfo.dkpart = nvram->Peek(0x0090) - '0';
! 691: bootinfo.dkfile = nvram->PeekString(0x00b0);
! 692: putmsg(1, "%s unit=%d", __func__, bootinfo.dkunit);
! 693: putmsg(1, "%s part=%c", __func__, bootinfo.dkpart + 'a');
! 694: putmsg(1, "%s file=|%s|", __func__, bootinfo.dkfile.c_str());
1.1 root 695: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.