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

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

unix.superglobalmegacorp.com

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