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