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

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

unix.superglobalmegacorp.com

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