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

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

unix.superglobalmegacorp.com

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