|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1.1.6 root 7: //
1.1 root 8: // LUNA-I の ROM エミュレーション
1.1.1.4 root 9: //
1.1.1.6 root 10:
1.1.1.4 root 11: // IODevice
12: // |
13: // +-- ROMDevice (LoadROM()、ウェイト、マスク等を持つ)
14: // | |
15: // | +-- PROMDevice (LUNA* の PROM)
16: // | +-- IPLROM1Device (X680x0 の IPLROM 後半)
17: // | +-- IPLROM2Device (X680x0 の IPLROM 前半)
18: // | +-- CGROMDevice (X680x0 の CGROM)
19: // | +-- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分)
20: // | |
21: // | | +--------------------+
1.1.1.7 ! root 22: // | +--| Luna1PROMEmuDevice | (LUNA-I の PROM エミュレーション)
1.1.1.4 root 23: // | | +--------------------+
24: // | |
1.1.1.7 ! root 25: // | +-- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション)
1.1.1.4 root 26: // |
27: // +-- PROM0Device (LUNA* のブートページ切り替え用プロキシ)
28: // +-- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ)
1.1 root 29:
1.1.1.6 root 30: // ROM マップ
31: //
32: // 先頭の "*" は仕様または実機と揃える必要があるアドレスを示す。
33: // そうでないものはこっちが適当に割り振っているアドレスで、変更可。
34: //
35: // *4100'0000.L リセットベクタ(SP)
36: // *4100'0004.L リセットベクタ(PC)
37: // *4100'000c.L メモリサイズ格納先アドレス (実 ROM は RAM をさしている)
38: // 4100'0010.L メモリサイズ
39: // *4100'00b8.L プレーンマスク格納先アドレス (実 ROM は RAM をさしている)
40: // 4100'00bc.L プレーンマスク
41: //
42: // 4100'0400 リセットハンドラ
43: // 4100'0600 Lv6 (SIO) 割り込みハンドラ
44: // 4100'0700 Lv7 (NMI) 割り込みハンドラ
45: // 4100'0800 デフォルトハンドラ
46: //
47: // *4101'ffd8〜 "ENADDR",0,0
48: // *4101'ffe0〜 MACアドレス(文字列形式、英大文字、区切りなし)
49: // 0123456789ab c
50: // "0011223344AA",0
51:
1.1 root 52: #include "romemu_luna1.h"
1.1.1.7 ! root 53: #include "bt45x.h"
1.1 root 54: #include "ethernet.h"
55: #include "mainapp.h"
1.1.1.7 ! root 56: #include "mainram.h"
1.1 root 57: #include "memorystream.h"
58: #include "mk48t02.h"
59: #include "mpu680x0.h"
60: #include "pio.h"
61:
62: // コンストラクタ
63: Luna1PROMEmuDevice::Luna1PROMEmuDevice()
64: {
65: // LUNA-I の ROM の特定アドレスを読み出す人がいるので、
66: // サイズは実 ROM と同じにしておく必要がある。
1.1.1.7 ! root 67: uint devlen = 128 * 1024;
1.1.1.4 root 68: imagebuf.reset(new uint8 [devlen]);
69: memset(&imagebuf[0], 0, devlen);
70: mem = &imagebuf[0];
71:
72: mask = devlen - 1;
1.1 root 73: }
74:
75: // デストラクタ
76: Luna1PROMEmuDevice::~Luna1PROMEmuDevice()
77: {
78: }
79:
1.1.1.7 ! root 80: // 初期化
1.1 root 81: bool
82: Luna1PROMEmuDevice::Init()
83: {
84: if (inherited::Init() == false) {
85: return false;
86: }
87:
1.1.1.4 root 88: MemoryStreamBE ms(imagebuf.get());
1.1 root 89: ms.Write32(0x00002000); // +00: リセットベクタ SP
90: ms.Write32(0x41000400); // +04: リセットベクタ PC
91: ms.Write32(0); // +08
1.1.1.6 root 92: ms.Write32(0x41000010); // +0c: メモリサイズ格納先
93: // +10: 値は ROM_Init() でセット
94: ms.SetOffset(0xb8);
95: ms.Write32(0x410000bc); // +b8: プレーンマスク格納先
96: // +bc: 値は ROM_Init() でセット
1.1 root 97:
98: // リセット時に実行する命令
1.1.1.6 root 99: ms.SetOffset(0x400);
1.1.1.4 root 100: ms.Write16(0x13c0); // move.b d0,#0x41000000 ; RAMに切り替え
101: ms.Write32(0x41000000);
1.1 root 102: ms.Write16(0x2039); // move.l (ROMIO_INIT),d0
103: ms.Write32(ROMIO_INIT);
1.1.1.7 ! root 104: ms.Write16(0x6a0c); // bpl _go ; 起動先あればGO
1.1 root 105: //_prompt:
1.1.1.6 root 106: uint32 _prompt = ms.GetOffset();
1.1 root 107: ms.Write32(0x4e722500); // stop #0x2500 ; キー入力を待つ
108: ms.Write16(0x2039); // move.l (ROMIO_ENTRY),d0
109: ms.Write32(ROMIO_ENTRY); // ; キー入力処理
110: ms.Write16(0x67f4); // beq _prompt ; 起動先なければループ
111: //_go:
112: ms.Write16(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット
113: ms.Write16(0x2039); // move.l (ROMIO_CLOSE),d0
114: ms.Write32(ROMIO_CLOSE); // ; 後始末
115: ms.Write16(0x4ed0); // jmp (a0) ; ジャンプ
116:
117: // Lv6 (SIO) 割り込みハンドラ
118: // キーボード割り込みが上がったら KEYIN をコールする
1.1.1.6 root 119: ms.SetOffset(0x600);
1.1 root 120: ms.Write16(0x4ab9); // tst.l (ROMIO_KEYIN)
121: ms.Write32(ROMIO_KEYIN); // ; キー入力処理
122: ms.Write16(0x4e73); // rte
123:
1.1.1.6 root 124: // NMI のハンドラ
125: ms.SetOffset(0x700);
126: ms.Write32(0x46fc2700); // move.w #0x2700,sr
127: ms.Write16(0x91c8); // suba.l a0,a0
128: ms.Write32(0x4e7b8801); // movec a0,vbr
129: ms.Write16(0x2e50); // movea.l (a0),sp
130: ms.Write16(0x4ef9); // jmp _prompt
131: ms.Write32(0x41000000 + _prompt);
132:
133: // デフォルトのハンドラ
134: ms.SetOffset(0x800);
135: ms.Write16(0x4e73); // rte
136:
1.1 root 137: // MAC アドレス
1.1.1.7 ! root 138: macaddr_t macaddr;
! 139: if (EthernetDevice::GetConfigMacAddr(&macaddr, false) == false) {
! 140: // エラーメッセージは表示済み
! 141: return false;
! 142: }
! 143: putmsg(1, "macaddr=%s", macaddr.ToString(':').c_str());
1.1.1.4 root 144: strcpy((char *)&imagebuf[0x1ffd8], "ENADDR");
1.1.1.6 root 145: memcpy(&imagebuf[0x1ffe0], macaddr.ToString().c_str(), 12);
1.1 root 146:
147: return true;
148: }
149:
150: // 起動時の処理を行う。
151: // 次段実行ファイルの読み込みに成功すればそのエントリポイントを返す。
1.1.1.7 ! root 152: // そうでなければ -1 を返すので、プロンプトに処理を移すこと。
1.1 root 153: uint32
154: Luna1PROMEmuDevice::ROM_Init()
155: {
1.1.1.6 root 156: MemoryStreamBE ms(imagebuf.get());
1.1 root 157: uint32 entry;
158:
159: // デバイスの初期化 (親クラス)
160: InitDevice();
161:
1.1.1.7 ! root 162: auto pio0 = GetPIO0Device();
! 163:
1.1.1.6 root 164: // +0010: メモリサイズ
165: ms.SetOffset(0x10);
1.1.1.7 ! root 166: ms.Write32(mainram->GetSize());
1.1 root 167:
1.1.1.7 ! root 168: // プレーン数(1,4,8)をプレーンマスク(0x01, 0x0f, 0xff)に
! 169: int nplane = bt45x->GetPlaneCount();
1.1 root 170: int planemask = (1 << nplane) - 1;
1.1.1.6 root 171: // プレーンマスク。実際は RAM に書き込まれるがとりあえず
172: ms.SetOffset(0xbc);
1.1 root 173: ms.Write32(planemask);
174:
1.1.1.6 root 175: // RAM にベクタを書き込む
176: ms.SetOffset(0);
1.1.1.7 ! root 177: mainram->Write32(0, ms.Read32()); // ROM のリセットベクタをコピー
! 178: mainram->Write32(4, ms.Read32());
1.1.1.6 root 179:
1.1.1.7 ! root 180: for (int i = 2; i < 256; i++) { // デフォルトベクタで埋める
! 181: mainram->Write32(i * 4, 0x41000800);
1.1.1.6 root 182: }
1.1.1.7 ! root 183: mainram->Write32(0x78, 0x41000600); // +78: Lv6 割り込み
! 184: mainram->Write32(0x7c, 0x41000700); // +7c: Lv7 割り込み = RESET
1.1.1.6 root 185:
1.1 root 186: prompt_idx = 0;
187: prompt = default_prompt;
188:
189: // スクリーンを初期化
1.1.1.6 root 190: InitScreen();
1.1 root 191:
1.1.1.7 ! root 192: entry = -1;
1.1.1.6 root 193: x_executed = false;
1.1.1.7 ! root 194: x_entrypoint = -1;
1.1 root 195:
196: // 表示環境が整ったところで NVRAM を照合
197: if (VerifyNVRAM() == false) {
198: InitNVRAM();
1.1.1.6 root 199: errmsg = "NVRAM Initialized.";
1.1 root 200: // NVRAM をクリアしたら DIPSW によらずプロンプトに降りる
201: goto done;
202: }
203:
1.1.1.5 root 204: // -X file
205: // DIPSW の状態に関わらず、ファイルをロードし実行する。
206: // --load-only file
207: // DIPSW の状態に関わらず、ファイルをロードし、プロンプトで止まる。
208: if (gMainApp.exec_file) {
209: // ホストのファイルを読み込んでエントリポイントアドレスを
210: // この Read アクセスの読み出し値として返す。
211: // エラーがあればエラーメッセージは呼び出し先側で表示してある。
212: x_entrypoint = LoadHostFile();
213: if (gMainApp.load_and_exec) {
214: entry = x_entrypoint;
215: }
216: } else {
217: // DIPSW#1-1 が UP なら自動起動、DOWN なら ROM モニタ起動なので、
218: // これを真似する。
1.1.1.7 ! root 219: if (pio0->IsDIPSW11Up()) {
1.1 root 220: // NVRAM の設定に従ってブート先を探す。
221: errmsg.clear();
222:
223: bootinfo_t bootinfo;
224: GetNVRAM(bootinfo);
225: entry = LoadGuestFile(bootinfo);
226: }
227: }
228:
229: done:
1.1.1.7 ! root 230: if (entry == -1) {
1.1.1.6 root 231: PrintTitle("LUNA-I");
232: if (errmsg.empty() == false) {
233: Print("** %s\n\n", errmsg.c_str());
234: }
1.1.1.3 root 235: ClearPrompt();
1.1 root 236: }
237:
238: return entry;
239: }
240:
241: // ROM 処理。エントリポイントを返す。
242: uint32
243: Luna1PROMEmuDevice::ROM_Entry()
244: {
245: if (x_executed && x_entrypoint != 0) {
246: return x_entrypoint;
247: } else {
248: return 0;
249: }
250: }
251:
252: // ROM 処理のクローズ。
253: // 次段プログラムにジャンプするための処理も含む。
254: void
255: Luna1PROMEmuDevice::ROM_Close()
256: {
257: inherited::ROM_Close();
258:
259: // NetBSD のブートローダがカーネルを読み込む時にはいくつかレジスタ
260: // 渡しのパラメータがあるので、ここで用意する。本当はターゲットが
261: // NetBSD カーネルの時に限定すべきのような気もするけど、とりあえず。
262: // ROM がブートローダを読み込む時にはそのような取り決め事は一切ない
263: // ので、ブートローダを読む時にも同じ値が入ってしまうが気にしない
264: // ことにする。
265: // 必要なパラメータは
266: // %d6 に bootdev、NetBSD/luna68k の場合は
267: // bootdev = $MACUPP00
268: // ||||++-- パーティション番号
269: // |||+---- SCSI ID (XXX ただしここでは 6 決め打ち)
270: // ||+----- unit (spc0 なら 0 のやつのはず)
271: // |+------ アダプタ (spc = 0、lance = 1)
272: // +------- magic ($a)
273: //
274: // %d7 に howto (0 でよい)
275: // (と %a0 にジャンプ先を入れるがこれは Init() が書き出した ROM
276: // アセンブラコード側で行っている)
1.1.1.7 ! root 277: m68kreg& reg = GetMPU680x0Device()->reg;
! 278: reg.D[6] = 0xa0060000;
! 279: reg.D[7] = 0;
1.1.1.6 root 280:
1.1.1.7 ! root 281: x_entrypoint = -1;
1.1.1.6 root 282: x_executed = false;
1.1 root 283: }
284:
285: // 入力コマンド処理 (入力行が揃ったところで呼ばれる)。
286: void
287: Luna1PROMEmuDevice::Command()
288: {
289: std::vector<char> buf(inputbuf.length() + 1);
290: std::vector<std::string> arg;
291:
292: // 1ワードごとに分解
293: strcpy(&buf[0], inputbuf.c_str());
294: char *p = &buf[0];
1.1.1.2 root 295: for (char *ap; (ap = strsep(&p, " ")) != NULL; ) {
296: if (*ap != '\0') {
297: arg.push_back(std::string(ap));
1.1 root 298: }
299: }
300: if (loglevel >= 1) {
301: for (int i = 0; i < arg.size(); i++) {
302: putmsgn("arg[%d]=|%s|", i, arg[i].c_str());
303: }
304: }
305:
306: // "k" コマンド中ならここで先に処理する
307: if (prompt_idx != 0) {
308: CommandK(arg);
309: return;
310: }
311:
312: // 空行
313: if (arg.size() == 0) {
314: return;
315: }
316:
317: // 1ワード目がコマンド
318: if (arg[0] == "h") {
319: // ヘルプメッセージ
1.1.1.6 root 320: Print("Commands\n");
321: Print(
1.1 root 322: " g [<filename>] : load program\n"
1.1.1.5 root 323: " gh : load host program (specified by --load-only option)\n"
1.1 root 324: " h : show this message\n"
325: " k : show/set boot constants\n"
326: " x : execute loaded program\n"
327: );
328: return;
329: }
330: if (arg[0] == "g") {
331: CommandG(arg);
332: return;
333: }
334: if (arg[0] == "gh") {
335: CommandGH();
336: return;
337: }
338: if (arg[0] == "k") {
339: CommandK(arg);
340: return;
341: }
342: if (arg[0] == "x") {
343: CommandX();
344: return;
345: }
346:
1.1.1.6 root 347: Print("** Unknown command: %s\n", arg[0].c_str());
1.1 root 348: }
349:
350: // "g" コマンド
351: // g なら NVRAM の情報に従ってプログラムをロード。
352: // g <fname> なら NVRAM の fname だけ指定の名前を使ってロード。NVRAM には
353: // 書き込まない。
354: void
355: Luna1PROMEmuDevice::CommandG(const std::vector<std::string>& arg)
356: {
357: std::string ctlr = nvram->PeekString(0x0030);
358: if (ctlr == "dk") { // harddisk
359: std::string fname {};
360:
361: switch (arg.size()) {
362: case 1:
363: break;
364: case 2:
365: fname = arg[1];
366: break;
367: default:
1.1.1.6 root 368: Print("** Invalid argument.\n");
1.1 root 369: return;
370: }
371: errmsg.clear();
372:
373: bootinfo_t bootinfo;
374: GetNVRAM(bootinfo);
375: // 引数で指定されたらファイル名だけ上書き
376: if (!fname.empty()) {
377: bootinfo.dkfile = fname;
378: }
379: x_entrypoint = LoadGuestFile(bootinfo);
1.1.1.7 ! root 380: if (x_entrypoint == -1) {
1.1.1.6 root 381: Print("** %s\n", errmsg.c_str());
1.1 root 382: }
383:
384: } else if (ctlr == "et" || // netboot
385: ctlr == "sd" || // cassette tape
386: ctlr == "fl" ) // floppy
387: {
1.1.1.6 root 388: Print("** %s boot not supported.\n", ctlr.c_str());
1.1 root 389: return;
390: } else {
391: // 起きないはず
1.1.1.6 root 392: Print("** Invalid boot controller name.\n");
1.1 root 393: return;
394: }
395:
1.1.1.7 ! root 396: if (x_entrypoint != -1) {
1.1.1.6 root 397: Print("Loaded. Entry point = $%08x\n", x_entrypoint);
1.1 root 398: }
399: }
400:
401: // "gh" コマンド (勝手に拡張)
1.1.1.4 root 402: // -X オプションで指定されたホストプログラムをロードする。
1.1 root 403: void
404: Luna1PROMEmuDevice::CommandGH()
405: {
406: // 指定されてたら読み込む
1.1.1.4 root 407: if (gMainApp.exec_file == NULL) {
1.1.1.6 root 408: Print("** Cannot loaded; host program is not specified.\n");
1.1 root 409: return;
410: }
411: x_entrypoint = LoadHostFile();
412: }
413:
414:
415: // k コマンドのパラメータ表
416: struct kinfo {
417: uint32 offset; // NVRAM 上のオフセット
418: const char * const name; // 表示名
419: int next; // 次インデックス
420: };
421: static const struct kinfo kinfo[] = {
422: { 0 }, // 0 は通常プロンプトを指すのでここでは使わない
423: { 0x0030, "controller", 0 }, // [1] BOOT (next は動的判定する)
424: { 0x0090, "drive unit", 3 }, // [2] DKUNIT
425: { 0x00b0, "partition ", 4 }, // [3] DKPART
426: { 0x00d0, "filename ", 0 }, // [4] FLNAME
427: { 0x0050, "hostname ", 6 }, // [5] HOST
428: { 0x0070, "servername", 7 }, // [6] SERVER
429: { 0x0190, "filename ", 8 }, // [7] ETBOOT
430: { 0x01b0, "", 0 }, // [8] ETFILE (ETBOOT と1行で処理する)
431: };
432:
433: // "k" コマンド
434: void
435: Luna1PROMEmuDevice::CommandK(const std::vector<std::string>& arg)
436: {
437: uint32 offset;
438: const char *name;
439: int next;
440:
441: // 入力を処理
442: if (prompt_idx == 0) {
443: // ここは1行目表示前なので前行の入力はない。
444: next = 1;
445: } else {
446: std::string val;
447: bool rv;
448:
449: // 入力があれば更新
450: if (arg.size() != 0) {
451: rv = CommandKInput(arg[0]);
452: } else {
453: // [7] の時に入力があれば CommandKInput() の中で更新されるが、
454: // 入力がなければそこを通らないので、こっちでやらないといけない。
455: // うーん。
456: if (prompt_idx == 7) {
457: prompt_idx = kinfo[prompt_idx].next;
458: }
459: rv = true;
460: }
461:
462: // これ以降は更新後の prompt_idx を使う
463:
464: // 入力エラーがあった時はこの行を再入力するため
465: next = prompt_idx;
466:
467: if (rv == true) {
468: // 入力があっても空でも次インデックスへ。
469: if (prompt_idx == 1) {
470: // BOOT なら現在値によって次のインデックスが変わる
471: // "dk" なら [2]、"et" なら [5]。他は未対応
472: offset = kinfo[prompt_idx].offset;
473: val = nvram->PeekString(offset);
474: if (val == "dk") {
475: next = 2;
476: } else if (val == "et") {
477: next = 5;
478: } else {
479: // 起きることはないはず
1.1.1.6 root 480: Print("** Inconsistent boot parameter: %s\n",
1.1 root 481: val.c_str());
482: }
483: } else {
484: // それ以外はテーブルにかかれている通り
485: next = kinfo[prompt_idx].next;
486: }
487: }
488: }
489:
490: // この行のプロンプト文字列を作成
491: prompt_idx = next;
492: if (prompt_idx == 0) {
493: // 最終行なら元に戻す
494: prompt = default_prompt;
495: } else {
496: // 次のプロンプトに変更
497: name = kinfo[prompt_idx].name;
498: offset = kinfo[prompt_idx].offset;
499: std::string val = nvram->PeekString(offset);
500:
501: // [7] ETBOOT だけ1行で ETBOOT:ETFILE 形式
502: if (prompt_idx == 7) {
503: next = kinfo[prompt_idx].next; // ETFILE
504: offset = kinfo[next].offset;
505: val += ":";
506: val += nvram->PeekString(offset);
507: }
508:
509: prompt = string_format("%s: %s ?", name, val.c_str());
510: }
511: }
512:
513: // k コマンドの入力値を処理する部分。
514: // 成功すれば true を返す。
515: // 失敗すれば false を返す。
516: // 実機 ROM は入力値にエラーがあると黙って再入力を促す。
517: // エラーメッセージくらい表示してもいいかもだがとりあえず真似しておく。
518: bool
519: Luna1PROMEmuDevice::CommandKInput(const std::string& val)
520: {
521: int offset;
522: bool rv = true;
523:
524: offset = kinfo[prompt_idx].offset;
525:
526: switch (prompt_idx) {
527: case 1: // BOOT
528: // 正常な入力値は "dk", "et", "sd", "fl" のみ。
529: if (val != "dk" && val != "et" && val != "sd" && val != "fl") {
530: return false;
531: }
532: rv = nvram->WriteString(offset, val);
533: if (rv == false) {
534: return false;
535: }
536: break;
537:
538: case 7: // ETBOOT
539: {
540: // こいつだけ ETBOOT:ETFILE 形式で2つのパラメータを同時に処理する
541:
542: // ':' で前後に分ける
543: int sep = val.find(':');
544: if (sep == std::string::npos) {
545: return false;
546: }
547: std::string etboot = val.substr(0, sep);
548: std::string etfile = val.substr(sep + 1, val.size() - sep + 1);
549: if (etboot.empty() || etfile.empty()) {
550: return false;
551: }
552:
553: // ETBOOT
554: rv = nvram->WriteString(offset, etboot);
555: if (rv == false) {
556: return false;
557: }
558:
559: // 次へ
560: prompt_idx = kinfo[prompt_idx].next;
561:
562: // ETFILE
563: offset = kinfo[prompt_idx].offset;
564: rv = nvram->WriteString(offset, etfile);
565: if (rv == false) {
566: return false;
567: }
568: break;
569: }
570:
571: default:
572: rv = nvram->WriteString(offset, val);
573: if (rv == false) {
574: return false;
575: }
576: break;
577: }
578:
579: WriteNVRAMCsum();
580: return rv;
581: }
582:
583: // "x" コマンド
584: // 読み込まれていたらフラグを立てるだけ。
585: void
586: Luna1PROMEmuDevice::CommandX()
587: {
1.1.1.7 ! root 588: if (x_entrypoint == -1) {
1.1.1.6 root 589: Print("** Program is not loaded.\n");
1.1 root 590: } else {
591: x_executed = true;
592: }
593: }
594:
595: // NVRAM を初期化する
596: bool
597: Luna1PROMEmuDevice::InitNVRAM()
598: {
1.1.1.3 root 599: nvram->ClearAll();
600:
1.1 root 601: // 初期値どうしたもんか
602: nvram->WriteString(0x0004, "<nv>");
603: nvram->WriteString(0x0020, "BOOT");
604: nvram->WriteString(0x0030, "dk");
605: nvram->WriteString(0x0040, "HOST");
606: nvram->WriteString(0x0050, "nono"); // 偽札的なアレ
607: nvram->WriteString(0x0060, "SERVER");
608: nvram->WriteString(0x0070, "servername");
609: nvram->WriteString(0x0080, "DKUNIT");
610: nvram->WriteString(0x0090, "0");
611: nvram->WriteString(0x00a0, "DKPART");
612: nvram->WriteString(0x00b0, "c");
613: nvram->WriteString(0x00c0, "DKFILE");
614: nvram->WriteString(0x00d0, "vmunix");
615: nvram->WriteString(0x00e0, "FLUNIT");
616: nvram->WriteString(0x00f0, "2");
617: nvram->WriteString(0x0100, "FLFILE");
618: nvram->WriteString(0x0110, "vmunix");
619: nvram->WriteString(0x0120, "STUNIT");
620: nvram->WriteString(0x0130, "0");
621: nvram->WriteString(0x0140, "STFLNO");
622: nvram->WriteString(0x0150, "1");
623: nvram->WriteString(0x0160, "STFILE");
624: nvram->WriteString(0x0170, "vmunix");
625: nvram->WriteString(0x0180, "ETBOOT");
626: nvram->WriteString(0x0190, "server");
627: nvram->WriteString(0x01a0, "ETFILE");
628: nvram->WriteString(0x01b0, "/vmunix");
629: nvram->WriteString(0x0560, "ENADDR");
630: nvram->WriteString(0x0570, ""); // どうするか
631:
632: // チェックサム再計算
633: WriteNVRAMCsum();
634:
635: return true;
636: }
637:
638: // NVRAM のブート設定を bootinfo に取得する。
639: void
640: Luna1PROMEmuDevice::GetNVRAM(bootinfo_t& bootinfo)
641: {
642: // 起動先情報を NVRAM (mk48t02) に問い合わせる
643: // DKUNIT が装置番号(今はまだ SCSI ID=6 固定)。
644: // DKPART が 'a'..'h' でパーティション。
645: // DKFILE が読み込む次段プログラム (NetBSD では通常 /boot のこと)。
646: bootinfo.dkunit = nvram->Peek(0x0090) - '0';
647: bootinfo.dkpart = nvram->Peek(0x00b0) - 'a';
648: bootinfo.dkfile = nvram->PeekString(0x00d0);
649: putmsg(1, "%s DKUNIT=%d", __func__, bootinfo.dkunit);
650: putmsg(1, "%s DKPART=%c", __func__, bootinfo.dkpart + 'a');
651: putmsg(1, "%s DKFILE=|%s|", __func__, bootinfo.dkfile.c_str());
652: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.