Annotation of nono/vm/romemu_luna1.cpp, revision 1.1.1.8

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;
1.1.1.8 ! root      139:        if (EthernetDevice::GetConfigMacAddr(0, &macaddr, false) == false) {
1.1.1.7   root      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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.